diff options
author | maximius <none@none> | 2009-10-17 15:51:44 -0700 |
---|---|---|
committer | maximius <none@none> | 2009-10-17 15:51:44 -0700 |
commit | e585187b248f48b3c6e9247b49fa07c6565d65e5 (patch) | |
tree | 637c5b7ddacf41040bef4ea4f75a97da64c6a9bc /src/game/StatSystem.cpp | |
parent | 26b5e033ffde3d161382fc9addbfa99738379641 (diff) |
*Backed out changeset 3be01fb200a5
--HG--
branch : trunk
Diffstat (limited to 'src/game/StatSystem.cpp')
-rw-r--r-- | src/game/StatSystem.cpp | 175 |
1 files changed, 175 insertions, 0 deletions
diff --git a/src/game/StatSystem.cpp b/src/game/StatSystem.cpp index cdbda70bdf7..56bde0e5442 100644 --- a/src/game/StatSystem.cpp +++ b/src/game/StatSystem.cpp @@ -17,30 +17,37 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + #include "Unit.h" #include "Player.h" #include "Pet.h" #include "Creature.h" #include "SharedDefines.h" #include "SpellAuras.h" + /*####################################### ######## ######## ######## PLAYERS STAT SYSTEM ######## ######## ######## #######################################*/ + 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: @@ -57,11 +64,14 @@ bool Player::UpdateStats(Stats stat) UpdateAllSpellCritChances(); UpdateArmor(); //SPELL_AURA_MOD_RESISTANCE_OF_INTELLECT_PERCENT, only armor currently break; + case STAT_SPIRIT: break; + default: break; } + if (stat == STAT_STRENGTH) { UpdateAttackPowerAndDamage(false); @@ -81,8 +91,10 @@ bool Player::UpdateStats(Stats stat) if (HasAuraTypeWithMiscvalue(SPELL_AURA_MOD_RANGED_ATTACK_POWER_OF_STAT_PERCENT, stat)) UpdateAttackPowerAndDamage(true); } + UpdateSpellDamageAndHealingBonus(); UpdateManaRegen(); + // Update ratings in exist SPELL_AURA_MOD_RATING_FROM_STAT and only depends from stat uint32 mask = 0; AuraEffectList const& modRatingFromStat = GetAurasByType(SPELL_AURA_MOD_RATING_FROM_STAT); @@ -97,14 +109,17 @@ bool Player::UpdateStats(Stats stat) } return true; } + void Player::ApplySpellPowerBonus(int32 amount, bool apply) { m_baseSpellPower+=apply?amount:-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);; } + void Player::UpdateSpellDamageAndHealingBonus() { // Magic damage modifiers implemented in Unit::SpellDamageBonus @@ -115,6 +130,7 @@ void Player::UpdateSpellDamageAndHealingBonus() for(int i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; ++i) SetStatInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS+i, SpellBaseDamageBonus(SpellSchoolMask(1 << i))); } + bool Player::UpdateAllStats() { for (int i = STAT_STRENGTH; i < MAX_STATS; ++i) @@ -122,12 +138,15 @@ bool Player::UpdateAllStats() float value = GetTotalStatValue(Stats(i)); SetStat(Stats(i), (int32)value); } + UpdateArmor(); // calls UpdateAttackPowerAndDamage() in UpdateArmor for SPELL_AURA_MOD_ATTACK_POWER_OF_ARMOR UpdateAttackPowerAndDamage(true); UpdateMaxHealth(); + for(int i = POWER_MANA; i < MAX_POWERS; ++i) UpdateMaxPower(Powers(i)); + UpdateAllCritPercentages(); UpdateAllSpellCritChances(); UpdateDefenseBonusesMod(); @@ -139,14 +158,17 @@ bool Player::UpdateAllStats() RecalculateRating(CR_ARMOR_PENETRATION); for (int i = SPELL_SCHOOL_NORMAL; i < MAX_SPELL_SCHOOL; ++i) UpdateResistances(i); + return true; } + void Player::UpdateResistances(uint32 school) { if(school > SPELL_SCHOOL_NORMAL) { float value = GetTotalAuraModValue(UnitMods(UNIT_MOD_RESISTANCE_START + school)); SetResistance(SpellSchools(school), int32(value)); + Pet *pet = GetPet(); if(pet) pet->UpdateResistances(school); @@ -154,14 +176,17 @@ void Player::UpdateResistances(uint32 school) else UpdateArmor(); } + 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 AuraEffectList const& mResbyIntellect = GetAurasByType(SPELL_AURA_MOD_RESISTANCE_OF_STAT_PERCENT); for(AuraEffectList::const_iterator i = mResbyIntellect.begin();i != mResbyIntellect.end(); ++i) @@ -169,64 +194,87 @@ void Player::UpdateArmor() if((*i)->GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL) value += int32(GetStat(Stats((*i)->GetMiscBValue())) * (*i)->GetAmount() / 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 } + float Player::GetHealthBonusFromStamina() { float stamina = GetStat(STAT_STAMINA); + float baseStam = stamina < 20 ? stamina : 20; float moreStam = stamina - baseStam; + return baseStam + (moreStam*10.0f); } + float Player::GetManaBonusFromIntellect() { float intellect = GetStat(STAT_INTELLECT); + float baseInt = intellect < 20 ? intellect : 20; float moreInt = intellect - baseInt; + return baseInt + (moreInt*15.0f); } + void Player::UpdateMaxHealth() { UnitMods unitMod = UNIT_MOD_HEALTH; + float value = GetModifierValue(unitMod, BASE_VALUE) + GetCreateHealth(); value *= GetModifierValue(unitMod, BASE_PCT); value += GetModifierValue(unitMod, TOTAL_VALUE) + GetHealthBonusFromStamina(); value *= GetModifierValue(unitMod, TOTAL_PCT); + SetMaxHealth((uint32)value); } + void Player::UpdateMaxPower(Powers power) { UnitMods unitMod = UnitMods(UNIT_MOD_POWER_START + power); + float bonusPower = (power == POWER_MANA) ? GetManaBonusFromIntellect() : 0; + float value = GetModifierValue(unitMod, BASE_VALUE) + GetCreatePowers(power); value *= GetModifierValue(unitMod, BASE_PCT); value += GetModifierValue(unitMod, TOTAL_VALUE) + bonusPower; value *= GetModifierValue(unitMod, TOTAL_PCT); + SetMaxPower(power, uint32(value)); } + void Player::ApplyFeralAPBonus(int32 amount, bool apply) { m_baseFeralAP+= apply ? amount:-amount; 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; @@ -281,6 +329,7 @@ void Player::UpdateAttackPowerAndDamage(bool ranged ) } default: break; } + switch(m_form) { case FORM_CAT: @@ -300,9 +349,12 @@ void Player::UpdateAttackPowerAndDamage(bool ranged ) 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 ) { @@ -318,15 +370,19 @@ void Player::UpdateAttackPowerAndDamage(bool ranged ) AuraEffectList const& mAPbyStat = GetAurasByType(SPELL_AURA_MOD_ATTACK_POWER_OF_STAT_PERCENT); for(AuraEffectList::const_iterator i = mAPbyStat.begin();i != mAPbyStat.end(); ++i) attPowerMod += int32(GetStat(Stats((*i)->GetMiscValue())) * (*i)->GetAmount() / 100.0f); + AuraEffectList const& mAPbyArmor = GetAurasByType(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) @@ -342,18 +398,22 @@ void Player::UpdateAttackPowerAndDamage(bool ranged ) UpdateDamagePhysical(OFF_ATTACK); if(getClass() == CLASS_SHAMAN) // mental quickness UpdateSpellDamageAndHealingBonus(); + if(pet && pet->IsPetGhoul()) // At ranged attack change for hunter pet pet->UpdateAttackPowerAndDamage(); } } + void Player::UpdateShieldBlockValue() { SetUInt32Value(PLAYER_SHIELD_BLOCK, GetShieldBlockValue()); } + void Player::CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, float& min_damage, float& max_damage) { UnitMods unitMod; UnitMods attPower; + switch(attType) { case BASE_ATTACK: @@ -370,17 +430,22 @@ void Player::CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bo 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 = 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 { uint32 lvl = getLevel(); if ( lvl > 60 ) lvl = 60; + weapon_mindamage = lvl*0.85*att_speed; weapon_maxdamage = lvl*1.25*att_speed; } @@ -401,14 +466,18 @@ void Player::CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bo 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::UpdateDamagePhysical(WeaponAttackType attType) { float mindamage; float maxdamage; + CalculateMinMaxDamage(attType, false, true, mindamage, maxdamage); + switch(attType) { case BASE_ATTACK: @@ -426,12 +495,14 @@ void Player::UpdateDamagePhysical(WeaponAttackType attType) break; } } + void Player::UpdateDefenseBonusesMod() { UpdateBlockPercentage(); UpdateParryPercentage(); UpdateDodgePercentage(); } + void Player::UpdateBlockPercentage() { // No block @@ -450,11 +521,13 @@ void Player::UpdateBlockPercentage() } SetStatFloatValue(PLAYER_BLOCK_PERCENTAGE, value); } + void Player::UpdateCritPercentage(WeaponAttackType attType) { BaseModGroup modGroup; uint16 index; CombatRating cr; + switch(attType) { case OFF_ATTACK: @@ -474,22 +547,27 @@ void Player::UpdateCritPercentage(WeaponAttackType attType) cr = CR_CRIT_MELEE; break; } + float value = GetTotalPercentageModValue(modGroup) + GetRatingBonusValue(cr); // Modify crit from weapon skill and maximized defense skill of same level victim difference value += (int32(GetWeaponSkillValue(attType)) - int32(GetMaxSkillValueForLevel())) * 0.04f; value = value < 0.0f ? 0.0f : value; SetStatFloatValue(index, value); } + void Player::UpdateAllCritPercentages() { float value = GetMeleeCritFromAgility(); + SetBaseModValue(CRIT_PERCENTAGE, PCT_MOD, value); SetBaseModValue(OFFHAND_CRIT_PERCENTAGE, PCT_MOD, value); SetBaseModValue(RANGED_CRIT_PERCENTAGE, PCT_MOD, value); + UpdateCritPercentage(BASE_ATTACK); UpdateCritPercentage(OFF_ATTACK); UpdateCritPercentage(RANGED_ATTACK); } + void Player::UpdateParryPercentage() { // No parry @@ -508,6 +586,7 @@ void Player::UpdateParryPercentage() } SetStatFloatValue(PLAYER_PARRY_PERCENTAGE, value); } + void Player::UpdateDodgePercentage() { // Dodge from agility @@ -521,6 +600,7 @@ void Player::UpdateDodgePercentage() value = value < 0.0f ? 0.0f : value; SetStatFloatValue(PLAYER_DODGE_PERCENTAGE, value); } + void Player::UpdateSpellCritChance(uint32 school) { // For normal school set zero crit chance @@ -541,40 +621,50 @@ void Player::UpdateSpellCritChance(uint32 school) crit += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_SPELL_CRIT_CHANCE_SCHOOL, 1<<school); // Increase crit from spell crit ratings crit += GetRatingBonusValue(CR_CRIT_SPELL); + // Store crit value SetFloatValue(PLAYER_SPELL_CRIT_PERCENTAGE1 + school, crit); } + void Player::UpdateArmorPenetration(int32 amount) { // Store Rating Value SetUInt32Value(PLAYER_FIELD_COMBAT_RATING_1 + CR_ARMOR_PENETRATION, amount); } + void Player::UpdateMeleeHitChances() { m_modMeleeHitChance = GetTotalAuraModifier(SPELL_AURA_MOD_HIT_CHANCE); m_modMeleeHitChance+= GetRatingBonusValue(CR_HIT_MELEE); } + void Player::UpdateRangedHitChances() { m_modRangedHitChance = GetTotalAuraModifier(SPELL_AURA_MOD_HIT_CHANCE); m_modRangedHitChance+= GetRatingBonusValue(CR_HIT_RANGED); } + void Player::UpdateSpellHitChances() { m_modSpellHitChance = GetTotalAuraModifier(SPELL_AURA_MOD_SPELL_HIT_CHANCE); m_modSpellHitChance+= GetRatingBonusValue(CR_HIT_SPELL); } + void Player::UpdateAllSpellCritChances() { for (int i = SPELL_SCHOOL_NORMAL; i < MAX_SPELL_SCHOOL; ++i) UpdateSpellCritChance(i); } + void Player::UpdateExpertise(WeaponAttackType attack) { if(attack==RANGED_ATTACK) return; + int32 expertise = int32(GetRatingBonusValue(CR_EXPERTISE)); + Item *weapon = GetWeaponForAttack(attack); + AuraEffectList const& expAuras = GetAurasByType(SPELL_AURA_MOD_EXPERTISE); for(AuraEffectList::const_iterator itr = expAuras.begin(); itr != expAuras.end(); ++itr) { @@ -585,8 +675,10 @@ void Player::UpdateExpertise(WeaponAttackType attack) else if(weapon && weapon->IsFitToSpellRequirements((*itr)->GetSpellProto())) expertise += (*itr)->GetAmount(); } + if(expertise < 0) expertise = 0; + switch(attack) { case BASE_ATTACK: SetUInt32Value(PLAYER_EXPERTISE, expertise); break; @@ -594,11 +686,13 @@ void Player::UpdateExpertise(WeaponAttackType attack) default: break; } } + void Player::ApplyManaRegenBonus(int32 amount, bool apply) { m_baseManaRegen+= apply ? amount : -amount; UpdateManaRegen(); } + void Player::UpdateManaRegen() { float Intellect = GetStat(STAT_INTELLECT); @@ -606,57 +700,76 @@ void Player::UpdateManaRegen() 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 AuraEffectList const& regenAura = GetAurasByType(SPELL_AURA_MOD_MANA_REGEN_FROM_STAT); for(AuraEffectList::const_iterator i = regenAura.begin();i != regenAura.end(); ++i) { power_regen_mp5 += GetStat(Stats((*i)->GetMiscValue())) * (*i)->GetAmount() / 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::_ApplyAllStatBonuses() { SetCanModifyStats(false); + _ApplyAllAuraMods(); _ApplyAllItemMods(); + SetCanModifyStats(true); + UpdateAllStats(); } + void Player::_RemoveAllStatBonuses() { SetCanModifyStats(false); + _RemoveAllItemMods(); _RemoveAllAuraMods(); + SetCanModifyStats(true); + UpdateAllStats(); } + /*####################################### ######## ######## ######## MOBS STAT SYSTEM ######## ######## ######## #######################################*/ + bool Creature::UpdateStats(Stats /*stat*/) { return true; } + bool Creature::UpdateAllStats() { UpdateMaxHealth(); UpdateAttackPowerAndDamage(); UpdateAttackPowerAndDamage(true); + for(int i = POWER_MANA; i < MAX_POWERS; ++i) UpdateMaxPower(Powers(i)); + for(int i = SPELL_SCHOOL_NORMAL; i < MAX_SPELL_SCHOOL; ++i) UpdateResistances(i); + return true; } + void Creature::UpdateResistances(uint32 school) { if(school > SPELL_SCHOOL_NORMAL) @@ -667,40 +780,50 @@ void Creature::UpdateResistances(uint32 school) else UpdateArmor(); } + void Creature::UpdateArmor() { float value = GetTotalAuraModValue(UNIT_MOD_ARMOR); SetArmor(int32(value)); } + void Creature::UpdateMaxHealth() { float value = GetTotalAuraModValue(UNIT_MOD_HEALTH); SetMaxHealth((uint32)value); } + void Creature::UpdateMaxPower(Powers power) { UnitMods unitMod = UnitMods(UNIT_MOD_POWER_START + power); + float value = GetTotalAuraModValue(unitMod); SetMaxPower(power, uint32(value)); } + void Creature::UpdateAttackPowerAndDamage(bool ranged) { 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; } + 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); @@ -710,6 +833,7 @@ void Creature::UpdateAttackPowerAndDamage(bool ranged) UpdateDamagePhysical(OFF_ATTACK); } } + void Creature::UpdateDamagePhysical(WeaponAttackType attType) { UnitMods unitMod; @@ -726,9 +850,12 @@ void Creature::UpdateDamagePhysical(WeaponAttackType attType) unitMod = UNIT_MOD_DAMAGE_RANGED; break; } + //float att_speed = float(GetAttackTime(attType))/1000.0f; + float weapon_mindamage = GetWeaponDamageRange(attType, MINDAMAGE); float weapon_maxdamage = GetWeaponDamageRange(attType, MAXDAMAGE); + /* difference in AP between current attack power and base value from DB */ float att_pwr_change = GetTotalAttackPowerValue(attType) - GetCreatureInfo()->attackpower; float base_value = GetModifierValue(unitMod, BASE_VALUE) + (att_pwr_change * GetAPMultiplier(attType, false) / 14.0f); @@ -736,13 +863,16 @@ void Creature::UpdateDamagePhysical(WeaponAttackType attType) float total_value = GetModifierValue(unitMod, TOTAL_VALUE); float total_pct = GetModifierValue(unitMod, TOTAL_PCT); float dmg_multiplier = GetCreatureInfo()->dmg_multiplier; + if(!CanUseAttackType(attType)) { weapon_mindamage = 0; weapon_maxdamage = 0; } + float mindamage = ((base_value + weapon_mindamage) * dmg_multiplier * base_pct + total_value) * total_pct; float maxdamage = ((base_value + weapon_maxdamage) * dmg_multiplier * base_pct + total_value) * total_pct; + switch(attType) { case BASE_ATTACK: @@ -760,11 +890,13 @@ void Creature::UpdateDamagePhysical(WeaponAttackType attType) break; } } + /*####################################### ######## ######## ######## PETS STAT SYSTEM ######## ######## ######## #######################################*/ + #define ENTRY_IMP 416 #define ENTRY_VOIDWALKER 1860 #define ENTRY_SUCCUBUS 1863 @@ -773,12 +905,15 @@ void Creature::UpdateDamagePhysical(WeaponAttackType attType) #define ENTRY_WATER_ELEMENTAL 510 #define ENTRY_TREANT 1964 #define ENTRY_FIRE_ELEMENTAL 15438 + bool Guardian::UpdateStats(Stats stat) { if(stat > STAT_SPIRIT) return false; + // value = ((base_value * base_pct) + total_value) * total_pct float value = GetTotalStatValue(stat); + Unit *owner = GetOwner(); if ( stat == STAT_STAMINA ) { @@ -798,7 +933,9 @@ bool Guardian::UpdateStats(Stats stat) if (IsPetGhoul()) value += float(owner->GetStat(stat)) * 0.3f; } + SetStat(stat, int32(value)); + switch(stat) { case STAT_STRENGTH: UpdateAttackPowerAndDamage(); break; @@ -809,50 +946,64 @@ bool Guardian::UpdateStats(Stats stat) default: break; } + return true; } + bool Guardian::UpdateAllStats() { for (int i = STAT_STRENGTH; i < MAX_STATS; ++i) UpdateStats(Stats(i)); + for(int i = POWER_MANA; i < MAX_POWERS; ++i) UpdateMaxPower(Powers(i)); + for (int i = SPELL_SCHOOL_NORMAL; i < MAX_SPELL_SCHOOL; ++i) UpdateResistances(i); + return true; } + void Guardian::UpdateResistances(uint32 school) { if(school > SPELL_SCHOOL_NORMAL) { float value = GetTotalAuraModValue(UnitMods(UNIT_MOD_RESISTANCE_START + school)); + // hunter and warlock pets gain 40% of owner's resistance if(isPet()) value += float(m_owner->GetResistance(SpellSchools(school))) * 0.4f; + SetResistance(SpellSchools(school), int32(value)); } else UpdateArmor(); } + void Guardian::UpdateArmor() { float value = 0.0f; float bonus_armor = 0.0f; UnitMods unitMod = UNIT_MOD_ARMOR; + // hunter and warlock pets gain 35% of owner's armor value if(isPet()) bonus_armor = 0.35f * float(m_owner->GetArmor()); + value = GetModifierValue(unitMod, BASE_VALUE); value *= GetModifierValue(unitMod, BASE_PCT); value += GetStat(STAT_AGILITY) * 2.0f; value += GetModifierValue(unitMod, TOTAL_VALUE) + bonus_armor; value *= GetModifierValue(unitMod, TOTAL_PCT); + SetArmor(int32(value)); } + void Guardian::UpdateMaxHealth() { UnitMods unitMod = UNIT_MOD_HEALTH; float stamina = GetStat(STAT_STAMINA) - GetCreateStat(STAT_STAMINA); + float multiplicator; switch(GetEntry()) { @@ -863,17 +1014,22 @@ void Guardian::UpdateMaxHealth() case ENTRY_FELGUARD: multiplicator = 11.0f; break; default: multiplicator = 10.0f; break; } + float value = GetModifierValue(unitMod, BASE_VALUE) + GetCreateHealth(); value *= GetModifierValue(unitMod, BASE_PCT); value += GetModifierValue(unitMod, TOTAL_VALUE) + stamina * multiplicator; value *= GetModifierValue(unitMod, TOTAL_PCT); + SetMaxHealth((uint32)value); } + void Guardian::UpdateMaxPower(Powers power) { UnitMods unitMod = UnitMods(UNIT_MOD_POWER_START + power); + float addValue = (power == POWER_MANA) ? GetStat(STAT_INTELLECT) - GetCreateStat(STAT_INTELLECT) : 0.0f; float multiplicator = 15.0f; + switch(GetEntry()) { case ENTRY_IMP: multiplicator = 4.95f; break; @@ -883,23 +1039,29 @@ void Guardian::UpdateMaxPower(Powers power) case ENTRY_FELGUARD: multiplicator = 11.5f; break; default: multiplicator = 15.0f; break; } + float value = GetModifierValue(unitMod, BASE_VALUE) + GetCreatePowers(power); value *= GetModifierValue(unitMod, BASE_PCT); value += GetModifierValue(unitMod, TOTAL_VALUE) + addValue * multiplicator; value *= GetModifierValue(unitMod, TOTAL_PCT); + SetMaxPower(power, uint32(value)); } + void Guardian::UpdateAttackPowerAndDamage(bool ranged) { if(ranged) return; + float val = 0.0f; float bonusAP = 0.0f; UnitMods unitMod = UNIT_MOD_ATTACK_POWER; + if(GetEntry() == ENTRY_IMP) // imp's attack power val = GetStat(STAT_STRENGTH) - 10.0f; else val = 2 * GetStat(STAT_STRENGTH) - 20.0f; + Unit* owner = GetOwner(); if( owner && owner->GetTypeId()==TYPEID_PLAYER) { @@ -933,24 +1095,30 @@ void Guardian::UpdateAttackPowerAndDamage(bool ranged) SetBonusDamage( int32(frost * 0.4f)); } } + SetModifierValue(UNIT_MOD_ATTACK_POWER, BASE_VALUE, val + bonusAP); + //in BASE_VALUE of UNIT_MOD_ATTACK_POWER for creatures we store data of meleeattackpower field in DB 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; + //UNIT_FIELD_(RANGED)_ATTACK_POWER field SetInt32Value(UNIT_FIELD_ATTACK_POWER, (int32)base_attPower); //UNIT_FIELD_(RANGED)_ATTACK_POWER_MODS field SetInt32Value(UNIT_FIELD_ATTACK_POWER_MODS, (int32)attPowerMod); //UNIT_FIELD_(RANGED)_ATTACK_POWER_MULTIPLIER field SetFloatValue(UNIT_FIELD_ATTACK_POWER_MULTIPLIER, attPowerMultiplier); + //automatically update weapon damage after attack power modification UpdateDamagePhysical(BASE_ATTACK); } + void Guardian::UpdateDamagePhysical(WeaponAttackType attType) { if(attType > BASE_ATTACK) return; + float bonusDamage = 0.0f; if(m_owner->GetTypeId() == TYPEID_PLAYER) { @@ -969,16 +1137,22 @@ void Guardian::UpdateDamagePhysical(WeaponAttackType attType) 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) { @@ -999,6 +1173,7 @@ void Guardian::UpdateDamagePhysical(WeaponAttackType attType) break; } } + SetStatFloatValue(UNIT_FIELD_MINDAMAGE, mindamage); SetStatFloatValue(UNIT_FIELD_MAXDAMAGE, maxdamage); } |