mirror of
https://github.com/mangosfour/server.git
synced 2025-12-14 07:37:01 +00:00
[7819] Correct use item ScalingStatValues data (ScalingStatValues.dbc):
- ScalingStatDistribution stats multiplier - Armor bonus from ssv - Damage from ssv - Feral AP from ssv - Feral AP from ssv dps bonus Use item->StatsCount in apply mods Not allow equip item if level > ScalingStatDistribution->maxlevel field TODO find more info about ScalingStatValuesEntry->spellBonus Signed-off-by: DiSlord <dislord@nomail.com>
This commit is contained in:
parent
fd71c2bd6f
commit
bfe2e187a6
4 changed files with 106 additions and 70 deletions
|
|
@ -1136,7 +1136,7 @@ struct RandomPropertiesPointsEntry
|
|||
struct ScalingStatDistributionEntry
|
||||
{
|
||||
uint32 Id;
|
||||
uint32 StatMod[10];
|
||||
int32 StatMod[10];
|
||||
uint32 Modifier[10];
|
||||
uint32 MaxLevel;
|
||||
};
|
||||
|
|
@ -1145,7 +1145,58 @@ struct ScalingStatValuesEntry
|
|||
{
|
||||
uint32 Id;
|
||||
uint32 Level;
|
||||
uint32 Multiplier[17];
|
||||
uint32 ssdMultiplier[5]; // Multiplier for ScalingStatDistribution
|
||||
uint32 armorMod[4]; // Armor for level
|
||||
uint32 dpsMod[6]; // DPS mod for level
|
||||
uint32 spellBonus; // not sure.. TODO: need more info about
|
||||
uint32 feralBonus; // Feral AP bonus
|
||||
|
||||
uint32 getssdMultiplier(uint32 mask) const
|
||||
{
|
||||
if (mask&0x001F)
|
||||
{
|
||||
if(mask & 0x00000001) return ssdMultiplier[0];
|
||||
if(mask & 0x00000002) return ssdMultiplier[1];
|
||||
if(mask & 0x00000004) return ssdMultiplier[2];
|
||||
if(mask & 0x00000008) return ssdMultiplier[3];
|
||||
if(mask & 0x00000010) return ssdMultiplier[4];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
uint32 getArmorMod(uint32 mask) const
|
||||
{
|
||||
if (mask&0x01E0)
|
||||
{
|
||||
if(mask & 0x00000020) return armorMod[0];
|
||||
if(mask & 0x00000040) return armorMod[1];
|
||||
if(mask & 0x00000080) return armorMod[2];
|
||||
if(mask & 0x00000100) return armorMod[3];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
uint32 getDPSMod(uint32 mask) const
|
||||
{
|
||||
if (mask&0x7E00)
|
||||
{
|
||||
if(mask & 0x00000200) return dpsMod[0];
|
||||
if(mask & 0x00000400) return dpsMod[1];
|
||||
if(mask & 0x00000800) return dpsMod[2];
|
||||
if(mask & 0x00001000) return dpsMod[3];
|
||||
if(mask & 0x00002000) return dpsMod[4];
|
||||
if(mask & 0x00004000) return dpsMod[5];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
uint32 getSpellBonus(uint32 mask) const
|
||||
{
|
||||
if (mask & 0x00008000) return spellBonus;
|
||||
return 0;
|
||||
}
|
||||
uint32 getFeralBonus(uint32 mask) const
|
||||
{
|
||||
if (mask & 0x00010000) return feralBonus;
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
//struct SkillLineCategoryEntry{
|
||||
|
|
|
|||
|
|
@ -593,46 +593,6 @@ struct ItemPrototype
|
|||
return false;
|
||||
}
|
||||
|
||||
uint32 GetScalingStatValuesColumn() const
|
||||
{
|
||||
if(ScalingStatValue & 0x00000001) // stat mod
|
||||
return 0;
|
||||
if(ScalingStatValue & 0x00000002) // stat mod
|
||||
return 1;
|
||||
if(ScalingStatValue & 0x00000004) // stat mod
|
||||
return 2;
|
||||
if(ScalingStatValue & 0x00000008) // stat mod
|
||||
return 3;
|
||||
if(ScalingStatValue & 0x00000010) // stat mod
|
||||
return 4;
|
||||
if(ScalingStatValue & 0x00000020) // armor mod
|
||||
return 5;
|
||||
if(ScalingStatValue & 0x00000040) // armor mod
|
||||
return 6;
|
||||
if(ScalingStatValue & 0x00000080) // armor mod
|
||||
return 7;
|
||||
if(ScalingStatValue & 0x00000100) // armor mod
|
||||
return 8;
|
||||
if(ScalingStatValue & 0x00000200) // damage mod
|
||||
return 9;
|
||||
if(ScalingStatValue & 0x00000400) // damage mod
|
||||
return 10;
|
||||
if(ScalingStatValue & 0x00000800) // damage mod
|
||||
return 11;
|
||||
if(ScalingStatValue & 0x00001000) // damage mod
|
||||
return 12;
|
||||
if(ScalingStatValue & 0x00002000) // damage mod
|
||||
return 13;
|
||||
if(ScalingStatValue & 0x00004000) // damage mod
|
||||
return 14;
|
||||
if(ScalingStatValue & 0x00008000) // spell power
|
||||
return 15;
|
||||
if(ScalingStatValue & 0x00020000) // feral AP
|
||||
return 16;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32 GetMaxStackSize() const { return Stackable > 0 ? uint32(Stackable) : uint32(0x7FFFFFFF-1); }
|
||||
|
||||
float getDPS() const
|
||||
|
|
@ -645,12 +605,12 @@ struct ItemPrototype
|
|||
return temp*500/Delay;
|
||||
}
|
||||
|
||||
int32 getFeralBonus() const
|
||||
int32 getFeralBonus(int32 extraDPS = 0) const
|
||||
{
|
||||
// 0x02A5F3 - is mask for Melee weapon from ItemSubClassMask.dbc
|
||||
if (Class == ITEM_CLASS_WEAPON && (1<<SubClass)&0x02A5F3)
|
||||
{
|
||||
int32 bonus = int32(getDPS()*14.0f) - 767;
|
||||
int32 bonus = int32((extraDPS + getDPS())*14.0f) - 767;
|
||||
if (bonus < 0)
|
||||
return 0;
|
||||
return bonus;
|
||||
|
|
|
|||
|
|
@ -6338,30 +6338,25 @@ void Player::_ApplyItemBonuses(ItemPrototype const *proto, uint8 slot, bool appl
|
|||
if(slot >= INVENTORY_SLOT_BAG_END || !proto)
|
||||
return;
|
||||
|
||||
ScalingStatDistributionEntry const *ssd = proto->ScalingStatDistribution ? sScalingStatDistributionStore.LookupEntry(proto->ScalingStatDistribution) : 0;
|
||||
ScalingStatValuesEntry const *ssv = proto->ScalingStatValue ? sScalingStatValuesStore.LookupEntry(getLevel()) : 0;
|
||||
|
||||
for (int i = 0; i < MAX_ITEM_PROTO_STATS; ++i)
|
||||
{
|
||||
uint32 statType = 0;
|
||||
int32 val = 0;
|
||||
|
||||
if(proto->ScalingStatDistribution)
|
||||
int32 val = 0;
|
||||
// If set ScalingStatDistribution need get stats and values from it
|
||||
if (ssd && ssv)
|
||||
{
|
||||
if(ScalingStatDistributionEntry const *ssd = sScalingStatDistributionStore.LookupEntry(proto->ScalingStatDistribution))
|
||||
{
|
||||
statType = ssd->StatMod[i];
|
||||
|
||||
if(uint32 modifier = ssd->Modifier[i])
|
||||
{
|
||||
uint32 level = ((getLevel() > ssd->MaxLevel) ? ssd->MaxLevel : getLevel());
|
||||
if(ScalingStatValuesEntry const *ssv = sScalingStatValuesStore.LookupEntry(level))
|
||||
{
|
||||
uint32 multiplier = ssv->Multiplier[proto->GetScalingStatValuesColumn()];
|
||||
val = (multiplier * modifier) / 10000;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ssd->StatMod[i] < 0)
|
||||
continue;
|
||||
statType = ssd->StatMod[i];
|
||||
val = (ssv->getssdMultiplier(proto->ScalingStatValue) * ssd->Modifier[i]) / 10000;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (proto->StatsCount >= i)
|
||||
continue;
|
||||
statType = proto->ItemStat[i].ItemStatType;
|
||||
val = proto->ItemStat[i].ItemStatValue;
|
||||
}
|
||||
|
|
@ -6516,8 +6511,15 @@ void Player::_ApplyItemBonuses(ItemPrototype const *proto, uint8 slot, bool appl
|
|||
}
|
||||
}
|
||||
|
||||
if (proto->Armor)
|
||||
HandleStatModifier(UNIT_MOD_ARMOR, BASE_VALUE, float(proto->Armor), apply);
|
||||
// If set ScalingStatValue armor get it or use item armor
|
||||
uint32 armor = proto->Armor;
|
||||
if (ssv)
|
||||
{
|
||||
if (uint32 ssvarmor = ssv->getArmorMod(proto->ScalingStatValue))
|
||||
armor = ssvarmor;
|
||||
}
|
||||
if (armor)
|
||||
HandleStatModifier(UNIT_MOD_ARMOR, BASE_VALUE, float(armor), apply);
|
||||
|
||||
if (proto->Block)
|
||||
HandleBaseModValue(SHIELD_BLOCK_VALUE, FLAT_MOD, float(proto->Block), apply);
|
||||
|
|
@ -6554,23 +6556,42 @@ void Player::_ApplyItemBonuses(ItemPrototype const *proto, uint8 slot, bool appl
|
|||
attType = OFF_ATTACK;
|
||||
}
|
||||
|
||||
if (proto->Damage[0].DamageMin > 0 )
|
||||
float minDamage = proto->Damage[0].DamageMin;
|
||||
float maxDamage = proto->Damage[0].DamageMax;
|
||||
int32 extraDPS = 0;
|
||||
// If set dpsMod in ScalingStatValue use it for min (70% from avernge), max (130% from averange) damage
|
||||
if (ssv)
|
||||
{
|
||||
damage = apply ? proto->Damage[0].DamageMin : BASE_MINDAMAGE;
|
||||
if (extraDPS = ssv->getDPSMod(proto->ScalingStatValue))
|
||||
{
|
||||
float averange = extraDPS * proto->Delay / 1000.0f;
|
||||
minDamage = 0.7f * averange;
|
||||
maxDamage = 1.3f * averange;
|
||||
}
|
||||
}
|
||||
if (minDamage > 0 )
|
||||
{
|
||||
damage = apply ? minDamage : BASE_MINDAMAGE;
|
||||
SetBaseWeaponDamage(attType, MINDAMAGE, damage);
|
||||
//sLog.outError("applying mindam: assigning %f to weapon mindamage, now is: %f", damage, GetWeaponDamageRange(attType, MINDAMAGE));
|
||||
}
|
||||
|
||||
if (proto->Damage[0].DamageMax > 0 )
|
||||
if (maxDamage > 0 )
|
||||
{
|
||||
damage = apply ? proto->Damage[0].DamageMax : BASE_MAXDAMAGE;
|
||||
damage = apply ? maxDamage : BASE_MAXDAMAGE;
|
||||
SetBaseWeaponDamage(attType, MAXDAMAGE, damage);
|
||||
}
|
||||
|
||||
// Druids get feral AP bonus from weapon dps
|
||||
// Apply feral bonus from ScalingStatValue if set
|
||||
if (ssv)
|
||||
{
|
||||
if (int32 feral_bonus = ssv->getFeralBonus(proto->ScalingStatValue))
|
||||
ApplyFeralAPBonus(feral_bonus, apply);
|
||||
}
|
||||
// Druids get feral AP bonus from weapon dps (lso use DPS from ScalingStatValue)
|
||||
if(getClass() == CLASS_DRUID)
|
||||
{
|
||||
int32 feral_bonus = proto->getFeralBonus();
|
||||
int32 feral_bonus = proto->getFeralBonus(extraDPS);
|
||||
if (feral_bonus > 0)
|
||||
ApplyFeralAPBonus(feral_bonus, apply);
|
||||
}
|
||||
|
|
@ -9566,6 +9587,10 @@ uint8 Player::CanEquipItem( uint8 slot, uint16 &dest, Item *pItem, bool swap, bo
|
|||
return EQUIP_ERR_CANT_DO_RIGHT_NOW;
|
||||
}
|
||||
|
||||
ScalingStatDistributionEntry const *ssd = pProto->ScalingStatDistribution ? sScalingStatDistributionStore.LookupEntry(pProto->ScalingStatDistribution) : 0;
|
||||
if (ssd && ssd->MaxLevel < getLevel())
|
||||
return EQUIP_ERR_ITEM_CANT_BE_EQUIPPED;
|
||||
|
||||
uint8 eslot = FindEquipSlot( pProto, slot, swap );
|
||||
if( eslot == NULL_SLOT )
|
||||
return EQUIP_ERR_ITEM_CANT_BE_EQUIPPED;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#ifndef __REVISION_NR_H__
|
||||
#define __REVISION_NR_H__
|
||||
#define REVISION_NR "7818"
|
||||
#define REVISION_NR "7819"
|
||||
#endif // __REVISION_NR_H__
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue