void Player::UpdateArmor() { UnitMods unitMod = UNIT_MOD_ARMOR; float value = GetModifierValue(unitMod, BASE_VALUE); // base armor (from items) value *= GetModifierValue(unitMod, BASE_PCT); // armor percent from items value += GetModifierValue(unitMod, TOTAL_VALUE); //add dynamic flat mods AuraEffectList const& mResbyIntellect = GetAuraEffectsByType(SPELL_AURA_MOD_RESISTANCE_OF_STAT_PERCENT); for (AuraEffectList::const_iterator i = mResbyIntellect.begin(); i != mResbyIntellect.end(); ++i) { if ((*i)->GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL) value += CalculatePct(GetStat(Stats((*i)->GetMiscValueB())), (*i)->GetAmount()); } if (GetShapeshiftForm() == FORM_BEAR) // Thick Hide if (AuraEffect* thickHide = GetDummyAuraEffect(SPELLFAMILY_GENERIC, 1558, EFFECT_1)) AddPct(value, thickHide->GetAmount()); value *= GetModifierValue(unitMod, TOTAL_PCT); SetArmor(int32(value)); RecalculatePetsScalingResistance(SPELL_SCHOOL_NORMAL); UpdateAttackPowerAndDamage(); // armor dependent auras update for SPELL_AURA_MOD_ATTACK_POWER_OF_ARMOR }
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: { // Check if Predatory Strikes is skilled float mLevelMult = 0.0f; float weapon_bonus = 0.0f; if (IsInFeralForm()) { Unit::AuraEffectList const& mDummy = GetAuraEffectsByType(SPELL_AURA_DUMMY); for (Unit::AuraEffectList::const_iterator itr = mDummy.begin(); itr != mDummy.end(); ++itr) { AuraEffect* aurEff = *itr; if (aurEff->GetSpellInfo()->SpellIconID == 1563) { switch (aurEff->GetEffIndex()) { case 0: // Predatory Strikes (effect 0) mLevelMult = CalculatePct(1.0f, aurEff->GetAmount()); break; case 1: // Predatory Strikes (effect 1) if (Item* mainHand = m_items[EQUIPMENT_SLOT_MAINHAND]) { // also gains % attack power from equipped weapon ItemTemplate const* proto = mainHand->GetTemplate(); if (!proto) continue; weapon_bonus = CalculatePct(float(proto->getFeralBonus()), aurEff->GetAmount()); } break; default: break; } } } } switch (GetShapeshiftForm()) { case FORM_CAT: val2 = getLevel() * (mLevelMult + 2.0f) + GetStat(STAT_STRENGTH) * 2.0f + GetStat(STAT_AGILITY) - 20.0f + weapon_bonus + m_baseFeralAP; break; case FORM_BEAR: case FORM_DIREBEAR: val2 = getLevel() * (mLevelMult + 3.0f) + GetStat(STAT_STRENGTH) * 2.0f - 20.0f + weapon_bonus + 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) { AuraEffectList const& mRAPbyStat = GetAuraEffectsByType(SPELL_AURA_MOD_RANGED_ATTACK_POWER_OF_STAT_PERCENT); for (AuraEffectList::const_iterator i = mRAPbyStat.begin(); i != mRAPbyStat.end(); ++i) attPowerMod += CalculatePct(GetStat(Stats((*i)->GetMiscValue())), (*i)->GetAmount()); } } else { AuraEffectList const& mAPbyStat = GetAuraEffectsByType(SPELL_AURA_MOD_ATTACK_POWER_OF_STAT_PERCENT); for (AuraEffectList::const_iterator i = mAPbyStat.begin(); i != mAPbyStat.end(); ++i) attPowerMod += CalculatePct(GetStat(Stats((*i)->GetMiscValue())), (*i)->GetAmount()); 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()); } 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 Pet* pet = GetPet(); //update pet's AP //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 (CanDualWield() && haveOffhandWeapon()) //allow update offhand damage only if player knows DualWield Spec and has equipped offhand weapon UpdateDamagePhysical(OFF_ATTACK); if (getClass() == CLASS_SHAMAN || getClass() == CLASS_PALADIN) // mental quickness UpdateSpellDamageAndHealingBonus(); if (pet && pet->IsPetGhoul()) // At ranged attack change for hunter pet pet->UpdateAttackPowerAndDamage(); } }
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_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 + 2.0f) + GetStat(STAT_STRENGTH) * 2.0f + GetStat(STAT_AGILITY) - 20.0f; break; case FORM_BEAR: case FORM_DIREBEAR: val2 = getLevel() * (mLevelMult + 3.0f) + 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); // 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); } } 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::CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, float& min_damage, float& max_damage) { UnitMods unitMod; UnitMods attPower; switch (attType) { case BASE_ATTACK: default: unitMod = UNIT_MOD_DAMAGE_MAINHAND; attPower = UNIT_MOD_ATTACK_POWER; break; case OFF_ATTACK: unitMod = UNIT_MOD_DAMAGE_OFFHAND; attPower = UNIT_MOD_ATTACK_POWER; break; case RANGED_ATTACK: unitMod = UNIT_MOD_DAMAGE_RANGED; attPower = UNIT_MOD_ATTACK_POWER_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 = GetModifierValue(unitMod, TOTAL_PCT); 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, non main hand attacks not allowed for this mode so not check attack type { float weaponSpeed = GetAttackTime(attType) / 1000.0f; switch (GetShapeshiftForm()) { case FORM_CAT: weapon_mindamage = weapon_mindamage / weaponSpeed; weapon_maxdamage = weapon_maxdamage / weaponSpeed; break; case FORM_BEAR: weapon_mindamage = weapon_mindamage / weaponSpeed + weapon_mindamage / 2.5f; weapon_maxdamage = weapon_maxdamage / weaponSpeed + weapon_maxdamage / 2.5f; break; } } else if (!CanUseEquippedWeapon(attType)) // check if player not in form but still can't use weapon (broken/etc) { weapon_mindamage = BASE_MINDAMAGE; weapon_maxdamage = BASE_MAXDAMAGE; } else if (attType == RANGED_ATTACK) // add ammo DPS to ranged damage { weapon_mindamage += GetAmmoDPS() * att_speed; weapon_maxdamage += GetAmmoDPS() * 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) { 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; if (ranged) { index = UNIT_FIELD_RANGED_ATTACK_POWER; 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: { switch (GetShapeshiftForm()) { case FORM_CAT: val2 = GetStat(STAT_STRENGTH) * 2.0f + GetStat(STAT_AGILITY) - 20.0f + m_baseFeralAP; break; case FORM_BEAR: case FORM_DIREBEAR: case FORM_MOONKIN: val2 = 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) { AuraEffectList const& mRAPbyStat = GetAuraEffectsByType(SPELL_AURA_MOD_RANGED_ATTACK_POWER_OF_STAT_PERCENT); for (AuraEffectList::const_iterator i = mRAPbyStat.begin(); i != mRAPbyStat.end(); ++i) attPowerMod += CalculatePctN(GetStat(Stats((*i)->GetMiscValue())), (*i)->GetAmount()); } } else { AuraEffectList const& mAPbyStat = GetAuraEffectsByType(SPELL_AURA_MOD_ATTACK_POWER_OF_STAT_PERCENT); for (AuraEffectList::const_iterator i = mAPbyStat.begin(); i != mAPbyStat.end(); ++i) attPowerMod += CalculatePctN(GetStat(Stats((*i)->GetMiscValue())), (*i)->GetAmount()); 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 Pet* pet = GetPet(); //update pet's AP //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 (CanDualWield() && haveOffhandWeapon()) //allow update offhand damage only if player knows DualWield Spec and has equipped offhand weapon UpdateDamagePhysical(OFF_ATTACK); if (getClass() == CLASS_SHAMAN || getClass() == CLASS_PALADIN) // mental quickness UpdateSpellDamageAndHealingBonus(); if (pet && pet->IsPetGhoul()) // At ranged attack change for hunter pet pet->UpdateAttackPowerAndDamage(); } }
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; // Maybe fix that in GetWeaponForAttack ? if (Item* weapon = GetUseableItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND)) if (weapon->GetTemplate()->Class == ITEM_CLASS_WEAPON) weaponSpeed = float(0.001f * weapon->GetTemplate()->Delay); 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_maxdamage / 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; } 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()); UnitMods unitMod_pos = ranged ? UNIT_MOD_ATTACK_POWER_RANGED_POS : UNIT_MOD_ATTACK_POWER_POS; UnitMods unitMod_neg = ranged ? UNIT_MOD_ATTACK_POWER_RANGED_NEG : UNIT_MOD_ATTACK_POWER_NEG; uint16 index = UNIT_FIELD_ATTACK_POWER; uint16 index_mod_pos = UNIT_FIELD_ATTACK_POWER_MOD_POS; uint16 index_mod_neg = UNIT_FIELD_ATTACK_POWER_MOD_NEG; uint16 index_mult = UNIT_FIELD_ATTACK_POWER_MULTIPLIER; if (ranged) { index = UNIT_FIELD_RANGED_ATTACK_POWER; index_mod_pos = UNIT_FIELD_RANGED_ATTACK_POWER_MOD_POS; index_mod_neg = UNIT_FIELD_RANGED_ATTACK_POWER_MOD_NEG; index_mult = UNIT_FIELD_RANGED_ATTACK_POWER_MULTIPLIER; switch (getClass()) { case CLASS_HUNTER: val2 = level * 2.0f + GetStat(STAT_AGILITY) * 2.0f - 20.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) * 2.0f - 20.0f; break; case CLASS_HUNTER: val2 = level * 2.0f + GetStat(STAT_STRENGTH) + GetStat(STAT_AGILITY) * 2.0f - 20.0f; break; case CLASS_SHAMAN: val2 = level * 2.0f + GetStat(STAT_STRENGTH) + GetStat(STAT_AGILITY) * 2.0f - 20.0f; break; case CLASS_DRUID: { ShapeshiftForm form = GetShapeshiftForm(); // Check if Predatory Strikes is skilled float mLevelMult = 0.0f; switch (form) { case FORM_CAT: case FORM_BEAR: case FORM_DIREBEAR: case FORM_MOONKIN: { Unit::AuraEffectList const& mDummy = GetAuraEffectsByType(SPELL_AURA_DUMMY); for (Unit::AuraEffectList::const_iterator itr = mDummy.begin(); itr != mDummy.end(); ++itr) { // Predatory Strikes (effect 0) if ((*itr)->GetEffIndex() == 0 && (*itr)->GetSpellProto()->SpellIconID == 1563) { mLevelMult = CalculatePctN(1.0f, (*itr)->GetAmount()); break; } } break; } default: break; } switch (form) { case FORM_CAT: val2 = getLevel() * (mLevelMult + 2.0f) + GetStat(STAT_STRENGTH) * 2.0f - 20.0f + GetStat(STAT_AGILITY) * 2.0f - 20.0f + m_baseFeralAP; break; case FORM_BEAR: case FORM_DIREBEAR: val2 = getLevel() * (mLevelMult + 2.0f) + GetStat(STAT_STRENGTH) * 2.0f - 20.0f + GetStat(STAT_AGILITY) * 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_pos, BASE_VALUE, val2); float base_attPower = (GetModifierValue(unitMod_pos, BASE_VALUE) - GetModifierValue(unitMod_neg, BASE_VALUE)) * (GetModifierValue(unitMod_pos, BASE_PCT) - GetModifierValue(unitMod_neg, BASE_PCT)); float attPowerMod_pos = GetModifierValue(unitMod_pos, TOTAL_VALUE); float attPowerMod_neg = GetModifierValue(unitMod_neg, TOTAL_VALUE); //add dynamic flat mods if (ranged) { if ((getClassMask() & CLASSMASK_WAND_USERS) == 0) { AuraEffectList const& mRAPbyStat = GetAuraEffectsByType(SPELL_AURA_MOD_RANGED_ATTACK_POWER_OF_STAT_PERCENT); for (AuraEffectList::const_iterator i = mRAPbyStat.begin(); i != mRAPbyStat.end(); ++i) { int32 temp = CalculatePctN(int32(GetStat(Stats((*i)->GetMiscValue()))), ((*i)->GetAmount() / 100)); if(temp > 0) attPowerMod_pos += temp; else attPowerMod_neg -= temp; } } } else { AuraEffectList const& mAPbyStat = GetAuraEffectsByType(SPELL_AURA_MOD_ATTACK_POWER_OF_STAT_PERCENT); for (AuraEffectList::const_iterator i = mAPbyStat.begin(); i != mAPbyStat.end(); ++i) { int32 temp = CalculatePctN(int32(GetStat(Stats((*i)->GetMiscValue()))), ((*i)->GetAmount() / 100)); if(temp > 0) attPowerMod_pos += temp; else attPowerMod_neg -= temp; } 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) int32 temp = int32(GetArmor() / (*iter)->GetAmount()); if(temp > 0) attPowerMod_pos += temp; else attPowerMod_neg -= temp; } } float attPowerMultiplier = (GetModifierValue(unitMod_pos, TOTAL_PCT) + (1 - GetModifierValue(unitMod_neg, TOTAL_PCT)))- 1.0f; SetInt32Value(index, (uint32)base_attPower); //UNIT_FIELD_(RANGED)_ATTACK_POWER field SetInt32Value(index_mod_pos, (uint32)attPowerMod_pos); //UNIT_FIELD_(RANGED)_ATTACK_POWER_MOD_POS field SetInt32Value(index_mod_neg, (uint32)attPowerMod_neg); //UNIT_FIELD_(RANGED)_ATTACK_POWER_MOD_NEG field SetFloatValue(index_mult, attPowerMultiplier); //UNIT_FIELD_(RANGED)_ATTACK_POWER_MULTIPLIER field Pet *pet = GetPet(); //update pet's AP //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 (CanDualWield() && haveOffhandWeapon()) //allow update offhand damage only if player knows DualWield Spec and has equipped offhand weapon UpdateDamagePhysical(OFF_ATTACK); if (getClass() == CLASS_SHAMAN || getClass() == CLASS_PALADIN) // mental quickness UpdateSpellDamageAndHealingBonus(); if (pet && pet->IsPetGhoul()) // At ranged attack change for hunter pet pet->UpdateAttackPowerAndDamage(); } }
void Player::UpdateAttackPowerAndDamage(bool ranged) { float val2 = 0.0f; float level = float(getLevel()); ChrClassesEntry const* entry = sChrClassesStore.LookupEntry(getClass()); UnitMods unitMod_pos = ranged ? UNIT_MOD_ATTACK_POWER_RANGED_POS : UNIT_MOD_ATTACK_POWER_POS; UnitMods unitMod_neg = ranged ? UNIT_MOD_ATTACK_POWER_RANGED_NEG : UNIT_MOD_ATTACK_POWER_NEG; uint16 index = UNIT_FIELD_ATTACK_POWER; uint16 index_mod_pos = UNIT_FIELD_ATTACK_POWER_MOD_POS; uint16 index_mod_neg = UNIT_FIELD_ATTACK_POWER_MOD_NEG; uint16 index_mult = UNIT_FIELD_ATTACK_POWER_MULTIPLIER; if (ranged) { index = UNIT_FIELD_RANGED_ATTACK_POWER; val2 = (level + std::max(GetStat(STAT_AGILITY) - 10.0f, 0.0f)) * entry->RAPPerAgility; index_mod_pos = UNIT_FIELD_RANGED_ATTACK_POWER_MOD_POS; index_mod_neg = UNIT_FIELD_RANGED_ATTACK_POWER_MOD_NEG; index_mult = UNIT_FIELD_RANGED_ATTACK_POWER_MULTIPLIER; } else { // This is general. float strengthValue = std::max((GetStat(STAT_STRENGTH) - 10.0f) * entry->APPerStrenth, 0.0f); float agilityValue = std::max((GetStat(STAT_AGILITY) - 10.0f) * entry->APPerAgility, 0.0f); // This is specific. switch (getClass()) { case CLASS_HUNTER: // in the case of Rogues, Hunters, and Shamans, each point of Agility will add 2 AP case CLASS_ROGUE: case CLASS_SHAMAN: agilityValue = std::max(GetStat(STAT_AGILITY) * 2, 0.0f); break; case CLASS_WARRIOR: // Warriors, Paladins, and Death Knights will gain 2 AP from each point of Strength. case CLASS_PALADIN: case CLASS_DEATH_KNIGHT: strengthValue = std::max(GetStat(STAT_STRENGTH) * 2, 0.0f); break; case CLASS_DRUID: // Druids will gain 2 AP from Agility in Bear/Cat form. You have NO strenght in Bear form. if (IsInFeralForm()) if (GetShapeshiftForm() == FORM_CAT || GetShapeshiftForm() == FORM_BEAR) agilityValue = std::max(GetStat(STAT_AGILITY) * 2, 0.0f); break; } val2 = strengthValue + agilityValue; } SetModifierValue(unitMod_pos, BASE_VALUE, val2); float base_attPower = (GetModifierValue(unitMod_pos, BASE_VALUE) - GetModifierValue(unitMod_neg, BASE_VALUE)) * (GetModifierValue(unitMod_pos, BASE_PCT) + (1 - GetModifierValue(unitMod_neg, BASE_PCT))); float attPowerMod_pos = GetModifierValue(unitMod_pos, TOTAL_VALUE); float attPowerMod_neg = GetModifierValue(unitMod_neg, TOTAL_VALUE); //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) int32 attPowerMod = int32(GetArmor() / (*iter)->GetAmount()); if (attPowerMod > 0) attPowerMod_pos += attPowerMod; else attPowerMod_neg -= attPowerMod; } } float attPowerMultiplier = (GetModifierValue(unitMod_pos, TOTAL_PCT) + (1 - GetModifierValue(unitMod_neg, TOTAL_PCT))) - 1.0f; SetInt32Value(index, (uint32)base_attPower); //UNIT_FIELD_(RANGED)_ATTACK_POWER field SetInt32Value(index_mod_pos, (uint32) attPowerMod_pos); //UNIT_FIELD_(RANGED)_ATTACK_POWER_MOD_POS field SetInt32Value(index_mod_neg, (uint32) attPowerMod_neg); //UNIT_FIELD_(RANGED)_ATTACK_POWER_MOD_NEG 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 (CanDualWield() && haveOffhandWeapon()) //allow update offhand damage only if player knows DualWield Spec and has equipped offhand weapon UpdateDamagePhysical(OFF_ATTACK); if (getClass() == CLASS_SHAMAN || getClass() == CLASS_PALADIN) // mental quickness 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(); } }
void Player::UpdateAttackPowerAndDamage(bool ranged) { float val2 = 0.0f; float level = float(getLevel()); ChrClassesEntry const* entry = sChrClassesStore.LookupEntry(getClass()); UnitMods unitMod = ranged ? UNIT_MOD_ATTACK_POWER_RANGED : UNIT_MOD_ATTACK_POWER; uint16 index = UNIT_FIELD_ATTACK_POWER; uint16 index_mod_pos = UNIT_FIELD_ATTACK_POWER_MOD_POS; uint16 index_mod_neg = UNIT_FIELD_ATTACK_POWER_MOD_NEG; uint16 index_mult = UNIT_FIELD_ATTACK_POWER_MULTIPLIER; if (ranged) { index = UNIT_FIELD_RANGED_ATTACK_POWER; index_mod_pos = UNIT_FIELD_RANGED_ATTACK_POWER_MOD_POS; index_mod_neg = UNIT_FIELD_RANGED_ATTACK_POWER_MOD_NEG; index_mult = UNIT_FIELD_RANGED_ATTACK_POWER_MULTIPLIER; val2 = (level + std::max(GetStat(STAT_AGILITY) - 10.0f, 0.0f)) * entry->RAPPerAgility; } else { float strengthValue = std::max((GetStat(STAT_STRENGTH) - 10.0f) * entry->APPerStrenth, 0.0f); float agilityValue = std::max((GetStat(STAT_AGILITY) - 10.0f) * entry->APPerAgility, 0.0f); if (GetShapeshiftForm() == FORM_CAT || GetShapeshiftForm() == FORM_BEAR) agilityValue += std::max((GetStat(STAT_AGILITY) - 10.0f) * 2, 0.0f); val2 = strengthValue + agilityValue; } 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 && HasAuraType(SPELL_AURA_MOD_ATTACK_POWER_OF_ARMOR)) { 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) int32 temp = int32(GetArmor() / (*iter)->GetAmount()); if (temp > 0) attPowerMod += temp; else attPowerMod -= temp; } } if (HasAuraType(SPELL_AURA_OVERRIDE_AP_BY_SPELL_POWER_PCT)) { int32 ApBySpellPct = 0; int32 spellPower = ToPlayer()->GetBaseSpellPowerBonus(); // SpellPower from Weapon spellPower += std::max(0, int32(ToPlayer()->GetStat(STAT_INTELLECT)) - 10); // SpellPower from intellect AuraEffectList const& mAPFromSpellPowerPct = GetAuraEffectsByType(SPELL_AURA_OVERRIDE_AP_BY_SPELL_POWER_PCT); for (AuraEffectList::const_iterator i = mAPFromSpellPowerPct.begin(); i != mAPFromSpellPowerPct.end(); ++i) ApBySpellPct += CalculatePct(spellPower, (*i)->GetAmount()); if (ApBySpellPct > 0) { SetInt32Value(index, uint32(ApBySpellPct)); //UNIT_FIELD_(RANGED)_ATTACK_POWER field SetFloatValue(index_mult, attPowerMultiplier); //UNIT_FIELD_(RANGED)_ATTACK_POWER_MULTIPLIER field } else { SetInt32Value(index, uint32(base_attPower + attPowerMod)); //UNIT_FIELD_(RANGED)_ATTACK_POWER field SetFloatValue(index_mult, attPowerMultiplier); //UNIT_FIELD_(RANGED)_ATTACK_POWER_MULTIPLIER field } } else { SetInt32Value(index, uint32(base_attPower + attPowerMod)); //UNIT_FIELD_(RANGED)_ATTACK_POWER field SetFloatValue(index_mult, attPowerMultiplier); //UNIT_FIELD_(RANGED)_ATTACK_POWER_MULTIPLIER field } Pet* pet = GetPet(); //update pet's AP //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 (CanDualWield() && haveOffhandWeapon()) //allow update offhand damage only if player knows DualWield Spec and has equipped offhand weapon UpdateDamagePhysical(OFF_ATTACK); if (getClass() == CLASS_SHAMAN || getClass() == CLASS_PALADIN) // mental quickness UpdateSpellDamageAndHealingBonus(); if (pet && pet->IsPetGhoul()) // At ranged attack change for hunter pet pet->UpdateAttackPowerAndDamage(); } }
void Player::CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, float& minDamage, float& maxDamage) { 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 attackPowerMod = std::max(GetAPMultiplier(attType, normalized), 0.25f); float baseValue = GetModifierValue(unitMod, BASE_VALUE) + GetTotalAttackPowerValue(attType) / 3.5f * attackPowerMod; float basePct = GetModifierValue(unitMod, BASE_PCT); float totalValue = GetModifierValue(unitMod, TOTAL_VALUE); float totalPct = addTotalPct ? GetModifierValue(unitMod, TOTAL_PCT) : 1.0f; float weaponMinDamage = GetWeaponDamageRange(attType, MINDAMAGE); float weaponMaxDamage = GetWeaponDamageRange(attType, MAXDAMAGE); SpellShapeshiftFormEntry const* shapeshift = sSpellShapeshiftFormStore.LookupEntry(GetShapeshiftForm()); if (shapeshift && shapeshift->CombatRoundTime) { weaponMinDamage = weaponMinDamage * shapeshift->CombatRoundTime / 1000.0f / attackPowerMod; weaponMaxDamage = weaponMaxDamage * shapeshift->CombatRoundTime / 1000.0f / attackPowerMod; } 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) { minDamage = 0; maxDamage = 0; return; } weaponMinDamage = BASE_MINDAMAGE; weaponMaxDamage = BASE_MAXDAMAGE; } minDamage = ((weaponMinDamage + baseValue) * basePct + totalValue) * totalPct; maxDamage = ((weaponMaxDamage + baseValue) * basePct + totalValue) * totalPct; }
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(); } }
void Player::UpdateAttackPowerAndDamage(bool ranged) { float val2 = 0.0f; float level = float(getLevel()); ChrClassesEntry const* entry = sChrClassesStore.LookupEntry(getClass()); UnitMods unitMod = ranged ? UNIT_MOD_ATTACK_POWER_RANGED : UNIT_MOD_ATTACK_POWER; uint16 index = UNIT_FIELD_ATTACK_POWER; if (ranged) { index = UNIT_FIELD_RANGED_ATTACK_POWER; val2 = (level + std::max(GetStat(STAT_AGILITY) - 10.0f, 0.0f)) * entry->RAPPerAgility; } else { float strengthValue = std::max((GetStat(STAT_STRENGTH) - 10.0f) * entry->APPerStrenth, 0.0f); float agilityValue = std::max((GetStat(STAT_AGILITY) - 10.0f) * entry->APPerAgility, 0.0f); SpellShapeshiftFormEntry const* form = sSpellShapeshiftFormStore.LookupEntry(GetShapeshiftForm()); // Directly taken from client, SHAPESHIFT_FLAG_AP_FROM_STRENGTH ? if (form && form->flags1 & 0x20) agilityValue += std::max((GetStat(STAT_AGILITY) - 10.0f) * entry->APPerStrenth, 0.0f); val2 = strengthValue + agilityValue; } 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) { 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 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 (CanDualWield() && haveOffhandWeapon()) //allow update offhand damage only if player knows DualWield Spec and has equipped offhand weapon UpdateDamagePhysical(OFF_ATTACK); if (getClass() == CLASS_SHAMAN || getClass() == CLASS_PALADIN) // mental quickness 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(); } }
///////////////////////////////////////////////// /// Interaction: Unit can interact with another unit (immediate response) /// /// @note Relations API Tier 1 /// /// Client-side counterpart: <tt>CGUnit_C::CanInteractNow(const CGUnit_C *this, const CGUnit_C *unit)</tt> ///////////////////////////////////////////////// bool Unit::CanInteractNow(const Unit* unit) const { // Simple sanity check if (!unit) return false; // Original logic // We can't intract while on taxi if (HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_TAXI_FLIGHT)) return false; // We can't interact while being charmed if (GetCharmerGuid()) return false; // We can't interact with anyone while being dead (this does not apply to player ghosts, which allow very limited interactions) if (!isAlive() && (GetTypeId() == TYPEID_UNIT || !(static_cast<const Player*>(this)->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST)))) return false; // We can't interact with anyone while being shapeshifted, unless form flags allow us to do so if (IsShapeShifted()) { if (SpellShapeshiftFormEntry const* formEntry = sSpellShapeshiftFormStore.LookupEntry(GetShapeshiftForm())) { if (!(formEntry->flags1 & SHAPESHIFT_FORM_FLAG_ALLOW_NPC_INTERACT)) return false; } } // We can't interact with dead units, unless it's a creature with special flag if (!unit->isAlive()) { if (GetTypeId() != TYPEID_UNIT || !(static_cast<const Creature*>(unit)->GetCreatureInfo()->CreatureTypeFlags & CREATURE_TYPEFLAGS_INTERACT_DEAD)) return false; } // We can't interact with charmed units if (unit->GetCharmerGuid()) return false; // We can't interact with units who are currently fighting if (unit->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PET_IN_COMBAT) || unit->getVictim()) return false; return CanInteract(unit); }
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.LookupEntry(getClass()); UnitMods unitMod = ranged ? UNIT_MOD_ATTACK_POWER_RANGED : UNIT_MOD_ATTACK_POWER; uint16 index = UNIT_FIELD_ATTACK_POWER; uint16 index_mult = UNIT_FIELD_ATTACK_POWER_MULTIPLIER; if (ranged) { index = UNIT_FIELD_RANGED_ATTACK_POWER; index_mult = UNIT_FIELD_RANGED_ATTACK_POWER_MULTIPLIER; val2 = (level + std::max(GetStat(STAT_AGILITY) - 10.0f, 0.0f)) * entry->RAPPerAgility; } else { float strengthValue = std::max((GetStat(STAT_STRENGTH) - 10.0f) * entry->APPerStrenth, 0.0f); float agilityValue = std::max((GetStat(STAT_AGILITY) - 10.0f) * entry->APPerAgility, 0.0f); if (GetShapeshiftForm() == FORM_CAT || GetShapeshiftForm() == FORM_BEAR) agilityValue += std::max((GetStat(STAT_AGILITY) - 10.0f) * 2, 0.0f); val2 = strengthValue + agilityValue; } SetModifierValue(unitMod, BASE_VALUE, val2); float base_attPower = GetModifierValue(unitMod, BASE_VALUE) * GetModifierValue(unitMod, BASE_PCT); float attPowerMultiplier = GetModifierValue(unitMod, TOTAL_PCT) - 1.0f; float attPowerMod = GetModifierValue(unitMod, TOTAL_VALUE); //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) attPowerMod += int32(GetArmor() / (*iter)->GetAmount()); } SetInt32Value(index, uint32(base_attPower + attPowerMod)); // UNIT_FIELD_(RANGED)_ATTACK_POWER field SetFloatValue(index_mult, attPowerMultiplier); // UNIT_FIELD_(RANGED)_ATTACK_POWER_MULTIPLIER field Pet* pet = GetPet(); //update pet's AP //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 (CanDualWield() && haveOffhandWeapon()) //allow update offhand damage only if player knows DualWield Spec and has equipped offhand weapon UpdateDamagePhysical(OFF_ATTACK); if (getClass() == CLASS_SHAMAN || getClass() == CLASS_PALADIN) // mental quickness UpdateSpellDamageAndHealingBonus(); if (pet && pet->IsPetGhoul()) // At ranged attack change for hunter pet pet->UpdateAttackPowerAndDamage(); } }