// 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 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 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 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; } }