- Try to get rid of all implicit casts from string to name, color or class. - Use FindClass where needed. - Used a map in a case where a dictionary was unneeded. - Use new bounce flags where needed. - Replace Legacy of Rust weapons/ammo.
464 lines
11 KiB
Text
464 lines
11 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 = SWWMAnimSprite.SpawnAt('SWWMHalfSmoke',pos);
|
|
s.vel = pvel+vel*.2;
|
|
s.scolor = Color(4,2,1)*Random[ExploS](48,63);
|
|
s.framestep = Random[ExploS](1,3);
|
|
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, detact;
|
|
Actor seektarget;
|
|
Vector3 InitialDir, Acceleration;
|
|
|
|
Default
|
|
{
|
|
Obituary "$O_HELLBLAZER";
|
|
DamageType 'Sydon';
|
|
Radius 2;
|
|
Height 4;
|
|
Speed 50;
|
|
PROJECTILE;
|
|
+EXPLODEONWATER;
|
|
+FORCERADIUSDMG;
|
|
+NODAMAGETHRUST;
|
|
+HITTRACER;
|
|
+SKYEXPLODE;
|
|
}
|
|
|
|
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 = SWWMAnimSprite.SpawnAt('SWWMHalfSmoke',level.Vec3Offset(pos,traildir*3));
|
|
s.scolor = smokecol*Random[Hellblazer](48,63);
|
|
s.scale *= FRandom[Hellblazer](.8,1.2);
|
|
s.framestep = Random[Hellblazer](1,3);
|
|
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.;
|
|
}
|
|
// don't auto-detonate if we're too close to our shooter
|
|
// ensures player doesn't eat up the full brunt of the blast
|
|
if ( (deto > 1) && (!target || !SWWMUtility.SphereIntersect(target,pos,150)) )
|
|
{
|
|
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,256);
|
|
foreach ( t,p,v:bt )
|
|
{
|
|
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;
|
|
}
|
|
bt.Destroy();
|
|
}
|
|
|
|
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,AMF_EMITFROMTARGET);
|
|
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,3000-special1*200,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;
|
|
LineTrace(ang,FRandom[Hellblazer](10,20)+10*special1*xscale,pt,TRF_THRUACTORS,data:d);
|
|
Vector3 HitNormal = SWWMUtility.GetLineTraceHitNormal(d);
|
|
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;
|
|
+CANBOUNCEWATER;
|
|
+KEEPBOUNCEANGLE;
|
|
+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 = SWWMUtility.GetActorHitNormal(self);
|
|
// 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;
|
|
}
|
|
}
|