mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-15 23:20:36 +01:00
Core/World: implement database support for default map and realm wide world states
Co-Authored-By: Shauren <shauren.trinity@gmail.com>
This commit is contained in:
19
sql/updates/world/master/2022_06_25_01_world.sql
Normal file
19
sql/updates/world/master/2022_06_25_01_world.sql
Normal file
@@ -0,0 +1,19 @@
|
||||
--
|
||||
-- Table structure for table `world_state`
|
||||
--
|
||||
DROP TABLE IF EXISTS `world_state`;
|
||||
CREATE TABLE `world_state` (
|
||||
`ID` int NOT NULL,
|
||||
`DefaultValue` int NOT NULL,
|
||||
`MapID` int unsigned DEFAULT NULL,
|
||||
`ScriptName` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
|
||||
`Comment` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci,
|
||||
PRIMARY KEY (`ID`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
INSERT INTO `world_state` (`ID`, `DefaultValue`, `MapID`, `Comment`) VALUES
|
||||
(5644, 0, 669, 'Blackwing Descent - Omnotron Defense System - Achieve-a-tron'),
|
||||
(5645, 0, 669, 'Blackwing Descent - Omnotron Defense System - Achieve-a-tron'),
|
||||
(5646, 0, 669, 'Blackwing Descent - Omnotron Defense System - Achieve-a-tron'),
|
||||
(5647, 0, 669, 'Blackwing Descent - Omnotron Defense System - Achieve-a-tron'),
|
||||
(5117, 0, 670, 'Grim Batol - Erudax - Don\'t need to Break Eggs to Make an Omelet');
|
||||
@@ -124,6 +124,7 @@
|
||||
#include "World.h"
|
||||
#include "WorldPacket.h"
|
||||
#include "WorldSession.h"
|
||||
#include "WorldStateMgr.h"
|
||||
#include "WorldStatePackets.h"
|
||||
#include <G3D/g3dmath.h>
|
||||
#include <sstream>
|
||||
@@ -9214,6 +9215,8 @@ void Player::SendInitWorldStates(uint32 zoneId, uint32 areaId)
|
||||
packet.AreaID = zoneId;
|
||||
packet.SubareaID = areaId;
|
||||
|
||||
sWorldStateMgr->FillInitialWorldStates(packet, GetMap());
|
||||
|
||||
packet.Worldstates.emplace_back(2264, 0); // SCOURGE_EVENT_WORLDSTATE_EASTERN_PLAGUELANDS
|
||||
packet.Worldstates.emplace_back(2263, 0); // SCOURGE_EVENT_WORLDSTATE_TANARIS
|
||||
packet.Worldstates.emplace_back(2262, 0); // SCOURGE_EVENT_WORLDSTATE_BURNING_STEPPES
|
||||
|
||||
@@ -56,6 +56,8 @@
|
||||
#include "WeatherMgr.h"
|
||||
#include "World.h"
|
||||
#include "WorldSession.h"
|
||||
#include "WorldStateMgr.h"
|
||||
#include "WorldStatePackets.h"
|
||||
#include <sstream>
|
||||
|
||||
#include "Hacks/boost_1_74_fibonacci_heap.h"
|
||||
@@ -371,6 +373,8 @@ i_scriptLock(false), _respawnCheckTimer(0)
|
||||
|
||||
MMAP::MMapFactory::createOrGetMMapManager()->loadMapInstance(sWorld->GetDataPath(), GetId(), i_InstanceId);
|
||||
|
||||
_worldStateValues = sWorldStateMgr->GetInitialWorldStatesForMap(this);
|
||||
|
||||
sScriptMgr->OnCreateMap(this);
|
||||
}
|
||||
|
||||
@@ -684,6 +688,30 @@ void Map::UpdatePersonalPhasesForPlayer(Player const* player)
|
||||
GetMultiPersonalPhaseTracker().OnOwnerPhaseChanged(player, getNGrid(cell.GridX(), cell.GridY()), this, cell);
|
||||
}
|
||||
|
||||
int32 Map::GetWorldStateValue(int32 worldStateId) const
|
||||
{
|
||||
if (int32 const* value = Trinity::Containers::MapGetValuePtr(_worldStateValues, worldStateId))
|
||||
return *value;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Map::SetWorldStateValue(int32 worldStateId, int32 value)
|
||||
{
|
||||
auto itr = _worldStateValues.try_emplace(worldStateId, 0).first;
|
||||
int32 oldValue = itr->second;
|
||||
itr->second = value;
|
||||
|
||||
if (WorldStateTemplate const* worldStateTemplate = sWorldStateMgr->GetWorldStateTemplate(worldStateId))
|
||||
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());
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void Map::InitializeObject(T* /*obj*/) { }
|
||||
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
#include "SharedDefines.h"
|
||||
#include "SpawnData.h"
|
||||
#include "Timer.h"
|
||||
#include "WorldStateDefines.h"
|
||||
#include <boost/heap/fibonacci_heap.hpp>
|
||||
#include <bitset>
|
||||
#include <list>
|
||||
@@ -918,6 +919,17 @@ class TC_GAME_API Map : public GridRefManager<NGridType>
|
||||
|
||||
private:
|
||||
MultiPersonalPhaseTracker _multiPersonalPhaseTracker;
|
||||
|
||||
/*********************************************************/
|
||||
/*** WorldStates ***/
|
||||
/*********************************************************/
|
||||
public:
|
||||
int32 GetWorldStateValue(int32 worldStateId) const;
|
||||
void SetWorldStateValue(int32 worldStateId, int32 value);
|
||||
WorldStateValueContainer const& GetWorldStateValues() const { return _worldStateValues; }
|
||||
|
||||
private:
|
||||
WorldStateValueContainer _worldStateValues;
|
||||
};
|
||||
|
||||
enum InstanceResetMethod
|
||||
|
||||
@@ -133,6 +133,10 @@ template<>
|
||||
struct is_script_database_bound<QuestScript>
|
||||
: std::true_type { };
|
||||
|
||||
template<>
|
||||
struct is_script_database_bound<WorldStateScript>
|
||||
: std::true_type { };
|
||||
|
||||
enum Spells
|
||||
{
|
||||
SPELL_HOTSWAP_VISUAL_SPELL_EFFECT = 40162 // 59084
|
||||
@@ -2322,6 +2326,7 @@ void ScriptMgr::OnSceneComplete(Player* player, uint32 sceneInstanceID, SceneTem
|
||||
tmpscript->OnSceneComplete(player, sceneInstanceID, sceneTemplate);
|
||||
}
|
||||
|
||||
// Quest
|
||||
void ScriptMgr::OnQuestStatusChange(Player* player, Quest const* quest, QuestStatus oldStatus, QuestStatus newStatus)
|
||||
{
|
||||
ASSERT(player);
|
||||
@@ -2349,6 +2354,15 @@ void ScriptMgr::OnQuestObjectiveChange(Player* player, Quest const* quest, Quest
|
||||
tmpscript->OnQuestObjectiveChange(player, quest, objective, oldAmount, newAmount);
|
||||
}
|
||||
|
||||
// WorldState
|
||||
void ScriptMgr::OnWorldStateValueChange(WorldStateTemplate const* worldStateTemplate, int32 oldValue, int32 newValue, Map const* map)
|
||||
{
|
||||
ASSERT(worldStateTemplate);
|
||||
|
||||
GET_SCRIPT(WorldStateScript, worldStateTemplate->ScriptId, tmpscript);
|
||||
tmpscript->OnValueChange(worldStateTemplate->Id, oldValue, newValue, map);
|
||||
}
|
||||
|
||||
SpellScriptLoader::SpellScriptLoader(char const* name)
|
||||
: ScriptObject(name)
|
||||
{
|
||||
@@ -2638,6 +2652,14 @@ QuestScript::QuestScript(char const* name)
|
||||
|
||||
QuestScript::~QuestScript() = default;
|
||||
|
||||
WorldStateScript::WorldStateScript(char const* name)
|
||||
: ScriptObject(name)
|
||||
{
|
||||
ScriptRegistry<WorldStateScript>::Instance()->AddScript(this);
|
||||
}
|
||||
|
||||
WorldStateScript::~WorldStateScript() = default;
|
||||
|
||||
// Specialize for each script type class like so:
|
||||
template class TC_GAME_API ScriptRegistry<SpellScriptLoader>;
|
||||
template class TC_GAME_API ScriptRegistry<ServerScript>;
|
||||
@@ -2671,3 +2693,4 @@ template class TC_GAME_API ScriptRegistry<AreaTriggerEntityScript>;
|
||||
template class TC_GAME_API ScriptRegistry<ConversationScript>;
|
||||
template class TC_GAME_API ScriptRegistry<SceneScript>;
|
||||
template class TC_GAME_API ScriptRegistry<QuestScript>;
|
||||
template class TC_GAME_API ScriptRegistry<WorldStateScript>;
|
||||
|
||||
@@ -77,6 +77,7 @@ struct MapEntry;
|
||||
struct Position;
|
||||
struct QuestObjective;
|
||||
struct SceneTemplate;
|
||||
struct WorldStateTemplate;
|
||||
|
||||
namespace Trinity::ChatCommands { struct ChatCommandBuilder; }
|
||||
|
||||
@@ -987,6 +988,20 @@ class TC_GAME_API QuestScript : public ScriptObject
|
||||
virtual void OnQuestObjectiveChange(Player* /*player*/, Quest const* /*quest*/, QuestObjective const& /*objective*/, int32 /*oldAmount*/, int32 /*newAmount*/) { }
|
||||
};
|
||||
|
||||
class TC_GAME_API WorldStateScript : public ScriptObject
|
||||
{
|
||||
protected:
|
||||
|
||||
WorldStateScript(char const* name);
|
||||
|
||||
public:
|
||||
|
||||
~WorldStateScript();
|
||||
|
||||
// Called when worldstate changes value, map is optional
|
||||
virtual void OnValueChange([[maybe_unused]] int32 worldStateId, [[maybe_unused]] int32 oldValue, [[maybe_unused]] int32 newValue, [[maybe_unused]] Map const* map) { }
|
||||
};
|
||||
|
||||
// Manages registration, loading, and execution of scripts.
|
||||
class TC_GAME_API ScriptMgr
|
||||
{
|
||||
@@ -1289,6 +1304,10 @@ class TC_GAME_API ScriptMgr
|
||||
void OnQuestAcknowledgeAutoAccept(Player* player, Quest const* quest);
|
||||
void OnQuestObjectiveChange(Player* player, Quest const* quest, QuestObjective const& objective, int32 oldAmount, int32 newAmount);
|
||||
|
||||
public: /* WorldStateScript */
|
||||
|
||||
void OnWorldStateValueChange(WorldStateTemplate const* worldStateTemplate, int32 oldValue, int32 newValue, Map const* map);
|
||||
|
||||
private:
|
||||
uint32 _scriptCount;
|
||||
bool _scriptIdUpdated;
|
||||
|
||||
@@ -100,6 +100,7 @@
|
||||
#include "WhoListStorage.h"
|
||||
#include "WorldSession.h"
|
||||
#include "WorldSocket.h"
|
||||
#include "WorldStateMgr.h"
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
||||
@@ -2241,6 +2242,9 @@ void World::SetInitialWorldSettings()
|
||||
TC_LOG_INFO("server.loading", "Loading Creature Formations...");
|
||||
sFormationMgr->LoadCreatureFormations();
|
||||
|
||||
TC_LOG_INFO("server.loading", "Loading World State templates...");
|
||||
sWorldStateMgr->LoadFromDB();
|
||||
|
||||
TC_LOG_INFO("server.loading", "Loading World States..."); // must be loaded before battleground, outdoor PvP and conditions
|
||||
LoadWorldStates();
|
||||
|
||||
|
||||
36
src/server/game/World/WorldStates/WorldStateDefines.h
Normal file
36
src/server/game/World/WorldStates/WorldStateDefines.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef WorldStateDefines_h__
|
||||
#define WorldStateDefines_h__
|
||||
|
||||
#include "Define.h"
|
||||
#include "Optional.h"
|
||||
#include <unordered_map>
|
||||
|
||||
struct WorldStateTemplate
|
||||
{
|
||||
int32 Id = 0;
|
||||
int32 DefaultValue = 0;
|
||||
uint32 ScriptId = 0;
|
||||
|
||||
Optional<uint32> MapId;
|
||||
};
|
||||
|
||||
using WorldStateValueContainer = std::unordered_map<int32 /*worldStateId*/, int32 /*value*/>;
|
||||
|
||||
#endif // WorldStateDefines_h__
|
||||
137
src/server/game/World/WorldStates/WorldStateMgr.cpp
Normal file
137
src/server/game/World/WorldStates/WorldStateMgr.cpp
Normal file
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "WorldStateMgr.h"
|
||||
#include "Containers.h"
|
||||
#include "DatabaseEnv.h"
|
||||
#include "Log.h"
|
||||
#include "Map.h"
|
||||
#include "ObjectMgr.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "World.h"
|
||||
#include "WorldStatePackets.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
std::unordered_map<int32, WorldStateTemplate> _worldStateTemplates;
|
||||
WorldStateValueContainer _realmWorldStateValues;
|
||||
std::unordered_map<uint32, WorldStateValueContainer> _worldStatesByMap;
|
||||
}
|
||||
|
||||
void WorldStateMgr::LoadFromDB()
|
||||
{
|
||||
uint32 oldMSTime = getMSTime();
|
||||
|
||||
// 0 1 2 3
|
||||
QueryResult result = WorldDatabase.Query("SELECT ID, DefaultValue, MapID, ScriptName FROM world_state");
|
||||
if (!result)
|
||||
return;
|
||||
|
||||
do
|
||||
{
|
||||
Field* fields = result->Fetch();
|
||||
|
||||
int32 id = fields[0].GetInt32();
|
||||
WorldStateTemplate& worldState = _worldStateTemplates[id];
|
||||
worldState.Id = id;
|
||||
worldState.DefaultValue = fields[1].GetInt32();
|
||||
if (!fields[2].IsNull())
|
||||
worldState.MapId = fields[2].GetUInt32();
|
||||
|
||||
worldState.ScriptId = sObjectMgr->GetScriptId(fields[3].GetString());
|
||||
|
||||
if (worldState.MapId)
|
||||
_worldStatesByMap[*worldState.MapId][id] = worldState.DefaultValue;
|
||||
else
|
||||
_realmWorldStateValues[id] = worldState.DefaultValue;
|
||||
|
||||
} while (result->NextRow());
|
||||
|
||||
TC_LOG_INFO("server.loading", ">> Loaded " SZFMTD " world state templates %u ms", _worldStateTemplates.size(), GetMSTimeDiffToNow(oldMSTime));
|
||||
}
|
||||
|
||||
WorldStateTemplate const* WorldStateMgr::GetWorldStateTemplate(int32 worldStateId) const
|
||||
{
|
||||
return Trinity::Containers::MapGetValuePtr(_worldStateTemplates, worldStateId);
|
||||
}
|
||||
|
||||
int32 WorldStateMgr::GetValue(int32 worldStateId, Map const* map) const
|
||||
{
|
||||
WorldStateTemplate const* worldStateTemplate = GetWorldStateTemplate(worldStateId);
|
||||
if (!worldStateTemplate || !worldStateTemplate->MapId)
|
||||
{
|
||||
if (int32 const* value = Trinity::Containers::MapGetValuePtr(_realmWorldStateValues, worldStateId))
|
||||
return *value;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (map->GetId() != worldStateTemplate->MapId)
|
||||
return 0;
|
||||
|
||||
return map->GetWorldStateValue(worldStateId);
|
||||
}
|
||||
|
||||
void WorldStateMgr::SetValue(int32 worldStateId, int32 value, Map* map)
|
||||
{
|
||||
WorldStateTemplate const* worldStateTemplate = GetWorldStateTemplate(worldStateId);
|
||||
if (!worldStateTemplate || !worldStateTemplate->MapId)
|
||||
{
|
||||
auto itr = _realmWorldStateValues.try_emplace(worldStateId, 0).first;
|
||||
int32 oldValue = itr->second;
|
||||
itr->second = value;
|
||||
|
||||
if (worldStateTemplate)
|
||||
sScriptMgr->OnWorldStateValueChange(worldStateTemplate, oldValue, value, nullptr);
|
||||
|
||||
// Broadcast update to all players on the server
|
||||
WorldPackets::WorldState::UpdateWorldState updateWorldState;
|
||||
updateWorldState.VariableID = worldStateId;
|
||||
updateWorldState.Value = value;
|
||||
sWorld->SendGlobalMessage(updateWorldState.Write());
|
||||
return;
|
||||
}
|
||||
|
||||
if (map->GetId() != worldStateTemplate->MapId)
|
||||
return;
|
||||
|
||||
map->SetWorldStateValue(worldStateId, value);
|
||||
}
|
||||
|
||||
WorldStateValueContainer WorldStateMgr::GetInitialWorldStatesForMap(Map const* map) const
|
||||
{
|
||||
WorldStateValueContainer initialValues;
|
||||
if (WorldStateValueContainer const* valuesTemplate = Trinity::Containers::MapGetValuePtr(_worldStatesByMap, map->GetId()))
|
||||
initialValues = *valuesTemplate;
|
||||
|
||||
return initialValues;
|
||||
}
|
||||
|
||||
void WorldStateMgr::FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& initWorldStates, Map const* map) const
|
||||
{
|
||||
for (auto const& [worldStateId, value] : _realmWorldStateValues)
|
||||
initWorldStates.Worldstates.emplace_back(worldStateId, value);
|
||||
|
||||
for (auto const& [worldStateId, value] : map->GetWorldStateValues())
|
||||
initWorldStates.Worldstates.emplace_back(worldStateId, value);
|
||||
}
|
||||
|
||||
WorldStateMgr* WorldStateMgr::instance()
|
||||
{
|
||||
static WorldStateMgr instance;
|
||||
return &instance;
|
||||
}
|
||||
50
src/server/game/World/WorldStates/WorldStateMgr.h
Normal file
50
src/server/game/World/WorldStates/WorldStateMgr.h
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef WorldStateMgr_h__
|
||||
#define WorldStateMgr_h__
|
||||
|
||||
#include "Define.h"
|
||||
#include "WorldStateDefines.h"
|
||||
|
||||
class Map;
|
||||
|
||||
namespace WorldPackets::WorldState
|
||||
{
|
||||
class InitWorldStates;
|
||||
}
|
||||
|
||||
class TC_GAME_API WorldStateMgr
|
||||
{
|
||||
public:
|
||||
static WorldStateMgr* instance();
|
||||
|
||||
void LoadFromDB();
|
||||
|
||||
WorldStateTemplate const* GetWorldStateTemplate(int32 worldStateId) const;
|
||||
|
||||
int32 GetValue(int32 worldStateId, Map const* map) const;
|
||||
void SetValue(int32 worldStateId, int32 value, Map* map);
|
||||
|
||||
WorldStateValueContainer GetInitialWorldStatesForMap(Map const* map) const;
|
||||
|
||||
void FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& initWorldStates, Map const* map) const;
|
||||
};
|
||||
|
||||
#define sWorldStateMgr WorldStateMgr::instance()
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user