Class HammerImpact : Actor { Default { Radius 0.1; Height 0; +NOGRAVITY; +NOCLIP; +DONTSPLASH; } override void PostBeginPlay() { Super.PostBeginPlay(); A_SprayDecal("ImpactMark",20); int numpt = Random[Impact](20,40); Vector3 x = (cos(angle)*cos(pitch),sin(angle)*cos(pitch),-sin(pitch)); for ( int i=0; i 0.2 ) { invoker.count = 0; A_AlertMonsters(); } A_QuakeEx(clamp(invoker.chargesize*3,0,3),clamp(invoker.chargesize*3,0,3),clamp(invoker.chargesize*3,0,3),amt+1,0,96,"",QF_RELATIVE,rollIntensity:clamp(invoker.chargesize*0.3,0,0.3)); } action void A_FireBlast() { Weapon weap = Weapon(invoker); if ( !weap ) return; A_PlaySound("impact/release",CHAN_WEAPON); invoker.FireEffect(); A_AlertMonsters(); Vector3 x, y, z; [x, y, z] = Matrix4.GetAxes(pitch,angle,roll); Vector3 origin = (pos.x,pos.y,player.viewz)+10.0*x+3.0*y-4.0*z; double realcharge = min(1.5,invoker.chargesize); FLineTraceData d; LineTrace(angle,80,BulletSlope(),TRF_ABSPOSITION,origin.z,origin.x,origin.y,d); if ( d.HitType == TRACE_HitActor ) { int dmg = Random[Impact](60,80)*realcharge; dmg = d.HitActor.DamageMobj(invoker,self,dmg,'impact'); d.HitActor.vel = x*(1000/d.HitActor.mass)*realcharge; if ( d.HitActor.bNOBLOOD ) { let p = Spawn("HammerImpact",d.HitLocation-d.HitDir*4); p.angle = atan2(d.HitDir.y,d.HitDir.x); p.pitch = asin(-d.HitDir.z); } else { d.HitActor.TraceBleed(dmg,invoker); d.HitActor.SpawnBlood(d.HitLocation,atan2(d.HitDir.y,d.HitDir.x)+180,dmg); } } else if ( d.HitType != TRACE_HitNone ) { realcharge = max(1.0,realcharge); int dmg = Random[Impact](16,24)*realcharge; // It's a flat damage of 36 on UT, but I think it's more fair for it to scale dmg = DamageMobj(invoker,self,dmg,'impact'); TraceBleed(dmg,invoker); vel -= x*(1200/mass)*realcharge; let p = Spawn("HammerImpact",d.HitLocation-d.HitDir*4); p.angle = atan2(d.HitDir.y,d.HitDir.x); p.pitch = asin(-d.HitDir.z); if ( d.HitType == TRACE_HitWall ) d.HitLine.RemoteActivate(self,d.LineSide,SPAC_Impact,d.HitLocation-d.HitDir*4); } A_QuakeEx(realcharge*6,realcharge*6,realcharge*6,16,0,1,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:realcharge*0.2); realcharge = max(1.0,realcharge); int numpt = Random[Impact](5,10); for ( int i=0; i 550) || (rdir dot x < 0.9) ) continue; m.speed = m.vel.length(); if ( m.vel dot y > 0 ) m.vel = m.speed*(m.vel+(750-rdist)*y*0.01).unit(); else m.vel = m.speed*(m.vel-(750-rdist)*y*0.01).unit(); if ( m.target == self ) continue; if ( m.bSEEKERMISSILE ) m.tracer = m.target; m.target = self; } int numpt = Random[Impact](5,10); for ( int i=0; i 1) && (d.HitType == TRACE_HitActor) ) { A_ClearRefire(); return; } A_Refire(flash); } override void DetachFromOwner() { if ( Owner ) Owner.A_StopSound(CHAN_WEAPON); Super.DetachFromOwner(); } Default { Tag "Impact Hammer"; Obituary "%o was smeared by %k's piston."; Inventory.PickupMessage "You got the Impact Hammer."; Weapon.UpSound "impact/select"; Weapon.SlotNumber 1; Weapon.SelectionOrder 9; +WEAPON.MELEEWEAPON; } States { Spawn: IMPP A -1; Stop; IMPP B -1; Stop; Select: IMPS A 1 A_Raise(int.max); Wait; Ready: IMPS ABCDEFGHIJKLMNOPQ 1 A_WeaponReady(WRF_NOFIRE); Idle: IMPI A 1 A_WeaponReady(); Wait; Fire: IMPL A 0 { A_ResetCharge(); A_PlaySound("impact/pull",CHAN_WEAPON); } IMPL A 5 A_ChargeUp(5); IMPL B 0 A_ImpactRefire(1); Goto Release; IMPL B 5 A_ChargeUp(5); IMPL C 0 A_ImpactRefire(1); Goto Release; IMPL C 5 A_ChargeUp(5); IMPL D 0 A_ImpactRefire(1); Goto Release; IMPL D 5 A_ChargeUp(5); IMPL E 0 A_ImpactRefire(1); Goto Release; IMPL E 5 A_ChargeUp(5); IMPL E 0 A_ImpactRefire(1); Goto Release; IMPL E 0 A_PlaySound("impact/loop",CHAN_WEAPON,looping:true); Hold: IMPR A 1 A_ChargeUp(); IMPR B 0 A_ImpactRefire(1); Goto Release; IMPR B 1 A_ChargeUp(); IMPR C 0 A_ImpactRefire(1); Goto Release; IMPR C 1 A_ChargeUp(); IMPR D 0 A_ImpactRefire(1); Goto Release; IMPR D 1 A_ChargeUp(); IMPR E 0 A_ImpactRefire(1); Goto Release; IMPR E 1 A_ChargeUp(); IMPR F 0 A_ImpactRefire(1); Goto Release; IMPR F 1 A_ChargeUp(); IMPR G 0 A_ImpactRefire(1); Goto Release; IMPR G 1 A_ChargeUp(); IMPR H 0 A_ImpactRefire(1); Goto Release; IMPR H 1 A_ChargeUp(); IMPR I 0 A_ImpactRefire(1); Goto Release; IMPR I 1 A_ChargeUp(); IMPR J 0 A_ImpactRefire(1); Goto Release; IMPR J 1 A_ChargeUp(); IMPR A 0 A_ImpactRefire("Hold"); Goto Release; Release: IMPF A 0 A_FireBlast(); IMPF AABCCDEEFGGHIIJKKLMMNOOP 1; Goto Idle; AltFire: IMPF A 0 A_FireAltBlast(); IMPF ABCDEFGHIJKLMNOP 1; Goto Idle; Deselect: IMPD A 0 A_StopSound(CHAN_WEAPON); IMPD ABCDE 2; IMPD E 1 A_Lower(int.max); Wait; } }