1 | /* |
---|
2 | * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> |
---|
3 | * |
---|
4 | * This program is free software; you can redistribute it and/or modify |
---|
5 | * it under the terms of the GNU General Public License as published by |
---|
6 | * the Free Software Foundation; either version 2 of the License, or |
---|
7 | * (at your option) any later version. |
---|
8 | * |
---|
9 | * This program is distributed in the hope that it will be useful, |
---|
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
12 | * GNU General Public License for more details. |
---|
13 | * |
---|
14 | * You should have received a copy of the GNU General Public License |
---|
15 | * along with this program; if not, write to the Free Software |
---|
16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
---|
17 | */ |
---|
18 | |
---|
19 | #include "Unit.h" |
---|
20 | #include "Player.h" |
---|
21 | #include "Pet.h" |
---|
22 | #include "Creature.h" |
---|
23 | #include "SharedDefines.h" |
---|
24 | #include "SpellAuras.h" |
---|
25 | |
---|
26 | /*####################################### |
---|
27 | ######## ######## |
---|
28 | ######## PLAYERS STAT SYSTEM ######## |
---|
29 | ######## ######## |
---|
30 | #######################################*/ |
---|
31 | |
---|
32 | bool Player::UpdateStats(Stats stat) |
---|
33 | { |
---|
34 | if(stat > STAT_SPIRIT) |
---|
35 | return false; |
---|
36 | |
---|
37 | // value = ((base_value * base_pct) + total_value) * total_pct |
---|
38 | float value = GetTotalStatValue(stat); |
---|
39 | |
---|
40 | SetStat(stat, int32(value)); |
---|
41 | |
---|
42 | if(stat == STAT_STAMINA || stat == STAT_INTELLECT) |
---|
43 | { |
---|
44 | Pet *pet = GetPet(); |
---|
45 | if(pet) |
---|
46 | pet->UpdateStats(stat); |
---|
47 | } |
---|
48 | |
---|
49 | switch(stat) |
---|
50 | { |
---|
51 | case STAT_STRENGTH: |
---|
52 | UpdateAttackPowerAndDamage(); |
---|
53 | UpdateShieldBlockValue(); |
---|
54 | break; |
---|
55 | case STAT_AGILITY: |
---|
56 | UpdateArmor(); |
---|
57 | UpdateAttackPowerAndDamage(true); |
---|
58 | if(getClass() == CLASS_ROGUE || getClass() == CLASS_HUNTER || getClass() == CLASS_DRUID && m_form==FORM_CAT) |
---|
59 | UpdateAttackPowerAndDamage(); |
---|
60 | |
---|
61 | UpdateAllCritPercentages(); |
---|
62 | UpdateDodgePercentage(); |
---|
63 | break; |
---|
64 | |
---|
65 | case STAT_STAMINA: UpdateMaxHealth(); break; |
---|
66 | case STAT_INTELLECT: |
---|
67 | UpdateMaxPower(POWER_MANA); |
---|
68 | UpdateAllSpellCritChances(); |
---|
69 | UpdateAttackPowerAndDamage(true); //SPELL_AURA_MOD_RANGED_ATTACK_POWER_OF_STAT_PERCENT, only intelect currently |
---|
70 | UpdateArmor(); //SPELL_AURA_MOD_RESISTANCE_OF_INTELLECT_PERCENT, only armor currently |
---|
71 | break; |
---|
72 | |
---|
73 | case STAT_SPIRIT: |
---|
74 | break; |
---|
75 | |
---|
76 | default: |
---|
77 | break; |
---|
78 | } |
---|
79 | UpdateSpellDamageAndHealingBonus(); |
---|
80 | UpdateManaRegen(); |
---|
81 | return true; |
---|
82 | } |
---|
83 | |
---|
84 | void Player::UpdateSpellDamageAndHealingBonus() |
---|
85 | { |
---|
86 | // Magic damage modifiers implemented in Unit::SpellDamageBonus |
---|
87 | // This information for client side use only |
---|
88 | // Get healing bonus for all schools |
---|
89 | SetStatInt32Value(PLAYER_FIELD_MOD_HEALING_DONE_POS, SpellBaseHealingBonus(SPELL_SCHOOL_MASK_ALL)); |
---|
90 | // Get damage bonus for all schools |
---|
91 | for(int i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; i++) |
---|
92 | SetStatInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS+i, SpellBaseDamageBonus(SpellSchoolMask(1 << i))); |
---|
93 | } |
---|
94 | |
---|
95 | bool Player::UpdateAllStats() |
---|
96 | { |
---|
97 | for (int i = STAT_STRENGTH; i < MAX_STATS; i++) |
---|
98 | { |
---|
99 | float value = GetTotalStatValue(Stats(i)); |
---|
100 | SetStat(Stats(i), (int32)value); |
---|
101 | } |
---|
102 | |
---|
103 | UpdateAttackPowerAndDamage(); |
---|
104 | UpdateAttackPowerAndDamage(true); |
---|
105 | UpdateArmor(); |
---|
106 | UpdateMaxHealth(); |
---|
107 | |
---|
108 | for(int i = POWER_MANA; i < MAX_POWERS; i++) |
---|
109 | UpdateMaxPower(Powers(i)); |
---|
110 | |
---|
111 | UpdateAllCritPercentages(); |
---|
112 | UpdateAllSpellCritChances(); |
---|
113 | UpdateDefenseBonusesMod(); |
---|
114 | UpdateShieldBlockValue(); |
---|
115 | UpdateSpellDamageAndHealingBonus(); |
---|
116 | UpdateManaRegen(); |
---|
117 | UpdateExpertise(BASE_ATTACK); |
---|
118 | UpdateExpertise(OFF_ATTACK); |
---|
119 | for (int i = SPELL_SCHOOL_NORMAL; i < MAX_SPELL_SCHOOL; i++) |
---|
120 | UpdateResistances(i); |
---|
121 | |
---|
122 | return true; |
---|
123 | } |
---|
124 | |
---|
125 | void Player::UpdateResistances(uint32 school) |
---|
126 | { |
---|
127 | if(school > SPELL_SCHOOL_NORMAL) |
---|
128 | { |
---|
129 | float value = GetTotalAuraModValue(UnitMods(UNIT_MOD_RESISTANCE_START + school)); |
---|
130 | SetResistance(SpellSchools(school), int32(value)); |
---|
131 | |
---|
132 | Pet *pet = GetPet(); |
---|
133 | if(pet) |
---|
134 | pet->UpdateResistances(school); |
---|
135 | } |
---|
136 | else |
---|
137 | UpdateArmor(); |
---|
138 | } |
---|
139 | |
---|
140 | void Player::UpdateArmor() |
---|
141 | { |
---|
142 | float value = 0.0f; |
---|
143 | UnitMods unitMod = UNIT_MOD_ARMOR; |
---|
144 | |
---|
145 | value = GetModifierValue(unitMod, BASE_VALUE); // base armor (from items) |
---|
146 | value *= GetModifierValue(unitMod, BASE_PCT); // armor percent from items |
---|
147 | value += GetStat(STAT_AGILITY) * 2.0f; // armor bonus from stats |
---|
148 | value += GetModifierValue(unitMod, TOTAL_VALUE); |
---|
149 | |
---|
150 | //add dynamic flat mods |
---|
151 | AuraList const& mResbyIntellect = GetAurasByType(SPELL_AURA_MOD_RESISTANCE_OF_STAT_PERCENT); |
---|
152 | for(AuraList::const_iterator i = mResbyIntellect.begin();i != mResbyIntellect.end(); ++i) |
---|
153 | { |
---|
154 | Modifier* mod = (*i)->GetModifier(); |
---|
155 | if(mod->m_miscvalue & SPELL_SCHOOL_MASK_NORMAL) |
---|
156 | value += int32(GetStat(Stats((*i)->GetMiscBValue())) * mod->m_amount / 100.0f); |
---|
157 | } |
---|
158 | |
---|
159 | value *= GetModifierValue(unitMod, TOTAL_PCT); |
---|
160 | |
---|
161 | SetArmor(int32(value)); |
---|
162 | |
---|
163 | Pet *pet = GetPet(); |
---|
164 | if(pet) |
---|
165 | pet->UpdateArmor(); |
---|
166 | } |
---|
167 | |
---|
168 | float Player::GetHealthBonusFromStamina() |
---|
169 | { |
---|
170 | float stamina = GetStat(STAT_STAMINA); |
---|
171 | |
---|
172 | float baseStam = stamina < 20 ? stamina : 20; |
---|
173 | float moreStam = stamina - baseStam; |
---|
174 | |
---|
175 | return baseStam + (moreStam*10.0f); |
---|
176 | } |
---|
177 | |
---|
178 | float Player::GetManaBonusFromIntellect() |
---|
179 | { |
---|
180 | float intellect = GetStat(STAT_INTELLECT); |
---|
181 | |
---|
182 | float baseInt = intellect < 20 ? intellect : 20; |
---|
183 | float moreInt = intellect - baseInt; |
---|
184 | |
---|
185 | return baseInt + (moreInt*15.0f); |
---|
186 | } |
---|
187 | |
---|
188 | void Player::UpdateMaxHealth() |
---|
189 | { |
---|
190 | UnitMods unitMod = UNIT_MOD_HEALTH; |
---|
191 | |
---|
192 | float value = GetModifierValue(unitMod, BASE_VALUE) + GetCreateHealth(); |
---|
193 | value *= GetModifierValue(unitMod, BASE_PCT); |
---|
194 | value += GetModifierValue(unitMod, TOTAL_VALUE) + GetHealthBonusFromStamina(); |
---|
195 | value *= GetModifierValue(unitMod, TOTAL_PCT); |
---|
196 | |
---|
197 | SetMaxHealth((uint32)value); |
---|
198 | } |
---|
199 | |
---|
200 | void Player::UpdateMaxPower(Powers power) |
---|
201 | { |
---|
202 | UnitMods unitMod = UnitMods(UNIT_MOD_POWER_START + power); |
---|
203 | |
---|
204 | float bonusPower = (power == POWER_MANA) ? GetManaBonusFromIntellect() : 0; |
---|
205 | |
---|
206 | float value = GetModifierValue(unitMod, BASE_VALUE) + GetCreatePowers(power); |
---|
207 | value *= GetModifierValue(unitMod, BASE_PCT); |
---|
208 | value += GetModifierValue(unitMod, TOTAL_VALUE) + bonusPower; |
---|
209 | value *= GetModifierValue(unitMod, TOTAL_PCT); |
---|
210 | |
---|
211 | SetMaxPower(power, uint32(value)); |
---|
212 | } |
---|
213 | |
---|
214 | void Player::UpdateAttackPowerAndDamage(bool ranged ) |
---|
215 | { |
---|
216 | float val2 = 0.0f; |
---|
217 | float level = float(getLevel()); |
---|
218 | |
---|
219 | UnitMods unitMod = ranged ? UNIT_MOD_ATTACK_POWER_RANGED : UNIT_MOD_ATTACK_POWER; |
---|
220 | |
---|
221 | uint16 index = UNIT_FIELD_ATTACK_POWER; |
---|
222 | uint16 index_mod = UNIT_FIELD_ATTACK_POWER_MODS; |
---|
223 | uint16 index_mult = UNIT_FIELD_ATTACK_POWER_MULTIPLIER; |
---|
224 | |
---|
225 | if(ranged) |
---|
226 | { |
---|
227 | index = UNIT_FIELD_RANGED_ATTACK_POWER; |
---|
228 | index_mod = UNIT_FIELD_RANGED_ATTACK_POWER_MODS; |
---|
229 | index_mult = UNIT_FIELD_RANGED_ATTACK_POWER_MULTIPLIER; |
---|
230 | |
---|
231 | switch(getClass()) |
---|
232 | { |
---|
233 | case CLASS_HUNTER: val2 = level * 2.0f + GetStat(STAT_AGILITY) - 10.0f; break; |
---|
234 | case CLASS_ROGUE: val2 = level + GetStat(STAT_AGILITY) - 10.0f; break; |
---|
235 | case CLASS_WARRIOR:val2 = level + GetStat(STAT_AGILITY) - 10.0f; break; |
---|
236 | case CLASS_DRUID: |
---|
237 | switch(m_form) |
---|
238 | { |
---|
239 | case FORM_CAT: |
---|
240 | case FORM_BEAR: |
---|
241 | case FORM_DIREBEAR: |
---|
242 | val2 = 0.0f; break; |
---|
243 | default: |
---|
244 | val2 = GetStat(STAT_AGILITY) - 10.0f; break; |
---|
245 | } |
---|
246 | break; |
---|
247 | default: val2 = GetStat(STAT_AGILITY) - 10.0f; break; |
---|
248 | } |
---|
249 | } |
---|
250 | else |
---|
251 | { |
---|
252 | switch(getClass()) |
---|
253 | { |
---|
254 | case CLASS_WARRIOR: val2 = level*3.0f + GetStat(STAT_STRENGTH)*2.0f - 20.0f; break; |
---|
255 | case CLASS_PALADIN: val2 = level*3.0f + GetStat(STAT_STRENGTH)*2.0f - 20.0f; break; |
---|
256 | case CLASS_ROGUE: val2 = level*2.0f + GetStat(STAT_STRENGTH) + GetStat(STAT_AGILITY) - 20.0f; break; |
---|
257 | case CLASS_HUNTER: val2 = level*2.0f + GetStat(STAT_STRENGTH) + GetStat(STAT_AGILITY) - 20.0f; break; |
---|
258 | case CLASS_SHAMAN: val2 = level*2.0f + GetStat(STAT_STRENGTH)*2.0f - 20.0f; break; |
---|
259 | case CLASS_DRUID: |
---|
260 | { |
---|
261 | //Check if Predatory Strikes is skilled |
---|
262 | float mLevelMult = 0.0; |
---|
263 | switch(m_form) |
---|
264 | { |
---|
265 | case FORM_CAT: |
---|
266 | case FORM_BEAR: |
---|
267 | case FORM_DIREBEAR: |
---|
268 | case FORM_MOONKIN: |
---|
269 | { |
---|
270 | Unit::AuraList const& mDummy = GetAurasByType(SPELL_AURA_DUMMY); |
---|
271 | for(Unit::AuraList::const_iterator itr = mDummy.begin(); itr != mDummy.end(); ++itr) |
---|
272 | { |
---|
273 | // Predatory Strikes |
---|
274 | if ((*itr)->GetSpellProto()->SpellIconID == 1563) |
---|
275 | { |
---|
276 | mLevelMult = (*itr)->GetModifier()->m_amount / 100.0f; |
---|
277 | break; |
---|
278 | } |
---|
279 | } |
---|
280 | break; |
---|
281 | } |
---|
282 | } |
---|
283 | |
---|
284 | switch(m_form) |
---|
285 | { |
---|
286 | case FORM_CAT: |
---|
287 | val2 = getLevel()*(mLevelMult+2.0f) + GetStat(STAT_STRENGTH)*2.0f + GetStat(STAT_AGILITY) - 20.0f; break; |
---|
288 | case FORM_BEAR: |
---|
289 | case FORM_DIREBEAR: |
---|
290 | val2 = getLevel()*(mLevelMult+3.0f) + GetStat(STAT_STRENGTH)*2.0f - 20.0f; break; |
---|
291 | case FORM_MOONKIN: |
---|
292 | val2 = getLevel()*(mLevelMult+1.5f) + GetStat(STAT_STRENGTH)*2.0f - 20.0f; break; |
---|
293 | default: |
---|
294 | val2 = GetStat(STAT_STRENGTH)*2.0f - 20.0f; break; |
---|
295 | } |
---|
296 | break; |
---|
297 | } |
---|
298 | case CLASS_MAGE: val2 = GetStat(STAT_STRENGTH) - 10.0f; break; |
---|
299 | case CLASS_PRIEST: val2 = GetStat(STAT_STRENGTH) - 10.0f; break; |
---|
300 | case CLASS_WARLOCK: val2 = GetStat(STAT_STRENGTH) - 10.0f; break; |
---|
301 | } |
---|
302 | } |
---|
303 | |
---|
304 | SetModifierValue(unitMod, BASE_VALUE, val2); |
---|
305 | |
---|
306 | float base_attPower = GetModifierValue(unitMod, BASE_VALUE) * GetModifierValue(unitMod, BASE_PCT); |
---|
307 | float attPowerMod = GetModifierValue(unitMod, TOTAL_VALUE); |
---|
308 | |
---|
309 | //add dynamic flat mods |
---|
310 | if( ranged && (getClassMask() & CLASSMASK_WAND_USERS)==0) |
---|
311 | { |
---|
312 | AuraList const& mRAPbyIntellect = GetAurasByType(SPELL_AURA_MOD_RANGED_ATTACK_POWER_OF_STAT_PERCENT); |
---|
313 | for(AuraList::const_iterator i = mRAPbyIntellect.begin();i != mRAPbyIntellect.end(); ++i) |
---|
314 | attPowerMod += int32(GetStat(Stats((*i)->GetModifier()->m_miscvalue)) * (*i)->GetModifier()->m_amount / 100.0f); |
---|
315 | } |
---|
316 | |
---|
317 | float attPowerMultiplier = GetModifierValue(unitMod, TOTAL_PCT) - 1.0f; |
---|
318 | |
---|
319 | SetUInt32Value(index, (uint32)base_attPower); //UNIT_FIELD_(RANGED)_ATTACK_POWER field |
---|
320 | SetUInt32Value(index_mod, (uint32)attPowerMod); //UNIT_FIELD_(RANGED)_ATTACK_POWER_MODS field |
---|
321 | SetFloatValue(index_mult, attPowerMultiplier); //UNIT_FIELD_(RANGED)_ATTACK_POWER_MULTIPLIER field |
---|
322 | |
---|
323 | //automatically update weapon damage after attack power modification |
---|
324 | if(ranged) |
---|
325 | { |
---|
326 | UpdateDamagePhysical(RANGED_ATTACK); |
---|
327 | |
---|
328 | Pet *pet = GetPet(); //update pet's AP |
---|
329 | if(pet) |
---|
330 | pet->UpdateAttackPowerAndDamage(); |
---|
331 | } |
---|
332 | else |
---|
333 | { |
---|
334 | UpdateDamagePhysical(BASE_ATTACK); |
---|
335 | if(CanDualWield() && haveOffhandWeapon()) //allow update offhand damage only if player knows DualWield Spec and has equipped offhand weapon |
---|
336 | UpdateDamagePhysical(OFF_ATTACK); |
---|
337 | } |
---|
338 | } |
---|
339 | |
---|
340 | void Player::UpdateShieldBlockValue() |
---|
341 | { |
---|
342 | SetUInt32Value(PLAYER_SHIELD_BLOCK, GetShieldBlockValue()); |
---|
343 | } |
---|
344 | |
---|
345 | void Player::CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, float& min_damage, float& max_damage) |
---|
346 | { |
---|
347 | UnitMods unitMod; |
---|
348 | UnitMods attPower; |
---|
349 | |
---|
350 | switch(attType) |
---|
351 | { |
---|
352 | case BASE_ATTACK: |
---|
353 | default: |
---|
354 | unitMod = UNIT_MOD_DAMAGE_MAINHAND; |
---|
355 | attPower = UNIT_MOD_ATTACK_POWER; |
---|
356 | break; |
---|
357 | case OFF_ATTACK: |
---|
358 | unitMod = UNIT_MOD_DAMAGE_OFFHAND; |
---|
359 | attPower = UNIT_MOD_ATTACK_POWER; |
---|
360 | break; |
---|
361 | case RANGED_ATTACK: |
---|
362 | unitMod = UNIT_MOD_DAMAGE_RANGED; |
---|
363 | attPower = UNIT_MOD_ATTACK_POWER_RANGED; |
---|
364 | break; |
---|
365 | } |
---|
366 | |
---|
367 | float att_speed = GetAPMultiplier(attType,normalized); |
---|
368 | |
---|
369 | float base_value = GetModifierValue(unitMod, BASE_VALUE) + GetTotalAttackPowerValue(attType)/ 14.0f * att_speed; |
---|
370 | float base_pct = GetModifierValue(unitMod, BASE_PCT); |
---|
371 | float total_value = GetModifierValue(unitMod, TOTAL_VALUE); |
---|
372 | float total_pct = GetModifierValue(unitMod, TOTAL_PCT); |
---|
373 | |
---|
374 | float weapon_mindamage = GetWeaponDamageRange(attType, MINDAMAGE); |
---|
375 | float weapon_maxdamage = GetWeaponDamageRange(attType, MAXDAMAGE); |
---|
376 | |
---|
377 | if (IsInFeralForm()) //check if player is druid and in cat or bear forms |
---|
378 | { |
---|
379 | uint32 lvl = getLevel(); |
---|
380 | if ( lvl > 60 ) lvl = 60; |
---|
381 | |
---|
382 | weapon_mindamage = lvl*0.85*att_speed; |
---|
383 | weapon_maxdamage = lvl*1.25*att_speed; |
---|
384 | } |
---|
385 | else if(!IsUseEquipedWeapon(attType==BASE_ATTACK)) //check if player not in form but still can't use weapon (broken/etc) |
---|
386 | { |
---|
387 | weapon_mindamage = BASE_MINDAMAGE; |
---|
388 | weapon_maxdamage = BASE_MAXDAMAGE; |
---|
389 | } |
---|
390 | else if(attType == RANGED_ATTACK) //add ammo DPS to ranged damage |
---|
391 | { |
---|
392 | weapon_mindamage += GetAmmoDPS() * att_speed; |
---|
393 | weapon_maxdamage += GetAmmoDPS() * att_speed; |
---|
394 | } |
---|
395 | |
---|
396 | min_damage = ((base_value + weapon_mindamage) * base_pct + total_value) * total_pct; |
---|
397 | max_damage = ((base_value + weapon_maxdamage) * base_pct + total_value) * total_pct; |
---|
398 | } |
---|
399 | |
---|
400 | void Player::UpdateDamagePhysical(WeaponAttackType attType) |
---|
401 | { |
---|
402 | float mindamage; |
---|
403 | float maxdamage; |
---|
404 | |
---|
405 | CalculateMinMaxDamage(attType,false,mindamage,maxdamage); |
---|
406 | |
---|
407 | switch(attType) |
---|
408 | { |
---|
409 | case BASE_ATTACK: |
---|
410 | default: |
---|
411 | SetStatFloatValue(UNIT_FIELD_MINDAMAGE,mindamage); |
---|
412 | SetStatFloatValue(UNIT_FIELD_MAXDAMAGE,maxdamage); |
---|
413 | break; |
---|
414 | case OFF_ATTACK: |
---|
415 | SetStatFloatValue(UNIT_FIELD_MINOFFHANDDAMAGE,mindamage); |
---|
416 | SetStatFloatValue(UNIT_FIELD_MAXOFFHANDDAMAGE,maxdamage); |
---|
417 | break; |
---|
418 | case RANGED_ATTACK: |
---|
419 | SetStatFloatValue(UNIT_FIELD_MINRANGEDDAMAGE,mindamage); |
---|
420 | SetStatFloatValue(UNIT_FIELD_MAXRANGEDDAMAGE,maxdamage); |
---|
421 | break; |
---|
422 | } |
---|
423 | } |
---|
424 | |
---|
425 | void Player::UpdateDefenseBonusesMod() |
---|
426 | { |
---|
427 | UpdateBlockPercentage(); |
---|
428 | UpdateParryPercentage(); |
---|
429 | UpdateDodgePercentage(); |
---|
430 | } |
---|
431 | |
---|
432 | void Player::UpdateBlockPercentage() |
---|
433 | { |
---|
434 | // No block |
---|
435 | float value = 0.0f; |
---|
436 | if(CanBlock()) |
---|
437 | { |
---|
438 | // Base value |
---|
439 | value = 5.0f; |
---|
440 | // Modify value from defense skill |
---|
441 | value += (int32(GetDefenseSkillValue()) - int32(GetMaxSkillValueForLevel())) * 0.04f; |
---|
442 | // Increase from SPELL_AURA_MOD_BLOCK_PERCENT aura |
---|
443 | value += GetTotalAuraModifier(SPELL_AURA_MOD_BLOCK_PERCENT); |
---|
444 | // Increase from rating |
---|
445 | value += GetRatingBonusValue(CR_BLOCK); |
---|
446 | value = value < 0.0f ? 0.0f : value; |
---|
447 | } |
---|
448 | SetStatFloatValue(PLAYER_BLOCK_PERCENTAGE, value); |
---|
449 | } |
---|
450 | |
---|
451 | void Player::UpdateCritPercentage(WeaponAttackType attType) |
---|
452 | { |
---|
453 | BaseModGroup modGroup; |
---|
454 | uint16 index; |
---|
455 | CombatRating cr; |
---|
456 | |
---|
457 | switch(attType) |
---|
458 | { |
---|
459 | case OFF_ATTACK: |
---|
460 | modGroup = OFFHAND_CRIT_PERCENTAGE; |
---|
461 | index = PLAYER_OFFHAND_CRIT_PERCENTAGE; |
---|
462 | cr = CR_CRIT_MELEE; |
---|
463 | break; |
---|
464 | case RANGED_ATTACK: |
---|
465 | modGroup = RANGED_CRIT_PERCENTAGE; |
---|
466 | index = PLAYER_RANGED_CRIT_PERCENTAGE; |
---|
467 | cr = CR_CRIT_RANGED; |
---|
468 | break; |
---|
469 | case BASE_ATTACK: |
---|
470 | default: |
---|
471 | modGroup = CRIT_PERCENTAGE; |
---|
472 | index = PLAYER_CRIT_PERCENTAGE; |
---|
473 | cr = CR_CRIT_MELEE; |
---|
474 | break; |
---|
475 | } |
---|
476 | |
---|
477 | float value = GetTotalPercentageModValue(modGroup) + GetRatingBonusValue(cr); |
---|
478 | // Modify crit from weapon skill and maximized defense skill of same level victim difference |
---|
479 | value += (int32(GetWeaponSkillValue(attType)) - int32(GetMaxSkillValueForLevel())) * 0.04f; |
---|
480 | value = value < 0.0f ? 0.0f : value; |
---|
481 | SetStatFloatValue(index, value); |
---|
482 | } |
---|
483 | |
---|
484 | void Player::UpdateAllCritPercentages() |
---|
485 | { |
---|
486 | float value = GetMeleeCritFromAgility(); |
---|
487 | |
---|
488 | SetBaseModValue(CRIT_PERCENTAGE, PCT_MOD, value); |
---|
489 | SetBaseModValue(OFFHAND_CRIT_PERCENTAGE, PCT_MOD, value); |
---|
490 | SetBaseModValue(RANGED_CRIT_PERCENTAGE, PCT_MOD, value); |
---|
491 | |
---|
492 | UpdateCritPercentage(BASE_ATTACK); |
---|
493 | UpdateCritPercentage(OFF_ATTACK); |
---|
494 | UpdateCritPercentage(RANGED_ATTACK); |
---|
495 | } |
---|
496 | |
---|
497 | void Player::UpdateParryPercentage() |
---|
498 | { |
---|
499 | // No parry |
---|
500 | float value = 0.0f; |
---|
501 | if (CanParry()) |
---|
502 | { |
---|
503 | // Base parry |
---|
504 | value = 5.0f; |
---|
505 | // Modify value from defense skill |
---|
506 | value += (int32(GetDefenseSkillValue()) - int32(GetMaxSkillValueForLevel())) * 0.04f; |
---|
507 | // Parry from SPELL_AURA_MOD_PARRY_PERCENT aura |
---|
508 | value += GetTotalAuraModifier(SPELL_AURA_MOD_PARRY_PERCENT); |
---|
509 | // Parry from rating |
---|
510 | value += GetRatingBonusValue(CR_PARRY); |
---|
511 | value = value < 0.0f ? 0.0f : value; |
---|
512 | } |
---|
513 | SetStatFloatValue(PLAYER_PARRY_PERCENTAGE, value); |
---|
514 | } |
---|
515 | |
---|
516 | void Player::UpdateDodgePercentage() |
---|
517 | { |
---|
518 | // Dodge from agility |
---|
519 | float value = GetDodgeFromAgility(); |
---|
520 | // Modify value from defense skill |
---|
521 | value += (int32(GetDefenseSkillValue()) - int32(GetMaxSkillValueForLevel())) * 0.04f; |
---|
522 | // Dodge from SPELL_AURA_MOD_DODGE_PERCENT aura |
---|
523 | value += GetTotalAuraModifier(SPELL_AURA_MOD_DODGE_PERCENT); |
---|
524 | // Dodge from rating |
---|
525 | value += GetRatingBonusValue(CR_DODGE); |
---|
526 | value = value < 0.0f ? 0.0f : value; |
---|
527 | SetStatFloatValue(PLAYER_DODGE_PERCENTAGE, value); |
---|
528 | } |
---|
529 | |
---|
530 | void Player::UpdateSpellCritChance(uint32 school) |
---|
531 | { |
---|
532 | // For normal school set zero crit chance |
---|
533 | if(school == SPELL_SCHOOL_NORMAL) |
---|
534 | { |
---|
535 | SetFloatValue(PLAYER_SPELL_CRIT_PERCENTAGE1, 0.0f); |
---|
536 | return; |
---|
537 | } |
---|
538 | // For others recalculate it from: |
---|
539 | float crit = 0.0f; |
---|
540 | // Crit from Intellect |
---|
541 | crit += GetSpellCritFromIntellect(); |
---|
542 | // Increase crit from SPELL_AURA_MOD_SPELL_CRIT_CHANCE |
---|
543 | crit += GetTotalAuraModifier(SPELL_AURA_MOD_SPELL_CRIT_CHANCE); |
---|
544 | // Increase crit by school from SPELL_AURA_MOD_SPELL_CRIT_CHANCE_SCHOOL |
---|
545 | crit += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_SPELL_CRIT_CHANCE_SCHOOL, 1<<school); |
---|
546 | // Increase crit from spell crit ratings |
---|
547 | crit += GetRatingBonusValue(CR_CRIT_SPELL); |
---|
548 | |
---|
549 | // Store crit value |
---|
550 | SetFloatValue(PLAYER_SPELL_CRIT_PERCENTAGE1 + school, crit); |
---|
551 | } |
---|
552 | |
---|
553 | void Player::UpdateAllSpellCritChances() |
---|
554 | { |
---|
555 | for (int i = SPELL_SCHOOL_NORMAL; i < MAX_SPELL_SCHOOL; i++) |
---|
556 | UpdateSpellCritChance(i); |
---|
557 | } |
---|
558 | |
---|
559 | void Player::UpdateExpertise(WeaponAttackType attack) |
---|
560 | { |
---|
561 | if(attack==RANGED_ATTACK) |
---|
562 | return; |
---|
563 | |
---|
564 | int32 expertise = int32(GetRatingBonusValue(CR_EXPERTISE)); |
---|
565 | |
---|
566 | Item *weapon = GetWeaponForAttack(attack); |
---|
567 | |
---|
568 | AuraList const& expAuras = GetAurasByType(SPELL_AURA_MOD_EXPERTISE); |
---|
569 | for(AuraList::const_iterator itr = expAuras.begin(); itr != expAuras.end(); ++itr) |
---|
570 | { |
---|
571 | // item neutral spell |
---|
572 | if((*itr)->GetSpellProto()->EquippedItemClass == -1) |
---|
573 | expertise += (*itr)->GetModifier()->m_amount; |
---|
574 | // item dependent spell |
---|
575 | else if(weapon && weapon->IsFitToSpellRequirements((*itr)->GetSpellProto())) |
---|
576 | expertise += (*itr)->GetModifier()->m_amount; |
---|
577 | } |
---|
578 | |
---|
579 | if(expertise < 0) |
---|
580 | expertise = 0; |
---|
581 | |
---|
582 | switch(attack) |
---|
583 | { |
---|
584 | case BASE_ATTACK: SetUInt32Value(PLAYER_EXPERTISE, expertise); break; |
---|
585 | case OFF_ATTACK: SetUInt32Value(PLAYER_OFFHAND_EXPERTISE, expertise); break; |
---|
586 | default: break; |
---|
587 | } |
---|
588 | } |
---|
589 | |
---|
590 | void Player::UpdateManaRegen() |
---|
591 | { |
---|
592 | float Intellect = GetStat(STAT_INTELLECT); |
---|
593 | // Mana regen from spirit and intellect |
---|
594 | float power_regen = sqrt(Intellect) * OCTRegenMPPerSpirit(); |
---|
595 | // Apply PCT bonus from SPELL_AURA_MOD_POWER_REGEN_PERCENT aura on spirit base regen |
---|
596 | power_regen *= GetTotalAuraMultiplierByMiscValue(SPELL_AURA_MOD_POWER_REGEN_PERCENT, POWER_MANA); |
---|
597 | |
---|
598 | // Mana regen from SPELL_AURA_MOD_POWER_REGEN aura |
---|
599 | float power_regen_mp5 = GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_POWER_REGEN, POWER_MANA) / 5.0f; |
---|
600 | |
---|
601 | // Get bonus from SPELL_AURA_MOD_MANA_REGEN_FROM_STAT aura |
---|
602 | AuraList const& regenAura = GetAurasByType(SPELL_AURA_MOD_MANA_REGEN_FROM_STAT); |
---|
603 | for(AuraList::const_iterator i = regenAura.begin();i != regenAura.end(); ++i) |
---|
604 | { |
---|
605 | Modifier* mod = (*i)->GetModifier(); |
---|
606 | power_regen_mp5 += GetStat(Stats(mod->m_miscvalue)) * mod->m_amount / 500.0f; |
---|
607 | } |
---|
608 | |
---|
609 | // Bonus from some dummy auras |
---|
610 | AuraList const& mDummyAuras = GetAurasByType(SPELL_AURA_PERIODIC_DUMMY); |
---|
611 | for(AuraList::const_iterator i = mDummyAuras.begin();i != mDummyAuras.end(); ++i) |
---|
612 | if((*i)->GetId() == 34074) // Aspect of the Viper |
---|
613 | { |
---|
614 | power_regen_mp5 += (*i)->GetModifier()->m_amount * Intellect / 500.0f; |
---|
615 | // Add regen bonus from level in this dummy |
---|
616 | power_regen_mp5 += getLevel() * 35 / 100; |
---|
617 | } |
---|
618 | |
---|
619 | // Set regen rate in cast state apply only on spirit based regen |
---|
620 | int32 modManaRegenInterrupt = GetTotalAuraModifier(SPELL_AURA_MOD_MANA_REGEN_INTERRUPT); |
---|
621 | if (modManaRegenInterrupt > 100) |
---|
622 | modManaRegenInterrupt = 100; |
---|
623 | SetStatFloatValue(PLAYER_FIELD_MOD_MANA_REGEN_INTERRUPT, power_regen_mp5 + power_regen * modManaRegenInterrupt / 100.0f); |
---|
624 | |
---|
625 | SetStatFloatValue(PLAYER_FIELD_MOD_MANA_REGEN, power_regen_mp5 + power_regen); |
---|
626 | } |
---|
627 | |
---|
628 | void Player::_ApplyAllStatBonuses() |
---|
629 | { |
---|
630 | SetCanModifyStats(false); |
---|
631 | |
---|
632 | _ApplyAllAuraMods(); |
---|
633 | _ApplyAllItemMods(); |
---|
634 | |
---|
635 | SetCanModifyStats(true); |
---|
636 | |
---|
637 | UpdateAllStats(); |
---|
638 | } |
---|
639 | |
---|
640 | void Player::_RemoveAllStatBonuses() |
---|
641 | { |
---|
642 | SetCanModifyStats(false); |
---|
643 | |
---|
644 | _RemoveAllItemMods(); |
---|
645 | _RemoveAllAuraMods(); |
---|
646 | |
---|
647 | SetCanModifyStats(true); |
---|
648 | |
---|
649 | UpdateAllStats(); |
---|
650 | } |
---|
651 | |
---|
652 | /*####################################### |
---|
653 | ######## ######## |
---|
654 | ######## MOBS STAT SYSTEM ######## |
---|
655 | ######## ######## |
---|
656 | #######################################*/ |
---|
657 | |
---|
658 | bool Creature::UpdateStats(Stats /*stat*/) |
---|
659 | { |
---|
660 | return true; |
---|
661 | } |
---|
662 | |
---|
663 | bool Creature::UpdateAllStats() |
---|
664 | { |
---|
665 | UpdateMaxHealth(); |
---|
666 | UpdateAttackPowerAndDamage(); |
---|
667 | |
---|
668 | for(int i = POWER_MANA; i < MAX_POWERS; ++i) |
---|
669 | UpdateMaxPower(Powers(i)); |
---|
670 | |
---|
671 | for(int i = SPELL_SCHOOL_NORMAL; i < MAX_SPELL_SCHOOL; ++i) |
---|
672 | UpdateResistances(i); |
---|
673 | |
---|
674 | return true; |
---|
675 | } |
---|
676 | |
---|
677 | void Creature::UpdateResistances(uint32 school) |
---|
678 | { |
---|
679 | if(school > SPELL_SCHOOL_NORMAL) |
---|
680 | { |
---|
681 | float value = GetTotalAuraModValue(UnitMods(UNIT_MOD_RESISTANCE_START + school)); |
---|
682 | SetResistance(SpellSchools(school), int32(value)); |
---|
683 | } |
---|
684 | else |
---|
685 | UpdateArmor(); |
---|
686 | } |
---|
687 | |
---|
688 | void Creature::UpdateArmor() |
---|
689 | { |
---|
690 | float value = GetTotalAuraModValue(UNIT_MOD_ARMOR); |
---|
691 | SetArmor(int32(value)); |
---|
692 | } |
---|
693 | |
---|
694 | void Creature::UpdateMaxHealth() |
---|
695 | { |
---|
696 | float value = GetTotalAuraModValue(UNIT_MOD_HEALTH); |
---|
697 | SetMaxHealth((uint32)value); |
---|
698 | } |
---|
699 | |
---|
700 | void Creature::UpdateMaxPower(Powers power) |
---|
701 | { |
---|
702 | UnitMods unitMod = UnitMods(UNIT_MOD_POWER_START + power); |
---|
703 | |
---|
704 | float value = GetTotalAuraModValue(unitMod); |
---|
705 | SetMaxPower(power, uint32(value)); |
---|
706 | } |
---|
707 | |
---|
708 | void Creature::UpdateAttackPowerAndDamage(bool ranged) |
---|
709 | { |
---|
710 | if(ranged) |
---|
711 | return; |
---|
712 | |
---|
713 | //automatically update weapon damage after attack power modification |
---|
714 | UpdateDamagePhysical(BASE_ATTACK); |
---|
715 | } |
---|
716 | |
---|
717 | void Creature::UpdateDamagePhysical(WeaponAttackType attType) |
---|
718 | { |
---|
719 | if(attType > BASE_ATTACK) |
---|
720 | return; |
---|
721 | |
---|
722 | UnitMods unitMod = UNIT_MOD_DAMAGE_MAINHAND; |
---|
723 | |
---|
724 | float att_speed = float(GetAttackTime(BASE_ATTACK))/1000.0f; |
---|
725 | |
---|
726 | float base_value = GetModifierValue(unitMod, BASE_VALUE) + GetTotalAttackPowerValue(attType)/ 14.0f * att_speed; |
---|
727 | float base_pct = GetModifierValue(unitMod, BASE_PCT); |
---|
728 | float total_value = GetModifierValue(unitMod, TOTAL_VALUE); |
---|
729 | float total_pct = GetModifierValue(unitMod, TOTAL_PCT); |
---|
730 | |
---|
731 | float weapon_mindamage = GetWeaponDamageRange(BASE_ATTACK, MINDAMAGE); |
---|
732 | float weapon_maxdamage = GetWeaponDamageRange(BASE_ATTACK, MAXDAMAGE); |
---|
733 | |
---|
734 | float mindamage = ((base_value + weapon_mindamage) * base_pct + total_value) * total_pct ; |
---|
735 | float maxdamage = ((base_value + weapon_maxdamage) * base_pct + total_value) * total_pct ; |
---|
736 | |
---|
737 | SetStatFloatValue(UNIT_FIELD_MINDAMAGE, mindamage); |
---|
738 | SetStatFloatValue(UNIT_FIELD_MAXDAMAGE, maxdamage); |
---|
739 | } |
---|
740 | |
---|
741 | /*####################################### |
---|
742 | ######## ######## |
---|
743 | ######## PETS STAT SYSTEM ######## |
---|
744 | ######## ######## |
---|
745 | #######################################*/ |
---|
746 | |
---|
747 | bool Pet::UpdateStats(Stats stat) |
---|
748 | { |
---|
749 | if(stat > STAT_SPIRIT) |
---|
750 | return false; |
---|
751 | |
---|
752 | // value = ((base_value * base_pct) + total_value) * total_pct |
---|
753 | float value = GetTotalStatValue(stat); |
---|
754 | |
---|
755 | Unit *owner = GetOwner(); |
---|
756 | if ( stat == STAT_STAMINA ) |
---|
757 | { |
---|
758 | if(owner) |
---|
759 | value += float(owner->GetStat(stat)) * 0.3f; |
---|
760 | } |
---|
761 | //warlock's and mage's pets gain 30% of owner's intellect |
---|
762 | else if ( stat == STAT_INTELLECT && getPetType() == SUMMON_PET ) |
---|
763 | { |
---|
764 | if(owner && (owner->getClass() == CLASS_WARLOCK || owner->getClass() == CLASS_MAGE) ) |
---|
765 | value += float(owner->GetStat(stat)) * 0.3f; |
---|
766 | } |
---|
767 | |
---|
768 | SetStat(stat, int32(value)); |
---|
769 | |
---|
770 | switch(stat) |
---|
771 | { |
---|
772 | case STAT_STRENGTH: UpdateAttackPowerAndDamage(); break; |
---|
773 | case STAT_AGILITY: UpdateArmor(); break; |
---|
774 | case STAT_STAMINA: UpdateMaxHealth(); break; |
---|
775 | case STAT_INTELLECT: UpdateMaxPower(POWER_MANA); break; |
---|
776 | case STAT_SPIRIT: |
---|
777 | default: |
---|
778 | break; |
---|
779 | } |
---|
780 | |
---|
781 | return true; |
---|
782 | } |
---|
783 | |
---|
784 | bool Pet::UpdateAllStats() |
---|
785 | { |
---|
786 | for (int i = STAT_STRENGTH; i < MAX_STATS; i++) |
---|
787 | UpdateStats(Stats(i)); |
---|
788 | |
---|
789 | for(int i = POWER_MANA; i < MAX_POWERS; i++) |
---|
790 | UpdateMaxPower(Powers(i)); |
---|
791 | |
---|
792 | for (int i = SPELL_SCHOOL_NORMAL; i < MAX_SPELL_SCHOOL; i++) |
---|
793 | UpdateResistances(i); |
---|
794 | |
---|
795 | return true; |
---|
796 | } |
---|
797 | |
---|
798 | void Pet::UpdateResistances(uint32 school) |
---|
799 | { |
---|
800 | if(school > SPELL_SCHOOL_NORMAL) |
---|
801 | { |
---|
802 | float value = GetTotalAuraModValue(UnitMods(UNIT_MOD_RESISTANCE_START + school)); |
---|
803 | |
---|
804 | Unit *owner = GetOwner(); |
---|
805 | // hunter and warlock pets gain 40% of owner's resistance |
---|
806 | if(owner && (getPetType() == HUNTER_PET || getPetType() == SUMMON_PET && owner->getClass() == CLASS_WARLOCK)) |
---|
807 | value += float(owner->GetResistance(SpellSchools(school))) * 0.4f; |
---|
808 | |
---|
809 | SetResistance(SpellSchools(school), int32(value)); |
---|
810 | } |
---|
811 | else |
---|
812 | UpdateArmor(); |
---|
813 | } |
---|
814 | |
---|
815 | void Pet::UpdateArmor() |
---|
816 | { |
---|
817 | float value = 0.0f; |
---|
818 | float bonus_armor = 0.0f; |
---|
819 | UnitMods unitMod = UNIT_MOD_ARMOR; |
---|
820 | |
---|
821 | Unit *owner = GetOwner(); |
---|
822 | // hunter and warlock pets gain 35% of owner's armor value |
---|
823 | if(owner && (getPetType() == HUNTER_PET || getPetType() == SUMMON_PET && owner->getClass() == CLASS_WARLOCK)) |
---|
824 | bonus_armor = 0.35f * float(owner->GetArmor()); |
---|
825 | |
---|
826 | value = GetModifierValue(unitMod, BASE_VALUE); |
---|
827 | value *= GetModifierValue(unitMod, BASE_PCT); |
---|
828 | value += GetStat(STAT_AGILITY) * 2.0f; |
---|
829 | value += GetModifierValue(unitMod, TOTAL_VALUE) + bonus_armor; |
---|
830 | value *= GetModifierValue(unitMod, TOTAL_PCT); |
---|
831 | |
---|
832 | SetArmor(int32(value)); |
---|
833 | } |
---|
834 | |
---|
835 | void Pet::UpdateMaxHealth() |
---|
836 | { |
---|
837 | UnitMods unitMod = UNIT_MOD_HEALTH; |
---|
838 | float stamina = GetStat(STAT_STAMINA) - GetCreateStat(STAT_STAMINA); |
---|
839 | |
---|
840 | float value = GetModifierValue(unitMod, BASE_VALUE) + GetCreateHealth(); |
---|
841 | value *= GetModifierValue(unitMod, BASE_PCT); |
---|
842 | value += GetModifierValue(unitMod, TOTAL_VALUE) + stamina * 10.0f; |
---|
843 | value *= GetModifierValue(unitMod, TOTAL_PCT); |
---|
844 | |
---|
845 | SetMaxHealth((uint32)value); |
---|
846 | } |
---|
847 | |
---|
848 | void Pet::UpdateMaxPower(Powers power) |
---|
849 | { |
---|
850 | UnitMods unitMod = UnitMods(UNIT_MOD_POWER_START + power); |
---|
851 | float addValue = (power == POWER_MANA) ? GetStat(STAT_INTELLECT) - GetCreateStat(STAT_INTELLECT) : 0.0f; |
---|
852 | |
---|
853 | float value = GetModifierValue(unitMod, BASE_VALUE) + GetCreatePowers(power); |
---|
854 | value *= GetModifierValue(unitMod, BASE_PCT); |
---|
855 | value += GetModifierValue(unitMod, TOTAL_VALUE) + addValue * 15.0f; |
---|
856 | value *= GetModifierValue(unitMod, TOTAL_PCT); |
---|
857 | |
---|
858 | SetMaxPower(power, uint32(value)); |
---|
859 | } |
---|
860 | |
---|
861 | void Pet::UpdateAttackPowerAndDamage(bool ranged) |
---|
862 | { |
---|
863 | if(ranged) |
---|
864 | return; |
---|
865 | |
---|
866 | float val = 0.0f; |
---|
867 | float bonusAP = 0.0f; |
---|
868 | UnitMods unitMod = UNIT_MOD_ATTACK_POWER; |
---|
869 | |
---|
870 | if(GetEntry() == 416) // imp's attack power |
---|
871 | val = GetStat(STAT_STRENGTH) - 10.0f; |
---|
872 | else |
---|
873 | val = 2 * GetStat(STAT_STRENGTH) - 20.0f; |
---|
874 | |
---|
875 | Unit* owner = GetOwner(); |
---|
876 | if( owner && owner->GetTypeId()==TYPEID_PLAYER) |
---|
877 | { |
---|
878 | if(getPetType() == HUNTER_PET) //hunter pets benefit from owner's attack power |
---|
879 | { |
---|
880 | bonusAP = owner->GetTotalAttackPowerValue(RANGED_ATTACK) * 0.22f; |
---|
881 | SetBonusDamage( int32(owner->GetTotalAttackPowerValue(RANGED_ATTACK) * 0.125f)); |
---|
882 | } |
---|
883 | //demons benefit from warlocks shadow or fire damage |
---|
884 | else if(getPetType() == SUMMON_PET && owner->getClass() == CLASS_WARLOCK) |
---|
885 | { |
---|
886 | int32 fire = int32(owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + SPELL_SCHOOL_FIRE)) - owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG + SPELL_SCHOOL_FIRE); |
---|
887 | int32 shadow = int32(owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + SPELL_SCHOOL_SHADOW)) - owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG + SPELL_SCHOOL_SHADOW); |
---|
888 | int32 maximum = (fire > shadow) ? fire : shadow; |
---|
889 | if(maximum < 0) |
---|
890 | maximum = 0; |
---|
891 | SetBonusDamage( int32(maximum * 0.15f)); |
---|
892 | bonusAP = maximum * 0.57f; |
---|
893 | } |
---|
894 | //water elementals benefit from mage's frost damage |
---|
895 | else if(getPetType() == SUMMON_PET && owner->getClass() == CLASS_MAGE) |
---|
896 | { |
---|
897 | int32 frost = int32(owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + SPELL_SCHOOL_FROST)) - owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG + SPELL_SCHOOL_FROST); |
---|
898 | if(frost < 0) |
---|
899 | frost = 0; |
---|
900 | SetBonusDamage( int32(frost * 0.4f)); |
---|
901 | } |
---|
902 | } |
---|
903 | |
---|
904 | SetModifierValue(UNIT_MOD_ATTACK_POWER, BASE_VALUE, val + bonusAP); |
---|
905 | |
---|
906 | //in BASE_VALUE of UNIT_MOD_ATTACK_POWER for creatures we store data of meleeattackpower field in DB |
---|
907 | float base_attPower = GetModifierValue(unitMod, BASE_VALUE) * GetModifierValue(unitMod, BASE_PCT); |
---|
908 | float attPowerMod = GetModifierValue(unitMod, TOTAL_VALUE); |
---|
909 | float attPowerMultiplier = GetModifierValue(unitMod, TOTAL_PCT) - 1.0f; |
---|
910 | |
---|
911 | //UNIT_FIELD_(RANGED)_ATTACK_POWER field |
---|
912 | SetUInt32Value(UNIT_FIELD_ATTACK_POWER, (uint32)base_attPower); |
---|
913 | //UNIT_FIELD_(RANGED)_ATTACK_POWER_MODS field |
---|
914 | SetUInt32Value(UNIT_FIELD_ATTACK_POWER_MODS, (uint32)attPowerMod); |
---|
915 | //UNIT_FIELD_(RANGED)_ATTACK_POWER_MULTIPLIER field |
---|
916 | SetFloatValue(UNIT_FIELD_ATTACK_POWER_MULTIPLIER, attPowerMultiplier); |
---|
917 | |
---|
918 | //automatically update weapon damage after attack power modification |
---|
919 | UpdateDamagePhysical(BASE_ATTACK); |
---|
920 | } |
---|
921 | |
---|
922 | void Pet::UpdateDamagePhysical(WeaponAttackType attType) |
---|
923 | { |
---|
924 | if(attType > BASE_ATTACK) |
---|
925 | return; |
---|
926 | |
---|
927 | UnitMods unitMod = UNIT_MOD_DAMAGE_MAINHAND; |
---|
928 | |
---|
929 | float att_speed = float(GetAttackTime(BASE_ATTACK))/1000.0f; |
---|
930 | |
---|
931 | float base_value = GetModifierValue(unitMod, BASE_VALUE) + GetTotalAttackPowerValue(attType)/ 14.0f * att_speed; |
---|
932 | float base_pct = GetModifierValue(unitMod, BASE_PCT); |
---|
933 | float total_value = GetModifierValue(unitMod, TOTAL_VALUE); |
---|
934 | float total_pct = GetModifierValue(unitMod, TOTAL_PCT); |
---|
935 | |
---|
936 | float weapon_mindamage = GetWeaponDamageRange(BASE_ATTACK, MINDAMAGE); |
---|
937 | float weapon_maxdamage = GetWeaponDamageRange(BASE_ATTACK, MAXDAMAGE); |
---|
938 | |
---|
939 | float mindamage = ((base_value + weapon_mindamage) * base_pct + total_value) * total_pct; |
---|
940 | float maxdamage = ((base_value + weapon_maxdamage) * base_pct + total_value) * total_pct; |
---|
941 | |
---|
942 | // Pet's base damage changes depending on happiness |
---|
943 | if (getPetType() == HUNTER_PET && attType == BASE_ATTACK) |
---|
944 | { |
---|
945 | switch(GetHappinessState()) |
---|
946 | { |
---|
947 | case HAPPY: |
---|
948 | // 125% of normal damage |
---|
949 | mindamage = mindamage * 1.25; |
---|
950 | maxdamage = maxdamage * 1.25; |
---|
951 | break; |
---|
952 | case CONTENT: |
---|
953 | // 100% of normal damage, nothing to modify |
---|
954 | break; |
---|
955 | case UNHAPPY: |
---|
956 | // 75% of normal damage |
---|
957 | mindamage = mindamage * 0.75; |
---|
958 | maxdamage = maxdamage * 0.75; |
---|
959 | break; |
---|
960 | } |
---|
961 | } |
---|
962 | |
---|
963 | SetStatFloatValue(UNIT_FIELD_MINDAMAGE, mindamage); |
---|
964 | SetStatFloatValue(UNIT_FIELD_MAXDAMAGE, maxdamage); |
---|
965 | } |
---|