mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-11 07:11:54 +00:00
Split off pain chance triggering from ReactToDamage into its own function and gave ZScript access to it.
- TriggerPainChance(Name mod, bool forcedPain) - One exception: PainThrehold is only checked in ReactToDamage, since this function does not require checking damage amount.
This commit is contained in:
parent
2f7fae2fb0
commit
6372cdaa41
2 changed files with 80 additions and 46 deletions
|
@ -788,6 +788,7 @@ void P_AutoUseStrifeHealth (player_t *player)
|
||||||
// ReactToDamage
|
// ReactToDamage
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
static bool TriggerPainChance(AActor *target, FName mod, bool forcedPain, bool zscript);
|
||||||
|
|
||||||
static inline bool MustForcePain(AActor *target, AActor *inflictor)
|
static inline bool MustForcePain(AActor *target, AActor *inflictor)
|
||||||
{
|
{
|
||||||
|
@ -809,7 +810,7 @@ static void ReactToDamage(AActor *target, AActor *inflictor, AActor *source, int
|
||||||
bool forcedPain = false;
|
bool forcedPain = false;
|
||||||
bool noPain = false;
|
bool noPain = false;
|
||||||
|
|
||||||
// Dead or non-existent entity, do not react.
|
// Dead or non-existent entity, do not react. Especially if the damage is cancelled.
|
||||||
if (target == nullptr || target->health < 1 || damage < 0)
|
if (target == nullptr || target->health < 1 || damage < 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -848,53 +849,14 @@ static void ReactToDamage(AActor *target, AActor *inflictor, AActor *source, int
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!noPain &&
|
if (!noPain &&
|
||||||
(target->player != nullptr || !G_SkillProperty(SKILLP_NoPain)) && !(target->flags & MF_SKULLFLY))
|
((target->player != nullptr || !G_SkillProperty(SKILLP_NoPain)) && !(target->flags & MF_SKULLFLY))
|
||||||
|
&& damage >= target->PainThreshold)
|
||||||
{
|
{
|
||||||
painchance = target->PainChance;
|
if (inflictor && inflictor->PainType != NAME_None)
|
||||||
for (auto & pc : target->GetInfo()->PainChances)
|
mod = inflictor->PainType;
|
||||||
{
|
|
||||||
if (pc.first == mod)
|
|
||||||
{
|
|
||||||
painchance = pc.second;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (forcedPain || ((damage >= target->PainThreshold) && (pr_damagemobj() < painchance)))
|
// Not called from ZScript.
|
||||||
{
|
justhit = TriggerPainChance(target, mod, forcedPain, false);
|
||||||
if (mod == NAME_Electric)
|
|
||||||
{
|
|
||||||
if (pr_lightning() < 96)
|
|
||||||
{
|
|
||||||
justhit = true;
|
|
||||||
FState *painstate = target->FindState(NAME_Pain, mod);
|
|
||||||
if (painstate != NULL)
|
|
||||||
target->SetState(painstate);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{ // "electrocute" the target
|
|
||||||
target->renderflags |= RF_FULLBRIGHT;
|
|
||||||
if ((target->flags3 & MF3_ISMONSTER) && pr_lightning() < 128)
|
|
||||||
{
|
|
||||||
target->Howl();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
justhit = true;
|
|
||||||
FState *painstate = target->FindState(NAME_Pain, ((inflictor && inflictor->PainType != NAME_None) ? inflictor->PainType : mod));
|
|
||||||
if (painstate != NULL)
|
|
||||||
target->SetState(painstate);
|
|
||||||
if (mod == NAME_PoisonCloud)
|
|
||||||
{
|
|
||||||
if ((target->flags3 & MF3_ISMONSTER) && pr_poison() < 128)
|
|
||||||
{
|
|
||||||
target->Howl();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (target->player == nullptr) target->reactiontime = 0; // we're awake now...
|
if (target->player == nullptr) target->reactiontime = 0; // we're awake now...
|
||||||
|
@ -935,6 +897,77 @@ static void ReactToDamage(AActor *target, AActor *inflictor, AActor *source, int
|
||||||
target->flags |= MF_JUSTHIT; // fight back!
|
target->flags |= MF_JUSTHIT; // fight back!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool TriggerPainChance(AActor *target, FName mod = NAME_None, bool forcedPain = false, bool zscript = false)
|
||||||
|
{
|
||||||
|
if (target == nullptr || target->flags5 & MF5_NOPAIN || target->health < 1)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
bool justhit = false, flinched = false;
|
||||||
|
int painchance = target->PainChance;
|
||||||
|
for (auto & pc : target->GetInfo()->PainChances)
|
||||||
|
{
|
||||||
|
if (pc.first == mod)
|
||||||
|
{
|
||||||
|
painchance = pc.second;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (forcedPain || (pr_damagemobj() < painchance))
|
||||||
|
{
|
||||||
|
if (mod == NAME_Electric)
|
||||||
|
{
|
||||||
|
if (pr_lightning() < 96)
|
||||||
|
{
|
||||||
|
justhit = true;
|
||||||
|
FState *painstate = target->FindState(NAME_Pain, mod);
|
||||||
|
if (painstate != NULL)
|
||||||
|
{
|
||||||
|
flinched = true;
|
||||||
|
target->SetState(painstate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // "electrocute" the target
|
||||||
|
target->renderflags |= RF_FULLBRIGHT;
|
||||||
|
if ((target->flags3 & MF3_ISMONSTER) && pr_lightning() < 128)
|
||||||
|
{
|
||||||
|
target->Howl();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
justhit = true;
|
||||||
|
FState *painstate = target->FindState(NAME_Pain, mod);
|
||||||
|
if (painstate != NULL)
|
||||||
|
{
|
||||||
|
flinched = true;
|
||||||
|
target->SetState(painstate);
|
||||||
|
}
|
||||||
|
if (mod == NAME_PoisonCloud)
|
||||||
|
{
|
||||||
|
if ((target->flags3 & MF3_ISMONSTER) && pr_poison() < 128)
|
||||||
|
{
|
||||||
|
target->Howl();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (zscript) ? flinched : justhit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TriggerPainChance directly from DECORATE/ZScript will return if the
|
||||||
|
// entity flinched or not.
|
||||||
|
|
||||||
|
DEFINE_ACTION_FUNCTION(AActor, TriggerPainChance)
|
||||||
|
{
|
||||||
|
PARAM_SELF_PROLOGUE(AActor);
|
||||||
|
PARAM_NAME(mod);
|
||||||
|
PARAM_BOOL(forcedPain);
|
||||||
|
ACTION_RETURN_BOOL(TriggerPainChance(self, mod, forcedPain, true));
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
=================
|
=================
|
||||||
=
|
=
|
||||||
|
|
|
@ -666,6 +666,7 @@ class Actor : Thinker native
|
||||||
|
|
||||||
native void SetIdle(bool nofunction = false);
|
native void SetIdle(bool nofunction = false);
|
||||||
native bool CheckMeleeRange();
|
native bool CheckMeleeRange();
|
||||||
|
native bool TriggerPainChance(Name mod, bool forcedPain = false);
|
||||||
native virtual int DamageMobj(Actor inflictor, Actor source, int damage, Name mod, int flags = 0, double angle = 0);
|
native virtual int DamageMobj(Actor inflictor, Actor source, int damage, Name mod, int flags = 0, double angle = 0);
|
||||||
native void PoisonMobj (Actor inflictor, Actor source, int damage, int duration, int period, Name type);
|
native void PoisonMobj (Actor inflictor, Actor source, int damage, int duration, int period, Name type);
|
||||||
native double AimLineAttack(double angle, double distance, out FTranslatedLineTarget pLineTarget = null, double vrange = 0., int flags = 0, Actor target = null, Actor friender = null);
|
native double AimLineAttack(double angle, double distance, out FTranslatedLineTarget pLineTarget = null, double vrange = 0., int flags = 0, Actor target = null, Actor friender = null);
|
||||||
|
|
Loading…
Reference in a new issue