Core/WorldStates: Add area requirements to world states
This commit is contained in:
1 parent
67dd72dfc0
commit
10823f8fcc
6 files changed
+90
-8
No files matched your search
@@ -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);
|
||||
@@ -8798,7 +8798,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); // 1
|
||||
packet.Worldstates.emplace_back(2263, 0); // 2
|
||||
|
||||
@@ -3538,12 +3538,29 @@ 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 DBCManager::IsInArea(playerAreaId, requiredAreaId);
|
||||
});
|
||||
if (!isInAllowedArea)
|
||||
continue;
|
||||
}
|
||||
|
||||
mapReference.GetSource()->SendDirectMessage(updateWorldState.GetRawPacket());
|
||||
}
|
||||
}
|
||||
@@ -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*/>;
|
||||
|
||||
@@ -36,8 +36,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;
|
||||
|
||||
@@ -79,11 +79,58 @@ void WorldStateMgr::LoadFromDB()
|
||||
continue;
|
||||
}
|
||||
|
||||
worldState.ScriptId = sObjectMgr->GetScriptId(fields[3].GetString());
|
||||
Tokenizer tokens2(fields[3].GetString(), ' ');
|
||||
i = 0;
|
||||
if (!worldState.MapIds.empty())
|
||||
{
|
||||
for (Tokenizer::const_iterator itr = tokens2.begin(); itr != tokens2.end(); ++itr, ++i)
|
||||
{
|
||||
uint32 areaId = atoul(*itr);
|
||||
if (!areaId)
|
||||
{
|
||||
TC_LOG_ERROR("sql.sql", "Table `world_state` contains a world state %u with non-integer AreaID, area ignored",
|
||||
id);
|
||||
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 (i > 0 && worldState.AreaIds.empty())
|
||||
{
|
||||
TC_LOG_ERROR("sql.sql", "Table `world_state` contains a world state %u with nonempty AreaIDs but no valid area id was found, ignored",
|
||||
id);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (tokens2.size() > 0)
|
||||
{
|
||||
TC_LOG_ERROR("sql.sql", "Table `world_state` contains a world state %u with nonempty AreaIDs but is a realm wide world state, area requirement ignored",
|
||||
id);
|
||||
}
|
||||
|
||||
worldState.ScriptId = sObjectMgr->GetScriptId(fields[4].GetString());
|
||||
|
||||
if (!worldState.MapIds.empty())
|
||||
{
|
||||
for (uint32 mapId : worldState.MapIds)
|
||||
_worldStatesByMap[mapId][id] = worldState.DefaultValue;
|
||||
}
|
||||
else
|
||||
_realmWorldStateValues[id] = worldState.DefaultValue;
|
||||
|
||||
@@ -149,13 +196,27 @@ 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 DBCManager::IsInArea(playerAreaId, requiredAreaId);
|
||||
});
|
||||
if (!isInAllowedArea)
|
||||
continue;
|
||||
}
|
||||
|
||||
initWorldStates.Worldstates.emplace_back(worldStateId, value);
|
||||
}
|
||||
}
|
||||
|
||||
WorldStateMgr* WorldStateMgr::instance()
|
||||
|
||||
@@ -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()
|
||||
|
||||
Reference in new issue
Block a user