Skip to content

Commit

Permalink
Core/AreaTriggers: Check actionset flags for client areatriggers to a…
Browse files Browse the repository at this point in the history
…llow some areatriggers to trigger while dead (TrinityCore#30042)
  • Loading branch information
meji46 authored Jun 23, 2024
1 parent 31bd380 commit d51d6b0
Show file tree
Hide file tree
Showing 11 changed files with 98 additions and 18 deletions.
7 changes: 7 additions & 0 deletions sql/updates/hotfixes/master/2024_06_23_00_hotfixes.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
DROP TABLE IF EXISTS `area_trigger_action_set`;
CREATE TABLE `area_trigger_action_set` (
`ID` int unsigned NOT NULL DEFAULT '0',
`Flags` int NOT NULL DEFAULT '0',
`VerifiedBuild` int NOT NULL DEFAULT '0',
PRIMARY KEY (`ID`,`VerifiedBuild`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,10 @@ void HotfixDatabaseConnection::DoPrepareStatements()
"BoxWidth, BoxHeight, BoxYaw, ShapeType, ShapeID, AreaTriggerActionSetID, Flags FROM area_trigger WHERE (`VerifiedBuild` > 0) = ?", CONNECTION_SYNCH);
PREPARE_MAX_ID_STMT(HOTFIX_SEL_AREA_TRIGGER, "SELECT MAX(ID) + 1 FROM area_trigger", CONNECTION_SYNCH);

// AreaTriggerActionSet.db2
PrepareStatement(HOTFIX_SEL_AREA_TRIGGER_ACTION_SET, "SELECT ID, Flags FROM area_trigger_action_set WHERE (`VerifiedBuild` > 0) = ?", CONNECTION_SYNCH);
PREPARE_MAX_ID_STMT(HOTFIX_SEL_AREA_TRIGGER_ACTION_SET, "SELECT MAX(ID) + 1 FROM area_trigger_action_set", CONNECTION_SYNCH);

// ArmorLocation.db2
PrepareStatement(HOTFIX_SEL_ARMOR_LOCATION, "SELECT ID, Clothmodifier, Leathermodifier, Chainmodifier, Platemodifier, Modifier FROM armor_location"
" WHERE (`VerifiedBuild` > 0) = ?", CONNECTION_SYNCH);
Expand Down
3 changes: 3 additions & 0 deletions src/server/database/Database/Implementation/HotfixDatabase.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ enum HotfixDatabaseStatements : uint32
HOTFIX_SEL_AREA_TRIGGER,
HOTFIX_SEL_AREA_TRIGGER_MAX_ID,

HOTFIX_SEL_AREA_TRIGGER_ACTION_SET,
HOTFIX_SEL_AREA_TRIGGER_ACTION_SET_MAX_ID,

HOTFIX_SEL_ARMOR_LOCATION,
HOTFIX_SEL_ARMOR_LOCATION_MAX_ID,

Expand Down
11 changes: 11 additions & 0 deletions src/server/game/DataStores/DB2LoadInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,17 @@ struct AreaTriggerLoadInfo
static constexpr DB2LoadInfo Instance{ Fields, 17, &AreaTriggerMeta::Instance, HOTFIX_SEL_AREA_TRIGGER };
};

struct AreaTriggerActionSetLoadInfo
{
static constexpr DB2FieldMeta Fields[2] =
{
{ false, FT_INT, "ID" },
{ true, FT_INT, "Flags" },
};

static constexpr DB2LoadInfo Instance{ Fields, 2, &AreaTriggerActionSetMeta::Instance, HOTFIX_SEL_AREA_TRIGGER_ACTION_SET };
};

struct ArmorLocationLoadInfo
{
static constexpr DB2FieldMeta Fields[6] =
Expand Down
2 changes: 2 additions & 0 deletions src/server/game/DataStores/DB2Stores.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ DB2Storage<AnimKitEntry> sAnimKitStore("AnimKit.db2", &An
DB2Storage<AreaGroupMemberEntry> sAreaGroupMemberStore("AreaGroupMember.db2", &AreaGroupMemberLoadInfo::Instance);
DB2Storage<AreaTableEntry> sAreaTableStore("AreaTable.db2", &AreaTableLoadInfo::Instance);
DB2Storage<AreaTriggerEntry> sAreaTriggerStore("AreaTrigger.db2", &AreaTriggerLoadInfo::Instance);
DB2Storage<AreaTriggerActionSetEntry> sAreaTriggerActionSetStore("AreaTriggerActionSet.db2", &AreaTriggerActionSetLoadInfo::Instance);
DB2Storage<ArmorLocationEntry> sArmorLocationStore("ArmorLocation.db2", &ArmorLocationLoadInfo::Instance);
DB2Storage<ArtifactEntry> sArtifactStore("Artifact.db2", &ArtifactLoadInfo::Instance);
DB2Storage<ArtifactAppearanceEntry> sArtifactAppearanceStore("ArtifactAppearance.db2", &ArtifactAppearanceLoadInfo::Instance);
Expand Down Expand Up @@ -660,6 +661,7 @@ uint32 DB2Manager::LoadStores(std::string const& dataPath, LocaleConstant defaul
LOAD_DB2(sAreaGroupMemberStore);
LOAD_DB2(sAreaTableStore);
LOAD_DB2(sAreaTriggerStore);
LOAD_DB2(sAreaTriggerActionSetStore);
LOAD_DB2(sArmorLocationStore);
LOAD_DB2(sArtifactStore);
LOAD_DB2(sArtifactAppearanceStore);
Expand Down
1 change: 1 addition & 0 deletions src/server/game/DataStores/DB2Stores.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ TC_GAME_API extern DB2Storage<AnimationDataEntry> sAnimationDa
TC_GAME_API extern DB2Storage<AnimKitEntry> sAnimKitStore;
TC_GAME_API extern DB2Storage<AreaTableEntry> sAreaTableStore;
TC_GAME_API extern DB2Storage<AreaTriggerEntry> sAreaTriggerStore;
TC_GAME_API extern DB2Storage<AreaTriggerActionSetEntry> sAreaTriggerActionSetStore;
TC_GAME_API extern DB2Storage<ArmorLocationEntry> sArmorLocationStore;
TC_GAME_API extern DB2Storage<ArtifactEntry> sArtifactStore;
TC_GAME_API extern DB2Storage<ArtifactCategoryEntry> sArtifactCategoryStore;
Expand Down
10 changes: 10 additions & 0 deletions src/server/game/DataStores/DB2Structure.h
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,16 @@ struct AreaTriggerEntry
int16 ShapeID;
int32 AreaTriggerActionSetID;
int8 Flags;

AreaTriggerShapeType GetShapeType() const { return static_cast<AreaTriggerShapeType>(ShapeType); }
};

struct AreaTriggerActionSetEntry
{
uint32 ID;
int32 Flags;

EnumFlag<AreaTriggerActionSetFlag> GetFlags() const { return static_cast<AreaTriggerActionSetFlag>(Flags); }
};

struct ArmorLocationEntry
Expand Down
33 changes: 33 additions & 0 deletions src/server/game/DataStores/DBCEnums.h
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,39 @@ enum class AreaMountFlags : uint8

DEFINE_ENUM_FLAG(AreaMountFlags);

enum class AreaTriggerActionSetFlag : uint32
{
None = 0x0000,
OnlyTriggeredByCaster = 0x0001,
ResurrectIfConditionFails = 0x0002,
Obsolete = 0x0004,
AllowWhileGhost = 0x0008,
AllowWhileDead = 0x0010,
UnifyAllInstances = 0x0020,
SuppressConditionError = 0x0040, // NYI
NotTriggeredbyCaster = 0x0080,
CreatorsPartyOnly = 0x0100,
DontRunOnLeaveWhenExpiring = 0x0200,
CanAffectUninteractible = 0x0400,
DontDespawnWithCreator = 0x0800,
CanAffectBeastmaster = 0x1000,
RequiresLineOfSight = 0x2000
};

DEFINE_ENUM_FLAG(AreaTriggerActionSetFlag);

enum class AreaTriggerShapeType : int8
{
Sphere = 0,
Box = 1,
Unk = 2,
Polygon = 3,
Cylinder = 4,
Disk = 5,
BoundedPlane = 6,
Max
};

enum ArtifactCategory : uint32
{
ARTIFACT_CATEGORY_PRIMARY = 1,
Expand Down
12 changes: 0 additions & 12 deletions src/server/game/Entities/AreaTrigger/AreaTriggerTemplate.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,18 +37,6 @@ enum class AreaTriggerFlag : uint32

DEFINE_ENUM_FLAG(AreaTriggerFlag);

enum class AreaTriggerShapeType : uint8
{
Sphere = 0,
Box = 1,
Unk = 2,
Polygon = 3,
Cylinder = 4,
Disk = 5,
BoundedPlane = 6,
Max
};

enum AreaTriggerActionTypes
{
AREATRIGGER_ACTION_CAST = 0,
Expand Down
31 changes: 26 additions & 5 deletions src/server/game/Entities/Player/Player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2028,25 +2028,46 @@ bool Player::IsInAreaTrigger(AreaTriggerEntry const* areaTrigger) const
if (!PhasingHandler::InDbPhaseShift(this, areaTrigger->PhaseUseFlags, areaTrigger->PhaseID, areaTrigger->PhaseGroupID))
return false;

auto hasActionSetFlag = [=](AreaTriggerActionSetFlag flag)
{
if (AreaTriggerActionSetEntry const* areaTriggerActionSet = sAreaTriggerActionSetStore.LookupEntry(areaTrigger->AreaTriggerActionSetID))
return areaTriggerActionSet->GetFlags().HasFlag(flag);
return false;
};

switch (getDeathState())
{
case DEAD:
if (!hasActionSetFlag(AreaTriggerActionSetFlag::AllowWhileGhost))
return false;
break;
case CORPSE:
if (!hasActionSetFlag(AreaTriggerActionSetFlag::AllowWhileDead))
return false;
break;
default:
break;
}

Position areaTriggerPos(areaTrigger->Pos.X, areaTrigger->Pos.Y, areaTrigger->Pos.Z, areaTrigger->BoxYaw);
switch (areaTrigger->ShapeType)
switch (areaTrigger->GetShapeType())
{
case 0: // Sphere
case AreaTriggerShapeType::Sphere:
if (!IsInDist(&areaTriggerPos, areaTrigger->Radius))
return false;
break;
case 1: // Box
case AreaTriggerShapeType::Box:
if (!IsWithinBox(areaTriggerPos, areaTrigger->BoxLength / 2.f, areaTrigger->BoxWidth / 2.f, areaTrigger->BoxHeight / 2.f))
return false;
break;
case 3: // Polygon
case AreaTriggerShapeType::Polygon:
{
AreaTriggerPolygon const* polygon = sObjectMgr->GetAreaTriggerPolygon(areaTrigger->ID);
if (!polygon || (polygon->Height && 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;
Expand Down
2 changes: 1 addition & 1 deletion src/server/game/Globals/ObjectMgr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7197,7 +7197,7 @@ void ObjectMgr::LoadAreaTriggerPolygons()
{
for (AreaTriggerEntry const* areaTrigger : sAreaTriggerStore)
{
if (areaTrigger->ShapeType != 3)
if (areaTrigger->GetShapeType() != AreaTriggerShapeType::Polygon)
continue;

PathDb2 const* path = sDB2Manager.GetPath(areaTrigger->ShapeID);
Expand Down

0 comments on commit d51d6b0

Please sign in to comment.