PageRenderTime 39ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 0ms

/src/server/game/Conditions/DisableMgr.cpp

https://github.com/Titan-Project/TrilliumEMU
C++ | 361 lines | 299 code | 36 blank | 26 comment | 77 complexity | b63216f87ea9f5c4b79fc1ffe1796aee MD5 | raw file
  1. /*
  2. * Copyright (C) 2005 - 2011 MaNGOS <http://www.getmangos.org/>
  3. *
  4. * Copyright (C) 2008 - 2011 TrinityCore <http://www.trinitycore.org/>
  5. *
  6. * Copyright (C) 2011 TrilliumEMU <http://www.trilliumemu.org/>
  7. *
  8. * This program is free software; you can redistribute it and/or modify it
  9. * under the terms of the GNU General Public License as published by the
  10. * Free Software Foundation; either version 2 of the License, or (at your
  11. * option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful, but WITHOUT
  14. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  15. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  16. * more details.
  17. *
  18. * You should have received a copy of the GNU General Public License along
  19. * with this program. If not, see <http://www.gnu.org/licenses/>.
  20. */
  21. #include "DisableMgr.h"
  22. #include "ObjectMgr.h"
  23. #include "OutdoorPvP.h"
  24. #include "SpellMgr.h"
  25. #include "VMapManager2.h"
  26. namespace DisableMgr
  27. {
  28. namespace
  29. {
  30. struct DisableData
  31. {
  32. uint8 flags;
  33. std::set<uint32> params[2]; // params0, params1
  34. };
  35. // single disables here with optional data
  36. typedef std::map<uint32, DisableData> DisableTypeMap;
  37. // global disable map by source
  38. typedef std::map<DisableType, DisableTypeMap> DisableMap;
  39. DisableMap m_DisableMap;
  40. uint8 MAX_DISABLE_TYPES = 7;
  41. }
  42. void LoadDisables()
  43. {
  44. uint32 oldMSTime = getMSTime();
  45. // reload case
  46. for (DisableMap::iterator itr = m_DisableMap.begin(); itr != m_DisableMap.end(); ++itr)
  47. itr->second.clear();
  48. m_DisableMap.clear();
  49. QueryResult result = WorldDatabase.Query("SELECT sourceType, entry, flags, params_0, params_1 FROM disables");
  50. uint32 total_count = 0;
  51. if (!result)
  52. {
  53. sLog->outString(">> Loaded 0 disables. DB table `disables` is empty!");
  54. sLog->outString();
  55. return;
  56. }
  57. Field* fields;
  58. do
  59. {
  60. fields = result->Fetch();
  61. DisableType type = DisableType(fields[0].GetUInt32());
  62. if (type >= MAX_DISABLE_TYPES)
  63. {
  64. sLog->outErrorDb("Invalid type %u specified in `disables` table, skipped.", type);
  65. continue;
  66. }
  67. uint32 entry = fields[1].GetUInt32();
  68. uint8 flags = fields[2].GetUInt8();
  69. std::string params_0 = fields[3].GetString();
  70. std::string params_1 = fields[4].GetString();
  71. DisableData data;
  72. data.flags = flags;
  73. switch (type)
  74. {
  75. case DISABLE_TYPE_SPELL:
  76. if (!(sSpellMgr->GetSpellInfo(entry) || flags & SPELL_DISABLE_DEPRECATED_SPELL))
  77. {
  78. sLog->outErrorDb("Spell entry %u from `disables` doesn't exist in dbc, skipped.", entry);
  79. continue;
  80. }
  81. if (!flags || flags > MAX_SPELL_DISABLE_TYPE)
  82. {
  83. sLog->outErrorDb("Disable flags for spell %u are invalid, skipped.", entry);
  84. continue;
  85. }
  86. if (flags & SPELL_DISABLE_MAP)
  87. {
  88. Tokens tokens(params_0, ',');
  89. for (uint8 i = 0; i < tokens.size(); )
  90. data.params[0].insert(atoi(tokens[i++]));
  91. }
  92. if (flags & SPELL_DISABLE_AREA)
  93. {
  94. Tokens tokens(params_1, ',');
  95. for (uint8 i = 0; i < tokens.size(); )
  96. data.params[1].insert(atoi(tokens[i++]));
  97. }
  98. break;
  99. // checked later
  100. case DISABLE_TYPE_QUEST:
  101. break;
  102. case DISABLE_TYPE_MAP:
  103. {
  104. MapEntry const* mapEntry = sMapStore.LookupEntry(entry);
  105. if (!mapEntry)
  106. {
  107. sLog->outErrorDb("Map entry %u from `disables` doesn't exist in dbc, skipped.", entry);
  108. continue;
  109. }
  110. bool isFlagInvalid = false;
  111. switch (mapEntry->map_type)
  112. {
  113. case MAP_COMMON:
  114. if (flags)
  115. isFlagInvalid = true;
  116. break;
  117. case MAP_INSTANCE:
  118. case MAP_RAID:
  119. if (flags & DUNGEON_STATUSFLAG_HEROIC && !GetMapDifficultyData(entry, DUNGEON_DIFFICULTY_HEROIC))
  120. isFlagInvalid = true;
  121. else if (flags & RAID_STATUSFLAG_10MAN_HEROIC && !GetMapDifficultyData(entry, RAID_DIFFICULTY_10MAN_HEROIC))
  122. isFlagInvalid = true;
  123. else if (flags & RAID_STATUSFLAG_25MAN_HEROIC && !GetMapDifficultyData(entry, RAID_DIFFICULTY_25MAN_HEROIC))
  124. isFlagInvalid = true;
  125. break;
  126. case MAP_BATTLEGROUND:
  127. case MAP_ARENA:
  128. sLog->outErrorDb("Battleground map %u specified to be disabled in map case, skipped.", entry);
  129. continue;
  130. }
  131. if (isFlagInvalid)
  132. {
  133. sLog->outErrorDb("Disable flags for map %u are invalid, skipped.", entry);
  134. continue;
  135. }
  136. break;
  137. }
  138. case DISABLE_TYPE_BATTLEGROUND:
  139. if (!sBattlemasterListStore.LookupEntry(entry))
  140. {
  141. sLog->outErrorDb("Battleground entry %u from `disables` doesn't exist in dbc, skipped.", entry);
  142. continue;
  143. }
  144. if (flags)
  145. sLog->outErrorDb("Disable flags specified for battleground %u, useless data.", entry);
  146. break;
  147. case DISABLE_TYPE_OUTDOORPVP:
  148. if (entry > MAX_OUTDOORPVP_TYPES)
  149. {
  150. sLog->outErrorDb("OutdoorPvPTypes value %u from `disables` is invalid, skipped.", entry);
  151. continue;
  152. }
  153. if (flags)
  154. sLog->outErrorDb("Disable flags specified for outdoor PvP %u, useless data.", entry);
  155. break;
  156. case DISABLE_TYPE_ACHIEVEMENT_CRITERIA:
  157. if (!sAchievementCriteriaStore.LookupEntry(entry))
  158. {
  159. sLog->outErrorDb("Achievement Criteria entry %u from `disables` doesn't exist in dbc, skipped.", entry);
  160. continue;
  161. }
  162. if (flags)
  163. sLog->outErrorDb("Disable flags specified for Achievement Criteria %u, useless data.", entry);
  164. break;
  165. case DISABLE_TYPE_VMAP:
  166. {
  167. MapEntry const* mapEntry = sMapStore.LookupEntry(entry);
  168. if (!mapEntry)
  169. {
  170. sLog->outErrorDb("Map entry %u from `disables` doesn't exist in dbc, skipped.", entry);
  171. continue;
  172. }
  173. switch (mapEntry->map_type)
  174. {
  175. case MAP_COMMON:
  176. if (flags & VMAP_DISABLE_AREAFLAG)
  177. sLog->outString("Areaflag disabled for world map %u.", entry);
  178. if (flags & VMAP_DISABLE_LIQUIDSTATUS)
  179. sLog->outString("Liquid status disabled for world map %u.", entry);
  180. break;
  181. case MAP_INSTANCE:
  182. case MAP_RAID:
  183. if (flags & VMAP_DISABLE_HEIGHT)
  184. sLog->outString("Height disabled for instance map %u.", entry);
  185. if (flags & VMAP_DISABLE_LOS)
  186. sLog->outString("LoS disabled for instance map %u.", entry);
  187. break;
  188. case MAP_BATTLEGROUND:
  189. if (flags & VMAP_DISABLE_HEIGHT)
  190. sLog->outString("Height disabled for battleground map %u.", entry);
  191. if (flags & VMAP_DISABLE_LOS)
  192. sLog->outString("LoS disabled for battleground map %u.", entry);
  193. break;
  194. case MAP_ARENA:
  195. if (flags & VMAP_DISABLE_HEIGHT)
  196. sLog->outString("Height disabled for arena map %u.", entry);
  197. if (flags & VMAP_DISABLE_LOS)
  198. sLog->outString("LoS disabled for arena map %u.", entry);
  199. break;
  200. default:
  201. break;
  202. }
  203. break;
  204. }
  205. default:
  206. break;
  207. }
  208. m_DisableMap[type].insert(DisableTypeMap::value_type(entry, data));
  209. ++total_count;
  210. }
  211. while (result->NextRow());
  212. sLog->outString(">> Loaded %u disables in %u ms", total_count, GetMSTimeDiffToNow(oldMSTime));
  213. sLog->outString();
  214. }
  215. void CheckQuestDisables()
  216. {
  217. uint32 oldMSTime = getMSTime();
  218. uint32 count = m_DisableMap[DISABLE_TYPE_QUEST].size();
  219. if (!count)
  220. {
  221. sLog->outString(">> Checked 0 quest disables.");
  222. sLog->outString();
  223. return;
  224. }
  225. // check only quests, rest already done at startup
  226. for (DisableTypeMap::iterator itr = m_DisableMap[DISABLE_TYPE_QUEST].begin(); itr != m_DisableMap[DISABLE_TYPE_QUEST].end();)
  227. {
  228. const uint32 entry = itr->first;
  229. if (!sObjectMgr->GetQuestTemplate(entry))
  230. {
  231. sLog->outErrorDb("Quest entry %u from `disables` doesn't exist, skipped.", entry);
  232. m_DisableMap[DISABLE_TYPE_QUEST].erase(itr++);
  233. continue;
  234. }
  235. if (itr->second.flags)
  236. sLog->outErrorDb("Disable flags specified for quest %u, useless data.", entry);
  237. ++itr;
  238. }
  239. sLog->outString(">> Checked %u quest disables in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
  240. sLog->outString();
  241. }
  242. bool IsDisabledFor(DisableType type, uint32 entry, Unit const* unit, uint8 flags)
  243. {
  244. ASSERT(type < MAX_DISABLE_TYPES);
  245. if (m_DisableMap[type].empty())
  246. return false;
  247. DisableTypeMap::iterator itr = m_DisableMap[type].find(entry);
  248. if (itr == m_DisableMap[type].end()) // not disabled
  249. return false;
  250. switch (type)
  251. {
  252. case DISABLE_TYPE_SPELL:
  253. {
  254. uint8 flags = itr->second.flags;
  255. if (unit)
  256. {
  257. if ((flags & SPELL_DISABLE_PLAYER && unit->GetTypeId() == TYPEID_PLAYER) ||
  258. (unit->GetTypeId() == TYPEID_UNIT && ((unit->ToCreature()->isPet() && flags & SPELL_DISABLE_PET) || flags & SPELL_DISABLE_CREATURE)))
  259. {
  260. if (flags & SPELL_DISABLE_MAP)
  261. {
  262. std::set<uint32> const& mapIds = itr->second.params[0];
  263. if (mapIds.find(unit->GetMapId()) != mapIds.end())
  264. return true; // Spell is disabled on current map
  265. if (!(flags & SPELL_DISABLE_AREA))
  266. return false; // Spell is disabled on another map, but not this one, return false
  267. // Spell is disabled in an area, but not explicitly our current mapId. Continue processing.
  268. }
  269. if (flags & SPELL_DISABLE_AREA)
  270. {
  271. std::set<uint32> const& areaIds = itr->second.params[1];
  272. if (areaIds.find(unit->GetAreaId()) != areaIds.end())
  273. return true; // Spell is disabled in this area
  274. return false; // Spell is disabled in another area, but not this one, return false
  275. }
  276. else
  277. return true; // Spell disabled for all maps
  278. }
  279. return false;
  280. }
  281. else if (flags & SPELL_DISABLE_DEPRECATED_SPELL) // call not from spellcast
  282. return true;
  283. }
  284. case DISABLE_TYPE_MAP:
  285. if (Player const* player = unit->ToPlayer())
  286. {
  287. MapEntry const* mapEntry = sMapStore.LookupEntry(entry);
  288. if (mapEntry->IsDungeon())
  289. {
  290. uint8 disabledModes = itr->second.flags;
  291. Difficulty targetDifficulty = player->GetDifficulty(mapEntry->IsRaid());
  292. GetDownscaledMapDifficultyData(entry, targetDifficulty);
  293. switch (targetDifficulty)
  294. {
  295. case DUNGEON_DIFFICULTY_NORMAL:
  296. return disabledModes & DUNGEON_STATUSFLAG_NORMAL;
  297. case DUNGEON_DIFFICULTY_HEROIC:
  298. return disabledModes & DUNGEON_STATUSFLAG_HEROIC;
  299. case RAID_DIFFICULTY_10MAN_HEROIC:
  300. return disabledModes & RAID_STATUSFLAG_10MAN_HEROIC;
  301. case RAID_DIFFICULTY_25MAN_HEROIC:
  302. return disabledModes & RAID_STATUSFLAG_25MAN_HEROIC;
  303. }
  304. }
  305. else if (mapEntry->map_type == MAP_COMMON)
  306. return true;
  307. }
  308. return false;
  309. case DISABLE_TYPE_QUEST:
  310. if (!unit)
  311. return true;
  312. if (Player const* player = unit->ToPlayer())
  313. if (player->isGameMaster())
  314. return false;
  315. return true;
  316. case DISABLE_TYPE_BATTLEGROUND:
  317. case DISABLE_TYPE_OUTDOORPVP:
  318. case DISABLE_TYPE_ACHIEVEMENT_CRITERIA:
  319. return true;
  320. case DISABLE_TYPE_VMAP:
  321. return flags & itr->second.flags;
  322. }
  323. return false;
  324. }
  325. } // Namespace