Core/Creatures: Implemented CREATURE_STATIC_FLAG_2_IGNORE_SANCTUARY (ignore SPELL_EFFECT_SANCTUARY, used by Vanish)
This commit is contained in:
1 parent
a4aa09de52
commit
a7644b03d4
9 files changed
+73
-33
No files matched your search
@@ -277,22 +277,31 @@ void CombatManager::EndCombatBeyondRange(float range, bool includingPvP)
|
||||
}
|
||||
}
|
||||
|
||||
void CombatManager::SuppressPvPCombat()
|
||||
void CombatManager::SuppressPvPCombat(UnitFilter* unitFilter /*= nullptr*/)
|
||||
{
|
||||
for (auto const& pair : _pvpRefs)
|
||||
pair.second->Suppress(_owner);
|
||||
for (auto const& [guid, combatRef] : _pvpRefs)
|
||||
if (!unitFilter || unitFilter(combatRef->GetOther(_owner)))
|
||||
combatRef->Suppress(_owner);
|
||||
|
||||
if (UpdateOwnerCombatState())
|
||||
if (UnitAI* ownerAI = _owner->GetAI())
|
||||
ownerAI->JustExitedCombat();
|
||||
}
|
||||
|
||||
void CombatManager::EndAllPvECombat()
|
||||
void CombatManager::EndAllPvECombat(UnitFilter* unitFilter /*= nullptr*/)
|
||||
{
|
||||
// cannot have threat without combat
|
||||
_owner->GetThreatManager().RemoveMeFromThreatLists();
|
||||
_owner->GetThreatManager().RemoveMeFromThreatLists(unitFilter);
|
||||
_owner->GetThreatManager().ClearAllThreat();
|
||||
while (!_pveRefs.empty())
|
||||
_pveRefs.begin()->second->EndCombat();
|
||||
|
||||
std::vector<CombatReference*> combatReferencesToRemove;
|
||||
combatReferencesToRemove.reserve(_pveRefs.size());
|
||||
for (auto const& [guid, combatRef] : _pveRefs)
|
||||
if (!unitFilter || unitFilter(combatRef->GetOther(_owner)))
|
||||
combatReferencesToRemove.push_back(combatRef);
|
||||
|
||||
for (CombatReference* combatRef : combatReferencesToRemove)
|
||||
combatRef->EndCombat();
|
||||
}
|
||||
|
||||
void CombatManager::RevalidateCombat()
|
||||
@@ -324,12 +333,19 @@ void CombatManager::RevalidateCombat()
|
||||
}
|
||||
}
|
||||
|
||||
void CombatManager::EndAllPvPCombat()
|
||||
void CombatManager::EndAllPvPCombat(UnitFilter* unitFilter /*= nullptr*/)
|
||||
{
|
||||
while (!_pvpRefs.empty())
|
||||
_pvpRefs.begin()->second->EndCombat();
|
||||
std::vector<CombatReference*> combatReferencesToRemove;
|
||||
combatReferencesToRemove.reserve(_pvpRefs.size());
|
||||
for (auto const& [guid, combatRef] : _pvpRefs)
|
||||
if (!unitFilter || unitFilter(combatRef->GetOther(_owner)))
|
||||
combatReferencesToRemove.push_back(combatRef);
|
||||
|
||||
for (CombatReference* combatRef : combatReferencesToRemove)
|
||||
combatRef->EndCombat();
|
||||
}
|
||||
|
||||
|
||||
/*static*/ void CombatManager::NotifyAICombat(Unit* me, Unit* other)
|
||||
{
|
||||
if (UnitAI* ai = me->GetAI())
|
||||
|
||||
@@ -119,12 +119,15 @@ class TC_GAME_API CombatManager
|
||||
bool IsInCombatWith(Unit const* who) const;
|
||||
void InheritCombatStatesFrom(Unit const* who);
|
||||
void EndCombatBeyondRange(float range, bool includingPvP = false);
|
||||
|
||||
using UnitFilter = bool(Unit const* otherUnit);
|
||||
|
||||
// flags any pvp refs for suppression on owner's side - these refs will not generate combat until refreshed
|
||||
void SuppressPvPCombat();
|
||||
void EndAllPvECombat();
|
||||
void SuppressPvPCombat(UnitFilter* unitFilter = nullptr);
|
||||
void EndAllPvECombat(UnitFilter* unitFilter = nullptr);
|
||||
void RevalidateCombat();
|
||||
void EndAllPvPCombat();
|
||||
void EndAllCombat() { EndAllPvECombat(); EndAllPvPCombat(); }
|
||||
void EndAllPvPCombat(UnitFilter* unitFilter = nullptr);
|
||||
void EndAllCombat(UnitFilter* unitFilter = nullptr) { EndAllPvECombat(unitFilter); EndAllPvPCombat(unitFilter); }
|
||||
|
||||
CombatManager(CombatManager const&) = delete;
|
||||
CombatManager& operator=(CombatManager const&) = delete;
|
||||
|
||||
@@ -752,13 +752,16 @@ void ThreatManager::ForwardThreatForAssistingMe(Unit* assistant, float baseAmoun
|
||||
threatened->GetThreatManager().AddThreat(assistant, 0.0f, spell, true);
|
||||
}
|
||||
|
||||
void ThreatManager::RemoveMeFromThreatLists()
|
||||
void ThreatManager::RemoveMeFromThreatLists(bool (*unitFilter)(Unit const* otherUnit))
|
||||
{
|
||||
while (!_threatenedByMe.empty())
|
||||
{
|
||||
auto& ref = _threatenedByMe.begin()->second;
|
||||
std::vector<ThreatReference*> threatReferencesToRemove;
|
||||
threatReferencesToRemove.reserve(_threatenedByMe.size());
|
||||
for (auto const& [guid, ref] : _threatenedByMe)
|
||||
if (!unitFilter || unitFilter(ref->GetOwner()))
|
||||
threatReferencesToRemove.push_back(ref);
|
||||
|
||||
for (ThreatReference* ref : threatReferencesToRemove)
|
||||
ref->_mgr.ClearThreat(_owner);
|
||||
}
|
||||
}
|
||||
|
||||
void ThreatManager::UpdateMyTempModifiers()
|
||||
|
||||
@@ -167,7 +167,7 @@ class TC_GAME_API ThreatManager
|
||||
// what it says on the tin - call AddThreat on everything that's threatened by us with the specified params
|
||||
void ForwardThreatForAssistingMe(Unit* assistant, float baseAmount, SpellInfo const* spell = nullptr, bool ignoreModifiers = false);
|
||||
// delete all ThreatReferences with victim == owner
|
||||
void RemoveMeFromThreatLists();
|
||||
void RemoveMeFromThreatLists(bool (*unitFilter)(Unit const* otherUnit));
|
||||
// re-calculates the temporary threat modifier from auras on myself
|
||||
void UpdateMyTempModifiers();
|
||||
// re-calculate SPELL_AURA_MOD_THREAT modifiers
|
||||
|
||||
@@ -277,6 +277,8 @@ class TC_GAME_API Creature : public Unit, public GridObject<Creature>, public Ma
|
||||
bool CanAssistTo(const Unit* u, const Unit* enemy, bool checkfaction = true) const;
|
||||
bool _IsTargetAcceptable(const Unit* target) const;
|
||||
bool CanIgnoreFeignDeath() const { return (GetCreatureTemplate()->flags_extra & CREATURE_FLAG_EXTRA_IGNORE_FEIGN_DEATH) != 0; }
|
||||
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); }
|
||||
|
||||
MovementGeneratorType GetDefaultMovementType() const { return m_defaultMovementType; }
|
||||
void SetDefaultMovementType(MovementGeneratorType mgt) { m_defaultMovementType = mgt; }
|
||||
|
||||
@@ -126,7 +126,7 @@ enum CreatureStaticFlags2
|
||||
CREATURE_STATIC_FLAG_2_NO_WOUNDED_SLOWDOWN = 0x00000040,
|
||||
CREATURE_STATIC_FLAG_2_USE_CREATOR_BONUSES = 0x00000080,
|
||||
CREATURE_STATIC_FLAG_2_IGNORE_FEIGN_DEATH = 0x00000100, // CREATURE_FLAG_EXTRA_IGNORE_FEIGN_DEATH
|
||||
CREATURE_STATIC_FLAG_2_IGNORE_SANCTUARY = 0x00000200,
|
||||
CREATURE_STATIC_FLAG_2_IGNORE_SANCTUARY = 0x00000200, // Ignores SPELL_EFFECT_SANCTUARY
|
||||
CREATURE_STATIC_FLAG_2_ACTION_TRIGGERS_WHILE_CHARMED = 0x00000400,
|
||||
CREATURE_STATIC_FLAG_2_INTERACT_WHILE_DEAD = 0x00000800, // CREATURE_TYPE_FLAG_INTERACT_WHILE_DEAD
|
||||
CREATURE_STATIC_FLAG_2_NO_INTERRUPT_SCHOOL_COOLDOWN = 0x00001000,
|
||||
|
||||
@@ -5530,23 +5530,32 @@ void Unit::ValidateAttackersAndOwnTarget()
|
||||
AttackStop();
|
||||
}
|
||||
|
||||
void Unit::CombatStop(bool includingCast, bool mutualPvP)
|
||||
void Unit::CombatStop(bool includingCast, bool mutualPvP, bool (*unitFilter)(Unit const* otherUnit))
|
||||
{
|
||||
if (includingCast && IsNonMeleeSpellCast(false))
|
||||
InterruptNonMeleeSpells(false);
|
||||
|
||||
AttackStop();
|
||||
RemoveAllAttackers();
|
||||
|
||||
if (!unitFilter)
|
||||
RemoveAllAttackers();
|
||||
else
|
||||
{
|
||||
std::vector<Unit*> attackersToRemove;
|
||||
attackersToRemove.reserve(m_attackers.size());
|
||||
std::copy_if(m_attackers.begin(), m_attackers.end(), std::back_inserter(attackersToRemove), unitFilter);
|
||||
|
||||
for (Unit* attacker : attackersToRemove)
|
||||
attacker->AttackStop();
|
||||
}
|
||||
if (GetTypeId() == TYPEID_PLAYER)
|
||||
ToPlayer()->SendAttackSwingCancelAttack(); // melee and ranged forced attack cancel
|
||||
|
||||
m_combatManager.EndAllPvECombat(unitFilter);
|
||||
if (mutualPvP)
|
||||
ClearInCombat();
|
||||
else
|
||||
{ // vanish and brethren are weird
|
||||
m_combatManager.EndAllPvECombat();
|
||||
m_combatManager.SuppressPvPCombat();
|
||||
}
|
||||
m_combatManager.EndAllPvPCombat(unitFilter);
|
||||
else // vanish and brethren are weird
|
||||
m_combatManager.SuppressPvPCombat(unitFilter);
|
||||
}
|
||||
|
||||
void Unit::CombatStopWithPets(bool includingCast)
|
||||
|
||||
@@ -865,7 +865,7 @@ class TC_GAME_API Unit : public WorldObject
|
||||
}
|
||||
|
||||
void ValidateAttackersAndOwnTarget();
|
||||
void CombatStop(bool includingCast = false, bool mutualPvP = true);
|
||||
void CombatStop(bool includingCast = false, bool mutualPvP = true, bool (*unitFilter)(Unit const* otherUnit) = nullptr);
|
||||
void CombatStopWithPets(bool includingCast = false);
|
||||
void StopAttackFaction(uint32 faction_id);
|
||||
Unit* SelectNearbyTarget(Unit* exclude = nullptr, float dist = NOMINAL_MELEE_RANGE) const;
|
||||
|
||||
@@ -3573,16 +3573,23 @@ void Spell::EffectSanctuary(SpellEffIndex /*effIndex*/)
|
||||
if (!unitTarget)
|
||||
return;
|
||||
|
||||
auto isAffectedBySanctuary = [](Unit const* attacker)
|
||||
{
|
||||
Creature const* attackerCreature = attacker->ToCreature();
|
||||
return !attackerCreature || !attackerCreature->IsIgnoringSanctuarySpellEffect();
|
||||
};
|
||||
|
||||
if (unitTarget->GetTypeId() == TYPEID_PLAYER && !unitTarget->GetMap()->IsDungeon())
|
||||
{
|
||||
// stop all pve combat for players outside dungeons, suppress pvp combat
|
||||
unitTarget->CombatStop(false, false);
|
||||
unitTarget->CombatStop(false, false, isAffectedBySanctuary);
|
||||
}
|
||||
else
|
||||
{
|
||||
// in dungeons (or for nonplayers), reset this unit on all enemies' threat lists
|
||||
for (auto const& pair : unitTarget->GetThreatManager().GetThreatenedByMeList())
|
||||
pair.second->ScaleThreat(0.0f);
|
||||
for (auto const& [guid, ref] : unitTarget->GetThreatManager().GetThreatenedByMeList())
|
||||
if (isAffectedBySanctuary(ref->GetOwner()))
|
||||
ref->ScaleThreat(0.0f);
|
||||
}
|
||||
|
||||
// makes spells cast before this time fizzle
|
||||
|
||||
Reference in new issue
Block a user