605 lines
15 KiB
Text
605 lines
15 KiB
Text
// Eviscerator projectiles and effects
|
|
|
|
Class EvisceratorChunkLight : PointLightAttenuated
|
|
{
|
|
Default
|
|
{
|
|
Args 255,224,128,16;
|
|
}
|
|
override void Tick()
|
|
{
|
|
Super.Tick();
|
|
if ( !EvisceratorChunk(target) || EvisceratorChunk(target).justdied )
|
|
{
|
|
Destroy();
|
|
return;
|
|
}
|
|
if ( isFrozen() || (freezetics > 0) ) return;
|
|
SetOrigin(target.pos,true);
|
|
double intst = clamp((.7-EvisceratorChunk(target).lifetime)/.7,0.,1.);
|
|
args[LIGHT_RED] = int(255*intst);
|
|
args[LIGHT_GREEN] = int(224*intst);
|
|
args[LIGHT_BLUE] = int(128*intst);
|
|
}
|
|
}
|
|
|
|
Class ChunkImpact : SWWMNonInteractiveActor
|
|
{
|
|
override void PostBeginPlay()
|
|
{
|
|
Super.PostBeginPlay();
|
|
A_SprayDecal("WallCrack",-20);
|
|
int numpt = Random[Eviscerator](-1,2);
|
|
Vector3 x = SWWMUtility.Vec3FromAngles(angle,pitch);
|
|
for ( int i=0; i<numpt; i++ )
|
|
{
|
|
Vector3 pvel = (x+SWWMUtility.Vec3FromAngles(FRandom[Eviscerator](0,360),FRandom[Eviscerator](-90,90))*.8).unit()*FRandom[Eviscerator](.1,1.2);
|
|
let s = Spawn("SWWMSmoke",pos);
|
|
s.vel = pvel;
|
|
s.scale *= .6;
|
|
s.special1 = Random[Eviscerator](0,1);
|
|
s.SetShade(Color(1,1,1)*Random[Eviscerator](96,192));
|
|
}
|
|
numpt = Random[Eviscerator](-2,2);
|
|
for ( int i=0; i<numpt; i++ )
|
|
{
|
|
Vector3 pvel = SWWMUtility.Vec3FromAngles(FRandom[Eviscerator](0,360),FRandom[Eviscerator](-90,90))*FRandom[Eviscerator](2,8);
|
|
let s = Spawn("SWWMSpark",pos);
|
|
s.vel = pvel;
|
|
}
|
|
numpt = Random[Eviscerator](-2,2);
|
|
for ( int i=0; i<numpt; i++ )
|
|
{
|
|
Vector3 pvel = SWWMUtility.Vec3FromAngles(FRandom[Eviscerator](0,360),FRandom[Eviscerator](-90,90))*FRandom[Eviscerator](1,4);
|
|
let s = Spawn("SWWMChip",pos);
|
|
s.vel = pvel;
|
|
}
|
|
Destroy();
|
|
}
|
|
}
|
|
|
|
Class EvisceratorChunkGlow : SWWMNonInteractiveActor
|
|
{
|
|
Default
|
|
{
|
|
RenderStyle "Add";
|
|
Scale .25;
|
|
+FORCEXYBILLBOARD;
|
|
}
|
|
override void Tick()
|
|
{
|
|
if ( freezetics > 0 )
|
|
{
|
|
freezetics--;
|
|
return;
|
|
}
|
|
if ( isFrozen() ) return;
|
|
if ( !EvisceratorChunk(target) || EvisceratorChunk(target).justdied )
|
|
{
|
|
Scale *= .9;
|
|
A_FadeOut();
|
|
return;
|
|
}
|
|
SetOrigin(target.pos,true);
|
|
alpha = clamp((.7-EvisceratorChunk(target).lifetime)/.7,0.,1.);
|
|
if ( alpha <= 0. ) Destroy();
|
|
}
|
|
States
|
|
{
|
|
Spawn:
|
|
ETRL A -1 Bright;
|
|
Stop;
|
|
}
|
|
}
|
|
|
|
Class EvisceratorChunkTrail : SWWMNonInteractiveActor
|
|
{
|
|
Default
|
|
{
|
|
RenderStyle "Add";
|
|
XScale 8.;
|
|
+FORCEXYBILLBOARD;
|
|
}
|
|
override void Tick()
|
|
{
|
|
if ( freezetics > 0 )
|
|
{
|
|
freezetics--;
|
|
return;
|
|
}
|
|
if ( isFrozen() ) return;
|
|
A_SetScale(scale.x*(.6+specialf1),scale.y);
|
|
A_FadeOut(.1+specialf2);
|
|
}
|
|
States
|
|
{
|
|
Spawn:
|
|
XZW1 ABCDEFGHIJ -1 Bright;
|
|
Stop;
|
|
}
|
|
}
|
|
|
|
Class EvisceratorChunk : Actor
|
|
{
|
|
Mixin SWWMMissileFix;
|
|
|
|
Actor lasthit;
|
|
double anglevel, pitchvel, rollvel;
|
|
double lifetime, lifespeed;
|
|
Vector3 oldvel;
|
|
bool justdied;
|
|
int trailcolor;
|
|
|
|
Default
|
|
{
|
|
Obituary "$O_EVISCERATOR";
|
|
Radius 2;
|
|
Height 4;
|
|
Speed 50;
|
|
DamageFunction int(clamp((vel.length()-5)*.2,0,15)+(max(0,1-lifetime)**5)*10);
|
|
DamageType 'Shrapnel';
|
|
BounceFactor 1.0;
|
|
WallBounceFactor 1.0;
|
|
PROJECTILE;
|
|
+USEBOUNCESTATE;
|
|
+BOUNCEONWALLS;
|
|
+BOUNCEONFLOORS;
|
|
+BOUNCEONCEILINGS;
|
|
+ALLOWBOUNCEONACTORS;
|
|
+NODAMAGETHRUST;
|
|
+DONTBOUNCEONSKY;
|
|
+CANBOUNCEWATER;
|
|
+INTERPOLATEANGLES;
|
|
+ROLLSPRITE;
|
|
+ROLLCENTER;
|
|
Scale 0.4;
|
|
}
|
|
|
|
override void PostBeginPlay()
|
|
{
|
|
Super.PostBeginPlay();
|
|
let l = Spawn("EvisceratorChunkLight",pos);
|
|
l.target = self;
|
|
let t = Spawn("EvisceratorChunkGlow",pos);
|
|
t.target = self;
|
|
lifespeed = FRandom[Eviscerator](0.01,0.02)*clamp((vel.length()/75.)**2,1.,2.);
|
|
anglevel = FRandom[Eviscerator](50,100)*RandomPick[Eviscerator](-1,1);
|
|
pitchvel = FRandom[Eviscerator](50,100)*RandomPick[Eviscerator](-1,1);
|
|
rollvel = FRandom[Eviscerator](50,100)*RandomPick[Eviscerator](-1,1);
|
|
scale *= Frandom[Eviscerator](0.8,1.2);
|
|
frame = Random[Eviscerator](0,7);
|
|
}
|
|
|
|
override void Tick()
|
|
{
|
|
static const name tls[] =
|
|
{
|
|
'HotMetal0', 'HotMetal1', 'HotMetal2', 'HotMetal3',
|
|
'HotMetal4', 'HotMetal5', 'HotMetal6', 'HotMetal7'
|
|
};
|
|
oldvel = vel;
|
|
Super.Tick();
|
|
// somehow checking the state does not work all the time
|
|
// so instead I have to set a bool at the start of XDeath,
|
|
// otherwise there is a single puff of smoke at the LAST tic
|
|
// of the state, there is no logical explanation for this,
|
|
// I guess I can blame graf, randi, or whoever else
|
|
if ( isFrozen() || (freezetics > 0) || justdied ) return;
|
|
lifetime += lifespeed;
|
|
if ( waterlevel > 0 ) lifetime = max(.7,lifetime);
|
|
A_SetTranslation(tls[clamp(int(lifetime*10),0,7)]);
|
|
if ( !Random[Eviscerator](0,2) && (lifetime < .7) )
|
|
{
|
|
let s = Spawn("SWWMHalfSmoke",pos);
|
|
s.vel = .2*vel+SWWMUtility.Vec3FromAngles(FRandom[Eviscerator](0,360),FRandom[Eviscerator](-90,90));
|
|
s.scale *= .5;
|
|
s.alpha *= scale.x*max(0,.7-lifetime)*1.5;
|
|
}
|
|
if ( !InStateSequence(CurState,FindState("Death")) )
|
|
{
|
|
angle += anglevel;
|
|
pitch += pitchvel;
|
|
roll += rollvel;
|
|
double alph = clamp((.7-lifetime)/.7,0,1.);
|
|
if ( alph < 0 ) return;
|
|
Vector3 dir = level.Vec3Diff(pos,prev);
|
|
double dist = dir.length();
|
|
if ( dist < 1. ) return;
|
|
dir /= dist;
|
|
let t = Spawn("EvisceratorChunkTrail",pos);
|
|
t.alpha = alph;
|
|
t.speed = dist;
|
|
[t.angle, t.pitch, t.scale.y] = SWWMUtility.CalcYBeam(dir,dist);
|
|
t.SetState(t.SpawnState+trailcolor);
|
|
if ( trailcolor > 0 )
|
|
{
|
|
// custom trails last longer
|
|
t.specialf1 = .3;
|
|
t.specialf2 = -.05;
|
|
}
|
|
}
|
|
}
|
|
|
|
void A_HandleBounce()
|
|
{
|
|
Vector3 HitNormal = SWWMUtility.GetActorHitNormal(self);
|
|
if ( swwm_omnibust ) BusterWall.ProjectileBust(self,GetMissileDamage(0,0),oldvel.unit());
|
|
// undo the bounce, we need to hook in our own
|
|
vel = oldvel;
|
|
// re-do the bounce with our formula
|
|
Vector3 RealHitNormal = HitNormal;
|
|
double dfact = clamp((oldvel.length()/75.)**2.,.02,.6);
|
|
HitNormal = (HitNormal+SWWMUtility.Vec3FromAngles(FRandom[Eviscerator](0,360),FRandom[Eviscerator](-90,90))*dfact).unit();
|
|
if ( (HitNormal dot RealHitNormal) < 0 ) HitNormal *= -.5;
|
|
vel = FRandom[Eviscerator](.8,.95)*((vel dot HitNormal)*HitNormal*(FRandom[Eviscerator](-1.8,-1.))+vel);
|
|
bHITOWNER = true;
|
|
lasthit = null;
|
|
if ( (vel.length() > 20) && !Random[Eviscerator](0,2) )
|
|
{
|
|
let l = Spawn("ChunkImpact",pos);
|
|
l.angle = atan2(RealHitNormal.y,RealHitNormal.x);
|
|
l.pitch = asin(-RealHitNormal.z);
|
|
A_StartSound("eviscerator/hith",CHAN_WEAPON,CHANF_OVERLAP,.5);
|
|
}
|
|
A_Gravity();
|
|
gravity = clamp(.35-vel.length()/200.,.15,.35);
|
|
anglevel = FRandom[Eviscerator](50,100)*RandomPick[Eviscerator](-1,1)*(vel.length()/speed);
|
|
pitchvel = FRandom[Eviscerator](50,100)*RandomPick[Eviscerator](-1,1)*(vel.length()/speed);
|
|
rollvel = FRandom[Eviscerator](50,100)*RandomPick[Eviscerator](-1,1)*(vel.length()/speed);
|
|
A_StartSound("eviscerator/hit",CHAN_WEAPON,CHANF_OVERLAP,.3);
|
|
if ( vel.length() < 3 )
|
|
{
|
|
A_Stop();
|
|
ClearBounce();
|
|
ExplodeMissile();
|
|
}
|
|
}
|
|
|
|
override bool CanCollideWith( Actor other, bool passive )
|
|
{
|
|
// safer to do here
|
|
if ( !(other.bSHOOTABLE || other.bSOLID) || ((vel.length() <= 5) && other.bSHOOTABLE) || ((other == target) && !bHITOWNER) || (other == lasthit) )
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
override int SpecialMissileHit( Actor victim )
|
|
{
|
|
// directly bounce off non-shootable solids
|
|
if ( !victim.bSHOOTABLE )
|
|
{
|
|
if ( victim.bSOLID )
|
|
{
|
|
BlockingMobj = victim;
|
|
A_HandleBounce();
|
|
lasthit = victim;
|
|
}
|
|
return 1;
|
|
}
|
|
// with this we can guarantee that the chunk won't just keep on dealing damage
|
|
// this is something I wish Unreal's boulders did
|
|
lasthit = victim;
|
|
// don't knock back if already dead
|
|
int oldamt = SWWMDamageAccumulator.GetAmount(victim);
|
|
if ( victim.health-oldamt > 0 ) SWWMUtility.DoKnockback(victim,vel.unit(),15000);
|
|
// gather damage
|
|
int dmg = GetMissileDamage(0,0);
|
|
SWWMDamageAccumulator.Accumulate(victim,dmg,self,target,damagetype);
|
|
int amt = SWWMDamageAccumulator.GetAmount(victim);
|
|
// pass through if it's already dead
|
|
// + random chance relative to health
|
|
int posthealth = victim.health-amt;
|
|
double hratio = posthealth/double(victim.GetSpawnHealth());
|
|
if ( (posthealth <= 0) || (FRandom[Eviscerator](hratio,1.) < .7) )
|
|
{
|
|
if ( !victim.bNOBLOOD && !victim.bDORMANT && !victim.bINVULNERABLE )
|
|
{
|
|
victim.SpawnBlood(pos,AngleTo(victim),dmg);
|
|
A_StartSound("eviscerator/hitf",CHAN_WEAPON,CHANF_OVERLAP,.1);
|
|
}
|
|
else
|
|
{
|
|
let l = Spawn("ChunkImpact",pos);
|
|
l.angle = angle+180;
|
|
l.pitch = -pitch;
|
|
A_StartSound("eviscerator/hith",CHAN_WEAPON,CHANF_OVERLAP,.1);
|
|
}
|
|
vel *= FRandom[Eviscerator](.8,.9); // reduce velocity as it rips
|
|
A_Gravity();
|
|
gravity = clamp(.35-vel.length()/200.,.15,.35);
|
|
return 1;
|
|
}
|
|
// HACK
|
|
if ( !victim.bNOBLOOD && !victim.bDORMANT && !victim.bINVULNERABLE )
|
|
{
|
|
victim.SpawnBlood(pos,AngleTo(victim),dmg);
|
|
A_StartSound("eviscerator/hitf",CHAN_WEAPON,CHANF_OVERLAP,.1);
|
|
ExplodeMissile(null,victim);
|
|
}
|
|
else
|
|
{
|
|
BlockingMobj = victim;
|
|
A_HandleBounce();
|
|
lasthit = victim;
|
|
}
|
|
return 1;
|
|
}
|
|
States
|
|
{
|
|
Spawn:
|
|
XZW1 # -1;
|
|
Stop;
|
|
Bounce:
|
|
XZW1 # 0 A_HandleBounce();
|
|
Goto Spawn;
|
|
Death:
|
|
XZW1 # 0
|
|
{
|
|
bMOVEWITHSECTOR = true;
|
|
A_SetTics(Random[Eviscerator](30,50));
|
|
}
|
|
XZW1 # 1 A_FadeOut();
|
|
Wait;
|
|
XDeath:
|
|
TNT1 A 35 { justdied = true; }
|
|
Stop;
|
|
}
|
|
}
|
|
|
|
Class EvisceratorProjSmoke : SWWMNonInteractiveActor
|
|
{
|
|
double lifetime, lifespeed;
|
|
override void PostBeginPlay()
|
|
{
|
|
lifetime = 0;
|
|
lifespeed = FRandom[Eviscerator](0.004,0.008);
|
|
}
|
|
override void Tick()
|
|
{
|
|
if ( freezetics > 0 )
|
|
{
|
|
freezetics--;
|
|
return;
|
|
}
|
|
if ( isFrozen() ) return;
|
|
lifetime += lifespeed;
|
|
let s = Spawn("SWWMSmoke",pos);
|
|
s.vel = SWWMUtility.Vec3FromAngles(FRandom[Eviscerator](0,360),FRandom[Eviscerator](-90,90))*.5;
|
|
s.vel.z += 2.;
|
|
s.alpha = scale.x;
|
|
s.SetShade(Color(1,1,1)*Random[Eviscerator](160,255));
|
|
scale.x = max(0,1-lifetime);
|
|
if ( scale.x <= 0 ) Destroy();
|
|
}
|
|
}
|
|
|
|
Class EvisceratorProjLight : PaletteLight
|
|
{
|
|
Default
|
|
{
|
|
Args 0,0,0,140;
|
|
ReactionTime 20;
|
|
}
|
|
}
|
|
|
|
Class EvisceratorProj : Actor
|
|
{
|
|
Mixin SWWMMissileFix;
|
|
|
|
double heat;
|
|
Vector3 startpos;
|
|
Default
|
|
{
|
|
Obituary "$O_EVISCERATOR";
|
|
DamageType 'Explosive';
|
|
Radius 2;
|
|
Height 4;
|
|
Gravity 0.35;
|
|
Speed 60;
|
|
PROJECTILE;
|
|
-NOGRAVITY;
|
|
+EXPLODEONWATER;
|
|
+HITTRACER;
|
|
+FORCERADIUSDMG;
|
|
+NODAMAGETHRUST;
|
|
}
|
|
override void PostBeginPlay()
|
|
{
|
|
Super.PostBeginPlay();
|
|
startpos = pos;
|
|
if ( waterlevel <= 0 ) vel.z += 3;
|
|
heat = 1.5;
|
|
}
|
|
void A_EvisExplode()
|
|
{
|
|
if ( target && tracer && (tracer.bIsMonster||tracer.player) && tracer.IsHostile(target) )
|
|
{
|
|
double dist = level.Vec3Diff(pos,startpos).length();
|
|
SWWMUtility.AchievementProgress("lead",int(dist),target.player);
|
|
}
|
|
bForceXYBillboard = true;
|
|
A_SetRenderStyle(1.0,STYLE_Add);
|
|
A_SprayDecal("BigRocketBlast",50);
|
|
A_NoGravity();
|
|
A_SetScale(3.);
|
|
SWWMUtility.DoExplosion(self,120,120000,150,80);
|
|
A_QuakeEx(6,6,6,20,0,1200,"",QF_RELATIVE|QF_SCALEDOWN|QF_3D,falloff:300,rollIntensity:.7);
|
|
A_StartSound("eviscerator/shell",CHAN_WEAPON,attenuation:.5);
|
|
A_StartSound("eviscerator/shell",CHAN_VOICE,attenuation:.3);
|
|
A_AlertMonsters(swwm_uncapalert?0:3000,AMF_EMITFROMTARGET);
|
|
if ( !Tracer ) Spawn("EvisceratorProjSmoke",pos);
|
|
Spawn("EvisceratorProjLight",pos);
|
|
Vector3 x, y, z;
|
|
double a, s;
|
|
[x, y, z] = SWWMUtility.GetAxes(angle,pitch,roll);
|
|
EvisceratorChunk p;
|
|
Vector3 spawnofs;
|
|
if ( BlockingMobj ) spawnofs = (0,0,0);
|
|
else if ( BlockingFloor ) spawnofs = BlockingFloor.floorplane.Normal*4;
|
|
else if ( BlockingCeiling ) spawnofs = BlockingCeiling.ceilingplane.Normal*4;
|
|
else if ( BlockingLine )
|
|
{
|
|
spawnofs = (-BlockingLine.delta.y,BlockingLine.delta.x,0).unit()*4;
|
|
if ( !SWWMUtility.PointOnLineSide(pos.xy,BlockingLine) )
|
|
spawnofs *= -1;
|
|
}
|
|
int trail = 0;
|
|
if ( target && target.player ) trail = CVar.GetCVar('swwm_funtrails',target.player).GetInt();
|
|
if ( trail == 8 ) trail = Random[Eviscerator](0,7);
|
|
for ( int i=0; i<30; i++ )
|
|
{
|
|
p = EvisceratorChunk(Spawn("EvisceratorChunk",level.Vec3Offset(pos,spawnofs)));
|
|
p.bHITOWNER = true;
|
|
a = FRandom[Eviscerator](0,360);
|
|
s = FRandom[Eviscerator](0,.4);
|
|
Vector3 dir = SWWMUtility.ConeSpread(x,y,z,a,s);
|
|
p.angle = atan2(dir.y,dir.x);
|
|
p.pitch = -asin(dir.z);
|
|
p.vel = SWWMUtility.Vec3FromAngles(p.angle,p.pitch)*(p.speed+FRandom[Eviscerator](-5,20));
|
|
p.target = target;
|
|
if ( trail < 8 ) p.trailcolor = max(0,trail);
|
|
else if ( trail == 9 ) p.trailcolor = (i%6)+2;
|
|
else if ( trail == 10 )
|
|
{
|
|
switch ( i%6 )
|
|
{
|
|
case 0:
|
|
case 3:
|
|
p.trailcolor = 8;
|
|
break;
|
|
case 1:
|
|
case 4:
|
|
p.trailcolor = 9;
|
|
break;
|
|
case 2:
|
|
p.trailcolor = 1;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
int numpt = Random[Eviscerator](10,15);
|
|
for ( int i=0; i<numpt; i++ )
|
|
{
|
|
Vector3 pvel = SWWMUtility.Vec3FromAngles(FRandom[ExploS](0,360),FRandom[ExploS](-90,90))*FRandom[ExploS](1,3);
|
|
let s = Spawn("SWWMSmoke",pos);
|
|
s.vel = pvel;
|
|
s.SetShade(Color(1,1,1)*Random[ExploS](64,224));
|
|
s.special1 = Random[ExploS](1,2);
|
|
s.scale *= 2.4;
|
|
s.alpha *= .4;
|
|
}
|
|
numpt = Random[Eviscerator](8,12);
|
|
for ( int i=0; i<numpt; i++ )
|
|
{
|
|
Vector3 pvel = SWWMUtility.Vec3FromAngles(FRandom[Eviscerator](0,360),FRandom[Eviscerator](-90,90))*FRandom[Eviscerator](2,8);
|
|
let s = Spawn("SWWMSpark",level.Vec3Offset(pos,spawnofs));
|
|
s.vel = pvel;
|
|
}
|
|
numpt = Random[Eviscerator](8,16);
|
|
for ( int i=0; i<numpt; i++ )
|
|
{
|
|
Vector3 pvel = SWWMUtility.Vec3FromAngles(FRandom[Eviscerator](0,360),FRandom[Eviscerator](-90,90))*FRandom[Eviscerator](6,16);
|
|
let s = Spawn("SWWMChip",level.Vec3Offset(pos,spawnofs));
|
|
s.vel = pvel;
|
|
s.scale *= FRandom[Eviscerator](0.9,1.8);
|
|
}
|
|
Spawn("EvisceratorRing",pos);
|
|
if ( swwm_omnibust ) BusterWall.ProjectileBust(self,150,SWWMUtility.Vec3FromAngles(angle,pitch));
|
|
}
|
|
void A_SubExpl()
|
|
{
|
|
special1++;
|
|
if ( special1 > 8 ) return;
|
|
int numpt = Random[Eviscerator](0,8-special1);
|
|
double ang, pt;
|
|
for ( int i=0; i<numpt; i++ )
|
|
{
|
|
ang = FRandom[Eviscerator](0,360);
|
|
pt = FRandom[Eviscerator](-90,90);
|
|
FLineTraceData d;
|
|
Vector3 HitNormal;
|
|
LineTrace(ang,FRandom[Eviscerator](10,30)+10*special1,pt,TRF_THRUACTORS,data:d);
|
|
hitnormal = SWWMUtility.GetLineTraceHitNormal(d);
|
|
let p = Spawn("EvisceratorSubExpl",d.HitLocation+hitnormal*4);
|
|
p.angle = atan2(hitnormal.y,hitnormal.x);
|
|
p.pitch = asin(-hitnormal.z);
|
|
p.target = target;
|
|
p.scale *= 2-special1*.1;
|
|
p.alpha *= 1-special1*.1;
|
|
}
|
|
}
|
|
States
|
|
{
|
|
Spawn:
|
|
XZW1 A 1
|
|
{
|
|
heat -= 0.004+0.0004*vel.length();
|
|
if ( heat > 0 )
|
|
{
|
|
let s = Spawn("SWWMHalfSmoke",pos);
|
|
s.alpha *= heat;
|
|
}
|
|
}
|
|
Wait;
|
|
Death:
|
|
TNT1 A 0 A_EvisExplode();
|
|
XSEX ABCDEFGHIJKLMNOPQRS 2 Bright A_Subexpl();
|
|
Stop;
|
|
}
|
|
}
|
|
|
|
Class EvisceratorSubExpl : SWWMNonInteractiveActor
|
|
{
|
|
Default
|
|
{
|
|
RenderStyle "Add";
|
|
Scale 2.;
|
|
Alpha .6;
|
|
+FORCEXYBILLBOARD;
|
|
}
|
|
States
|
|
{
|
|
Spawn:
|
|
XSEX ABCDEFGHIJKLMNOPQRS 1 Bright;
|
|
Stop;
|
|
}
|
|
}
|
|
|
|
Class EvisceratorRing : SWWMNonInteractiveActor
|
|
{
|
|
Default
|
|
{
|
|
RenderStyle "Add";
|
|
Scale 4.;
|
|
+FORCEXYBILLBOARD;
|
|
}
|
|
States
|
|
{
|
|
Spawn:
|
|
XRG0 ABCDEFGHIJKLMNOPQRSTUVWX 1 Bright A_SetScale(scale.x*1.01);
|
|
Stop;
|
|
}
|
|
}
|
|
|
|
Class EvisceratorCasing : SWWMCasing
|
|
{
|
|
Default
|
|
{
|
|
Mass 10;
|
|
BounceFactor 0.4;
|
|
WallBounceFactor 0.4;
|
|
BounceSound "eviscerator/casing";
|
|
}
|
|
States
|
|
{
|
|
Death:
|
|
XZW1 BC -1
|
|
{
|
|
bINTERPOLATEANGLES = false;
|
|
pitch = roll = 0;
|
|
angle = FRandom[Junk](0,360);
|
|
frame = RandomPick[Junk](1,2);
|
|
}
|
|
Stop;
|
|
}
|
|
}
|