From 382b983820eb0c5a29a2b66524edbc9410391477 Mon Sep 17 00:00:00 2001 From: Hondacrx Date: Sun, 1 Sep 2024 17:25:52 -0400 Subject: [PATCH] Core/AreaTriggers: Added ActionSet flags for serverside areatriggers Port From (https://github.com/TrinityCore/TrinityCore/commit/1426f58ff007eac2d9719b41f9189d82b733789e) --- .../Framework/Constants/AchievementConst.cs | 4 +- Source/Framework/Constants/CliDBConst.cs | 12 ++-- Source/Game/Achievements/CriteriaHandler.cs | 14 ++++- .../DataStorage/AreaTriggerDataStorage.cs | 6 +- Source/Game/DataStorage/Structs/A_Records.cs | 2 +- .../Game/Entities/AreaTrigger/AreaTrigger.cs | 60 ++++++++++++++++++- .../AreaTrigger/AreaTriggerTemplate.cs | 2 + Source/Game/Handlers/MiscHandler.cs | 8 +++ Source/Game/Maps/GridNotifiers.cs | 15 +++-- 9 files changed, 101 insertions(+), 22 deletions(-) diff --git a/Source/Framework/Constants/AchievementConst.cs b/Source/Framework/Constants/AchievementConst.cs index 316077683..fa81a36b9 100644 --- a/Source/Framework/Constants/AchievementConst.cs +++ b/Source/Framework/Constants/AchievementConst.cs @@ -661,8 +661,8 @@ namespace Framework.Constants GroupedTankLeftEarlyInLFRDungeon = 150, /*NYI*/ // Grouped tank left early in an LFR dungeon CompleteAnyScenario = 151, // Complete a Scenario CompleteScenario = 152, // Complete scenario "{Scenario}" - EnterAreaTriggerWithActionSet = 153, /*NYI*/ // Enter area trigger "{AreaTriggerActionSet}" - LeaveAreaTriggerWithActionSet = 154, /*NYI*/ // Leave area trigger "{AreaTriggerActionSet}" + EnterAreaTriggerWithActionSet = 153, // Enter area trigger "{AreaTriggerActionSet}" + LeaveAreaTriggerWithActionSet = 154, // Leave area trigger "{AreaTriggerActionSet}" LearnedNewPet = 155, // (Account Only) Learned a new pet UniquePetsOwned = 156, // (Account Only) Unique pets owned AccountObtainPetThroughBattle = 157, /*NYI*/ // (Account Only) Obtain a pet through battle diff --git a/Source/Framework/Constants/CliDBConst.cs b/Source/Framework/Constants/CliDBConst.cs index 76547e02a..be002c428 100644 --- a/Source/Framework/Constants/CliDBConst.cs +++ b/Source/Framework/Constants/CliDBConst.cs @@ -957,19 +957,19 @@ namespace Framework.Constants { None = 0x00, OnlyTriggeredByCaster = 0x01, - ResurrectIfConditionFails = 0x02, + ResurrectIfConditionFails = 0x02, // NYI Obsolete = 0x04, AllowWhileGhost = 0x08, AllowWhileDead = 0x10, - UnifyAllInstances = 0x20, + UnifyAllInstances = 0x20, // NYI SuppressConditionError = 0x40, // NYI NotTriggeredbyCaster = 0x80, CreatorsPartyOnly = 0x100, - DontRunOnLeaveWhenExpiring = 0x200, + DontRunOnLeaveWhenExpiring = 0x200, // NYI CanAffectUninteractible = 0x400, - DontDespawnWithCreator = 0x800, - CanAffectBeastmaster = 0x1000, - RequiresLineOfSight = 0x2000 + DontDespawnWithCreator = 0x800, // NYI + CanAffectBeastmaster = 0x1000, // Can affect GMs + RequiresLineOfSight = 0x2000 // NYI } public enum AreaTriggerShapeType diff --git a/Source/Game/Achievements/CriteriaHandler.cs b/Source/Game/Achievements/CriteriaHandler.cs index e8c26803d..96ab573d8 100644 --- a/Source/Game/Achievements/CriteriaHandler.cs +++ b/Source/Game/Achievements/CriteriaHandler.cs @@ -262,6 +262,8 @@ namespace Game.Achievements case CriteriaType.GotHaircut: case CriteriaType.EquipItemInSlot: case CriteriaType.EquipItem: + case CriteriaType.EnterAreaTriggerWithActionSet: + case CriteriaType.LeaveAreaTriggerWithActionSet: case CriteriaType.LearnedNewPet: case CriteriaType.EnterArea: case CriteriaType.LeaveArea: @@ -420,7 +422,6 @@ namespace Game.Achievements case CriteriaType.KickTargetInLFGDungeon: case CriteriaType.AbandonedLFGDungeon: case CriteriaType.GroupedTankLeftEarlyInLFGDungeon: - case CriteriaType.EnterAreaTriggerWithActionSet: case CriteriaType.StartGarrisonMission: case CriteriaType.QualityUpgradedForGarrisonFollower: case CriteriaType.CompleteResearchGarrisonTalent: @@ -820,12 +821,14 @@ namespace Game.Achievements case CriteriaType.GotHaircut: case CriteriaType.EquipItemInSlot: case CriteriaType.EquipItem: + case CriteriaType.EnterAreaTriggerWithActionSet: + case CriteriaType.LeaveAreaTriggerWithActionSet: case CriteriaType.LearnedNewPet: - case CriteriaType.HonorLevelIncrease: - case CriteriaType.PrestigeLevelIncrease: case CriteriaType.EnterArea: case CriteriaType.LeaveArea: case CriteriaType.RecruitGarrisonFollower: + case CriteriaType.HonorLevelIncrease: + case CriteriaType.PrestigeLevelIncrease: case CriteriaType.ActivelyReachLevel: case CriteriaType.CollectTransmogSetFromGroup: case CriteriaType.EnterTopLevelArea: @@ -1219,6 +1222,11 @@ namespace Game.Achievements if (miscValue1 != criteria.Entry.Asset) return false; break; + case CriteriaType.EnterAreaTriggerWithActionSet: + case CriteriaType.LeaveAreaTriggerWithActionSet: + if (miscValue1 == 0 || miscValue1 != criteria.Entry.Asset) + return false; + break; default: break; } diff --git a/Source/Game/DataStorage/AreaTriggerDataStorage.cs b/Source/Game/DataStorage/AreaTriggerDataStorage.cs index f0eec3fed..f5ddb682b 100644 --- a/Source/Game/DataStorage/AreaTriggerDataStorage.cs +++ b/Source/Game/DataStorage/AreaTriggerDataStorage.cs @@ -104,8 +104,8 @@ namespace Game.DataStorage Log.outInfo(LogFilter.ServerLoading, "Loaded 0 AreaTrigger splines. DB table `areatrigger_create_properties_spline_point` is empty."); } - // 0 1 2 - SQLResult templates = DB.World.Query("SELECT Id, IsCustom, Flags FROM `areatrigger_template`"); + // 0 1 2 3 4 + SQLResult templates = DB.World.Query("SELECT Id, IsCustom, Flags, ActionSetId, ActionSetFlags FROM `areatrigger_template`"); if (!templates.IsEmpty()) { do @@ -113,6 +113,8 @@ namespace Game.DataStorage AreaTriggerTemplate areaTriggerTemplate = new(); areaTriggerTemplate.Id = new(templates.Read(0), templates.Read(1)); areaTriggerTemplate.Flags = (AreaTriggerFlag)templates.Read(2); + areaTriggerTemplate.ActionSetId = templates.Read(3); + areaTriggerTemplate.ActionSetFlags = (AreaTriggerActionSetFlag)templates.Read(4); areaTriggerTemplate.Actions = actionsByAreaTrigger[areaTriggerTemplate.Id]; _areaTriggerTemplateStore[areaTriggerTemplate.Id] = areaTriggerTemplate; diff --git a/Source/Game/DataStorage/Structs/A_Records.cs b/Source/Game/DataStorage/Structs/A_Records.cs index 45a9b2563..86452ef6b 100644 --- a/Source/Game/DataStorage/Structs/A_Records.cs +++ b/Source/Game/DataStorage/Structs/A_Records.cs @@ -156,7 +156,7 @@ namespace Game.DataStorage public float BoxYaw; public sbyte ShapeType; public short ShapeID; - public int AreaTriggerActionSetID; + public uint AreaTriggerActionSetID; public sbyte Flags; public AreaTriggerShapeType GetShapeType() { return (AreaTriggerShapeType)ShapeType; } diff --git a/Source/Game/Entities/AreaTrigger/AreaTrigger.cs b/Source/Game/Entities/AreaTrigger/AreaTrigger.cs index ea41b3277..29e89bd27 100644 --- a/Source/Game/Entities/AreaTrigger/AreaTrigger.cs +++ b/Source/Game/Entities/AreaTrigger/AreaTrigger.cs @@ -606,8 +606,55 @@ namespace Game.Entities if (GetTemplate() != null) { var conditions = Global.ConditionMgr.GetConditionsForAreaTrigger(GetTemplate().Id.Id, GetTemplate().Id.IsCustom); - if (conditions != null && !conditions.Empty()) - targetList.RemoveAll(target => !Global.ConditionMgr.IsObjectMeetToConditions(target, conditions)); + targetList.RemoveAll(target => + { + if (GetCasterGuid() == target.GetGUID()) + { + if (HasActionSetFlag(AreaTriggerActionSetFlag.NotTriggeredbyCaster)) + return true; + } + else + { + if (HasActionSetFlag(AreaTriggerActionSetFlag.OnlyTriggeredByCaster)) + return true; + + if (HasActionSetFlag(AreaTriggerActionSetFlag.CreatorsPartyOnly)) + { + Unit caster = GetCaster(); + if (caster == null) + return true; + + if (!caster.IsInRaidWith(target)) + return true; + } + } + + Player player = target.ToPlayer(); + if (player != null) + { + switch (player.GetDeathState()) + { + case DeathState.Dead: + if (!HasActionSetFlag(AreaTriggerActionSetFlag.AllowWhileGhost)) + return true; + break; + case DeathState.Corpse: + if (!HasActionSetFlag(AreaTriggerActionSetFlag.AllowWhileDead)) + return true; + break; + default: + break; + } + } + + if (!HasActionSetFlag(AreaTriggerActionSetFlag.CanAffectUninteractible) && target.IsUninteractible()) + return true; + + if (conditions != null) + return !Global.ConditionMgr.IsObjectMeetToConditions(target, conditions); + + return false; + }); } HandleUnitEnterExit(targetList); @@ -615,7 +662,7 @@ namespace Game.Entities void SearchUnits(List targetList, float radius, bool check3D) { - var check = new AnyUnitInObjectRangeCheck(this, radius, check3D); + var check = new AnyUnitInObjectRangeCheck(this, radius, check3D, false); if (IsStaticSpawn()) { List temp = new List(); @@ -770,6 +817,9 @@ namespace Game.Entities player.SendSysMessage(CypherStrings.DebugAreatriggerEntityEntered, GetEntry(), IsCustom(), IsStaticSpawn(), _spawnId); player.UpdateQuestObjectiveProgress(QuestObjectiveType.AreaTriggerEnter, (int)GetEntry(), 1); + + if (GetTemplate().ActionSetId != 0) + player.UpdateCriteria(CriteriaType.EnterAreaTriggerWithActionSet, GetTemplate().ActionSetId); } DoActions(unit); @@ -789,6 +839,9 @@ namespace Game.Entities player.SendSysMessage(CypherStrings.DebugAreatriggerEntityLeft, GetEntry(), IsCustom(), IsStaticSpawn(), _spawnId); player.UpdateQuestObjectiveProgress(QuestObjectiveType.AreaTriggerExit, (int)GetEntry(), 1); + + if (GetTemplate().ActionSetId != 0) + player.UpdateCriteria(CriteriaType.LeaveAreaTriggerWithActionSet, GetTemplate().ActionSetId); } UndoActions(leavingUnit); @@ -1344,6 +1397,7 @@ namespace Game.Entities public bool IsCustom() { return _areaTriggerTemplate.Id.IsCustom; } public bool IsServerSide() { return _areaTriggerTemplate.Flags.HasFlag(AreaTriggerFlag.IsServerSide); } public bool IsStaticSpawn() { return _spawnId != 0; } + public bool HasActionSetFlag(AreaTriggerActionSetFlag flag) { return _areaTriggerTemplate.ActionSetFlags.HasFlag(flag); } [System.Diagnostics.Conditional("DEBUG")] void DebugVisualizePosition() diff --git a/Source/Game/Entities/AreaTrigger/AreaTriggerTemplate.cs b/Source/Game/Entities/AreaTrigger/AreaTriggerTemplate.cs index 55523e941..e07bf58ef 100644 --- a/Source/Game/Entities/AreaTrigger/AreaTriggerTemplate.cs +++ b/Source/Game/Entities/AreaTrigger/AreaTriggerTemplate.cs @@ -243,6 +243,8 @@ namespace Game.Entities { public AreaTriggerId Id; public AreaTriggerFlag Flags; + public uint ActionSetId; + public AreaTriggerActionSetFlag ActionSetFlags; public List Actions = new(); } diff --git a/Source/Game/Handlers/MiscHandler.cs b/Source/Game/Handlers/MiscHandler.cs index 77e9df631..89eb61918 100644 --- a/Source/Game/Handlers/MiscHandler.cs +++ b/Source/Game/Handlers/MiscHandler.cs @@ -187,6 +187,14 @@ namespace Game if (Global.ScriptMgr.OnAreaTrigger(player, atEntry, packet.Entered)) return; + if (atEntry.AreaTriggerActionSetID != 0) + { + if (packet.Entered) + player.UpdateCriteria(CriteriaType.EnterAreaTriggerWithActionSet, atEntry.AreaTriggerActionSetID); + else + player.UpdateCriteria(CriteriaType.LeaveAreaTriggerWithActionSet, atEntry.AreaTriggerActionSetID); + } + if (player.IsAlive() && packet.Entered) { // not using Player.UpdateQuestObjectiveProgress, ObjectID in quest_objectives can be set to -1, areatrigger_involvedrelation then holds correct id diff --git a/Source/Game/Maps/GridNotifiers.cs b/Source/Game/Maps/GridNotifiers.cs index c007e16bc..963fbecd4 100644 --- a/Source/Game/Maps/GridNotifiers.cs +++ b/Source/Game/Maps/GridNotifiers.cs @@ -2130,17 +2130,21 @@ namespace Game.Maps public class AnyUnitInObjectRangeCheck : ICheck { - public AnyUnitInObjectRangeCheck(WorldObject obj, float range, bool check3D = true) + public AnyUnitInObjectRangeCheck(WorldObject obj, float range, bool check3D = true, bool reqAlive = true) { i_obj = obj; i_range = range; i_check3D = check3D; + i_reqAlive = reqAlive; } public bool Invoke(Unit u) { - if (u.IsAlive() && i_obj.IsWithinDist(u, i_range, i_check3D)) - return true; + if (i_reqAlive && !u.IsAlive()) + return false; + + if (!i_obj.IsWithinDist(u, i_range, i_check3D)) + return false; return false; } @@ -2148,6 +2152,7 @@ namespace Game.Maps WorldObject i_obj; float i_range; bool i_check3D; + bool i_reqAlive; } // Success at unit in range, range update for next check (this can be use with UnitLastSearcher to find nearest unit) @@ -2543,7 +2548,7 @@ namespace Game.Maps return true; } } - + public class AnyPlayerInObjectRangeCheck : ICheck { public AnyPlayerInObjectRangeCheck(WorldObject obj, float range, bool reqAlive = true) @@ -3035,7 +3040,7 @@ namespace Game.Maps i_range = i_obj.GetDistance(obj); } } - + public class AnyDeadUnitObjectInRangeCheck : ICheck where T : WorldObject { public AnyDeadUnitObjectInRangeCheck(WorldObject searchObj, float range)