Advertisement
Guest User

Untitled

a guest
Jun 14th, 2011
1,404
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 34.97 KB | None | 0 0
  1. # HG changeset patch
  2. # User Riname <riname@laposte.net>
  3. # Date 1308076198 -7200
  4. # Branch Enhanced Edition // Feriale
  5. # Node ID f38058f568e468d6247de26b96db47dbba619d8b
  6. # Parent f0ba6a0deaa4e455736bff9d141107a83f85e4b6
  7. Enhanced Edition // Feriale: Try to fix Spell penetration and Binary resistance
  8.  
  9. diff -r f0ba6a0deaa4 -r f38058f568e4 src/server/game/Entities/GameObject/GameObject.cpp
  10. --- a/src/server/game/Entities/GameObject/GameObject.cpp Mon Jun 13 20:21:50 2011 +0200
  11. +++ b/src/server/game/Entities/GameObject/GameObject.cpp Tue Jun 14 20:29:58 2011 +0200
  12. @@ -1668,11 +1668,13 @@
  13. if (Unit* owner = GetOwner())
  14. {
  15. trigger->setFaction(owner->getFaction());
  16. + trigger->SetLevel(owner->getLevel());
  17. trigger->CastSpell(target ? target : trigger, spellInfo, true, 0, 0, owner->GetGUID());
  18. }
  19. else
  20. {
  21. trigger->setFaction(14);
  22. + trigger->SetLevel(target ? target->getLevel() : 255);
  23. // Set owner guid for target if no owner avalible - needed by trigger auras
  24. // - trigger gets despawned and there's no caster avalible (see AuraEffect::TriggerSpell())
  25. trigger->CastSpell(target ? target : trigger, spellInfo, true, 0, 0, target ? target->GetGUID() : 0);
  26. diff -r f0ba6a0deaa4 -r f38058f568e4 src/server/game/Entities/Player/Player.cpp
  27. --- a/src/server/game/Entities/Player/Player.cpp Mon Jun 13 20:21:50 2011 +0200
  28. +++ b/src/server/game/Entities/Player/Player.cpp Tue Jun 14 20:29:58 2011 +0200
  29. @@ -8088,9 +8088,8 @@
  30. case ITEM_MOD_HEALTH_REGEN:
  31. ApplyHealthRegenBonus(int32(val), apply);
  32. break;
  33. - case ITEM_MOD_SPELL_PENETRATION:
  34. - ApplyModInt32Value(PLAYER_FIELD_MOD_TARGET_RESISTANCE, -val, apply);
  35. - m_spellPenetrationItemMod += apply ? val : -val;
  36. + case ITEM_MOD_SPELL_PENETRATION:
  37. + ApplySpellPenetrationBonus(int32(val), apply);
  38. break;
  39. // deprecated item mods
  40. case ITEM_MOD_SPELL_HEALING_DONE:
  41. @@ -14069,8 +14068,7 @@
  42. sLog->outDebug(LOG_FILTER_PLAYER_ITEMS, "+ %u HEALTH_REGENERATION", enchant_amount);
  43. break;
  44. case ITEM_MOD_SPELL_PENETRATION:
  45. - ApplyModInt32Value(PLAYER_FIELD_MOD_TARGET_RESISTANCE, enchant_amount, apply);
  46. - m_spellPenetrationItemMod += apply ? int32(enchant_amount) : -int32(enchant_amount);
  47. + ApplySpellPenetrationBonus(enchant_amount, apply);
  48. sLog->outDebug(LOG_FILTER_PLAYER_ITEMS, "+ %u SPELL_PENETRATION", enchant_amount);
  49. break;
  50. case ITEM_MOD_BLOCK_VALUE:
  51. diff -r f0ba6a0deaa4 -r f38058f568e4 src/server/game/Entities/Player/Player.h
  52. --- a/src/server/game/Entities/Player/Player.h Mon Jun 13 20:21:50 2011 +0200
  53. +++ b/src/server/game/Entities/Player/Player.h Tue Jun 14 20:29:58 2011 +0200
  54. @@ -1877,6 +1877,7 @@
  55.  
  56. bool UpdateStats(Stats stat);
  57. bool UpdateAllStats();
  58. + void ApplySpellPenetrationBonus(int32 amount, bool apply);
  59. void UpdateResistances(uint32 school);
  60. void UpdateArmor();
  61. void UpdateMaxHealth();
  62. @@ -1902,7 +1903,7 @@
  63. float OCTRegenMPPerSpirit();
  64. float GetRatingMultiplier(CombatRating cr) const;
  65. float GetRatingBonusValue(CombatRating cr) const;
  66. - uint32 GetBaseSpellPowerBonus() { return m_baseSpellPower; }
  67. + uint32 GetBaseSpellPowerBonus() const { return m_baseSpellPower; }
  68. int32 GetSpellPenetrationItemMod() const { return m_spellPenetrationItemMod; }
  69.  
  70. float GetExpertiseDodgeOrParryReduction(WeaponAttackType attType) const;
  71. diff -r f0ba6a0deaa4 -r f38058f568e4 src/server/game/Entities/Unit/StatSystem.cpp
  72. --- a/src/server/game/Entities/Unit/StatSystem.cpp Mon Jun 13 20:21:50 2011 +0200
  73. +++ b/src/server/game/Entities/Unit/StatSystem.cpp Tue Jun 14 20:29:58 2011 +0200
  74. @@ -176,6 +176,12 @@
  75. return true;
  76. }
  77.  
  78. +void Player::ApplySpellPenetrationBonus(int32 amount, bool apply)
  79. +{
  80. + ApplyModInt32Value(PLAYER_FIELD_MOD_TARGET_RESISTANCE, -amount, apply);
  81. + m_spellPenetrationItemMod += apply ? amount : -amount;
  82. +}
  83. +
  84. void Player::UpdateResistances(uint32 school)
  85. {
  86. if (school > SPELL_SCHOOL_NORMAL)
  87. diff -r f0ba6a0deaa4 -r f38058f568e4 src/server/game/Entities/Unit/Unit.cpp
  88. --- a/src/server/game/Entities/Unit/Unit.cpp Mon Jun 13 20:21:50 2011 +0200
  89. +++ b/src/server/game/Entities/Unit/Unit.cpp Tue Jun 14 20:29:58 2011 +0200
  90. @@ -974,7 +974,7 @@
  91. return damageInfo.damage;
  92. }
  93.  
  94. -void Unit::CalculateSpellDamageTaken(SpellNonMeleeDamage *damageInfo, int32 damage, SpellEntry const *spellInfo, WeaponAttackType attackType, bool crit)
  95. +void Unit::CalculateSpellDamageTaken(SpellNonMeleeDamage *damageInfo, int32 damage, SpellEntry const *spellInfo, WeaponAttackType attackType, bool crit, int32 calc_resist)
  96. {
  97. if (damage < 0)
  98. return;
  99. @@ -1082,7 +1082,7 @@
  100. // Calculate absorb resist
  101. if (damage > 0)
  102. {
  103. - CalcAbsorbResist(pVictim, damageSchoolMask, SPELL_DIRECT_DAMAGE, damage, &damageInfo->absorb, &damageInfo->resist, spellInfo);
  104. + CalcAbsorbResist(pVictim, damageSchoolMask, SPELL_DIRECT_DAMAGE, damage, &damageInfo->absorb, &damageInfo->resist, spellInfo, calc_resist);
  105. damage -= damageInfo->absorb + damageInfo->resist;
  106. }
  107. else
  108. @@ -1572,73 +1572,134 @@
  109. return (newdamage > 1) ? newdamage : 1;
  110. }
  111.  
  112. -void Unit::CalcAbsorbResist(Unit *pVictim, SpellSchoolMask schoolMask, DamageEffectType damagetype, const uint32 damage, uint32 *absorb, uint32 *resist, SpellEntry const *spellInfo)
  113. +uint32 Unit::GetSpellPenetration(SpellSchoolMask schoolMask) const
  114. +{
  115. + int32 spellPenetration = 0;
  116. +
  117. + const Unit * source = ToPlayer();
  118. +
  119. + if (!source)
  120. + {
  121. + source = ToCreature();
  122. +
  123. + if (source)
  124. + {
  125. + source = source->ToCreature()->GetOwner();
  126. +
  127. + if (source)
  128. + source = source->ToPlayer();
  129. + }
  130. + }
  131. +
  132. + if (source && !isTotem())
  133. + spellPenetration += source->ToPlayer()->GetSpellPenetrationItemMod();
  134. + else
  135. + source = this;
  136. +
  137. + spellPenetration += -source->GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_TARGET_RESISTANCE, schoolMask);
  138. +
  139. + return uint32(std::max<int32>(spellPenetration, 0));
  140. +}
  141. +
  142. +uint32 Unit::CalcSpellResistance(Unit * pVictim, SpellSchoolMask schoolMask, bool binary, SpellEntry const * spellProto) const
  143. +{
  144. + // Magic damage, check for resists
  145. + if (uint32(schoolMask & (SPELL_SCHOOL_MASK_NORMAL | SPELL_SCHOOL_HOLY)) > 0)
  146. + return 0;
  147. +
  148. + // These spells should ignore any resistances
  149. + if (spellProto && spellProto->AttributesEx3 & SPELL_ATTR3_IGNORE_HIT_RESULT)
  150. + return 0;
  151. +
  152. + uint8 BOSS_LEVEL = 83;
  153. + int32 BOSS_RESISTANCE_CONSTANT = 510;
  154. +
  155. + int32 resistanceConstant = 0;
  156. + if (getLevel() >= BOSS_LEVEL)
  157. + resistanceConstant = BOSS_RESISTANCE_CONSTANT;
  158. + else
  159. + resistanceConstant = getLevel() * 5;
  160. +
  161. + int32 levelDiff = std::max<int32>(pVictim->getLevel() - getLevel(), 0);
  162. +
  163. + int32 baseVictimResistance = pVictim->GetResistance(GetFirstSchoolInMask(schoolMask));
  164. + uint32 spellPenetration = GetSpellPenetration(schoolMask);
  165. + int32 victimResistance = std::max<int32>(baseVictimResistance - spellPenetration, 0);
  166. +
  167. + int32 ignoredResistance = 0;
  168. +
  169. + if (victimResistance > 0)
  170. + {
  171. + AuraEffectList const & aurasA = GetAuraEffectsByType(SPELL_AURA_MOD_ABILITY_IGNORE_TARGET_RESIST);
  172. + for (AuraEffectList::const_iterator itr = aurasA.begin(); itr != aurasA.end(); ++itr)
  173. + if (((*itr)->GetMiscValue() & schoolMask) && (*itr)->IsAffectedOnSpell(spellProto))
  174. + ignoredResistance += (*itr)->GetAmount();
  175. +
  176. + AuraEffectList const & aurasB = GetAuraEffectsByType(SPELL_AURA_MOD_IGNORE_TARGET_RESIST);
  177. + for (AuraEffectList::const_iterator itr = aurasB.begin(); itr != aurasB.end(); ++itr)
  178. + if ((*itr)->GetMiscValue() & schoolMask)
  179. + ignoredResistance += (*itr)->GetAmount();
  180. +
  181. + ignoredResistance = std::min<int32>(ignoredResistance, 100);
  182. + }
  183. +
  184. + victimResistance = victimResistance * (100 - ignoredResistance) / 100;
  185. + victimResistance += (levelDiff * 5); // Level diff resistance cannot be pierced
  186. +
  187. + if (victimResistance <= 0)
  188. + return 0;
  189. +
  190. + float averageResist = float(victimResistance) / float(victimResistance + resistanceConstant);
  191. +
  192. + if (binary) // No partial resists for binary spells
  193. + {
  194. + int32 tmp = int32(averageResist * 10000);
  195. + int32 rand = irand(0, 10000);
  196. + return rand < tmp ? 100 : 0;
  197. + }
  198. +
  199. + float discreteResistProbability[11];
  200. +
  201. + for (uint32 i = 0; i < 11; i++)
  202. + {
  203. + discreteResistProbability[i] = 0.5f - 2.5f * fabs(0.1f * i - averageResist);
  204. + if (discreteResistProbability[i] < 0.0f)
  205. + discreteResistProbability[i] = 0.0f;
  206. + }
  207. +
  208. + if (averageResist <= 0.1f)
  209. + {
  210. + discreteResistProbability[0] = 1.0f - 7.5f * averageResist;
  211. + discreteResistProbability[1] = 5.0f * averageResist;
  212. + discreteResistProbability[2] = 2.5f * averageResist;
  213. + }
  214. +
  215. + uint32 resistance = 0;
  216. + float r = float(rand_norm());
  217. + float probabilitySum = discreteResistProbability[0];
  218. +
  219. + while ((r >= probabilitySum) && (resistance < 10))
  220. + {
  221. + ++resistance;
  222. + probabilitySum += discreteResistProbability[resistance];
  223. + }
  224. +
  225. + return (resistance * 10);
  226. +}
  227. +
  228. +void Unit::CalcAbsorbResist(Unit * pVictim, SpellSchoolMask schoolMask, DamageEffectType damagetype, const uint32 damage, uint32 * absorb, uint32 * resist, SpellEntry const * spellInfo, int32 calc_resist)
  229. {
  230. if (!pVictim || !pVictim->isAlive() || !damage)
  231. return;
  232.  
  233. DamageInfo dmgInfo = DamageInfo(this, pVictim, damage, spellInfo, schoolMask, damagetype);
  234.  
  235. - // Magic damage, check for resists
  236. - if ((schoolMask & SPELL_SCHOOL_MASK_NORMAL) == 0)
  237. - {
  238. - float baseVictimResistance = float(pVictim->GetResistance(GetFirstSchoolInMask(schoolMask)));
  239. - float ignoredResistance = float(GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_TARGET_RESISTANCE, schoolMask));
  240. - if (Player* player = ToPlayer())
  241. - ignoredResistance += float(player->GetSpellPenetrationItemMod());
  242. - float victimResistance = baseVictimResistance + ignoredResistance;
  243. -
  244. - static const uint32 BOSS_LEVEL = 83;
  245. - static const float BOSS_RESISTANCE_CONSTANT = 510.0;
  246. - uint32 level = getLevel();
  247. - float resistanceConstant = 0.0f;
  248. -
  249. - if (level == BOSS_LEVEL)
  250. - resistanceConstant = BOSS_RESISTANCE_CONSTANT;
  251. - else
  252. - resistanceConstant = level * 5.0f;
  253. -
  254. - float averageResist = victimResistance / (victimResistance + resistanceConstant);
  255. - float discreteResistProbability[11];
  256. - for (uint32 i = 0; i < 11; ++i)
  257. - {
  258. - discreteResistProbability[i] = 0.5f - 2.5f * fabs(0.1f * i - averageResist);
  259. - if (discreteResistProbability[i] < 0.0f)
  260. - discreteResistProbability[i] = 0.0f;
  261. - }
  262. -
  263. - if (averageResist <= 0.1f)
  264. - {
  265. - discreteResistProbability[0] = 1.0f - 7.5f * averageResist;
  266. - discreteResistProbability[1] = 5.0f * averageResist;
  267. - discreteResistProbability[2] = 2.5f * averageResist;
  268. - }
  269. -
  270. - float r = float(rand_norm());
  271. - uint32 i = 0;
  272. - float probabilitySum = discreteResistProbability[0];
  273. -
  274. - while (r >= probabilitySum && i < 10)
  275. - probabilitySum += discreteResistProbability[++i];
  276. -
  277. - float damageResisted = float(damage * i / 10);
  278. -
  279. - AuraEffectList const &ResIgnoreAurasAb = GetAuraEffectsByType(SPELL_AURA_MOD_ABILITY_IGNORE_TARGET_RESIST);
  280. - for (AuraEffectList::const_iterator j = ResIgnoreAurasAb.begin(); j != ResIgnoreAurasAb.end(); ++j)
  281. - if (((*j)->GetMiscValue() & schoolMask) && (*j)->IsAffectedOnSpell(spellInfo))
  282. - AddPctN(damageResisted, -(*j)->GetAmount());
  283. -
  284. - AuraEffectList const &ResIgnoreAuras = GetAuraEffectsByType(SPELL_AURA_MOD_IGNORE_TARGET_RESIST);
  285. - for (AuraEffectList::const_iterator j = ResIgnoreAuras.begin(); j != ResIgnoreAuras.end(); ++j)
  286. - if ((*j)->GetMiscValue() & schoolMask)
  287. - AddPctN(damageResisted, -(*j)->GetAmount());
  288. -
  289. - // These spells should ignore any resistances
  290. - if (spellInfo && spellInfo->AttributesEx3 & SPELL_ATTR3_IGNORE_HIT_RESULT)
  291. - damageResisted = 0;
  292. -
  293. - dmgInfo.ResistDamage(uint32(damageResisted));
  294. - }
  295. + bool binary = (spellInfo && (uint32(sSpellMgr->GetSpellCustomAttr(spellInfo->Id) & SPELL_ATTR0_CU_BINARY) > 0));
  296. + if (!binary)
  297. + if (calc_resist >= 0)
  298. + dmgInfo.ResistDamage(damage * calc_resist / 100);
  299. + else
  300. + dmgInfo.ResistDamage(damage * CalcSpellResistance(pVictim, schoolMask, binary, spellInfo) / 100);
  301.  
  302. // Ignore Absorption Auras
  303. float auraAbsorbMod = 0;
  304. @@ -2264,7 +2325,7 @@
  305. return false;
  306. }
  307.  
  308. -int32 Unit::GetMechanicResistChance(const SpellEntry *spell)
  309. +int32 Unit::GetMechanicResistChance(const SpellEntry *spell) const
  310. {
  311. if (!spell)
  312. return 0;
  313. @@ -2455,19 +2516,13 @@
  314. return SPELL_MISS_NONE;
  315. }
  316.  
  317. -// TODO need use unit spell resistances in calculations
  318. -SpellMissInfo Unit::MagicSpellHitResult(Unit *pVictim, SpellEntry const *spell)
  319. -{
  320. - // Can`t miss on dead target (on skinning for example)
  321. - if (!pVictim->isAlive() && pVictim->GetTypeId() != TYPEID_PLAYER)
  322. - return SPELL_MISS_NONE;
  323. -
  324. - SpellSchoolMask schoolMask = GetSpellSchoolMask(spell);
  325. +uint32 Unit::CalcMagicSpellHitChance(Unit * pVictim, SpellSchoolMask schoolMask, SpellEntry const * spellProto)
  326. +{
  327. // PvP - PvE spell misschances per leveldif > 2
  328. int32 lchance = pVictim->GetTypeId() == TYPEID_PLAYER ? 7 : 11;
  329. int32 thisLevel = getLevelForTarget(pVictim);
  330. if (GetTypeId() == TYPEID_UNIT && ToCreature()->isTrigger())
  331. - thisLevel = std::max<int32>(thisLevel, spell->spellLevel);
  332. + thisLevel = std::max<int32>(thisLevel, spellProto->spellLevel);
  333. int32 leveldif = int32(pVictim->getLevelForTarget(this)) - thisLevel;
  334.  
  335. // Base hit chance from attacker and victim levels
  336. @@ -2475,44 +2530,131 @@
  337. if (leveldif < 3)
  338. modHitChance = 96 - leveldif;
  339. else
  340. - modHitChance = 94 - (leveldif - 2) * lchance;
  341. -
  342. + modHitChance = 94 - (leveldif - 2) * lchance;
  343. +
  344. + Unit * source = ToPlayer();
  345. + if (!source)
  346. + {
  347. + source = ToCreature();
  348. + if (source)
  349. + {
  350. + source = source->ToCreature()->GetOwner();
  351. + if (source)
  352. + source = source->ToPlayer();
  353. + }
  354. + }
  355. + if (source && !isTotem())
  356. + source->ToPlayer()->ApplySpellMod(spellProto->Id, SPELLMOD_RESIST_MISS_CHANCE, modHitChance);
  357. + else
  358. + source = this;
  359. +
  360. // Spellmod from SPELLMOD_RESIST_MISS_CHANCE
  361. if (Player *modOwner = GetSpellModOwner())
  362. - modOwner->ApplySpellMod(spell->Id, SPELLMOD_RESIST_MISS_CHANCE, modHitChance);
  363. + modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_RESIST_MISS_CHANCE, modHitChance);
  364.  
  365. // Increase from attacker SPELL_AURA_MOD_INCREASES_SPELL_PCT_TO_HIT auras
  366. modHitChance += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_INCREASES_SPELL_PCT_TO_HIT, schoolMask);
  367.  
  368. // Spells with SPELL_ATTR3_IGNORE_HIT_RESULT will ignore target's avoidance effects
  369. - if (!(spell->AttributesEx3 & SPELL_ATTR3_IGNORE_HIT_RESULT))
  370. + if (!(spellProto->AttributesEx3 & SPELL_ATTR3_IGNORE_HIT_RESULT))
  371. {
  372. // Chance hit from victim SPELL_AURA_MOD_ATTACKER_SPELL_HIT_CHANCE auras
  373. - if (!(spell->SpellFamilyName == SPELLFAMILY_WARLOCK && spell->SpellIconID == 3178)) // Chaos Bolt should ignore it
  374. - modHitChance += pVictim->GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_ATTACKER_SPELL_HIT_CHANCE, schoolMask);
  375. + if (!(spellProto->SpellFamilyName == SPELLFAMILY_WARLOCK && spellProto->SpellIconID == 3178)) // Chaos Bolt should ignore it
  376. + modHitChance += pVictim->GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_ATTACKER_SPELL_HIT_CHANCE, schoolMask);
  377. // Reduce spell hit chance for Area of effect spells from victim SPELL_AURA_MOD_AOE_AVOIDANCE aura
  378. - if (IsAreaOfEffectSpell(spell))
  379. + if (IsAreaOfEffectSpell(spellProto))
  380. modHitChance -= pVictim->GetTotalAuraModifier(SPELL_AURA_MOD_AOE_AVOIDANCE);
  381.  
  382. // Decrease hit chance from victim rating bonus
  383. if (pVictim->GetTypeId() == TYPEID_PLAYER)
  384. modHitChance -= int32(pVictim->ToPlayer()->GetRatingBonusValue(CR_HIT_TAKEN_SPELL));
  385. - }
  386. -
  387. - int32 HitChance = modHitChance * 100;
  388. - // Increase hit chance from attacker SPELL_AURA_MOD_SPELL_HIT_CHANCE and attacker ratings
  389. - HitChance += int32(m_modSpellHitChance * 100.0f);
  390. -
  391. - if (HitChance < 100)
  392. - HitChance = 100;
  393. - else if (HitChance > 10000)
  394. - HitChance = 10000;
  395. -
  396. - int32 tmp = 10000 - HitChance;
  397. + }
  398. + // Chance resist mechanic (select max value from every mechanic spell effect)
  399. + modHitChance -= pVictim->GetMechanicResistChance(spellProto);
  400. +
  401. + // Chance resist debuff
  402. + if (!IsPositiveSpell(spellProto->Id))
  403. + {
  404. + bool bNegativeAura = false;
  405. + for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
  406. + {
  407. + if (spellProto->EffectApplyAuraName[i] != 0)
  408. + {
  409. + bNegativeAura = true;
  410. + break;
  411. + }
  412. + }
  413. +
  414. + // Direct Damage spells should not be fully resisted
  415. + bool bDirectDamage = false;
  416. + for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
  417. + {
  418. + if (spellProto->Effect[i] == SPELL_EFFECT_SCHOOL_DAMAGE || spellProto->Effect[i] == SPELL_EFFECT_HEALTH_LEECH)
  419. + {
  420. + bDirectDamage = true;
  421. + break;
  422. + }
  423. + }
  424. +
  425. + if (bNegativeAura && !bDirectDamage)
  426. + {
  427. + modHitChance -= pVictim->GetMaxPositiveAuraModifierByMiscValue(SPELL_AURA_MOD_DEBUFF_RESISTANCE, int32(spellProto->Dispel));
  428. + modHitChance -= pVictim->GetMaxNegativeAuraModifierByMiscValue(SPELL_AURA_MOD_DEBUFF_RESISTANCE, int32(spellProto->Dispel));
  429. + }
  430. + }
  431. +
  432. + int32 hit = modHitChance * 100;
  433. + // Increase hit chance from attacker SPELL_AURA_MOD_SPELL_HIT_CHANCE and attacker ratings
  434. + hit += int32(source->m_modSpellHitChance * 100.0f);
  435. +
  436. + // Decrease hit chance from victim rating bonus
  437. + if (pVictim->ToPlayer())
  438. + hit -= int32(pVictim->ToPlayer()->GetRatingBonusValue(CR_HIT_TAKEN_SPELL) * 100.0f);
  439. +
  440. + hit = std::min<int32>(std::max<int32>(hit, 100), 10000);
  441. +
  442. + return uint32(hit);
  443. +}
  444. +
  445. +SpellMissInfo Unit::MagicSpellHitResult(Unit * pVictim, SpellEntry const * spell)
  446. +{
  447. + // Can`t miss on dead target (on skinning for example)
  448. + if (!pVictim->isAlive() && pVictim->GetTypeId() != TYPEID_PLAYER)
  449. + return SPELL_MISS_NONE;
  450. +
  451. + SpellSchoolMask schoolMask = GetSpellSchoolMask(spell);
  452. +
  453. + int32 ignoredResistance = 0;
  454. +
  455. + AuraEffectList const & aurasA = GetAuraEffectsByType(SPELL_AURA_MOD_ABILITY_IGNORE_TARGET_RESIST);
  456. + for (AuraEffectList::const_iterator itr = aurasA.begin(); itr != aurasA.end(); ++itr)
  457. + if (((*itr)->GetMiscValue() & schoolMask) && (*itr)->IsAffectedOnSpell(spell))
  458. + ignoredResistance += (*itr)->GetAmount();
  459. +
  460. + AuraEffectList const & aurasB = GetAuraEffectsByType(SPELL_AURA_MOD_IGNORE_TARGET_RESIST);
  461. + for (AuraEffectList::const_iterator itr = aurasB.begin(); itr != aurasB.end(); ++itr)
  462. + if ((*itr)->GetMiscValue() & schoolMask)
  463. + ignoredResistance += (*itr)->GetAmount();
  464. +
  465. + ignoredResistance = std::min(ignoredResistance, int32(100));
  466. +
  467. + // cast by caster in front of victim
  468. + int32 deflect_chance = (pVictim->GetTotalAuraModifier(SPELL_AURA_DEFLECT_SPELLS) * (100 - ignoredResistance) / 100) * 100;
  469. +
  470. + if (deflect_chance > 0)
  471. + if (pVictim->HasInArc(M_PI, this) || pVictim->HasAuraType(SPELL_AURA_IGNORE_HIT_DIRECTION))
  472. + {
  473. + int32 rand = irand(0, 10000);
  474. +
  475. + if (rand < deflect_chance)
  476. + return SPELL_MISS_DEFLECT;
  477. + }
  478. +
  479. + int32 miss = (10000 - CalcMagicSpellHitChance(pVictim, schoolMask, spell)) * (100 - ignoredResistance) / 100;
  480.  
  481. int32 rand = irand(0, 10000);
  482.  
  483. - if (rand < tmp)
  484. + if (rand < miss)
  485. return SPELL_MISS_MISS;
  486.  
  487. // Spells with SPELL_ATTR3_IGNORE_HIT_RESULT will additionally fully ignore
  488. @@ -2520,58 +2662,10 @@
  489. if (spell->AttributesEx3 & SPELL_ATTR3_IGNORE_HIT_RESULT)
  490. return SPELL_MISS_NONE;
  491.  
  492. - // Chance resist mechanic (select max value from every mechanic spell effect)
  493. - int32 resist_chance = pVictim->GetMechanicResistChance(spell) * 100;
  494. - tmp += resist_chance;
  495. -
  496. - // Chance resist debuff
  497. - if (!IsPositiveSpell(spell->Id))
  498. - {
  499. - bool bNegativeAura = false;
  500. - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
  501. - {
  502. - if (spell->EffectApplyAuraName[i] != 0)
  503. - {
  504. - bNegativeAura = true;
  505. - break;
  506. - }
  507. - }
  508. -
  509. - // Direct Damage spells should not be fully resisted
  510. - bool bDirectDamage = false;
  511. - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
  512. - {
  513. - if (spell->Effect[i] == SPELL_EFFECT_SCHOOL_DAMAGE || spell->Effect[i] == SPELL_EFFECT_HEALTH_LEECH)
  514. - {
  515. - bDirectDamage = true;
  516. - break;
  517. - }
  518. - }
  519. -
  520. - if (bNegativeAura && !bDirectDamage)
  521. - {
  522. - tmp += pVictim->GetMaxPositiveAuraModifierByMiscValue(SPELL_AURA_MOD_DEBUFF_RESISTANCE, int32(spell->Dispel)) * 100;
  523. - tmp += pVictim->GetMaxNegativeAuraModifierByMiscValue(SPELL_AURA_MOD_DEBUFF_RESISTANCE, int32(spell->Dispel)) * 100;
  524. - }
  525. - }
  526. -
  527. - // Roll chance
  528. - if (rand < tmp)
  529. - return SPELL_MISS_RESIST;
  530. -
  531. // Chaos Bolt cannot be deflected
  532. if (spell->SpellFamilyName == SPELLFAMILY_WARLOCK && spell->SpellIconID == 3178)
  533. return SPELL_MISS_NONE;
  534.  
  535. - // cast by caster in front of victim
  536. - if (pVictim->HasInArc(M_PI, this) || pVictim->HasAuraType(SPELL_AURA_IGNORE_HIT_DIRECTION))
  537. - {
  538. - int32 deflect_chance = pVictim->GetTotalAuraModifier(SPELL_AURA_DEFLECT_SPELLS) * 100;
  539. - tmp += deflect_chance;
  540. - if (rand < tmp)
  541. - return SPELL_MISS_DEFLECT;
  542. - }
  543. -
  544. return SPELL_MISS_NONE;
  545. }
  546.  
  547. diff -r f0ba6a0deaa4 -r f38058f568e4 src/server/game/Entities/Unit/Unit.h
  548. --- a/src/server/game/Entities/Unit/Unit.h Mon Jun 13 20:21:50 2011 +0200
  549. +++ b/src/server/game/Entities/Unit/Unit.h Tue Jun 14 20:29:58 2011 +0200
  550. @@ -1254,6 +1254,7 @@
  551.  
  552. uint32 GetResistance(SpellSchools school) const { return GetUInt32Value(UNIT_FIELD_RESISTANCES+school); }
  553. void SetResistance(SpellSchools school, int32 val) { SetStatInt32Value(UNIT_FIELD_RESISTANCES+school, val); }
  554. + uint32 GetSpellPenetration(SpellSchoolMask schoolMask) const;
  555.  
  556. uint32 GetHealth() const { return GetUInt32Value(UNIT_FIELD_HEALTH); }
  557. uint32 GetMaxHealth() const { return GetUInt32Value(UNIT_FIELD_MAXHEALTH); }
  558. @@ -1358,7 +1359,7 @@
  559. void CalculateMeleeDamage(Unit *pVictim, uint32 damage, CalcDamageInfo *damageInfo, WeaponAttackType attackType = BASE_ATTACK);
  560. void DealMeleeDamage(CalcDamageInfo *damageInfo, bool durabilityLoss);
  561.  
  562. - void CalculateSpellDamageTaken(SpellNonMeleeDamage *damageInfo, int32 damage, SpellEntry const *spellInfo, WeaponAttackType attackType = BASE_ATTACK, bool crit = false);
  563. + void CalculateSpellDamageTaken(SpellNonMeleeDamage *damageInfo, int32 damage, SpellEntry const *spellInfo, WeaponAttackType attackType = BASE_ATTACK, bool crit = false, int32 calc_resist = -1);
  564. void DealSpellDamage(SpellNonMeleeDamage *damageInfo, bool durabilityLoss);
  565.  
  566. // player or player's pet resilience (-1%)
  567. @@ -1384,13 +1385,14 @@
  568. float MeleeSpellMissChance(const Unit *pVictim, WeaponAttackType attType, int32 skillDiff, uint32 spellId) const;
  569. SpellMissInfo MeleeSpellHitResult(Unit *pVictim, SpellEntry const *spell);
  570. SpellMissInfo MagicSpellHitResult(Unit *pVictim, SpellEntry const *spell);
  571. + uint32 CalcMagicSpellHitChance(Unit * pVictim, SpellSchoolMask schoolMask, SpellEntry const * spellProto);
  572. SpellMissInfo SpellHitResult(Unit *pVictim, SpellEntry const *spell, bool canReflect = false);
  573.  
  574. float GetUnitDodgeChance() const;
  575. float GetUnitParryChance() const;
  576. float GetUnitBlockChance() const;
  577. float GetUnitCriticalChance(WeaponAttackType attackType, const Unit *pVictim) const;
  578. - int32 GetMechanicResistChance(const SpellEntry *spell);
  579. + int32 GetMechanicResistChance(const SpellEntry *spell) const;
  580. bool CanUseAttackType(uint8 attacktype) const
  581. {
  582. switch(attacktype)
  583. @@ -1937,7 +1939,8 @@
  584. // redefined in Creature
  585. static bool IsDamageReducedByArmor(SpellSchoolMask damageSchoolMask, SpellEntry const *spellInfo = NULL, uint8 effIndex = MAX_SPELL_EFFECTS);
  586. uint32 CalcArmorReducedDamage(Unit* pVictim, const uint32 damage, SpellEntry const *spellInfo, WeaponAttackType attackType=MAX_ATTACK);
  587. - void CalcAbsorbResist(Unit *pVictim, SpellSchoolMask schoolMask, DamageEffectType damagetype, const uint32 damage, uint32 *absorb, uint32 *resist, SpellEntry const *spellInfo = NULL);
  588. + void CalcAbsorbResist(Unit *pVictim, SpellSchoolMask schoolMask, DamageEffectType damagetype, const uint32 damage, uint32 *absorb, uint32 *resist, SpellEntry const *spellInfo = NULL, int32 calc_resist = -1);
  589. + uint32 CalcSpellResistance(Unit * pVictim, SpellSchoolMask schoolMask, bool binary, SpellEntry const * spellProto) const;
  590. void CalcHealAbsorb(Unit *pVictim, const SpellEntry *spellProto, uint32 &healAmount, uint32 &absorb);
  591.  
  592. void UpdateSpeed(UnitMoveType mtype, bool forced);
  593. diff -r f0ba6a0deaa4 -r f38058f568e4 src/server/game/Spells/Spell.cpp
  594. --- a/src/server/game/Spells/Spell.cpp Mon Jun 13 20:21:50 2011 +0200
  595. +++ b/src/server/game/Spells/Spell.cpp Tue Jun 14 20:29:58 2011 +0200
  596. @@ -932,15 +932,9 @@
  597. target.scaleAura = true;
  598. }
  599.  
  600. - // Calculate hit result
  601. - if (m_originalCaster)
  602. - {
  603. - target.missCondition = m_originalCaster->SpellHitResult(pVictim, m_spellInfo, m_canReflect);
  604. - if (m_skipCheck && target.missCondition != SPELL_MISS_IMMUNE)
  605. - target.missCondition = SPELL_MISS_NONE;
  606. - }
  607. - else
  608. - target.missCondition = SPELL_MISS_EVADE; //SPELL_MISS_NONE;
  609. + target.missCondition = m_originalCaster->SpellHitResult(pVictim, m_spellInfo, m_canReflect);
  610. + if (m_skipCheck && target.missCondition != SPELL_MISS_IMMUNE)
  611. + target.missCondition = SPELL_MISS_NONE;
  612.  
  613. // Spell have speed - need calculate incoming time
  614. // Incoming time is zero for self casts. At least I think so.
  615. @@ -1109,6 +1103,7 @@
  616. // Reset damage/healing counter
  617. m_damage = target->damage;
  618. m_healing = -target->damage;
  619. + m_resist = 0;
  620.  
  621. // Fill base trigger info
  622. uint32 procAttacker = m_procAttacker;
  623. @@ -1138,11 +1133,11 @@
  624.  
  625. if (spellHitTarget)
  626. {
  627. - SpellMissInfo missInfo = DoSpellHitOnUnit(spellHitTarget, mask, target->scaleAura);
  628. - if (missInfo != SPELL_MISS_NONE)
  629. - {
  630. - if (missInfo != SPELL_MISS_MISS)
  631. - m_caster->SendSpellMiss(unit, m_spellInfo->Id, missInfo);
  632. + SpellMissInfo tmp = DoSpellHitOnUnit(spellHitTarget, mask, target->scaleAura);
  633. + if (tmp != SPELL_MISS_NONE)
  634. + {
  635. + if (tmp != SPELL_MISS_MISS)
  636. + m_caster->SendSpellMiss(unit, m_spellInfo->Id, tmp);
  637. m_damage = 0;
  638. spellHitTarget = NULL;
  639. }
  640. @@ -1238,7 +1233,7 @@
  641. SpellNonMeleeDamage damageInfo(caster, unitTarget, m_spellInfo->Id, m_spellSchoolMask);
  642.  
  643. // Add bonuses and fill damageInfo struct
  644. - caster->CalculateSpellDamageTaken(&damageInfo, m_damage, m_spellInfo, m_attackType, target->crit);
  645. + caster->CalculateSpellDamageTaken(&damageInfo, m_damage, m_spellInfo, m_attackType, target->crit, m_resist);
  646. caster->DealDamageMods(damageInfo.target, damageInfo.damage, &damageInfo.absorb);
  647.  
  648. // Send log damage message to client
  649. @@ -1371,6 +1366,11 @@
  650. //TODO: This is a hack. But we do not know what types of stealth should be interrupted by CC
  651. if ((m_customAttr & SPELL_ATTR0_CU_AURA_CC) && unit->IsControlledByPlayer())
  652. unit->RemoveAurasByType(SPELL_AURA_MOD_STEALTH);
  653. +
  654. + bool binary = (uint32(sSpellMgr->GetSpellCustomAttr(m_spellInfo->Id) & SPELL_ATTR0_CU_BINARY) > 0);
  655. + m_resist = m_caster->CalcSpellResistance(unit, GetSpellSchoolMask(m_spellInfo), binary, m_spellInfo);
  656. + if (m_resist >= 100)
  657. + return SPELL_MISS_RESIST;
  658. }
  659. else
  660. {
  661. @@ -1393,6 +1393,13 @@
  662. }
  663. }
  664. }
  665. + else if (!IsPositiveSpell(m_spellInfo->Id))
  666. + {
  667. + bool binary = (uint32(sSpellMgr->GetSpellCustomAttr(m_spellInfo->Id) & SPELL_ATTR0_CU_BINARY) > 0);
  668. + m_resist = m_caster->CalcSpellResistance(unit, GetSpellSchoolMask(m_spellInfo), binary, m_spellInfo);
  669. + if (m_resist >= 100)
  670. + return SPELL_MISS_RESIST;
  671. + }
  672.  
  673. // Get Data Needed for Diminishing Returns, some effects may have multiple auras, so this must be done on spell hit, not aura add
  674. m_diminishGroup = GetDiminishingReturnsGroupForSpell(m_spellInfo, m_triggeredByAuraSpell);
  675. diff -r f0ba6a0deaa4 -r f38058f568e4 src/server/game/Spells/Spell.h
  676. --- a/src/server/game/Spells/Spell.h Mon Jun 13 20:21:50 2011 +0200
  677. +++ b/src/server/game/Spells/Spell.h Tue Jun 14 20:29:58 2011 +0200
  678. @@ -605,6 +605,7 @@
  679. // Damage and healing in effects need just calculate
  680. int32 m_damage; // Damge in effects count here
  681. int32 m_healing; // Healing in effects count here
  682. + int32 m_resist; // Resist in effects count here
  683.  
  684. // ******************************************
  685. // Spell trigger system
  686. diff -r f0ba6a0deaa4 -r f38058f568e4 src/server/game/Spells/SpellMgr.cpp
  687. --- a/src/server/game/Spells/SpellMgr.cpp Mon Jun 13 20:21:50 2011 +0200
  688. +++ b/src/server/game/Spells/SpellMgr.cpp Tue Jun 14 20:29:58 2011 +0200
  689. @@ -3613,6 +3613,79 @@
  690. }
  691. }
  692.  
  693. + if (spellInfo->DmgClass == SPELL_DAMAGE_CLASS_MAGIC)
  694. + {
  695. + if (spellInfo->Mechanic != 0 &&
  696. + spellInfo->Mechanic != MECHANIC_INFECTED)
  697. + {
  698. + mSpellCustomAttr[i] |= SPELL_ATTR0_CU_BINARY;
  699. + count++;
  700. + }
  701. + else if (spellInfo->EffectMechanic[0] != 0 &&
  702. + spellInfo->EffectMechanic[0] != MECHANIC_INFECTED &&
  703. + spellInfo->Effect[1] != SPELL_EFFECT_SCHOOL_DAMAGE)
  704. + {
  705. + mSpellCustomAttr[i] |= SPELL_ATTR0_CU_BINARY;
  706. + count++;
  707. + }
  708. + else if (spellInfo->EffectMechanic[1] != 0 &&
  709. + spellInfo->EffectMechanic[1] != MECHANIC_INFECTED)
  710. + {
  711. + mSpellCustomAttr[i] |= SPELL_ATTR0_CU_BINARY;
  712. + count++;
  713. + }
  714. + else if (spellInfo->Effect[0] == SPELL_EFFECT_DISPEL ||
  715. + spellInfo->Effect[1] == SPELL_EFFECT_DISPEL ||
  716. + spellInfo->Effect[2] == SPELL_EFFECT_DISPEL)
  717. + {
  718. + mSpellCustomAttr[i] |= SPELL_ATTR0_CU_BINARY;
  719. + count++;
  720. + }
  721. + else if (spellInfo->Effect[0] == SPELL_EFFECT_STEAL_BENEFICIAL_BUFF ||
  722. + spellInfo->Effect[1] == SPELL_EFFECT_STEAL_BENEFICIAL_BUFF ||
  723. + spellInfo->Effect[2] == SPELL_EFFECT_STEAL_BENEFICIAL_BUFF)
  724. + {
  725. + mSpellCustomAttr[i] |= SPELL_ATTR0_CU_BINARY;
  726. + count++;
  727. + }
  728. + else if (spellInfo->Effect[0] == SPELL_EFFECT_POWER_BURN ||
  729. + spellInfo->Effect[1] == SPELL_EFFECT_POWER_BURN ||
  730. + spellInfo->Effect[2] == SPELL_EFFECT_POWER_BURN)
  731. + {
  732. + mSpellCustomAttr[i] |= SPELL_ATTR0_CU_BINARY;
  733. + count++;
  734. + }
  735. + else if (spellInfo->Effect[0] == SPELL_EFFECT_POWER_DRAIN ||
  736. + spellInfo->Effect[1] == SPELL_EFFECT_POWER_DRAIN ||
  737. + spellInfo->Effect[2] == SPELL_EFFECT_POWER_DRAIN)
  738. + {
  739. + mSpellCustomAttr[i] |= SPELL_ATTR0_CU_BINARY;
  740. + count++;
  741. + }
  742. + else if (spellInfo->EffectApplyAuraName[0] == SPELL_AURA_PERIODIC_MANA_LEECH ||
  743. + spellInfo->EffectApplyAuraName[1] == SPELL_AURA_PERIODIC_MANA_LEECH ||
  744. + spellInfo->EffectApplyAuraName[2] == SPELL_AURA_PERIODIC_MANA_LEECH)
  745. + {
  746. + mSpellCustomAttr[i] |= SPELL_ATTR0_CU_BINARY;
  747. + count++;
  748. + }
  749. + else if ((spellInfo->Dispel == DISPEL_POISON) ||
  750. + (spellInfo->Dispel == DISPEL_CURSE) ||
  751. + (spellInfo->Dispel == DISPEL_DISEASE))
  752. + {
  753. + if (spellInfo->Effect[0] != SPELL_EFFECT_SCHOOL_DAMAGE &&
  754. + spellInfo->Effect[1] != SPELL_EFFECT_SCHOOL_DAMAGE &&
  755. + spellInfo->Effect[2] != SPELL_EFFECT_SCHOOL_DAMAGE &&
  756. + spellInfo->EffectApplyAuraName[0] != SPELL_AURA_PERIODIC_DAMAGE &&
  757. + spellInfo->EffectApplyAuraName[1] != SPELL_AURA_PERIODIC_DAMAGE &&
  758. + spellInfo->EffectApplyAuraName[2] != SPELL_AURA_PERIODIC_DAMAGE)
  759. + {
  760. + mSpellCustomAttr[i] |= SPELL_ATTR0_CU_BINARY;
  761. + count++;
  762. + }
  763. + }
  764. + }
  765. +
  766. if (!_isPositiveEffect(i, 0, false))
  767. {
  768. mSpellCustomAttr[i] |= SPELL_ATTR0_CU_NEGATIVE_EFF0;
  769. diff -r f0ba6a0deaa4 -r f38058f568e4 src/server/game/Spells/SpellMgr.h
  770. --- a/src/server/game/Spells/SpellMgr.h Mon Jun 13 20:21:50 2011 +0200
  771. +++ b/src/server/game/Spells/SpellMgr.h Tue Jun 14 20:29:58 2011 +0200
  772. @@ -890,6 +890,7 @@
  773. SPELL_ATTR0_CU_NEGATIVE_EFF1 = 0x00020000,
  774. SPELL_ATTR0_CU_NEGATIVE_EFF2 = 0x00040000,
  775. SPELL_ATTR0_CU_IGNORE_ARMOR = 0x00080000,
  776. + SPELL_ATTR0_CU_BINARY = 0x00100000,
  777.  
  778. SPELL_ATTR0_CU_NEGATIVE = SPELL_ATTR0_CU_NEGATIVE_EFF0 | SPELL_ATTR0_CU_NEGATIVE_EFF1 | SPELL_ATTR0_CU_NEGATIVE_EFF2,
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement