// Base casing classes Class SWWMCasing : Actor abstract { Mixin SWWMMissileFix; SWWMCasing prevcasing, nextcasing; bool killme; int numbounces; double pitchvel, anglevel; double heat; Default { Radius 2; Height 4; +NOBLOCKMAP; +MISSILE; +DROPOFF; +MOVEWITHSECTOR; +THRUACTORS; +USEBOUNCESTATE; +INTERPOLATEANGLES; +NOTELEPORT; +ROLLSPRITE; +ROLLCENTER; +SYNCHRONIZED; +CANBOUNCEWATER; Mass 1; Gravity 0.35; BounceType "Hexen"; WallBounceFactor 0.65; BounceFactor 0.65; BounceSound "explodium/casing"; FloatBobPhase 0; } override void PostBeginPlay() { Super.PostBeginPlay(); pitchvel = FRandom[Junk](10,30)*RandomPick[Junk](-1,1); anglevel = FRandom[Junk](10,30)*RandomPick[Junk](-1,1); heat = 1.0; SWWMHandler.QueueCasing(self); } override void OnDestroy() { SWWMHandler.DeQueueCasing(self); Super.OnDestroy(); } override void Tick() { Super.Tick(); if ( isFrozen() || (freezetics > 0) ) return; if ( killme ) A_FadeOut(.01); if ( waterlevel > 0 ) { anglevel *= .98; pitchvel *= .98; } if ( heat <= 0 ) return; let s = Spawn("SWWMSmallSmoke",pos); s.alpha *= heat; heat -= 0.05; } States { Spawn: XZW1 A 1 { angle += anglevel; pitch += pitchvel; } Loop; Bounce: XZW1 A 0 { pitchvel = FRandom[Junk](10,30)*RandomPick[Junk](-1,1); anglevel = FRandom[Junk](10,30)*RandomPick[Junk](-1,1); vel = (vel.unit()+SWWMUtility.Vec3FromAngles(FRandom[Junk](0,360),FRandom[Junk](-90,90))*.2).unit()*vel.length(); if ( numbounces && ((numbounces > 3) || (Random[Junk](1,20) < 17) || (vel.z > -1.4)) ) { ClearBounce(); ExplodeMissile(); } numbounces++; } Goto Spawn; Death: XZW1 B -1 { bINTERPOLATEANGLES = false; pitch = roll = 0; angle = FRandom[Junk](0,360); // disappear if we fell into a terrain with floor clip if ( GetFloorTerrain().footclip > 0 ) Destroy(); } Stop; } } Class SWWMBulletImpact : SWWMNonInteractiveActor { Default { RenderStyle "Add"; Scale 0.25; } override void PostBeginPlay() { Super.PostBeginPlay(); A_SprayDecal("Pock",-20); int numpt = int(Random[Junk](5,10)*scale.x*4); Vector3 x = SWWMUtility.Vec3FromAngles(angle,pitch); for ( int i=0; i 0) ) return; if ( !target ) { Destroy(); return; } if ( target.player ) { Vector3 x, y, z, origin; [x, y, z] = swwm_CoordUtil.GetAxes(target.pitch,target.angle,target.roll); origin = level.Vec3Offset(target.Vec2OffsetZ(0,0,target.player.viewz),x*12); SetOrigin(origin,true); } else SetOrigin(target.pos,true); if ( cnt++ > 2 ) Destroy(); } } Class PunchImpact : SWWMNonInteractiveActor { Default { Tag "WallCrack"; } override void PostBeginPlay() { Super.PostBeginPlay(); A_QuakeEx(2,2,2,12,0,200,"",QF_RELATIVE|QF_SCALEDOWN|QF_3D,falloff:100,rollIntensity:.3); A_StartSound("demolitionist/punch",CHAN_VOICE,CHANF_DEFAULT,bAMBUSH?.6:1.); A_SprayDecal(GetTag(),-20); int numpt = Random[Ponch](5,10); if ( bAMBUSH ) numpt /= 3; Vector3 x = SWWMUtility.Vec3FromAngles(angle,pitch); for ( int i=0; i