Class StingerAmmo : Ammo { Default { Tag "$T_STINGERAMMO"; Inventory.Icon "I_Stingr"; Inventory.PickupMessage ""; Inventory.Amount 5; Inventory.MaxAmount 200; Ammo.BackpackAmount 20; Ammo.BackpackMaxAmount 400; Ammo.DropAmount 2; } override String PickupMessage() { return String.Format("%s%d%s",StringTable.Localize("$I_STINGERAMMOL"),Amount,StringTable.Localize("$I_STINGERAMMOR")); } States { Spawn: SAMO A -1; Stop; } } Class StingerAmmo2 : StingerAmmo { Default { Tag "$T_STINGERAMMO2"; Inventory.Amount 40; Ammo.DropAmount 15; } States { Spawn: SAMO B -1; Stop; } } Class StingerBurstLight : PaletteLight { Default { Tag "Blue4"; Args 0,0,0,30; ReactionTime 12; } } Class StingerChunk : Actor { int deadtimer; double rollvel, anglevel, pitchvel; Default { Radius 2; Height 2; +NOBLOCKMAP; +MISSILE; +MOVEWITHSECTOR; +THRUACTORS; +NOTELEPORT; +DONTSPLASH; +INTERPOLATEANGLES; BounceType "Doom"; BounceFactor 0.4; Gravity 0.35; } override void PostBeginPlay() { Super.PostBeginPlay(); deadtimer = 0; anglevel = FRandom[Junk](10,30)*RandomPick[Junk](-1,1); pitchvel = FRandom[Junk](10,30)*RandomPick[Junk](-1,1); rollvel = FRandom[Junk](10,30)*RandomPick[Junk](-1,1); frame = Random[Junk](0,8); scale *= Frandom[Junk](0.4,0.8); } override void Tick() { Super.Tick(); if ( isFrozen() ) return; if ( InStateSequence(CurState,ResolveState("Death")) ) { deadtimer++; if ( deadtimer > 60 ) A_FadeOut(0.05); return; } } States { Spawn: CHIP # 1 { angle += anglevel; pitch += pitchvel; roll += rollvel; } Loop; Bounce: CHIP # 0 { anglevel = FRandom[Junk](10,30)*RandomPick[Junk](-1,1); pitchvel = FRandom[Junk](10,30)*RandomPick[Junk](-1,1); rollvel = FRandom[Junk](10,30)*RandomPick[Junk](-1,1); } Goto Spawn; Death: CHIP # -1; Stop; Dummy: CHIP ABCDEFGHI -1; Stop; } } Class ViewStingerChunk : StingerChunk { Vector3 ofs, vvel; Default { +NOCLIP; +NOGRAVITY; -MISSILE; BounceType "None"; } override void Tick() { Actor.Tick(); if ( !target || !target.player ) { Destroy(); return; } Vector3 x, y, z; [x, y, z] = dt_CoordUtil.GetAxes(target.pitch,target.angle,target.roll); Vector3 origin = x*ofs.x+y*ofs.y+z*ofs.z+(0,0,target.player.viewz); SetOrigin(target.Vec2OffsetZ(origin.x,origin.y,origin.z),true); bInvisible = (players[consoleplayer].camera != target); if ( isFrozen() ) return; ofs += vvel; scale *= 0.75; if ( scale.x <= 0.01 ) Destroy(); } } Class TarydiumExLight : PaletteLight { Default { Tag "Blue2"; Args 0,0,0,60; ReactionTime 30; } } Class TarydiumExplosion : Actor { Default { RenderStyle "Add"; +NOGRAVITY; +NOBLOCKMAP; +FORCEXYBILLBOARD; +FORCERADIUSDMG; +NODAMAGETHRUST; DamageType 'TarydiumCharge'; Obituary "$O_STINGERX"; } override void PostBeginPlay() { Super.PostBeginPlay(); A_Explode(special1,int(90*scale.x)); UTMainHandler.DoBlast(self,90*scale.x,90000); A_PlaySound("flare/explode"); let l = Spawn("TarydiumExLight",pos); l.args[3] = int(60*scale.x); scale.x *= RandomPick[Stinger](-1,1); scale.y *= RandomPick[Stinger](-1,1); double ang, pt; int numpt = Random[Stinger](10,15)*min(3,special1/60); for ( int i=0; i 100 ) { amount += 30; BlowUp(); } } void BlowUp() { reentrant = true; let b = victim.Spawn("TarydiumExplosion",victim.Vec3Offset(0,0,victim.default.height/2)); b.target = instigator; b.special1 = amount; b.scale *= 1.+min(1.5,amount*0.02); Destroy(); } override void Tick() { if ( !sting_stinger ) { Destroy(); return; } if ( !victim || (victim.Health <= 0) ) { BlowUp(); return; } if ( victim.pos.z > victim.floorz ) wasonair = true; else { if ( wasonair && (oldvel.z < -20) ) { Amount += min(int(-oldvel.z),100); BlowUp(); return; } wasonair = false; } oldvel = victim.vel; if ( !(level.maptime%20) ) { amount--; UpdateEffect(); if ( amount <= 0 ) { Destroy(); return; } } if ( level.maptime%3 ) return; int numpt = clamp(int(Random[Stinger](1,3)*amount*0.02),1,8); for ( int i=0; ivictim.floorz); t.UpdateEffect(); } } Class StingerProjectile : Actor { Vector3 oldvel; Default { Obituary "$O_STINGER"; DamageType 'Stinger'; DamageFunction Random[Stinger](15,25); Speed 40; Radius 2; Height 2; PROJECTILE; +SKYEXPLODE; } override void PostBeginPlay() { Super.PostBeginPlay(); if ( sting_stingerb ) { // set bounce stuff bBOUNCEONWALLS = true; bBOUNCEONFLOORS = true; bBOUNCEONCEILINGS = true; bALLOWBOUNCEONACTORS = true; bCANBOUNCEWATER = true; bUSEBOUNCESTATE = true; BounceCount = 4; BounceFactor = 1.; WallBounceFactor = 1.; } } override void Tick() { oldvel = vel; Super.Tick(); } void A_HandleBounce() { // cancel bounce based on "incidence" if ( vel dot oldvel < 0.87 ) { ClearBounce(); ExplodeMissile(); return; } if ( !Random[Stinger](0,2) ) A_PlaySound("stinger/hit2",CHAN_BODY,0.5,pitch:FRandom[Stinger](0.5,1.5)); else A_PlaySound("stinger/hit",CHAN_BODY,0.6); A_SprayDecal("WallCrack",-20); A_AlertMonsters(); let l = Spawn("StingerBurstLight",pos); l.Args[3] /= 2; double ang, pt; int numpt = Random[Stinger](1,3); for ( int i=0; i