diff options
-rw-r--r-- | src/game/DBCStructure.h | 55 | ||||
-rw-r--r-- | src/game/ItemPrototype.h | 44 | ||||
-rw-r--r-- | src/game/Player.cpp | 75 |
3 files changed, 105 insertions, 69 deletions
diff --git a/src/game/DBCStructure.h b/src/game/DBCStructure.h index 3798785ca03..d5078e8b408 100644 --- a/src/game/DBCStructure.h +++ b/src/game/DBCStructure.h @@ -1143,7 +1143,7 @@ struct RandomPropertiesPointsEntry struct ScalingStatDistributionEntry { uint32 Id; - uint32 StatMod[10]; + int32 StatMod[10]; uint32 Modifier[10]; uint32 MaxLevel; }; @@ -1152,7 +1152,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{ diff --git a/src/game/ItemPrototype.h b/src/game/ItemPrototype.h index f87e52b2e22..e7a37dc8e14 100644 --- a/src/game/ItemPrototype.h +++ b/src/game/ItemPrototype.h @@ -600,46 +600,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 @@ -652,12 +612,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; diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 2dffafc095a..c29c9abe065 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -6483,30 +6483,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; } @@ -6661,8 +6656,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); @@ -6699,23 +6701,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) + { + 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 ? proto->Damage[0].DamageMin : BASE_MINDAMAGE; + 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); } @@ -9844,6 +9865,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; |