diff --git a/Source/Framework/Constants/AreaTriggerConst.cs b/Source/Framework/Constants/AreaTriggerConst.cs index 42721e249..61d6c7f9c 100644 --- a/Source/Framework/Constants/AreaTriggerConst.cs +++ b/Source/Framework/Constants/AreaTriggerConst.cs @@ -9,18 +9,6 @@ namespace Framework.Constants IsServerSide = 0x01 } - public enum AreaTriggerShapeType - { - Sphere = 0, - Box = 1, - Unk = 2, - Polygon = 3, - Cylinder = 4, - Disk = 5, - BoundedPlane = 6, - Max - } - public enum AreaTriggerActionTypes { Cast = 0, diff --git a/Source/Framework/Constants/CliDBConst.cs b/Source/Framework/Constants/CliDBConst.cs index 9bb52e7c9..76547e02a 100644 --- a/Source/Framework/Constants/CliDBConst.cs +++ b/Source/Framework/Constants/CliDBConst.cs @@ -952,6 +952,38 @@ namespace Framework.Constants ClientEnforcesMount = 0x10 } + [Flags] + public enum AreaTriggerActionSetFlag + { + None = 0x00, + OnlyTriggeredByCaster = 0x01, + ResurrectIfConditionFails = 0x02, + Obsolete = 0x04, + AllowWhileGhost = 0x08, + AllowWhileDead = 0x10, + UnifyAllInstances = 0x20, + SuppressConditionError = 0x40, // NYI + NotTriggeredbyCaster = 0x80, + CreatorsPartyOnly = 0x100, + DontRunOnLeaveWhenExpiring = 0x200, + CanAffectUninteractible = 0x400, + DontDespawnWithCreator = 0x800, + CanAffectBeastmaster = 0x1000, + RequiresLineOfSight = 0x2000 + } + + public enum AreaTriggerShapeType + { + Sphere = 0, + Box = 1, + Unk = 2, + Polygon = 3, + Cylinder = 4, + Disk = 5, + BoundedPlane = 6, + Max + } + public enum ArtifactCategory { Primary = 1, diff --git a/Source/Framework/Database/Databases/HotfixDatabase.cs b/Source/Framework/Database/Databases/HotfixDatabase.cs index 3bc39a75f..08aba4e5c 100644 --- a/Source/Framework/Database/Databases/HotfixDatabase.cs +++ b/Source/Framework/Database/Databases/HotfixDatabase.cs @@ -55,6 +55,9 @@ namespace Framework.Database PrepareStatement(HotfixStatements.SEL_AREA_TRIGGER, "SELECT PosX, PosY, PosZ, ID, ContinentID, PhaseUseFlags, PhaseID, PhaseGroupID, Radius, BoxLength, " + "BoxWidth, BoxHeight, BoxYaw, ShapeType, ShapeID, AreaTriggerActionSetID, Flags FROM area_trigger WHERE (`VerifiedBuild` > 0) = ?"); + // AreaTriggerActionSet.db2 + PrepareStatement(HotfixStatements.SEL_AREA_TRIGGER_ACTION_SET, "SELECT ID, Flags FROM area_trigger_action_set WHERE (`VerifiedBuild` > 0) = ?"); + // ArmorLocation.db2 PrepareStatement(HotfixStatements.SEL_ARMOR_LOCATION, "SELECT ID, Clothmodifier, Leathermodifier, Chainmodifier, Platemodifier, Modifier FROM armor_location" + " WHERE (`VerifiedBuild` > 0) = ?"); @@ -1642,6 +1645,8 @@ namespace Framework.Database SEL_AREA_TRIGGER, + SEL_AREA_TRIGGER_ACTION_SET, + SEL_ARMOR_LOCATION, SEL_ARTIFACT, diff --git a/Source/Game/DataStorage/CliDB.cs b/Source/Game/DataStorage/CliDB.cs index fc88686a6..6ecf5c1ea 100644 --- a/Source/Game/DataStorage/CliDB.cs +++ b/Source/Game/DataStorage/CliDB.cs @@ -57,6 +57,7 @@ namespace Game.DataStorage AreaGroupMemberStorage = ReadDB2("AreaGroupMember.db2", HotfixStatements.SEL_AREA_GROUP_MEMBER); AreaTableStorage = ReadDB2("AreaTable.db2", HotfixStatements.SEL_AREA_TABLE, HotfixStatements.SEL_AREA_TABLE_LOCALE); AreaTriggerStorage = ReadDB2("AreaTrigger.db2", HotfixStatements.SEL_AREA_TRIGGER); + AreaTriggerActionSetStorage = ReadDB2("AreaTriggerActionSet.db2", HotfixStatements.SEL_AREA_TRIGGER_ACTION_SET); ArmorLocationStorage = ReadDB2("ArmorLocation.db2", HotfixStatements.SEL_ARMOR_LOCATION); ArtifactStorage = ReadDB2("Artifact.db2", HotfixStatements.SEL_ARTIFACT, HotfixStatements.SEL_ARTIFACT_APPEARANCE_LOCALE); ArtifactAppearanceStorage = ReadDB2("ArtifactAppearance.db2", HotfixStatements.SEL_ARTIFACT_APPEARANCE, HotfixStatements.SEL_ARTIFACT_APPEARANCE_LOCALE); @@ -501,6 +502,7 @@ namespace Game.DataStorage public static DB6Storage AreaGroupMemberStorage; public static DB6Storage AreaTableStorage; public static DB6Storage AreaTriggerStorage; + public static DB6Storage AreaTriggerActionSetStorage; public static DB6Storage ArmorLocationStorage; public static DB6Storage ArtifactStorage; public static DB6Storage ArtifactAppearanceStorage; diff --git a/Source/Game/DataStorage/Structs/A_Records.cs b/Source/Game/DataStorage/Structs/A_Records.cs index 48fc2281e..45a9b2563 100644 --- a/Source/Game/DataStorage/Structs/A_Records.cs +++ b/Source/Game/DataStorage/Structs/A_Records.cs @@ -158,6 +158,16 @@ namespace Game.DataStorage public short ShapeID; public int AreaTriggerActionSetID; public sbyte Flags; + + public AreaTriggerShapeType GetShapeType() { return (AreaTriggerShapeType)ShapeType; } + } + + public sealed class AreaTriggerActionSetRecord + { + public uint Id; + public int Flags; + + public AreaTriggerActionSetFlag GetFlags() { return (AreaTriggerActionSetFlag)Flags; } } public sealed class ArmorLocationRecord diff --git a/Source/Game/Entities/Player/Player.cs b/Source/Game/Entities/Player/Player.cs index 9244fb3b2..b05dcbb66 100644 --- a/Source/Game/Entities/Player/Player.cs +++ b/Source/Game/Entities/Player/Player.cs @@ -2437,23 +2437,46 @@ namespace Game.Entities if (!PhasingHandler.InDbPhaseShift(this, (PhaseUseFlagsValues)areaTrigger.PhaseUseFlags, areaTrigger.PhaseID, areaTrigger.PhaseGroupID)) return false; - Position areaTriggerPos = new(areaTrigger.Pos.X, areaTrigger.Pos.Y, areaTrigger.Pos.Z, areaTrigger.BoxYaw); - switch (areaTrigger.ShapeType) + bool hasActionSetFlag(AreaTriggerActionSetFlag flag) { - case 0: // Sphere + var areaTriggerActionSet = CliDB.AreaTriggerActionSetStorage.LookupByKey(areaTrigger.AreaTriggerActionSetID); + if (areaTriggerActionSet != null) + return areaTriggerActionSet.GetFlags().HasFlag(flag); + + return false; + } + + switch (GetDeathState()) + { + case DeathState.Dead: + if (!hasActionSetFlag(AreaTriggerActionSetFlag.AllowWhileGhost)) + return false; + break; + case DeathState.Corpse: + if (!hasActionSetFlag(AreaTriggerActionSetFlag.AllowWhileDead)) + return false; + break; + default: + break; + } + + Position areaTriggerPos = new(areaTrigger.Pos.X, areaTrigger.Pos.Y, areaTrigger.Pos.Z, areaTrigger.BoxYaw); + switch (areaTrigger.GetShapeType()) + { + case AreaTriggerShapeType.Sphere: if (!IsInDist(areaTriggerPos, areaTrigger.Radius)) return false; break; - case 1: // Box + case AreaTriggerShapeType.Box: if (!IsWithinBox(areaTriggerPos, areaTrigger.BoxLength / 2.0f, areaTrigger.BoxWidth / 2.0f, areaTrigger.BoxHeight / 2.0f)) return false; break; - case 3: // Polygon + case AreaTriggerShapeType.Polygon: var polygon = ObjectMgr.GetAreaTriggerPolygon(areaTrigger.Id); if (polygon == null || (polygon.Height.HasValue && GetPositionZ() > areaTrigger.Pos.Z + polygon.Height) || !IsInPolygon2D(areaTriggerPos, polygon.Vertices)) return false; break; - case 4: // Cylinder + case AreaTriggerShapeType.Cylinder: if (!IsWithinVerticalCylinder(areaTriggerPos, areaTrigger.Radius, areaTrigger.BoxHeight)) return false; break; diff --git a/Source/Game/Globals/ObjectManager.cs b/Source/Game/Globals/ObjectManager.cs index e79b5205e..55c965747 100644 --- a/Source/Game/Globals/ObjectManager.cs +++ b/Source/Game/Globals/ObjectManager.cs @@ -5470,7 +5470,7 @@ namespace Game { foreach (var (_, areaTrigger) in CliDB.AreaTriggerStorage) { - if (areaTrigger.ShapeType != 3) + if (areaTrigger.GetShapeType() != AreaTriggerShapeType.Polygon) continue; PathDb2 path = Global.DB2Mgr.GetPath((uint)areaTrigger.ShapeID);