Merge branch 'master' into Playerbot

This commit is contained in:
Yunfan Li
2025-06-01 14:55:09 +08:00
66 changed files with 1638 additions and 550 deletions
+133
View File
@@ -1785,6 +1785,139 @@ void ObjectMgr::LoadCreatureModelInfo()
LOG_INFO("server.loading", " ");
}
void ObjectMgr::LoadPlayerTotemModels()
{
uint32 oldMSTime = getMSTime();
QueryResult result = WorldDatabase.Query("SELECT TotemID, RaceID, ModelID from player_totem_model");
if (!result)
{
LOG_INFO("server.loading", ">> Loaded 0 player totem model records. DB table `player_totem_model` is empty.");
return;
}
uint32 count = 0;
do
{
Field* fields = result->Fetch();
SummonSlot totemSlot = SummonSlot(fields[0].Get<uint8>());
uint8 race = fields[1].Get<uint8>();
uint32 displayId = fields[2].Get<uint32>();
if (totemSlot < SUMMON_SLOT_TOTEM_FIRE || totemSlot >= MAX_TOTEM_SLOT)
{
LOG_ERROR("sql.sql", "Wrong TotemSlot {} in `player_totem_model` table, skipped.", totemSlot);
continue;
}
ChrRacesEntry const* raceEntry = sChrRacesStore.LookupEntry(race);
if (!raceEntry)
{
LOG_ERROR("sql.sql", "Race {} defined in `player_totem_model` does not exists, skipped.", uint32(race));
continue;
}
CreatureDisplayInfoEntry const* displayEntry = sCreatureDisplayInfoStore.LookupEntry(displayId);
if (!displayEntry)
{
LOG_ERROR("sql.sql", "TotemSlot: {} defined in `player_totem_model` has non-existing model ({}), skipped.", totemSlot, displayId);
continue;
}
_playerTotemModel[std::make_pair(totemSlot, Races(race))] = displayId;
++count;
} while (result->NextRow());
LOG_INFO("server.loading", ">> Loaded {} player totem model records in {} ms", count, GetMSTimeDiffToNow(oldMSTime));
LOG_INFO("server.loading", " ");
}
uint32 ObjectMgr::GetModelForTotem(SummonSlot totemSlot, Races race) const
{
auto itr = _playerTotemModel.find(std::make_pair(totemSlot, race));
if (itr != _playerTotemModel.end())
return itr->second;
LOG_ERROR("misc", "TotemSlot {} with RaceID ({}) have no totem model data defined, set to default model.", totemSlot, race);
return 0;
}
void ObjectMgr::LoadPlayerShapeshiftModels()
{
uint32 oldMSTime = getMSTime();
QueryResult result = WorldDatabase.Query("SELECT ShapeshiftID, RaceID, CustomizationID, GenderID, ModelID from player_shapeshift_model");
if (!result)
{
LOG_INFO("server.loading", ">> Loaded 0 player shapeshift model records. DB table `player_shapeshift_model` is empty.");
return;
}
uint32 count = 0;
do
{
Field* fields = result->Fetch();
ShapeshiftForm shapeshiftForm = ShapeshiftForm(fields[0].Get<uint8>());
uint8 race = fields[1].Get<uint8>();
uint8 customizationID = fields[2].Get<uint8>();
uint8 genderID = Gender(fields[3].Get<uint8>());
uint32 modelId = fields[4].Get<uint32>();
ChrRacesEntry const* raceEntry = sChrRacesStore.LookupEntry(race);
if (!raceEntry)
{
LOG_ERROR("sql.sql", "Race {} defined in `player_shapeshift_model` does not exists, skipped.", uint32(race));
continue;
}
CreatureDisplayInfoEntry const* displayEntry = sCreatureDisplayInfoStore.LookupEntry(modelId);
if (!displayEntry)
{
LOG_ERROR("sql.sql", "ShapeshiftForm: {}, Race: {} defined in `player_shapeshift_model` has non-existing model ({}), skipped.", shapeshiftForm, race, modelId);
continue;
}
_playerShapeshiftModel[std::make_tuple(shapeshiftForm, race, customizationID, genderID)] = modelId;
++count;
} while (result->NextRow());
LOG_INFO("server.loading", ">> Loaded {} player totem model records in {} ms", count, GetMSTimeDiffToNow(oldMSTime));
LOG_INFO("server.loading", " ");
}
uint32 ObjectMgr::GetModelForShapeshift(ShapeshiftForm form, Player* player) const
{
uint8 customizationID;
if (player->GetTeamId() == TEAM_ALLIANCE)
customizationID = player->GetByteValue(PLAYER_BYTES, 3); // Use Hair Color
else
customizationID = player->GetByteValue(PLAYER_BYTES, 0); // Use Skin Color
auto itr = _playerShapeshiftModel.find(std::make_tuple(form, player->getRace(), customizationID, player->getGender()));
if (itr != _playerShapeshiftModel.end())
return itr->second; // Explicit combination
itr = _playerShapeshiftModel.find(std::make_tuple(form, player->getRace(), customizationID, GENDER_NONE));
if (itr != _playerShapeshiftModel.end())
return itr->second; // Combination applied to both genders
itr = _playerShapeshiftModel.find(std::make_tuple(form, player->getRace(), 255, player->getGender()));
if (itr != _playerShapeshiftModel.end())
return itr->second; // Default gender-dependent model
itr = _playerShapeshiftModel.find(std::make_tuple(form, player->getRace(), 255, GENDER_NONE));
if (itr != _playerShapeshiftModel.end())
return itr->second; // Last resort
LOG_DEBUG("entities.player", "ShapeshiftForm {} with RaceID ({}) have no shapeshift model data defined, using fallback data.", form, player->getRace());
return 0;
}
void ObjectMgr::LoadLinkedRespawn()
{
uint32 oldMSTime = getMSTime();
+14
View File
@@ -711,6 +711,10 @@ struct DungeonEncounter
typedef std::list<DungeonEncounter const*> DungeonEncounterList;
typedef std::unordered_map<uint32, DungeonEncounterList> DungeonEncounterContainer;
typedef std::map<std::pair<SummonSlot /*TotemSlot*/, Races /*RaceId*/>, uint32 /*DisplayId*/> PlayerTotemModelMap;
typedef std::map<std::tuple<ShapeshiftForm /*ShapeshiftID*/, uint8 /*RaceID*/, uint8 /*CustomizationID*/, uint8 /*GenderID*/>, uint32 /*ModelID*/> PlayerShapeshiftModelMap;
static constexpr uint32 MAX_QUEST_MONEY_REWARDS = 10;
typedef std::array<uint32, MAX_QUEST_MONEY_REWARDS> QuestMoneyRewardArray;
typedef std::unordered_map<uint32, QuestMoneyRewardArray> QuestMoneyRewardStore;
@@ -777,6 +781,10 @@ public:
[[nodiscard]] ItemTemplateContainer const* GetItemTemplateStore() const { return &_itemTemplateStore; }
[[nodiscard]] std::vector<ItemTemplate*> const* GetItemTemplateStoreFast() const { return &_itemTemplateStoreFast; }
uint32 GetModelForTotem(SummonSlot totemSlot, Races race) const;
uint32 GetModelForShapeshift(ShapeshiftForm form, Player* player) const;
ItemSetNameEntry const* GetItemSetNameEntry(uint32 itemId)
{
ItemSetNameContainer::iterator itr = _itemSetNameStore.find(itemId);
@@ -1036,6 +1044,8 @@ public:
void LoadCreatureAddons();
void LoadGameObjectAddons();
void LoadCreatureModelInfo();
void LoadPlayerTotemModels();
void LoadPlayerShapeshiftModels();
void LoadEquipmentTemplates();
void LoadCreatureMovementOverrides();
void LoadGameObjectLocales();
@@ -1623,6 +1633,10 @@ private:
std::set<uint32> _transportMaps; // Helper container storing map ids that are for transports only, loaded from gameobject_template
PlayerTotemModelMap _playerTotemModel;
PlayerShapeshiftModelMap _playerShapeshiftModel;
QuestMoneyRewardStore _questMoneyRewards;
struct GameobjectInstanceSavedState