75#include <G3D/g3dmath.h>
108 std::string res =
"";
177 size_t pos = name.find(
'-');
178 if (pos != std::string::npos)
190 Unit const* summoner =
nullptr;
221 _equipmentSetGuid(1),
225 _gameObjectSpawnId(1),
243 if (data.size() <=
size_t(localeConstant))
246 data.resize(localeConstant + 1);
249 data[localeConstant] = value.empty() ?
"" : value;
259 QueryResult result =
WorldDatabase.Query(
"SELECT entry, locale, Name, NameAlt, Title, TitleAlt FROM creature_template_locale");
265 Field* fields = result->Fetch();
280 }
while (result->NextRow());
292 QueryResult result =
WorldDatabase.Query(
"SELECT MenuID, OptionID, Locale, OptionText, BoxText FROM gossip_menu_option_locale");
299 Field* fields = result->Fetch();
312 }
while (result->NextRow());
330 Field* fields = result->Fetch();
341 }
while (result->NextRow());
376 TC_LOG_INFO(
"server.loading",
">> Loaded 0 creature template definitions. DB table `creature_template` is empty.");
383 Field* fields = result->Fetch();
385 }
while (result->NextRow());
405 creatureTemplate.
Entry = entry;
434 creatureTemplate.
type =
uint32(fields[27].GetUInt8());
440 creatureTemplate.
spells[i] = 0;
446 if (!fields[31].IsNull())
449 if (!fields[32].IsNull())
452 if (!fields[33].IsNull())
455 if (!fields[34].IsNull())
479 TC_LOG_INFO(
"server.loading",
">> Loaded 0 creature template gossip definitions. DB table `creature_template_gossip` is empty.");
487 Field* fields = result->Fetch();
495 TC_LOG_ERROR(
"sql.sql",
"creature_template_gossip has gossip definitions for creature {} but this creature doesn't exist", creatureID);
500 if (menuBounds.first == menuBounds.second)
502 TC_LOG_ERROR(
"sql.sql",
"creature_template_gossip has gossip definitions for menu id {} but this menu doesn't exist", menuID);
511 }
while (result->NextRow());
521 QueryResult result =
WorldDatabase.Query(
"SELECT CreatureID, School, Resistance FROM creature_template_resistance");
525 TC_LOG_INFO(
"server.loading",
">> Loaded 0 creature template resistance definitions. DB table `creature_template_resistance` is empty.");
533 Field* fields = result->Fetch();
540 TC_LOG_ERROR(
"sql.sql",
"creature_template_resistance has resistance definitions for creature {} but this school {} doesn't exist", creatureID, school);
547 TC_LOG_ERROR(
"sql.sql",
"creature_template_resistance has resistance definitions for creature {} but this creature doesn't exist", creatureID);
556 }
while (result->NextRow());
570 TC_LOG_INFO(
"server.loading",
">> Loaded 0 creature template spell definitions. DB table `creature_template_spell` is empty.");
578 Field* fields = result->Fetch();
585 TC_LOG_ERROR(
"sql.sql",
"creature_template_spell has spell definitions for creature {} with a incorrect index {}", creatureID, index);
592 TC_LOG_ERROR(
"sql.sql",
"creature_template_spell has spell definitions for creature {} but this creature doesn't exist", creatureID);
601 }
while (result->NextRow());
611 QueryResult result =
WorldDatabase.Query(
"SELECT CreatureID, CreatureDisplayID, DisplayScale, Probability FROM creature_template_model ORDER BY Idx ASC");
615 TC_LOG_INFO(
"server.loading",
">> Loaded 0 creature template model definitions. DB table `creature_template_model` is empty.");
622 Field* fields = result->Fetch();
626 float displayScale = fields[2].
GetFloat();
627 float probability = fields[3].
GetFloat();
632 TC_LOG_ERROR(
"sql.sql",
"Creature template (Entry: {}) does not exist but has a record in `creature_template_model`", creatureId);
639 TC_LOG_ERROR(
"sql.sql",
"Creature (Entry: {}) lists non-existing CreatureDisplayID id ({}), this can crash the client.", creatureId, creatureDisplayId);
645 TC_LOG_ERROR(
"sql.sql",
"No model data exist for `CreatureDisplayID` = {} listed by creature (Entry: {}).", creatureDisplayId, creatureId);
647 if (displayScale <= 0.0f)
654 while (result->NextRow());
664 QueryResult result =
WorldDatabase.Query(
"SELECT CreatureID, CreatureIDVisibleToSummoner, GroundMountDisplayID, FlyingMountDisplayID, DespawnOnQuestsRemoved FROM creature_summoned_data");
668 TC_LOG_INFO(
"server.loading",
">> Loaded 0 creature summoned data definitions. DB table `creature_summoned_data` is empty.");
674 Field* fields = result->Fetch();
679 TC_LOG_ERROR(
"sql.sql",
"Table `creature_summoned_data` references non-existing creature {}, skipped", creatureId);
685 if (!fields[1].IsNull())
690 TC_LOG_ERROR(
"sql.sql",
"Table `creature_summoned_data` references non-existing creature {} in CreatureIDVisibleToSummoner for creature {}, set to 0",
696 if (!fields[2].IsNull())
701 TC_LOG_ERROR(
"sql.sql",
"Table `creature_summoned_data` references non-existing display id {} in GroundMountDisplayID for creature {}, set to 0",
707 if (!fields[3].IsNull())
712 TC_LOG_ERROR(
"sql.sql",
"Table `creature_summoned_data` references non-existing display id {} in FlyingMountDisplayID for creature {}, set to 0",
718 if (!fields[4].IsNull())
720 std::vector<uint32> questList;
721 for (std::string_view questStr :
Trinity::Tokenize(fields[4].GetStringView(),
',',
false))
730 TC_LOG_ERROR(
"sql.sql",
"Table `creature_summoned_data` references non-existing quest {} in DespawnOnQuestsRemoved for creature {}, skipping",
731 *questId, creatureId);
735 questList.push_back(*questId);
738 if (!questList.empty())
742 }
while (result->NextRow());
752 QueryResult result =
WorldDatabase.Query(
"SELECT entry, PathId, mount, StandState, AnimTier, VisFlags, SheathState, PvPFlags, emote, aiAnimKit, movementAnimKit, meleeAnimKit, visibilityDistanceType, auras FROM creature_template_addon");
756 TC_LOG_INFO(
"server.loading",
">> Loaded 0 creature template addon definitions. DB table `creature_template_addon` is empty.");
763 Field* fields = result->Fetch();
769 TC_LOG_ERROR(
"sql.sql",
"Creature template (Entry: {}) does not exist but has a record in `creature_template_addon`", entry);
788 for (std::string_view aura :
Trinity::Tokenize(fields[13].GetStringView(),
' ',
false))
796 TC_LOG_ERROR(
"sql.sql",
"Creature (Entry: {}) has wrong spell '{}' defined in `auras` field in `creature_template_addon`.", entry, std::string(aura));
801 TC_LOG_ERROR(
"sql.sql",
"Creature (Entry: {}) has SPELL_AURA_CONTROL_VEHICLE aura {} defined in `auras` field in `creature_template_addon`.", entry, spellInfo->
Id);
803 if (std::find(creatureAddon.
auras.begin(), creatureAddon.
auras.end(), spellInfo->
Id) != creatureAddon.
auras.end())
805 TC_LOG_ERROR(
"sql.sql",
"Creature (Entry: {}) has duplicate aura (spell {}) in `auras` field in `creature_template_addon`.", entry, spellInfo->
Id);
811 TC_LOG_ERROR(
"sql.sql",
"Creature (Entry: {}) has temporary aura (spell {}) in `auras` field in `creature_template_addon`.", entry, spellInfo->
Id);
815 creatureAddon.
auras.push_back(spellInfo->
Id);
818 if (creatureAddon.
mount)
822 TC_LOG_ERROR(
"sql.sql",
"Creature (Entry: {}) has invalid displayInfoId ({}) for mount defined in `creature_template_addon`", entry, creatureAddon.
mount);
823 creatureAddon.
mount = 0;
829 TC_LOG_ERROR(
"sql.sql",
"Creature (Entry: {}) has invalid unit stand state ({}) defined in `creature_template_addon`. Truncated to 0.", entry, creatureAddon.
standState);
835 TC_LOG_ERROR(
"sql.sql",
"Creature (Entry: {}) has invalid animation tier ({}) defined in `creature_template_addon`. Truncated to 0.", entry, creatureAddon.
animTier);
841 TC_LOG_ERROR(
"sql.sql",
"Creature (Entry: {}) has invalid sheath state ({}) defined in `creature_template_addon`. Truncated to 0.", entry, creatureAddon.
sheathState);
849 TC_LOG_ERROR(
"sql.sql",
"Creature (Entry: {}) has invalid emote ({}) defined in `creature_template_addon`.", entry, creatureAddon.
emote);
850 creatureAddon.
emote = 0;
855 TC_LOG_ERROR(
"sql.sql",
"Creature (Entry: {}) has invalid aiAnimKit ({}) defined in `creature_template_addon`.", entry, creatureAddon.
aiAnimKit);
861 TC_LOG_ERROR(
"sql.sql",
"Creature (Entry: {}) has invalid movementAnimKit ({}) defined in `creature_template_addon`.", entry, creatureAddon.
movementAnimKit);
867 TC_LOG_ERROR(
"sql.sql",
"Creature (Entry: {}) has invalid meleeAnimKit ({}) defined in `creature_template_addon`.", entry, creatureAddon.
meleeAnimKit);
873 TC_LOG_ERROR(
"sql.sql",
"Creature (Entry: {}) has invalid visibilityDistanceType ({}) defined in `creature_template_addon`.",
880 while (result->NextRow());
890 QueryResult result =
WorldDatabase.Query(
"SELECT Entry, NoNPCDamageBelowHealthPct FROM creature_template_sparring");
894 TC_LOG_INFO(
"server.loading",
">> Loaded 0 creature template sparring definitions. DB table `creature_template_sparring` is empty.");
901 Field* fields = result->Fetch();
904 float noNPCDamageBelowHealthPct = fields[1].
GetFloat();
908 TC_LOG_ERROR(
"sql.sql",
"Creature template (Entry: {}) does not exist but has a record in `creature_template_sparring`", entry);
912 if (noNPCDamageBelowHealthPct <= 0 || noNPCDamageBelowHealthPct > 100)
914 TC_LOG_ERROR(
"sql.sql",
"Creature (Entry: {}) has invalid NoNPCDamageBelowHealthPct ({}) defined in `creature_template_sparring`. Skipping",
915 entry, noNPCDamageBelowHealthPct);
921 }
while (result->NextRow());
931 QueryResult result =
WorldDatabase.Query(
"SELECT Entry, DifficultyID, LevelScalingDeltaMin, LevelScalingDeltaMax, ContentTuningID, HealthScalingExpansion, "
933 "HealthModifier, ManaModifier, ArmorModifier, DamageModifier, CreatureDifficultyID, TypeFlags, TypeFlags2, "
935 "LootID, PickPocketLootID, SkinLootID, GoldMin, GoldMax,"
937 "StaticFlags1, StaticFlags2, StaticFlags3, StaticFlags4, StaticFlags5, StaticFlags6, StaticFlags7, StaticFlags8 "
938 "FROM creature_template_difficulty ORDER BY Entry");
942 TC_LOG_INFO(
"server.loading",
">> Loaded 0 creature template difficulty definitions. DB table `creature_template_difficulty` is empty.");
949 Field* fields = result->Fetch();
957 TC_LOG_ERROR(
"sql.sql",
"Creature template (Entry: {}) does not exist but has a record in `creature_template_difficulty`", entry);
987 TC_LOG_ERROR(
"sql.sql",
"Table `creature_template_difficulty` lists creature (ID: {}) with invalid `HealthScalingExpansion` {}. Ignored and set to 0.",
994 TC_LOG_ERROR(
"sql.sql",
"Table `creature_template_difficulty` lists creature (ID: {}) with `GoldMin` {} greater than `GoldMax` {}, setting `GoldMax` to {}.",
999 itr->second.difficultyStore[difficulty] = creatureDifficulty;
1002 }
while (result->NextRow());
1012 if (!cInfo->
AIName.empty())
1017 TC_LOG_ERROR(
"sql.sql",
"Creature (Entry: {}) has non-registered `AIName` '{}' set, removing", cInfo->
Entry, cInfo->
AIName);
1025 TC_LOG_ERROR(
"sql.sql",
"Creature (Entry: {}) has not-allowed `AIName` '{}' set, removing", cInfo->
Entry, cInfo->
AIName);
1032 if (!factionTemplate)
1034 TC_LOG_ERROR(
"sql.sql",
"Creature (Entry: {}) has non-existing faction template ({}). This can lead to crashes, set to faction 35.", cInfo->
Entry, cInfo->
faction);
1044 TC_LOG_ERROR(
"sql.sql",
"Creature (Entry: {}) lists non-existing creature entry {} in `KillCredit{}`.", cInfo->
Entry, cInfo->
KillCredit[k], k + 1);
1050 if (cInfo->
Models.empty())
1051 TC_LOG_ERROR(
"sql.sql",
"Creature (Entry: {}) does not have any existing display id in creature_template_model.", cInfo->
Entry);
1055 TC_LOG_ERROR(
"sql.sql",
"Creature (Entry: {}) has invalid unit_class ({}) in creature_template. Set to 1 (UNIT_CLASS_WARRIOR).", cInfo->
Entry, cInfo->
unit_class);
1061 TC_LOG_ERROR(
"sql.sql",
"Creature (Entry: {}) has invalid spell school value ({}) in `dmgschool`.", cInfo->
Entry, cInfo->
dmgschool);
1079 TC_LOG_ERROR(
"sql.sql",
"Creature (Entry: {}) has wrong value ({}) in speed_run, set to 1.14286.", cInfo->
Entry, cInfo->
speed_run);
1085 TC_LOG_ERROR(
"sql.sql",
"Creature (Entry: {}) has invalid creature type ({}) in `type`.", cInfo->
Entry, cInfo->
type);
1091 TC_LOG_ERROR(
"sql.sql",
"Creature (Entry: {}) has invalid creature family ({}) in `family`.", cInfo->
Entry, cInfo->
family);
1102 TC_LOG_ERROR(
"sql.sql",
"Creature (Entry: {}) has a non-existing VehicleId ({}). This *WILL* cause the client to freeze!", cInfo->
Entry, cInfo->
VehicleId);
1111 TC_LOG_ERROR(
"sql.sql",
"Creature (Entry: {}) has non-existing Spell{} ({}), set to 0.", cInfo->
Entry, j+1, cInfo->
spells[j]);
1118 TC_LOG_ERROR(
"sql.sql",
"Creature (Entry: {}) has wrong movement generator type ({}), ignored and set to IDLE.", cInfo->
Entry, cInfo->
MovementType);
1124 TC_LOG_ERROR(
"sql.sql",
"Table `creature_template` lists creature (Entry: {}) with `RequiredExpansion` {}. Ignored and set to 0.", cInfo->
Entry, cInfo->
RequiredExpansion);
1130 TC_LOG_ERROR(
"sql.sql",
"Table `creature_template` lists creature (Entry: {}) with disallowed `flags_extra` {}, removing incorrect flag.", cInfo->
Entry, badFlags);
1136 TC_LOG_ERROR(
"sql.sql",
"Table `creature_template` lists creature (Entry: {}) with disallowed `unit_flags` {}, removing incorrect flag.", cInfo->
Entry, disallowedUnitFlags);
1142 TC_LOG_ERROR(
"sql.sql",
"Table `creature_template` lists creature (Entry: {}) with disallowed `unit_flags2` {}, removing incorrect flag.", cInfo->
Entry, disallowedUnitFlags2);
1148 TC_LOG_ERROR(
"sql.sql",
"Table `creature_template` lists creature (Entry: {}) with disallowed `unit_flags3` {}, removing incorrect flag.", cInfo->
Entry, disallowedUnitFlags3);
1153 TC_LOG_INFO(
"sql.sql",
"Creature (Entry: {}) has assigned gossip menu, but npcflag does not include UNIT_NPC_FLAG_GOSSIP.", cInfo->
Entry);
1155 TC_LOG_INFO(
"sql.sql",
"Creature (Entry: {}) has npcflag UNIT_NPC_FLAG_GOSSIP, but gossip menu is unassigned.", cInfo->
Entry);
1168 TC_LOG_ERROR(
"sql.sql",
"`{}`.`Chase` wrong value ({}) for Id {}, setting to Run.",
1175 TC_LOG_ERROR(
"sql.sql",
"`{}`.`Random` wrong value ({}) for Id {}, setting to Walk.",
1186 QueryResult result =
WorldDatabase.Query(
"SELECT guid, PathId, mount, StandState, AnimTier, VisFlags, SheathState, PvPFlags, emote, aiAnimKit, movementAnimKit, meleeAnimKit, visibilityDistanceType, auras FROM creature_addon");
1190 TC_LOG_INFO(
"server.loading",
">> Loaded 0 creature addon definitions. DB table `creature_addon` is empty.");
1197 Field* fields = result->Fetch();
1204 TC_LOG_ERROR(
"sql.sql",
"Creature (GUID: {}) does not exist but has a record in `creature_addon`", guid);
1214 TC_LOG_ERROR(
"sql.sql",
"Creature (GUID {}) has movement type set to WAYPOINT_MOTION_TYPE but no path assigned", guid);
1229 for (std::string_view aura :
Trinity::Tokenize(fields[13].GetStringView(),
' ',
false))
1237 TC_LOG_ERROR(
"sql.sql",
"Creature (GUID: {}) has wrong spell '{}' defined in `auras` field in `creature_addon`.", guid, std::string(aura));
1242 TC_LOG_ERROR(
"sql.sql",
"Creature (GUID: {}) has SPELL_AURA_CONTROL_VEHICLE aura {} defined in `auras` field in `creature_addon`.", guid, spellInfo->
Id);
1244 if (std::find(creatureAddon.
auras.begin(), creatureAddon.
auras.end(), spellInfo->
Id) != creatureAddon.
auras.end())
1246 TC_LOG_ERROR(
"sql.sql",
"Creature (GUID: {}) has duplicate aura (spell {}) in `auras` field in `creature_addon`.", guid, spellInfo->
Id);
1252 TC_LOG_ERROR(
"sql.sql",
"Creature (GUID: {}) has temporary aura (spell {}) in `auras` field in `creature_addon`.", guid, spellInfo->
Id);
1256 creatureAddon.
auras.push_back(spellInfo->
Id);
1259 if (creatureAddon.
mount)
1263 TC_LOG_ERROR(
"sql.sql",
"Creature (GUID: {}) has invalid displayInfoId ({}) for mount defined in `creature_addon`", guid, creatureAddon.
mount);
1264 creatureAddon.
mount = 0;
1270 TC_LOG_ERROR(
"sql.sql",
"Creature (GUID: {}) has invalid unit stand state ({}) defined in `creature_addon`. Truncated to 0.", guid, creatureAddon.
standState);
1276 TC_LOG_ERROR(
"sql.sql",
"Creature (GUID: {}) has invalid animation tier ({}) defined in `creature_addon`. Truncated to 0.", guid, creatureAddon.
animTier);
1282 TC_LOG_ERROR(
"sql.sql",
"Creature (GUID: {}) has invalid sheath state ({}) defined in `creature_addon`. Truncated to 0.", guid, creatureAddon.
sheathState);
1290 TC_LOG_ERROR(
"sql.sql",
"Creature (GUID: {}) has invalid emote ({}) defined in `creature_addon`.", guid, creatureAddon.
emote);
1291 creatureAddon.
emote = 0;
1296 TC_LOG_ERROR(
"sql.sql",
"Creature (GUID: {}) has invalid aiAnimKit ({}) defined in `creature_addon`.", guid, creatureAddon.
aiAnimKit);
1302 TC_LOG_ERROR(
"sql.sql",
"Creature (GUID: {}) has invalid movementAnimKit ({}) defined in `creature_addon`.", guid, creatureAddon.
movementAnimKit);
1308 TC_LOG_ERROR(
"sql.sql",
"Creature (GUID: {}) has invalid meleeAnimKit ({}) defined in `creature_addon`.", guid, creatureAddon.
meleeAnimKit);
1314 TC_LOG_ERROR(
"sql.sql",
"Creature (GUID: {}) has invalid visibilityDistanceType ({}) defined in `creature_addon`.",
1321 while (result->NextRow());
1331 QueryResult result =
WorldDatabase.Query(
"SELECT guid, parent_rotation0, parent_rotation1, parent_rotation2, parent_rotation3, invisibilityType, invisibilityValue, WorldEffectID, AIAnimKitID FROM gameobject_addon");
1335 TC_LOG_INFO(
"server.loading",
">> Loaded 0 gameobject addon definitions. DB table `gameobject_addon` is empty.");
1342 Field* fields = result->Fetch();
1349 TC_LOG_ERROR(
"sql.sql",
"GameObject (GUID: {}) does not exist but has a record in `gameobject_addon`", guid);
1354 gameObjectAddon.
ParentRotation =
QuaternionData(fields[1].GetFloat(), fields[2].GetFloat(), fields[3].GetFloat(), fields[4].GetFloat());
1362 TC_LOG_ERROR(
"sql.sql",
"GameObject (GUID: {}) has invalid InvisibilityType in `gameobject_addon`, disabled invisibility", guid);
1369 TC_LOG_ERROR(
"sql.sql",
"GameObject (GUID: {}) has InvisibilityType set but has no InvisibilityValue in `gameobject_addon`, set to 1", guid);
1375 TC_LOG_ERROR(
"sql.sql",
"GameObject (GUID: {}) has invalid parent rotation in `gameobject_addon`, set to default", guid);
1381 TC_LOG_ERROR(
"sql.sql",
"GameObject (GUID: {}) has invalid WorldEffectID ({}) in `gameobject_addon`, set to 0.", guid, gameObjectAddon.
WorldEffectID);
1387 TC_LOG_ERROR(
"sql.sql",
"GameObject (GUID: {}) has invalid AIAnimKitID ({}) in `gameobject_addon`, set to 0.", guid, gameObjectAddon.
AIAnimKitID);
1393 while (result->NextRow());
1402 return &(itr->second);
1411 return &(itr->second);
1420 return &(itr->second);
1441 if (itr->second.empty())
1446 EquipmentInfoContainerInternal::const_iterator ritr = itr->second.begin();
1447 std::advance(ritr,
urand(0u, itr->second.size() - 1));
1448 id = std::distance(itr->second.begin(), ritr) + 1;
1449 return &ritr->second;
1453 EquipmentInfoContainerInternal::const_iterator itr2 = itr->second.find(
id);
1454 if (itr2 != itr->second.end())
1455 return &itr2->second;
1468 "ItemID2, AppearanceModID2, ItemVisual2, "
1470 "ItemID3, AppearanceModID3, ItemVisual3 "
1471 "FROM creature_equip_template");
1475 TC_LOG_INFO(
"server.loading",
">> Loaded 0 creature equipment templates. DB table `creature_equip_template` is empty!");
1482 Field* fields = result->Fetch();
1488 TC_LOG_ERROR(
"sql.sql",
"Creature template (CreatureID: {}) does not exist but has a record in `creature_equip_template`", entry);
1495 TC_LOG_ERROR(
"sql.sql",
"Creature equipment template with id 0 found for creature {}, skipped.", entry);
1512 TC_LOG_ERROR(
"sql.sql",
"Unknown item (ID={}) in creature_equip_template.ItemID{} for CreatureID = {} and ID={}, forced to 0.",
1521 TC_LOG_ERROR(
"sql.sql",
"Unknown item appearance for (ID={}, AppearanceModID={}) pair in creature_equip_template.ItemID{} creature_equip_template.AppearanceModID{} "
1522 "for CreatureID = {} and ID={}, forced to default.",
1533 TC_LOG_ERROR(
"sql.sql",
"Item (ID={}) in creature_equip_template.ItemID{} for CreatureID = {} and ID = {} is not equipable in a hand, forced to 0.",
1541 while (result->NextRow());
1554 "SELECT cmo.SpawnId,"
1555 "COALESCE(cmo.HoverInitiallyEnabled, ctm.HoverInitiallyEnabled),"
1556 "COALESCE(cmo.Chase, ctm.Chase),"
1557 "COALESCE(cmo.Random, ctm.Random),"
1558 "COALESCE(cmo.InteractionPauseTimer, ctm.InteractionPauseTimer) "
1559 "FROM creature_movement_override AS cmo "
1560 "LEFT JOIN creature AS c ON c.guid = cmo.SpawnId "
1561 "LEFT JOIN creature_template_movement AS ctm ON ctm.CreatureId = c.id");
1565 TC_LOG_INFO(
"server.loading",
">> Loaded 0 creature movement overrides. DB table `creature_movement_override` is empty!");
1571 Field* fields = result->Fetch();
1575 TC_LOG_ERROR(
"sql.sql",
"Creature (GUID: {}) does not exist but has a record in `creature_movement_override`", spawnId);
1580 if (!fields[1].IsNull())
1582 if (!fields[2].IsNull())
1584 if (!fields[3].IsNull())
1586 if (!fields[4].IsNull())
1591 while (result->NextRow());
1600 return &(itr->second);
1626#define ChooseCreatureFlagSource(field) ((data && data->field.has_value()) ? *data->field : cInfo->field)
1658#undef ChooseCreatureFlagSource
1677 if (creatureTemplate)
1679 auto itr = std::find_if(creatureTemplate->
Models.begin(), creatureTemplate->
Models.end(), [&](
CreatureModel const& templateModel)
1681 return templateModel.CreatureDisplayID == modelInfo->displayId_other_gender;
1683 if (itr != creatureTemplate->
Models.end())
1697 QueryResult result =
WorldDatabase.Query(
"SELECT DisplayID, BoundingRadius, CombatReach, DisplayID_Other_Gender FROM creature_model_info");
1701 TC_LOG_INFO(
"server.loading",
">> Loaded 0 creature model definitions. DB table `creature_model_info` is empty.");
1709 uint32 trigggerCreatureModelFileID[5] = { 124640, 124641, 124642, 343863, 439302 };
1713 Field* fields = result->Fetch();
1718 if (!creatureDisplay)
1720 TC_LOG_ERROR(
"sql.sql",
"Table `creature_model_info` has a non-existent DisplayID (ID: {}). Skipped.", displayId);
1744 TC_LOG_ERROR(
"sql.sql",
"Table `creature_model_info` has a non-existent DisplayID_Other_Gender (ID: {}) being used by DisplayID (ID: {}).", modelInfo.
displayId_other_gender, displayId);
1753 for (
uint32 i = 0; i < 5; ++i)
1755 if (modelData->FileDataID == trigggerCreatureModelFileID[i])
1765 while (result->NextRow());
1776 QueryResult result =
WorldDatabase.Query(
"SELECT guid, linkedGuid, linkType FROM linked_respawn ORDER BY guid ASC");
1780 TC_LOG_INFO(
"server.loading",
">> Loaded 0 linked respawns. DB table `linked_respawn` is empty.");
1786 Field* fields = result->Fetch();
1801 TC_LOG_ERROR(
"sql.sql",
"LinkedRespawn: Creature (guid) '{}' not found in creature table", guidLow);
1809 TC_LOG_ERROR(
"sql.sql",
"LinkedRespawn: Creature (linkedGuid) '{}' not found in creature table", linkedGuidLow);
1817 TC_LOG_ERROR(
"sql.sql",
"LinkedRespawn: Creature '{}' linking to Creature '{}' on an unpermitted map.", guidLow, linkedGuidLow);
1825 TC_LOG_ERROR(
"sql.sql",
"LinkedRespawn: Creature '{}' linking to Creature '{}' with not corresponding spawnMask", guidLow, linkedGuidLow);
1830 guid = ObjectGuid::Create<HighGuid::Creature>(slave->
mapId, slave->
id, guidLow);
1831 linkedGuid = ObjectGuid::Create<HighGuid::Creature>(master->
mapId, master->
id, linkedGuidLow);
1839 TC_LOG_ERROR(
"sql.sql",
"LinkedRespawn: Creature (guid) '{}' not found in creature table", guidLow);
1847 TC_LOG_ERROR(
"sql.sql",
"LinkedRespawn: Gameobject (linkedGuid) '{}' not found in gameobject table", linkedGuidLow);
1855 TC_LOG_ERROR(
"sql.sql",
"LinkedRespawn: Creature '{}' linking to Gameobject '{}' on an unpermitted map.", guidLow, linkedGuidLow);
1863 TC_LOG_ERROR(
"sql.sql",
"LinkedRespawn: Creature '{}' linking to Gameobject '{}' with not corresponding spawnMask", guidLow, linkedGuidLow);
1868 guid = ObjectGuid::Create<HighGuid::Creature>(slave->
mapId, slave->
id, guidLow);
1869 linkedGuid = ObjectGuid::Create<HighGuid::GameObject>(master->
mapId, master->
id, linkedGuidLow);
1877 TC_LOG_ERROR(
"sql.sql",
"LinkedRespawn: Gameobject (guid) '{}' not found in gameobject table", guidLow);
1885 TC_LOG_ERROR(
"sql.sql",
"LinkedRespawn: Gameobject (linkedGuid) '{}' not found in gameobject table", linkedGuidLow);
1893 TC_LOG_ERROR(
"sql.sql",
"LinkedRespawn: Gameobject '{}' linking to Gameobject '{}' on an unpermitted map.", guidLow, linkedGuidLow);
1901 TC_LOG_ERROR(
"sql.sql",
"LinkedRespawn: Gameobject '{}' linking to Gameobject '{}' with not corresponding spawnMask", guidLow, linkedGuidLow);
1906 guid = ObjectGuid::Create<HighGuid::GameObject>(slave->
mapId, slave->
id, guidLow);
1907 linkedGuid = ObjectGuid::Create<HighGuid::GameObject>(master->
mapId, master->
id, linkedGuidLow);
1915 TC_LOG_ERROR(
"sql.sql",
"LinkedRespawn: Gameobject (guid) '{}' not found in gameobject table", guidLow);
1923 TC_LOG_ERROR(
"sql.sql",
"LinkedRespawn: Creature (linkedGuid) '{}' not found in creature table", linkedGuidLow);
1931 TC_LOG_ERROR(
"sql.sql",
"LinkedRespawn: Gameobject '{}' linking to Creature '{}' on an unpermitted map.", guidLow, linkedGuidLow);
1939 TC_LOG_ERROR(
"sql.sql",
"LinkedRespawn: Gameobject '{}' linking to Creature '{}' with not corresponding spawnMask", guidLow, linkedGuidLow);
1944 guid = ObjectGuid::Create<HighGuid::GameObject>(slave->
mapId, slave->
id, guidLow);
1945 linkedGuid = ObjectGuid::Create<HighGuid::Creature>(master->
mapId, master->
id, linkedGuidLow);
1953 while (result->NextRow());
1965 ObjectGuid guid = ObjectGuid::Create<HighGuid::Creature>(master->
mapId, master->
id, guidLow);
1980 TC_LOG_ERROR(
"sql.sql",
"Creature '{}' linking to non-existent creature '{}'.", guidLow, linkedGuidLow);
1987 TC_LOG_ERROR(
"sql.sql",
"Creature '{}' linking to '{}' on an unpermitted map.", guidLow, linkedGuidLow);
1994 TC_LOG_ERROR(
"sql.sql",
"LinkedRespawn: Creature '{}' linking to '{}' with not corresponding spawnMask", guidLow, linkedGuidLow);
1998 ObjectGuid linkedGuid = ObjectGuid::Create<HighGuid::Creature>(slave->
mapId, slave->
id, linkedGuidLow);
2016 QueryResult result =
WorldDatabase.Query(
"SELECT summonerId, summonerType, groupId, entry, position_x, position_y, position_z, orientation, summonType, summonTime FROM creature_summon_groups");
2020 TC_LOG_INFO(
"server.loading",
">> Loaded 0 temp summons. DB table `creature_summon_groups` is empty.");
2027 Field* fields = result->Fetch();
2033 switch (summonerType)
2038 TC_LOG_ERROR(
"sql.sql",
"Table `creature_summon_groups` has summoner with non existing entry {} for creature summoner type, skipped.", summonerId);
2045 TC_LOG_ERROR(
"sql.sql",
"Table `creature_summon_groups` has summoner with non existing entry {} for gameobject summoner type, skipped.", summonerId);
2052 TC_LOG_ERROR(
"sql.sql",
"Table `creature_summon_groups` has summoner with non existing entry {} for map summoner type, skipped.", summonerId);
2057 TC_LOG_ERROR(
"sql.sql",
"Table `creature_summon_groups` has unhandled summoner type {} for summoner {}, skipped.", summonerType, summonerId);
2066 TC_LOG_ERROR(
"sql.sql",
"Table `creature_summon_groups` has creature in group [Summoner ID: {}, Summoner Type: {}, Group ID: {}] with non existing creature entry {}, skipped.", summonerId, summonerType, group, data.
entry);
2073 float orientation = fields[7].
GetFloat();
2081 TC_LOG_ERROR(
"sql.sql",
"Table `creature_summon_groups` has unhandled temp summon type {} in group [Summoner ID: {}, Summoner Type: {}, Group ID: {}] for creature entry {}, skipped.", data.
type, summonerId, summonerType, group, data.
entry);
2092 }
while (result->NextRow());
2098 std::set<Difficulty>
const& mapDifficulties)
2100 std::vector<Difficulty> difficulties;
2101 bool isTransportMap =
sObjectMgr->IsTransportMap(mapId);
2107 TC_LOG_ERROR(
"sql.sql",
"Table `{}` has {} (GUID: {}) with non invalid difficulty id {}, skipped.",
2108 table, table, spawnId,
uint32(difficultyId));
2112 if (!isTransportMap && mapDifficulties.find(difficultyId) == mapDifficulties.end())
2114 TC_LOG_ERROR(
"sql.sql",
"Table `{}` has {} (GUID: {}) has unsupported difficulty {} for map (Id: {}).",
2115 table, table, spawnId,
uint32(difficultyId), mapId);
2119 difficulties.push_back(difficultyId);
2122 std::sort(difficulties.begin(), difficulties.end());
2123 return difficulties;
2131 QueryResult result =
WorldDatabase.Query(
"SELECT creature.guid, id, map, position_x, position_y, position_z, orientation, modelid, equipment_id, spawntimesecs, wander_distance, "
2133 "currentwaypoint, curHealthPct, MovementType, spawnDifficulties, eventEntry, poolSpawnId, creature.npcflag, creature.unit_flags, creature.unit_flags2, creature.unit_flags3, "
2135 "creature.phaseUseFlags, creature.phaseid, creature.phasegroup, creature.terrainSwapMap, creature.ScriptName, creature.StringId "
2137 "LEFT OUTER JOIN game_event_creature ON creature.guid = game_event_creature.guid "
2138 "LEFT OUTER JOIN pool_members ON pool_members.type = 0 AND creature.guid = pool_members.spawnId");
2142 TC_LOG_INFO(
"server.loading",
">> Loaded 0 creatures. DB table `creature` is empty.");
2147 std::unordered_map<uint32, std::set<Difficulty>> spawnMasks;
2149 spawnMasks[mapDifficulty->MapID].insert(
Difficulty(mapDifficulty->DifficultyID));
2157 Field* fields = result->Fetch();
2165 TC_LOG_ERROR(
"sql.sql",
"Table `creature` has creature (GUID: {}) with non existing creature entry {}, skipped.", guid, entry);
2173 data.
spawnPoint.
Relocate(fields[3].GetFloat(), fields[4].GetFloat(), fields[5].GetFloat(), fields[6].GetFloat());
2174 if (
uint32 displayId = fields[7].GetUInt32())
2185 if (!fields[17].IsNull())
2187 if (!fields[18].IsNull())
2189 if (!fields[19].IsNull())
2191 if (!fields[20].IsNull())
2204 TC_LOG_ERROR(
"sql.sql",
"Table `creature` has creature (GUID: {}) that spawned at nonexistent map (Id: {}), skipped.", guid, data.
mapId);
2220 TC_LOG_ERROR(
"sql.sql",
"Table `creature` has creature (GUID: {} Entry: {} MapID: {}) spawned on a possible invalid position ({})",
2228 TC_LOG_ERROR(
"sql.sql",
"Table `creature` has creature (GUID: {}) that is not spawned in any difficulty, skipped.", guid);
2236 TC_LOG_ERROR(
"sql.sql",
"Table `creature` has creature (GUID: {} Entry: {}) with invalid `modelid` {}, ignoring.", guid, data.
id, data.
display->CreatureDisplayID);
2246 TC_LOG_ERROR(
"sql.sql",
"Table `creature` has creature (Entry: {}) with equipment_id {} not found in table `creature_equip_template`, set to no equipment.", data.
id, data.
equipmentId);
2254 TC_LOG_ERROR(
"sql.sql",
"Table `creature` has creature (GUID: {} Entry: {}) with `creature_template`.`flags_extra` including CREATURE_FLAG_EXTRA_INSTANCE_BIND but creature is not in instance.", guid, data.
id);
2259 TC_LOG_ERROR(
"sql.sql",
"Table `creature` has creature (GUID: {} Entry: {}) with wrong movement generator type ({}), ignored and set to IDLE.", guid, data.
id, data.
movementType);
2265 TC_LOG_ERROR(
"sql.sql",
"Table `creature` has creature (GUID: {} Entry: {}) with `wander_distance`< 0, set to 0.", guid, data.
id);
2270 TC_LOG_ERROR(
"sql.sql",
"Table `creature` has creature (GUID: {} Entry: {}) with `wander_distance` below the allowed minimum distance of 0.1, set to 0.", guid, data.
id);
2277 TC_LOG_ERROR(
"sql.sql",
"Table `creature` has creature (GUID: {} Entry: {}) with `MovementType`=1 (random movement) but with `wander_distance`=0, replace by idle movement type (0).", guid, data.
id);
2285 TC_LOG_ERROR(
"sql.sql",
"Table `creature` has creature (GUID: {} Entry: {}) with `MovementType`=0 (idle) have `wander_distance`<>0, set to 0.", guid, data.
id);
2292 TC_LOG_ERROR(
"sql.sql",
"Table `creature` have creature (GUID: {} Entry: {}) has unknown `phaseUseFlags` set, removed unknown value.", guid, data.
id);
2298 TC_LOG_ERROR(
"sql.sql",
"Table `creature` have creature (GUID: {} Entry: {}) has both `phaseUseFlags` PHASE_USE_FLAGS_ALWAYS_VISIBLE and PHASE_USE_FLAGS_INVERSE,"
2299 " removing PHASE_USE_FLAGS_INVERSE.", guid, data.
id);
2305 TC_LOG_ERROR(
"sql.sql",
"Table `creature` have creature (GUID: {} Entry: {}) with both `phaseid` and `phasegroup` set, `phasegroup` set to 0", guid, data.
id);
2313 TC_LOG_ERROR(
"sql.sql",
"Table `creature` have creature (GUID: {} Entry: {}) with `phaseid` {} does not exist, set to 0", guid, data.
id, data.
phaseId);
2322 TC_LOG_ERROR(
"sql.sql",
"Table `creature` have creature (GUID: {} Entry: {}) with `phasegroup` {} does not exist, set to 0", guid, data.
id, data.
phaseGroup);
2330 if (!terrainSwapEntry)
2332 TC_LOG_ERROR(
"sql.sql",
"Table `creature` have creature (GUID: {} Entry: {}) with `terrainSwapMap` {} does not exist, set to -1", guid, data.
id, data.
terrainSwapMap);
2337 TC_LOG_ERROR(
"sql.sql",
"Table `creature` have creature (GUID: {} Entry: {}) with `terrainSwapMap` {} which cannot be used on spawn map, set to -1", guid, data.
id, data.
terrainSwapMap);
2346 TC_LOG_ERROR(
"sql.sql",
"Table `creature` has creature (GUID: {} Entry: {}) with disallowed `unit_flags` {}, removing incorrect flag.", guid, data.
id, disallowedUnitFlags);
2355 TC_LOG_ERROR(
"sql.sql",
"Table `creature` has creature (GUID: {} Entry: {}) with disallowed `unit_flags2` {}, removing incorrect flag.", guid, data.
id, disallowedUnitFlags2);
2361 TC_LOG_ERROR(
"sql.sql",
"Table `creature` has creature (GUID: {} Entry: {}) has UNIT_FLAG2_FEIGN_DEATH set without IMMUNE_TO_PC | IMMUNE_TO_NPC, removing incorrect flag.", guid, data.
id);
2370 TC_LOG_ERROR(
"sql.sql",
"Table `creature` has creature (GUID: {} Entry: {}) with disallowed `unit_flags3` {}, removing incorrect flag.", guid, data.
id, disallowedUnitFlags3);
2376 TC_LOG_ERROR(
"sql.sql",
"Table `creature` has creature (GUID: {} Entry: {}) has UNIT_FLAG3_FAKE_DEAD set without IMMUNE_TO_PC | IMMUNE_TO_NPC, removing incorrect flag.", guid, data.
id);
2384 TC_LOG_ERROR(
"sql.sql",
"Table `creature` has creature (GUID: {} Entry: {}) with invalid `curHealthPct` {}, set to {}.", guid, data.
id, data.
curHealthPct, healthPct);
2408 while (result->NextRow());
2439template<CellGu
idSet CellObjectGu
ids::*gu
ids>
2444 if (!isPersonalPhase)
2456template<CellGu
idSet CellObjectGu
ids::*gu
ids>
2461 if (!isPersonalPhase)
2475 AddSpawnDataToGrid<&CellObjectGuids::creatures>(data);
2480 RemoveSpawnDataFromGrid<&CellObjectGuids::creatures>(data);
2488 QueryResult result =
WorldDatabase.Query(
"SELECT gameobject.guid, id, map, position_x, position_y, position_z, orientation, "
2490 "rotation0, rotation1, rotation2, rotation3, spawntimesecs, animprogress, state, spawnDifficulties, eventEntry, poolSpawnId, "
2492 "phaseUseFlags, phaseid, phasegroup, terrainSwapMap, ScriptName, StringId "
2493 "FROM gameobject LEFT OUTER JOIN game_event_gameobject ON gameobject.guid = game_event_gameobject.guid "
2494 "LEFT OUTER JOIN pool_members ON pool_members.type = 1 AND gameobject.guid = pool_members.spawnId");
2498 TC_LOG_INFO(
"server.loading",
">> Loaded 0 gameobjects. DB table `gameobject` is empty.");
2503 std::unordered_map<uint32, std::set<Difficulty>> spawnMasks;
2505 spawnMasks[mapDifficulty->MapID].insert(
Difficulty(mapDifficulty->DifficultyID));
2513 Field* fields = result->Fetch();
2521 TC_LOG_ERROR(
"sql.sql",
"Table `gameobject` has gameobject (GUID: {}) with non existing gameobject entry {}, skipped.", guid, entry);
2527 switch (gInfo->
type)
2533 TC_LOG_ERROR(
"sql.sql",
"Gameobject (GUID: {} Entry {} GoType: {}) doesn't have a displayId ({}), not loaded.", guid, entry, gInfo->
type, gInfo->
displayId);
2540 TC_LOG_ERROR(
"sql.sql",
"Gameobject (GUID: {} Entry {} GoType: {}) has an invalid displayId ({}), not loaded.", guid, entry, gInfo->
type, gInfo->
displayId);
2549 data.
spawnPoint.
Relocate(fields[3].GetFloat(), fields[4].GetFloat(), fields[5].GetFloat(), fields[6].GetFloat());
2560 TC_LOG_ERROR(
"sql.sql",
"Table `gameobject` has gameobject (GUID: {} Entry: {}) spawned on a non-existed map (Id: {}), skip", guid, data.
id, data.
mapId);
2576 TC_LOG_ERROR(
"sql.sql",
"Table `gameobject` has gameobject (GUID: {} Entry: {} MapID: {}) spawned on a possible invalid position ({})",
2584 TC_LOG_ERROR(
"sql.sql",
"Table `gameobject` has gameobject (GUID: {} Entry: {}) with `spawntimesecs` (0) value, but the gameobejct is marked as despawnable at action.", guid, data.
id);
2595 TC_LOG_ERROR(
"sql.sql",
"Table `gameobject` has gameobject (GUID: {} Entry: {}) with invalid `state` ({}) value, skip", guid, data.
id, go_state);
2604 TC_LOG_ERROR(
"sql.sql",
"Table `creature` has creature (GUID: {}) that is not spawned in any difficulty, skipped.", guid);
2616 TC_LOG_ERROR(
"sql.sql",
"Table `gameobject` have gameobject (GUID: {} Entry: {}) has unknown `phaseUseFlags` set, removed unknown value.", guid, data.
id);
2622 TC_LOG_ERROR(
"sql.sql",
"Table `gameobject` have gameobject (GUID: {} Entry: {}) has both `phaseUseFlags` PHASE_USE_FLAGS_ALWAYS_VISIBLE and PHASE_USE_FLAGS_INVERSE,"
2623 " removing PHASE_USE_FLAGS_INVERSE.", guid, data.
id);
2629 TC_LOG_ERROR(
"sql.sql",
"Table `gameobject` have gameobject (GUID: {} Entry: {}) with both `phaseid` and `phasegroup` set, `phasegroup` set to 0", guid, data.
id);
2637 TC_LOG_ERROR(
"sql.sql",
"Table `gameobject` have gameobject (GUID: {} Entry: {}) with `phaseid` {} does not exist, set to 0", guid, data.
id, data.
phaseId);
2646 TC_LOG_ERROR(
"sql.sql",
"Table `gameobject` have gameobject (GUID: {} Entry: {}) with `phaseGroup` {} does not exist, set to 0", guid, data.
id, data.
phaseGroup);
2655 if (!terrainSwapEntry)
2657 TC_LOG_ERROR(
"sql.sql",
"Table `gameobject` have gameobject (GUID: {} Entry: {}) with `terrainSwapMap` {} does not exist, set to -1", guid, data.
id, data.
terrainSwapMap);
2662 TC_LOG_ERROR(
"sql.sql",
"Table `gameobject` have gameobject (GUID: {} Entry: {}) with `terrainSwapMap` {} which cannot be used on spawn map, set to -1", guid, data.
id, data.
terrainSwapMap);
2672 TC_LOG_ERROR(
"sql.sql",
"Table `gameobject` has gameobject (GUID: {} Entry: {}) with invalid rotationX ({}) value, skip", guid, data.
id, data.
rotation.
x);
2678 TC_LOG_ERROR(
"sql.sql",
"Table `gameobject` has gameobject (GUID: {} Entry: {}) with invalid rotationY ({}) value, skip", guid, data.
id, data.
rotation.
y);
2684 TC_LOG_ERROR(
"sql.sql",
"Table `gameobject` has gameobject (GUID: {} Entry: {}) with invalid rotationZ ({}) value, skip", guid, data.
id, data.
rotation.
z);
2690 TC_LOG_ERROR(
"sql.sql",
"Table `gameobject` has gameobject (GUID: {} Entry: {}) with invalid rotationW ({}) value, skip", guid, data.
id, data.
rotation.
w);
2696 TC_LOG_ERROR(
"sql.sql",
"Table `gameobject` has gameobject (GUID: {} Entry: {}) with invalid coordinates, skip", guid, data.
id);
2702 TC_LOG_ERROR(
"sql.sql",
"Table `gameobject` has gameobject (GUID: {} Entry: {}) with invalid rotation quaternion (non-unit), defaulting to orientation on Z axis only", guid, data.
id);
2725 while (result->NextRow());
2741 Field* fields = result->Fetch();
2755 flags &= ~SPAWNGROUP_FLAG_MANUAL_SPAWN;
2756 TC_LOG_ERROR(
"sql.sql",
"System spawn group {} ({}) has invalid manual spawn flag. Ignored.", groupId, group.
name);
2759 }
while (result->NextRow());
2764 TC_LOG_ERROR(
"sql.sql",
"Default spawn group (index 0) is missing from DB! Manually inserted.");
2767 data.
name =
"Default Group";
2773 TC_LOG_ERROR(
"sql.sql",
"Default legacy spawn group (index 1) is missing from DB! Manually inserted.");
2776 data.
name =
"Legacy Group";
2784 TC_LOG_INFO(
"server.loading",
">> Loaded 0 spawn group templates. DB table `spawn_group_template` is empty.");
2798 TC_LOG_INFO(
"server.loading",
">> Loaded 0 spawn group members. DB table `spawn_group` is empty.");
2805 Field* fields = result->Fetch();
2810 TC_LOG_ERROR(
"sql.sql",
"Spawn data with invalid type {} listed for spawn group {}. Skipped.",
uint32(spawnType), groupId);
2818 TC_LOG_ERROR(
"sql.sql",
"Spawn data with ID ({},{}) not found, but is listed as a member of spawn group {}!",
uint32(spawnType), spawnId, groupId);
2823 TC_LOG_ERROR(
"sql.sql",
"Spawn with ID ({},{}) is listed as a member of spawn group {}, but is already a member of spawn group {}. Skipping.",
uint32(spawnType), spawnId, groupId, data->
spawnGroupData->
groupId);
2829 TC_LOG_ERROR(
"sql.sql",
"Spawn group {} assigned to spawn ID ({},{}), but group is found!", groupId,
uint32(spawnType), spawnId);
2842 TC_LOG_ERROR(
"sql.sql",
"Spawn group {} has map ID {}, but spawn ({},{}) has map id {} - spawn NOT added to group!", groupId, groupTemplate.
mapId,
uint32(spawnType), spawnId, data->
mapId);
2845 const_cast<SpawnMetadata*
>(data)->spawnGroupData = &groupTemplate;
2850 }
while (result->NextRow());
2860 QueryResult result =
WorldDatabase.Query(
"SELECT instanceMapId, bossStateId, bossStates, spawnGroupId, flags FROM instance_spawn_groups");
2864 TC_LOG_INFO(
"server.loading",
">> Loaded 0 instance spawn groups. DB table `instance_spawn_groups` is empty.");
2871 Field* fields = result->Fetch();
2876 TC_LOG_ERROR(
"sql.sql",
"Invalid spawn group {} specified for instance {}. Skipped.", spawnGroupId, fields[0].GetUInt16());
2881 if (it->second.mapId != instanceMapId)
2883 TC_LOG_ERROR(
"sql.sql",
"Instance spawn group {} specified for instance {} has spawns on a different map {}. Skipped.",
2884 spawnGroupId, instanceMapId, it->second.mapId);
2894 if (states & ~ALL_STATES)
2897 TC_LOG_ERROR(
"sql.sql",
"Instance spawn group ({},{}) had invalid boss state mask {} - truncated to {}.", instanceMapId, spawnGroupId, states, info.
BossStates);
2906 TC_LOG_ERROR(
"sql.sql",
"Instance spawn group ({},{}) had invalid flags {} - truncated to {}.", instanceMapId, spawnGroupId,
flags, info.
Flags);
2914 TC_LOG_ERROR(
"sql.sql",
"Instance spawn group ({},{}) FLAG_ALLIANCE_ONLY and FLAG_HORDE_ONLY may not be used together in a single entry - truncated to {}.", instanceMapId, spawnGroupId, info.
Flags);
2918 }
while (result->NextRow());
2949 bool erased =
false;
2950 for (
auto it = pair.first; it != pair.second; ++it)
2952 if (it->second != data)
2968 for (
auto it = pair.first; it != pair.second; ++it)
2970 if (it->second != data)
2980 AddSpawnDataToGrid<&CellObjectGuids::gameobjects>(data);
2985 RemoveSpawnDataFromGrid<&CellObjectGuids::gameobjects>(data);
2995 0.92f, 0.92f, 0.92f, 1.11f, 1.32f, 1.61f, 0.0f, 0.0f
2998 static float const armorMultipliers[
MAX_INVTYPE] =
3062 float levelPenalty = 1.0f;
3063 if (itemLevel <= 28)
3064 levelPenalty = 0.966f - float(28u - itemLevel) / 54.0f;
3071 return 5 *
uint32(round(25.0f * qualityMultipliers[quality] * armorMultipliers[inventoryType] * levelPenalty));
3074 return 5 *
uint32(round(18.0f * qualityMultipliers[quality] * weaponMultipliers[itemSubClass] * levelPenalty));
3234 switch (itemStatType)
3313 if (std::vector<ItemSpecOverrideEntry const*>
const* itemSpecOverrides =
sDB2Manager.GetItemSpecOverrides(sparse->ID))
3332 if (itemSpecStats.
ItemType != itemSpec->ItemType)
3342 hasSecondary =
true;
3345 if (!hasPrimary || !hasSecondary)
3350 if ((1 << (specialization->ClassID - 1)) & sparse->AllowableClass)
3355 if (itemSpec->MaxLevel > 40)
3357 if (itemSpec->MaxLevel >= 110)
3366 if (specs.count() == 0)
3374 item->Effects.push_back(effect);
3384 QueryResult result =
WorldDatabase.Query(
"SELECT Id, FlagsCu, FoodType, MinMoneyLoot, MaxMoneyLoot, SpellPPMChance, RandomBonusListTemplateId, QuestLogItemId FROM item_template_addon");
3389 Field* fields = result->Fetch();
3394 TC_LOG_ERROR(
"sql.sql",
"Item {} specified in `item_template_addon` does not exist, skipped.", itemId);
3400 if (minMoneyLoot > maxMoneyLoot)
3402 TC_LOG_ERROR(
"sql.sql",
"Minimum money loot specified in `item_template_addon` for item {} was greater than maximum amount, swapping.", itemId);
3403 std::swap(minMoneyLoot, maxMoneyLoot);
3413 }
while (result->NextRow());
3428 Field* fields = result->Fetch();
3433 TC_LOG_ERROR(
"sql.sql",
"Item {} specified in `item_script_names` does not exist, skipped.", itemId);
3439 }
while (result->NextRow());
3459 QueryResult result =
WorldDatabase.Query(
"SELECT `entry`, `accessory_entry`, `seat_id`, `minion`, `summontype`, `summontimer` FROM `vehicle_template_accessory`");
3463 TC_LOG_INFO(
"server.loading",
">> Loaded 0 vehicle template accessories. DB table `vehicle_template_accessory` is empty.");
3469 Field* fields = result->Fetch();
3474 bool isMinion = fields[3].
GetBool();
3480 TC_LOG_ERROR(
"sql.sql",
"Table `vehicle_template_accessory`: creature template entry {} does not exist.", entry);
3486 TC_LOG_ERROR(
"sql.sql",
"Table `vehicle_template_accessory`: Accessory {} does not exist.", accessory);
3492 TC_LOG_ERROR(
"sql.sql",
"Table `vehicle_template_accessory`: creature template entry {} has no data in npc_spellclick_spells", entry);
3500 while (result->NextRow());
3516 TC_LOG_INFO(
"server.loading",
">> Loaded 0 vehicle template. DB table `vehicle_template` is empty.");
3522 Field* fields = result->Fetch();
3528 TC_LOG_ERROR(
"sql.sql",
"Table `vehicle_template`: Vehicle {} does not exist.", creatureId);
3535 }
while (result->NextRow());
3549 QueryResult result =
WorldDatabase.Query(
"SELECT `guid`, `accessory_entry`, `seat_id`, `minion`, `summontype`, `summontimer` FROM `vehicle_accessory`");
3553 TC_LOG_INFO(
"server.loading",
">> Loaded 0 vehicle accessories. DB table `vehicle_accessory` is empty.");
3559 Field* fields = result->Fetch();
3563 int8 uiSeat =
int8(fields[2].GetInt16());
3564 bool bMinion = fields[3].
GetBool();
3570 TC_LOG_ERROR(
"sql.sql",
"Table `vehicle_accessory`: Accessory {} does not exist.", uiAccessory);
3578 while (result->NextRow());
3592 QueryResult result =
WorldDatabase.Query(
"SELECT `SeatEntry`, `SeatOrientation`, `ExitParamX`, `ExitParamY`, `ExitParamZ`, `ExitParamO`, `ExitParamValue` FROM `vehicle_seat_addon`");
3596 TC_LOG_ERROR(
"server.loading",
">> Loaded 0 vehicle seat addons. DB table `vehicle_seat_addon` is empty.");
3602 Field* fields = result->Fetch();
3605 float orientation = fields[1].
GetFloat();
3606 float exitX = fields[2].
GetFloat();
3607 float exitY = fields[3].
GetFloat();
3608 float exitZ = fields[4].
GetFloat();
3609 float exitO = fields[5].
GetFloat();
3614 TC_LOG_ERROR(
"sql.sql",
"Table `vehicle_seat_addon`: SeatID: {} does not exist in VehicleSeat.dbc. Skipping entry.", seatID);
3619 if (orientation >
float(
M_PI * 2))
3621 TC_LOG_ERROR(
"sql.sql",
"Table `vehicle_seat_addon`: SeatID: {} is using invalid angle offset value ({}). Set Value to 0.", seatID, orientation);
3627 TC_LOG_ERROR(
"sql.sql",
"Table `vehicle_seat_addon`: SeatID: {} is using invalid exit parameter value ({}). Setting to 0 (none).", seatID, exitParam);
3634 }
while (result->NextRow());
3644 QueryResult result =
WorldDatabase.Query(
"SELECT creature_entry, level, hp, mana, str, agi, sta, inte, spi, armor FROM pet_levelstats");
3648 TC_LOG_INFO(
"server.loading",
">> Loaded 0 level pet stats definitions. DB table `pet_levelstats` is empty.");
3656 Field* fields = result->Fetch();
3661 TC_LOG_ERROR(
"sql.sql",
"Wrong creature id {} in `pet_levelstats` table, ignoring.", creature_id);
3672 TC_LOG_INFO(
"misc",
"Unused (> MaxPlayerLevel in worldserver.conf) level {} in `pet_levelstats` table, ignoring.", current_level);
3677 else if (current_level < 1)
3679 TC_LOG_ERROR(
"sql.sql",
"Wrong (<1) level {} in `pet_levelstats` table, ignoring.", current_level);
3688 PetLevelInfo* pLevelInfo = &pInfoMapEntry[current_level - 1];
3699 while (result->NextRow());
3704 auto& pInfo = itr->second;
3707 if (!pInfo || pInfo[0].health == 0)
3709 TC_LOG_ERROR(
"sql.sql",
"Creature {} does not have pet stats data for Level 1!", itr->first);
3716 if (pInfo[level].health == 0)
3718 TC_LOG_ERROR(
"sql.sql",
"Creature {} has no data for Level {} pet stats data, using data of Level {}.", itr->first, level + 1, level);
3719 pInfo[level] = pInfo[level - 1];
3736 return &itr->second[level - 1];
3746 playerInfo->
item.emplace_back(itemId, count);
3750 TC_LOG_ERROR(
"sql.sql",
"Invalid count {} specified on item {} be removed from original player create info (use -1)!", count, itemId);
3754 auto erased = std::remove_if(items.begin(), items.end(), [itemId](
PlayerCreateInfoItem const& item) { return item.item_id == itemId; });
3755 if (erased == items.end())
3757 TC_LOG_ERROR(
"sql.sql",
"Item {} specified to be removed from original create info not found in db2!", itemId);
3761 items.erase(erased, items.end());
3771 QueryResult result =
WorldDatabase.Query(
"SELECT race, class, map, position_x, position_y, position_z, orientation, npe_map, npe_position_x, npe_position_y, npe_position_z, npe_orientation, npe_transport_guid, intro_movie_id, intro_scene_id, npe_intro_scene_id FROM playercreateinfo");
3775 TC_LOG_ERROR(
"server.loading",
">> Loaded 0 player create definitions. DB table `playercreateinfo` is empty.");
3784 Field* fields = result->Fetch();
3789 float positionX = fields[3].
GetFloat();
3790 float positionY = fields[4].
GetFloat();
3791 float positionZ = fields[5].
GetFloat();
3792 float orientation = fields[6].
GetFloat();
3796 TC_LOG_ERROR(
"sql.sql",
"Wrong race {} in `playercreateinfo` table, ignoring.", current_race);
3802 TC_LOG_ERROR(
"sql.sql",
"Wrong class {} in `playercreateinfo` table, ignoring.", current_class);
3809 TC_LOG_ERROR(
"sql.sql",
"Wrong home position for class {} race {} pair in `playercreateinfo` table, ignoring.", current_class, current_race);
3813 if (
sMapStore.LookupEntry(mapId)->Instanceable())
3815 TC_LOG_ERROR(
"sql.sql",
"Home position in instanceable map for class {} race {} pair in `playercreateinfo` table, ignoring.", current_class, current_race);
3821 TC_LOG_ERROR(
"sql.sql",
"Missing male model for race {}, ignoring.", current_race);
3827 TC_LOG_ERROR(
"sql.sql",
"Missing female model for race {}, ignoring.", current_race);
3831 std::unique_ptr<PlayerInfo> info = std::make_unique<PlayerInfo>();
3832 info->createPosition.Loc.WorldRelocate(mapId, positionX, positionY, positionZ, orientation);
3834 if (std::none_of(fields + 7, fields + 12, [](
Field const& field) {
return field.
IsNull(); }))
3836 info->createPositionNPE.emplace();
3838 info->createPositionNPE->Loc.WorldRelocate(fields[7].GetUInt32(), fields[8].GetFloat(), fields[9].GetFloat(), fields[10].GetFloat(), fields[11].GetFloat());
3839 if (!fields[12].IsNull())
3840 info->createPositionNPE->TransportGuid = fields[12].
GetUInt64();
3842 if (!
sMapStore.LookupEntry(info->createPositionNPE->Loc.GetMapId()))
3844 TC_LOG_ERROR(
"sql.sql",
"Invalid NPE map id {} for class {} race {} pair in `playercreateinfo` table, ignoring.",
3845 info->createPositionNPE->Loc.GetMapId(), current_class, current_race);
3846 info->createPositionNPE.reset();
3849 if (info->createPositionNPE && info->createPositionNPE->TransportGuid && !
sTransportMgr->GetTransportSpawn(*info->createPositionNPE->TransportGuid))
3851 TC_LOG_ERROR(
"sql.sql",
"Invalid NPE transport spawn id {} for class {} race {} pair in `playercreateinfo` table, ignoring.",
3852 *info->createPositionNPE->TransportGuid, current_class, current_race);
3853 info->createPositionNPE.reset();
3857 if (!fields[13].IsNull())
3861 info->introMovieId = introMovieId;
3863 TC_LOG_ERROR(
"sql.sql",
"Invalid intro movie id {} for class {} race {} pair in `playercreateinfo` table, ignoring.",
3864 introMovieId, current_class, current_race);
3867 if (!fields[14].IsNull())
3871 info->introSceneId = introSceneId;
3873 TC_LOG_ERROR(
"sql.sql",
"Invalid intro scene id {} for class {} race {} pair in `playercreateinfo` table, ignoring.",
3874 introSceneId, current_class, current_race);
3877 if (!fields[15].IsNull())
3881 info->introSceneIdNPE = introSceneId;
3883 TC_LOG_ERROR(
"sql.sql",
"Invalid NPE intro scene id {} for class {} race {} pair in `playercreateinfo` table, ignoring.",
3884 introSceneId, current_class, current_race);
3891 while (result->NextRow());
3898 TC_LOG_INFO(
"server.loading",
"Loading Player Create Items Data...");
3900 std::unordered_map<uint32, std::vector<ItemTemplate const*>> itemsByCharacterLoadout;
3903 itemsByCharacterLoadout[characterLoadoutItem->CharacterLoadoutID].push_back(itemTemplate);
3907 if (!characterLoadout->IsForNewCharacter())
3916 if (!characterLoadout->RaceMask.HasRace(raceIndex))
3921 playerInfo->itemContext =
ItemContext(characterLoadout->ItemContext);
3926 uint32 count = itemTemplate->GetBuyCount();
3931 if (!itemTemplate->Effects.empty())
3933 switch (itemTemplate->Effects[0]->SpellCategoryID)
3943 if (itemTemplate->GetMaxStackSize() < count)
3944 count = itemTemplate->GetMaxStackSize();
3947 playerInfo->item.emplace_back(itemTemplate->GetId(), count);
3954 TC_LOG_INFO(
"server.loading",
"Loading Player Create Items Override Data...");
3962 TC_LOG_INFO(
"server.loading",
">> Loaded 0 custom player create items. DB table `playercreateinfo_item` is empty.");
3970 Field* fields = result->Fetch();
3975 TC_LOG_ERROR(
"sql.sql",
"Wrong race {} in `playercreateinfo_item` table, ignoring.", current_race);
3982 TC_LOG_ERROR(
"sql.sql",
"Wrong class {} in `playercreateinfo_item` table, ignoring.", current_class);
3990 TC_LOG_ERROR(
"sql.sql",
"Item id {} (race {} class {}) in `playercreateinfo_item` table but it does not exist, ignoring.", item_id, current_race, current_class);
3998 TC_LOG_ERROR(
"sql.sql",
"Item id {} (class {} race {}) have amount == 0 in `playercreateinfo_item` table, ignoring.", item_id, current_race, current_class);
4002 if (!current_race || !current_class)
4004 uint32 min_race = current_race ? current_race : 1;
4006 uint32 min_class = current_class ? current_class : 1;
4008 for (
uint32 r = min_race; r < max_race; ++r)
4009 for (
uint32 c = min_class; c < max_class; ++c)
4017 while (result->NextRow());
4024 TC_LOG_INFO(
"server.loading",
"Loading Player Create Skill Data...");
4029 if (rcInfo->Availability == 1)
4031 if (rcInfo->RaceMask.IsEmpty() || rcInfo->RaceMask.HasRace(raceIndex))
4033 if (rcInfo->ClassMask == -1 || rcInfo->ClassMask == 0 || ((1 << (classIndex - 1)) & rcInfo->ClassMask))
4035 playerInfo->skills.push_back(rcInfo);
4041 TC_LOG_INFO(
"server.loading",
"Loading Player Create Custom Spell Data...");
4049 TC_LOG_INFO(
"server.loading",
">> Loaded 0 player create custom spells. DB table `playercreateinfo_spell_custom` is empty.");
4057 Field* fields = result->Fetch();
4064 TC_LOG_ERROR(
"sql.sql",
"Wrong race mask {} in `playercreateinfo_spell_custom` table, ignoring.", raceMask.
RawValue);
4070 TC_LOG_ERROR(
"sql.sql",
"Wrong class mask {} in `playercreateinfo_spell_custom` table, ignoring.", classMask);
4080 if (classMask == 0 || ((1 << (classIndex - 1)) & classMask))
4084 playerInfo->customSpells.push_back(spellId);
4096 while (result->NextRow());
4103 TC_LOG_INFO(
"server.loading",
"Loading Player Create Cast Spell Data...");
4107 QueryResult result =
WorldDatabase.PQuery(
"SELECT raceMask, classMask, spell, createMode FROM playercreateinfo_cast_spell");
4110 TC_LOG_INFO(
"server.loading",
">> Loaded 0 player create cast spells. DB table `playercreateinfo_cast_spell` is empty.");
4117 Field* fields = result->Fetch();
4125 TC_LOG_ERROR(
"sql.sql",
"Wrong race mask {} in `playercreateinfo_cast_spell` table, ignoring.", raceMask.
RawValue);
4131 TC_LOG_ERROR(
"sql.sql",
"Wrong class mask {} in `playercreateinfo_cast_spell` table, ignoring.", classMask);
4137 TC_LOG_ERROR(
"sql.sql",
"Uses invalid createMode {} in `playercreateinfo_cast_spell` table, ignoring.", playerCreateMode);
4147 if (classMask == 0 || ((1 << (classIndex - 1)) & classMask))
4151 playerInfo->castSpells[playerCreateMode].push_back(spellId);
4158 }
while (result->NextRow());
4165 TC_LOG_INFO(
"server.loading",
"Loading Player Create Action Data...");
4174 TC_LOG_INFO(
"server.loading",
">> Loaded 0 player create actions. DB table `playercreateinfo_action` is empty.");
4182 Field* fields = result->Fetch();
4187 TC_LOG_ERROR(
"sql.sql",
"Wrong race {} in `playercreateinfo_action` table, ignoring.", current_race);
4194 TC_LOG_ERROR(
"sql.sql",
"Wrong class {} in `playercreateinfo_action` table, ignoring.", current_class);
4203 while (result->NextRow());
4210 TC_LOG_INFO(
"server.loading",
"Loading Player Create Level Stats Data...");
4214 std::array<int16, MAX_STATS> StatModifier = { };
4217 std::array<RaceStats, MAX_RACES> raceStatModifiers = { };
4223 if (!raceStatsResult)
4225 TC_LOG_ERROR(
"server.loading",
">> Loaded 0 race stats definitions. DB table `player_racestats` is empty.");
4231 Field* fields = raceStatsResult->Fetch();
4236 TC_LOG_ERROR(
"sql.sql",
"Wrong race {} in `player_racestats` table, ignoring.", current_race);
4241 raceStatModifiers[current_race].StatModifier[i] = fields[i + 1].GetInt16();
4243 }
while (raceStatsResult->NextRow());
4250 TC_LOG_ERROR(
"server.loading",
">> Loaded 0 level stats definitions. DB table `player_classlevelstats` is empty.");
4258 Field* fields = result->Fetch();
4263 TC_LOG_ERROR(
"sql.sql",
"Wrong class {} in `player_classlevelstats` table, ignoring.", current_class);
4273 TC_LOG_INFO(
"misc",
"Unused (> MaxPlayerLevel in worldserver.conf) level {} in `player_classlevelstats` table, ignoring.", current_level);
4278 for (std::size_t race = 0; race < raceStatModifiers.size(); ++race)
4282 if (!playerInfo->levelInfo)
4285 PlayerLevelInfo& levelInfo = playerInfo->levelInfo[current_level - 1];
4287 levelInfo.
stats[i] = fields[i + 2].
GetInt32() + raceStatModifiers[race].StatModifier[i];
4293 while (result->NextRow());
4337 if (!playerInfo->levelInfo || playerInfo->levelInfo[0].stats[0] == 0)
4339 TC_LOG_ERROR(
"sql.sql",
"Race {} Class {} Level 1 does not have stats data!", race, class_);
4346 if (playerInfo->levelInfo[level].stats[0] == 0)
4348 TC_LOG_ERROR(
"sql.sql",
"Race {} Class {} Level {} does not have stats data. Using stats data of level {}.", race, class_, level + 1, level);
4349 playerInfo->levelInfo[level] = playerInfo->levelInfo[level - 1];
4359 TC_LOG_INFO(
"server.loading",
"Loading Player Create XP Data...");
4379 Field* fields = result->Fetch();
4390 TC_LOG_INFO(
"misc",
"Unused (> MaxPlayerLevel in worldserver.conf) level {} in `player_xp_for_level` table, ignoring.", current_level);
4398 }
while (result->NextRow());
4406 TC_LOG_ERROR(
"sql.sql",
"Level {} does not have XP for level data. Using data of level [{}] + 12000.", level + 1, level);
4426 TC_LOG_ERROR(
"misc",
"Tried to get non-existant Class-Level combination data for base hp/mp. Class {} Level {}", class_, level);
4545 "ID, QuestType, QuestPackageID, ContentTuningID, QuestSortID, QuestInfoID, SuggestedGroupNum, RewardNextQuest, RewardXPDifficulty, RewardXPMultiplier, "
4547 "RewardMoneyDifficulty, RewardMoneyMultiplier, RewardBonusMoney, RewardSpell, RewardHonor, RewardKillHonor, StartItem, "
4549 "RewardArtifactXPDifficulty, RewardArtifactXPMultiplier, RewardArtifactCategoryID, Flags, FlagsEx, FlagsEx2, "
4551 "RewardItem1, RewardAmount1, ItemDrop1, ItemDropQuantity1, RewardItem2, RewardAmount2, ItemDrop2, ItemDropQuantity2, "
4553 "RewardItem3, RewardAmount3, ItemDrop3, ItemDropQuantity3, RewardItem4, RewardAmount4, ItemDrop4, ItemDropQuantity4, "
4555 "RewardChoiceItemID1, RewardChoiceItemQuantity1, RewardChoiceItemDisplayID1, RewardChoiceItemID2, RewardChoiceItemQuantity2, RewardChoiceItemDisplayID2, "
4557 "RewardChoiceItemID3, RewardChoiceItemQuantity3, RewardChoiceItemDisplayID3, RewardChoiceItemID4, RewardChoiceItemQuantity4, RewardChoiceItemDisplayID4, "
4559 "RewardChoiceItemID5, RewardChoiceItemQuantity5, RewardChoiceItemDisplayID5, RewardChoiceItemID6, RewardChoiceItemQuantity6, RewardChoiceItemDisplayID6, "
4561 "POIContinent, POIx, POIy, POIPriority, RewardTitle, RewardArenaPoints, RewardSkillLineID, RewardNumSkillUps, "
4563 "PortraitGiver, PortraitGiverMount, PortraitGiverModelSceneID, PortraitTurnIn, "
4565 "RewardFactionID1, RewardFactionValue1, RewardFactionOverride1, RewardFactionCapIn1, RewardFactionID2, RewardFactionValue2, RewardFactionOverride2, RewardFactionCapIn2, "
4567 "RewardFactionID3, RewardFactionValue3, RewardFactionOverride3, RewardFactionCapIn3, RewardFactionID4, RewardFactionValue4, RewardFactionOverride4, RewardFactionCapIn4, "
4569 "RewardFactionID5, RewardFactionValue5, RewardFactionOverride5, RewardFactionCapIn5, RewardFactionFlags, "
4571 "RewardCurrencyID1, RewardCurrencyQty1, RewardCurrencyID2, RewardCurrencyQty2, RewardCurrencyID3, RewardCurrencyQty3, RewardCurrencyID4, RewardCurrencyQty4, "
4573 "AcceptedSoundKitID, CompleteSoundKitID, AreaGroupID, TimeAllowed, AllowableRaces, ResetByScheduler, Expansion, ManagedWorldStateID, QuestSessionBonus, "