TrinityCore
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 "Containers.h"
20#include "DatabaseEnv.h"
21#include "DB2Stores.h"
22#include "InstanceScenario.h"
23#include "Log.h"
24#include "Map.h"
25#include "ScenarioPackets.h"
26
28{
29 static ScenarioMgr instance;
30 return &instance;
31}
32
34{
35 auto dbDataItr = _scenarioDBData.find(std::make_pair(map->GetId(), map->GetDifficultyID()));
36 // No scenario registered for this map and difficulty in the database
37 if (dbDataItr == _scenarioDBData.end())
38 return nullptr;
39
40 uint32 scenarioID = 0;
41 switch (team)
42 {
43 case TEAM_ALLIANCE:
44 scenarioID = dbDataItr->second.Scenario_A;
45 break;
46 case TEAM_HORDE:
47 scenarioID = dbDataItr->second.Scenario_H;
48 break;
49 default:
50 break;
51 }
52
53 auto itr = _scenarioData.find(scenarioID);
54 if (itr == _scenarioData.end())
55 {
56 TC_LOG_ERROR("scenario", "Table `scenarios` contained data linking scenario (Id: {}) to map (Id: {}), difficulty (Id: {}) but no scenario data was found related to that scenario Id.", scenarioID, map->GetId(), map->GetDifficultyID());
57 return nullptr;
58 }
59
60 return new InstanceScenario(map, &itr->second);
61}
62
64{
65 _scenarioDBData.clear();
66
67 uint32 oldMSTime = getMSTime();
68
69 QueryResult result = WorldDatabase.Query("SELECT map, difficulty, scenario_A, scenario_H FROM scenarios");
70
71 if (!result)
72 {
73 TC_LOG_INFO("server.loading", ">> Loaded 0 scenarios. DB table `scenarios` is empty!");
74 return;
75 }
76
77 do
78 {
79 Field* fields = result->Fetch();
80
81 uint32 mapId = fields[0].GetUInt32();
82 uint8 difficulty = fields[1].GetUInt8();
83
84 uint32 scenarioAllianceId = fields[2].GetUInt32();
85 if (scenarioAllianceId > 0 && _scenarioData.find(scenarioAllianceId) == _scenarioData.end())
86 {
87 TC_LOG_ERROR("sql.sql", "ScenarioMgr::LoadDBData: DB Table `scenarios`, column scenario_A contained an invalid scenario (Id: {})!", scenarioAllianceId);
88 continue;
89 }
90
91 uint32 scenarioHordeId = fields[3].GetUInt32();
92 if (scenarioHordeId > 0 && _scenarioData.find(scenarioHordeId) == _scenarioData.end())
93 {
94 TC_LOG_ERROR("sql.sql", "ScenarioMgr::LoadDBData: DB Table `scenarios`, column scenario_H contained an invalid scenario (Id: {})!", scenarioHordeId);
95 continue;
96 }
97
98 if (scenarioHordeId == 0)
99 scenarioHordeId = scenarioAllianceId;
100
101 ScenarioDBData& data = _scenarioDBData[std::make_pair(mapId, difficulty)];
102 data.MapID = mapId;
103 data.DifficultyID = difficulty;
104 data.Scenario_A = scenarioAllianceId;
105 data.Scenario_H = scenarioHordeId;
106 }
107 while (result->NextRow());
108
109 TC_LOG_INFO("server.loading", ">> Loaded {} instance scenario entries in {} ms", _scenarioDBData.size(), GetMSTimeDiffToNow(oldMSTime));
110}
111
113{
114 _scenarioData.clear();
115
116 std::unordered_map<uint32, std::map<uint8, ScenarioStepEntry const*>> scenarioSteps;
117 uint32 deepestCriteriaTreeSize = 0;
118
119 for (ScenarioStepEntry const* step : sScenarioStepStore)
120 {
121 scenarioSteps[step->ScenarioID][step->OrderIndex] = step;
122 if (CriteriaTree const* tree = sCriteriaMgr->GetCriteriaTree(step->Criteriatreeid))
123 {
124 uint32 criteriaTreeSize = 0;
125 CriteriaMgr::WalkCriteriaTree(tree, [&criteriaTreeSize](CriteriaTree const* /*tree*/)
126 {
127 ++criteriaTreeSize;
128 });
129 deepestCriteriaTreeSize = std::max(deepestCriteriaTreeSize, criteriaTreeSize);
130 }
131 }
132
133 ASSERT(deepestCriteriaTreeSize < MAX_ALLOWED_SCENARIO_POI_QUERY_SIZE, "MAX_ALLOWED_SCENARIO_POI_QUERY_SIZE must be at least %u", deepestCriteriaTreeSize + 1);
134
135 for (ScenarioEntry const* scenario : sScenarioStore)
136 {
137 ScenarioData& data = _scenarioData[scenario->ID];
138 data.Entry = scenario;
139 data.Steps = std::move(scenarioSteps[scenario->ID]);
140 }
141}
142
144{
145 uint32 oldMSTime = getMSTime();
146
147 _scenarioPOIStore.clear(); // need for reload case
148
149 uint32 count = 0;
150
151 // 0 1 2 3 4 5 6 7 8 9
152 QueryResult result = WorldDatabase.Query("SELECT CriteriaTreeID, BlobIndex, Idx1, MapID, UiMapID, Priority, Flags, WorldEffectID, PlayerConditionID, NavigationPlayerConditionID FROM scenario_poi ORDER BY CriteriaTreeID, Idx1");
153 if (!result)
154 {
155 TC_LOG_ERROR("server.loading", ">> Loaded 0 scenario POI definitions. DB table `scenario_poi` is empty.");
156 return;
157 }
158
159 // 0 1 2 3 4
160 QueryResult pointsResult = WorldDatabase.Query("SELECT CriteriaTreeID, Idx1, X, Y, Z FROM scenario_poi_points ORDER BY CriteriaTreeID DESC, Idx1, Idx2");
161
162 std::unordered_map<int32, std::map<int32, std::vector<ScenarioPOIPoint>>> allPoints;
163
164 if (pointsResult)
165 {
166 Field* fields = pointsResult->Fetch();
167
168 do
169 {
170 fields = pointsResult->Fetch();
171
172 int32 CriteriaTreeID = fields[0].GetInt32();
173 int32 Idx1 = fields[1].GetInt32();
174 int32 X = fields[2].GetInt32();
175 int32 Y = fields[3].GetInt32();
176 int32 Z = fields[4].GetInt32();
177
178 allPoints[CriteriaTreeID][Idx1].emplace_back(X, Y, Z);
179 } while (pointsResult->NextRow());
180 }
181
182 do
183 {
184 Field* fields = result->Fetch();
185
186 int32 criteriaTreeID = fields[0].GetInt32();
187 int32 blobIndex = fields[1].GetInt32();
188 int32 idx1 = fields[2].GetInt32();
189 int32 mapID = fields[3].GetInt32();
190 int32 uiMapID = fields[4].GetInt32();
191 int32 priority = fields[5].GetInt32();
192 int32 flags = fields[6].GetInt32();
193 int32 worldEffectID = fields[7].GetInt32();
194 int32 playerConditionID = fields[8].GetInt32();
195 int32 navigationPlayerConditionID = fields[9].GetInt32();
196
197 if (!sCriteriaMgr->GetCriteriaTree(criteriaTreeID))
198 TC_LOG_ERROR("sql.sql", "`scenario_poi` CriteriaTreeID ({}) Idx1 ({}) does not correspond to a valid criteria tree", criteriaTreeID, idx1);
199
200 if (std::map<int32, std::vector<ScenarioPOIPoint>>* blobs = Trinity::Containers::MapGetValuePtr(allPoints, criteriaTreeID))
201 {
202 if (std::vector<ScenarioPOIPoint>* points = Trinity::Containers::MapGetValuePtr(*blobs, idx1))
203 {
204 _scenarioPOIStore[criteriaTreeID].emplace_back(blobIndex, mapID, uiMapID, priority, flags, worldEffectID, playerConditionID, navigationPlayerConditionID, std::move(*points));
205 ++count;
206 continue;
207 }
208 }
209
210 TC_LOG_ERROR("server.loading", "Table scenario_poi references unknown scenario poi points for criteria tree id {} POI id {}", criteriaTreeID, blobIndex);
211
212 } while (result->NextRow());
213
214 TC_LOG_INFO("server.loading", ">> Loaded {} scenario POI definitions in {} ms", count, GetMSTimeDiffToNow(oldMSTime));
215}
216
218{
219 auto itr = _scenarioPOIStore.find(criteriaTreeID);
220 if (itr != _scenarioPOIStore.end())
221 return &itr->second;
222
223 return nullptr;
224}
#define sCriteriaMgr
DB2Storage< ScenarioEntry > sScenarioStore("Scenario.db2", &ScenarioLoadInfo::Instance)
DB2Storage< ScenarioStepEntry > sScenarioStepStore("ScenarioStep.db2", &ScenarioStepLoadInfo::Instance)
std::shared_ptr< ResultSet > QueryResult
DatabaseWorkerPool< WorldDatabaseConnection > WorldDatabase
Accessor to the world database.
Definition: DatabaseEnv.cpp:20
uint8_t uint8
Definition: Define.h:144
int32_t int32
Definition: Define.h:138
uint32_t uint32
Definition: Define.h:142
uint16 flags
Definition: DisableMgr.cpp:49
#define ASSERT
Definition: Errors.h:68
#define TC_LOG_ERROR(filterType__,...)
Definition: Log.h:165
#define TC_LOG_INFO(filterType__,...)
Definition: Log.h:159
std::vector< ScenarioPOI > ScenarioPOIVector
Definition: ScenarioMgr.h:96
#define MAX_ALLOWED_SCENARIO_POI_QUERY_SIZE
TeamId
@ 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:90
uint8 GetUInt8() const
Definition: Field.cpp:30
uint32 GetUInt32() const
Definition: Field.cpp:62
int32 GetInt32() const
Definition: Field.cpp:70
Difficulty GetDifficultyID() const
Definition: Map.h:324
uint32 GetId() const
Definition: Map.cpp:3228
ScenarioDataContainer _scenarioData
Definition: ScenarioMgr.h:117
ScenarioDBDataContainer _scenarioDBData
Definition: ScenarioMgr.h:119
void LoadDBData()
Definition: ScenarioMgr.cpp:63
void LoadDB2Data()
ScenarioPOIVector const * GetScenarioPOIs(int32 criteriaTreeID) const
ScenarioPOIContainer _scenarioPOIStore
Definition: ScenarioMgr.h:118
void LoadScenarioPOI()
static ScenarioMgr * Instance()
Definition: ScenarioMgr.cpp:27
InstanceScenario * CreateInstanceScenario(InstanceMap *map, TeamId team) const
Definition: ScenarioMgr.cpp:33
auto MapGetValuePtr(M &map, typename M::key_type const &key)
Definition: MapUtils.h:29
uint8 DifficultyID
Definition: ScenarioMgr.h:48
uint32 Scenario_H
Definition: ScenarioMgr.h:50
uint32 Scenario_A
Definition: ScenarioMgr.h:49
std::map< uint8, ScenarioStepEntry const * > Steps
Definition: ScenarioMgr.h:36
ScenarioEntry const * Entry
Definition: ScenarioMgr.h:35