mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-16 07:30:42 +01:00
Core/Creatures: Fixed level 240 guards and updated scaling level calculation
This commit is contained in:
10
sql/updates/world/master/2020_05_02_03_world.sql
Normal file
10
sql/updates/world/master/2020_05_02_03_world.sql
Normal file
@@ -0,0 +1,10 @@
|
||||
UPDATE creature_template SET `minlevel`=0 WHERE `minlevel`=1 AND `HealthScalingExpansion`=-1 AND `BaseAttackTime`=0; -- no attack time means we have no data and minlevel value was also defaulted
|
||||
UPDATE creature_template SET `maxlevel`=0 WHERE `maxlevel`=1 AND `HealthScalingExpansion`=-1 AND `BaseAttackTime`=0; -- no attack time means we have no data and maxlevel value was also defaulted
|
||||
UPDATE creature_template SET `minlevel`=`minlevel`-90 WHERE `minlevel`>=90 AND `minlevel`<100 AND `HealthScalingExpansion`=-1;
|
||||
UPDATE creature_template SET `maxlevel`=`maxlevel`-90 WHERE `maxlevel`>=90 AND `maxlevel`<100 AND `HealthScalingExpansion`=-1;
|
||||
UPDATE creature_template SET `minlevel`=`minlevel`-100 WHERE `minlevel`>=100 AND `minlevel`<110 AND `HealthScalingExpansion`=-1;
|
||||
UPDATE creature_template SET `maxlevel`=`maxlevel`-100 WHERE `maxlevel`>=100 AND `maxlevel`<110 AND `HealthScalingExpansion`=-1;
|
||||
UPDATE creature_template SET `minlevel`=`minlevel`-110 WHERE `minlevel`>=110 AND `minlevel`<120 AND `HealthScalingExpansion`=-1;
|
||||
UPDATE creature_template SET `maxlevel`=`maxlevel`-110 WHERE `maxlevel`>=110 AND `maxlevel`<120 AND `HealthScalingExpansion`=-1;
|
||||
UPDATE creature_template SET `minlevel`=`minlevel`-120 WHERE `minlevel`>=120 AND `minlevel`<130 AND `HealthScalingExpansion`=-1;
|
||||
UPDATE creature_template SET `maxlevel`=`maxlevel`-120 WHERE `maxlevel`>=120 AND `maxlevel`<130 AND `HealthScalingExpansion`=-1;
|
||||
@@ -77,7 +77,7 @@ void WorldDatabaseConnection::DoPrepareStatements()
|
||||
PrepareStatement(WORLD_SEL_WAYPOINT_SCRIPT_ID_BY_GUID, "SELECT id FROM waypoint_scripts WHERE guid = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(WORLD_DEL_CREATURE, "DELETE FROM creature WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(WORLD_SEL_COMMANDS, "SELECT name, permission, help FROM command", CONNECTION_SYNCH);
|
||||
PrepareStatement(WORLD_SEL_CREATURE_TEMPLATE, "SELECT entry, difficulty_entry_1, difficulty_entry_2, difficulty_entry_3, KillCredit1, KillCredit2, name, femaleName, subname, TitleAlt, IconName, gossip_menu_id, minlevel, maxlevel, HealthScalingExpansion, RequiredExpansion, VignetteID, faction, npcflag, speed_walk, speed_run, scale, `rank`, dmgschool, BaseAttackTime, RangeAttackTime, BaseVariance, RangeVariance, unit_class, unit_flags, unit_flags2, unit_flags3, dynamicflags, family, trainer_class, type, type_flags, type_flags2, lootid, pickpocketloot, skinloot, resistance1, resistance2, resistance3, resistance4, resistance5, resistance6, spell1, spell2, spell3, spell4, spell5, spell6, spell7, spell8, VehicleId, mingold, maxgold, AIName, MovementType, InhabitType, HoverHeight, HealthModifier, HealthModifierExtra, ManaModifier, ManaModifierExtra, ArmorModifier, DamageModifier, ExperienceModifier, RacialLeader, movementId, RegenHealth, mechanic_immune_mask, flags_extra, ScriptName FROM creature_template WHERE entry = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(WORLD_SEL_CREATURE_TEMPLATE, "SELECT entry, difficulty_entry_1, difficulty_entry_2, difficulty_entry_3, KillCredit1, KillCredit2, name, femaleName, subname, TitleAlt, IconName, gossip_menu_id, minlevel, maxlevel, HealthScalingExpansion, RequiredExpansion, VignetteID, faction, npcflag, speed_walk, speed_run, scale, `rank`, dmgschool, BaseAttackTime, RangeAttackTime, BaseVariance, RangeVariance, unit_class, unit_flags, unit_flags2, unit_flags3, dynamicflags, family, trainer_class, type, type_flags, type_flags2, lootid, pickpocketloot, skinloot, resistance1, resistance2, resistance3, resistance4, resistance5, resistance6, spell1, spell2, spell3, spell4, spell5, spell6, spell7, spell8, VehicleId, mingold, maxgold, AIName, MovementType, InhabitType, HoverHeight, HealthModifier, HealthModifierExtra, ManaModifier, ManaModifierExtra, ArmorModifier, DamageModifier, ExperienceModifier, RacialLeader, movementId, FadeRegionRadius, WidgetSetID, WidgetSetUnitConditionID, RegenHealth, mechanic_immune_mask, flags_extra, ScriptName FROM creature_template WHERE entry = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(WORLD_SEL_WAYPOINT_SCRIPT_BY_ID, "SELECT guid, delay, command, datalong, datalong2, dataint, x, y, z, o FROM waypoint_scripts WHERE id = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(WORLD_SEL_CREATURE_BY_ID, "SELECT guid FROM creature WHERE id = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(WORLD_SEL_GAMEOBJECT_NEAREST, "SELECT guid, id, position_x, position_y, position_z, map, (POW(position_x - ?, 2) + POW(position_y - ?, 2) + POW(position_z - ?, 2)) AS order_ FROM gameobject WHERE map = ? AND (POW(position_x - ?, 2) + POW(position_y - ?, 2) + POW(position_z - ?, 2)) <= ? ORDER BY order_", CONNECTION_SYNCH);
|
||||
|
||||
@@ -143,6 +143,20 @@ CreatureModel const* CreatureTemplate::GetFirstVisibleModel() const
|
||||
return &CreatureModel::DefaultVisibleModel;
|
||||
}
|
||||
|
||||
std::pair<int16, int16> CreatureTemplate::GetMinMaxLevel() const
|
||||
{
|
||||
return
|
||||
{
|
||||
HealthScalingExpansion != EXPANSION_LEVEL_CURRENT ? minlevel : minlevel + MAX_LEVEL,
|
||||
HealthScalingExpansion != EXPANSION_LEVEL_CURRENT ? maxlevel : maxlevel + MAX_LEVEL
|
||||
};
|
||||
}
|
||||
|
||||
int32 CreatureTemplate::GetHealthScalingExpansion() const
|
||||
{
|
||||
return HealthScalingExpansion == EXPANSION_LEVEL_CURRENT ? CURRENT_EXPANSION : HealthScalingExpansion;
|
||||
}
|
||||
|
||||
void CreatureTemplate::InitializeQueryData()
|
||||
{
|
||||
WorldPacket queryTemp;
|
||||
@@ -1389,8 +1403,9 @@ void Creature::SelectLevel()
|
||||
CreatureTemplate const* cInfo = GetCreatureTemplate();
|
||||
|
||||
// level
|
||||
uint8 minlevel = std::min(cInfo->maxlevel, cInfo->minlevel);
|
||||
uint8 maxlevel = std::max(cInfo->maxlevel, cInfo->minlevel);
|
||||
std::pair<int16, int16> levels = cInfo->GetMinMaxLevel();
|
||||
uint8 minlevel = std::min(levels.first, levels.second);
|
||||
uint8 maxlevel = std::max(levels.first, levels.second);
|
||||
uint8 level = minlevel == maxlevel ? minlevel : urand(minlevel, maxlevel);
|
||||
SetLevel(level);
|
||||
|
||||
@@ -2702,7 +2717,7 @@ uint64 Creature::GetMaxHealthByLevel(uint8 level) const
|
||||
{
|
||||
CreatureTemplate const* cInfo = GetCreatureTemplate();
|
||||
CreatureLevelScaling const* scaling = cInfo->GetLevelScaling(GetMap()->GetDifficultyID());
|
||||
float baseHealth = sDB2Manager.EvaluateExpectedStat(ExpectedStatType::CreatureHealth, level, cInfo->HealthScalingExpansion, scaling->ContentTuningID, Classes(cInfo->unit_class));
|
||||
float baseHealth = sDB2Manager.EvaluateExpectedStat(ExpectedStatType::CreatureHealth, level, cInfo->GetHealthScalingExpansion(), scaling->ContentTuningID, Classes(cInfo->unit_class));
|
||||
return baseHealth * cInfo->ModHealth * cInfo->ModHealthExtra;
|
||||
}
|
||||
|
||||
@@ -2722,7 +2737,7 @@ float Creature::GetBaseDamageForLevel(uint8 level) const
|
||||
{
|
||||
CreatureTemplate const* cInfo = GetCreatureTemplate();
|
||||
CreatureLevelScaling const* scaling = cInfo->GetLevelScaling(GetMap()->GetDifficultyID());
|
||||
return sDB2Manager.EvaluateExpectedStat(ExpectedStatType::CreatureAutoAttackDps, level, cInfo->HealthScalingExpansion, scaling->ContentTuningID, Classes(cInfo->unit_class));
|
||||
return sDB2Manager.EvaluateExpectedStat(ExpectedStatType::CreatureAutoAttackDps, level, cInfo->GetHealthScalingExpansion(), scaling->ContentTuningID, Classes(cInfo->unit_class));
|
||||
}
|
||||
|
||||
float Creature::GetDamageMultiplierForTarget(WorldObject const* target) const
|
||||
@@ -2739,7 +2754,7 @@ float Creature::GetBaseArmorForLevel(uint8 level) const
|
||||
{
|
||||
CreatureTemplate const* cInfo = GetCreatureTemplate();
|
||||
CreatureLevelScaling const* scaling = cInfo->GetLevelScaling(GetMap()->GetDifficultyID());
|
||||
float baseArmor = sDB2Manager.EvaluateExpectedStat(ExpectedStatType::CreatureArmor, level, cInfo->HealthScalingExpansion, scaling->ContentTuningID, Classes(cInfo->unit_class));
|
||||
float baseArmor = sDB2Manager.EvaluateExpectedStat(ExpectedStatType::CreatureArmor, level, cInfo->GetHealthScalingExpansion(), scaling->ContentTuningID, Classes(cInfo->unit_class));
|
||||
return baseArmor * cInfo->ModArmor;
|
||||
}
|
||||
|
||||
@@ -2767,12 +2782,28 @@ uint8 Creature::GetLevelForTarget(WorldObject const* target) const
|
||||
// between UNIT_FIELD_SCALING_LEVEL_MIN and UNIT_FIELD_SCALING_LEVEL_MAX
|
||||
if (HasScalableLevels())
|
||||
{
|
||||
uint8 targetLevelWithDelta = unitTarget->getLevel() + m_unitData->ScalingLevelDelta;
|
||||
int32 scalingLevelMin = m_unitData->ScalingLevelMin;
|
||||
int32 scalingLevelMax = m_unitData->ScalingLevelMax;
|
||||
int32 scalingLevelDelta = m_unitData->ScalingLevelDelta;
|
||||
int32 scalingFactionGroup = m_unitData->ScalingFactionGroup;
|
||||
int32 targetLevel = unitTarget->m_unitData->EffectiveLevel;
|
||||
if (!targetLevel)
|
||||
targetLevel = unitTarget->getLevel();
|
||||
|
||||
if (target->IsPlayer())
|
||||
targetLevelWithDelta += target->ToPlayer()->m_activePlayerData->ScalingPlayerLevelDelta;
|
||||
int32 targetLevelDelta = 0;
|
||||
|
||||
return RoundToInterval<uint8>(targetLevelWithDelta, m_unitData->ScalingLevelMin, m_unitData->ScalingLevelMax);
|
||||
if (Player const* playerTarget = target->ToPlayer())
|
||||
{
|
||||
if (scalingFactionGroup && sFactionTemplateStore.AssertEntry(sChrRacesStore.AssertEntry(playerTarget->getRace())->FactionID)->FactionGroup != scalingFactionGroup)
|
||||
scalingLevelMin = scalingLevelMax;
|
||||
|
||||
int32 maxCreatureScalingLevel = playerTarget->m_activePlayerData->MaxCreatureScalingLevel;
|
||||
targetLevelDelta = std::min(maxCreatureScalingLevel > 0 ? maxCreatureScalingLevel - targetLevel : 0, *playerTarget->m_activePlayerData->ScalingPlayerLevelDelta);
|
||||
}
|
||||
|
||||
int32 levelWithDelta = targetLevel + targetLevelDelta;
|
||||
int32 level = RoundToInterval(levelWithDelta, scalingLevelMin, scalingLevelMax) + scalingLevelDelta;
|
||||
return RoundToInterval(level, 1, MAX_LEVEL + 3);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -409,6 +409,8 @@ struct TC_GAME_API CreatureTemplate
|
||||
CreatureModel const* GetModelWithDisplayId(uint32 displayId) const;
|
||||
CreatureModel const* GetFirstInvisibleModel() const;
|
||||
CreatureModel const* GetFirstVisibleModel() const;
|
||||
std::pair<int16, int16> GetMinMaxLevel() const;
|
||||
int32 GetHealthScalingExpansion() const;
|
||||
CreatureLevelScaling const* GetLevelScaling(Difficulty difficulty) const;
|
||||
|
||||
// helpers
|
||||
|
||||
@@ -842,7 +842,7 @@ bool Guardian::InitStatsForLevel(uint8 petlevel)
|
||||
CreatureBaseStats const* stats = sObjectMgr->GetCreatureBaseStats(petlevel, cinfo->unit_class);
|
||||
CreatureLevelScaling const* scaling = cinfo->GetLevelScaling(GetMap()->GetDifficultyID());
|
||||
|
||||
SetCreateHealth(sDB2Manager.EvaluateExpectedStat(ExpectedStatType::CreatureHealth, petlevel, cinfo->HealthScalingExpansion, scaling->ContentTuningID, Classes(cinfo->unit_class)) * cinfo->ModHealth * cinfo->ModHealthExtra);
|
||||
SetCreateHealth(sDB2Manager.EvaluateExpectedStat(ExpectedStatType::CreatureHealth, petlevel, cinfo->GetHealthScalingExpansion(), scaling->ContentTuningID, Classes(cinfo->unit_class)) * cinfo->ModHealth * cinfo->ModHealthExtra);
|
||||
SetCreateMana(stats->BaseMana);
|
||||
|
||||
SetCreateStat(STAT_STRENGTH, 22);
|
||||
|
||||
@@ -1032,13 +1032,13 @@ void ObjectMgr::CheckCreatureTemplate(CreatureTemplate const* cInfo)
|
||||
const_cast<CreatureTemplate*>(cInfo)->MovementType = IDLE_MOTION_TYPE;
|
||||
}
|
||||
|
||||
if (cInfo->HealthScalingExpansion < EXPANSION_LEVEL_CURRENT || cInfo->HealthScalingExpansion > (MAX_EXPANSIONS - 1))
|
||||
if (cInfo->HealthScalingExpansion < EXPANSION_LEVEL_CURRENT || cInfo->HealthScalingExpansion >= MAX_EXPANSIONS)
|
||||
{
|
||||
TC_LOG_ERROR("sql.sql", "Table `creature_template` lists creature (ID: %u) with invalid `HealthScalingExpansion` %i. Ignored and set to 0.", cInfo->Entry, cInfo->HealthScalingExpansion);
|
||||
const_cast<CreatureTemplate*>(cInfo)->HealthScalingExpansion = 0;
|
||||
}
|
||||
|
||||
if (cInfo->RequiredExpansion > (MAX_EXPANSIONS - 1))
|
||||
if (cInfo->RequiredExpansion >= MAX_EXPANSIONS)
|
||||
{
|
||||
TC_LOG_ERROR("sql.sql", "Table `creature_template` lists creature (Entry: %u) with `RequiredExpansion` %u. Ignored and set to 0.", cInfo->Entry, cInfo->RequiredExpansion);
|
||||
const_cast<CreatureTemplate*>(cInfo)->RequiredExpansion = 0;
|
||||
@@ -1050,26 +1050,19 @@ void ObjectMgr::CheckCreatureTemplate(CreatureTemplate const* cInfo)
|
||||
const_cast<CreatureTemplate*>(cInfo)->flags_extra &= CREATURE_FLAG_EXTRA_DB_ALLOWED;
|
||||
}
|
||||
|
||||
// -1, as expansion, is used in CreatureDifficulty.db2 for
|
||||
// auto-updating the levels of creatures having their expansion
|
||||
// set to that value to the current expansion's max leveling level
|
||||
if (cInfo->HealthScalingExpansion == EXPANSION_LEVEL_CURRENT)
|
||||
std::pair<int16, int16> levels = cInfo->GetMinMaxLevel();
|
||||
if (levels.first < 1 || levels.first > STRONG_MAX_LEVEL)
|
||||
{
|
||||
const_cast<CreatureTemplate*>(cInfo)->minlevel = (MAX_LEVEL + cInfo->minlevel);
|
||||
const_cast<CreatureTemplate*>(cInfo)->maxlevel = (MAX_LEVEL + cInfo->maxlevel);
|
||||
const_cast<CreatureTemplate*>(cInfo)->HealthScalingExpansion = CURRENT_EXPANSION;
|
||||
TC_LOG_ERROR("sql.sql", "Creature (ID: %u): Calculated minLevel %i is not within [1, 255], value has been set to %u.", cInfo->Entry, cInfo->minlevel,
|
||||
cInfo->HealthScalingExpansion == EXPANSION_LEVEL_CURRENT ? MAX_LEVEL : 1);
|
||||
const_cast<CreatureTemplate*>(cInfo)->minlevel = cInfo->HealthScalingExpansion == EXPANSION_LEVEL_CURRENT ? 0 : 1;
|
||||
}
|
||||
|
||||
if (cInfo->minlevel < 1 || cInfo->minlevel > STRONG_MAX_LEVEL)
|
||||
if (levels.second < 1 || levels.second > STRONG_MAX_LEVEL)
|
||||
{
|
||||
TC_LOG_ERROR("sql.sql", "Creature (ID: %u): MinLevel %i is not within [1, 255], value has been set to 1.", cInfo->Entry, cInfo->minlevel);
|
||||
const_cast<CreatureTemplate*>(cInfo)->minlevel = 1;
|
||||
}
|
||||
|
||||
if (cInfo->maxlevel < 1 || cInfo->maxlevel > STRONG_MAX_LEVEL)
|
||||
{
|
||||
TC_LOG_ERROR("sql.sql", "Creature (ID: %u): MaxLevel %i is not within [1, 255], value has been set to 1.", cInfo->Entry, cInfo->maxlevel);
|
||||
const_cast<CreatureTemplate*>(cInfo)->maxlevel = 1;
|
||||
TC_LOG_ERROR("sql.sql", "Creature (ID: %u): Calculated maxLevel %i is not within [1, 255], value has been set to %u.", cInfo->Entry, cInfo->maxlevel,
|
||||
cInfo->HealthScalingExpansion == EXPANSION_LEVEL_CURRENT ? MAX_LEVEL : 1);
|
||||
const_cast<CreatureTemplate*>(cInfo)->maxlevel = cInfo->HealthScalingExpansion == EXPANSION_LEVEL_CURRENT ? 0 : 1;
|
||||
}
|
||||
|
||||
const_cast<CreatureTemplate*>(cInfo)->ModDamage *= Creature::_GetDamageMod(cInfo->rank);
|
||||
@@ -2229,7 +2222,8 @@ ObjectGuid::LowType ObjectMgr::AddCreatureData(uint32 entry, uint32 mapId, float
|
||||
if (!cInfo)
|
||||
return UI64LIT(0);
|
||||
|
||||
uint32 level = cInfo->minlevel == cInfo->maxlevel ? cInfo->minlevel : urand(cInfo->minlevel, cInfo->maxlevel); // Only used for extracting creature base stats
|
||||
std::pair<int16, int16> levels = cInfo->GetMinMaxLevel();
|
||||
uint32 level = levels.first == levels.second ? levels.first : urand(levels.first, levels.second); // Only used for extracting creature base stats
|
||||
CreatureBaseStats const* stats = GetCreatureBaseStats(level, cInfo->unit_class);
|
||||
Map* map = sMapMgr->CreateBaseMap(mapId);
|
||||
if (!map)
|
||||
@@ -2250,7 +2244,7 @@ ObjectGuid::LowType ObjectMgr::AddCreatureData(uint32 entry, uint32 mapId, float
|
||||
data.spawntimesecs = spawntimedelay;
|
||||
data.spawndist = 0;
|
||||
data.currentwaypoint = 0;
|
||||
data.curhealth = sDB2Manager.EvaluateExpectedStat(ExpectedStatType::CreatureHealth, level, cInfo->HealthScalingExpansion, scaling->ContentTuningID, Classes(cInfo->unit_class)) * cInfo->ModHealth * cInfo->ModHealthExtra;
|
||||
data.curhealth = sDB2Manager.EvaluateExpectedStat(ExpectedStatType::CreatureHealth, level, cInfo->GetHealthScalingExpansion(), scaling->ContentTuningID, Classes(cInfo->unit_class)) * cInfo->ModHealth * cInfo->ModHealthExtra;
|
||||
data.curmana = stats->GenerateMana(cInfo);
|
||||
data.movementType = cInfo->MovementType;
|
||||
data.spawnDifficulties.push_back(DIFFICULTY_NONE);
|
||||
@@ -9298,9 +9292,10 @@ void ObjectMgr::LoadCreatureClassLevelStats()
|
||||
while (result->NextRow());
|
||||
|
||||
CreatureTemplateContainer const* ctc = sObjectMgr->GetCreatureTemplates();
|
||||
for (CreatureTemplateContainer::const_iterator itr = ctc->begin(); itr != ctc->end(); ++itr)
|
||||
for (auto itr = ctc->begin(); itr != ctc->end(); ++itr)
|
||||
{
|
||||
for (uint16 lvl = itr->second.minlevel; lvl <= itr->second.maxlevel; ++lvl)
|
||||
std::pair<int16, int16> levels = itr->second.GetMinMaxLevel();
|
||||
for (int16 lvl = levels.first; lvl <= levels.second; ++lvl)
|
||||
{
|
||||
if (_creatureBaseStatsStore.find(MAKE_PAIR16(lvl, itr->second.unit_class)) == _creatureBaseStatsStore.end())
|
||||
TC_LOG_ERROR("sql.sql", "Missing base stats for creature class %u level %u", itr->second.unit_class, lvl);
|
||||
|
||||
@@ -181,7 +181,7 @@ namespace Trinity
|
||||
if (gain && creature)
|
||||
{
|
||||
// Players get only 10% xp for killing creatures of lower expansion levels than himself
|
||||
if ((uint32(creature->GetCreatureTemplate()->HealthScalingExpansion) < GetExpansionForLevel(player->getLevel())))
|
||||
if ((uint32(creature->GetCreatureTemplate()->GetHealthScalingExpansion()) < GetExpansionForLevel(player->getLevel())))
|
||||
gain = uint32(round(gain / 10.0f));
|
||||
|
||||
if (creature->isElite())
|
||||
|
||||
Reference in New Issue
Block a user