swwmgz_m/zscript/weapons/swwm_blazeit_fx.zsc

515 lines
12 KiB
Text

// Hellblazer projectiles and effects
Class HellblazerExplLight : PaletteLight
{
Default
{
Tag "HellExpl";
Args 0,0,0,200;
ReactionTime 25;
}
}
Class HellblazerSubExpl : SWWMNonInteractiveActor
{
Default
{
RenderStyle "Add";
Scale 2.2;
Alpha .75;
+FORCEXYBILLBOARD;
+ROLLSPRITE;
+ROLLCENTER;
}
override void PostBeginPlay()
{
Super.PostBeginPlay();
roll = FRandom[ExploS](0,360);
scale.x *= RandomPick[ExploS](-1,1);
scale.y *= RandomPick[ExploS](-1,1);
}
States
{
Spawn:
XEX0 ABCDEFGHIJKLMNOPQRS 1 Bright;
Stop;
}
}
Class HellblazerRing : SWWMNonInteractiveActor
{
Default
{
RenderStyle "Add";
Scale 2.;
+FORCEXYBILLBOARD;
}
States
{
Spawn:
XRG3 ACEGIKMOQSUW 1 Bright A_SetScale(scale.x*1.15);
Stop;
}
}
Class HellblazerArmTrail : SWWMNonInteractiveActor
{
Default
{
RenderStyle "Add";
+FORCEXYBILLBOARD;
Scale 2.5;
}
States
{
Spawn:
XEX0 ACEGIKMOQS 1 Bright;
Stop;
}
}
Class HellblazerArm : Actor
{
Default
{
Obituary "$O_HELLBLAZER";
DamageType 'Fire';
PROJECTILE;
+THRUACTORS;
+BOUNCEONWALLS;
+BOUNCEONFLOORS;
+BOUNCEONCEILINGS;
+CANBOUNCEWATER;
+NODAMAGETHRUST;
+FORCERADIUSDMG;
-NOGRAVITY;
+NOFRICTION;
Gravity 0.35;
BounceFactor 1.0;
Radius 4;
Height 4;
}
override void PostBeginPlay()
{
Super.PostBeginPlay();
reactiontime = Random[ExploS](6,8);
double ang, pt;
ang = FRandom[ExploS](0,360);
pt = FRandom[ExploS](-90,90);
vel = SWWMUtility.Vec3FromAngles(ang,pt)*FRandom[ExploS](30.,40.);
}
States
{
Spawn:
TNT1 A 1
{
Spawn("HellblazerArmTrail",pos);
SWWMUtility.DoExplosion(self,6+reactiontime/2,3000+500*reactiontime,80+10*reactiontime);
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*.2;
s.SetShade(Color(4,2,1)*Random[ExploS](48,63));
s.special1 = Random[ExploS](0,2);
s.scale *= 3.;
s.alpha *= 0.1+.4*(ReactionTime/8.);
A_CountDown();
}
Wait;
}
}
Class HellblazerTrail : SWWMNonInteractiveActor
{
Default
{
RenderStyle "Add";
Scale .2;
Alpha .3;
+FORCEXYBILLBOARD;
}
override void PostBeginPlay()
{
Super.PostBeginPlay();
SetState(FindState("Spawn")+Random[ExploS](0,7));
}
States
{
Spawn:
JFLR ABCDEFGH 1 Bright
{
A_FadeOut(.06);
A_SetScale(scale.x*.95);
if ( waterlevel > 0 )
{
let b = Spawn("SWWMBubble",pos);
b.vel = vel;
b.scale *= scale.x;
Destroy();
}
}
Loop;
}
}
Class HellblazerFlare : SWWMNonInteractiveActor
{
Default
{
RenderStyle "Add";
+FORCEXYBILLBOARD;
}
override void Tick()
{
if ( !master || !master.bMISSILE )
{
Destroy();
return;
}
Vector3 traildir = -SWWMUtility.Vec3FromAngles(master.angle,master.pitch);
SetOrigin(level.Vec3Offset(master.pos,traildir*3),true);
}
States
{
Spawn:
HFLR A -1 Bright;
Stop;
}
}
// rockets
Class HellblazerMissile : Actor
{
Mixin SWWMMissileFix;
int deto;
Actor seektarget;
Vector3 InitialDir, Acceleration;
Default
{
Obituary "$O_HELLBLAZER";
DamageType 'Explosive';
Radius 2;
Height 4;
Speed 50;
PROJECTILE;
+EXPLODEONWATER;
+FORCERADIUSDMG;
+NODAMAGETHRUST;
+HITTRACER;
}
override void PostBeginPlay()
{
Super.PostBeginPlay();
if ( bNOGRAVITY )
{
A_StartSound("hellblazer/fly",CHAN_BODY,CHANF_LOOP,1.,2.);
let t = Spawn("HellblazerFlare",pos);
t.master = self;
}
}
void A_BlazerTick( Color smokecol )
{
Vector3 traildir = -SWWMUtility.Vec3FromAngles(angle,pitch);
for ( int i=0; i<3; i++ )
{
let s = Spawn("SWWMHalfSmoke",level.Vec3Offset(pos,traildir*3));
s.SetShade(smokecol*Random[Hellblazer](48,63));
s.scale *= FRandom[Hellblazer](.8,1.2);
s.special1 = Random[Hellblazer](0,2);
s.alpha *= .5;
s.vel = .3*vel + (traildir+SWWMUtility.Vec3FromAngles(FRandom[Hellblazer](0,360),FRandom[Hellblazer](-90,90))*.4).unit()*FRandom[Hellblazer](1.,2.);
}
if ( bNOGRAVITY )
{
for ( double i=0.; i<vel.length(); i+= 5. )
{
let t = Spawn("HellblazerTrail",level.Vec3Offset(pos,-vel.unit()*i+traildir*3));
t.vel = traildir*4.;
}
if ( InitialDir.length() < double.epsilon ) InitialDir = vel.unit();
vel += Acceleration/GameTicRate;
Vector3 dir = vel.unit();
if ( vel.length() > 50. ) vel = dir*50.;
}
if ( deto > 1 )
{
ExplodeMissile();
return;
}
if ( seektarget )
{
// seek tracer
if ( SWWMUtility.SphereIntersect(seektarget,level.Vec3Offset(pos,vel),bNOGRAVITY?50:90) )
{
deto++;
tracer = seektarget;
return;
}
if ( bNOGRAVITY )
{
Vector3 SeekingDir = level.Vec3Diff(pos,seektarget.Vec3Offset(0,0,seektarget.height/2)).unit();
if ( SeekingDir dot InitialDir > -1 )
{
double MagnitudeVel = Vel.length();
SeekingDir = (SeekingDir*.25*MagnitudeVel+Vel).unit();
Vel = MagnitudeVel*SeekingDir;
Acceleration = 25*SeekingDir;
}
}
return;
}
// proximity check
let bt = BlockThingsIterator.Create(self,200);
while ( bt.Next() )
{
let t = bt.Thing;
if ( !t || !t.bSHOOTABLE || (!t.bISMONSTER && !(t is 'BossBrain') && !t.player) || (t.Health <= 0) || (target && t.IsFriend(target)) || !SWWMUtility.SphereIntersect(t,level.Vec3Offset(pos,vel),bNOGRAVITY?50:90) || !CheckSight(t,SF_IGNOREVISIBILITY|SF_IGNOREWATERBOUNDARY) ) continue;
deto++;
tracer = t;
break;
}
}
void A_BlazerMissileExplode()
{
bForceXYBillboard = true;
bRollSprite = false;
A_SetRenderStyle(1.0,STYLE_Add);
A_SprayDecal("BigRocketBlast",50);
A_SetScale(4.5);
SWWMUtility.DoExplosion(self,200,320000,150,100);
A_NoGravity();
A_QuakeEx(5,5,5,15,0,1500,"",QF_RELATIVE|QF_SCALEDOWN|QF_3D,falloff:500,rollIntensity:.8);
A_StopSound(CHAN_BODY);
A_StartSound("hellblazer/hit",CHAN_WEAPON,attenuation:.8);
A_StartSound("hellblazer/hit",CHAN_VOICE,attenuation:.5);
A_AlertMonsters(swwm_uncapalert?0:2500);
Spawn("HellblazerExplLight",pos);
int numpt = Random[Hellblazer](12,24);
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = SWWMUtility.Vec3FromAngles(FRandom[Hellblazer](0,360),FRandom[Hellblazer](-90,90))*FRandom[Hellblazer](2,8);
let s = Spawn("SWWMSmoke",pos);
s.vel = pvel;
s.SetShade(Color(4,2,1)*Random[Hellblazer](48,63));
s.special1 = Random[Hellblazer](1,4);
s.scale *= 2.8;
s.alpha *= .4;
}
numpt = Random[Hellblazer](8,12);
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = SWWMUtility.Vec3FromAngles(FRandom[Hellblazer](0,360),FRandom[Hellblazer](-90,90))*FRandom[Hellblazer](4,12);
let s = Spawn("SWWMSpark",pos);
s.vel = pvel;
}
numpt = Random[Hellblazer](12,16);
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = SWWMUtility.Vec3FromAngles(FRandom[Hellblazer](0,360),FRandom[Hellblazer](-90,90))*FRandom[Hellblazer](10,20);
let s = Spawn("SWWMChip",pos);
s.vel = pvel;
s.scale *= FRandom[Hellblazer](0.9,1.8);
}
Spawn("HellblazerRing",pos);
if ( swwm_omnibust ) BusterWall.ProjectileBust(self,320,SWWMUtility.Vec3FromAngles(angle,pitch));
}
void A_SubExpl( double xscale = 1. )
{
if ( special1 < 15 ) SWWMUtility.DoExplosion(self,60-special1*4,30000-special1*2000,100+special1*10,damagetype:'Fire');
special1++;
if ( (special1 <= 8) && !(special1%2) )
{
int numpt = Random[Hellblazer](0,8-special1);
double ang, pt;
for ( int i=0; i<numpt; i++ )
{
ang = FRandom[Hellblazer](0,360);
pt = FRandom[Hellblazer](-90,90);
FLineTraceData d;
Vector3 HitNormal;
LineTrace(ang,FRandom[Hellblazer](10,20)+10*special1*xscale,pt,TRF_THRUACTORS,data:d);
hitnormal = -d.HitDir;
if ( d.HitType == TRACE_HitFloor )
{
if ( d.Hit3DFloor ) hitnormal = -d.Hit3DFloor.top.Normal;
else hitnormal = d.HitSector.floorplane.Normal;
}
else if ( d.HitType == TRACE_HitCeiling )
{
if ( d.Hit3DFloor ) hitnormal = -d.Hit3DFloor.bottom.Normal;
else hitnormal = d.HitSector.ceilingplane.Normal;
}
else if ( d.HitType == TRACE_HitWall )
{
hitnormal = (-d.HitLine.delta.y,d.HitLine.delta.x,0).unit();
if ( !d.LineSide ) hitnormal *= -1;
}
let p = Spawn("HellblazerSubExpl",d.HitLocation+hitnormal*4);
p.angle = atan2(hitnormal.y,hitnormal.x);
p.pitch = asin(-hitnormal.z);
p.target = target;
p.scale *= xscale*(2-special1*.1);
p.alpha *= 1-special1*.1;
}
}
special2++;
if ( (special2 <= 6) && !(special2%3) )
{
int numpt = 5-special2/2;
for ( int i=0; i<numpt; i++ )
{
double ang = FRandom[Hellblazer](0,360);
double pt = FRandom[Hellblazer](-90,90);
let c = Spawn("HellblazerArm",pos);
c.angle = ang;
c.pitch = pt;
c.target = target;
}
}
}
States
{
Spawn:
XZW1 A 1 A_BlazerTick(Color(4,3,2));
Wait;
Death:
TNT1 A 0 A_BlazerMissileExplode();
HEXP ABCDEFGHIJKLMNOPQR 1 Bright A_SubExpl();
Stop;
}
}
// grenades
Class HellblazerMissile2 : HellblazerMissile
{
double rollvel, anglevel, pitchvel;
Vector3 oldvel;
Default
{
BounceFactor 1.;
WallBounceFactor 1.;
Gravity .35;
ReactionTime 85;
-NOGRAVITY;
-EXPLODEONWATER;
+USEBOUNCESTATE;
+BOUNCEONWALLS;
+BOUNCEONFLOORS;
+BOUNCEONCEILINGS;
+ALLOWBOUNCEONACTORS;
+DONTBOUNCEONSHOOTABLES;
+DONTBOUNCEONSKY;
+CANBOUNCEWATER;
+INTERPOLATEANGLES;
+ROLLSPRITE;
+ROLLCENTER;
}
override void PostBeginPlay()
{
Super.PostBeginPlay();
rollvel = FRandom[Hellblazer](-4,4);
anglevel = FRandom[Hellblazer](-4,4);
pitchvel = FRandom[Hellblazer](-4,4);
oldvel = vel;
}
override void Tick()
{
oldvel = vel;
Super.Tick();
if ( isFrozen() || (freezetics > 0) || !InStateSequence(CurState,FindState("Spawn")) ) return;
roll += rollvel;
angle += anglevel;
pitch += pitchvel;
ReactionTime--;
if ( ReactionTime <= 0 ) ExplodeMissile();
}
virtual void A_HandleBounce()
{
Vector3 HitNormal = -vel.unit();
F3DFloor ff;
if ( BlockingFloor )
{
// find closest 3d floor for its normal
for ( int i=0; i<BlockingFloor.Get3DFloorCount(); i++ )
{
if ( !(BlockingFloor.Get3DFloor(i).flags&F3DFloor.FF_SOLID) ) continue;
if ( !(BlockingFloor.Get3DFloor(i).top.ZAtPoint(pos.xy) ~== floorz) ) continue;
ff = BlockingFloor.Get3DFloor(i);
break;
}
if ( ff ) HitNormal = -ff.top.Normal;
else HitNormal = BlockingFloor.floorplane.Normal;
}
else if ( BlockingCeiling )
{
// find closest 3d floor for its normal
for ( int i=0; i<BlockingCeiling.Get3DFloorCount(); i++ )
{
if ( !(BlockingCeiling.Get3DFloor(i).flags&F3DFloor.FF_SOLID) ) continue;
if ( !(BlockingCeiling.Get3DFloor(i).bottom.ZAtPoint(pos.xy) ~== ceilingz) ) continue;
ff = BlockingCeiling.Get3DFloor(i);
break;
}
if ( ff ) HitNormal = -ff.bottom.Normal;
else HitNormal = BlockingCeiling.ceilingplane.Normal;
}
else if ( BlockingLine )
{
HitNormal = (-BlockingLine.delta.y,BlockingLine.delta.x,0).unit();
if ( !SWWMUtility.PointOnLineSide(pos.xy,BlockingLine) )
HitNormal *= -1;
}
else if ( BlockingMobj )
{
Vector3 diff = level.Vec3Diff(BlockingMobj.Vec3Offset(0,0,BlockingMobj.Height/2),pos);
HitNormal = diff.unit();
}
// undo the bounce, we need to hook in our own
vel = oldvel;
// re-do the bounce with our formula
Vector3 RealHitNormal = HitNormal;
HitNormal = (HitNormal+SWWMUtility.Vec3FromAngles(FRandom[Hellblazer](0,360),FRandom[Hellblazer](-90,90))*.1).unit();
if ( (HitNormal dot RealHitNormal) < 0 ) HitNormal *= -.5;
vel = FRandom[Hellblazer](.8,.9)*((vel dot HitNormal)*HitNormal*(FRandom[Hellblazer](-2.,-1.6))+vel);
if ( vel.z > 10 ) vel.z = 0.5*(10+vel.z);
bHITOWNER = true;
if ( vel.length() < 4. )
{
ClearBounce();
ExplodeMissile();
return;
}
A_StartSound("hellblazer/bounce",CHAN_ITEM);
rollvel = FRandom[Hellblazer](-16,16);
anglevel = FRandom[Hellblazer](-16,16);
pitchvel = FRandom[Hellblazer](-16,16);
// steer towards seek target
if ( seektarget )
{
Vector3 dirto = level.Vec3Diff(pos,seektarget.Vec3Offset(0,0,seektarget.Height/2));
double distto = dirto.length();
if ( distto <= 0. ) return;
dirto /= distto;
dirto.z += .1;
double spd = vel.length();
if ( spd <= 0. ) return;
vel /= spd;
vel = (vel*.3+dirto*.7)*spd;
}
}
States
{
Bounce:
XZW1 A 0 A_HandleBounce();
Goto Spawn;
}
}