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::UpdateExpertise(WeaponAttackType attack) { if (attack == RANGED_ATTACK) return; int32 expertise = int32(GetRatingBonusValue(CR_EXPERTISE)); Item* weapon = GetWeaponForAttack(attack, true); AuraEffectList const& expAuras = GetAuraEffectsByType(SPELL_AURA_MOD_EXPERTISE); for (AuraEffectList::const_iterator itr = expAuras.begin(); itr != expAuras.end(); ++itr) { // item neutral spell if ((*itr)->GetSpellInfo()->EquippedItemClass == -1) expertise += (*itr)->GetAmount(); // item dependent spell else if (weapon && weapon->IsFitToSpellRequirements((*itr)->GetSpellInfo())) expertise += (*itr)->GetAmount(); } if (expertise < 0) expertise = 0; switch (attack) { case BASE_ATTACK: SetUInt32Value(PLAYER_FIELD_MAINHAND_EXPERTISE, expertise); break; case OFF_ATTACK: SetUInt32Value(PLAYER_FIELD_OFFHAND_EXPERTISE, expertise); break; default: break; } }
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 (auto expAura : expAuras) { // item neutral spell if (expAura->GetSpellProto()->EquippedItemClass == -1) expertise += expAura->GetModifier()->m_amount; // item dependent spell else if (weapon && weapon->IsFitToSpellRequirements(expAura->GetSpellProto())) expertise += expAura->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::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::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::CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, float& min_damage, float& max_damage) { UnitMods unitMod; switch (attType) { case BASE_ATTACK: default: unitMod = UNIT_MOD_DAMAGE_MAINHAND; break; case OFF_ATTACK: unitMod = UNIT_MOD_DAMAGE_OFFHAND; break; case RANGED_ATTACK: unitMod = UNIT_MOD_DAMAGE_RANGED; break; } float att_speed = GetAPMultiplier(attType, normalized); float base_value = GetModifierValue(unitMod, BASE_VALUE) + GetTotalAttackPowerValue(attType) / 14.0f * att_speed; float base_pct = GetModifierValue(unitMod, BASE_PCT); float total_value = GetModifierValue(unitMod, TOTAL_VALUE); float total_pct = addTotalPct ? GetModifierValue(unitMod, TOTAL_PCT) : 1.0f; float weapon_mindamage = GetWeaponDamageRange(attType, MINDAMAGE); float weapon_maxdamage = GetWeaponDamageRange(attType, MAXDAMAGE); if (IsInFeralForm()) //check if player is druid and in cat or bear forms { float weaponSpeed = BASE_ATTACK_TIME / 1000.f; if (Item* weapon = GetWeaponForAttack(BASE_ATTACK, true)) weaponSpeed = weapon->GetTemplate()->Delay / 1000; if (GetShapeshiftForm() == FORM_CAT) { weapon_mindamage = weapon_mindamage / weaponSpeed; weapon_maxdamage = weapon_maxdamage / weaponSpeed; } else if (GetShapeshiftForm() == FORM_BEAR) { weapon_mindamage = weapon_mindamage / weaponSpeed + weapon_mindamage / 2.5; weapon_maxdamage = weapon_mindamage / weaponSpeed + weapon_maxdamage / 2.5; } } else if (!CanUseAttackType(attType)) //check if player not in form but still can't use (disarm case) { //cannot use ranged/off attack, set values to 0 if (attType != BASE_ATTACK) { min_damage = 0; max_damage = 0; return; } weapon_mindamage = BASE_MINDAMAGE; weapon_maxdamage = BASE_MAXDAMAGE; } /* TODO: Is this still needed after ammo has been removed? else if (attType == RANGED_ATTACK) //add ammo DPS to ranged damage { weapon_mindamage += ammo * att_speed; weapon_maxdamage += ammo * att_speed; }*/ min_damage = ((base_value + weapon_mindamage) * base_pct + total_value) * total_pct; max_damage = ((base_value + weapon_maxdamage) * base_pct + total_value) * total_pct; }
void Player::UpdateAttackPowerAndDamage(bool ranged) { float val2 = 0.0f; float level = float(getLevel()); ChrClassesEntry const* entry = sChrClassesStore.AssertEntry(getClass()); 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; } if (!HasAuraType(SPELL_AURA_OVERRIDE_ATTACK_POWER_BY_SP_PCT)) { if (!ranged) { float strengthValue = std::max(GetStat(STAT_STRENGTH) * entry->AttackPowerPerStrength, 0.0f); float agilityValue = std::max(GetStat(STAT_AGILITY) * entry->AttackPowerPerAgility, 0.0f); SpellShapeshiftFormEntry const* form = sSpellShapeshiftFormStore.LookupEntry(GetShapeshiftForm()); // Directly taken from client, SHAPESHIFT_FLAG_AP_FROM_STRENGTH ? if (form && form->Flags & 0x20) agilityValue += std::max(GetStat(STAT_AGILITY) * entry->AttackPowerPerStrength, 0.0f); val2 = strengthValue + agilityValue; } else val2 = (level + std::max(GetStat(STAT_AGILITY), 0.0f)) * entry->RangedAttackPowerPerAgility; } else { int32 minSpellPower = GetInt32Value(PLAYER_FIELD_MOD_HEALING_DONE_POS); for (int i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; ++i) minSpellPower = std::min(minSpellPower, GetInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + i)); val2 = CalculatePct(float(minSpellPower), GetFloatValue(PLAYER_FIELD_OVERRIDE_AP_BY_SPELL_POWER_PERCENT)); } 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; //add dynamic flat mods if (!ranged) { AuraEffectList const& mAPbyArmor = GetAuraEffectsByType(SPELL_AURA_MOD_ATTACK_POWER_OF_ARMOR); for (AuraEffectList::const_iterator iter = mAPbyArmor.begin(); iter != mAPbyArmor.end(); ++iter) // always: ((*i)->GetModifier()->m_miscvalue == 1 == SPELL_SCHOOL_MASK_NORMAL) attPowerMod += int32(GetArmor() / (*iter)->GetAmount()); } SetInt32Value(index, (uint32)base_attPower); //UNIT_FIELD_(RANGED)_ATTACK_POWER field SetInt32Value(index_mod, (uint32)attPowerMod); //UNIT_FIELD_(RANGED)_ATTACK_POWER_MOD_POS field SetFloatValue(index_mult, attPowerMultiplier); //UNIT_FIELD_(RANGED)_ATTACK_POWER_MULTIPLIER field Pet* pet = GetPet(); //update pet's AP Guardian* guardian = GetGuardianPet(); //automatically update weapon damage after attack power modification if (ranged) { UpdateDamagePhysical(RANGED_ATTACK); if (pet && pet->IsHunterPet()) // At ranged attack change for hunter pet pet->UpdateAttackPowerAndDamage(); } else { UpdateDamagePhysical(BASE_ATTACK); if (Item* offhand = GetWeaponForAttack(OFF_ATTACK, true)) if (CanDualWield() || offhand->GetTemplate()->GetFlags3() & ITEM_FLAG3_ALWAYS_ALLOW_DUAL_WIELD) UpdateDamagePhysical(OFF_ATTACK); if (HasAuraType(SPELL_AURA_MOD_SPELL_DAMAGE_OF_ATTACK_POWER) || HasAuraType(SPELL_AURA_MOD_SPELL_HEALING_OF_ATTACK_POWER) || HasAuraType(SPELL_AURA_OVERRIDE_SPELL_POWER_BY_AP_PCT)) UpdateSpellDamageAndHealingBonus(); if (pet && pet->IsPetGhoul()) // At melee attack power change for DK pet pet->UpdateAttackPowerAndDamage(); if (guardian && guardian->IsSpiritWolf()) // At melee attack power change for Shaman feral spirit guardian->UpdateAttackPowerAndDamage(); } }