TrinityCore
Loading...
Searching...
No Matches
ScenarioMgr.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include "ScenarioMgr.h"
19#include "DB2Stores.h"
20#include "DatabaseEnv.h"
21#include "InstanceScenario.h"
22#include "Log.h"
23#include "Map.h"
24#include "MapUtils.h"
25#include "ScenarioPackets.h"
26
27ScenarioMgr::ScenarioMgr() = default;
29
31{
32 static ScenarioMgr instance;
33 return &instance;
34}
35
37{
38 auto dbDataItr = _scenarioDBData.find(std::make_pair(map->GetId(), map->GetDifficultyID()));
39 // No scenario registered for this map and difficulty in the database
40 if (dbDataItr == _scenarioDBData.end())
41 return nullptr;
42
43 uint32 scenarioID = 0;
44 switch (team)
45 {
46 case TEAM_ALLIANCE:
47 scenarioID = dbDataItr->second.Scenario_A;
48 break;
49 case TEAM_HORDE:
50 scenarioID = dbDataItr->second.Scenario_H;
51 break;
52 default:
53 break;
54 }
55
56 return CreateInstanceScenario(map, scenarioID);
57}
58
60{
61 auto itr = _scenarioData.find(scenarioID);
62 if (itr == _scenarioData.end())
63 {
64 TC_LOG_ERROR("scenario", "No scenario data was found related to scenario (Id: {}) for map (Id: {}), difficulty (Id: {}).", scenarioID, map->GetId(), map->GetDifficultyID());
65 return nullptr;
66 }
67
68 return new InstanceScenario(map, &itr->second);
69}
70
72{
73 _scenarioDBData.clear();
74
75 uint32 oldMSTime = getMSTime();
76
77 QueryResult result = WorldDatabase.Query("SELECT map, difficulty, scenario_A, scenario_H FROM scenarios");
78
79 if (!result)
80 {
81 TC_LOG_INFO("server.loading", ">> Loaded 0 scenarios. DB table `scenarios` is empty!");
82 return;
83 }
84
85 do
86 {
87 Field* fields = result->Fetch();
88
89 uint32 mapId = fields[0].GetUInt32();
90 Difficulty difficulty = Difficulty(fields[1].GetInt32());
91
92 uint32 scenarioAllianceId = fields[2].GetUInt32();
93 if (scenarioAllianceId > 0 && !_scenarioData.contains(scenarioAllianceId))
94 {
95 TC_LOG_ERROR("sql.sql", "ScenarioMgr::LoadDBData: DB Table `scenarios`, column scenario_A contained an invalid scenario (Id: {})!", scenarioAllianceId);
96 continue;
97 }
98
99 uint32 scenarioHordeId = fields[3].GetUInt32();
100 if (scenarioHordeId > 0 && !_scenarioData.contains(scenarioHordeId))
101 {
102 TC_LOG_ERROR("sql.sql", "ScenarioMgr::LoadDBData: DB Table `scenarios`, column scenario_H contained an invalid scenario (Id: {})!", scenarioHordeId);
103 continue;
104 }
105
106 if (scenarioHordeId == 0)
107 scenarioHordeId = scenarioAllianceId;
108
109 ScenarioDBData& data = _scenarioDBData[std::make_pair(mapId, difficulty)];
110 data.MapID = mapId;
111 data.DifficultyID = difficulty;
112 data.Scenario_A = scenarioAllianceId;
113 data.Scenario_H = scenarioHordeId;
114 }
115 while (result->NextRow());
116
117 TC_LOG_INFO("server.loading", ">> Loaded {} instance scenario entries in {} ms", _scenarioDBData.size(), GetMSTimeDiffToNow(oldMSTime));
118}
119
121{
122 _scenarioData.clear();
123
124 std::unordered_map<uint32, std::map<uint8, ScenarioStepEntry const*>> scenarioSteps;
125 uint32 deepestCriteriaTreeSize = 0;
126
127 for (ScenarioStepEntry const* step : sScenarioStepStore)
128 {
129 scenarioSteps[step->ScenarioID][step->OrderIndex] = step;
130 if (CriteriaTree const* tree = sCriteriaMgr->GetCriteriaTree(step->Criteriatreeid))
131 {
132 uint32 criteriaTreeSize = 0;
133 CriteriaMgr::WalkCriteriaTree(tree, [&criteriaTreeSize](CriteriaTree const* /*tree*/)
134 {
135 ++criteriaTreeSize;
136 });
137 deepestCriteriaTreeSize = std::max(deepestCriteriaTreeSize, criteriaTreeSize);
138 }
139 }
140
141 ASSERT(deepestCriteriaTreeSize < MAX_ALLOWED_SCENARIO_POI_QUERY_SIZE, "MAX_ALLOWED_SCENARIO_POI_QUERY_SIZE must be at least %u", deepestCriteriaTreeSize + 1);
142
143 for (ScenarioEntry const* scenario : sScenarioStore)
144 {
145 ScenarioData& data = _scenarioData[scenario->ID];
146 data.Entry = scenario;
147 data.Steps = std::move(scenarioSteps[scenario->ID]);
148 }
149}
150
152{
153 uint32 oldMSTime = getMSTime();
154
155 _scenarioPOIStore.clear(); // need for reload case
156
157 uint32 count = 0;
158
159 // 0 1 2 3 4 5 6 7 8 9
160 QueryResult result = WorldDatabase.Query("SELECT CriteriaTreeID, BlobIndex, Idx1, MapID, UiMapID, Priority, Flags, WorldEffectID, PlayerConditionID, NavigationPlayerConditionID FROM scenario_poi ORDER BY CriteriaTreeID, Idx1");
161 if (!result)
162 {
163 TC_LOG_ERROR("server.loading", ">> Loaded 0 scenario POI definitions. DB table `scenario_poi` is empty.");
164 return;
165 }
166
167 // 0 1 2 3 4
168 QueryResult pointsResult = WorldDatabase.Query("SELECT CriteriaTreeID, Idx1, X, Y, Z FROM scenario_poi_points ORDER BY CriteriaTreeID DESC, Idx1, Idx2");
169
170 std::unordered_map<int32, std::map<int32, std::vector<ScenarioPOIPoint>>> allPoints;
171
172 if (pointsResult)
173 {
174 Field* fields = pointsResult->Fetch();
175
176 do
177 {
178 fields = pointsResult->Fetch();
179
180 int32 CriteriaTreeID = fields[0].GetInt32();
181 int32 Idx1 = fields[1].GetInt32();
182 int32 X = fields[2].GetInt32();
183 int32 Y = fields[3].GetInt32();
184 int32 Z = fields[4].GetInt32();
185
186 allPoints[CriteriaTreeID][Idx1].emplace_back(X, Y, Z);
187 } while (pointsResult->NextRow());
188 }
189
190 do
191 {
192 Field* fields = result->Fetch();
193
194 int32 criteriaTreeID = fields[0].GetInt32();
195 int32 blobIndex = fields[1].GetInt32();
196 int32 idx1 = fields[2].GetInt32();
197 int32 mapID = fields[3].GetInt32();
198 int32 uiMapID = fields[4].GetInt32();
199 int32 priority = fields[5].GetInt32();
200 int32 flags = fields[6].GetInt32();
201 int32 worldEffectID = fields[7].GetInt32();
202 int32 playerConditionID = fields[8].GetInt32();
203 int32 navigationPlayerConditionID = fields[9].GetInt32();
204
205 if (!sCriteriaMgr->GetCriteriaTree(criteriaTreeID))
206 TC_LOG_ERROR("sql.sql", "`scenario_poi` CriteriaTreeID ({}) Idx1 ({}) does not correspond to a valid criteria tree", criteriaTreeID, idx1);
207
208 if (std::map<int32, std::vector<ScenarioPOIPoint>>* blobs = Trinity::Containers::MapGetValuePtr(allPoints, criteriaTreeID))
209 {
210 if (std::vector<ScenarioPOIPoint>* points = Trinity::Containers::MapGetValuePtr(*blobs, idx1))
211 {
212 _scenarioPOIStore[criteriaTreeID].emplace_back(blobIndex, mapID, uiMapID, priority, flags, worldEffectID, playerConditionID, navigationPlayerConditionID, std::move(*points));
213 ++count;
214 continue;
215 }
216 }
217
218 TC_LOG_ERROR("server.loading", "Table scenario_poi references unknown scenario poi points for criteria tree id {} POI id {}", criteriaTreeID, blobIndex);
219
220 } while (result->NextRow());
221
222 TC_LOG_INFO("server.loading", ">> Loaded {} scenario POI definitions in {} ms", count, GetMSTimeDiffToNow(oldMSTime));
223}
224
226{
227 auto itr = _scenarioPOIStore.find(criteriaTreeID);
228 if (itr != _scenarioPOIStore.end())
229 return &itr->second;
230
231 return nullptr;
232}
#define sCriteriaMgr
DB2Storage< ScenarioEntry > sScenarioStore("Scenario.db2", &ScenarioLoadInfo::Instance)
DB2Storage< ScenarioStepEntry > sScenarioStepStore("ScenarioStep.db2", &ScenarioStepLoadInfo::Instance)
Difficulty
Definition DBCEnums.h:932
std::shared_ptr< ResultSet > QueryResult
DatabaseWorkerPool< WorldDatabaseConnection > WorldDatabase
Accessor to the world database.
int32_t int32
Definition Define.h:150
uint32_t uint32
Definition Define.h:154
uint16 flags
#define ASSERT
Definition Errors.h:80
#define TC_LOG_ERROR(filterType__, message__,...)
Definition Log.h:190
#define TC_LOG_INFO(filterType__, message__,...)
Definition Log.h:184
std::vector< ScenarioPOI > ScenarioPOIVector
Definition ScenarioMgr.h:97
#define MAX_ALLOWED_SCENARIO_POI_QUERY_SIZE
@ TEAM_ALLIANCE
@ TEAM_HORDE
uint32 GetMSTimeDiffToNow(uint32 oldMSTime)
Definition Timer.h:57
uint32 getMSTime()
Definition Timer.h:33
static void WalkCriteriaTree(CriteriaTree const *tree, Func const &func)
Class used to access individual fields of database query result.
Definition Field.h:94
uint32 GetUInt32() const noexcept
Definition Field.cpp:57
int32 GetInt32() const noexcept
Definition Field.cpp:64
Difficulty GetDifficultyID() const
Definition Map.h:360
uint32 GetId() const
Definition Map.cpp:3257
ScenarioDataContainer _scenarioData
ScenarioDBDataContainer _scenarioDBData
InstanceScenario * CreateInstanceScenarioForTeam(InstanceMap *map, TeamId team) const
InstanceScenario * CreateInstanceScenario(InstanceMap *map, uint32 scenarioID) const
void LoadDBData()
void LoadDB2Data()
ScenarioPOIVector const * GetScenarioPOIs(int32 criteriaTreeID) const
ScenarioPOIContainer _scenarioPOIStore
void LoadScenarioPOI()
static ScenarioMgr * Instance()
auto MapGetValuePtr(M &map, typename M::key_type const &key)
Definition MapUtils.h:37
Difficulty DifficultyID
Definition ScenarioMgr.h:49
uint32 Scenario_H
Definition ScenarioMgr.h:51
uint32 Scenario_A
Definition ScenarioMgr.h:50
std::map< uint8, ScenarioStepEntry const * > Steps
Definition ScenarioMgr.h:37
ScenarioEntry const * Entry
Definition ScenarioMgr.h:36