swwmgz_m/zscript/dlc1/swwm_notashotgun_fx.zsc

1091 lines
27 KiB
Text

// Quadravol projectiles and effects
Class QuadravolCasing : SWWMCasing
{
Default
{
BounceSound "quadshot/casing";
}
override void PostBeginPlay()
{
Super.PostBeginPlay();
heat = 0;
}
}
Class QuadExplLight : PaletteLight
{
Default
{
Tag "QuadExpl";
Args 0,0,0,150;
ReactionTime 20;
}
}
Class QuadExplLight2 : PaletteLight
{
Default
{
Tag "QuadExpl";
Args 0,0,0,250;
ReactionTime 25;
}
}
Class QuadExplLight3 : PaletteLight
{
Default
{
Tag "QuadExpl";
Args 0,0,0,300;
ReactionTime 30;
}
}
Class QuadFlare : SWWMNonInteractiveActor
{
bool bBig;
Default
{
RenderStyle "Add";
Alpha .5;
+FORCEXYBILLBOARD;
}
override void Tick()
{
prev = pos;
if ( freezetics > 0 )
{
freezetics--;
return;
}
if ( isFrozen() ) return;
if ( !master || !master.bMISSILE )
{
if ( !bBig )
{
bBig = true;
Scale *= 3.;
}
Scale *= .97;
A_FadeOut(.03);
return;
}
SetOrigin(master.pos,true);
}
States
{
Spawn:
QFLR A -1 Bright;
Stop;
}
}
Class QuadTrail : SWWMNonInteractiveActor
{
Mixin SWWMMinimalMovingTick;
Default
{
RenderStyle "Add";
Alpha .5;
Scale 1.5;
+FORCEXYBILLBOARD;
+ROLLSPRITE;
+ROLLCENTER;
}
override void PostBeginPlay()
{
Super.PostBeginPlay();
Scale.x *= RandomPick[ExploS](-1,1);
Scale.y *= RandomPick[ExploS](-1,1);
roll = FRandom[ExploS](0,360);
SetState(SpawnState+Random[ExploS](0,19));
}
void A_Flame()
{
vel *= .9;
A_SetScale(scale.x*.96);
A_FadeOut(.05);
}
States
{
Spawn:
XFLM ABCDEFGHIJKLMNOPQRST 1 Bright A_Flame();
Loop;
}
}
Class QuadEmber : SWWMNonInteractiveActor
{
Vector3 freq, amp, ph;
Default
{
RenderStyle "Add";
Scale .3;
+FORCEXYBILLBOARD;
}
override void PostBeginPlay()
{
Scale *= FRandom[ExploS](.5,1.5);
double ang = FRandom[ExploS](0,360),
pt = FRandom[ExploS](-90,90);
vel = SWWMUtility.Vec3FromAngles(ang,pt)*FRandom[ExploS](4.,8.);
freq = (FRandom[ExploS](.5,3.),FRandom[ExploS](.5,3.),FRandom[ExploS](.5,3.));
amp = (FRandom[ExploS](.5,2.),FRandom[ExploS](.5,2.),FRandom[ExploS](.5,2.));
ph = (FRandom[ExploS](0.,360.),FRandom[ExploS](0.,360.),FRandom[ExploS](0.,360.));
specialf1 = FRandom[ExploS](.98,.99);
specialf2 = FRandom[ExploS](.98,.99);
}
override void Tick()
{
prev = pos;
if ( freezetics > 0 )
{
freezetics--;
return;
}
if ( isFrozen() ) return;
if ( !InStateSequence(CurState,FindState("Death")) )
{
vel *= .95;
vel += .2*(sin(ph.x)*amp.x,sin(ph.y)*amp.y,sin(ph.z)*amp.z);
vel.z -= .05*clamp(2.-amp.length(),0.,2.);
ph.x += freq.x*(360./GameTicRate);
ph.y += freq.y*(360./GameTicRate);
ph.z += freq.z*(360./GameTicRate);
freq *= specialf1;
amp *= specialf2;
Vector3 newpos = level.Vec3Offset(pos,vel);
if ( !level.IsPointInLevel(newpos) )
{
vel *= 0;
SetStateLabel("Death");
return;
}
SetOrigin(newpos,true);
UpdateWaterLevel();
if ( waterlevel > 0 )
{
vel *= 0;
SetStateLabel("Death");
return;
}
A_FadeOut(FRandom[ExploS](.002,.005));
}
else A_FadeOut(FRandom[ExploS](.02,.05));
frame = clamp(int(round(4-alpha*4)),0,4);
}
States
{
Spawn:
QEMB # -1 Bright;
Stop;
Death:
QEMB # -1 Bright;
Stop;
}
}
Class QuadExplRing : SWWMNonInteractiveActor
{
Default
{
RenderStyle "Add";
Scale 1.2;
+FORCEXYBILLBOARD;
}
States
{
Spawn:
XRG8 ACEGIKMOQSUW 1 Bright A_SetScale(scale.x*1.05);
Stop;
}
}
Class QuadProj : Actor
{
meta double drift, accelrate, maxspeed;
Property Drift: drift;
Property AccelRate: accelrate;
Property MaxSpeed: maxspeed;
override void PostBeginPlay()
{
Super.PostBeginPlay();
A_StartSound("quadshot/fly",CHAN_BODY,CHANF_LOOP);
let t = Spawn("QuadFlare",pos);
t.master = self;
t.scale = scale*2.;
}
// acceleration, drift and speed limit
void A_QuadMove()
{
A_QuadTrail();
Vector3 x, y, z;
[x, y, z] = SWWMUtility.GetAxes(angle,pitch,roll);
double a = FRandom[Quadravol](0.,360.), s = FRandom[Quadravol](0.,drift);
vel += x*(accelrate/GameTicRate);
vel += SWWMUtility.CircleOffset(y,z,a,s);
double magvel = vel.length();
Vector3 dir = (magvel<=0.)?x:(vel/magvel);
if ( magvel > maxspeed ) magvel = maxspeed;
vel = dir*magvel;
speed = magvel;
}
virtual void A_QuadTrail()
{
let s = Spawn("QuadTrail",pos);
s.scale *= .6;
s.vel = vel*.2;
s = Spawn("SWWMHalfSmoke",pos);
s.vel = SWWMUtility.Vec3FromAngles(FRandom[Quadravol](0,360),FRandom[Quadravol](-90,90))*.4;
s.vel += vel*.3;
s.alpha *= .4;
int numpt = Random[Quadravol](5,15);
for ( int i=0; i<numpt; i++ )
{
s = Spawn("QuadEmber",pos);
s.vel += vel*.3;
}
}
virtual void A_QuadExplode()
{
A_StopSound(CHAN_BODY);
Scale *= 2.;
A_SprayDecal("ShockMark",50);
Vector3 x = SWWMUtility.Vec3FromAngles(angle,pitch);
if ( master && ((master.pos.z <= master.floorz) || !master.TestMobjZ()) )
{
Vector3 rel = level.Vec3Diff(master.pos,pos);
double hdiff = 1.-2.*clamp((rel.z-4.)/master.height,0.,.5);
SWWMUtility.DoKnockback(master,x+(0,0,hdiff),200000+special2);
}
if ( tracer ) SWWMUtility.DoKnockback(tracer,-x+(0,0,.1),bAMBUSH?150000:500000);
A_QuakeEx(3,3,3,20,0,500,"",QF_RELATIVE|QF_SCALEDOWN|QF_3D,falloff:200,rollintensity:.6);
SWWMUtility.DoExplosion(self,0,120000+special2,150,40,DE_BLAST|DE_EXTRAZTHRUST);
SWWMUtility.DoExplosion(self,100+special1,0,150,0,DE_QUADRAVOL|DE_NOSPLASH,ignoreme:tracer);
SWWMUtility.DoExplosion(self,200+special1,0,120,40,DE_HOWL|DE_NOSPLASH,ignoreme:tracer);
A_StartSound("quadshot/hit",CHAN_WEAPON,attenuation:.6);
A_StartSound("quadshot/hit",CHAN_VOICE,attenuation:.4);
A_AlertMonsters(swwm_uncapalert?0:1500);
Spawn("QuadExplLight",pos);
Spawn("QuadExplRing",pos);
int numpt = Random[Quadravol](12,18);
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = SWWMUtility.Vec3FromAngles(FRandom[Quadravol](0,360),FRandom[Quadravol](-90,90))*FRandom[Quadravol](2,8);
let s = Spawn("SWWMSmoke",pos);
s.vel = pvel;
s.special1 = Random[Quadravol](2,3);
s.scale *= 4.;
s.alpha *= .3;
}
numpt = Random[Quadravol](10,15);
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = SWWMUtility.Vec3FromAngles(FRandom[Quadravol](0,360),FRandom[Quadravol](-90,90))*FRandom[Quadravol](4,16);
let s = Spawn("SWWMSpark",pos);
s.vel = pvel;
}
numpt = Random[Quadravol](4,8);
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = SWWMUtility.Vec3FromAngles(FRandom[Quadravol](0,360),FRandom[Quadravol](-90,90))*FRandom[Quadravol](6,12);
let s = Spawn("SWWMChip",pos);
s.vel = pvel;
s.scale *= FRandom[Quadravol](0.9,1.8);
}
if ( swwm_omnibust ) BusterWall.ProjectileBust(self,150,SWWMUtility.Vec3FromAngles(angle,pitch));
}
override String GetObituary( Actor victim, Actor inflictor, Name mod, bool playerattack )
{
// from melee combo
if ( bAMBUSH ) return StringTable.Localize("$O_QUADRAVOL2");
return Super.GetObituary(victim,inflictor,mod,playerattack);
}
Default
{
Obituary "$O_QUADRAVOL";
DamageType "Fire";
Scale .5;
Radius 6;
Height 6;
Speed 60;
QuadProj.Drift .15;
QuadProj.AccelRate 30;
QuadProj.MaxSpeed 120;
PROJECTILE;
+FORCEXYBILLBOARD;
+EXPLODEONWATER;
+FORCERADIUSDMG;
+NODAMAGETHRUST;
+HITMASTER;
+NOFRICTION;
RenderStyle "Add";
}
States
{
Spawn:
QFBL ABCDEFGHIJ 1 Bright A_QuadMove();
Loop;
Death:
TNT1 A 0 A_QuadExplode();
XEX0 ABCDEFGHIJKLMNOPQRS 1 Bright A_SetScale(scale.x*1.05);
Stop;
}
}
Class QuadExplArm : Actor
{
Default
{
PROJECTILE;
+THRUACTORS;
+BOUNCEONWALLS;
+BOUNCEONFLOORS;
+BOUNCEONCEILINGS;
+CANBOUNCEWATER;
+NODAMAGETHRUST;
+FORCERADIUSDMG;
-NOGRAVITY;
+NOFRICTION;
Gravity .35;
BounceFactor 1.;
Radius 2;
Height 4;
}
override void PostBeginPlay()
{
Super.PostBeginPlay();
reactiontime = Random[ExploS](4,8)+special1;
double ang, pt;
ang = FRandom[ExploS](0,360);
pt = FRandom[ExploS](-90,90);
speed = FRandom[ExploS](12.,32.);
vel = SWWMUtility.Vec3FromAngles(ang,pt)*speed;
}
States
{
Spawn:
TNT1 A 1
{
Spawn("QuadExplTrail",pos);
if ( !(ReactionTime%2) )
SWWMUtility.DoExplosion(self,8+reactiontime*3,0,40+5*reactiontime,20,DE_QUADRAVOL|DE_NOSPLASH,ignoreme:tracer);
Vector3 pvel = SWWMUtility.Vec3FromAngles(FRandom[ExploS](0,360),FRandom[ExploS](-90,90))*FRandom[ExploS](1,5);
let s = Spawn("SWWMHalfSmoke",pos);
s.vel = pvel+vel*.3;
s.special1 = Random[ExploS](1,3);
s.scale *= 3.;
s.alpha *= .1+.4*(ReactionTime/(8.+special1));
int numpt = Random[Quadravol](1,4);
for ( int i=0; i<numpt; i++ )
{
s = Spawn("QuadEmber",pos);
s.vel += vel*.4;
}
A_CountDown();
}
Wait;
}
}
Class QuadExplArm2 : QuadExplArm
{
override void PostBeginPlay()
{
Actor.PostBeginPlay();
reactiontime = Random[ExploS](4,8)+special1;
speed = FRandom[ExploS](40.,80.)+special2;
vel = SWWMUtility.Vec3FromAngles(angle,pitch)*speed;
}
States
{
Spawn:
TNT1 A 1
{
Spawn("QuadExplTrail2",pos);
if ( !(ReactionTime%2) )
{
SWWMUtility.DoExplosion(self,0,80000+reactiontime*5000,120+6*reactiontime,50,DE_BLAST|DE_EXTRAZTHRUST,ignoreme:tracer);
SWWMUtility.DoExplosion(self,60+reactiontime*5,0,120+6*reactiontime,50,DE_QUADRAVOL|DE_NOSPLASH,ignoreme:tracer);
SWWMUtility.DoExplosion(self,80+reactiontime*10,0,100+4*reactiontime,50,DE_HOWL|DE_NOSPLASH,ignoreme:tracer);
}
Vector3 pvel = SWWMUtility.Vec3FromAngles(FRandom[ExploS](0,360),FRandom[ExploS](-90,90))*FRandom[ExploS](2,5);
let s = Spawn("SWWMHalfSmoke",pos);
s.vel = pvel+vel*.6;
s.special1 = Random[ExploS](2,4);
s.scale *= 3.2;
s.alpha *= .1+.4*(ReactionTime/(12.+special1));
int numpt = Random[Quadravol](1,5);
for ( int i=0; i<numpt; i++ )
{
s = Spawn("QuadEmber",pos);
s.vel += vel*.7;
}
A_CountDown();
}
Wait;
}
}
Class QuadExplTrail : SWWMNonInteractiveActor
{
Default
{
RenderStyle "Add";
+FORCEXYBILLBOARD;
Scale 1.2;
}
States
{
Spawn:
XEX0 ACEGIKMOQS 1 Bright A_SetScale(scale.x*1.03);
Stop;
}
}
Class QuadExplTrail2 : QuadExplTrail
{
States
{
Spawn:
XEX0 ABCDEFGHIJKLMNOPQRS 1 Bright A_SetScale(scale.x*1.02);
Stop;
}
}
Class QuadExplRing2 : QuadExplRing
{
Default
{
Scale 2.;
}
States
{
Spawn:
XRG8 ABCDEFGHIJKLMNOPQRSTUVWX 1 Bright A_SetScale(scale.x*1.04);
Stop;
}
}
Class QuadProj2 : QuadProj
{
Default
{
Scale .85;
Radius 8;
Height 8;
Speed 40;
QuadProj.Drift .25;
QuadProj.AccelRate 20;
QuadProj.MaxSpeed 80;
}
override void A_QuadTrail()
{
let s = Spawn("QuadTrail",pos);
s.scale *= .8;
s.vel = vel*.3;
s = Spawn("SWWMHalfSmoke",pos);
s.vel = SWWMUtility.Vec3FromAngles(FRandom[Quadravol](0,360),FRandom[Quadravol](-90,90))*.4;
s.vel += vel*.4;
s.alpha *= .6;
int numpt = Random[Quadravol](5,25);
for ( int i=0; i<numpt; i++ )
{
s = Spawn("QuadEmber",pos);
s.vel += vel*.4;
}
}
override void A_QuadExplode()
{
A_StopSound(CHAN_BODY);
Scale *= 2.4;
A_SprayDecal("ShockMarkBig",50);
Vector3 x = SWWMUtility.Vec3FromAngles(angle,pitch);
if ( master && ((master.pos.z <= master.floorz) || !master.TestMobjZ()) )
{
Vector3 rel = level.Vec3Diff(master.pos,pos);
double hdiff = 1.-2.*clamp((rel.z-4.)/master.height,0.,.5);
SWWMUtility.DoKnockback(master,x+(0,0,hdiff),280000+special2);
}
if ( tracer ) SWWMUtility.DoKnockback(tracer,-x+(0,0,.1),bAMBUSH?160000:600000);
A_QuakeEx(5,5,5,25,0,900,"",QF_RELATIVE|QF_SCALEDOWN|QF_3D,falloff:400,rollintensity:.8);
SWWMUtility.DoExplosion(self,0,180000+special2,240,80,DE_BLAST|DE_EXTRAZTHRUST);
SWWMUtility.DoExplosion(self,200+special1,0,240,0,DE_QUADRAVOL|DE_NOSPLASH,ignoreme:tracer);
SWWMUtility.DoExplosion(self,400+special1,0,200,80,DE_HOWL|DE_NOSPLASH,ignoreme:tracer);
A_StartSound("quadshot/twohit",CHAN_WEAPON,attenuation:.5);
A_StartSound("quadshot/twohit",CHAN_VOICE,attenuation:.25);
A_AlertMonsters(swwm_uncapalert?0:2500);
Spawn("QuadExplLight2",pos);
Spawn("QuadExplRing2",pos);
int numpt = Random[Quadravol](20,30);
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = SWWMUtility.Vec3FromAngles(FRandom[Quadravol](0,360),FRandom[Quadravol](-90,90))*FRandom[Quadravol](2,12);
let s = Spawn("SWWMSmoke",pos);
s.vel = pvel;
s.special1 = Random[Quadravol](2,3);
s.scale *= 4.;
s.alpha *= .3;
}
numpt = Random[Quadravol](15,20);
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = SWWMUtility.Vec3FromAngles(FRandom[Quadravol](0,360),FRandom[Quadravol](-90,90))*FRandom[Quadravol](4,16);
let s = Spawn("SWWMSpark",pos);
s.vel = pvel;
}
numpt = Random[Quadravol](8,12);
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = SWWMUtility.Vec3FromAngles(FRandom[Quadravol](0,360),FRandom[Quadravol](-90,90))*FRandom[Quadravol](6,12);
let s = Spawn("SWWMChip",pos);
s.vel = pvel;
s.scale *= FRandom[Quadravol](0.9,1.8);
}
numpt = Random[Quadravol](12,16);
for ( int i=0; i<numpt; i++ )
{
let s = Spawn("QuadExplArm",pos);
s.target = target;
s.tracer = tracer;
}
if ( swwm_omnibust ) BusterWall.ProjectileBust(self,300,SWWMUtility.Vec3FromAngles(angle,pitch));
}
States
{
Death:
TNT1 A 0 A_QuadExplode();
XEX0 ABCDEFGHIJKLMNOPQRS 1 Bright A_SetScale(scale.x*1.065);
Stop;
}
}
Class QuadProjSub : QuadProj
{
Default
{
Scale .3;
Radius 2;
Height 2;
Speed 30;
QuadProj.Drift 10.;
QuadProj.AccelRate 100;
QuadProj.MaxSpeed 150;
}
override void A_QuadTrail()
{
let s = Spawn("QuadTrail",pos);
s.scale *= .5;
s.vel = vel*.3;
s = Spawn("SWWMHalfSmoke",pos);
s.vel = SWWMUtility.Vec3FromAngles(FRandom[Quadravol](0,360),FRandom[Quadravol](-90,90))*.4;
s.vel += vel*.4;
s.alpha *= .2;
int numpt = Random[Quadravol](1,4);
for ( int i=0; i<numpt; i++ )
{
s = Spawn("QuadEmber",pos);
s.vel += vel*.4;
}
}
override void A_QuadExplode()
{
A_StopSound(CHAN_BODY);
Scale *= 1.5;
A_SprayDecal("ShockMark",50);
Vector3 x = SWWMUtility.Vec3FromAngles(angle,pitch);
if ( master && ((master.pos.z <= master.floorz) || !master.TestMobjZ()) )
{
Vector3 rel = level.Vec3Diff(master.pos,pos);
double hdiff = 1.-2.*clamp((rel.z-4.)/master.height,0.,.5);
SWWMUtility.DoKnockback(master,x+(0,0,hdiff),100000);
}
A_QuakeEx(2,2,2,10,0,300,"",QF_RELATIVE|QF_SCALEDOWN|QF_3D,falloff:100,rollintensity:.3);
SWWMUtility.DoExplosion(self,0,70000,120,40,DE_BLAST|DE_EXTRAZTHRUST);
SWWMUtility.DoExplosion(self,50,0,120,0,DE_QUADRAVOL|DE_NOSPLASH,ignoreme:tracer);
SWWMUtility.DoExplosion(self,150,0,100,40,DE_HOWL|DE_NOSPLASH,ignoreme:tracer);
A_StartSound("quadshot/hit",CHAN_WEAPON,attenuation:.8,pitch:1.2);
A_AlertMonsters(swwm_uncapalert?0:800);
Spawn("QuadExplLight",pos);
int numpt = Random[Quadravol](6,12);
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = SWWMUtility.Vec3FromAngles(FRandom[Quadravol](0,360),FRandom[Quadravol](-90,90))*FRandom[Quadravol](2,8);
let s = Spawn("SWWMSmoke",pos);
s.vel = pvel;
s.special1 = Random[Quadravol](2,3);
s.scale *= 4.;
s.alpha *= .3;
}
numpt = Random[Quadravol](5,10);
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = SWWMUtility.Vec3FromAngles(FRandom[Quadravol](0,360),FRandom[Quadravol](-90,90))*FRandom[Quadravol](4,16);
let s = Spawn("SWWMSpark",pos);
s.vel = pvel;
}
numpt = Random[Quadravol](2,4);
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = SWWMUtility.Vec3FromAngles(FRandom[Quadravol](0,360),FRandom[Quadravol](-90,90))*FRandom[Quadravol](6,12);
let s = Spawn("SWWMChip",pos);
s.vel = pvel;
s.scale *= FRandom[Quadravol](0.9,1.8);
}
if ( swwm_omnibust ) BusterWall.ProjectileBust(self,100,SWWMUtility.Vec3FromAngles(angle,pitch));
}
States
{
Death:
TNT1 A 0 A_QuadExplode();
XEX0 ACEGIKMOQS 1 Bright A_SetScale(scale.x*1.1);
Stop;
}
}
Class QuadProjSub2 : QuadProj
{
Default
{
Scale .3;
Radius 4;
Height 4;
Speed 30;
QuadProj.Drift 3.;
QuadProj.AccelRate 80;
QuadProj.MaxSpeed 120;
}
override void A_QuadTrail()
{
let s = Spawn("QuadTrail",pos);
s.scale *= .3;
s.vel = vel*.3;
s = Spawn("SWWMHalfSmoke",pos);
s.vel = SWWMUtility.Vec3FromAngles(FRandom[Quadravol](0,360),FRandom[Quadravol](-90,90))*.4;
s.vel += vel*.4;
s.alpha *= .2;
int numpt = Random[Quadravol](1,4);
for ( int i=0; i<numpt; i++ )
{
s = Spawn("QuadEmber",pos);
s.vel += vel*.4;
}
}
override void A_QuadExplode()
{
A_StopSound(CHAN_BODY);
Scale *= 1.5;
A_SprayDecal("ShockMark",50);
Vector3 x = SWWMUtility.Vec3FromAngles(angle,pitch);
if ( master && ((master.pos.z <= master.floorz) || !master.TestMobjZ()) )
{
Vector3 rel = level.Vec3Diff(master.pos,pos);
double hdiff = 1.-2.*clamp((rel.z-4.)/master.height,0.,.5);
SWWMUtility.DoKnockback(master,x+(0,0,hdiff),100000);
}
A_QuakeEx(2,2,2,10,0,200,"",QF_RELATIVE|QF_SCALEDOWN|QF_3D,falloff:80,rollintensity:.2);
SWWMUtility.DoExplosion(self,0,60000,120,40,DE_BLAST|DE_EXTRAZTHRUST);
SWWMUtility.DoExplosion(self,80,0,120,0,DE_QUADRAVOL|DE_NOSPLASH,ignoreme:tracer);
SWWMUtility.DoExplosion(self,180,0,100,40,DE_HOWL|DE_NOSPLASH,ignoreme:tracer);
A_StartSound("quadshot/hit",CHAN_WEAPON,attenuation:.6,pitch:1.1);
A_AlertMonsters(swwm_uncapalert?0:600);
Spawn("QuadExplLight",pos);
int numpt = Random[Quadravol](6,12);
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = SWWMUtility.Vec3FromAngles(FRandom[Quadravol](0,360),FRandom[Quadravol](-90,90))*FRandom[Quadravol](2,8);
let s = Spawn("SWWMSmoke",pos);
s.vel = pvel;
s.special1 = Random[Quadravol](2,3);
s.scale *= 4.;
s.alpha *= .3;
}
numpt = Random[Quadravol](5,10);
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = SWWMUtility.Vec3FromAngles(FRandom[Quadravol](0,360),FRandom[Quadravol](-90,90))*FRandom[Quadravol](4,16);
let s = Spawn("SWWMSpark",pos);
s.vel = pvel;
}
numpt = Random[Quadravol](2,4);
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = SWWMUtility.Vec3FromAngles(FRandom[Quadravol](0,360),FRandom[Quadravol](-90,90))*FRandom[Quadravol](6,12);
let s = Spawn("SWWMChip",pos);
s.vel = pvel;
s.scale *= FRandom[Quadravol](0.9,1.8);
}
if ( swwm_omnibust ) BusterWall.ProjectileBust(self,120,SWWMUtility.Vec3FromAngles(angle,pitch));
}
States
{
Death:
TNT1 A 0 A_QuadExplode();
XEX0 ACEGIKMOQS 1 Bright A_SetScale(scale.x*1.1);
Stop;
}
}
Class QuadExplRing3 : QuadExplRing
{
Default
{
Scale 2.5;
}
States
{
Spawn:
XRG8 ABCDEFGHIJKLMNOPQRSTUVWX 1 Bright A_SetScale(scale.x*1.05);
Stop;
}
}
Class QuadProj3 : QuadProj
{
Default
{
Scale 1.;
Radius 10;
Height 10;
Speed 20;
QuadProj.Drift .8;
QuadProj.AccelRate 40;
QuadProj.MaxSpeed 60;
}
override void A_QuadTrail()
{
let s = Spawn("QuadTrail",pos);
s.scale *= 1.2;
s.vel = vel*.4;
s = Spawn("SWWMHalfSmoke",pos);
s.vel = SWWMUtility.Vec3FromAngles(FRandom[Quadravol](0,360),FRandom[Quadravol](-90,90))*.4;
s.vel += vel*.6;
s.alpha *= .8;
s.special1 = 1;
int numpt = Random[Quadravol](5,30);
for ( int i=0; i<numpt; i++ )
{
s = Spawn("QuadEmber",pos);
s.vel += vel*.6;
}
}
override void A_QuadExplode()
{
A_StopSound(CHAN_BODY);
Scale *= 3.;
A_SprayDecal("ShockMarkHuge",50);
Vector3 x = SWWMUtility.Vec3FromAngles(angle,pitch);
if ( master && ((master.pos.z <= master.floorz) || !master.TestMobjZ()) )
{
Vector3 rel = level.Vec3Diff(master.pos,pos);
double hdiff = 1.-2.*clamp((rel.z-4.)/master.height,0.,.5);
SWWMUtility.DoKnockback(master,x+(0,0,hdiff),350000+special2);
}
if ( tracer ) SWWMUtility.DoKnockback(tracer,-x+(0,0,.1),bAMBUSH?180000:800000);
A_QuakeEx(7,7,7,35,0,1200,"",QF_RELATIVE|QF_SCALEDOWN|QF_3D,falloff:600,rollintensity:1.2);
SWWMUtility.DoExplosion(self,0,200000+special2,300,120,DE_BLAST|DE_EXTRAZTHRUST);
SWWMUtility.DoExplosion(self,300+special1,0,300,0,DE_QUADRAVOL|DE_NOSPLASH,ignoreme:tracer);
SWWMUtility.DoExplosion(self,500+special1,0,240,120,DE_HOWL|DE_NOSPLASH,ignoreme:tracer);
A_StartSound("quadshot/twohit",CHAN_WEAPON,attenuation:.4,pitch:.9);
A_StartSound("quadshot/twohit",CHAN_VOICE,attenuation:.3,pitch:.8);
A_StartSound("quadshot/extrahit",CHAN_ITEM,attenuation:.2,pitch:1.1);
A_AlertMonsters(swwm_uncapalert?0:3500);
Spawn("QuadExplLight3",pos);
Spawn("QuadExplRing3",pos);
int numpt = Random[Quadravol](25,35);
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = SWWMUtility.Vec3FromAngles(FRandom[Quadravol](0,360),FRandom[Quadravol](-90,90))*FRandom[Quadravol](2,12);
let s = Spawn("SWWMSmoke",pos);
s.vel = pvel;
s.special1 = Random[Quadravol](2,3);
s.scale *= 4.;
s.alpha *= .3;
}
numpt = Random[Quadravol](20,25);
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = SWWMUtility.Vec3FromAngles(FRandom[Quadravol](0,360),FRandom[Quadravol](-90,90))*FRandom[Quadravol](4,16);
let s = Spawn("SWWMSpark",pos);
s.vel = pvel;
}
numpt = Random[Quadravol](10,15);
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = SWWMUtility.Vec3FromAngles(FRandom[Quadravol](0,360),FRandom[Quadravol](-90,90))*FRandom[Quadravol](6,12);
let s = Spawn("SWWMChip",pos);
s.vel = pvel;
s.scale *= FRandom[Quadravol](0.9,1.8);
}
numpt = Random[Quadravol](16,20);
for ( int i=0; i<numpt; i++ )
{
let s = Spawn("QuadExplArm",pos);
s.target = target;
s.tracer = tracer;
s.special1 = 10;
}
for ( int j=-90; j<=90; j+=30 ) for ( int i=0; i<360; i+=60 )
{
double ang = i+FRandom[ExploS](-30,30);
double pt = j+FRandom[ExploS](-15,15);
// skip if directly hitting a wall
if ( LineTrace(ang,40,pt,TRF_THRUACTORS|TRF_THRUHITSCAN) ) continue;
let s = Spawn("QuadProjSub",pos);
s.target = target;
s.tracer = tracer;
s.angle = ang;
s.pitch = pt;
s.vel = SWWMUtility.Vec3FromAngles(ang,pt)*s.speed*FRandom[ExploS](.8,1.2);
s.bHITOWNER = !tracer;
if ( (j == -90) || (j == 90) ) break; // only one per pole
}
if ( swwm_omnibust ) BusterWall.ProjectileBust(self,300,SWWMUtility.Vec3FromAngles(angle,pitch));
}
States
{
Death:
TNT1 A 0 A_QuadExplode();
XEX0 ABCDEFGHIJKLMNOPQRS 1 Bright A_SetScale(scale.x*1.08);
Stop;
}
}
Class OnFireLight : PointLightFlickerRandomAttenuated
{
OnFire of;
override void Tick()
{
Super.Tick();
if ( !of || !of.Owner )
{
A_StopSound(CHAN_VOICE);
Destroy();
return;
}
Args[0] = clamp(of.Amount*4,0,255);
Args[1] = clamp(of.Amount*2,0,160);
Args[2] = clamp(of.Amount/2,0,24);
Args[3] = int(max(of.Owner.radius,of.Owner.height)*2.5+40+clamp(of.Amount/4,0,120));
Args[4] = args[3]+8;
SetOrigin(of.Owner.Vec3Offset(0,0,of.Owner.Height/2),true);
}
}
Class OnFire : Inventory
{
Actor instigator, lite;
int cnt;
double oangle;
Default
{
Obituary "$O_QUADRAVOL";
Inventory.Amount 1;
Inventory.MaxAmount 500;
+INVENTORY.KEEPDEPLETED; // since our amount can go below 0, we need special cleanup
+INVENTORY.UNDROPPABLE;
+INVENTORY.UNTOSSABLE;
+NOEXTREMEDEATH;
}
override void AttachToOwner( Actor other )
{
Super.AttachToOwner(other);
cnt = 1;
lite = Spawn("OnFireLight",other.pos);
lite.specialf1 = 3;
OnFireLight(lite).of = self;
}
override void OwnerDied()
{
Super.OwnerDied();
amount = min(amount,100);
}
override void PreTravelled()
{
Super.PreTravelled();
// debuff disappears between levels
Destroy();
}
override int DoSpecialDamage( Actor target, int Damage, Name DamageType )
{
if ( target == Owner ) return Damage;
// spread ourselves
// note: cannot spread to Demolitionist
if ( !(target is 'Demolitionist') )
{
let t = OnFire(target.FindInventory("OnFire"));
if ( !t )
{
t = Apply(target,instigator,min(Damage,int(Amount*.6))); // prevent "escalating" spread
t.cnt = 15; // long delay
}
else if ( t.Amount < int(Amount*.6) ) t.Amount = min(t.Amount+Damage,int(Amount*.6)); // prevent "escalating" spread
t.instigator = instigator;
}
return clamp(int(Damage*.15),1,50); // reduced direct damage
}
override void DoEffect()
{
Super.DoEffect();
if ( !Owner )
{
Destroy();
return;
}
if ( Owner is 'Demolitionist' ) amount = min(amount-1,100); // Demo's body puts out fire faster
if ( !(level.maptime%3) )
amount--;
if ( Owner.player ) amount -= int(abs(actor.deltaangle(Owner.angle,oangle))/30);
oangle = Owner.angle;
if ( amount < -30 )
{
Destroy();
return;
}
if ( cnt > 0 ) cnt--;
else
{
cnt = 10;
if ( Owner.bSHOOTABLE && (Owner.Health > 0) && (amount > 0) )
{
int flg = DMG_THRUSTLESS;
if ( Owner is 'Centaur' ) flg |= DMG_FOILINVUL; // you're on fire, that shield is worthless
Owner.DamageMobj(self,instigator,clamp(int(amount*.15),1,50),'Fire',flg);
if ( Owner && Owner.bISMONSTER && !Random[FlameT](0,3) )
Owner.Howl();
}
if ( !Owner )
{
Destroy();
return;
}
// damage nearby actors
if ( amount > 0 ) SWWMUtility.DoExplosion(Owner,amount,0,Owner.radius+40+amount/5,Owner.radius+20,DE_NOBLEED|DE_NOSPLASH|DE_HOWL|DE_CENTERHEIGHT|DE_NONEXPLOSIVE,'Fire',null,DMG_THRUSTLESS,instigator,self);
}
double mult = max(Owner.radius,Owner.height)/30.;
if ( lite ) lite.A_SoundVolume(CHAN_VOICE,min(1.,mult*amount/80.));
if ( level.maptime%5 ) return;
int numpt = clamp(int(Random[FlameT](2,4)*amount*.02),1,4);
numpt = int(clamp(numpt*mult**.5,1,5));
for ( int i=0; i<numpt; i++ )
{
Vector3 tpos = Owner.Vec3Offset(FRandom[FlameT](-Owner.radius,Owner.radius)*.8,FRandom[FlameT](-Owner.radius,Owner.radius)*.8,FRandom[FlameT](Owner.height*.2,Owner.height*.8));
double ang = FRandom[FlameT](0,360);
double pt = FRandom[FlameT](-90,90);
if ( amount > 0 )
{
let c = Spawn("OnFireTrail",tpos);
c.scale *= max(.35,mult*.6);
c.vel = Owner.vel*.5+SWWMUtility.Vec3FromAngles(ang,pt)*FRandom[FlameT](.5,2.)*c.scale.x;
}
if ( Random[FlameT](0,3) ) continue;
let s = Spawn("SWWMHalfSmoke",tpos);
s.scale *= max(.35,mult*.5);
s.alpha *= min(amount+30,100)*.005;
s.vel = Owner.vel*.5+SWWMUtility.Vec3FromAngles(ang,pt)*FRandom[FlameT](.2,.6)*s.scale.x;
}
}
static OnFire Apply( Actor victim, Actor instigator, int amount )
{
let t = OnFire(victim.FindInventory("OnFire"));
if ( t )
{
t.instigator = instigator;
t.amount = min(t.maxamount,t.amount+amount);
t.cnt = min(t.cnt,5);
return t;
}
t = OnFire(Spawn("ONFire"));
t.AttachToOwner(victim);
t.instigator = instigator;
t.amount = min(t.maxamount,amount);
t.cnt = 1;
t.oangle = victim.angle;
double mult = max(victim.radius,victim.height)/30.;
t.lite.A_StartSound("misc/flame",CHAN_VOICE,CHANF_LOOP);
t.lite.A_SoundVolume(CHAN_VOICE,min(1.,mult*amount/80.));
return t;
}
static clearscope OnFire IsOnFire( Actor victim )
{
let t = OnFire(victim.FindInventory("OnFire"));
if ( t && (t.amount > 0) ) return t;
return null;
}
}
Class OnFireTrail : SWWMNonInteractiveActor
{
Mixin SWWMMinimalMovingWaterTick;
override void PostBeginPlay()
{
Super.PostBeginPlay();
Scale.x *= RandomPick[ExploS](-1,1);
Scale.y *= RandomPick[ExploS](-1,1);
roll = FRandom[ExploS](0,360);
SetState(SpawnState+Random[ExploS](0,39));
}
void A_Flame()
{
special1++;
if ( waterlevel > 0 )
vel *= .9;
else
{
vel *= .98;
vel.z += .1+.2*abs(scale.x);
}
if ( !Random[FlameT](0,int(40*(default.alpha-alpha))) )
{
let s = Spawn("SWWMHalfSmoke",pos);
s.vel = SWWMUtility.Vec3FromAngles(FRandom[FlameT](0,360),FRandom[FlameT](-90,90))*.2;
s.vel += vel*.3;
s.alpha *= alpha*.5;
s.scale *= .5+abs(scale.x*2)*(.5+special1/6.);
s.special1 = 1;
}
A_SetScale(scale.x*.98,scale.y*.98);
A_FadeOut(.01);
}
Default
{
RenderStyle "Add";
Speed 2;
Alpha .3;
Scale .6;
+FORCEXYBILLBOARD;
+ROLLSPRITE;
+ROLLCENTER;
}
States
{
Spawn:
XFLM AABBCCDDEEFFGGHHIIJJKKLLMMNNOOPPQQRRSSTT 1 Bright A_Flame();
Loop;
}
}