- Migrated screen projection code to libeye. - Some pickups emit light, like in Doomreal. - Backported map revealer item from Doomreal. - Brand new Invulnerability and Night Vision powerups. - Add option to allow Shield Belt and armors simultaneously. - Backported armor bonus model from Doomreal. - Added Dual Enforcers icon for HUD. - Changed player class names to their character names, like in Doomreal. - Terrain splashes. - Translocator doesn't telefrag other players in coop. - Reduced view shake from Impact Hammer. - Various other updates and bug fixes.
612 lines
13 KiB
Text
612 lines
13 KiB
Text
// Blood
|
|
Class UTBlood : Actor
|
|
{
|
|
Default
|
|
{
|
|
RenderStyle "Add";
|
|
Scale 1.1;
|
|
+NOBLOCKMAP;
|
|
+NOGRAVITY;
|
|
+NOTELEPORT;
|
|
+DONTSPLASH;
|
|
+FORCEXYBILLBOARD;
|
|
+PUFFGETSOWNER;
|
|
}
|
|
void A_Bleed( int str = 1 )
|
|
{
|
|
Scale *= 0.7+0.3*str;
|
|
vel *= 0;
|
|
let b = Spawn("UTBloodSpurt",pos);
|
|
b.angle = angle+FRandom[Blud](-15,15);
|
|
b.pitch = pitch+FRandom[Blud](-15,15);
|
|
b.translation = translation;
|
|
b.args[0] = str;
|
|
// transfer blood color for decals
|
|
if ( target && target.bloodcolor ) b.SetShade(target.bloodcolor);
|
|
else b.SetShade(gameinfo.defaultbloodcolor);
|
|
}
|
|
States
|
|
{
|
|
Spawn:
|
|
TNT1 A 0 NoDelay A_Bleed(3);
|
|
Goto Puff;
|
|
TNT1 A 0 A_Bleed(2);
|
|
Goto Puff;
|
|
TNT1 A 0 A_Bleed(1);
|
|
Goto Puff;
|
|
Puff:
|
|
TNT1 A 0
|
|
{
|
|
int dec = Random[Blod](0,2);
|
|
if ( dec == 1 )
|
|
return ResolveState("Puff1");
|
|
if ( dec == 2 )
|
|
return ResolveState("Puff2");
|
|
return ResolveState("Puff3");
|
|
}
|
|
Puff1:
|
|
BPF1 ABCDEFGHIJK 1;
|
|
Stop;
|
|
Puff2:
|
|
BPF2 ABCDEFGH 1;
|
|
Stop;
|
|
Puff3:
|
|
BPF3 ABCDEFGHIJ 1;
|
|
Stop;
|
|
}
|
|
}
|
|
|
|
// single drop of blod
|
|
Class UTBloodDrop : Actor
|
|
{
|
|
Default
|
|
{
|
|
Scale 0.24;
|
|
Gravity 0.8;
|
|
Mass 1;
|
|
Radius 2;
|
|
Height 2;
|
|
RenderStyle "Translucent";
|
|
+MISSILE;
|
|
+NOTELEPORT;
|
|
+DONTSPLASH;
|
|
+THRUACTORS;
|
|
+FORCEXYBILLBOARD;
|
|
}
|
|
override void PostBeginPlay()
|
|
{
|
|
Super.PostBeginPlay();
|
|
SetState(FindState("Spawn")+Random[Blod](0,4));
|
|
Scale *= FRandom[Blod](0.6,1.4);
|
|
}
|
|
void A_BloodDie()
|
|
{
|
|
// TODO leave decals
|
|
}
|
|
States
|
|
{
|
|
Spawn:
|
|
BDRP ABCDE -1;
|
|
Stop;
|
|
Death:
|
|
TNT1 A 0 A_BloodDie();
|
|
Stop;
|
|
}
|
|
}
|
|
|
|
// a burst of blod
|
|
Class UTBloodSpurt : Actor
|
|
{
|
|
double str;
|
|
|
|
Default
|
|
{
|
|
+NOBLOCKMAP;
|
|
+NOGRAVITY;
|
|
+DONTSPLASH;
|
|
+NOTELEPORT;
|
|
+THRUACTORS;
|
|
}
|
|
override void PostBeginPlay()
|
|
{
|
|
Super.PostBeginPlay();
|
|
str = FRandom[Blood](2.0,3.2)*args[0];
|
|
int sz = 7*args[0];
|
|
double ang, pt;
|
|
if ( !flak_blood ) sz /= 3;
|
|
for ( int i=0; i<sz; i++ )
|
|
{
|
|
Actor d;
|
|
if ( flak_blood ) d = Spawn("UTBloodDrop",pos);
|
|
else d = Spawn("Blood",pos,ALLOW_REPLACE);
|
|
d.translation = translation;
|
|
d.SetShade(fillcolor);
|
|
ang = angle+FRandom[Blood](-3,3)*str;
|
|
pt = pitch+FRandom[Blood](-3,3)*str;
|
|
Vector3 dir = (cos(pt)*cos(ang),cos(pt)*sin(ang),-sin(pt));
|
|
d.vel = dir*str*FRandom[Blood](0.4,0.8);
|
|
d.vel.z += str*0.5;
|
|
d.scale *= str*0.15*FRandom[Blood](0.6,1.4);
|
|
}
|
|
Destroy();
|
|
}
|
|
}
|
|
|
|
// for chunks
|
|
Class UTBloodTrail : Actor
|
|
{
|
|
double str;
|
|
|
|
Default
|
|
{
|
|
+NOBLOCKMAP;
|
|
+NOGRAVITY;
|
|
+NOTELEPORT;
|
|
+DONTSPLASH;
|
|
+THRUACTORS;
|
|
}
|
|
override void PostBeginPlay()
|
|
{
|
|
Super.PostBeginPlay();
|
|
if ( !target ) return;
|
|
str = FRandom[Blood](2.0,4.0);
|
|
}
|
|
private bool IsTargetFlying()
|
|
{
|
|
if ( !target ) return false;
|
|
if ( target.InStateSequence(target.CurState,target.FindState("Spawn")) ) return true;
|
|
return false;
|
|
}
|
|
override void Tick()
|
|
{
|
|
Super.Tick();
|
|
if ( isFrozen() ) return;
|
|
if ( !target ) return;
|
|
SetOrigin(target.pos,true);
|
|
double ang, pt;
|
|
int max = flak_blood?3:Random[Blood](-2,1);
|
|
for ( int i=0; i<max; i++ )
|
|
{
|
|
Actor d;
|
|
if ( flak_blood ) d = Spawn("UTBloodDrop",pos);
|
|
else d = Spawn("Blood",pos,ALLOW_REPLACE);
|
|
d.translation = translation;
|
|
d.SetShade(fillcolor);
|
|
ang = FRandom[Blood](0,360);
|
|
pt = FRandom[Blood](-90,90);
|
|
Vector3 dir = -target.vel*0.2;
|
|
dir += (cos(ang)*cos(pt),sin(ang)*cos(pt),-sin(pt))*0.8;
|
|
d.vel = dir*str*FRandom[Blood](0.8,1.2);
|
|
d.scale *= str*0.15*FRandom[Blood](0.6,1.4);
|
|
}
|
|
bool flying = IsTargetFlying();
|
|
if ( !flying ) Destroy();
|
|
}
|
|
}
|
|
|
|
// Poof
|
|
Class UTBloodPuff : Actor
|
|
{
|
|
Default
|
|
{
|
|
RenderStyle "Add";
|
|
Scale 1.1;
|
|
Alpha 0.4;
|
|
+NOBLOCKMAP;
|
|
+NOGRAVITY;
|
|
+NOTELEPORT;
|
|
+DONTSPLASH;
|
|
+FORCEXYBILLBOARD;
|
|
}
|
|
States
|
|
{
|
|
Spawn:
|
|
TNT1 A 0 NoDelay
|
|
{
|
|
int dec = Random[Blod](0,2);
|
|
if ( dec == 1 )
|
|
return ResolveState("Puff1");
|
|
if ( dec == 2 )
|
|
return ResolveState("Puff2");
|
|
return ResolveState("Puff3");
|
|
}
|
|
Puff1:
|
|
BPF1 ABCDEFGHIJK 2;
|
|
Stop;
|
|
Puff2:
|
|
BPF2 ABCDEFGH 2;
|
|
Stop;
|
|
Puff3:
|
|
BPF3 ABCDEFGHIJ 2;
|
|
Stop;
|
|
}
|
|
}
|
|
|
|
// Chunkers
|
|
Class UTGibber : Actor
|
|
{
|
|
Actor Gibbed;
|
|
int gibcount, gibsize;
|
|
color shadecol;
|
|
Vector3 rvel;
|
|
|
|
virtual void BurstGibs()
|
|
{
|
|
static const class<Actor> gibcls[] = {"UTGenericGib1","UTGenericGib2","UTGenericGib3","UTGenericGib4"};
|
|
Actor a;
|
|
double ang, pt;
|
|
Vector3 dir;
|
|
bool dummy;
|
|
for ( int i=0; i<gibsize; i++ )
|
|
{
|
|
let a = Spawn(gibcls[Random[Blod](0,3)],Vec3Offset(FRandom[Blod](-0.5,0.5)*radius,FRandom[Blod](-0.5,0.5)*radius,FRandom[Blod](0.2,0.8)*height));
|
|
a.translation = translation;
|
|
a.SetShade(fillcolor);
|
|
a.scale *= FRandom[Blod](1.7,2.3)*scale.x;
|
|
ang = FRandom[Blod](0,360);
|
|
pt = FRandom[Blod](-90,90);
|
|
dir = (cos(pt)*cos(ang),cos(pt)*sin(ang),sin(-pt));
|
|
a.vel = rvel*0.6+dir*FRandom[Blod](3.0,6.0);
|
|
}
|
|
for ( int i=0; i<gibsize; i++ )
|
|
{
|
|
let a = Spawn("UTBloodPuff",Vec3Offset(FRandom[Blod](-12,12),FRandom[Blod](-12,12),FRandom[Blod](0.1,0.9)*height));
|
|
a.translation = translation;
|
|
a.SetShade(fillcolor);
|
|
a.scale *= FRandom[Blod](1.8,2.3)*scale.x;
|
|
ang = FRandom[Blod](0,360);
|
|
pt = FRandom[Blod](-90,90);
|
|
dir = (cos(pt)*cos(ang),cos(pt)*sin(ang),sin(-pt));
|
|
a.vel = rvel*0.2+dir*FRandom[Blod](1.5,3.0);
|
|
}
|
|
A_CountDown();
|
|
}
|
|
|
|
override void PostBeginPlay()
|
|
{
|
|
Super.PostBeginPlay();
|
|
gibsize = int(min(max(radius,height)/24,3));
|
|
reactiontime = int(min(max(radius,height)/10,4));
|
|
rvel = vel;
|
|
vel *= 0;
|
|
}
|
|
|
|
Default
|
|
{
|
|
+NOCLIP;
|
|
+NOGRAVITY;
|
|
+NOTELEPORT;
|
|
Radius 32;
|
|
Height 16;
|
|
}
|
|
|
|
States
|
|
{
|
|
Spawn:
|
|
TNT1 A 0 NoDelay A_PlaySound("misc/gibbed");
|
|
TNT1 A 1 BurstGibs();
|
|
Wait;
|
|
}
|
|
}
|
|
|
|
Class UTFemaleLegGibber : UTGibber
|
|
{
|
|
bool firstgib;
|
|
|
|
override void BurstGibs()
|
|
{
|
|
static const class<Actor> parts[] = {"UTFemaleFoot","UTThigh"};
|
|
static const double partofsy[] = {9,8};
|
|
static const double partofsz[] = {9,20};
|
|
Actor a;
|
|
double ang, pt;
|
|
Vector3 dir;
|
|
if ( !firstgib )
|
|
{
|
|
firstgib = true;
|
|
for ( int i=0; i<2; i++ )
|
|
{
|
|
Actor a = Spawn(parts[i],Vec3Offset(-partofsy[i]*sin(angle),partofsy[i]*cos(angle),partofsz[i]));
|
|
ang = FRandom[Blod](0,360);
|
|
pt = FRandom[Blod](-90,90);
|
|
dir = (cos(pt)*cos(ang),cos(pt)*sin(ang),sin(-pt));
|
|
a.vel = rvel*0.6+dir*FRandom[Blod](3.0,6.0);
|
|
}
|
|
}
|
|
for ( int i=0; i<gibsize; i++ )
|
|
{
|
|
Vector3 box = (FRandom[Blod](-8,8),FRandom[Blod](7,12),FRandom[Blod](5,18));
|
|
let a = Spawn("UTBloodPuff",Vec3Offset(box.x*cos(angle)-box.y*sin(angle),box.x*sin(angle)+box.y*cos(angle),box.z));
|
|
ang = FRandom[Blod](0,360);
|
|
pt = FRandom[Blod](-90,90);
|
|
dir = (cos(pt)*cos(ang),cos(pt)*sin(ang),sin(-pt));
|
|
a.vel = rvel*0.2+dir*FRandom[Blod](1.5,3.0);
|
|
}
|
|
A_CountDown();
|
|
}
|
|
override void PostBeginPlay()
|
|
{
|
|
Super.PostBeginPlay();
|
|
gibsize = 3;
|
|
reactiontime = 5;
|
|
}
|
|
States
|
|
{
|
|
Spawn:
|
|
TNT1 A 0 NoDelay; // no sound, done by player
|
|
TNT1 A 1 BurstGibs();
|
|
Wait;
|
|
}
|
|
}
|
|
|
|
Class UTPlayerGibber : UTGibber
|
|
{
|
|
bool firstgib;
|
|
|
|
override void BurstGibs()
|
|
{
|
|
static const class<Actor> bossparts[] = {"UTBossArm","UTBossArm","UTBossFoot","UTBossFoot","UTMaleTorso","UTHeadBoss"};
|
|
static const class<Actor> maleparts[] = {"UTMaleArm","UTMaleArm","UTMaleFoot","UTMaleFoot","UTMaleTorso","UTHeadMale"};
|
|
static const class<Actor> femaleparts[] = {"UTFemaleArm","UTFemaleArm","UTFemaleFoot","UTFemaleFoot","UTFemaleTorso","UTHeadFemale"};
|
|
static const class<Actor> extraparts[] = {"UTThigh","UTThigh","UTHeart","UTLiver","UTStomach"};
|
|
static const double partofsy[] =
|
|
{
|
|
14,
|
|
-14,
|
|
9,
|
|
-9,
|
|
0,
|
|
0,
|
|
8,
|
|
-8,
|
|
-2,
|
|
5,
|
|
-3
|
|
};
|
|
static const double partofsz[] =
|
|
{
|
|
36,
|
|
36,
|
|
9,
|
|
9,
|
|
32,
|
|
48,
|
|
20,
|
|
20,
|
|
40,
|
|
32,
|
|
35
|
|
};
|
|
Actor a;
|
|
double ang, pt;
|
|
Vector3 dir;
|
|
if ( !firstgib )
|
|
{
|
|
firstgib = true;
|
|
for ( int i=0; i<11; i++ )
|
|
{
|
|
if ( (i == 5) && UTPlayer(Gibbed).headless ) continue;
|
|
if ( (i == 0) && UTPlayer(Gibbed).armlessR ) continue;
|
|
if ( (i == 1) && UTPlayer(Gibbed).armlessL ) continue;
|
|
if ( ((i == 2) || (i == 6)) && UTPlayer(Gibbed).leglessR ) continue;
|
|
if ( ((i == 3) || (i == 7)) && UTPlayer(Gibbed).leglessL ) continue;
|
|
if ( ((i == 4) || (i > 7)) && UTPlayer(Gibbed).torsoless ) continue;
|
|
Actor a;
|
|
if ( i < 6 )
|
|
{
|
|
if ( UTPlayer(Gibbed).DollType == UTPlayer.DOLL_Boss )
|
|
a = Spawn(bossparts[i],Vec3Offset(-partofsy[i]*sin(angle),partofsy[i]*cos(angle),partofsz[i]));
|
|
else if ( UTPlayer(Gibbed).DollType == UTPlayer.DOLL_Female )
|
|
a = Spawn(femaleparts[i],Vec3Offset(-partofsy[i]*sin(angle),partofsy[i]*cos(angle),partofsz[i]));
|
|
else a = Spawn(maleparts[i],Vec3Offset(-partofsy[i]*sin(angle),partofsy[i]*cos(angle),partofsz[i]));
|
|
}
|
|
else a = Spawn(extraparts[i-6],Vec3Offset(-partofsy[i]*sin(angle),partofsy[i]*cos(angle),partofsz[i]));
|
|
ang = FRandom[Blod](0,360);
|
|
pt = FRandom[Blod](-90,90);
|
|
if ( a is 'UTHead' )
|
|
{
|
|
pt = FRandom[Blod](-90,-15);
|
|
if ( UTPlayer(Gibbed).player )
|
|
{
|
|
UTPlayer(Gibbed).player.Camera = a;
|
|
UTHead(a).headowner = UTPlayer(Gibbed).player;
|
|
}
|
|
}
|
|
dir = (cos(pt)*cos(ang),cos(pt)*sin(ang),sin(-pt));
|
|
a.vel = rvel*0.6+dir*FRandom[Blod](3.0,6.0);
|
|
}
|
|
}
|
|
for ( int i=0; i<gibsize; i++ )
|
|
{
|
|
let a = Spawn("UTBloodPuff",Vec3Offset(FRandom[Blod](-0.8,0.8)*radius,FRandom[Blod](-0.8,0.8)*radius,FRandom[Blod](0.1,0.9)*height));
|
|
ang = FRandom[Blod](0,360);
|
|
pt = FRandom[Blod](-90,90);
|
|
dir = (cos(pt)*cos(ang),cos(pt)*sin(ang),sin(-pt));
|
|
a.vel = rvel*0.2+dir*FRandom[Blod](1.5,3.0);
|
|
}
|
|
A_CountDown();
|
|
}
|
|
override void PostBeginPlay()
|
|
{
|
|
Super.PostBeginPlay();
|
|
gibsize = 3;
|
|
reactiontime = 5;
|
|
}
|
|
States
|
|
{
|
|
Spawn:
|
|
TNT1 A 0 NoDelay; // no sound, done by player
|
|
TNT1 A 1 BurstGibs();
|
|
Wait;
|
|
}
|
|
}
|
|
|
|
// Chunks
|
|
Class UTGib : Actor
|
|
{
|
|
double rollvel, anglevel, pitchvel;
|
|
|
|
Default
|
|
{
|
|
Radius 4;
|
|
Height 4;
|
|
BounceType "Hexen";
|
|
BounceFactor 0.8;
|
|
WallBounceFactor 0.8;
|
|
Gravity 0.6;
|
|
+ROLLSPRITE;
|
|
+ROLLCENTER;
|
|
+INTERPOLATEANGLES;
|
|
+CANBOUNCEWATER;
|
|
+MISSILE;
|
|
+THRUACTORS;
|
|
+USEBOUNCESTATE;
|
|
+NOTELEPORT;
|
|
}
|
|
override void PostBeginPlay()
|
|
{
|
|
Super.PostBeginPlay();
|
|
tracer = Spawn("UTBloodTrail",pos);
|
|
tracer.target = self;
|
|
if ( bloodcolor ) tracer.SetShade(bloodcolor);
|
|
else tracer.SetShade(gameinfo.defaultbloodcolor);
|
|
tracer.translation = bloodtranslation;
|
|
rollvel = FRandom[Blod](3,6)*RandomPick[Blod](-1,1);
|
|
anglevel = FRandom[Blod](3,6)*RandomPick[Blod](-1,1);
|
|
pitchvel = FRandom[Blod](3,6)*RandomPick[Blod](-1,1);
|
|
}
|
|
void A_HandleBounce()
|
|
{
|
|
double spd = vel.length();
|
|
if ( spd > double.epsilon )
|
|
vel = (vel.unit()+(FRandom[Blod](-0.2,0.2),FRandom[Blod](-0.2,0.2),FRandom[Blod](-0.2,0.2))).unit()*spd;
|
|
if ( BlockingFloor && (vel.xy.length() < 1) )
|
|
{
|
|
ClearBounce();
|
|
ExplodeMissile();
|
|
}
|
|
if ( spd < 10 )
|
|
{
|
|
if ( tracer ) tracer.Destroy();
|
|
}
|
|
else if ( spd > 20 ) vel *= 0.8;
|
|
A_PlaySound("misc/gibp");
|
|
double ang, pt;
|
|
int max = flak_blood?6:2;
|
|
for ( int i=0; i<max; i++ )
|
|
{
|
|
Actor d;
|
|
if ( flak_blood ) d = Spawn("UTBloodDrop",pos);
|
|
else d = Spawn("Blood",pos,ALLOW_REPLACE);
|
|
d.translation = bloodtranslation;
|
|
if ( bloodcolor ) d.SetShade(bloodcolor);
|
|
else d.SetShade(gameinfo.defaultbloodcolor);
|
|
ang = FRandom[Blood](0,360);
|
|
pt = FRandom[Blood](-90,90);
|
|
Vector3 dir = -vel*0.4;
|
|
dir += (cos(ang)*cos(pt),sin(ang)*cos(pt),-sin(pt))*1.3;
|
|
d.vel = dir*FRandom[Blood](0.8,1.2);
|
|
d.scale *= 0.75*FRandom[Blood](0.6,1.4);
|
|
}
|
|
rollvel = FRandom[Blod](3,6)*RandomPick[Blod](-1,1);
|
|
anglevel = FRandom[Blod](3,6)*RandomPick[Blod](-1,1);
|
|
pitchvel = FRandom[Blod](3,6)*RandomPick[Blod](-1,1);
|
|
}
|
|
States
|
|
{
|
|
Spawn:
|
|
UGIB A 1
|
|
{
|
|
roll += rollvel;
|
|
angle += anglevel;
|
|
pitch += pitchvel;
|
|
}
|
|
Wait;
|
|
Bounce:
|
|
UGIB A 0 A_HandleBounce();
|
|
Goto Spawn;
|
|
Death:
|
|
UGIB A 1 A_SetTics(Random[Blod](12,18)*15);
|
|
UGIB A 1 A_FadeOut(0.05);
|
|
Wait;
|
|
}
|
|
}
|
|
Class UTGenericGib1 : UTGib {}
|
|
Class UTGenericGib2 : UTGib {}
|
|
Class UTGenericGib3 : UTGib {}
|
|
Class UTGenericGib4 : UTGib {}
|
|
Class UTThigh : UTGib {}
|
|
Class UTFemaleArm : UTGib {}
|
|
Class UTFemaleFoot : UTGib {}
|
|
Class UTFemaleTorso : UTGib {}
|
|
Class UTMaleArm : UTGib {}
|
|
Class UTMaleFoot : UTGib {}
|
|
Class UTMaleTorso : UTGib {}
|
|
Class UTBossArm : UTGib {}
|
|
Class UTBossFoot : UTGib {}
|
|
Class UTBossTorso : UTGib {}
|
|
Class UTHeart : UTGib
|
|
{
|
|
States
|
|
{
|
|
Spawn:
|
|
UGIB ABCDEF 1
|
|
{
|
|
roll += rollvel;
|
|
angle += anglevel;
|
|
pitch += pitchvel;
|
|
}
|
|
Loop;
|
|
Death:
|
|
UGIB ABCDEFABCDEFABCDEF 2;
|
|
UGIB ABCDEFABCDEF 4;
|
|
UGIB ABCDEF 8;
|
|
UGIB A 1 A_SetTics(Random[Blod](12,18)*15);
|
|
UGIB A 1 A_FadeOut(0.05);
|
|
Wait;
|
|
}
|
|
}
|
|
Class UTLiver : UTGib {}
|
|
Class UTStomach : UTGib {}
|
|
Class UTHead : UTGib
|
|
{
|
|
PlayerInfo headowner;
|
|
|
|
override void PostBeginPlay()
|
|
{
|
|
Super.PostBeginPlay();
|
|
UTMainHandler.DoFlash(self,Color(128,255,0,0),150);
|
|
UTMainHandler.DoFlash(self,Color(96,255,0,0),0);
|
|
}
|
|
|
|
override void Tick()
|
|
{
|
|
Super.Tick();
|
|
if ( headowner && headowner.mo && (headowner.mo.Health > 0) && (headowner.Camera == self) )
|
|
{
|
|
headowner.Camera = headowner.mo;
|
|
headowner = null;
|
|
}
|
|
}
|
|
|
|
override void OnDestroy()
|
|
{
|
|
if ( headowner && (headowner.Camera == self) && headowner.mo )
|
|
{
|
|
headowner.Camera = headowner.mo;
|
|
headowner = null;
|
|
}
|
|
Super.OnDestroy();
|
|
}
|
|
States
|
|
{
|
|
Death:
|
|
UGIB A 1 A_SetTics(Random[Blod](12,18)*15);
|
|
UGIB A 0 A_JumpIf(headowner,"Death");
|
|
UGIB A 1 A_FadeOut(0.05);
|
|
Wait;
|
|
}
|
|
}
|
|
Class UTHeadFemale : UTHead {}
|
|
Class UTHeadMale : UTHead {}
|
|
Class UTHeadBoss : UTHead {}
|