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)
|
for (auto const& [guid, combatRef] : _pvpRefs)
|
||||||
pair.second->Suppress(_owner);
|
if (!unitFilter || unitFilter(combatRef->GetOther(_owner)))
|
||||||
|
combatRef->Suppress(_owner);
|
||||||
|
|
||||||
if (UpdateOwnerCombatState())
|
if (UpdateOwnerCombatState())
|
||||||
if (UnitAI* ownerAI = _owner->GetAI())
|
if (UnitAI* ownerAI = _owner->GetAI())
|
||||||
ownerAI->JustExitedCombat();
|
ownerAI->JustExitedCombat();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CombatManager::EndAllPvECombat()
|
void CombatManager::EndAllPvECombat(UnitFilter* unitFilter /*= nullptr*/)
|
||||||
{
|
{
|
||||||
// cannot have threat without combat
|
// cannot have threat without combat
|
||||||
_owner->GetThreatManager().RemoveMeFromThreatLists();
|
_owner->GetThreatManager().RemoveMeFromThreatLists(unitFilter);
|
||||||
_owner->GetThreatManager().ClearAllThreat();
|
_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()
|
void CombatManager::RevalidateCombat()
|
||||||
@@ -324,12 +333,19 @@ void CombatManager::RevalidateCombat()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CombatManager::EndAllPvPCombat()
|
void CombatManager::EndAllPvPCombat(UnitFilter* unitFilter /*= nullptr*/)
|
||||||
{
|
{
|
||||||
while (!_pvpRefs.empty())
|
std::vector<CombatReference*> combatReferencesToRemove;
|
||||||
_pvpRefs.begin()->second->EndCombat();
|
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)
|
/*static*/ void CombatManager::NotifyAICombat(Unit* me, Unit* other)
|
||||||
{
|
{
|
||||||
if (UnitAI* ai = me->GetAI())
|
if (UnitAI* ai = me->GetAI())
|
||||||
|
|||||||
@@ -119,12 +119,15 @@ class TC_GAME_API CombatManager
|
|||||||
bool IsInCombatWith(Unit const* who) const;
|
bool IsInCombatWith(Unit const* who) const;
|
||||||
void InheritCombatStatesFrom(Unit const* who);
|
void InheritCombatStatesFrom(Unit const* who);
|
||||||
void EndCombatBeyondRange(float range, bool includingPvP = false);
|
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
|
// flags any pvp refs for suppression on owner's side - these refs will not generate combat until refreshed
|
||||||
void SuppressPvPCombat();
|
void SuppressPvPCombat(UnitFilter* unitFilter = nullptr);
|
||||||
void EndAllPvECombat();
|
void EndAllPvECombat(UnitFilter* unitFilter = nullptr);
|
||||||
void RevalidateCombat();
|
void RevalidateCombat();
|
||||||
void EndAllPvPCombat();
|
void EndAllPvPCombat(UnitFilter* unitFilter = nullptr);
|
||||||
void EndAllCombat() { EndAllPvECombat(); EndAllPvPCombat(); }
|
void EndAllCombat(UnitFilter* unitFilter = nullptr) { EndAllPvECombat(unitFilter); EndAllPvPCombat(unitFilter); }
|
||||||
|
|
||||||
CombatManager(CombatManager const&) = delete;
|
CombatManager(CombatManager const&) = delete;
|
||||||
CombatManager& operator=(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);
|
threatened->GetThreatManager().AddThreat(assistant, 0.0f, spell, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ThreatManager::RemoveMeFromThreatLists()
|
void ThreatManager::RemoveMeFromThreatLists(bool (*unitFilter)(Unit const* otherUnit))
|
||||||
{
|
{
|
||||||
while (!_threatenedByMe.empty())
|
std::vector<ThreatReference*> threatReferencesToRemove;
|
||||||
{
|
threatReferencesToRemove.reserve(_threatenedByMe.size());
|
||||||
auto& ref = _threatenedByMe.begin()->second;
|
for (auto const& [guid, ref] : _threatenedByMe)
|
||||||
|
if (!unitFilter || unitFilter(ref->GetOwner()))
|
||||||
|
threatReferencesToRemove.push_back(ref);
|
||||||
|
|
||||||
|
for (ThreatReference* ref : threatReferencesToRemove)
|
||||||
ref->_mgr.ClearThreat(_owner);
|
ref->_mgr.ClearThreat(_owner);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ThreatManager::UpdateMyTempModifiers()
|
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
|
// 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);
|
void ForwardThreatForAssistingMe(Unit* assistant, float baseAmount, SpellInfo const* spell = nullptr, bool ignoreModifiers = false);
|
||||||
// delete all ThreatReferences with victim == owner
|
// 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
|
// re-calculates the temporary threat modifier from auras on myself
|
||||||
void UpdateMyTempModifiers();
|
void UpdateMyTempModifiers();
|
||||||
// re-calculate SPELL_AURA_MOD_THREAT modifiers
|
// 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 CanAssistTo(const Unit* u, const Unit* enemy, bool checkfaction = true) const;
|
||||||
bool _IsTargetAcceptable(const Unit* target) const;
|
bool _IsTargetAcceptable(const Unit* target) const;
|
||||||
bool CanIgnoreFeignDeath() const { return (GetCreatureTemplate()->flags_extra & CREATURE_FLAG_EXTRA_IGNORE_FEIGN_DEATH) != 0; }
|
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; }
|
MovementGeneratorType GetDefaultMovementType() const { return m_defaultMovementType; }
|
||||||
void SetDefaultMovementType(MovementGeneratorType mgt) { m_defaultMovementType = mgt; }
|
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_NO_WOUNDED_SLOWDOWN = 0x00000040,
|
||||||
CREATURE_STATIC_FLAG_2_USE_CREATOR_BONUSES = 0x00000080,
|
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_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_ACTION_TRIGGERS_WHILE_CHARMED = 0x00000400,
|
||||||
CREATURE_STATIC_FLAG_2_INTERACT_WHILE_DEAD = 0x00000800, // CREATURE_TYPE_FLAG_INTERACT_WHILE_DEAD
|
CREATURE_STATIC_FLAG_2_INTERACT_WHILE_DEAD = 0x00000800, // CREATURE_TYPE_FLAG_INTERACT_WHILE_DEAD
|
||||||
CREATURE_STATIC_FLAG_2_NO_INTERRUPT_SCHOOL_COOLDOWN = 0x00001000,
|
CREATURE_STATIC_FLAG_2_NO_INTERRUPT_SCHOOL_COOLDOWN = 0x00001000,
|
||||||
|
|||||||
@@ -5530,23 +5530,32 @@ void Unit::ValidateAttackersAndOwnTarget()
|
|||||||
AttackStop();
|
AttackStop();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Unit::CombatStop(bool includingCast, bool mutualPvP)
|
void Unit::CombatStop(bool includingCast, bool mutualPvP, bool (*unitFilter)(Unit const* otherUnit))
|
||||||
{
|
{
|
||||||
if (includingCast && IsNonMeleeSpellCast(false))
|
if (includingCast && IsNonMeleeSpellCast(false))
|
||||||
InterruptNonMeleeSpells(false);
|
InterruptNonMeleeSpells(false);
|
||||||
|
|
||||||
AttackStop();
|
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)
|
if (GetTypeId() == TYPEID_PLAYER)
|
||||||
ToPlayer()->SendAttackSwingCancelAttack(); // melee and ranged forced attack cancel
|
ToPlayer()->SendAttackSwingCancelAttack(); // melee and ranged forced attack cancel
|
||||||
|
|
||||||
|
m_combatManager.EndAllPvECombat(unitFilter);
|
||||||
if (mutualPvP)
|
if (mutualPvP)
|
||||||
ClearInCombat();
|
m_combatManager.EndAllPvPCombat(unitFilter);
|
||||||
else
|
else // vanish and brethren are weird
|
||||||
{ // vanish and brethren are weird
|
m_combatManager.SuppressPvPCombat(unitFilter);
|
||||||
m_combatManager.EndAllPvECombat();
|
|
||||||
m_combatManager.SuppressPvPCombat();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Unit::CombatStopWithPets(bool includingCast)
|
void Unit::CombatStopWithPets(bool includingCast)
|
||||||
|
|||||||
@@ -865,7 +865,7 @@ class TC_GAME_API Unit : public WorldObject
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ValidateAttackersAndOwnTarget();
|
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 CombatStopWithPets(bool includingCast = false);
|
||||||
void StopAttackFaction(uint32 faction_id);
|
void StopAttackFaction(uint32 faction_id);
|
||||||
Unit* SelectNearbyTarget(Unit* exclude = nullptr, float dist = NOMINAL_MELEE_RANGE) const;
|
Unit* SelectNearbyTarget(Unit* exclude = nullptr, float dist = NOMINAL_MELEE_RANGE) const;
|
||||||
|
|||||||
@@ -3573,16 +3573,23 @@ void Spell::EffectSanctuary(SpellEffIndex /*effIndex*/)
|
|||||||
if (!unitTarget)
|
if (!unitTarget)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
auto isAffectedBySanctuary = [](Unit const* attacker)
|
||||||
|
{
|
||||||
|
Creature const* attackerCreature = attacker->ToCreature();
|
||||||
|
return !attackerCreature || !attackerCreature->IsIgnoringSanctuarySpellEffect();
|
||||||
|
};
|
||||||
|
|
||||||
if (unitTarget->GetTypeId() == TYPEID_PLAYER && !unitTarget->GetMap()->IsDungeon())
|
if (unitTarget->GetTypeId() == TYPEID_PLAYER && !unitTarget->GetMap()->IsDungeon())
|
||||||
{
|
{
|
||||||
// stop all pve combat for players outside dungeons, suppress pvp combat
|
// stop all pve combat for players outside dungeons, suppress pvp combat
|
||||||
unitTarget->CombatStop(false, false);
|
unitTarget->CombatStop(false, false, isAffectedBySanctuary);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// in dungeons (or for nonplayers), reset this unit on all enemies' threat lists
|
// in dungeons (or for nonplayers), reset this unit on all enemies' threat lists
|
||||||
for (auto const& pair : unitTarget->GetThreatManager().GetThreatenedByMeList())
|
for (auto const& [guid, ref] : unitTarget->GetThreatManager().GetThreatenedByMeList())
|
||||||
pair.second->ScaleThreat(0.0f);
|
if (isAffectedBySanctuary(ref->GetOwner()))
|
||||||
|
ref->ScaleThreat(0.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
// makes spells cast before this time fizzle
|
// makes spells cast before this time fizzle
|
||||||
|
|||||||
Reference in new issue
Block a user