Core/Auras: Feign death will no longer cause creatures immune to it to drop combat (and then reenter it because the unit feigning death is considered valid)

This commit is contained in:
Shauren
2024-03-04 16:14:23 +01:00
parent 1369b87084
commit 0c32277139
3 changed files with 27 additions and 15 deletions

View File

@@ -567,6 +567,7 @@ bool Creature::InitEntry(uint32 entry, CreatureData const* data /*= nullptr*/)
// TODO: migrate these in DB
_staticFlags.ApplyFlag(CREATURE_STATIC_FLAG_2_ALLOW_MOUNTED_COMBAT, (GetCreatureDifficulty()->TypeFlags & CREATURE_TYPE_FLAG_ALLOW_MOUNTED_COMBAT) != 0);
SetIgnoreFeignDeath((creatureInfo->flags_extra & CREATURE_FLAG_EXTRA_IGNORE_FEIGN_DEATH) != 0);
SetInteractionAllowedInCombat((GetCreatureDifficulty()->TypeFlags & CREATURE_TYPE_FLAG_ALLOW_INTERACTION_WHILE_IN_COMBAT) != 0);
SetTreatAsRaidUnit((GetCreatureDifficulty()->TypeFlags & CREATURE_TYPE_FLAG_TREAT_AS_RAID_UNIT) != 0);
@@ -2641,7 +2642,7 @@ bool Creature::_IsTargetAcceptable(Unit const* target) const
if (target->HasUnitState(UNIT_STATE_DIED))
{
// some creatures can detect fake death
if (CanIgnoreFeignDeath() && target->HasUnitFlag2(UNIT_FLAG2_FEIGN_DEATH))
if (IsIgnoringFeignDeath() && target->HasUnitFlag2(UNIT_FLAG2_FEIGN_DEATH))
return true;
else
return false;

View File

@@ -319,9 +319,10 @@ class TC_GAME_API Creature : public Unit, public GridObject<Creature>, public Ma
bool HasSearchedAssistance() const { return m_AlreadySearchedAssistance; }
bool CanAssistTo(Unit const* u, Unit const* enemy, bool checkfaction = true) const;
bool _IsTargetAcceptable(Unit const* target) const;
bool CanIgnoreFeignDeath() const { return (GetCreatureTemplate()->flags_extra & CREATURE_FLAG_EXTRA_IGNORE_FEIGN_DEATH) != 0; }
bool IsIgnoringFeignDeath() const { return _staticFlags.HasFlag(CREATURE_STATIC_FLAG_2_IGNORE_FEIGN_DEATH); }
void SetIgnoreFeignDeath(bool ignoreFeignDeath) { _staticFlags.ApplyFlag(CREATURE_STATIC_FLAG_2_IGNORE_FEIGN_DEATH, ignoreFeignDeath); }
bool IsIgnoringSanctuarySpellEffect() const { return _staticFlags.HasFlag(CREATURE_STATIC_FLAG_2_IGNORE_SANCTUARY); }
void SetIngoreSanctuarySpellEffect(bool ignoreSanctuary) { _staticFlags.ApplyFlag(CREATURE_STATIC_FLAG_2_IGNORE_SANCTUARY, ignoreSanctuary); }
void SetIgnoreSanctuarySpellEffect(bool ignoreSanctuary) { _staticFlags.ApplyFlag(CREATURE_STATIC_FLAG_2_IGNORE_SANCTUARY, ignoreSanctuary); }
void RemoveCorpse(bool setSpawnTime = true, bool destroyForNearbyPlayers = true);

View File

@@ -2209,27 +2209,37 @@ void AuraEffect::HandleFeignDeath(AuraApplication const* aurApp, uint8 mode, boo
if (apply)
{
UnitList targets;
Trinity::AnyUnfriendlyUnitInObjectRangeCheck u_check(target, target, target->GetMap()->GetVisibilityRange());
Trinity::UnitListSearcher<Trinity::AnyUnfriendlyUnitInObjectRangeCheck> searcher(target, targets, u_check);
Cell::VisitAllObjects(target, searcher, target->GetMap()->GetVisibilityRange());
for (UnitList::iterator iter = targets.begin(); iter != targets.end(); ++iter)
auto isAffectedByFeignDeath = [](Unit const* attacker)
{
if (!(*iter)->HasUnitState(UNIT_STATE_CASTING))
Creature const* attackerCreature = attacker->ToCreature();
return !attackerCreature || !attackerCreature->IsIgnoringFeignDeath();
};
std::vector<Unit*> targets;
Trinity::AnyUnfriendlyUnitInObjectRangeCheck u_check(target, target, target->GetMap()->GetVisibilityRange());
Trinity::UnitListSearcher searcher(target, targets, u_check);
Cell::VisitAllObjects(target, searcher, target->GetMap()->GetVisibilityRange());
for (Unit* unit : targets)
{
if (!unit->HasUnitState(UNIT_STATE_CASTING))
continue;
if (!isAffectedByFeignDeath(unit))
continue;
for (uint32 i = CURRENT_FIRST_NON_MELEE_SPELL; i < CURRENT_MAX_SPELL; i++)
{
if ((*iter)->GetCurrentSpell(i)
&& (*iter)->GetCurrentSpell(i)->m_targets.GetUnitTargetGUID() == target->GetGUID())
if (unit->GetCurrentSpell(i)
&& unit->GetCurrentSpell(i)->m_targets.GetUnitTargetGUID() == target->GetGUID())
{
(*iter)->InterruptSpell(CurrentSpellTypes(i), false);
unit->InterruptSpell(CurrentSpellTypes(i), false);
}
}
}
for (auto& pair : target->GetThreatManager().GetThreatenedByMeList())
pair.second->ScaleThreat(0.0f);
for (auto const& [guid, ref] : target->GetThreatManager().GetThreatenedByMeList())
if (isAffectedByFeignDeath(ref->GetOwner()))
ref->ScaleThreat(0.0f);
if (target->GetMap()->IsDungeon()) // feign death does not remove combat in dungeons
{
@@ -2238,7 +2248,7 @@ void AuraEffect::HandleFeignDeath(AuraApplication const* aurApp, uint8 mode, boo
targetPlayer->SendAttackSwingCancelAttack();
}
else
target->CombatStop(false, false);
target->CombatStop(false, false, isAffectedByFeignDeath);
// prevent interrupt message
if (GetCasterGUID() == target->GetGUID() && target->GetCurrentSpell(CURRENT_GENERIC_SPELL))