void Player::UpdateSpellDamageAndHealingBonus() { // Magic damage modifiers implemented in Unit::SpellDamageBonusDone // This information for client side use only // Get healing bonus for all schools SetStatInt32Value(PLAYER_FIELD_MOD_HEALING_DONE_POS, SpellBaseHealingBonusDone(SPELL_SCHOOL_MASK_ALL)); // Get damage bonus for all schools Unit::AuraEffectList const& modDamageAuras = GetAuraEffectsByType(SPELL_AURA_MOD_DAMAGE_DONE); for (uint16 i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; ++i) { SetInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG + i, std::accumulate(modDamageAuras.begin(), modDamageAuras.end(), 0, [i](int32 negativeMod, AuraEffect const* aurEff) { if (aurEff->GetAmount() < 0 && aurEff->GetMiscValue() & (1 << i)) negativeMod += aurEff->GetAmount(); return negativeMod; })); SetStatInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + i, SpellBaseDamageBonusDone(SpellSchoolMask(1 << i)) - GetInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG + i)); } if (HasAuraType(SPELL_AURA_OVERRIDE_ATTACK_POWER_BY_SP_PCT)) { UpdateAttackPowerAndDamage(); UpdateAttackPowerAndDamage(true); } }
void Totem::Update(uint32 update_diff, uint32 time ) { Unit *owner = GetOwner(); if (!owner || !owner->isAlive() || !isAlive()) { UnSummon(); // remove self return; } if (m_duration <= update_diff) { UnSummon(); // remove self return; } else m_duration -= update_diff; // Grounding totem + polymorph = unsummon if(GetCreatureInfo()->Entry == 5925 && HasAuraType(SPELL_AURA_MOD_CONFUSE)) { UnSummon(); // remove self return; } Creature::Update( update_diff, time ); }
void Player::UpdateManaRegen() { if (GetPowerIndex(POWER_MANA) == MAX_POWERS) return; // Mana regen from spirit float spirit_regen = OCTRegenMPPerSpirit(); float pctPerSec = 0.004f; float netherBonus = 1.0f; float regenRate = 1.0f; uint32 baseMana = GetCreateMana(); // CombatRegen = 2-5% of Base Mana depending on class // Warlock and Mage have 5% default regen switch (getClass()) { case CLASS_MAGE: // According to reports by QA, Nether Attunement should give a 65% regen boost if (HasAura(117957)) netherBonus = 1.13f; case CLASS_WARLOCK: // Base percent per second is higher for mages and warlocks pctPerSec = 0.01f; // Additionally add haste to the mana regen for Warlocks and Mages if (HasAuraType(SPELL_AURA_MOD_MANA_REGEN_BY_HASTE)) regenRate = GetFloatValue(UNIT_MOD_HASTE_REGEN); break; case CLASS_DRUID: // Druids should be calculated based off their mana pool after they gain Natural Insight if (HasAura(112857)) baseMana *= 5; break; case CLASS_PALADIN: // Paladins should be calculated based off their mana pool after they gain Holy Insight if (HasAura(112859)) baseMana *= 5; break; case CLASS_SHAMAN: // Shamans should be calculated based off their mana pool after they gain Spiritual Insight (also elemental shamans) if (HasAura(112858) || HasAura(123099)) baseMana *= 5; break; default: break; } float base_regen = (baseMana * pctPerSec * netherBonus) / regenRate + (GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_POWER_REGEN, POWER_MANA) / 5.0f); // Set regen rate in cast state apply only on spirit based regen int32 modManaRegenInterrupt = GetTotalAuraModifier(SPELL_AURA_MOD_MANA_REGEN_INTERRUPT); // Questionable base_regen *= GetTotalAuraMultiplierByMiscValue(SPELL_AURA_MOD_POWER_REGEN_PERCENT, POWER_MANA); SetStatFloatValue(UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER + GetPowerIndex(POWER_MANA), base_regen + CalculatePct(spirit_regen, modManaRegenInterrupt)); SetStatFloatValue(UNIT_FIELD_POWER_REGEN_FLAT_MODIFIER + GetPowerIndex(POWER_MANA), 0.001f + spirit_regen + base_regen); }
void Player::ApplySpellPowerBonus(int32 amount, bool apply) { if (HasAuraType(SPELL_AURA_OVERRIDE_SPELL_POWER_BY_AP_PCT)) return; apply = _ModifyUInt32(apply, m_baseSpellPower, amount); // For speed just update for client ApplyModUInt32Value(PLAYER_FIELD_MOD_HEALING_DONE_POS, amount, apply); for (int i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; ++i) ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + i, amount, apply); if (HasAuraType(SPELL_AURA_OVERRIDE_ATTACK_POWER_BY_SP_PCT)) { UpdateAttackPowerAndDamage(); UpdateAttackPowerAndDamage(true); } }
void Player::UpdateMastery() { if (HasAuraType(SPELL_AURA_MASTERY)) { if(HasAura(76671)) GetAura(76671)->RecalculateAmountOfEffects();//Paladin Protection Mastery if(HasAura(77514)) GetAura(77514)->RecalculateAmountOfEffects();//DK Frost Mastery if(HasAura(48517)) GetAura(48517)->RecalculateAmountOfEffects();// Druid Balance Mastery if(HasAura(48518)) GetAura(48518)->RecalculateAmountOfEffects();// Druid Balance Mastery if(HasAura(76857)) GetAura(76857)->RecalculateAmountOfEffects();// Warrior Protection Mastery SetInt32Value(PLAYER_FIELD_COMBAT_RATING_1 + CR_MASTERY, m_baseRatingValue[CR_MASTERY]); SetFloatValue(PLAYER_MASTERY, GetMasteryPoints()); } }
void Player::UpdateMasteryAuras() { if (!HasAuraType(SPELL_AURA_MASTERY)) { SetFloatValue(PLAYER_MASTERY, 0.0f); return; } float masteryValue = GetTotalAuraModifier(SPELL_AURA_MASTERY) + GetRatingBonusValue(CR_MASTERY); SetFloatValue(PLAYER_MASTERY, masteryValue); std::vector<uint32> const* masterySpells = GetTalentTreeMasterySpells(m_talentsPrimaryTree[m_activeSpec]); if (!masterySpells) return; for (uint32 i = 0; i < masterySpells->size(); ++i) { SpellAuraHolder* holder = GetSpellAuraHolder(masterySpells->at(i)); if (!holder) continue; SpellEntry const* spellEntry = holder->GetSpellProto(); // calculate mastery scaling coef int32 masteryCoef = GetMasteryCoefficient(spellEntry); if (!masteryCoef) continue; // update aura modifiers for (uint32 j = 0; j < MAX_EFFECT_INDEX; ++j) { Aura* aura = holder->GetAuraByEffectIndex(SpellEffectIndex(j)); if (!aura) continue; if (spellEntry->CalculateSimpleValue(SpellEffectIndex(j))) continue; aura->ApplyModifier(false, false); aura->GetModifier()->m_amount = int32(masteryValue * masteryCoef / 100.0f); aura->ApplyModifier(true, false); } } }
void Vehicle::AddPassenger(Unit *unit, int8 seatId, bool force) { SeatMap::iterator seat; seat = m_Seats.find(seatId); // this should never happen if(seat == m_Seats.end()) return; unit->SetVehicleGUID(GetGUID()); seat->second.passenger = unit; if(unit->GetTypeId() == TYPEID_UNIT && ((Creature*)unit)->isVehicle()) { if(((Vehicle*)unit)->GetEmptySeatsCount(true) == 0) seat->second.flags = SEAT_VEHICLE_FULL; else seat->second.flags = SEAT_VEHICLE_FREE; } else { seat->second.flags = SEAT_FULL; } if(unit->GetTypeId() == TYPEID_PLAYER) { WorldPacket data0(SMSG_FORCE_MOVE_ROOT, 10); data0 << unit->GetPackGUID(); data0 << (uint32)((seat->second.vs_flags & SF_CAN_CAST) ? 2 : 0); unit->SendMessageToSet(&data0,true); } if(seat->second.vs_flags & SF_MAIN_RIDER) { if(!(GetVehicleFlags() & VF_MOVEMENT)) { GetMotionMaster()->Clear(false); GetMotionMaster()->MoveIdle(); SetCharmerGUID(unit->GetGUID()); unit->SetUInt64Value(UNIT_FIELD_CHARM, GetGUID()); if(unit->GetTypeId() == TYPEID_PLAYER) { ((Player*)unit)->SetMover(this); ((Player*)unit)->SetMoverInQueve(this); ((Player*)unit)->SetClientControl(this, 1); } if(canFly() || HasAuraType(SPELL_AURA_FLY) || HasAuraType(SPELL_AURA_MOD_FLIGHT_SPEED_MOUNTED)) { WorldPacket data3(SMSG_MOVE_SET_CAN_FLY, 12); data3<< GetPackGUID(); data3 << (uint32)(0); SendMessageToSet(&data3,false); } } SpellClickInfoMapBounds clickPair = sObjectMgr.GetSpellClickInfoMapBounds(GetEntry()); for(SpellClickInfoMap::const_iterator itr = clickPair.first; itr != clickPair.second; ++itr) { if (unit->GetTypeId() == TYPEID_UNIT || itr->second.IsFitToRequirements((Player*)unit)) { Unit *caster = (itr->second.castFlags & 0x1) ? unit : this; Unit *target = (itr->second.castFlags & 0x2) ? unit : this; caster->CastSpell(target, itr->second.spellId, true); } } if(unit->GetTypeId() == TYPEID_PLAYER) { // it should be added only on rider enter? if(((Player*)unit)->GetGroup()) ((Player*)unit)->SetGroupUpdateFlag(GROUP_UPDATE_VEHICLE); ((Player*)unit)->GetCamera().SetView(this); BuildVehicleActionBar((Player*)unit); } if(!(GetVehicleFlags() & VF_FACTION)) setFaction(unit->getFaction()); if(GetVehicleFlags() & VF_CANT_MOVE) { WorldPacket data2(SMSG_FORCE_MOVE_ROOT, 10); data2<< GetPackGUID(); data2 << (uint32)(2); SendMessageToSet(&data2,false); } if(GetVehicleFlags() & VF_NON_SELECTABLE) SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); } if(seat->second.vs_flags & SF_UNATTACKABLE) unit->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); EmptySeatsCountChanged(); }
void Player::UpdateManaRegen() { // Mana regen from spirit float spirit_regen = OCTRegenMPPerSpirit(); spirit_regen *= GetTotalAuraMultiplierByMiscValue(SPELL_AURA_MOD_POWER_REGEN_PERCENT, POWER_MANA); float HastePct = 1.0f + GetUInt32Value(PLAYER_FIELD_COMBAT_RATING_1 + CR_HASTE_MELEE) * GetRatingMultiplier(CR_HASTE_MELEE) / 100.0f; float combat_regen = 0.004f * GetMaxPower(POWER_MANA) + spirit_regen + (GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_POWER_REGEN, POWER_MANA) / 5.0f); float base_regen = 0.004f * GetMaxPower(POWER_MANA) + (GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_POWER_REGEN, POWER_MANA) / 5.0f); if (getClass() == CLASS_WARLOCK) { combat_regen = 0.01f * GetMaxPower(POWER_MANA) + spirit_regen + GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_POWER_REGEN, POWER_MANA); base_regen = 0.01f * GetMaxPower(POWER_MANA) + GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_POWER_REGEN, POWER_MANA); } // Mana Meditation && Meditation if (HasAuraType(SPELL_AURA_MOD_MANA_REGEN_INTERRUPT)) base_regen += 0.5 * spirit_regen; // Allows 50% of your mana regeneration from Spirit to continue while in combat. // Rune of Power : Increase Mana regeneration by 100% if (HasAura(116014)) { combat_regen *= 2; base_regen *= 2; } // Incanter's Ward : Increase Mana regen by 65% if (HasAura(118858)) { combat_regen *= 1.65f; base_regen *= 1.65f; } // Chaotic Energy : Increase Mana regen by 625% if (HasAura(111546)) { // haste also increase your mana regeneration HastePct = 1.0f + GetUInt32Value(PLAYER_FIELD_COMBAT_RATING_1 + CR_HASTE_MELEE) * GetRatingMultiplier(CR_HASTE_MELEE) / 100.0f; combat_regen = combat_regen + (combat_regen * 6.25f); combat_regen *= HastePct; base_regen = base_regen + (base_regen * 6.25f); base_regen *= HastePct; } // Nether Attunement - 117957 : Haste also increase your mana regeneration if (HasAura(117957)) { HastePct = 1.0f + GetUInt32Value(PLAYER_FIELD_COMBAT_RATING_1 + CR_HASTE_MELEE) * GetRatingMultiplier(CR_HASTE_MELEE) / 100.0f; combat_regen *= HastePct; base_regen *= HastePct; } // Mana Attunement : Increase Mana regen by 50% if (HasAura(121039)) { combat_regen = combat_regen + (combat_regen * 0.5f); combat_regen *= HastePct; base_regen = base_regen + (base_regen * 0.5f); base_regen *= HastePct; } // Invocation : Decrease your mana regen by 50% if (HasAura(114003)) { combat_regen *= 0.5f; base_regen *= 0.5f; } // Not In Combat : 2% of base mana + spirit_regen SetStatFloatValue(UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER, base_regen); // In Combat : 2% of base mana SetStatFloatValue(UNIT_FIELD_POWER_REGEN_FLAT_MODIFIER, combat_regen); }
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::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(); } }