diff --git a/Source/Framework/Constants/AreaTriggerConst.cs b/Source/Framework/Constants/AreaTriggerConst.cs index 1bae22981..7224eb065 100644 --- a/Source/Framework/Constants/AreaTriggerConst.cs +++ b/Source/Framework/Constants/AreaTriggerConst.cs @@ -70,4 +70,10 @@ namespace Framework.Constants None = 2, MovementScript = 3 } + + public enum AreaTriggerExitReason + { + NotInside = 0, // Unit leave areatrigger + ByExpire = 1 // On areatrigger despawn + } } diff --git a/Source/Framework/Constants/CliDBConst.cs b/Source/Framework/Constants/CliDBConst.cs index d436d4b7e..c33083465 100644 --- a/Source/Framework/Constants/CliDBConst.cs +++ b/Source/Framework/Constants/CliDBConst.cs @@ -967,7 +967,7 @@ namespace Framework.Constants SuppressConditionError = 0x40, // NYI NotTriggeredbyCaster = 0x80, CreatorsPartyOnly = 0x100, - DontRunOnLeaveWhenExpiring = 0x200, // NYI + DontRunOnLeaveWhenExpiring = 0x200, CanAffectUninteractible = 0x400, DontDespawnWithCreator = 0x800, // NYI CanAffectBeastmaster = 0x1000, // Can affect GMs diff --git a/Source/Game/AI/CoreAI/AreaTriggerAI.cs b/Source/Game/AI/CoreAI/AreaTriggerAI.cs index 5e54eacfd..4d1f51750 100644 --- a/Source/Game/AI/CoreAI/AreaTriggerAI.cs +++ b/Source/Game/AI/CoreAI/AreaTriggerAI.cs @@ -1,6 +1,7 @@ // Copyright (c) CypherCore All rights reserved. // Licensed under the GNU GENERAL PUBLIC LICENSE. See LICENSE file in the project root for full license information. +using Framework.Constants; using Game.Entities; using Game.Spells; @@ -34,7 +35,7 @@ namespace Game.AI public virtual void OnUnitEnter(Unit unit) { } // Called when an unit exit the AreaTrigger, or when the AreaTrigger is removed - public virtual void OnUnitExit(Unit unit) { } + public virtual void OnUnitExit(Unit unit, AreaTriggerExitReason reason) { } // Called when the AreaTrigger is removed public virtual void OnRemove() { } diff --git a/Source/Game/AI/SmartScripts/SmartAI.cs b/Source/Game/AI/SmartScripts/SmartAI.cs index 004860a95..32a2a091d 100644 --- a/Source/Game/AI/SmartScripts/SmartAI.cs +++ b/Source/Game/AI/SmartScripts/SmartAI.cs @@ -1200,7 +1200,7 @@ namespace Game.AI GetScript().ProcessEventsFor(SmartEvents.AreatriggerEnter, unit); } - public override void OnUnitExit(Unit unit) + public override void OnUnitExit(Unit unit, AreaTriggerExitReason reason) { GetScript().ProcessEventsFor(SmartEvents.AreatriggerExit, unit); } diff --git a/Source/Game/Entities/AreaTrigger/AreaTrigger.cs b/Source/Game/Entities/AreaTrigger/AreaTrigger.cs index d3979b6b8..510813125 100644 --- a/Source/Game/Entities/AreaTrigger/AreaTrigger.cs +++ b/Source/Game/Entities/AreaTrigger/AreaTrigger.cs @@ -67,7 +67,7 @@ namespace Game.Entities _ai.OnRemove(); // Handle removal of all units, calling OnUnitExit & deleting auras if needed - HandleUnitEnterExit(new List()); + HandleUnitEnterExit(new List(), AreaTriggerExitReason.ByExpire); base.RemoveFromWorld(); if (IsStaticSpawn()) @@ -809,7 +809,7 @@ namespace Game.Entities } } - void HandleUnitEnterExit(List newTargetList) + void HandleUnitEnterExit(List newTargetList, AreaTriggerExitReason exitMode = AreaTriggerExitReason.NotInside) { List exitUnits = _insideUnits; _insideUnits.Clear(); @@ -832,7 +832,7 @@ namespace Game.Entities { Unit leavingUnit = Global.ObjAccessor.GetUnit(this, exitUnitGuid); if (leavingUnit != null) - HandleUnitExitInternal(leavingUnit); + HandleUnitExitInternal(leavingUnit, exitMode); } UpdateHasPlayersFlag(); @@ -861,23 +861,30 @@ namespace Game.Entities unit.EnterAreaTrigger(this); } - void HandleUnitExitInternal(Unit unit) + void HandleUnitExitInternal(Unit unit, AreaTriggerExitReason exitMode = AreaTriggerExitReason.NotInside) { + bool canTriggerOnExit = exitMode != AreaTriggerExitReason.ByExpire || !HasActionSetFlag(AreaTriggerActionSetFlag.DontRunOnLeaveWhenExpiring); + Player player = unit.ToPlayer(); if (player != null) { if (player.IsDebugAreaTriggers) player.SendSysMessage(CypherStrings.DebugAreatriggerEntityLeft, GetEntry(), IsCustom(), IsStaticSpawn(), _spawnId); - player.UpdateQuestObjectiveProgress(QuestObjectiveType.AreaTriggerExit, (int)GetEntry(), 1); + if (canTriggerOnExit) + { + player.UpdateQuestObjectiveProgress(QuestObjectiveType.AreaTriggerExit, (int)GetEntry(), 1); - if (GetTemplate().ActionSetId != 0) - player.UpdateCriteria(CriteriaType.LeaveAreaTriggerWithActionSet, GetTemplate().ActionSetId); + if (GetTemplate().ActionSetId != 0) + player.UpdateCriteria(CriteriaType.LeaveAreaTriggerWithActionSet, GetTemplate().ActionSetId); + } } UndoActions(unit); - _ai.OnUnitExit(unit); + if (canTriggerOnExit) + _ai.OnUnitExit(unit, exitMode); + unit.ExitAreaTrigger(this); } diff --git a/Source/Scripts/Spells/DeathKnight.cs b/Source/Scripts/Spells/DeathKnight.cs index ca04dc4fa..c2738807b 100644 --- a/Source/Scripts/Spells/DeathKnight.cs +++ b/Source/Scripts/Spells/DeathKnight.cs @@ -1376,7 +1376,7 @@ class at_dk_death_and_decay(AreaTrigger areaTrigger) : AreaTriggerAI(areaTrigger unit.CastSpell(unit, SpellIds.SanguineGround); } - public override void OnUnitExit(Unit unit) + public override void OnUnitExit(Unit unit, AreaTriggerExitReason reason) { if (unit.GetGUID() != at.GetCasterGUID()) return; diff --git a/Source/Scripts/Spells/DemonHunter.cs b/Source/Scripts/Spells/DemonHunter.cs index fc96ccdf9..bc9fc45a0 100644 --- a/Source/Scripts/Spells/DemonHunter.cs +++ b/Source/Scripts/Spells/DemonHunter.cs @@ -736,7 +736,7 @@ class areatrigger_dh_darkness : AreaTriggerAI }); } - public override void OnUnitExit(Unit unit) + public override void OnUnitExit(Unit unit, AreaTriggerExitReason reason) { unit.RemoveAura(SpellIds.DarknessAbsorb, at.GetCasterGUID()); } diff --git a/Source/Scripts/Spells/Hunter.cs b/Source/Scripts/Spells/Hunter.cs index 9cde984b2..d3a1f5b13 100644 --- a/Source/Scripts/Spells/Hunter.cs +++ b/Source/Scripts/Spells/Hunter.cs @@ -263,7 +263,7 @@ class at_hun_binding_shot(AreaTrigger areaTrigger) : AreaTriggerAI(areaTrigger) } } - public override void OnUnitExit(Unit unit) + public override void OnUnitExit(Unit unit, AreaTriggerExitReason reason) { unit.RemoveAurasDueToSpell(SpellIds.BindingShotMarker, at.GetCasterGUID()); @@ -1322,7 +1322,7 @@ class areatrigger_hun_tar_trap(AreaTrigger areaTrigger) : AreaTriggerAI(areaTrig } } - public override void OnUnitExit(Unit unit) + public override void OnUnitExit(Unit unit, AreaTriggerExitReason reason) { unit.RemoveAurasDueToSpell(SpellIds.TarTrapSlow, at.GetCasterGUID()); } diff --git a/Source/Scripts/Spells/Mage.cs b/Source/Scripts/Spells/Mage.cs index c8042e01a..aa3447044 100644 --- a/Source/Scripts/Spells/Mage.cs +++ b/Source/Scripts/Spells/Mage.cs @@ -1501,7 +1501,7 @@ class at_mage_meteor_burn(AreaTrigger areaTrigger) : AreaTriggerAI(areaTrigger) caster.CastSpell(unit, SpellIds.MeteorBurnDamage, TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError); } - public override void OnUnitExit(Unit unit) + public override void OnUnitExit(Unit unit, AreaTriggerExitReason reason) { unit.RemoveAurasDueToSpell(SpellIds.MeteorBurnDamage, at.GetCasterGUID()); } diff --git a/Source/Scripts/Spells/Paladin.cs b/Source/Scripts/Spells/Paladin.cs index fbc1daa56..3b57ec182 100644 --- a/Source/Scripts/Spells/Paladin.cs +++ b/Source/Scripts/Spells/Paladin.cs @@ -248,7 +248,7 @@ class areatrigger_pal_ashen_hallow(AreaTrigger areaTrigger) : AreaTriggerAI(area unit.CastSpell(unit, SpellIds.AshenHallowAllowHammer, true); } - public override void OnUnitExit(Unit unit) + public override void OnUnitExit(Unit unit, AreaTriggerExitReason reason) { if (unit.GetGUID() == at.GetCasterGUID()) unit.RemoveAura(SpellIds.AshenHallowAllowHammer); @@ -429,7 +429,7 @@ class areatrigger_pal_consecration(AreaTrigger areaTrigger) : AreaTriggerAI(area } } - public override void OnUnitExit(Unit unit) + public override void OnUnitExit(Unit unit, AreaTriggerExitReason reason) { if (at.GetCasterGUID() == unit.GetGUID()) unit.RemoveAurasDueToSpell(SpellIds.ConsecrationProtectionAura, at.GetCasterGUID()); diff --git a/Source/Scripts/Spells/Priest.cs b/Source/Scripts/Spells/Priest.cs index 9c4db0d13..6c6fd0a85 100644 --- a/Source/Scripts/Spells/Priest.cs +++ b/Source/Scripts/Spells/Priest.cs @@ -1054,7 +1054,7 @@ class areatrigger_pri_divine_star(AreaTrigger areaTrigger) : AreaTriggerAI(areaT HandleUnitEnterExit(unit); } - public override void OnUnitExit(Unit unit) + public override void OnUnitExit(Unit unit, AreaTriggerExitReason reason) { // Note: this ensures any unit receives a second hit if they happen to be inside the At when Divine Star starts its return path. HandleUnitEnterExit(unit); diff --git a/Source/Scripts/Spells/Shaman.cs b/Source/Scripts/Spells/Shaman.cs index afa4075a3..4fc1bb346 100644 --- a/Source/Scripts/Spells/Shaman.cs +++ b/Source/Scripts/Spells/Shaman.cs @@ -3428,7 +3428,7 @@ class areatrigger_sha_arctic_snowstorm(AreaTrigger areaTrigger) : AreaTriggerAI( } } - public override void OnUnitExit(Unit unit) + public override void OnUnitExit(Unit unit, AreaTriggerExitReason reason) { unit.RemoveAurasDueToSpell(SpellIds.ArcticSnowstormSlow, at.GetCasterGUID()); }