Core/Items: Fixed item level and stat calculation
This commit is contained in:
@@ -2295,13 +2295,13 @@ uint32 Item::GetItemLevel(ItemTemplate const* itemTemplate, BonusData const& bon
|
||||
else if (Optional<ContentTuningLevels> levels = sDB2Manager.GetContentTuningData(bonusData.ContentTuningId, {}, true))
|
||||
level = std::min(std::max(int16(level), levels->MinLevel), levels->MaxLevel);
|
||||
|
||||
itemLevel = uint32(sDB2Manager.GetCurveValueAt(bonusData.PlayerLevelToItemLevelCurveId, level));
|
||||
itemLevel = uint32(std::round(sDB2Manager.GetCurveValueAt(bonusData.PlayerLevelToItemLevelCurveId, level)));
|
||||
}
|
||||
|
||||
itemLevel += bonusData.ItemLevelBonus;
|
||||
}
|
||||
else
|
||||
itemLevel = bonusData.ItemLevelOffset + uint32(sDB2Manager.GetCurveValueAt(bonusData.ItemLevelOffsetCurveId, bonusData.ItemLevelOffsetItemLevel));
|
||||
itemLevel = bonusData.ItemLevelOffset + uint32(std::round(sDB2Manager.GetCurveValueAt(bonusData.ItemLevelOffsetCurveId, bonusData.ItemLevelOffsetItemLevel)));
|
||||
|
||||
for (uint32 i = 0; i < MAX_ITEM_PROTO_SOCKETS; ++i)
|
||||
itemLevel += bonusData.GemItemLevelBonus[i];
|
||||
@@ -2323,17 +2323,17 @@ uint32 Item::GetItemLevel(ItemTemplate const* itemTemplate, BonusData const& bon
|
||||
int32 currentBuild = ClientBuild::GetMinorMajorBugfixVersionForBuild(currentRealm->Build);
|
||||
|
||||
// apply all squishes between items_squish and server_squish
|
||||
for (uint32 squishId = bonusData.ItemSquishEraID; squishId < sItemSquishEraStore.GetNumRows(); ++squishId)
|
||||
for (uint32 squishId = bonusData.ItemSquishEraID + 1; squishId < sItemSquishEraStore.GetNumRows(); ++squishId)
|
||||
{
|
||||
ItemSquishEraEntry const* squish = sItemSquishEraStore.LookupEntry(squishId);
|
||||
if (!squish)
|
||||
if (!squish || squish->Flags & 0x1)
|
||||
continue;
|
||||
|
||||
if (squish->Patch > currentBuild)
|
||||
break;
|
||||
|
||||
if (squish->CurveID)
|
||||
itemLevel = uint32(sDB2Manager.GetCurveValueAt(squish->CurveID, itemLevel));
|
||||
itemLevel = uint32(std::round(sDB2Manager.GetCurveValueAt(squish->CurveID, itemLevel)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2367,7 +2367,7 @@ float Item::GetItemStatValue(uint32 index, Player const* owner) const
|
||||
{
|
||||
float statValue = float(_bonusData.StatPercentEditor[index] * randomPropPoints) * 0.0001f;
|
||||
if (GtItemSocketCostPerLevelEntry const* gtCost = sItemSocketCostPerLevelGameTable.GetRow(itemLevel))
|
||||
statValue -= float(int32(_bonusData.ItemStatSocketCostMultiplier[index] * gtCost->SocketCost));
|
||||
statValue -= float(_bonusData.ItemStatSocketCostMultiplier[index] * gtCost->SocketCost);
|
||||
|
||||
return statValue;
|
||||
}
|
||||
|
||||
@@ -7970,6 +7970,44 @@ void Player::_ApplyItemBonuses(Item* item, uint8 slot, bool apply)
|
||||
if (val == 0)
|
||||
continue;
|
||||
|
||||
// apply stat multiplier
|
||||
switch (statType)
|
||||
{
|
||||
case ITEM_MOD_STAMINA:
|
||||
if (GtStaminaMultByILvl const* staminaMult = sStaminaMultByILvlGameTable.GetRow(itemLevel))
|
||||
val *= GetIlvlStatMultiplier(staminaMult, proto->GetInventoryType());
|
||||
break;
|
||||
case ITEM_MOD_DEFENSE_SKILL_RATING:
|
||||
case ITEM_MOD_DODGE_RATING:
|
||||
case ITEM_MOD_PARRY_RATING:
|
||||
case ITEM_MOD_BLOCK_RATING:
|
||||
case ITEM_MOD_HIT_MELEE_RATING:
|
||||
case ITEM_MOD_HIT_RANGED_RATING:
|
||||
case ITEM_MOD_HIT_SPELL_RATING:
|
||||
case ITEM_MOD_CRIT_MELEE_RATING:
|
||||
case ITEM_MOD_CRIT_RANGED_RATING:
|
||||
case ITEM_MOD_CRIT_SPELL_RATING:
|
||||
case ITEM_MOD_HIT_RATING:
|
||||
case ITEM_MOD_CRIT_RATING:
|
||||
case ITEM_MOD_HIT_TAKEN_RATING:
|
||||
case ITEM_MOD_CRIT_TAKEN_RATING:
|
||||
case ITEM_MOD_RESILIENCE_RATING:
|
||||
case ITEM_MOD_HASTE_RATING:
|
||||
case ITEM_MOD_EXPERTISE_RATING:
|
||||
case ITEM_MOD_VERSATILITY:
|
||||
case ITEM_MOD_MASTERY_RATING:
|
||||
case ITEM_MOD_CR_SPEED:
|
||||
case ITEM_MOD_CR_LIFESTEAL:
|
||||
case ITEM_MOD_CR_AVOIDANCE:
|
||||
case ITEM_MOD_CR_STURDINESS:
|
||||
val *= combatRatingMultiplier;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
val = std::round(val);
|
||||
|
||||
switch (statType)
|
||||
{
|
||||
case ITEM_MOD_MANA:
|
||||
@@ -7995,42 +8033,38 @@ void Player::_ApplyItemBonuses(Item* item, uint8 slot, bool apply)
|
||||
UpdateStatBuffMod(STAT_SPIRIT);
|
||||
break;
|
||||
case ITEM_MOD_STAMINA: //modify stamina
|
||||
{
|
||||
if (GtStaminaMultByILvl const* staminaMult = sStaminaMultByILvlGameTable.GetRow(itemLevel))
|
||||
val = int32(val * GetIlvlStatMultiplier(staminaMult, proto->GetInventoryType()));
|
||||
HandleStatFlatModifier(UNIT_MOD_STAT_STAMINA, BASE_VALUE, float(val), apply);
|
||||
UpdateStatBuffMod(STAT_STAMINA);
|
||||
break;
|
||||
}
|
||||
case ITEM_MOD_DEFENSE_SKILL_RATING:
|
||||
ApplyRatingMod(CR_DEFENSE_SKILL, int32(val * combatRatingMultiplier), apply);
|
||||
ApplyRatingMod(CR_DEFENSE_SKILL, int32(val), apply);
|
||||
break;
|
||||
case ITEM_MOD_DODGE_RATING:
|
||||
ApplyRatingMod(CR_DODGE, int32(val * combatRatingMultiplier), apply);
|
||||
ApplyRatingMod(CR_DODGE, int32(val), apply);
|
||||
break;
|
||||
case ITEM_MOD_PARRY_RATING:
|
||||
ApplyRatingMod(CR_PARRY, int32(val * combatRatingMultiplier), apply);
|
||||
ApplyRatingMod(CR_PARRY, int32(val), apply);
|
||||
break;
|
||||
case ITEM_MOD_BLOCK_RATING:
|
||||
ApplyRatingMod(CR_BLOCK, int32(val * combatRatingMultiplier), apply);
|
||||
ApplyRatingMod(CR_BLOCK, int32(val), apply);
|
||||
break;
|
||||
case ITEM_MOD_HIT_MELEE_RATING:
|
||||
ApplyRatingMod(CR_HIT_MELEE, int32(val * combatRatingMultiplier), apply);
|
||||
ApplyRatingMod(CR_HIT_MELEE, int32(val), apply);
|
||||
break;
|
||||
case ITEM_MOD_HIT_RANGED_RATING:
|
||||
ApplyRatingMod(CR_HIT_RANGED, int32(val * combatRatingMultiplier), apply);
|
||||
ApplyRatingMod(CR_HIT_RANGED, int32(val), apply);
|
||||
break;
|
||||
case ITEM_MOD_HIT_SPELL_RATING:
|
||||
ApplyRatingMod(CR_HIT_SPELL, int32(val * combatRatingMultiplier), apply);
|
||||
ApplyRatingMod(CR_HIT_SPELL, int32(val), apply);
|
||||
break;
|
||||
case ITEM_MOD_CRIT_MELEE_RATING:
|
||||
ApplyRatingMod(CR_CRIT_MELEE, int32(val * combatRatingMultiplier), apply);
|
||||
ApplyRatingMod(CR_CRIT_MELEE, int32(val), apply);
|
||||
break;
|
||||
case ITEM_MOD_CRIT_RANGED_RATING:
|
||||
ApplyRatingMod(CR_CRIT_RANGED, int32(val * combatRatingMultiplier), apply);
|
||||
ApplyRatingMod(CR_CRIT_RANGED, int32(val), apply);
|
||||
break;
|
||||
case ITEM_MOD_CRIT_SPELL_RATING:
|
||||
ApplyRatingMod(CR_CRIT_SPELL, int32(val * combatRatingMultiplier), apply);
|
||||
ApplyRatingMod(CR_CRIT_SPELL, int32(val), apply);
|
||||
break;
|
||||
// case ITEM_MOD_HIT_TAKEN_MELEE_RATING:
|
||||
// ApplyRatingMod(CR_HIT_TAKEN_MELEE, int32(val), apply);
|
||||
@@ -8060,14 +8094,14 @@ void Player::_ApplyItemBonuses(Item* item, uint8 slot, bool apply)
|
||||
ApplyRatingMod(CR_HASTE_SPELL, int32(val), apply);
|
||||
break;
|
||||
case ITEM_MOD_HIT_RATING:
|
||||
ApplyRatingMod(CR_HIT_MELEE, int32(val * combatRatingMultiplier), apply);
|
||||
ApplyRatingMod(CR_HIT_RANGED, int32(val * combatRatingMultiplier), apply);
|
||||
ApplyRatingMod(CR_HIT_SPELL, int32(val * combatRatingMultiplier), apply);
|
||||
ApplyRatingMod(CR_HIT_MELEE, int32(val), apply);
|
||||
ApplyRatingMod(CR_HIT_RANGED, int32(val), apply);
|
||||
ApplyRatingMod(CR_HIT_SPELL, int32(val), apply);
|
||||
break;
|
||||
case ITEM_MOD_CRIT_RATING:
|
||||
ApplyRatingMod(CR_CRIT_MELEE, int32(val * combatRatingMultiplier), apply);
|
||||
ApplyRatingMod(CR_CRIT_RANGED, int32(val * combatRatingMultiplier), apply);
|
||||
ApplyRatingMod(CR_CRIT_SPELL, int32(val * combatRatingMultiplier), apply);
|
||||
ApplyRatingMod(CR_CRIT_MELEE, int32(val), apply);
|
||||
ApplyRatingMod(CR_CRIT_RANGED, int32(val), apply);
|
||||
ApplyRatingMod(CR_CRIT_SPELL, int32(val), apply);
|
||||
break;
|
||||
// case ITEM_MOD_HIT_TAKEN_RATING: // Unused since 3.3.5
|
||||
// ApplyRatingMod(CR_HIT_TAKEN_MELEE, int32(val), apply);
|
||||
@@ -8080,15 +8114,15 @@ void Player::_ApplyItemBonuses(Item* item, uint8 slot, bool apply)
|
||||
// ApplyRatingMod(CR_CRIT_TAKEN_SPELL, int32(val), apply);
|
||||
// break;
|
||||
case ITEM_MOD_RESILIENCE_RATING:
|
||||
ApplyRatingMod(CR_RESILIENCE_PLAYER_DAMAGE, int32(val * combatRatingMultiplier), apply);
|
||||
ApplyRatingMod(CR_RESILIENCE_PLAYER_DAMAGE, int32(val), apply);
|
||||
break;
|
||||
case ITEM_MOD_HASTE_RATING:
|
||||
ApplyRatingMod(CR_HASTE_MELEE, int32(val * combatRatingMultiplier), apply);
|
||||
ApplyRatingMod(CR_HASTE_RANGED, int32(val * combatRatingMultiplier), apply);
|
||||
ApplyRatingMod(CR_HASTE_SPELL, int32(val * combatRatingMultiplier), apply);
|
||||
ApplyRatingMod(CR_HASTE_MELEE, int32(val), apply);
|
||||
ApplyRatingMod(CR_HASTE_RANGED, int32(val), apply);
|
||||
ApplyRatingMod(CR_HASTE_SPELL, int32(val), apply);
|
||||
break;
|
||||
case ITEM_MOD_EXPERTISE_RATING:
|
||||
ApplyRatingMod(CR_EXPERTISE, int32(val * combatRatingMultiplier), apply);
|
||||
ApplyRatingMod(CR_EXPERTISE, int32(val), apply);
|
||||
break;
|
||||
case ITEM_MOD_ATTACK_POWER:
|
||||
HandleStatFlatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_VALUE, float(val), apply);
|
||||
@@ -8098,9 +8132,9 @@ void Player::_ApplyItemBonuses(Item* item, uint8 slot, bool apply)
|
||||
HandleStatFlatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(val), apply);
|
||||
break;
|
||||
case ITEM_MOD_VERSATILITY:
|
||||
ApplyRatingMod(CR_VERSATILITY_DAMAGE_DONE, int32(val * combatRatingMultiplier), apply);
|
||||
ApplyRatingMod(CR_VERSATILITY_DAMAGE_TAKEN, int32(val * combatRatingMultiplier), apply);
|
||||
ApplyRatingMod(CR_VERSATILITY_HEALING_DONE, int32(val * combatRatingMultiplier), apply);
|
||||
ApplyRatingMod(CR_VERSATILITY_DAMAGE_DONE, int32(val), apply);
|
||||
ApplyRatingMod(CR_VERSATILITY_DAMAGE_TAKEN, int32(val), apply);
|
||||
ApplyRatingMod(CR_VERSATILITY_HEALING_DONE, int32(val), apply);
|
||||
break;
|
||||
case ITEM_MOD_MANA_REGENERATION:
|
||||
ApplyManaRegenBonus(int32(val), apply);
|
||||
@@ -8115,10 +8149,10 @@ void Player::_ApplyItemBonuses(Item* item, uint8 slot, bool apply)
|
||||
ApplyHealthRegenBonus(int32(val), apply);
|
||||
break;
|
||||
case ITEM_MOD_SPELL_PENETRATION:
|
||||
ApplySpellPenetrationBonus(val, apply);
|
||||
ApplySpellPenetrationBonus(int32(val), apply);
|
||||
break;
|
||||
case ITEM_MOD_MASTERY_RATING:
|
||||
ApplyRatingMod(CR_MASTERY, int32(val * combatRatingMultiplier), apply);
|
||||
ApplyRatingMod(CR_MASTERY, int32(val), apply);
|
||||
break;
|
||||
case ITEM_MOD_EXTRA_ARMOR:
|
||||
HandleStatFlatModifier(UNIT_MOD_ARMOR, TOTAL_VALUE, float(val), apply);
|
||||
@@ -8151,16 +8185,16 @@ void Player::_ApplyItemBonuses(Item* item, uint8 slot, bool apply)
|
||||
ApplyRatingMod(CR_CORRUPTION_RESISTANCE, int32(val), apply);
|
||||
break;
|
||||
case ITEM_MOD_CR_SPEED:
|
||||
ApplyRatingMod(CR_SPEED, int32(val * combatRatingMultiplier), apply);
|
||||
ApplyRatingMod(CR_SPEED, int32(val), apply);
|
||||
break;
|
||||
case ITEM_MOD_CR_LIFESTEAL:
|
||||
ApplyRatingMod(CR_LIFESTEAL, int32(val * combatRatingMultiplier), apply);
|
||||
ApplyRatingMod(CR_LIFESTEAL, int32(val), apply);
|
||||
break;
|
||||
case ITEM_MOD_CR_AVOIDANCE:
|
||||
ApplyRatingMod(CR_AVOIDANCE, int32(val * combatRatingMultiplier), apply);
|
||||
ApplyRatingMod(CR_AVOIDANCE, int32(val), apply);
|
||||
break;
|
||||
case ITEM_MOD_CR_STURDINESS:
|
||||
ApplyRatingMod(CR_STURDINESS, int32(val * combatRatingMultiplier), apply);
|
||||
ApplyRatingMod(CR_STURDINESS, int32(val), apply);
|
||||
break;
|
||||
case ITEM_MOD_AGI_STR_INT:
|
||||
HandleStatFlatModifier(UNIT_MOD_STAT_AGILITY, BASE_VALUE, float(val), apply);
|
||||
|
||||
Reference in New Issue
Block a user