swwmgz_m/zscript/weapons/swwm_splode_fx.zsc

561 lines
14 KiB
Text

// Explodium Gun projectiles and effects
Class ExplodiumCasing : SWWMCasing {}
Class ExplodiumMag : SWWMCasing
{
Default
{
Mass 10;
BounceFactor 0.4;
WallBounceFactor 0.4;
BounceSound "explodium/mag";
}
override void PostBeginPlay()
{
Super.PostBeginPlay();
heat = 0;
}
States
{
Death:
XZW1 BC -1
{
pitch = roll = 0;
angle = FRandom[Junk](0,360);
frame = RandomPick[Junk](1,2);
}
Stop;
}
}
Class ExplodiumMagArm : Actor
{
Default
{
Obituary "$O_EXPLODIUM";
PROJECTILE;
+THRUACTORS;
+BOUNCEONWALLS;
+BOUNCEONFLOORS;
+BOUNCEONCEILINGS;
+CANBOUNCEWATER;
+NODAMAGETHRUST;
+FORCERADIUSDMG;
-NOGRAVITY;
Gravity 0.35;
BounceFactor 1.0;
Radius 2;
Height 4;
}
override void PostBeginPlay()
{
Super.PostBeginPlay();
reactiontime = Random[ExploS](10,15);
double ang, pt;
ang = FRandom[ExploS](0,360);
pt = FRandom[ExploS](-90,90);
vel = (cos(ang)*cos(pt),sin(ang)*cos(pt),-sin(pt))*FRandom[ExploS](8.,20.);
}
States
{
Spawn:
TNT1 A 1
{
Spawn("ExplodiumMagTrail",pos);
if ( !(ReactionTime%2) )
{
int nhit, nkill;
[nhit, nkill] = SWWMUtility.DoExplosion(self,3+reactiontime/2,3000+500*reactiontime,40+3*reactiontime,20,DE_COUNTENEMIES);
if ( target && special1 ) SWWMUtility.AchievementProgressInc("grenade",nkill,target.player);
}
Vector3 pvel = (FRandom[ExploS](-1,1),FRandom[ExploS](-1,1),FRandom[ExploS](-1,1)).unit()*FRandom[ExploS](1,5);
let s = Spawn("SWWMHalfSmoke",pos);
s.vel = pvel+vel*.2;
s.SetShade(Color(1,1,1)*Random[ExploS](64,224));
s.special1 = Random[ExploS](1,3);
s.scale *= 2.4;
s.alpha *= 0.1+.4*(ReactionTime/15.);
A_CountDown();
}
Wait;
}
}
Class ExplodiumMagTrail : Actor
{
Default
{
RenderStyle "Add";
+NOBLOCKMAP;
+NOGRAVITY;
+FORCEXYBILLBOARD;
+NOTELEPORT;
+NOINTERACTION;
Scale 1.1;
}
override void Tick()
{
if ( isFrozen() ) return;
if ( !CheckNoDelay() || (tics == -1) ) return;
if ( tics > 0 ) tics--;
while ( !tics )
{
if ( !SetState(CurState.NextState) )
return;
}
}
States
{
Spawn:
XEX1 ADGJMPSVY\ 1 Bright;
Stop;
}
}
Class ExplodiumMagProj : Actor
{
double pitchvel, anglevel;
Vector3 cvel;
Default
{
Obituary "$O_EXPLODIUM";
DamageType "Explodium";
Radius 2;
Height 4;
Gravity 0.5;
Speed 30;
PROJECTILE;
-NOGRAVITY;
+ROLLSPRITE;
+ROLLCENTER;
+INTERPOLATEANGLES;
+NODAMAGETHRUST;
+FORCERADIUSDMG;
+FORCEXYBILLBOARD;
+BOUNCEONFLOORS;
+BOUNCEONCEILINGS;
+BOUNCEONWALLS;
+CANBOUNCEWATER;
+DONTBOUNCEONSKY;
+USEBOUNCESTATE;
BounceFactor 0.4;
WallBounceFactor 0.4;
}
override void PostBeginPlay()
{
Super.PostBeginPlay();
pitchvel = FRandom[Junk](10,30)*RandomPick[Junk](-1,1);
anglevel = FRandom[Junk](10,30)*RandomPick[Junk](-1,1);
}
void A_BlowUp()
{
bool isplanted = (self is 'ExplodiumMagAttach');
angle = atan2(cvel.y,cvel.x);
pitch = asin(-cvel.z);
bNOGRAVITY = true;
A_SetRenderStyle(1.,STYLE_Add);
Scale *= 2.+.2*special1;
A_AlertMonsters(swwm_uncapalert?0:6000);
int nhit, nkill;
[nhit, nkill] = SWWMUtility.DoExplosion(self,20+25*special1,80000+8000*special1,90+10*special1,60,DE_EXTRAZTHRUST|DE_COUNTENEMIES);
if ( target && isplanted ) SWWMUtility.AchievementProgressInc("grenade",nkill,target.player);
A_QuakeEx(9,9,9,30,0,400+80*special1,"",QF_RELATIVE|QF_SCALEDOWN|QF_3D,falloff:300,rollintensity:2.);
A_StartSound("explodium/maghit",CHAN_VOICE,attenuation:.35);
A_StartSound("explodium/maghit",CHAN_WEAPON,attenuation:.2);
A_SprayDecal("BigRocketBlast",172);
Scale *= FRandom[ExploS](0.8,1.1);
Scale.x *= RandomPick[ExploS](-1,1);
Scale.y *= RandomPick[ExploS](-1,1);
int numpt = Random[ExploS](16,24);
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = (FRandom[ExploS](-1,1),FRandom[ExploS](-1,1),FRandom[ExploS](-1,1)).unit()*FRandom[ExploS](1,6);
let s = Spawn("SWWMSmoke",pos);
s.vel = pvel;
s.SetShade(Color(1,1,1)*Random[ExploS](64,224));
s.special1 = Random[ExploS](1,4);
s.scale *= 2.8;
s.alpha *= .4;
}
numpt = Random[ExploS](10,15);
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = (FRandom[ExploS](-1,1),FRandom[ExploS](-1,1),FRandom[ExploS](-1,1)).unit()*FRandom[ExploS](2,12);
let s = Spawn("SWWMSpark",pos);
s.vel = pvel;
}
numpt = Random[ExploS](15,25);
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = (FRandom[ExploS](-1,1),FRandom[ExploS](-1,1),FRandom[ExploS](-1,1)).unit()*FRandom[ExploS](2,24);
let s = Spawn("SWWMChip",pos);
s.vel = pvel;
}
numpt = int(Random[ExploS](2,3)+(.6*special1));
for ( int i=0; i<numpt; i++ )
{
let s = Spawn("ExplodiumMagArm",pos);
s.target = target;
s.special1 = isplanted;
}
Spawn("ExploLight2",pos);
if ( swwm_omnibust ) BusterWall.ProjectileBust(self,20+15*special1,cvel);
}
void A_CheckBounce()
{
if ( (vel.length() > 4) && (vel.unit() dot cvel > 0.) )
{
bHITOWNER = true;
A_StartSound("explodium/mag");
return;
}
ExplodeMissile();
}
States
{
Spawn:
XZW1 A 1
{
pitch += pitchvel;
angle += anglevel;
if ( vel.length() > 0. ) cvel = vel.unit();
}
Wait;
Bounce:
XZW1 A 0 A_CheckBounce();
Goto Spawn;
Death:
TNT1 A 0 A_BlowUp();
XEX1 ABCDEFGHIJKLMNOPQRSTUVWXYZ[\] 1 Bright;
Stop;
}
}
Class ExplodiumMagHitbox : Actor
{
Default
{
Radius 2;
Height 4;
+NOGRAVITY;
+DONTSPLASH;
+NOTELEPORT;
+SHOOTABLE;
+NOBLOOD;
}
override void Tick()
{
if ( !target || target.bKILLED )
{
Destroy();
return;
}
SetOrigin(target.Vec3Offset(0,0,-height*.5),false);
let bt = BlockThingsIterator.Create(self,128);
while ( bt.Next() )
{
if ( !bt.Thing || (bt.Thing == self) || !bt.Thing.bSHOOTABLE || (bt.Thing == target.target) || bt.Thing.IsFriend(target.target) || !SWWMUtility.BoxIntersect(self,bt.Thing) )
continue;
target.bKILLED = true;
target.SetStateLabel("Detonate");
Destroy();
break;
}
}
override int DamageMobj( Actor inflictor, Actor source, int damage, Name mod, int flags, double angle )
{
if ( target && !target.bKILLED )
{
target.bKILLED = true;
target.SetStateLabel("Detonate");
Destroy();
}
return 0;
}
}
Class ExplodiumMagAttach : ExplodiumMagProj
{
Line atline;
int atside;
int atpart;
int atplane;
Sector atsector;
double atz;
Vector3 normal;
Actor hitbox;
default
{
+MOVEWITHSECTOR;
+EXPLODEONWATER;
-BOUNCEONFLOORS;
-BOUNCEONCEILINGS;
-BOUNCEONWALLS;
-CANBOUNCEWATER;
-USEBOUNCESTATE;
Speed 15;
}
override int SpecialMissileHit( Actor victim )
{
if ( victim is 'ExplodiumMagHitbox' ) return 1;
return -1;
}
override void Tick()
{
Super.Tick();
if ( isFrozen() ) return;
if ( bKILLED ) return;
if ( atline ) // attempt to follow the movement of the line
{
if ( atpart == 1 )
{
if ( atline.flags&Line.ML_DONTPEGTOP ) SetOrigin(Vec2OffsetZ(0,0,atz+atline.sidedef[atside].sector.GetPlaneTexZ(1)),true);
else SetOrigin(Vec2OffsetZ(0,0,atz+atline.sidedef[!atside].sector.GetPlaneTexZ(1)),true);
}
else if ( atpart == -1 )
{
if ( atline.flags&Line.ML_DONTPEGBOTTOM ) SetOrigin(Vec2OffsetZ(0,0,atz+atline.sidedef[atside].sector.GetPlaneTexZ(0)),true);
else SetOrigin(Vec2OffsetZ(0,0,atz+atline.sidedef[!atside].sector.GetPlaneTexZ(0)),true);
}
else if ( atline.flags&Line.ML_DONTPEGBOTTOM ) SetOrigin(Vec2OffsetZ(0,0,atz+atline.sidedef[atside].sector.GetPlaneTexZ(0)),true);
else SetOrigin(Vec2OffsetZ(0,0,atz+atline.sidedef[atside].sector.GetPlaneTexZ(1)),true);
if ( (pos.z > ceilingz) || (pos.z < floorz) ) bKILLED = true;
}
else if ( atsector ) // attempt to follow the movement of the plane
{
SetOrigin(Vec2OffsetZ(0,0,atz+atsector.GetPlaneTexZ(atplane)),true);
if ( ceilingz-floorz <= 2 ) bKILLED = true;
}
if ( bKILLED ) SetStateLabel("Detonate");
}
void A_Attach()
{
F3DFloor ff;
A_NoGravity();
A_Stop();
if ( BlockingFloor )
{
// find closest 3d floor for its normal
for ( int i=0; i<BlockingFloor.Get3DFloorCount(); i++ )
{
if ( !(BlockingFloor.Get3DFloor(i).top.ZAtPoint(pos.xy) ~== floorz) ) continue;
ff = BlockingFloor.Get3DFLoor(i);
break;
}
if ( ff )
{
normal = -ff.top.Normal;
atsector = ff.model;
atplane = 1;
SWWMUtility.SetToSlopeSpecific(self,angle,ff.top,true);
}
else
{
normal = BlockingFloor.floorplane.Normal;
atsector = BlockingFloor;
atplane = 0;
SWWMUtility.SetToSlopeSpecific(self,angle,BlockingFloor.floorplane,false);
}
frame = 1; // on floor
SetOrigin((pos.x,pos.y,floorz)+normal*.75,true);
atz = pos.z-atsector.GetPlaneTexZ(atplane);
}
else if ( BlockingCeiling )
{
// find closest 3d floor for its normal
for ( int i=0; i<BlockingCeiling.Get3DFloorCount(); i++ )
{
if ( !(BlockingCeiling.Get3DFloor(i).bottom.ZAtPoint(pos.xy) ~== ceilingz) ) continue;
ff = BlockingCeiling.Get3DFloor(i);
break;
}
if ( ff )
{
normal = -ff.bottom.Normal;
atsector = ff.model;
atplane = 0;
SWWMUtility.SetToSlopeSpecific(self,angle,ff.bottom,false);
}
else
{
normal = BlockingCeiling.ceilingplane.Normal;
atsector = BlockingCeiling;
atplane = 1;
SWWMUtility.SetToSlopeSpecific(self,angle,BlockingCeiling.ceilingplane,true);
}
frame = 2; // on ceiling
SetOrigin((pos.x,pos.y,ceilingz)+normal*.75,true);
atz = pos.z-atsector.GetPlaneTexZ(atplane);
}
else if ( BlockingLine )
{
atline = BlockingLine;
normal = (-BlockingLine.delta.y,BlockingLine.delta.x,0).unit();
atside = SWWMUtility.PointOnLineSide(pos.xy,BlockingLine);
if ( !atside ) normal *= -1;
Vector3 orig = (BlockingLine.v1.p.x,BlockingLine.v1.p.y,0);
Vector3 onwall = pos-(normal dot (pos-orig))*normal;
SetOrigin(onwall+normal*.75,true);
// attempt to guess line part (upper/mid/lower)
if ( !atline.sidedef[1] ) atpart = 0; // mid
else if ( atline.sidedef[!atside].sector.ceilingplane.ZAtPoint(pos.xy) < pos.z ) atpart = 1; // upper
else if ( atline.sidedef[!atside].sector.floorplane.ZAtPoint(pos.xy) > (pos.z+height) ) atpart = -1; // lower
else
{
atpart = 0;
// check if we're touching a 3d floor line
Sector backsector = atline.sidedef[!atside].sector;
for ( int i=0; i<backsector.Get3DFloorCount(); i++ )
{
if ( backsector.Get3DFloor(i).bottom.ZAtPoint(pos.xy) > (pos.z+height) ) continue;
if ( backsector.Get3DFloor(i).top.ZAtPoint(pos.xy) < pos.z ) continue;
ff = backsector.Get3DFloor(i);
break;
}
// attach to it
if ( ff )
{
atline = ff.master;
atside = 0;
}
}
if ( atpart == 1 )
{
if ( atline.flags&Line.ML_DONTPEGTOP ) atz = pos.z-atline.sidedef[atside].sector.GetPlaneTexZ(1);
else atz = pos.z-atline.sidedef[!atside].sector.GetPlaneTexZ(1);
}
else if ( atpart == -1 )
{
if ( atline.flags&Line.ML_DONTPEGBOTTOM ) atz = pos.z-atline.sidedef[atside].sector.GetPlaneTexZ(0);
else atz = pos.z-atline.sidedef[!atside].sector.GetPlaneTexZ(0);
}
else if ( atline.flags&Line.ML_DONTPEGBOTTOM ) atz = pos.z-atline.sidedef[atside].sector.GetPlaneTexZ(0);
else atz = pos.z-atline.sidedef[atside].sector.GetPlaneTexZ(1);
angle = atan2(normal.y,normal.x)+180;
pitch = 0;
}
else
{
bKILLED = true;
SetStateLabel("Detonate");
return;
}
let b = Spawn("ExplodiumMagHitbox",pos);
b.target = self;
A_StartSound("explodium/jamitin",CHAN_BODY,CHANF_DEFAULT,.65,2.5);
}
States
{
Spawn:
XZW1 A -1;
Stop;
Death:
XZW1 A -1 A_Attach();
Stop;
Detonate:
XZW1 # 2;
TNT1 A 0
{
cvel = (cos(angle)*cos(pitch),sin(angle)*cos(pitch),-sin(pitch));
A_BlowUp();
}
XEX1 ABCDEFGHIJKLMNOPQRSTUVWXYZ[\] 1 Bright;
Stop;
}
}
Class ExploLight : PaletteLight
{
Default
{
ReactionTime 15;
}
}
Class ExploLight2 : PaletteLight
{
Default
{
ReactionTime 30;
Args 0,0,0,120;
}
}
Class ExplodiumBulletImpact : Actor
{
Default
{
Obituary "$O_EXPLODIUM";
DamageType "Explodium";
RenderStyle "Add";
Radius .1;
Height 0.;
Scale 1.2;
+NOGRAVITY;
+NOBLOCKMAP;
+NODAMAGETHRUST;
+FORCERADIUSDMG;
+FORCEXYBILLBOARD;
+NOTELEPORT;
+NOINTERACTION;
}
override void PostBeginPlay()
{
Super.PostBeginPlay();
A_AlertMonsters(swwm_uncapalert?0:3000);
SWWMUtility.DoExplosion(self,25,40000,70,40,DE_EXTRAZTHRUST);
A_QuakeEx(4,4,4,10,0,250,"",QF_RELATIVE|QF_SCALEDOWN|QF_3D,falloff:150,rollintensity:0.2);
A_StartSound("explodium/hit",CHAN_VOICE,attenuation:.6);
A_StartSound("explodium/hit",CHAN_WEAPON,attenuation:.3);
A_SprayDecal("RocketBlast",-172);
Scale *= FRandom[ExploS](0.8,1.1);
Scale.x *= RandomPick[ExploS](-1,1);
Scale.y *= RandomPick[ExploS](-1,1);
int numpt = Random[ExploS](10,20);
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = (FRandom[ExploS](-1,1),FRandom[ExploS](-1,1),FRandom[ExploS](-1,1)).unit()*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[ExploS](8,12);
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = (FRandom[ExploS](-1,1),FRandom[ExploS](-1,1),FRandom[ExploS](-1,1)).unit()*FRandom[ExploS](2,6);
let s = Spawn("SWWMSpark",pos);
s.vel = pvel;
}
numpt = Random[ExploS](6,16);
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = (FRandom[ExploS](-1,1),FRandom[ExploS](-1,1),FRandom[ExploS](-1,1)).unit()*FRandom[ExploS](2,12);
let s = Spawn("SWWMChip",pos);
s.vel = pvel;
}
Spawn("ExploLight",pos);
}
override void Tick()
{
if ( isFrozen() ) return;
if ( !CheckNoDelay() || (tics == -1) ) return;
if ( tics > 0 ) tics--;
while ( !tics )
{
if ( !SetState(CurState.NextState) )
return;
}
}
States
{
Spawn:
XEX1 ACEGIKMOQSUWY[] 1 Bright;
Stop;
}
}