// Deep Impact projectiles and effects Class AirBullet : FastProjectile { int tcnt; Actor lasthit; Default { Obituary "$O_DEEPIMPACT"; Radius 2; Height 4; DamageFunction 50; DamageType 'AirRip'; Speed 400; PROJECTILE; +FORCERADIUSDMG; +NODAMAGETHRUST; +RIPPER; +NOFRICTION; } override void PostBeginPlay() { A_StartSound("deepimpact/bullet",CHAN_BODY,CHANF_LOOP,1.,1.5); } override int DoSpecialDamage( Actor target, int damage, Name damagetype ) { if ( target.bBOSS || target.FindInventory("BossMarker") ) damage = int(damage*.4); if ( !bAMBUSH ) { if ( target == lasthit ) return 0; lasthit = target; } Vector3 dirto = level.Vec3Offset(pos,target.Vec3Offset(0,0,target.Height/2.)); if ( vel.length() <= double.epsilon ) return damage; if ( dirto.length() <= double.epsilon ) dirto = vel; dirto /= dirto.length(); SWWMUtility.DoKnockback(target,vel.unit()*.6+dirto*.4,80000); if ( !target.player ) target.bBLASTED = true; return damage; } override void Effect() { let r = Spawn("AirBulletRing",pos); r.angle = angle; r.pitch = pitch; r.roll = FRandom[Impact](0,360); r.scale *= .3; r.alpha *= .6; int numpt = Random[ExploS](2,4); for ( int i=0; i target.floorz) && target.TestMobjZ() ) mm *= 1.6; SWWMUtility.DoKnockback(target,dir,mm); } SWWMUtility.DoExplosion(self,20,80000,200,80,DE_NONEXPLOSIVE,ignoreme:target); A_QuakeEx(6,6,6,20,0,250,"",QF_RELATIVE|QF_SCALEDOWN|QF_3D,rollIntensity:1.); A_StartSound("deepimpact/bullethit",CHAN_VOICE,CHANF_DEFAULT,1.,.3); A_SprayDecal("ImpactMark"); Spawn("AirBulletLight",pos); int numpt = Random[ExploS](10,20); for ( int i=0; i