Core/Creatures: Implemented CREATURE_STATIC_FLAG_2_IGNORE_SANCTUARY (ignore SPELL_EFFECT_SANCTUARY, used by Vanish)

Port From (https://github.com/TrinityCore/TrinityCore/commit/1369b8708458fb5020b6ab7a9608123459d4eb26)
This commit is contained in:
hondacrx
2024-03-05 18:33:31 -05:00
parent 83bd8b255b
commit 536f72d077
6 changed files with 69 additions and 33 deletions
+1 -1
View File
@@ -316,7 +316,7 @@ namespace Framework.Constants
NoWoundedSlowdown = 0x00000040, NoWoundedSlowdown = 0x00000040,
UseCreatorBonuses = 0x00000080, UseCreatorBonuses = 0x00000080,
IgnoreFeignDeath = 0x00000100, // CreatureFlagExtraIgnoreFeignDeath IgnoreFeignDeath = 0x00000100, // CreatureFlagExtraIgnoreFeignDeath
IgnoreSanctuary = 0x00000200, IgnoreSanctuary = 0x00000200, // Ignores SPELL_EFFECT_SANCTUARY
ActionTriggersWhileCharmed = 0x00000400, ActionTriggersWhileCharmed = 0x00000400,
InteractWhileDead = 0x00000800, // CreatureTypeFlagInteractWhileDead InteractWhileDead = 0x00000800, // CreatureTypeFlagInteractWhileDead
NoInterruptSchoolCooldown = 0x00001000, NoInterruptSchoolCooldown = 0x00001000,
+32 -13
View File
@@ -4,6 +4,7 @@
using Framework.Constants; using Framework.Constants;
using Game.AI; using Game.AI;
using Game.Entities; using Game.Entities;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
@@ -58,9 +59,9 @@ namespace Game.Combat
public void Update(uint tdiff) public void Update(uint tdiff)
{ {
foreach(var pair in _pvpRefs.ToList()) foreach (var pair in _pvpRefs.ToList())
{ {
PvPCombatReference refe = pair.Value; PvPCombatReference refe = pair.Value;
if (refe.first == _owner && !refe.Update(tdiff)) // only update if we're the first unit involved (otherwise double decrement) if (refe.first == _owner && !refe.Update(tdiff)) // only update if we're the first unit involved (otherwise double decrement)
{ {
_pvpRefs.Remove(pair.Key); _pvpRefs.Remove(pair.Key);
@@ -217,10 +218,11 @@ namespace Game.Combat
} }
} }
public void SuppressPvPCombat() public void SuppressPvPCombat(Func<Unit, bool> unitFilter = null)
{ {
foreach (var pair in _pvpRefs) foreach (var (_, combatRef) in _pvpRefs)
pair.Value.Suppress(_owner); if (unitFilter == null || unitFilter(combatRef.GetOther(_owner)))
combatRef.Suppress(_owner);
if (UpdateOwnerCombatState()) if (UpdateOwnerCombatState())
{ {
@@ -230,18 +232,24 @@ namespace Game.Combat
} }
} }
public void EndAllPvECombat() public void EndAllPvECombat(Func<Unit, bool> unitFilter = null)
{ {
// 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.First().Value.EndCombat(); List<CombatReference> combatReferencesToRemove = new();
foreach (var (_, combatRef) in _pveRefs)
if (unitFilter == null || unitFilter(combatRef.GetOther(_owner)))
combatReferencesToRemove.Add(combatRef);
foreach (CombatReference combatRef in combatReferencesToRemove)
combatRef.EndCombat();
} }
public void RevalidateCombat() public void RevalidateCombat()
{ {
foreach(var (guid, refe) in _pveRefs.ToList()) foreach (var (guid, refe) in _pveRefs.ToList())
{ {
if (!CanBeginCombat(_owner, refe.GetOther(_owner))) if (!CanBeginCombat(_owner, refe.GetOther(_owner)))
{ {
@@ -260,10 +268,21 @@ namespace Game.Combat
} }
} }
void EndAllPvPCombat() public void EndAllPvPCombat(Func<Unit, bool> unitFilter = null)
{ {
while (!_pvpRefs.Empty()) List<CombatReference> combatReferencesToRemove = new();
_pvpRefs.First().Value.EndCombat(); foreach (var (_, combatRef) in _pvpRefs)
if (unitFilter == null || unitFilter(combatRef.GetOther(_owner)))
combatReferencesToRemove.Add(combatRef);
foreach (CombatReference combatRef in combatReferencesToRemove)
combatRef.EndCombat();
}
void EndAllCombat(Func<Unit, bool> unitFilter = null)
{
EndAllPvECombat(unitFilter);
EndAllPvPCombat(unitFilter);
} }
public static void NotifyAICombat(Unit me, Unit other) public static void NotifyAICombat(Unit me, Unit other)
+7 -5
View File
@@ -610,13 +610,15 @@ namespace Game.Combat
threatened.GetThreatManager().AddThreat(assistant, 0.0f, spell, true); threatened.GetThreatManager().AddThreat(assistant, 0.0f, spell, true);
} }
public void RemoveMeFromThreatLists() public void RemoveMeFromThreatLists(Func<Unit, bool> unitFilter)
{ {
while (!_threatenedByMe.Empty()) List<ThreatReference> threatReferencesToRemove = new();
{ foreach (var (_, refe) in _threatenedByMe)
var refe = _threatenedByMe.FirstOrDefault().Value; if (unitFilter == null || unitFilter(refe.GetOwner()))
threatReferencesToRemove.Add(refe);
foreach (ThreatReference refe in threatReferencesToRemove)
refe._mgr.ClearThreat(_owner); refe._mgr.ClearThreat(_owner);
}
} }
public void UpdateMyTempModifiers() public void UpdateMyTempModifiers()
@@ -3564,6 +3564,8 @@ namespace Game.Entities
public void SetNoSearchAssistance(bool val) { m_AlreadySearchedAssistance = val; } public void SetNoSearchAssistance(bool val) { m_AlreadySearchedAssistance = val; }
public bool HasSearchedAssistance() { return m_AlreadySearchedAssistance; } public bool HasSearchedAssistance() { return m_AlreadySearchedAssistance; }
public bool CanIgnoreFeignDeath() { return GetCreatureTemplate().FlagsExtra.HasFlag(CreatureFlagsExtra.IgnoreFeighDeath); } public bool CanIgnoreFeignDeath() { return GetCreatureTemplate().FlagsExtra.HasFlag(CreatureFlagsExtra.IgnoreFeighDeath); }
public bool IsIgnoringSanctuarySpellEffect() { return _staticFlags.HasFlag(CreatureStaticFlags2.IgnoreSanctuary); }
public void SetIngoreSanctuarySpellEffect(bool ignoreSanctuary) { _staticFlags.ApplyFlag(CreatureStaticFlags2.IgnoreSanctuary, ignoreSanctuary); }
public override MovementGeneratorType GetDefaultMovementType() { return DefaultMovementType; } public override MovementGeneratorType GetDefaultMovementType() { return DefaultMovementType; }
public void SetDefaultMovementType(MovementGeneratorType mgt) { DefaultMovementType = mgt; } public void SetDefaultMovementType(MovementGeneratorType mgt) { DefaultMovementType = mgt; }
+14 -8
View File
@@ -55,23 +55,29 @@ namespace Game.Entities
public virtual void AtDisengage() { } public virtual void AtDisengage() { }
public void CombatStop(bool includingCast = false, bool mutualPvP = true) public void CombatStop(bool includingCast = false, bool mutualPvP = true, Func<Unit, bool> unitFilter = null)
{ {
if (includingCast && IsNonMeleeSpellCast(false)) if (includingCast && IsNonMeleeSpellCast(false))
InterruptNonMeleeSpells(false); InterruptNonMeleeSpells(false);
AttackStop(); AttackStop();
RemoveAllAttackers(); if (unitFilter == null)
RemoveAllAttackers();
else
{
List<Unit> attackersToRemove = attackerList.Where(unitFilter).ToList();
foreach (Unit attacker in attackersToRemove)
attacker.AttackStop();
}
if (IsTypeId(TypeId.Player)) if (IsTypeId(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();
}
} }
public void CombatStopWithPets(bool includingCast = false) public void CombatStopWithPets(bool includingCast = false)
+10 -3
View File
@@ -2840,16 +2840,23 @@ namespace Game.Spells
if (unitTarget == null) if (unitTarget == null)
return; return;
var isAffectedBySanctuary = bool (Unit attacker) =>
{
Creature attackerCreature = attacker.ToCreature();
return attackerCreature == null || !attackerCreature.IsIgnoringSanctuarySpellEffect();
};
if (unitTarget.IsPlayer() && !unitTarget.GetMap().IsDungeon()) if (unitTarget.IsPlayer() && !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
foreach (var pair in unitTarget.GetThreatManager().GetThreatenedByMeList()) foreach (var (_, refe) in unitTarget.GetThreatManager().GetThreatenedByMeList())
pair.Value.ScaleThreat(0.0f); if (isAffectedBySanctuary(refe.GetOwner()))
refe.ScaleThreat(0.0f);
} }
// makes spells cast before this time fizzle // makes spells cast before this time fizzle