diff --git a/src/playsim/p_local.h b/src/playsim/p_local.h index 0c7bb1bc72..2a031b6895 100644 --- a/src/playsim/p_local.h +++ b/src/playsim/p_local.h @@ -246,6 +246,7 @@ extern TArray portalhit; int P_TestMobjLocation (AActor *mobj); int P_TestMobjZ (AActor *mobj, bool quick=true, AActor **pOnmobj = NULL); bool P_CheckPosition(AActor *thing, const DVector2 &pos, bool actorsonly = false); +void P_DoMissileDamage(AActor* inflictor, AActor* target); bool P_CheckPosition(AActor *thing, const DVector2 &pos, FCheckPosition &tm, bool actorsonly = false); AActor *P_CheckOnmobj (AActor *thing); void P_FakeZMovement (AActor *mo); diff --git a/src/playsim/p_map.cpp b/src/playsim/p_map.cpp index ae0eecef0c..ac7b817d59 100644 --- a/src/playsim/p_map.cpp +++ b/src/playsim/p_map.cpp @@ -1230,6 +1230,57 @@ static bool CanAttackHurt(AActor *victim, AActor *shooter) return true; } +//========================================================================== +// +// P_DoMissileDamage +// Handle damaging/poisoning enemies from missiles. +// target is the target to be dealt damage to. +// inflictor is the actor dealing the damage. +// +//========================================================================== + +void P_DoMissileDamage(AActor* inflictor, AActor* target) +{ + // Do poisoning (if using new style poison) + if (inflictor->PoisonDamage > 0 && inflictor->PoisonDuration != INT_MIN) + { + P_PoisonMobj(target, inflictor, inflictor->target, inflictor->PoisonDamage, inflictor->PoisonDuration, inflictor->PoisonPeriod, inflictor->PoisonDamageType); + } + + // Do damage + int damage = inflictor->GetMissileDamage((inflictor->flags4 & MF4_STRIFEDAMAGE) ? 3 : 7, 1); + if ((damage > 0) || (inflictor->flags6 & MF6_FORCEPAIN) || (inflictor->flags7 & MF7_CAUSEPAIN)) + { + int newdam = P_DamageMobj(target, inflictor, inflictor->target, damage, inflictor->DamageType); + if (damage > 0) + { + if ((inflictor->flags5 & MF5_BLOODSPLATTER) && + !(target->flags & MF_NOBLOOD) && + !(target->flags2 & MF2_REFLECTIVE) && + !(target->flags2 & (MF2_INVULNERABLE | MF2_DORMANT)) && + !(inflictor->flags3 & MF3_BLOODLESSIMPACT) && + (pr_checkthing() < 192)) + { + P_BloodSplatter(inflictor->Pos(), target, inflictor->AngleTo(target)); + } + if (!(inflictor->flags3 & MF3_BLOODLESSIMPACT)) + { + P_TraceBleed(newdam > 0 ? newdam : damage, target, inflictor); + } + } + } + else + { + P_GiveBody(target, -damage); + } +} +DEFINE_ACTION_FUNCTION(AActor, DoMissileDamage) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_OBJECT_NOT_NULL(target, AActor); + P_DoMissileDamage(self, target); + return 0; +} //========================================================================== // // PIT_CheckThing @@ -1555,38 +1606,7 @@ bool PIT_CheckThing(FMultiBlockThingsIterator &it, FMultiBlockThingsIterator::Ch } } - // Do poisoning (if using new style poison) - if (tm.thing->PoisonDamage > 0 && tm.thing->PoisonDuration != INT_MIN) - { - P_PoisonMobj(thing, tm.thing, tm.thing->target, tm.thing->PoisonDamage, tm.thing->PoisonDuration, tm.thing->PoisonPeriod, tm.thing->PoisonDamageType); - } - - // Do damage - damage = tm.thing->GetMissileDamage((tm.thing->flags4 & MF4_STRIFEDAMAGE) ? 3 : 7, 1); - if ((damage > 0) || (tm.thing->flags6 & MF6_FORCEPAIN) || (tm.thing->flags7 & MF7_CAUSEPAIN)) - { - int newdam = P_DamageMobj(thing, tm.thing, tm.thing->target, damage, tm.thing->DamageType); - if (damage > 0) - { - if ((tm.thing->flags5 & MF5_BLOODSPLATTER) && - !(thing->flags & MF_NOBLOOD) && - !(thing->flags2 & MF2_REFLECTIVE) && - !(thing->flags2 & (MF2_INVULNERABLE | MF2_DORMANT)) && - !(tm.thing->flags3 & MF3_BLOODLESSIMPACT) && - (pr_checkthing() < 192)) - { - P_BloodSplatter(tm.thing->Pos(), thing, tm.thing->AngleTo(thing)); - } - if (!(tm.thing->flags3 & MF3_BLOODLESSIMPACT)) - { - P_TraceBleed(newdam > 0 ? newdam : damage, thing, tm.thing); - } - } - } - else - { - P_GiveBody(thing, -damage); - } + P_DoMissileDamage(tm.thing, thing); if ((thing->flags7 & MF7_THRUREFLECT) && (thing->flags2 & MF2_REFLECTIVE) && (tm.thing->flags & MF_MISSILE)) { diff --git a/src/playsim/p_mobj.cpp b/src/playsim/p_mobj.cpp index 0f6f32e9d4..c98bc9c7b1 100644 --- a/src/playsim/p_mobj.cpp +++ b/src/playsim/p_mobj.cpp @@ -3976,6 +3976,7 @@ void AActor::Tick () // to be in line with the case when an actor's side is hit. if (!res && (flags & MF_MISSILE)) { + P_DoMissileDamage(this, onmo); P_ExplodeMissile(this, nullptr, onmo); } } diff --git a/wadsrc/static/zscript/actors/actor.zs b/wadsrc/static/zscript/actors/actor.zs index 0b3841a19c..27a929fdd4 100644 --- a/wadsrc/static/zscript/actors/actor.zs +++ b/wadsrc/static/zscript/actors/actor.zs @@ -759,6 +759,7 @@ class Actor : Thinker native native void GiveSecret(bool printmsg = true, bool playsound = true); native clearscope double GetCameraHeight() const; native clearscope double GetGravity() const; + native void DoMissileDamage(Actor target); //========================================================================== //