refactor(Core): Use database tables for Shaman totems and Druid shapeshift forms. (#22104)

Co-authored-by: DoctorKraft <25483209+doctorkraft@users.noreply.github.com>
Co-authored-by: Shauren <shauren.trinity@gmail.com>
Co-authored-by: ForesterDev <11771800+ForesterDev@users.noreply.github.com>
This commit is contained in:
Benjamin Jackson
2025-05-27 09:40:57 -04:00
committed by GitHub
parent c10e4dc015
commit db18d5b035
12 changed files with 356 additions and 298 deletions

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();