bool Player::UpdateStats(Stats stat) { if (stat > STAT_SPIRIT) return false; // value = ((base_value * base_pct) + total_value) * total_pct float value = GetTotalStatValue(stat); SetStat(stat, int32(value)); if (stat == STAT_STAMINA || stat == STAT_INTELLECT) { Pet* pet = GetPet(); if (pet) pet->UpdateStats(stat); } switch (stat) { case STAT_STRENGTH: break; case STAT_AGILITY: UpdateArmor(); UpdateAllCritPercentages(); UpdateDodgePercentage(); break; case STAT_STAMINA: UpdateMaxHealth(); break; case STAT_INTELLECT: UpdateMaxPower(POWER_MANA); UpdateAllSpellCritChances(); UpdateArmor(); // SPELL_AURA_MOD_RESISTANCE_OF_INTELLECT_PERCENT, only armor currently break; case STAT_SPIRIT: break; default: break; } // Need update (exist AP from stat auras) UpdateAttackPowerAndDamage(); UpdateAttackPowerAndDamage(true); UpdateSpellDamageAndHealingBonus(); UpdateManaRegen(); // Update ratings in exist SPELL_AURA_MOD_RATING_FROM_STAT and only depends from stat uint32 mask = 0; AuraList const& modRatingFromStat = GetAurasByType(SPELL_AURA_MOD_RATING_FROM_STAT); for (AuraList::const_iterator i = modRatingFromStat.begin(); i != modRatingFromStat.end(); ++i) if (Stats((*i)->GetMiscBValue()) == stat) mask |= (*i)->GetMiscValue(); if (mask) { for (uint32 rating = 0; rating < MAX_COMBAT_RATING; ++rating) if (mask & (1 << rating)) ApplyRatingMod(CombatRating(rating), 0, true); } return true; }
float Creature::GetAttackDistance(Unit *pl) const { int32 playerlevel = pl->getLevel(); int32 creaturelevel = getLevel(); int32 leveldif = playerlevel - creaturelevel; // "The maximum Aggro Radius has a cap of 25 levels under. Example: A level 30 char has the same Aggro Radius of a level 5 char on a level 60 mob." if ( leveldif < - 25) leveldif = -25; // "The aggro radius of a mob having the same level as the player is roughly 20 yards" float RetDistance = 20; // "Aggro Radius varries with level difference at a rate of roughly 1 yard/level" // radius grow if playlevel < creaturelevel RetDistance -= (float)leveldif; if(getLevel() <= 55) { // decrease aggro range auras AuraList const& modDectectRangeList = GetAurasByType(SPELL_AURA_MOD_DETECT_RANGE); for(AuraList::const_iterator itr = modDectectRangeList.begin(); itr != modDectectRangeList.end(); ++itr) RetDistance += (*itr)->GetModifier()->m_amount; } // "Minimum Aggro Radius for a mob seems to be combat range (5 yards)" if(RetDistance < 5 && sWorld.getRate(RATE_CREATURE_AGGRO) != 0) RetDistance = 5; return (RetDistance*sWorld.getRate(RATE_CREATURE_AGGRO)); }
void Player::UpdateArmor() { float value = 0.0f; UnitMods unitMod = UNIT_MOD_ARMOR; value = GetModifierValue(unitMod, BASE_VALUE); // base armor (from items) value *= GetModifierValue(unitMod, BASE_PCT); // armor percent from items value += GetStat(STAT_AGILITY) * 2.0f; // armor bonus from stats value += GetModifierValue(unitMod, TOTAL_VALUE); // add dynamic flat mods AuraList const& mResbyIntellect = GetAurasByType(SPELL_AURA_MOD_RESISTANCE_OF_STAT_PERCENT); for (AuraList::const_iterator i = mResbyIntellect.begin(); i != mResbyIntellect.end(); ++i) { Modifier* mod = (*i)->GetModifier(); if (mod->m_miscvalue & SPELL_SCHOOL_MASK_NORMAL) value += int32(GetStat(Stats((*i)->GetMiscBValue())) * mod->m_amount / 100.0f); } value *= GetModifierValue(unitMod, TOTAL_PCT); SetArmor(int32(value)); Pet* pet = GetPet(); if (pet) pet->UpdateArmor(); UpdateAttackPowerAndDamage(); // armor dependent auras update for SPELL_AURA_MOD_ATTACK_POWER_OF_ARMOR }
void Player::UpdateExpertise(WeaponAttackType attack) { if (attack == RANGED_ATTACK) return; int32 expertise = int32(GetRatingBonusValue(CR_EXPERTISE)); Item* weapon = GetWeaponForAttack(attack); AuraList const& expAuras = GetAurasByType(SPELL_AURA_MOD_EXPERTISE); for (AuraList::const_iterator itr = expAuras.begin(); itr != expAuras.end(); ++itr) { // item neutral spell if((*itr)->GetSpellProto()->GetEquippedItemClass() == -1) expertise += (*itr)->GetModifier()->m_amount; // item dependent spell else if (weapon && weapon->IsFitToSpellRequirements((*itr)->GetSpellProto())) expertise += (*itr)->GetModifier()->m_amount; } if (expertise < 0) expertise = 0; switch (attack) { case BASE_ATTACK: SetUInt32Value(PLAYER_EXPERTISE, expertise); break; case OFF_ATTACK: SetUInt32Value(PLAYER_OFFHAND_EXPERTISE, expertise); break; default: break; } }
void Player::UpdateArmorPenetration(int32 amount) { AuraList const& expAuras = GetAurasByType(SPELL_AURA_MOD_ARMOR_PENETRATION_PCT); for(AuraList::const_iterator itr = expAuras.begin(); itr != expAuras.end(); ++itr) { // item neutral spell if((*itr)->GetSpellProto()->EquippedItemClass == -1) { amount *= ((*itr)->GetAmount() + 100.0f) / 100.0f; continue; } // item dependent spell - check curent weapons for(int i = 0; i < MAX_ATTACK; ++i) { Item *weapon = GetWeaponForAttack(WeaponAttackType(i)); if(weapon && weapon->IsFitToSpellRequirements((*itr)->GetSpellProto())) { amount *= ((*itr)->GetAmount() + 100.0f) / 100.0f; break; } } } // Store Rating Value SetUInt32Value(PLAYER_FIELD_COMBAT_RATING_1 + CR_ARMOR_PENETRATION, amount); }
void Player::UpdateManaRegen() { float Intellect = GetStat(STAT_INTELLECT); // Mana regen from spirit and intellect float power_regen = sqrt(Intellect) * OCTRegenMPPerSpirit(); // Apply PCT bonus from SPELL_AURA_MOD_POWER_REGEN_PERCENT aura on spirit base regen power_regen *= GetTotalAuraMultiplierByMiscValue(SPELL_AURA_MOD_POWER_REGEN_PERCENT, POWER_MANA); // Mana regen from SPELL_AURA_MOD_POWER_REGEN aura float power_regen_mp5 = (GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_POWER_REGEN, POWER_MANA) + m_baseManaRegen) / 5.0f; // Get bonus from SPELL_AURA_MOD_MANA_REGEN_FROM_STAT aura AuraList const& regenAura = GetAurasByType(SPELL_AURA_MOD_MANA_REGEN_FROM_STAT); for(AuraList::const_iterator i = regenAura.begin();i != regenAura.end(); ++i) { Modifier* mod = (*i)->GetModifier(); power_regen_mp5 += GetStat(Stats(mod->m_miscvalue)) * mod->m_amount / 500.0f; } // Set regen rate in cast state apply only on spirit based regen int32 modManaRegenInterrupt = GetTotalAuraModifier(SPELL_AURA_MOD_MANA_REGEN_INTERRUPT); if (modManaRegenInterrupt > 100) modManaRegenInterrupt = 100; SetStatFloatValue(UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER, power_regen_mp5 + power_regen * modManaRegenInterrupt / 100.0f); SetStatFloatValue(UNIT_FIELD_POWER_REGEN_FLAT_MODIFIER, power_regen_mp5 + power_regen); }
void Player::UpdateArmorPenetration() { m_armorPenetrationPct = GetRatingBonusValue(CR_ARMOR_PENETRATION); AuraList const& armorAuras = GetAurasByType(SPELL_AURA_MOD_TARGET_ARMOR_PCT); for(AuraList::const_iterator itr = armorAuras.begin(); itr != armorAuras.end(); ++itr) { // affects all weapons if((*itr)->GetSpellProto()->EquippedItemClass == -1) { m_armorPenetrationPct += (*itr)->GetModifier()->m_amount; continue; } // dependent on weapon class for(uint8 i = 0; i < MAX_ATTACK; ++i) { Item *weapon = GetWeaponForAttack(WeaponAttackType(i)); if(weapon && weapon->IsFitToSpellRequirements((*itr)->GetSpellProto())) { m_armorPenetrationPct += (*itr)->GetModifier()->m_amount; break; } } } }
void Player::UpdateArmor() { float value = 0.0f; UnitMods unitMod = UNIT_MOD_ARMOR; value = GetModifierValue(unitMod, BASE_VALUE); // base armor (from items) value *= GetModifierValue(unitMod, BASE_PCT); // armor percent from items value += GetStat(STAT_AGILITY) * 2.0f; // armor bonus from stats value += GetModifierValue(unitMod, TOTAL_VALUE); //add dynamic flat mods AuraList const& mResbyIntellect = GetAurasByType(SPELL_AURA_MOD_RESISTANCE_OF_STAT_PERCENT); for (AuraList::const_iterator i = mResbyIntellect.begin();i != mResbyIntellect.end(); ++i) { Modifier* mod = (*i)->GetModifier(); if (mod->m_miscvalue & SPELL_SCHOOL_MASK_NORMAL) value += int32(GetStat(Stats((*i)->GetMiscBValue())) * (*i)->GetModifierValue() / 100.0f); } value *= GetModifierValue(unitMod, TOTAL_PCT); if (HasAura(5229,0)) value -= HasAura(9634,0) ? 0.16*value : 0.27*value; SetArmor(int32(value)); Pet *pet = GetPet(); if (pet) pet->UpdateArmor(); }
void Player::UpdateExpertise(WeaponAttackType attack) { if(attack==RANGED_ATTACK) return; int32 expertise = int32(GetRatingBonusValue(CR_EXPERTISE)); Item *weapon = GetWeaponForAttack(attack); AuraList const& expAuras = GetAurasByType(SPELL_AURA_MOD_EXPERTISE); for(AuraList::const_iterator itr = expAuras.begin(); itr != expAuras.end(); ++itr) { // item neutral spell if((*itr)->GetSpellProto()->EquippedItemClass == -1) expertise += (*itr)->GetModifier()->m_amount; // item dependent spell else if(weapon && weapon->IsFitToSpellRequirements((*itr)->GetSpellProto())) expertise += (*itr)->GetModifier()->m_amount; } if(expertise < 0) expertise = 0; switch(attack) { case BASE_ATTACK: SetUInt32Value(PLAYER_EXPERTISE, expertise); break; case OFF_ATTACK: SetUInt32Value(PLAYER_OFFHAND_EXPERTISE, expertise); break; default: break; } if (IsInWorld()) CallForAllControlledUnits(ApplyScalingBonusWithHelper(SCALING_TARGET_EXPERTIZE, 0, false),CONTROLLED_PET|CONTROLLED_GUARDIANS); }
void Player::UpdateManaRegen() { float Intellect = GetStat(STAT_INTELLECT); // Mana regen from spirit float power_regen = OCTRegenMPPerSpirit(); // Apply PCT bonus from SPELL_AURA_MOD_POWER_REGEN_PERCENT aura on spirit base regen power_regen *= GetTotalAuraMultiplierByMiscValue(SPELL_AURA_MOD_POWER_REGEN_PERCENT, POWER_MANA); // Mana regen from SPELL_AURA_MOD_POWER_REGEN aura float power_regen_mp5 = GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_POWER_REGEN, POWER_MANA) / 5.0f; // Get bonus from SPELL_AURA_MOD_MANA_REGEN_FROM_STAT aura AuraList const& regenAura = GetAurasByType(SPELL_AURA_MOD_MANA_REGEN_FROM_STAT); for(AuraList::const_iterator i = regenAura.begin();i != regenAura.end(); ++i) { Modifier* mod = (*i)->GetModifier(); power_regen_mp5 += GetStat(Stats(mod->m_miscvalue)) * (*i)->GetModifierValue() / 500.0f; } // Bonus from some dummy auras AuraList const& mDummyAuras = GetAurasByType(SPELL_AURA_PERIODIC_DUMMY); for(AuraList::const_iterator i = mDummyAuras.begin();i != mDummyAuras.end(); ++i) if((*i)->GetId() == 34074) // Aspect of the Viper { power_regen_mp5 += (*i)->GetModifier()->m_amount * Intellect / 500.0f; // Add regen bonus from level in this dummy power_regen_mp5 += getLevel() * 35 / 100; } // Set regen rate in cast state apply only on spirit based regen int32 modManaRegenInterrupt = GetTotalAuraModifier(SPELL_AURA_MOD_MANA_REGEN_INTERRUPT); if (modManaRegenInterrupt > 100) modManaRegenInterrupt = 100; m_modManaRegen[1] = power_regen_mp5 + power_regen * modManaRegenInterrupt / 100.0f ; // recent cast m_modManaRegen[0] = power_regen_mp5 + power_regen; }
void Player::UpdateManaRegen() { float Intellect = GetStat(STAT_INTELLECT); // Mana regen from spirit and intellect float power_regen = sqrt(Intellect) * OCTRegenMPPerSpirit(); // Apply PCT bonus from SPELL_AURA_MOD_POWER_REGEN_PERCENT aura on spirit base regen power_regen *= GetTotalAuraMultiplierByMiscValue(SPELL_AURA_MOD_POWER_REGEN_PERCENT, POWER_MANA); // Mana regen from SPELL_AURA_MOD_POWER_REGEN aura float power_regen_mp5 = GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_POWER_REGEN, POWER_MANA) / 5.0f; // Get bonus from SPELL_AURA_MOD_MANA_REGEN_FROM_STAT aura AuraList const& regenAura = GetAurasByType(SPELL_AURA_MOD_MANA_REGEN_FROM_STAT); for (AuraList::const_iterator i = regenAura.begin();i != regenAura.end(); ++i) { Modifier* mod = (*i)->GetModifier(); power_regen_mp5 += GetStat(Stats(mod->m_miscvalue)) * (*i)->GetModifierValue() / 500.0f; } // Bonus from some dummy auras AuraMap const& mAuras = GetAuras(); for (AuraMap::const_iterator itr = mAuras.begin(); itr != mAuras.end(); ++itr) { // Aspect of the Viper if (itr->second->GetId() == 34074) { power_regen_mp5 += itr->second->GetModifier()->m_amount * Intellect / 500.0f; // Add regen bonus from level in this dummy power_regen_mp5 += getLevel() * 35 / 100; } // Improved Water Shield (Totem of the Thunderhead) if (itr->second->GetId() == 34318) { power_regen_mp5 += 0.4;//itr->second->GetSpellProto()->EffectMiscValue[1]; } } // Set regen rate in cast state apply only on spirit based regen int32 modManaRegenInterrupt = GetTotalAuraModifier(SPELL_AURA_MOD_MANA_REGEN_INTERRUPT); if (modManaRegenInterrupt > 100) modManaRegenInterrupt = 100; SetStatFloatValue(PLAYER_FIELD_MOD_MANA_REGEN_INTERRUPT, power_regen_mp5 + power_regen * modManaRegenInterrupt / 100.0f); SetStatFloatValue(PLAYER_FIELD_MOD_MANA_REGEN, power_regen_mp5 + power_regen); }
void Player::UpdateArmor() { float value; UnitMods unitMod = UNIT_MOD_ARMOR; value = GetModifierValue(unitMod, BASE_VALUE); // base armor (from items) value *= GetModifierValue(unitMod, BASE_PCT); // armor percent from items value += GetStat(STAT_AGILITY) * 2.0f; // armor bonus from stats value += GetModifierValue(unitMod, TOTAL_VALUE); // add dynamic flat mods AuraList const& mResbyIntellect = GetAurasByType(SPELL_AURA_MOD_RESISTANCE_OF_STAT_PERCENT); for (AuraList::const_iterator i = mResbyIntellect.begin(); i != mResbyIntellect.end(); ++i) { Modifier* mod = (*i)->GetModifier(); if (mod->m_miscvalue & SPELL_SCHOOL_MASK_NORMAL) { value += int32(GetStat(STAT_INTELLECT) * mod->m_amount / 100.0f); } } value *= GetModifierValue(unitMod, TOTAL_PCT); SetArmor(int32(value)); }
void Player::UpdateAttackPowerAndDamage(bool ranged ) { float val2 = 0.0f; float level = float(getLevel()); UnitMods unitMod = ranged ? UNIT_MOD_ATTACK_POWER_RANGED : UNIT_MOD_ATTACK_POWER; uint16 index = UNIT_FIELD_ATTACK_POWER; uint16 index_mod = UNIT_FIELD_ATTACK_POWER_MODS; uint16 index_mult = UNIT_FIELD_ATTACK_POWER_MULTIPLIER; if(ranged) { index = UNIT_FIELD_RANGED_ATTACK_POWER; index_mod = UNIT_FIELD_RANGED_ATTACK_POWER_MODS; index_mult = UNIT_FIELD_RANGED_ATTACK_POWER_MULTIPLIER; switch(getClass()) { case CLASS_HUNTER: val2 = level * 2.0f + GetStat(STAT_AGILITY) - 10.0f; break; case CLASS_ROGUE: val2 = level + GetStat(STAT_AGILITY) - 10.0f; break; case CLASS_WARRIOR:val2 = level + GetStat(STAT_AGILITY) - 10.0f; break; case CLASS_DRUID: switch(m_form) { case FORM_CAT: case FORM_BEAR: case FORM_DIREBEAR: val2 = 0.0f; break; default: val2 = GetStat(STAT_AGILITY) - 10.0f; break; } break; default: val2 = GetStat(STAT_AGILITY) - 10.0f; break; } } else { switch(getClass()) { case CLASS_WARRIOR: val2 = level*3.0f + GetStat(STAT_STRENGTH)*2.0f - 20.0f; break; case CLASS_PALADIN: val2 = level*3.0f + GetStat(STAT_STRENGTH)*2.0f - 20.0f; break; case CLASS_DEATH_KNIGHT: val2 = level*3.0f + GetStat(STAT_STRENGTH)*2.0f - 20.0f; break; case CLASS_ROGUE: val2 = level*2.0f + GetStat(STAT_STRENGTH) + GetStat(STAT_AGILITY) - 20.0f; break; case CLASS_HUNTER: val2 = level*2.0f + GetStat(STAT_STRENGTH) + GetStat(STAT_AGILITY) - 20.0f; break; case CLASS_SHAMAN: val2 = level*2.0f + GetStat(STAT_STRENGTH) + GetStat(STAT_AGILITY) - 20.0f; break; case CLASS_DRUID: { //Check if Predatory Strikes is skilled float mLevelMult = 0.0; switch(m_form) { case FORM_CAT: case FORM_BEAR: case FORM_DIREBEAR: case FORM_MOONKIN: { Unit::AuraList const& mDummy = GetAurasByType(SPELL_AURA_DUMMY); for(Unit::AuraList::const_iterator itr = mDummy.begin(); itr != mDummy.end(); ++itr) { // Predatory Strikes (effect 0) if ((*itr)->GetEffIndex() == EFFECT_INDEX_0 && (*itr)->GetSpellProto()->SpellIconID == 1563) { mLevelMult = (*itr)->GetModifier()->m_amount / 100.0f; break; } } break; } default: break; } switch(m_form) { case FORM_CAT: val2 = getLevel()*(mLevelMult+2.0f) + GetStat(STAT_STRENGTH)*2.0f + GetStat(STAT_AGILITY) - 20.0f + m_baseFeralAP; break; case FORM_BEAR: case FORM_DIREBEAR: val2 = getLevel()*(mLevelMult+3.0f) + GetStat(STAT_STRENGTH)*2.0f - 20.0f + m_baseFeralAP; break; case FORM_MOONKIN: val2 = getLevel()*(mLevelMult+1.5f) + GetStat(STAT_STRENGTH)*2.0f - 20.0f + m_baseFeralAP; break; default: val2 = GetStat(STAT_STRENGTH)*2.0f - 20.0f; break; } break; } case CLASS_MAGE: val2 = GetStat(STAT_STRENGTH) - 10.0f; break; case CLASS_PRIEST: val2 = GetStat(STAT_STRENGTH) - 10.0f; break; case CLASS_WARLOCK: val2 = GetStat(STAT_STRENGTH) - 10.0f; break; } } SetModifierValue(unitMod, BASE_VALUE, val2); float base_attPower = GetModifierValue(unitMod, BASE_VALUE) * GetModifierValue(unitMod, BASE_PCT); float attPowerMod = GetModifierValue(unitMod, TOTAL_VALUE); //add dynamic flat mods if( ranged ) { if ((getClassMask() & CLASSMASK_WAND_USERS)==0) { AuraList const& mRAPbyStat = GetAurasByType(SPELL_AURA_MOD_RANGED_ATTACK_POWER_OF_STAT_PERCENT); for(AuraList::const_iterator i = mRAPbyStat.begin();i != mRAPbyStat.end(); ++i) attPowerMod += int32(GetStat(Stats((*i)->GetModifier()->m_miscvalue)) * (*i)->GetModifier()->m_amount / 100.0f); } } else { AuraList const& mAPbyStat = GetAurasByType(SPELL_AURA_MOD_ATTACK_POWER_OF_STAT_PERCENT); for(AuraList::const_iterator i = mAPbyStat.begin();i != mAPbyStat.end(); ++i) attPowerMod += int32(GetStat(Stats((*i)->GetModifier()->m_miscvalue)) * (*i)->GetModifier()->m_amount / 100.0f); AuraList const& mAPbyArmor = GetAurasByType(SPELL_AURA_MOD_ATTACK_POWER_OF_ARMOR); for(AuraList::const_iterator iter = mAPbyArmor.begin(); iter != mAPbyArmor.end(); ++iter) // always: ((*i)->GetModifier()->m_miscvalue == 1 == SPELL_SCHOOL_MASK_NORMAL) attPowerMod += int32(GetArmor() / (*iter)->GetModifier()->m_amount); } float attPowerMultiplier = GetModifierValue(unitMod, TOTAL_PCT) - 1.0f; SetInt32Value(index, (uint32)base_attPower); //UNIT_FIELD_(RANGED)_ATTACK_POWER field SetInt32Value(index_mod, (uint32)attPowerMod); //UNIT_FIELD_(RANGED)_ATTACK_POWER_MODS field SetFloatValue(index_mult, attPowerMultiplier); //UNIT_FIELD_(RANGED)_ATTACK_POWER_MULTIPLIER field //automatically update weapon damage after attack power modification if(ranged) { UpdateDamagePhysical(RANGED_ATTACK); Pet *pet = GetPet(); //update pet's AP if(pet) pet->UpdateAttackPowerAndDamage(); } else { UpdateDamagePhysical(BASE_ATTACK); if(CanDualWield() && haveOffhandWeapon()) //allow update offhand damage only if player knows DualWield Spec and has equipped offhand weapon UpdateDamagePhysical(OFF_ATTACK); } }
void Player::UpdateAttackPowerAndDamage(bool ranged) { ChrClassesEntry const * chrEntry = sChrClassesStore.LookupEntry(getClass()); MANGOS_ASSERT(chrEntry); float val2 = 0.0f; float level = float(getLevel()); UnitMods unitMod = ranged ? UNIT_MOD_ATTACK_POWER_RANGED : UNIT_MOD_ATTACK_POWER; uint16 index = UNIT_FIELD_ATTACK_POWER; uint16 index_mod = UNIT_FIELD_ATTACK_POWER_MOD_POS; uint16 index_mult = UNIT_FIELD_ATTACK_POWER_MULTIPLIER; if (ranged) { index = UNIT_FIELD_RANGED_ATTACK_POWER; index_mod = UNIT_FIELD_RANGED_ATTACK_POWER_MOD_POS; index_mult = UNIT_FIELD_RANGED_ATTACK_POWER_MULTIPLIER; float rapPerAgi = std::max(GetStat(STAT_AGILITY) - 10.0f, 0.0f) * chrEntry->rapPerAgi; switch (getClass()) { case CLASS_HUNTER: val2 = level * 2.0f + rapPerAgi; break; case CLASS_ROGUE: val2 = level + rapPerAgi; break; case CLASS_WARRIOR: val2 = level + rapPerAgi; break; default: break; } } else { float apPerAgi = std::max(GetStat(STAT_AGILITY) - 10.0f, 0.0f) * chrEntry->apPerAgi; float apPerStr = std::max(GetStat(STAT_STRENGTH) - 10.0f, 0.0f) * chrEntry->apPerStr; float levelmod; switch (getClass()) { case CLASS_WARRIOR: case CLASS_PALADIN: case CLASS_DEATH_KNIGHT: case CLASS_DRUID: levelmod = 3.0f; break; default: levelmod = 2.0f; break; } val2 = level * levelmod + apPerAgi + apPerStr; // extracted from client if (getClass() == CLASS_DRUID && GetShapeshiftForm()) { if (SpellShapeshiftFormEntry const * entry = sSpellShapeshiftFormStore.LookupEntry(uint32(GetShapeshiftForm()))) if (entry->flags1 & 0x20) val2 += std::max(GetStat(STAT_AGILITY) - 10.0f, 0.0f) * chrEntry->apPerStr; } } SetModifierValue(unitMod, BASE_VALUE, val2); float base_attPower = GetModifierValue(unitMod, BASE_VALUE) * GetModifierValue(unitMod, BASE_PCT); float attPowerMod = GetModifierValue(unitMod, TOTAL_VALUE); // add dynamic flat mods if (!ranged) { AuraList const& mAPbyArmor = GetAurasByType(SPELL_AURA_MOD_ATTACK_POWER_OF_ARMOR); for (AuraList::const_iterator iter = mAPbyArmor.begin(); iter != mAPbyArmor.end(); ++iter) // always: ((*i)->GetModifier()->m_miscvalue == 1 == SPELL_SCHOOL_MASK_NORMAL) attPowerMod += int32(GetArmor() / (*iter)->GetModifier()->m_amount); } float attPowerMultiplier = GetModifierValue(unitMod, TOTAL_PCT) - 1.0f; SetInt32Value(index, (uint32)base_attPower); // UNIT_FIELD_(RANGED)_ATTACK_POWER field SetInt32Value(index_mod, (uint32)attPowerMod); // UNIT_FIELD_(RANGED)_ATTACK_POWER_MODS field SetFloatValue(index_mult, attPowerMultiplier); // UNIT_FIELD_(RANGED)_ATTACK_POWER_MULTIPLIER field // automatically update weapon damage after attack power modification if (ranged) { UpdateDamagePhysical(RANGED_ATTACK); Pet* pet = GetPet(); // update pet's AP if (pet) pet->UpdateAttackPowerAndDamage(); } else { UpdateDamagePhysical(BASE_ATTACK); if (CanDualWield() && haveOffhandWeapon()) // allow update offhand damage only if player knows DualWield Spec and has equipped offhand weapon UpdateDamagePhysical(OFF_ATTACK); } }
void Player::UpdateAttackPowerAndDamage(bool ranged ) { float val2 = 0.0f; float level = float(getLevel()); UnitMods unitMod = ranged ? UNIT_MOD_ATTACK_POWER_RANGED : UNIT_MOD_ATTACK_POWER; uint16 index = UNIT_FIELD_ATTACK_POWER; uint16 index_mod = UNIT_FIELD_ATTACK_POWER_MODS; uint16 index_mult = UNIT_FIELD_ATTACK_POWER_MULTIPLIER; if(ranged) { index = UNIT_FIELD_RANGED_ATTACK_POWER; index_mod = UNIT_FIELD_RANGED_ATTACK_POWER_MODS; index_mult = UNIT_FIELD_RANGED_ATTACK_POWER_MULTIPLIER; switch(getClass()) { case CLASS_HUNTER: val2 = level * 2.0f + GetStat(STAT_AGILITY) - 10.0f; break; case CLASS_ROGUE: val2 = level + GetStat(STAT_AGILITY) - 10.0f; break; case CLASS_WARRIOR:val2 = level + GetStat(STAT_AGILITY) - 10.0f; break; case CLASS_DRUID: switch(GetShapeshiftForm()) { case FORM_CAT: case FORM_BEAR: case FORM_DIREBEAR: val2 = 0.0f; break; default: val2 = GetStat(STAT_AGILITY) - 10.0f; break; } break; default: val2 = GetStat(STAT_AGILITY) - 10.0f; break; } } else { switch(getClass()) { case CLASS_WARRIOR: val2 = level*3.0f + GetStat(STAT_STRENGTH)*2.0f - 20.0f; break; case CLASS_PALADIN: val2 = level*3.0f + GetStat(STAT_STRENGTH)*2.0f - 20.0f; break; case CLASS_DEATH_KNIGHT: val2 = level*3.0f + GetStat(STAT_STRENGTH)*2.0f - 20.0f; break; case CLASS_ROGUE: val2 = level*2.0f + GetStat(STAT_STRENGTH) + GetStat(STAT_AGILITY) - 20.0f; break; case CLASS_HUNTER: val2 = level*2.0f + GetStat(STAT_STRENGTH) + GetStat(STAT_AGILITY) - 20.0f; break; case CLASS_SHAMAN: val2 = level*2.0f + GetStat(STAT_STRENGTH) + GetStat(STAT_AGILITY) - 20.0f; break; case CLASS_DRUID: { ShapeshiftForm form = GetShapeshiftForm(); //Check if Predatory Strikes is skilled float mLevelBonus = 0.0f; float mBonusWeaponAtt = 0.0f; switch(form) { case FORM_CAT: case FORM_BEAR: case FORM_DIREBEAR: case FORM_MOONKIN: { Unit::AuraList const& mDummy = GetAurasByType(SPELL_AURA_DUMMY); for(Unit::AuraList::const_iterator itr = mDummy.begin(); itr != mDummy.end(); ++itr) { if((*itr)->GetSpellProto()->SpellIconID != 1563) continue; // Predatory Strikes (effect 0) if ((*itr)->GetEffIndex() == EFFECT_INDEX_0 && IsInFeralForm()) mLevelBonus = getLevel() * (*itr)->GetModifier()->m_amount / 100.0f; // Predatory Strikes (effect 1) else if ((*itr)->GetEffIndex() == EFFECT_INDEX_1) mBonusWeaponAtt = (*itr)->GetModifier()->m_amount * m_baseFeralAP / 100.0f; if (mLevelBonus != 0.0f && mBonusWeaponAtt != 0.0f) break; } break; } default: break; } switch(form) { case FORM_CAT: val2 = GetStat(STAT_STRENGTH)*2.0f + GetStat(STAT_AGILITY) - 20.0f + mLevelBonus + m_baseFeralAP + mBonusWeaponAtt; break; case FORM_BEAR: case FORM_DIREBEAR: val2 = GetStat(STAT_STRENGTH)*2.0f - 20.0f + mLevelBonus + m_baseFeralAP + mBonusWeaponAtt; break; case FORM_MOONKIN: val2 = GetStat(STAT_STRENGTH)*2.0f - 20.0f + m_baseFeralAP + mBonusWeaponAtt; break; default: val2 = GetStat(STAT_STRENGTH)*2.0f - 20.0f; break; } break; } case CLASS_MAGE: val2 = GetStat(STAT_STRENGTH) - 10.0f; break; case CLASS_PRIEST: val2 = GetStat(STAT_STRENGTH) - 10.0f; break; case CLASS_WARLOCK: val2 = GetStat(STAT_STRENGTH) - 10.0f; break; } } SetModifierValue(unitMod, BASE_VALUE, val2); float base_attPower = GetModifierValue(unitMod, BASE_VALUE) * GetModifierValue(unitMod, BASE_PCT); float attPowerMod = GetModifierValue(unitMod, TOTAL_VALUE); //add dynamic flat mods if( ranged ) { if ((getClassMask() & CLASSMASK_WAND_USERS)==0) { AuraList const& mRAPbyStat = GetAurasByType(SPELL_AURA_MOD_RANGED_ATTACK_POWER_OF_STAT_PERCENT); for(AuraList::const_iterator i = mRAPbyStat.begin();i != mRAPbyStat.end(); ++i) attPowerMod += int32(GetStat(Stats((*i)->GetModifier()->m_miscvalue)) * (*i)->GetModifier()->m_amount / 100.0f); } } else { AuraList const& mAPbyStat = GetAurasByType(SPELL_AURA_MOD_ATTACK_POWER_OF_STAT_PERCENT); for(AuraList::const_iterator i = mAPbyStat.begin();i != mAPbyStat.end(); ++i) attPowerMod += int32(GetStat(Stats((*i)->GetModifier()->m_miscvalue)) * (*i)->GetModifier()->m_amount / 100.0f); AuraList const& mAPbyArmor = GetAurasByType(SPELL_AURA_MOD_ATTACK_POWER_OF_ARMOR); for(AuraList::const_iterator iter = mAPbyArmor.begin(); iter != mAPbyArmor.end(); ++iter) // always: ((*i)->GetModifier()->m_miscvalue == 1 == SPELL_SCHOOL_MASK_NORMAL) attPowerMod += int32(GetArmor() / (*iter)->GetModifier()->m_amount); } float attPowerMultiplier = GetModifierValue(unitMod, TOTAL_PCT) - 1.0f; SetInt32Value(index, (uint32)base_attPower); //UNIT_FIELD_(RANGED)_ATTACK_POWER field SetInt32Value(index_mod, (uint32)attPowerMod); //UNIT_FIELD_(RANGED)_ATTACK_POWER_MODS field SetFloatValue(index_mult, attPowerMultiplier); //UNIT_FIELD_(RANGED)_ATTACK_POWER_MULTIPLIER field //automatically update weapon damage after attack power modification if(ranged) { UpdateDamagePhysical(RANGED_ATTACK); } else { UpdateDamagePhysical(BASE_ATTACK); if(CanDualWield() && haveOffhandWeapon()) //allow update offhand damage only if player knows DualWield Spec and has equipped offhand weapon UpdateDamagePhysical(OFF_ATTACK); } if (IsInWorld()) { CallForAllControlledUnits(ApplyScalingBonusWithHelper(SCALING_TARGET_ATTACKPOWER, 0, false),CONTROLLED_PET|CONTROLLED_GUARDIANS); CallForAllControlledUnits(ApplyScalingBonusWithHelper(SCALING_TARGET_SPELLDAMAGE, 0, false),CONTROLLED_PET|CONTROLLED_GUARDIANS); CallForAllControlledUnits(ApplyScalingBonusWithHelper(SCALING_TARGET_DAMAGE, 0, false),CONTROLLED_PET|CONTROLLED_GUARDIANS); } }
void Player::UpdateAttackPowerAndDamage(bool ranged) { float val2 = 0.0f; float level = float(getLevel()); UnitMods unitMod = ranged ? UNIT_MOD_ATTACK_POWER_RANGED : UNIT_MOD_ATTACK_POWER; uint16 index = UNIT_FIELD_ATTACK_POWER; uint16 index_mod = UNIT_FIELD_ATTACK_POWER_MODS; uint16 index_mult = UNIT_FIELD_ATTACK_POWER_MULTIPLIER; if (ranged) { index = UNIT_FIELD_RANGED_ATTACK_POWER; index_mod = UNIT_FIELD_RANGED_ATTACK_POWER_MODS; index_mult = UNIT_FIELD_RANGED_ATTACK_POWER_MULTIPLIER; switch (getClass()) { case CLASS_HUNTER: val2 = level * 2.0f + GetStat(STAT_AGILITY) * 2.0f - 10.0f; break; case CLASS_ROGUE: val2 = level + GetStat(STAT_AGILITY) - 10.0f; break; case CLASS_WARRIOR: val2 = level + GetStat(STAT_AGILITY) - 10.0f; break; case CLASS_DRUID: switch (GetShapeshiftForm()) { case FORM_CAT: case FORM_BEAR: case FORM_DIREBEAR: val2 = 0.0f; break; default: val2 = GetStat(STAT_AGILITY) - 10.0f; break; } break; default: val2 = GetStat(STAT_AGILITY) - 10.0f; break; } } else { switch (getClass()) { case CLASS_WARRIOR: val2 = level * 3.0f + GetStat(STAT_STRENGTH) * 2.0f - 20.0f; break; case CLASS_PALADIN: val2 = level * 3.0f + GetStat(STAT_STRENGTH) * 2.0f - 20.0f; break; case CLASS_ROGUE: val2 = level * 2.0f + GetStat(STAT_STRENGTH) + GetStat(STAT_AGILITY) - 20.0f; break; case CLASS_HUNTER: val2 = level * 2.0f + GetStat(STAT_STRENGTH) + GetStat(STAT_AGILITY) - 20.0f; break; case CLASS_SHAMAN: val2 = level * 2.0f + GetStat(STAT_STRENGTH) * 2.0f - 20.0f; break; case CLASS_DRUID: { ShapeshiftForm form = GetShapeshiftForm(); // Check if Predatory Strikes is skilled float mLevelMult = 0.0; switch (form) { case FORM_CAT: case FORM_BEAR: case FORM_DIREBEAR: case FORM_MOONKIN: { Unit::AuraList const& mDummy = GetAurasByType(SPELL_AURA_DUMMY); for (Unit::AuraList::const_iterator itr = mDummy.begin(); itr != mDummy.end(); ++itr) { // Predatory Strikes if ((*itr)->GetSpellProto()->SpellIconID == 1563) { mLevelMult = (*itr)->GetModifier()->m_amount / 100.0f; break; } } break; } default: break; } switch (form) { case FORM_CAT: val2 = getLevel() * mLevelMult + GetStat(STAT_STRENGTH) * 2.0f + GetStat(STAT_AGILITY) - 20.0f; break; case FORM_BEAR: case FORM_DIREBEAR: val2 = getLevel() * mLevelMult + GetStat(STAT_STRENGTH) * 2.0f - 20.0f; break; case FORM_MOONKIN: val2 = getLevel() * (mLevelMult + 1.5f) + GetStat(STAT_STRENGTH) * 2.0f - 20.0f; break; default: val2 = GetStat(STAT_STRENGTH) * 2.0f - 20.0f; break; } break; } case CLASS_MAGE: val2 = GetStat(STAT_STRENGTH) - 10.0f; break; case CLASS_PRIEST: val2 = GetStat(STAT_STRENGTH) - 10.0f; break; case CLASS_WARLOCK: val2 = GetStat(STAT_STRENGTH) - 10.0f; break; } } SetModifierValue(unitMod, BASE_VALUE, val2); float base_attPower = GetModifierValue(unitMod, BASE_VALUE) * GetModifierValue(unitMod, BASE_PCT); float attPowerMod = GetModifierValue(unitMod, TOTAL_VALUE); float attPowerMultiplier = GetModifierValue(unitMod, TOTAL_PCT) - 1.0f; SetInt32Value(index, (uint32)base_attPower); // UNIT_FIELD_(RANGED)_ATTACK_POWER field SetInt32Value(index_mod, (uint32)attPowerMod); // UNIT_FIELD_(RANGED)_ATTACK_POWER_MODS field SetFloatValue(index_mult, attPowerMultiplier); // UNIT_FIELD_(RANGED)_ATTACK_POWER_MULTIPLIER field // automatically update weapon damage after attack power modification if (ranged) { UpdateDamagePhysical(RANGED_ATTACK); } else { UpdateDamagePhysical(BASE_ATTACK); if (CanDualWield() && haveOffhandWeapon()) // allow update offhand damage only if player knows DualWield Spec and has equipped offhand weapon { UpdateDamagePhysical(OFF_ATTACK); } } }
void Guardian::UpdateDamagePhysical(WeaponAttackType attType) { if(attType > BASE_ATTACK) return; float bonusDamage = 0.0f; if(m_owner->GetTypeId() == TYPEID_PLAYER) { //force of nature if(GetEntry() == ENTRY_TREANT) { int32 spellDmg = int32(m_owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + SPELL_SCHOOL_NATURE)) - m_owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG + SPELL_SCHOOL_NATURE); if(spellDmg > 0) bonusDamage = spellDmg * 0.09f; } //greater fire elemental else if(GetEntry() == ENTRY_FIRE_ELEMENTAL) { int32 spellDmg = int32(m_owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + SPELL_SCHOOL_FIRE)) - m_owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG + SPELL_SCHOOL_FIRE); if(spellDmg > 0) bonusDamage = spellDmg * 0.4f; } } UnitMods unitMod = UNIT_MOD_DAMAGE_MAINHAND; float att_speed = float(GetAttackTime(BASE_ATTACK))/1000.0f; float base_value = GetModifierValue(unitMod, BASE_VALUE) + GetTotalAttackPowerValue(attType)/ 14.0f * att_speed + bonusDamage; float base_pct = GetModifierValue(unitMod, BASE_PCT); float total_value = GetModifierValue(unitMod, TOTAL_VALUE); float total_pct = GetModifierValue(unitMod, TOTAL_PCT); float weapon_mindamage = GetWeaponDamageRange(BASE_ATTACK, MINDAMAGE); float weapon_maxdamage = GetWeaponDamageRange(BASE_ATTACK, MAXDAMAGE); float mindamage = ((base_value + weapon_mindamage) * base_pct + total_value) * total_pct; float maxdamage = ((base_value + weapon_maxdamage) * base_pct + total_value) * total_pct; // Pet's base damage changes depending on happiness if (isHunterPet() && attType == BASE_ATTACK) { switch(((Pet*)this)->GetHappinessState()) { case HAPPY: // 125% of normal damage mindamage = mindamage * 1.25; maxdamage = maxdamage * 1.25; break; case CONTENT: // 100% of normal damage, nothing to modify break; case UNHAPPY: // 75% of normal damage mindamage = mindamage * 0.75; maxdamage = maxdamage * 0.75; break; } } Unit::AuraEffectList const& mDummy = GetAurasByType(SPELL_AURA_MOD_ATTACKSPEED); for(Unit::AuraEffectList::const_iterator itr = mDummy.begin(); itr != mDummy.end(); ++itr) { switch ((*itr)->GetSpellProto()->Id) { case 61682: case 61683: mindamage = mindamage * (100.0f-float((*itr)->GetAmount()))/100.0f; maxdamage = maxdamage * (100.0f-float((*itr)->GetAmount()))/100.0f; break; default: break; } } SetStatFloatValue(UNIT_FIELD_MINDAMAGE, mindamage); SetStatFloatValue(UNIT_FIELD_MAXDAMAGE, maxdamage); }