DB/Creatures: Port master model system

Fixes incorrect displayid for creatures, due to probability
This commit is contained in:
funjoker committed 2023-09-15 23:52:51 +02:00
1 parent eb5cbdf948
commit df32b341a5
43 files changed
+65170 -262

No files matched your search

+100 -96
View File
@@ -454,6 +454,9 @@ void ObjectMgr::LoadCreatureTemplates()
}
while (result->NextRow());
// We load the creature models after loading but before checking
LoadCreatureTemplateModels();
// Checking needs to be done after loading because of the difficulty self referencing
for (CreatureTemplateContainer::const_iterator itr = _creatureTemplateStore.begin(); itr != _creatureTemplateStore.end(); ++itr)
CheckCreatureTemplate(&itr->second);
@@ -475,10 +478,10 @@ void ObjectMgr::LoadCreatureTemplate(Field* fields)
for (uint8 i = 0; i < MAX_KILL_CREDIT; ++i)
creatureTemplate.KillCredit[i] = fields[4 + i].GetUInt32();
creatureTemplate.Modelid1 = fields[6].GetUInt32();
creatureTemplate.Modelid2 = fields[7].GetUInt32();
creatureTemplate.Modelid3 = fields[8].GetUInt32();
creatureTemplate.Modelid4 = fields[9].GetUInt32();
//creatureTemplate.Modelid1 = fields[6].GetUInt32();
//creatureTemplate.Modelid2 = fields[7].GetUInt32();
//creatureTemplate.Modelid3 = fields[8].GetUInt32();
//creatureTemplate.Modelid4 = fields[9].GetUInt32();
creatureTemplate.Name = fields[10].GetString();
creatureTemplate.FemaleName = fields[11].GetString();
creatureTemplate.Title = fields[12].GetString();
@@ -562,6 +565,70 @@ void ObjectMgr::LoadCreatureTemplate(Field* fields)
creatureTemplate.ScriptID = GetScriptId(fields[87].GetCString());
}
void ObjectMgr::LoadCreatureTemplateModels()
{
uint32 oldMSTime = getMSTime();
// 0 1 2 3
QueryResult result = WorldDatabase.Query("SELECT CreatureID, Idx, CreatureDisplayID, Probability FROM creature_template_model ORDER BY Idx ASC");
if (!result)
{
TC_LOG_INFO("server.loading", ">> Loaded 0 creature template model definitions. DB table `creature_template_model` is empty.");
return;
}
uint32 count = 0;
do
{
Field* fields = result->Fetch();
uint32 creatureId = fields[0].GetUInt32();
uint32 idx = fields[1].GetUInt32();
uint32 creatureDisplayId = fields[2].GetUInt32();
float probability = fields[3].GetFloat();
CreatureTemplate const* cInfo = GetCreatureTemplate(creatureId);
if (!cInfo)
{
TC_LOG_ERROR("sql.sql", "Creature template (Entry: %u) does not exist but has a record in `creature_template_model`", creatureId);
continue;
}
if (idx >= MAX_CREATURE_MODELS)
{
TC_LOG_ERROR("sql.sql", "Creature (Entry: %u) lists CreatureDisplayID id (%u) at Idx (%u), max supported Idx is 3. Skipped!.", creatureId, creatureDisplayId, idx);
continue;
}
CreatureDisplayInfoEntry const* displayEntry = sCreatureDisplayInfoStore.LookupEntry(creatureDisplayId);
if (!displayEntry)
{
TC_LOG_ERROR("sql.sql", "Creature (Entry: %u) lists non-existing CreatureDisplayID id (%u), this can crash the client.", creatureId, creatureDisplayId);
continue;
}
CreatureModelInfo const* modelInfo = GetCreatureModelInfo(creatureDisplayId);
if (!modelInfo)
TC_LOG_ERROR("sql.sql", "No model data exist for `CreatureDisplayID` = %u listed by creature (Entry: %u).", creatureDisplayId, creatureId);
/// if not set custom creature scale then load scale from CreatureDisplayInfo.dbc
if (cInfo->scale <= 0.0f)
{
if (displayEntry)
const_cast<CreatureTemplate*>(cInfo)->scale = displayEntry->CreatureModelScale;
else
const_cast<CreatureTemplate*>(cInfo)->scale = 1.0f;
}
const_cast<CreatureTemplate*>(cInfo)->Models.emplace_back(creatureDisplayId, idx, probability);
++count;
} while (result->NextRow());
TC_LOG_INFO("server.loading", ">> Loaded %u creature template models in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
}
void ObjectMgr::LoadCreatureTemplateAddons()
{
uint32 oldMSTime = getMSTime();
@@ -950,75 +1017,8 @@ void ObjectMgr::CheckCreatureTemplate(CreatureTemplate const* cInfo)
ABORT();
}
// used later for scale
CreatureDisplayInfoEntry const* displayScaleEntry = nullptr;
if (cInfo->Modelid1)
{
CreatureDisplayInfoEntry const* displayEntry = sCreatureDisplayInfoStore.LookupEntry(cInfo->Modelid1);
if (!displayEntry)
{
TC_LOG_ERROR("sql.sql", "Creature (Entry: %u) lists non-existing Modelid1 id (%u), this can crash the client.", cInfo->Entry, cInfo->Modelid1);
const_cast<CreatureTemplate*>(cInfo)->Modelid1 = 0;
}
else
displayScaleEntry = displayEntry;
CreatureModelInfo const* modelInfo = GetCreatureModelInfo(cInfo->Modelid1);
if (!modelInfo)
TC_LOG_ERROR("sql.sql", "No model data exist for `Modelid1` = %u listed by creature (Entry: %u).", cInfo->Modelid1, cInfo->Entry);
}
if (cInfo->Modelid2)
{
CreatureDisplayInfoEntry const* displayEntry = sCreatureDisplayInfoStore.LookupEntry(cInfo->Modelid2);
if (!displayEntry)
{
TC_LOG_ERROR("sql.sql", "Creature (Entry: %u) lists non-existing Modelid2 id (%u), this can crash the client.", cInfo->Entry, cInfo->Modelid2);
const_cast<CreatureTemplate*>(cInfo)->Modelid2 = 0;
}
else if (!displayScaleEntry)
displayScaleEntry = displayEntry;
CreatureModelInfo const* modelInfo = GetCreatureModelInfo(cInfo->Modelid2);
if (!modelInfo)
TC_LOG_ERROR("sql.sql", "No model data exist for `Modelid2` = %u listed by creature (Entry: %u).", cInfo->Modelid2, cInfo->Entry);
}
if (cInfo->Modelid3)
{
CreatureDisplayInfoEntry const* displayEntry = sCreatureDisplayInfoStore.LookupEntry(cInfo->Modelid3);
if (!displayEntry)
{
TC_LOG_ERROR("sql.sql", "Creature (Entry: %u) lists non-existing Modelid3 id (%u), this can crash the client.", cInfo->Entry, cInfo->Modelid3);
const_cast<CreatureTemplate*>(cInfo)->Modelid3 = 0;
}
else if (!displayScaleEntry)
displayScaleEntry = displayEntry;
CreatureModelInfo const* modelInfo = GetCreatureModelInfo(cInfo->Modelid3);
if (!modelInfo)
TC_LOG_ERROR("sql.sql", "No model data exist for `Modelid3` = %u listed by creature (Entry: %u).", cInfo->Modelid3, cInfo->Entry);
}
if (cInfo->Modelid4)
{
CreatureDisplayInfoEntry const* displayEntry = sCreatureDisplayInfoStore.LookupEntry(cInfo->Modelid4);
if (!displayEntry)
{
TC_LOG_ERROR("sql.sql", "Creature (Entry: %u) lists non-existing Modelid4 id (%u), this can crash the client.", cInfo->Entry, cInfo->Modelid4);
const_cast<CreatureTemplate*>(cInfo)->Modelid4 = 0;
}
else if (!displayScaleEntry)
displayScaleEntry = displayEntry;
CreatureModelInfo const* modelInfo = GetCreatureModelInfo(cInfo->Modelid4);
if (!modelInfo)
TC_LOG_ERROR("sql.sql", "No model data exist for `Modelid4` = %u listed by creature (Entry: %u).", cInfo->Modelid4, cInfo->Entry);
}
if (!displayScaleEntry)
TC_LOG_ERROR("sql.sql", "Creature (Entry: %u) does not have any existing display id in Modelid1/Modelid2/Modelid3/Modelid4.", cInfo->Entry);
if (cInfo->Models.empty())
TC_LOG_ERROR("sql.sql", "Creature (Entry: %u) does not have any existing display id in creature_template_model.", cInfo->Entry);
for (uint8 k = 0; k < MAX_KILL_CREDIT; ++k)
{
@@ -1115,15 +1115,6 @@ void ObjectMgr::CheckCreatureTemplate(CreatureTemplate const* cInfo)
const_cast<CreatureTemplate*>(cInfo)->MovementType = IDLE_MOTION_TYPE;
}
/// if not set custom creature scale then load scale from CreatureDisplayInfo.dbc
if (cInfo->scale <= 0.0f)
{
if (displayScaleEntry)
const_cast<CreatureTemplate*>(cInfo)->scale = displayScaleEntry->CreatureModelScale;
else
const_cast<CreatureTemplate*>(cInfo)->scale = 1.0f;
}
if (cInfo->expansion > (MAX_EXPANSIONS - 1))
{
TC_LOG_ERROR("sql.sql", "Table `creature_template` lists creature (Entry: %u) with expansion %u. Ignored and set to 0.", cInfo->Entry, cInfo->expansion);
@@ -1620,14 +1611,16 @@ CreatureModelInfo const* ObjectMgr::GetCreatureModelInfo(uint32 modelId) const
return nullptr;
}
uint32 ObjectMgr::ChooseDisplayId(CreatureTemplate const* cinfo, CreatureData const* data /*= nullptr*/)
CreatureModel const* ObjectMgr::ChooseDisplayId(CreatureTemplate const* cinfo, CreatureData const* data /*= nullptr*/)
{
// Load creature model (display id)
if (data && data->displayid)
return data->displayid;
if (CreatureModel const* model = cinfo->GetModelWithDisplayId(data->displayid))
return model;
if (!(cinfo->flags_extra & CREATURE_FLAG_EXTRA_TRIGGER))
return cinfo->GetRandomValidModelId();
if (CreatureModel const* model = cinfo->GetRandomValidModel())
return model;
// Triggers by default receive the invisible model
return cinfo->GetFirstInvisibleModel();
@@ -1652,9 +1645,9 @@ void ObjectMgr::ChooseCreatureFlags(CreatureTemplate const* cinfo, uint32& npcfl
}
}
CreatureModelInfo const* ObjectMgr::GetCreatureModelRandomGender(uint32* displayID) const
CreatureModelInfo const* ObjectMgr::GetCreatureModelRandomGender(CreatureModel* model, CreatureTemplate const* creatureTemplate) const
{
CreatureModelInfo const* modelInfo = GetCreatureModelInfo(*displayID);
CreatureModelInfo const* modelInfo = GetCreatureModelInfo(model->CreatureDisplayID);
if (!modelInfo)
return nullptr;
@@ -1663,11 +1656,20 @@ CreatureModelInfo const* ObjectMgr::GetCreatureModelRandomGender(uint32* display
{
CreatureModelInfo const* minfo_tmp = GetCreatureModelInfo(modelInfo->modelid_other_gender);
if (!minfo_tmp)
TC_LOG_ERROR("sql.sql", "Model (Entry: %u) has modelid_other_gender %u not found in table `creature_model_info`. ", *displayID, modelInfo->modelid_other_gender);
TC_LOG_ERROR("sql.sql", "Model (Entry: {}) has modelid_other_gender {} not found in table `creature_model_info`. ", model->CreatureDisplayID, modelInfo->modelid_other_gender);
else
{
// Model ID changed
*displayID = modelInfo->modelid_other_gender;
// DisplayID changed
model->CreatureDisplayID = modelInfo->modelid_other_gender;
if (creatureTemplate)
{
auto itr = std::find_if(creatureTemplate->Models.begin(), creatureTemplate->Models.end(), [&](CreatureModel const& templateModel)
{
return templateModel.CreatureDisplayID == modelInfo->modelid_other_gender;
});
if (itr != creatureTemplate->Models.end())
*model = *itr;
}
return minfo_tmp;
}
}
@@ -6260,7 +6262,8 @@ void ObjectMgr::GetTaxiPath(uint32 source, uint32 destination, uint32 &path, uin
uint32 ObjectMgr::GetTaxiMountDisplayId(uint32 id, uint32 team, bool allowed_alt_team /* = false */)
{
uint32 mount_id = 0;
CreatureModel mountModel;
CreatureTemplate const* mount_info = nullptr;
// select mount creature id
TaxiNodesEntry const* node = sTaxiNodesStore.LookupEntry(id);
@@ -6280,22 +6283,23 @@ uint32 ObjectMgr::GetTaxiMountDisplayId(uint32 id, uint32 team, bool allowed_alt
mount_entry = team == ALLIANCE ? node->MountCreatureID[0] : node->MountCreatureID[1];
}
CreatureTemplate const* mount_info = GetCreatureTemplate(mount_entry);
mount_info = GetCreatureTemplate(mount_entry);
if (mount_info)
{
mount_id = mount_info->GetRandomValidModelId();
if (!mount_id)
CreatureModel const* model = mount_info->GetRandomValidModel();
if (!model)
{
TC_LOG_ERROR("sql.sql", "No displayid found for the taxi mount with the entry %u! Can't load it!", mount_entry);
return 0;
}
mountModel = *model;
}
}
// minfo is not actually used but the mount_id was updated
GetCreatureModelRandomGender(&mount_id);
GetCreatureModelRandomGender(&mountModel, mount_info);
return mount_id;
return mountModel.CreatureDisplayID;
}
Quest const* ObjectMgr::GetQuestTemplate(uint32 quest_id) const