mirror of
https://github.com/mangosfour/server.git
synced 2025-12-15 01:37:00 +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
|
struct ScalingStatDistributionEntry
|
||||||
{
|
{
|
||||||
uint32 Id;
|
uint32 Id;
|
||||||
uint32 StatMod[10];
|
int32 StatMod[10];
|
||||||
uint32 Modifier[10];
|
uint32 Modifier[10];
|
||||||
uint32 MaxLevel;
|
uint32 MaxLevel;
|
||||||
};
|
};
|
||||||
|
|
@ -1145,7 +1145,58 @@ struct ScalingStatValuesEntry
|
||||||
{
|
{
|
||||||
uint32 Id;
|
uint32 Id;
|
||||||
uint32 Level;
|
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{
|
//struct SkillLineCategoryEntry{
|
||||||
|
|
|
||||||
|
|
@ -593,46 +593,6 @@ struct ItemPrototype
|
||||||
return false;
|
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); }
|
uint32 GetMaxStackSize() const { return Stackable > 0 ? uint32(Stackable) : uint32(0x7FFFFFFF-1); }
|
||||||
|
|
||||||
float getDPS() const
|
float getDPS() const
|
||||||
|
|
@ -645,12 +605,12 @@ struct ItemPrototype
|
||||||
return temp*500/Delay;
|
return temp*500/Delay;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32 getFeralBonus() const
|
int32 getFeralBonus(int32 extraDPS = 0) const
|
||||||
{
|
{
|
||||||
// 0x02A5F3 - is mask for Melee weapon from ItemSubClassMask.dbc
|
// 0x02A5F3 - is mask for Melee weapon from ItemSubClassMask.dbc
|
||||||
if (Class == ITEM_CLASS_WEAPON && (1<<SubClass)&0x02A5F3)
|
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)
|
if (bonus < 0)
|
||||||
return 0;
|
return 0;
|
||||||
return bonus;
|
return bonus;
|
||||||
|
|
|
||||||
|
|
@ -6338,30 +6338,25 @@ void Player::_ApplyItemBonuses(ItemPrototype const *proto, uint8 slot, bool appl
|
||||||
if(slot >= INVENTORY_SLOT_BAG_END || !proto)
|
if(slot >= INVENTORY_SLOT_BAG_END || !proto)
|
||||||
return;
|
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)
|
for (int i = 0; i < MAX_ITEM_PROTO_STATS; ++i)
|
||||||
{
|
{
|
||||||
uint32 statType = 0;
|
uint32 statType = 0;
|
||||||
int32 val = 0;
|
int32 val = 0;
|
||||||
|
// If set ScalingStatDistribution need get stats and values from it
|
||||||
if(proto->ScalingStatDistribution)
|
if (ssd && ssv)
|
||||||
{
|
{
|
||||||
if(ScalingStatDistributionEntry const *ssd = sScalingStatDistributionStore.LookupEntry(proto->ScalingStatDistribution))
|
if (ssd->StatMod[i] < 0)
|
||||||
{
|
continue;
|
||||||
statType = ssd->StatMod[i];
|
statType = ssd->StatMod[i];
|
||||||
|
val = (ssv->getssdMultiplier(proto->ScalingStatValue) * ssd->Modifier[i]) / 10000;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if (proto->StatsCount >= i)
|
||||||
|
continue;
|
||||||
statType = proto->ItemStat[i].ItemStatType;
|
statType = proto->ItemStat[i].ItemStatType;
|
||||||
val = proto->ItemStat[i].ItemStatValue;
|
val = proto->ItemStat[i].ItemStatValue;
|
||||||
}
|
}
|
||||||
|
|
@ -6516,8 +6511,15 @@ void Player::_ApplyItemBonuses(ItemPrototype const *proto, uint8 slot, bool appl
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (proto->Armor)
|
// If set ScalingStatValue armor get it or use item armor
|
||||||
HandleStatModifier(UNIT_MOD_ARMOR, BASE_VALUE, float(proto->Armor), apply);
|
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)
|
if (proto->Block)
|
||||||
HandleBaseModValue(SHIELD_BLOCK_VALUE, FLAT_MOD, float(proto->Block), apply);
|
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;
|
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);
|
SetBaseWeaponDamage(attType, MINDAMAGE, damage);
|
||||||
//sLog.outError("applying mindam: assigning %f to weapon mindamage, now is: %f", damage, GetWeaponDamageRange(attType, MINDAMAGE));
|
//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);
|
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)
|
if(getClass() == CLASS_DRUID)
|
||||||
{
|
{
|
||||||
int32 feral_bonus = proto->getFeralBonus();
|
int32 feral_bonus = proto->getFeralBonus(extraDPS);
|
||||||
if (feral_bonus > 0)
|
if (feral_bonus > 0)
|
||||||
ApplyFeralAPBonus(feral_bonus, apply);
|
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;
|
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 );
|
uint8 eslot = FindEquipSlot( pProto, slot, swap );
|
||||||
if( eslot == NULL_SLOT )
|
if( eslot == NULL_SLOT )
|
||||||
return EQUIP_ERR_ITEM_CANT_BE_EQUIPPED;
|
return EQUIP_ERR_ITEM_CANT_BE_EQUIPPED;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
#ifndef __REVISION_NR_H__
|
#ifndef __REVISION_NR_H__
|
||||||
#define __REVISION_NR_H__
|
#define __REVISION_NR_H__
|
||||||
#define REVISION_NR "7818"
|
#define REVISION_NR "7819"
|
||||||
#endif // __REVISION_NR_H__
|
#endif // __REVISION_NR_H__
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue