aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sql/updates/world/master/2022_06_26_02_world.sql3
-rw-r--r--src/server/game/Entities/Player/Player.cpp2
-rw-r--r--src/server/game/Maps/Map.cpp18
-rw-r--r--src/server/game/World/WorldStates/WorldStateDefines.h1
-rw-r--r--src/server/game/World/WorldStates/WorldStateMgr.cpp64
-rw-r--r--src/server/game/World/WorldStates/WorldStateMgr.h2
6 files changed, 82 insertions, 8 deletions
diff --git a/sql/updates/world/master/2022_06_26_02_world.sql b/sql/updates/world/master/2022_06_26_02_world.sql
new file mode 100644
index 00000000000..31f3cdf533f
--- /dev/null
+++ b/sql/updates/world/master/2022_06_26_02_world.sql
@@ -0,0 +1,3 @@
+ALTER TABLE `world_state` ADD `AreaIDs` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL AFTER `MapIDs`;
+
+UPDATE `world_state` SET `MapIDs`='571,2118',`AreaIDs`='4197,10176' WHERE `ID` IN (3490,3491,3680,3681,3698,3699,3700,3701,3702,3703,3704,3705,3706,3710,3711,3712,3713,3714,3749,3750,3751,3752,3753,3754,3755,3756,3757,3758,3759,3760,3761,3762,3763,3764,3765,3766,3767,3768,3769,3770,3771,3772,3773,3781,3801,3802,3803,4022,4023,4024,4025,4354);
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 56380e7adf7..6d7eead1e2b 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -9215,7 +9215,7 @@ void Player::SendInitWorldStates(uint32 zoneId, uint32 areaId)
packet.AreaID = zoneId;
packet.SubareaID = areaId;
- sWorldStateMgr->FillInitialWorldStates(packet, GetMap());
+ sWorldStateMgr->FillInitialWorldStates(packet, GetMap(), areaId);
packet.Worldstates.emplace_back(2264, 0); // SCOURGE_EVENT_WORLDSTATE_EASTERN_PLAGUELANDS
packet.Worldstates.emplace_back(2263, 0); // SCOURGE_EVENT_WORLDSTATE_TANARIS
diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp
index 7771fe6198e..acf5a1a035c 100644
--- a/src/server/game/Maps/Map.cpp
+++ b/src/server/game/Maps/Map.cpp
@@ -702,14 +702,28 @@ void Map::SetWorldStateValue(int32 worldStateId, int32 value)
int32 oldValue = itr->second;
itr->second = value;
- if (WorldStateTemplate const* worldStateTemplate = sWorldStateMgr->GetWorldStateTemplate(worldStateId))
+ WorldStateTemplate const* worldStateTemplate = sWorldStateMgr->GetWorldStateTemplate(worldStateId);
+ if (worldStateTemplate)
sScriptMgr->OnWorldStateValueChange(worldStateTemplate, oldValue, value, this);
// Broadcast update to all players on the map
WorldPackets::WorldState::UpdateWorldState updateWorldState;
updateWorldState.VariableID = worldStateId;
updateWorldState.Value = value;
- SendToPlayers(updateWorldState.Write());
+ updateWorldState.Write();
+
+ for (MapReference const& mapReference : m_mapRefManager)
+ {
+ if (worldStateTemplate && !worldStateTemplate->AreaIds.empty())
+ {
+ bool isInAllowedArea = std::any_of(worldStateTemplate->AreaIds.begin(), worldStateTemplate->AreaIds.end(),
+ [playerAreaId = mapReference.GetSource()->GetAreaId()](uint32 requiredAreaId) { return DB2Manager::IsInArea(playerAreaId, requiredAreaId); });
+ if (!isInAllowedArea)
+ continue;
+ }
+
+ mapReference.GetSource()->SendDirectMessage(updateWorldState.GetRawPacket());
+ }
}
template<class T>
diff --git a/src/server/game/World/WorldStates/WorldStateDefines.h b/src/server/game/World/WorldStates/WorldStateDefines.h
index 97966fb5ce2..410ce8f5580 100644
--- a/src/server/game/World/WorldStates/WorldStateDefines.h
+++ b/src/server/game/World/WorldStates/WorldStateDefines.h
@@ -29,6 +29,7 @@ struct WorldStateTemplate
uint32 ScriptId = 0;
std::unordered_set<uint32> MapIds;
+ std::unordered_set<uint32> AreaIds;
};
using WorldStateValueContainer = std::unordered_map<int32 /*worldStateId*/, int32 /*value*/>;
diff --git a/src/server/game/World/WorldStates/WorldStateMgr.cpp b/src/server/game/World/WorldStates/WorldStateMgr.cpp
index 13fee84bcad..9867b3a0123 100644
--- a/src/server/game/World/WorldStates/WorldStateMgr.cpp
+++ b/src/server/game/World/WorldStates/WorldStateMgr.cpp
@@ -39,8 +39,8 @@ void WorldStateMgr::LoadFromDB()
{
uint32 oldMSTime = getMSTime();
- // 0 1 2 3
- QueryResult result = WorldDatabase.Query("SELECT ID, DefaultValue, MapIDs, ScriptName FROM world_state");
+ // 0 1 2 3 4
+ QueryResult result = WorldDatabase.Query("SELECT ID, DefaultValue, MapIDs, AreaIDs, ScriptName FROM world_state");
if (!result)
return;
@@ -81,7 +81,51 @@ void WorldStateMgr::LoadFromDB()
continue;
}
- worldState.ScriptId = sObjectMgr->GetScriptId(fields[3].GetString());
+ std::string_view areaIds = fields[3].GetStringView();
+ if (!worldState.MapIds.empty())
+ {
+ for (std::string_view areaIdToken : Trinity::Tokenize(areaIds, ',', false))
+ {
+ Optional<uint32> areaId = Trinity::StringTo<uint32>(areaIdToken);
+ if (!areaId)
+ {
+ TC_LOG_ERROR("sql.sql", "Table `world_state` contains a world state %u with non-integer AreaID (" STRING_VIEW_FMT "), area ignored",
+ id, STRING_VIEW_FMT_ARG(areaIdToken));
+ continue;
+ }
+
+ AreaTableEntry const* areaTableEntry = sAreaTableStore.LookupEntry(*areaId);
+ if (!areaTableEntry)
+ {
+ TC_LOG_ERROR("sql.sql", "Table `world_state` contains a world state %u with invalid AreaID (%u), area ignored",
+ id, *areaId);
+ continue;
+ }
+
+ if (worldState.MapIds.find(areaTableEntry->ContinentID) == worldState.MapIds.end())
+ {
+ TC_LOG_ERROR("sql.sql", "Table `world_state` contains a world state %u with AreaID (%u) not on any of required maps, area ignored",
+ id, *areaId);
+ continue;
+ }
+
+ worldState.AreaIds.insert(*areaId);
+ }
+
+ if (!areaIds.empty() && worldState.AreaIds.empty())
+ {
+ TC_LOG_ERROR("sql.sql", "Table `world_state` contains a world state %u with nonempty AreaIDs (" STRING_VIEW_FMT ") but no valid area id was found, ignored",
+ id, STRING_VIEW_FMT_ARG(areaIds));
+ continue;
+ }
+ }
+ else if (!areaIds.empty())
+ {
+ TC_LOG_ERROR("sql.sql", "Table `world_state` contains a world state %u with nonempty AreaIDs (" STRING_VIEW_FMT ") but is a realm wide world state, area requirement ignored",
+ id, STRING_VIEW_FMT_ARG(areaIds));
+ }
+
+ worldState.ScriptId = sObjectMgr->GetScriptId(fields[4].GetString());
if (!worldState.MapIds.empty())
{
@@ -153,13 +197,25 @@ WorldStateValueContainer WorldStateMgr::GetInitialWorldStatesForMap(Map const* m
return initialValues;
}
-void WorldStateMgr::FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& initWorldStates, Map const* map) const
+void WorldStateMgr::FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& initWorldStates, Map const* map, uint32 playerAreaId) const
{
for (auto const& [worldStateId, value] : _realmWorldStateValues)
initWorldStates.Worldstates.emplace_back(worldStateId, value);
for (auto const& [worldStateId, value] : map->GetWorldStateValues())
+ {
+ WorldStateTemplate const* worldStateTemplate = GetWorldStateTemplate(worldStateId);
+ if (worldStateTemplate && !worldStateTemplate->AreaIds.empty())
+ {
+ bool isInAllowedArea = std::any_of(worldStateTemplate->AreaIds.begin(), worldStateTemplate->AreaIds.end(),
+ [=](uint32 requiredAreaId) { return DB2Manager::IsInArea(playerAreaId, requiredAreaId); });
+ if (!isInAllowedArea)
+ continue;
+ }
+
+
initWorldStates.Worldstates.emplace_back(worldStateId, value);
+ }
}
WorldStateMgr* WorldStateMgr::instance()
diff --git a/src/server/game/World/WorldStates/WorldStateMgr.h b/src/server/game/World/WorldStates/WorldStateMgr.h
index 18ce38afd2f..ae9e72f9f5a 100644
--- a/src/server/game/World/WorldStates/WorldStateMgr.h
+++ b/src/server/game/World/WorldStates/WorldStateMgr.h
@@ -42,7 +42,7 @@ public:
WorldStateValueContainer GetInitialWorldStatesForMap(Map const* map) const;
- void FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& initWorldStates, Map const* map) const;
+ void FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& initWorldStates, Map const* map, uint32 playerAreaId) const;
};
#define sWorldStateMgr WorldStateMgr::instance()