Advertisement
minato4thhokage

Untitled

Mar 17th, 2016
592
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /
  2. * Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
  3. * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
  4. *
  5. * This program is free software; you can redistribute it and/or modify it
  6. * under the terms of the GNU General Public License as published by the
  7. * Free Software Foundation; either version 2 of the License, or (at your
  8. * option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful, but WITHOUT
  11. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  13. * more details.
  14. *
  15. * You should have received a copy of the GNU General Public License along
  16. * with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18.  
  19. #include "Common.h"
  20. #include "DatabaseEnv.h"
  21. #include "WorldPacket.h"
  22. #include "Opcodes.h"
  23. #include "Log.h"
  24. #include "UpdateMask.h"
  25. #include "World.h"
  26. #include "ObjectMgr.h"
  27. #include "SpellMgr.h"
  28. #include "Player.h"
  29. #include "SkillExtraItems.h"
  30. #include "Unit.h"
  31. #include "Spell.h"
  32. #include "DynamicObject.h"
  33. #include "SpellAuras.h"
  34. #include "SpellAuraEffects.h"
  35. #include "Group.h"
  36. #include "UpdateData.h"
  37. #include "MapManager.h"
  38. #include "ObjectAccessor.h"
  39. #include "SharedDefines.h"
  40. #include "Pet.h"
  41. #include "GameObject.h"
  42. #include "GossipDef.h"
  43. #include "Creature.h"
  44. #include "Totem.h"
  45. #include "CreatureAI.h"
  46. #include "BattlegroundMgr.h"
  47. #include "Battleground.h"
  48. #include "BattlegroundEY.h"
  49. #include "BattlegroundWS.h"
  50. #include "OutdoorPvPMgr.h"
  51. #include "Language.h"
  52. #include "SocialMgr.h"
  53. #include "Util.h"
  54. #include "VMapFactory.h"
  55. #include "TemporarySummon.h"
  56. #include "CellImpl.h"
  57. #include "GridNotifiers.h"
  58. #include "GridNotifiersImpl.h"
  59. #include "SkillDiscovery.h"
  60. #include "Formulas.h"
  61. #include "Vehicle.h"
  62. #include "ScriptMgr.h"
  63. #include "GameObjectAI.h"
  64. #include "AccountMgr.h"
  65. #include "InstanceScript.h"
  66. #include "ReputationMgr.h"
  67.  
  68. pEffect SpellEffects[TOTAL_SPELL_EFFECTS]=
  69. {
  70. &Spell::EffectNULL, // 0
  71. &Spell::EffectInstaKill, // 1 SPELL_EFFECT_INSTAKILL
  72. &Spell::EffectSchoolDMG, // 2 SPELL_EFFECT_SCHOOL_DAMAGE
  73. &Spell::EffectDummy, // 3 SPELL_EFFECT_DUMMY
  74. &Spell::EffectUnused, // 4 SPELL_EFFECT_PORTAL_TELEPORT unused
  75. &Spell::EffectTeleportUnits, // 5 SPELL_EFFECT_TELEPORT_UNITS
  76. &Spell::EffectApplyAura, // 6 SPELL_EFFECT_APPLY_AURA
  77. &Spell::EffectEnvironmentalDMG, // 7 SPELL_EFFECT_ENVIRONMENTAL_DAMAGE
  78. &Spell::EffectPowerDrain, // 8 SPELL_EFFECT_POWER_DRAIN
  79. &Spell::EffectHealthLeech, // 9 SPELL_EFFECT_HEALTH_LEECH
  80. &Spell::EffectHeal, // 10 SPELL_EFFECT_HEAL
  81. &Spell::EffectBind, // 11 SPELL_EFFECT_BIND
  82. &Spell::EffectNULL, // 12 SPELL_EFFECT_PORTAL
  83. &Spell::EffectUnused, // 13 SPELL_EFFECT_RITUAL_BASE unused
  84. &Spell::EffectUnused, // 14 SPELL_EFFECT_RITUAL_SPECIALIZE unused
  85. &Spell::EffectUnused, // 15 SPELL_EFFECT_RITUAL_ACTIVATE_PORTAL unused
  86. &Spell::EffectQuestComplete, // 16 SPELL_EFFECT_QUEST_COMPLETE
  87. &Spell::EffectWeaponDmg, // 17 SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL
  88. &Spell::EffectResurrect, // 18 SPELL_EFFECT_RESURRECT
  89. &Spell::EffectAddExtraAttacks, // 19 SPELL_EFFECT_ADD_EXTRA_ATTACKS
  90. &Spell::EffectUnused, // 20 SPELL_EFFECT_DODGE one spell: Dodge
  91. &Spell::EffectUnused, // 21 SPELL_EFFECT_EVADE one spell: Evade (DND)
  92. &Spell::EffectParry, // 22 SPELL_EFFECT_PARRY
  93. &Spell::EffectBlock, // 23 SPELL_EFFECT_BLOCK one spell: Block
  94. &Spell::EffectCreateItem, // 24 SPELL_EFFECT_CREATE_ITEM
  95. &Spell::EffectUnused, // 25 SPELL_EFFECT_WEAPON
  96. &Spell::EffectUnused, // 26 SPELL_EFFECT_DEFENSE one spell: Defense
  97. &Spell::EffectPersistentAA, // 27 SPELL_EFFECT_PERSISTENT_AREA_AURA
  98. &Spell::EffectSummonType, // 28 SPELL_EFFECT_SUMMON
  99. &Spell::EffectLeap, // 29 SPELL_EFFECT_LEAP
  100. &Spell::EffectEnergize, // 30 SPELL_EFFECT_ENERGIZE
  101. &Spell::EffectWeaponDmg, // 31 SPELL_EFFECT_WEAPON_PERCENT_DAMAGE
  102. &Spell::EffectTriggerMissileSpell, // 32 SPELL_EFFECT_TRIGGER_MISSILE
  103. &Spell::EffectOpenLock, // 33 SPELL_EFFECT_OPEN_LOCK
  104. &Spell::EffectSummonChangeItem, // 34 SPELL_EFFECT_SUMMON_CHANGE_ITEM
  105. &Spell::EffectApplyAreaAura, // 35 SPELL_EFFECT_APPLY_AREA_AURA_PARTY
  106. &Spell::EffectLearnSpell, // 36 SPELL_EFFECT_LEARN_SPELL
  107. &Spell::EffectUnused, // 37 SPELL_EFFECT_SPELL_DEFENSE one spell: SPELLDEFENSE (DND)
  108. &Spell::EffectDispel, // 38 SPELL_EFFECT_DISPEL
  109. &Spell::EffectUnused, // 39 SPELL_EFFECT_LANGUAGE
  110. &Spell::EffectDualWield, // 40 SPELL_EFFECT_DUAL_WIELD
  111. &Spell::EffectJump, // 41 SPELL_EFFECT_JUMP
  112. &Spell::EffectJumpDest, // 42 SPELL_EFFECT_JUMP_DEST
  113. &Spell::EffectTeleUnitsFaceCaster, // 43 SPELL_EFFECT_TELEPORT_UNITS_FACE_CASTER
  114. &Spell::EffectLearnSkill, // 44 SPELL_EFFECT_SKILL_STEP
  115. &Spell::EffectAddHonor, // 45 SPELL_EFFECT_ADD_HONOR honor/pvp related
  116. &Spell::EffectUnused, // 46 SPELL_EFFECT_SPAWN clientside, unit appears as if it was just spawned
  117. &Spell::EffectTradeSkill, // 47 SPELL_EFFECT_TRADE_SKILL
  118. &Spell::EffectUnused, // 48 SPELL_EFFECT_STEALTH one spell: Base Stealth
  119. &Spell::EffectUnused, // 49 SPELL_EFFECT_DETECT one spell: Detect
  120. &Spell::EffectTransmitted, // 50 SPELL_EFFECT_TRANS_DOOR
  121. &Spell::EffectUnused, // 51 SPELL_EFFECT_FORCE_CRITICAL_HIT unused
  122. &Spell::EffectUnused, // 52 SPELL_EFFECT_GUARANTEE_HIT one spell: zzOLDCritical Shot
  123. &Spell::EffectEnchantItemPerm, // 53 SPELL_EFFECT_ENCHANT_ITEM
  124. &Spell::EffectEnchantItemTmp, // 54 SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY
  125. &Spell::EffectTameCreature, // 55 SPELL_EFFECT_TAMECREATURE
  126. &Spell::EffectSummonPet, // 56 SPELL_EFFECT_SUMMON_PET
  127. &Spell::EffectLearnPetSpell, // 57 SPELL_EFFECT_LEARN_PET_SPELL
  128. &Spell::EffectWeaponDmg, // 58 SPELL_EFFECT_WEAPON_DAMAGE
  129. &Spell::EffectCreateRandomItem, // 59 SPELL_EFFECT_CREATE_RANDOM_ITEM create item base at spell specific loot
  130. &Spell::EffectProficiency, // 60 SPELL_EFFECT_PROFICIENCY
  131. &Spell::EffectSendEvent, // 61 SPELL_EFFECT_SEND_EVENT
  132. &Spell::EffectPowerBurn, // 62 SPELL_EFFECT_POWER_BURN
  133. &Spell::EffectThreat, // 63 SPELL_EFFECT_THREAT
  134. &Spell::EffectTriggerSpell, // 64 SPELL_EFFECT_TRIGGER_SPELL
  135. &Spell::EffectApplyAreaAura, // 65 SPELL_EFFECT_APPLY_AREA_AURA_RAID
  136. &Spell::EffectRechargeManaGem, // 66 SPELL_EFFECT_CREATE_MANA_GEM (possibly recharge it, misc - is item ID)
  137. &Spell::EffectHealMaxHealth, // 67 SPELL_EFFECT_HEAL_MAX_HEALTH
  138. &Spell::EffectInterruptCast, // 68 SPELL_EFFECT_INTERRUPT_CAST
  139. &Spell::EffectDistract, // 69 SPELL_EFFECT_DISTRACT
  140. &Spell::EffectPull, // 70 SPELL_EFFECT_PULL one spell: Distract Move
  141. &Spell::EffectPickPocket, // 71 SPELL_EFFECT_PICKPOCKET
  142. &Spell::EffectAddFarsight, // 72 SPELL_EFFECT_ADD_FARSIGHT
  143. &Spell::EffectUntrainTalents, // 73 SPELL_EFFECT_UNTRAIN_TALENTS
  144. &Spell::EffectApplyGlyph, // 74 SPELL_EFFECT_APPLY_GLYPH
  145. &Spell::EffectHealMechanical, // 75 SPELL_EFFECT_HEAL_MECHANICAL one spell: Mechanical Patch Kit
  146. &Spell::EffectSummonObjectWild, // 76 SPELL_EFFECT_SUMMON_OBJECT_WILD
  147. &Spell::EffectScriptEffect, // 77 SPELL_EFFECT_SCRIPT_EFFECT
  148. &Spell::EffectUnused, // 78 SPELL_EFFECT_ATTACK
  149. &Spell::EffectSanctuary, // 79 SPELL_EFFECT_SANCTUARY
  150. &Spell::EffectAddComboPoints, // 80 SPELL_EFFECT_ADD_COMBO_POINTS
  151. &Spell::EffectUnused, // 81 SPELL_EFFECT_CREATE_HOUSE one spell: Create House (TEST)
  152. &Spell::EffectNULL, // 82 SPELL_EFFECT_BIND_SIGHT
  153. &Spell::EffectDuel, // 83 SPELL_EFFECT_DUEL
  154. &Spell::EffectStuck, // 84 SPELL_EFFECT_STUCK
  155. &Spell::EffectSummonPlayer, // 85 SPELL_EFFECT_SUMMON_PLAYER
  156. &Spell::EffectActivateObject, // 86 SPELL_EFFECT_ACTIVATE_OBJECT
  157. &Spell::EffectGameObjectDamage, // 87 SPELL_EFFECT_GAMEOBJECT_DAMAGE
  158. &Spell::EffectGameObjectRepair, // 88 SPELL_EFFECT_GAMEOBJECT_REPAIR
  159. &Spell::EffectGameObjectSetDestructionState, // 89 SPELL_EFFECT_GAMEOBJECT_SET_DESTRUCTION_STATE
  160. &Spell::EffectKillCreditPersonal, // 90 SPELL_EFFECT_KILL_CREDIT Kill credit but only for single person
  161. &Spell::EffectUnused, // 91 SPELL_EFFECT_THREAT_ALL one spell: zzOLDBrainwash
  162. &Spell::EffectEnchantHeldItem, // 92 SPELL_EFFECT_ENCHANT_HELD_ITEM
  163. &Spell::EffectForceDeselect, // 93 SPELL_EFFECT_FORCE_DESELECT
  164. &Spell::EffectSelfResurrect, // 94 SPELL_EFFECT_SELF_RESURRECT
  165. &Spell::EffectSkinning, // 95 SPELL_EFFECT_SKINNING
  166. &Spell::EffectCharge, // 96 SPELL_EFFECT_CHARGE
  167. &Spell::EffectCastButtons, // 97 SPELL_EFFECT_CAST_BUTTON (totem bar since 3.2.2a)
  168. &Spell::EffectKnockBack, // 98 SPELL_EFFECT_KNOCK_BACK
  169. &Spell::EffectDisEnchant, // 99 SPELL_EFFECT_DISENCHANT
  170. &Spell::EffectInebriate, //100 SPELL_EFFECT_INEBRIATE
  171. &Spell::EffectFeedPet, //101 SPELL_EFFECT_FEED_PET
  172. &Spell::EffectDismissPet, //102 SPELL_EFFECT_DISMISS_PET
  173. &Spell::EffectReputation, //103 SPELL_EFFECT_REPUTATION
  174. &Spell::EffectSummonObject, //104 SPELL_EFFECT_SUMMON_OBJECT_SLOT1
  175. &Spell::EffectSummonObject, //105 SPELL_EFFECT_SUMMON_OBJECT_SLOT2
  176. &Spell::EffectSummonObject, //106 SPELL_EFFECT_SUMMON_OBJECT_SLOT3
  177. &Spell::EffectSummonObject, //107 SPELL_EFFECT_SUMMON_OBJECT_SLOT4
  178. &Spell::EffectDispelMechanic, //108 SPELL_EFFECT_DISPEL_MECHANIC
  179. &Spell::EffectSummonDeadPet, //109 SPELL_EFFECT_SUMMON_DEAD_PET
  180. &Spell::EffectDestroyAllTotems, //110 SPELL_EFFECT_DESTROY_ALL_TOTEMS
  181. &Spell::EffectDurabilityDamage, //111 SPELL_EFFECT_DURABILITY_DAMAGE
  182. &Spell::EffectUnused, //112 SPELL_EFFECT_112
  183. &Spell::EffectResurrectNew, //113 SPELL_EFFECT_RESURRECT_NEW
  184. &Spell::EffectTaunt, //114 SPELL_EFFECT_ATTACK_ME
  185. &Spell::EffectDurabilityDamagePCT, //115 SPELL_EFFECT_DURABILITY_DAMAGE_PCT
  186. &Spell::EffectSkinPlayerCorpse, //116 SPELL_EFFECT_SKIN_PLAYER_CORPSE one spell: Remove Insignia, bg usage, required special corpse flags...
  187. &Spell::EffectSpiritHeal, //117 SPELL_EFFECT_SPIRIT_HEAL one spell: Spirit Heal
  188. &Spell::EffectSkill, //118 SPELL_EFFECT_SKILL professions and more
  189. &Spell::EffectApplyAreaAura, //119 SPELL_EFFECT_APPLY_AREA_AURA_PET
  190. &Spell::EffectUnused, //120 SPELL_EFFECT_TELEPORT_GRAVEYARD one spell: Graveyard Teleport Test
  191. &Spell::EffectWeaponDmg, //121 SPELL_EFFECT_NORMALIZED_WEAPON_DMG
  192. &Spell::EffectUnused, //122 SPELL_EFFECT_122 unused
  193. &Spell::EffectSendTaxi, //123 SPELL_EFFECT_SEND_TAXI taxi/flight related (misc value is taxi path id)
  194. &Spell::EffectPullTowards, //124 SPELL_EFFECT_PULL_TOWARDS
  195. &Spell::EffectModifyThreatPercent, //125 SPELL_EFFECT_MODIFY_THREAT_PERCENT
  196. &Spell::EffectStealBeneficialBuff, //126 SPELL_EFFECT_STEAL_BENEFICIAL_BUFF spell steal effect?
  197. &Spell::EffectProspecting, //127 SPELL_EFFECT_PROSPECTING Prospecting spell
  198. &Spell::EffectApplyAreaAura, //128 SPELL_EFFECT_APPLY_AREA_AURA_FRIEND
  199. &Spell::EffectApplyAreaAura, //129 SPELL_EFFECT_APPLY_AREA_AURA_ENEMY
  200. &Spell::EffectRedirectThreat, //130 SPELL_EFFECT_REDIRECT_THREAT
  201. &Spell::EffectPlayerNotification, //131 SPELL_EFFECT_PLAYER_NOTIFICATION sound id in misc value (SoundEntries.dbc)
  202. &Spell::EffectPlayMusic, //132 SPELL_EFFECT_PLAY_MUSIC sound id in misc value (SoundEntries.dbc)
  203. &Spell::EffectUnlearnSpecialization, //133 SPELL_EFFECT_UNLEARN_SPECIALIZATION unlearn profession specialization
  204. &Spell::EffectKillCredit, //134 SPELL_EFFECT_KILL_CREDIT misc value is creature entry
  205. &Spell::EffectNULL, //135 SPELL_EFFECT_CALL_PET
  206. &Spell::EffectHealPct, //136 SPELL_EFFECT_HEAL_PCT
  207. &Spell::EffectEnergizePct, //137 SPELL_EFFECT_ENERGIZE_PCT
  208. &Spell::EffectLeapBack, //138 SPELL_EFFECT_LEAP_BACK Leap back
  209. &Spell::EffectQuestClear, //139 SPELL_EFFECT_CLEAR_QUEST Reset quest status (miscValue - quest ID)
  210. &Spell::EffectForceCast, //140 SPELL_EFFECT_FORCE_CAST
  211. &Spell::EffectForceCast, //141 SPELL_EFFECT_FORCE_CAST_WITH_VALUE
  212. &Spell::EffectTriggerSpell, //142 SPELL_EFFECT_TRIGGER_SPELL_WITH_VALUE
  213. &Spell::EffectApplyAreaAura, //143 SPELL_EFFECT_APPLY_AREA_AURA_OWNER
  214. &Spell::EffectKnockBack, //144 SPELL_EFFECT_KNOCK_BACK_DEST
  215. &Spell::EffectPullTowards, //145 SPELL_EFFECT_PULL_TOWARDS_DEST Black Hole Effect
  216. &Spell::EffectActivateRune, //146 SPELL_EFFECT_ACTIVATE_RUNE
  217. &Spell::EffectQuestFail, //147 SPELL_EFFECT_QUEST_FAIL quest fail
  218. &Spell::EffectTriggerMissileSpell, //148 SPELL_EFFECT_TRIGGER_MISSILE_SPELL_WITH_VALUE
  219. &Spell::EffectChargeDest, //149 SPELL_EFFECT_CHARGE_DEST
  220. &Spell::EffectQuestStart, //150 SPELL_EFFECT_QUEST_START
  221. &Spell::EffectTriggerRitualOfSummoning, //151 SPELL_EFFECT_TRIGGER_SPELL_2
  222. &Spell::EffectSummonRaFFriend, //152 SPELL_EFFECT_SUMMON_RAF_FRIEND summon Refer-a-Friend
  223. &Spell::EffectCreateTamedPet, //153 SPELL_EFFECT_CREATE_TAMED_PET misc value is creature entry
  224. &Spell::EffectDiscoverTaxi, //154 SPELL_EFFECT_DISCOVER_TAXI
  225. &Spell::EffectTitanGrip, //155 SPELL_EFFECT_TITAN_GRIP Allows you to equip two-handed axes, maces and swords in one hand, but you attack $49152s1% slower than normal.
  226. &Spell::EffectEnchantItemPrismatic, //156 SPELL_EFFECT_ENCHANT_ITEM_PRISMATIC
  227. &Spell::EffectCreateItem2, //157 SPELL_EFFECT_CREATE_ITEM_2 create item or create item template and replace by some randon spell loot item
  228. &Spell::EffectMilling, //158 SPELL_EFFECT_MILLING milling
  229. &Spell::EffectRenamePet, //159 SPELL_EFFECT_ALLOW_RENAME_PET allow rename pet once again
  230. &Spell::EffectNULL, //160 SPELL_EFFECT_160 1 spell - 45534
  231. &Spell::EffectSpecCount, //161 SPELL_EFFECT_TALENT_SPEC_COUNT second talent spec (learn/revert)
  232. &Spell::EffectActivateSpec, //162 SPELL_EFFECT_TALENT_SPEC_SELECT activate primary/secondary spec
  233. &Spell::EffectNULL, //163 unused
  234. &Spell::EffectRemoveAura, //164 SPELL_EFFECT_REMOVE_AURA
  235. };
  236.  
  237. void Spell::EffectNULL(SpellEffIndex /*effIndex*/)
  238. {
  239. sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "WORLD: Spell Effect DUMMY");
  240. }
  241.  
  242. void Spell::EffectUnused(SpellEffIndex /*effIndex*/)
  243. {
  244. // NOT USED BY ANY SPELL OR USELESS OR IMPLEMENTED IN DIFFERENT WAY IN TRINITY
  245. }
  246.  
  247. void Spell::EffectResurrectNew(SpellEffIndex effIndex)
  248. {
  249. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
  250. return;
  251.  
  252. if (!unitTarget || unitTarget->isAlive())
  253. return;
  254.  
  255. if (unitTarget->GetTypeId() != TYPEID_PLAYER)
  256. return;
  257.  
  258. if (!unitTarget->IsInWorld())
  259. return;
  260.  
  261. Player* target = unitTarget->ToPlayer();
  262.  
  263. if (target->isRessurectRequested()) // already have one active request
  264. return;
  265.  
  266. uint32 health = damage;
  267. uint32 mana = m_spellInfo->Effects[effIndex].MiscValue;
  268. ExecuteLogEffectResurrect(effIndex, target);
  269. target->setResurrectRequestData(m_caster->GetGUID(), m_caster->GetMapId(), m_caster->GetPositionX(), m_caster->GetPositionY(), m_caster->GetPositionZ(), health, mana);
  270. SendResurrectRequest(target);
  271. }
  272.  
  273. void Spell::EffectInstaKill(SpellEffIndex /*effIndex*/)
  274. {
  275. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
  276. return;
  277.  
  278. if (!unitTarget || !unitTarget->isAlive())
  279. return;
  280.  
  281. if (unitTarget->GetTypeId() == TYPEID_PLAYER)
  282. if (unitTarget->ToPlayer()->GetCommandStatus(CHEAT_GOD))
  283. return;
  284.  
  285. if (m_caster == unitTarget) // prevent interrupt message
  286. finish();
  287.  
  288. WorldPacket data(SMSG_SPELLINSTAKILLLOG, 8+8+4);
  289. data << uint64(m_caster->GetGUID());
  290. data << uint64(unitTarget->GetGUID());
  291. data << uint32(m_spellInfo->Id);
  292. m_caster->SendMessageToSet(&data, true);
  293.  
  294. m_caster->DealDamage(unitTarget, unitTarget->GetHealth(), NULL, NODAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
  295. }
  296.  
  297. void Spell::EffectEnvironmentalDMG(SpellEffIndex /*effIndex*/)
  298. {
  299. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
  300. return;
  301.  
  302. if (!unitTarget || !unitTarget->isAlive())
  303. return;
  304.  
  305. uint32 absorb = 0;
  306. uint32 resist = 0;
  307.  
  308. m_caster->CalcAbsorbResist(unitTarget, m_spellInfo->GetSchoolMask(), SPELL_DIRECT_DAMAGE, damage, &absorb, &resist, m_spellInfo);
  309.  
  310. m_caster->SendSpellNonMeleeDamageLog(unitTarget, m_spellInfo->Id, damage, m_spellInfo->GetSchoolMask(), absorb, resist, false, 0, false);
  311. if (unitTarget->GetTypeId() == TYPEID_PLAYER)
  312. unitTarget->ToPlayer()->EnvironmentalDamage(DAMAGE_FIRE, damage);
  313. }
  314.  
  315. void Spell::EffectSchoolDMG(SpellEffIndex effIndex)
  316. {
  317. if (effectHandleMode != SPELL_EFFECT_HANDLE_LAUNCH_TARGET)
  318. return;
  319.  
  320. if (unitTarget && unitTarget->isAlive())
  321. {
  322. bool apply_direct_bonus = true;
  323. switch (m_spellInfo->SpellFamilyName)
  324. {
  325. case SPELLFAMILY_GENERIC:
  326. {
  327. // Meteor like spells (divided damage to targets)
  328. if (m_spellInfo->AttributesCu & SPELL_ATTR0_CU_SHARE_DAMAGE)
  329. {
  330. uint32 count = 0;
  331. for (std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
  332. if (ihit->effectMask & (1<<effIndex))
  333. ++count;
  334.  
  335. damage /= count; // divide to all targets
  336. }
  337.  
  338. switch (m_spellInfo->Id) // better way to check unknown
  339. {
  340. // Consumption
  341. case 28865:
  342. damage = (((InstanceMap*)m_caster->GetMap())->GetDifficulty() == REGULAR_DIFFICULTY ? 2750 : 4250);
  343. break;
  344. // percent from health with min
  345. case 25599: // Thundercrash
  346. {
  347. damage = unitTarget->GetHealth() / 2;
  348. if (damage < 200)
  349. damage = 200;
  350. break;
  351. }
  352. // arcane charge. must only affect demons (also undead?)
  353. case 45072:
  354. {
  355. if (unitTarget->GetCreatureType() != CREATURE_TYPE_DEMON
  356. && unitTarget->GetCreatureType() != CREATURE_TYPE_UNDEAD)
  357. return;
  358. break;
  359. }
  360. // Gargoyle Strike
  361. case 51963:
  362. {
  363. // about +4 base spell dmg per level
  364. damage = (m_caster->getLevel() - 60) * 4 + 60;
  365. break;
  366. }
  367. }
  368. break;
  369. }
  370. case SPELLFAMILY_WARRIOR:
  371. {
  372. // Shield Slam
  373. if (m_spellInfo->SpellFamilyFlags[1] & 0x200 && m_spellInfo->Category == 1209)
  374. {
  375. uint8 level = m_caster->getLevel();
  376. uint32 block_value = m_caster->GetShieldBlockValue(uint32(float(level) * 24.5f), uint32(float(level) * 34.5f));
  377. damage += int32(m_caster->ApplyEffectModifiers(m_spellInfo, effIndex, float(block_value)));
  378. }
  379. // Victory Rush
  380. else if (m_spellInfo->SpellFamilyFlags[1] & 0x100)
  381. ApplyPct(damage, m_caster->GetTotalAttackPowerValue(BASE_ATTACK));
  382. // Shockwave
  383. else if (m_spellInfo->Id == 46968)
  384. {
  385. int32 pct = m_caster->CalculateSpellDamage(unitTarget, m_spellInfo, 2);
  386. if (pct > 0)
  387. damage += int32(CalculatePct(m_caster->GetTotalAttackPowerValue(BASE_ATTACK), pct));
  388. break;
  389. }
  390. break;
  391. }
  392. case SPELLFAMILY_WARLOCK:
  393. {
  394. // Incinerate Rank 1 & 2
  395. if ((m_spellInfo->SpellFamilyFlags[1] & 0x000040) && m_spellInfo->SpellIconID == 2128)
  396. {
  397. // Incinerate does more dmg (dmg*0.25) if the target have Immolate debuff.
  398. // Check aura state for speed but aura state set not only for Immolate spell
  399. if (unitTarget->HasAuraState(AURA_STATE_CONFLAGRATE))
  400. {
  401. if (unitTarget->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_WARLOCK, 0x4, 0, 0))
  402. damage += damage/4;
  403. }
  404. }
  405. // Conflagrate - consumes Immolate or Shadowflame
  406. else if (m_spellInfo->TargetAuraState == AURA_STATE_CONFLAGRATE)
  407. {
  408. AuraEffect const* aura = NULL; // found req. aura for damage calculation
  409.  
  410. Unit::AuraEffectList const &mPeriodic = unitTarget->GetAuraEffectsByType(SPELL_AURA_PERIODIC_DAMAGE);
  411. for (Unit::AuraEffectList::const_iterator i = mPeriodic.begin(); i != mPeriodic.end(); ++i)
  412. {
  413. // for caster applied auras only
  414. if ((*i)->GetSpellInfo()->SpellFamilyName != SPELLFAMILY_WARLOCK ||
  415. (*i)->GetCasterGUID() != m_caster->GetGUID())
  416. continue;
  417.  
  418. // Immolate
  419. if ((*i)->GetSpellInfo()->SpellFamilyFlags[0] & 0x4)
  420. {
  421. aura = *i; // it selected always if exist
  422. break;
  423. }
  424.  
  425. // Shadowflame
  426. if ((*i)->GetSpellInfo()->SpellFamilyFlags[2] & 0x00000002)
  427. aura = *i; // remember but wait possible Immolate as primary priority
  428. }
  429.  
  430. // found Immolate or Shadowflame
  431. if (aura)
  432. {
  433. uint32 pdamage = uint32(std::max(aura->GetAmount(), 0));
  434. pdamage = m_caster->SpellDamageBonusDone(unitTarget, aura->GetSpellInfo(), pdamage, DOT, aura->GetBase()->GetStackAmount());
  435. pdamage = unitTarget->SpellDamageBonusTaken(m_caster, aura->GetSpellInfo(), pdamage, DOT, aura->GetBase()->GetStackAmount());
  436. uint32 pct_dir = m_caster->CalculateSpellDamage(unitTarget, m_spellInfo, (effIndex + 1));
  437. uint8 baseTotalTicks = uint8(m_caster->CalcSpellDuration(aura->GetSpellInfo()) / aura->GetSpellInfo()->Effects[EFFECT_0].Amplitude);
  438. damage += int32(CalculatePct(pdamage * baseTotalTicks, pct_dir));
  439.  
  440. uint32 pct_dot = m_caster->CalculateSpellDamage(unitTarget, m_spellInfo, (effIndex + 2)) / 3;
  441. m_spellValue->EffectBasePoints[1] = m_spellInfo->Effects[EFFECT_1].CalcBaseValue(int32(CalculatePct(pdamage * baseTotalTicks, pct_dot)));
  442.  
  443. apply_direct_bonus = false;
  444. // Glyph of Conflagrate
  445. if (!m_caster->HasAura(56235))
  446. unitTarget->RemoveAurasDueToSpell(aura->GetId(), m_caster->GetGUID());
  447.  
  448. break;
  449. }
  450. }
  451. // Shadow Bite
  452. else if (m_spellInfo->SpellFamilyFlags[1] & 0x400000)
  453. {
  454. if (m_caster->GetTypeId() == TYPEID_UNIT && m_caster->ToCreature()->isPet())
  455. {
  456. if (Player* owner = m_caster->GetOwner()->ToPlayer())
  457. {
  458. if (AuraEffect* aurEff = owner->GetAuraEffect(SPELL_AURA_ADD_FLAT_MODIFIER, SPELLFAMILY_WARLOCK, 214, 0))
  459. {
  460. int32 bp0 = aurEff->GetId() == 54037 ? 4 : 8;
  461. m_caster->CastCustomSpell(m_caster, 54425, &bp0, NULL, NULL, true);
  462. }
  463. }
  464. }
  465. }
  466. break;
  467. }
  468. case SPELLFAMILY_PRIEST:
  469. {
  470. // Improved Mind Blast (Mind Blast in shadow form bonus)
  471. if (m_caster->GetShapeshiftForm() == FORM_SHADOW && (m_spellInfo->SpellFamilyFlags[0] & 0x00002000))
  472. {
  473. Unit::AuraEffectList const& ImprMindBlast = m_caster->GetAuraEffectsByType(SPELL_AURA_ADD_FLAT_MODIFIER);
  474. for (Unit::AuraEffectList::const_iterator i = ImprMindBlast.begin(); i != ImprMindBlast.end(); ++i)
  475. {
  476. if ((*i)->GetSpellInfo()->SpellFamilyName == SPELLFAMILY_PRIEST &&
  477. ((*i)->GetSpellInfo()->SpellIconID == 95))
  478. {
  479. int chance = (*i)->GetSpellInfo()->Effects[EFFECT_1].CalcValue(m_caster);
  480. if (roll_chance_i(chance))
  481. // Mind Trauma
  482. m_caster->CastSpell(unitTarget, 48301, true, 0);
  483. break;
  484. }
  485. }
  486. }
  487. break;
  488. }
  489. case SPELLFAMILY_DRUID:
  490. {
  491. // Ferocious Bite
  492. if (m_caster->GetTypeId() == TYPEID_PLAYER && (m_spellInfo->SpellFamilyFlags[0] & 0x000800000) && m_spellInfo->SpellVisual[0] == 6587)
  493. {
  494. // converts each extra point of energy into ($f1+$AP/410) additional damage
  495. float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
  496. float multiple = ap / 410 + m_spellInfo->Effects[effIndex].DamageMultiplier;
  497. int32 energy = -(m_caster->ModifyPower(POWER_ENERGY, -30));
  498. damage += int32(energy * multiple);
  499. damage += int32(CalculatePct(m_caster->ToPlayer()->GetComboPoints() * ap, 7));
  500. }
  501. // Wrath
  502. else if (m_spellInfo->SpellFamilyFlags[0] & 0x00000001)
  503. {
  504. // Improved Insect Swarm
  505. if (AuraEffect const* aurEff = m_caster->GetDummyAuraEffect(SPELLFAMILY_DRUID, 1771, 0))
  506. if (unitTarget->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_DRUID, 0x00200000, 0, 0))
  507. AddPct(damage, aurEff->GetAmount());
  508. }
  509. break;
  510. }
  511. case SPELLFAMILY_ROGUE:
  512. {
  513. // Envenom
  514. if (m_spellInfo->SpellFamilyFlags[1] & 0x00000008)
  515. {
  516. if (Player* player = m_caster->ToPlayer())
  517. {
  518. // consume from stack dozes not more that have combo-points
  519. if (uint32 combo = player->GetComboPoints())
  520. {
  521. // Lookup for Deadly poison (only attacker applied)
  522. if (AuraEffect const* aurEff = unitTarget->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_ROGUE, 0x00010000, 0, 0, m_caster->GetGUID()))
  523. {
  524. // count consumed deadly poison doses at target
  525. bool needConsume = true;
  526. uint32 spellId = aurEff->GetId();
  527.  
  528. uint32 doses = aurEff->GetBase()->GetStackAmount();
  529. if (doses > combo)
  530. doses = combo;
  531.  
  532. // Master Poisoner
  533. Unit::AuraEffectList const& auraList = player->GetAuraEffectsByType(SPELL_AURA_MOD_AURA_DURATION_BY_DISPEL_NOT_STACK);
  534. for (Unit::AuraEffectList::const_iterator iter = auraList.begin(); iter != auraList.end(); ++iter)
  535. {
  536. if ((*iter)->GetSpellInfo()->SpellFamilyName == SPELLFAMILY_ROGUE && (*iter)->GetSpellInfo()->SpellIconID == 1960)
  537. {
  538. uint32 chance = (*iter)->GetSpellInfo()->Effects[EFFECT_2].CalcValue(m_caster);
  539.  
  540. if (chance && roll_chance_i(chance))
  541. needConsume = false;
  542.  
  543. break;
  544. }
  545. }
  546.  
  547. if (needConsume)
  548. for (uint32 i = 0; i < doses; ++i)
  549. unitTarget->RemoveAuraFromStack(spellId);
  550.  
  551. damage *= doses;
  552. damage += int32(player->GetTotalAttackPowerValue(BASE_ATTACK) * 0.09f * combo);
  553. }
  554.  
  555. // Eviscerate and Envenom Bonus Damage (item set effect)
  556. if (m_caster->HasAura(37169))
  557. damage += combo * 40;
  558. }
  559. }
  560. }
  561. // Eviscerate
  562. else if (m_spellInfo->SpellFamilyFlags[0] & 0x00020000)
  563. {
  564. if (m_caster->GetTypeId() == TYPEID_PLAYER)
  565. {
  566. if (uint32 combo = ((Player*)m_caster)->GetComboPoints())
  567. {
  568. float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
  569. damage += irand(int32(ap * combo * 0.03f), int32(ap * combo * 0.07f));
  570.  
  571. // Eviscerate and Envenom Bonus Damage (item set effect)
  572. if (m_caster->HasAura(37169))
  573. damage += combo*40;
  574. }
  575. }
  576. }
  577. break;
  578. }
  579. case SPELLFAMILY_HUNTER:
  580. {
  581. //Gore
  582. if (m_spellInfo->SpellIconID == 1578)
  583. {
  584. if (m_caster->HasAura(57627)) // Charge 6 sec post-affect
  585. damage *= 2;
  586. }
  587. // Steady Shot
  588. else if (m_spellInfo->SpellFamilyFlags[1] & 0x1)
  589. {
  590. bool found = false;
  591. // check dazed affect
  592. Unit::AuraEffectList const& decSpeedList = unitTarget->GetAuraEffectsByType(SPELL_AURA_MOD_DECREASE_SPEED);
  593. for (Unit::AuraEffectList::const_iterator iter = decSpeedList.begin(); iter != decSpeedList.end(); ++iter)
  594. {
  595. if ((*iter)->GetSpellInfo()->SpellIconID == 15 && (*iter)->GetSpellInfo()->Dispel == 0)
  596. {
  597. found = true;
  598. break;
  599. }
  600. }
  601.  
  602. // TODO: should this be put on taken but not done?
  603. if (found)
  604. damage += m_spellInfo->Effects[EFFECT_1].CalcValue();
  605.  
  606. if (Player* caster = m_caster->ToPlayer())
  607. {
  608. // Add Ammo and Weapon damage plus RAP * 0.1
  609. if (Item* item = caster->GetWeaponForAttack(RANGED_ATTACK))
  610. {
  611. ItemTemplate const* weaponTemplate = item->GetTemplate();
  612. float dmg_min = weaponTemplate->Damage[0].DamageMin;
  613. float dmg_max = weaponTemplate->Damage[0].DamageMax;
  614. if (dmg_max == 0.0f && dmg_min > dmg_max)
  615. damage += int32(dmg_min);
  616. else
  617. damage += irand(int32(dmg_min), int32(dmg_max));
  618. damage += int32(caster->GetAmmoDPS() * weaponTemplate->Delay * 0.001f);
  619. }
  620. }
  621. }
  622. break;
  623. }
  624. case SPELLFAMILY_PALADIN:
  625. {
  626. // Hammer of the Righteous
  627. if (m_spellInfo->SpellFamilyFlags[1]&0x00040000)
  628. {
  629. // Add main hand dps * effect[2] amount
  630. float average = (m_caster->GetFloatValue(UNIT_FIELD_MINDAMAGE) + m_caster->GetFloatValue(UNIT_FIELD_MAXDAMAGE)) / 2;
  631. int32 count = m_caster->CalculateSpellDamage(unitTarget, m_spellInfo, EFFECT_2);
  632. damage += count * int32(average * IN_MILLISECONDS) / m_caster->GetAttackTime(BASE_ATTACK);
  633. break;
  634. }
  635. // Shield of Righteousness
  636. if (m_spellInfo->SpellFamilyFlags[EFFECT_1] & 0x100000)
  637. {
  638. uint8 level = m_caster->getLevel();
  639. uint32 block_value = m_caster->GetShieldBlockValue(uint32(float(level) * 29.5f), uint32(float(level) * 39.5f));
  640. damage += CalculatePct(block_value, m_spellInfo->Effects[EFFECT_1].CalcValue());
  641. break;
  642. }
  643. break;
  644. }
  645. case SPELLFAMILY_DEATHKNIGHT:
  646. {
  647. // Blood Boil - bonus for diseased targets
  648. if (m_spellInfo->SpellFamilyFlags[0] & 0x00040000)
  649. {
  650. if (unitTarget->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_DEATHKNIGHT, 0, 0, 0x00000002, m_caster->GetGUID()))
  651. {
  652. damage += m_damage / 2;
  653. damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * 0.035f);
  654. }
  655. }
  656. break;
  657. }
  658. case SPELLFAMILY_MAGE:
  659. {
  660. // Deep Freeze should deal damage to permanently stun-immune targets.
  661. if (m_spellInfo->Id == 71757)
  662. if (unitTarget->GetTypeId() != TYPEID_UNIT || !(unitTarget->IsImmunedToSpellEffect(sSpellMgr->GetSpellInfo(44572), 0)))
  663. return;
  664. break;
  665. }
  666. }
  667.  
  668. if (m_originalCaster && damage > 0 && apply_direct_bonus)
  669. {
  670. damage = m_originalCaster->SpellDamageBonusDone(unitTarget, m_spellInfo, (uint32)damage, SPELL_DIRECT_DAMAGE);
  671. damage = unitTarget->SpellDamageBonusTaken(m_originalCaster, m_spellInfo, (uint32)damage, SPELL_DIRECT_DAMAGE);
  672. }
  673.  
  674. m_damage += damage;
  675. }
  676. }
  677.  
  678. void Spell::EffectDummy(SpellEffIndex effIndex)
  679. {
  680. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
  681. return;
  682.  
  683. if (!unitTarget && !gameObjTarget && !itemTarget)
  684. return;
  685.  
  686. uint32 spell_id = 0;
  687. int32 bp = 0;
  688. bool triggered = true;
  689. SpellCastTargets targets;
  690.  
  691. // selection by spell family
  692. switch (m_spellInfo->SpellFamilyName)
  693. {
  694. case SPELLFAMILY_PALADIN:
  695. switch (m_spellInfo->Id)
  696. {
  697. case 31789: // Righteous Defense (step 1)
  698. {
  699. // Clear targets for eff 1
  700. for (std::list<TargetInfo>::iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
  701. ihit->effectMask &= ~(1<<1);
  702.  
  703. // not empty (checked), copy
  704. Unit::AttackerSet attackers = unitTarget->getAttackers();
  705.  
  706. // remove invalid attackers
  707. for (Unit::AttackerSet::iterator aItr = attackers.begin(); aItr != attackers.end();)
  708. if (!(*aItr)->IsValidAttackTarget(m_caster))
  709. attackers.erase(aItr++);
  710. else
  711. ++aItr;
  712.  
  713. // selected from list 3
  714. uint32 maxTargets = std::min<uint32>(3, attackers.size());
  715. for (uint32 i = 0; i < maxTargets; ++i)
  716. {
  717. Unit* attacker = Trinity::Containers::SelectRandomContainerElement(attackers);
  718. AddUnitTarget(attacker, 1 << 1);
  719. attackers.erase(attacker);
  720. }
  721.  
  722. // now let next effect cast spell at each target.
  723. return;
  724. }
  725. }
  726. break;
  727. case SPELLFAMILY_DEATHKNIGHT:
  728. switch (m_spellInfo->Id)
  729. {
  730. case 46584: // Raise Dead
  731. if (m_caster->GetTypeId() != TYPEID_PLAYER)
  732. return;
  733.  
  734. // Do we have talent Master of Ghouls?
  735. if (m_caster->HasAura(52143))
  736. // summon as pet
  737. bp = 52150;
  738. else
  739. // or guardian
  740. bp = 46585;
  741.  
  742. if (m_targets.HasDst())
  743. targets.SetDst(*m_targets.GetDstPos());
  744. else
  745. {
  746. targets.SetDst(*m_caster);
  747. // Corpse not found - take reagents (only not triggered cast can take them)
  748. triggered = false;
  749. }
  750. // Remove cooldown - summon spellls have category
  751. m_caster->ToPlayer()->RemoveSpellCooldown(m_spellInfo->Id, true);
  752. spell_id = 48289;
  753. break;
  754. // Raise dead - take reagents and trigger summon spells
  755. case 48289:
  756. if (m_targets.HasDst())
  757. targets.SetDst(*m_targets.GetDstPos());
  758. spell_id = CalculateDamage(0, NULL);
  759. break;
  760. }
  761. break;
  762. }
  763.  
  764. //spells triggered by dummy effect should not miss
  765. if (spell_id)
  766. {
  767. SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spell_id);
  768.  
  769. if (!spellInfo)
  770. {
  771. sLog->outError(LOG_FILTER_SPELLS_AURAS, "EffectDummy of spell %u: triggering unknown spell id %i\n", m_spellInfo->Id, spell_id);
  772. return;
  773. }
  774.  
  775. targets.SetUnitTarget(unitTarget);
  776. Spell* spell = new Spell(m_caster, spellInfo, triggered ? TRIGGERED_FULL_MASK : TRIGGERED_NONE, m_originalCasterGUID, true);
  777. if (bp) spell->SetSpellValue(SPELLVALUE_BASE_POINT0, bp);
  778. spell->prepare(&targets);
  779. }
  780.  
  781. // pet auras
  782. if (PetAura const* petSpell = sSpellMgr->GetPetAura(m_spellInfo->Id, effIndex))
  783. {
  784. m_caster->AddPetAura(petSpell);
  785. return;
  786. }
  787.  
  788. // normal DB scripted effect
  789. sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "Spell ScriptStart spellid %u in EffectDummy(%u)", m_spellInfo->Id, effIndex);
  790. m_caster->GetMap()->ScriptsStart(sSpellScripts, uint32(m_spellInfo->Id | (effIndex << 24)), m_caster, unitTarget);
  791.  
  792. // Script based implementation. Must be used only for not good for implementation in core spell effects
  793. // So called only for not proccessed cases
  794. if (gameObjTarget)
  795. sScriptMgr->OnDummyEffect(m_caster, m_spellInfo->Id, effIndex, gameObjTarget);
  796. else if (unitTarget && unitTarget->GetTypeId() == TYPEID_UNIT)
  797. sScriptMgr->OnDummyEffect(m_caster, m_spellInfo->Id, effIndex, unitTarget->ToCreature());
  798. else if (itemTarget)
  799. sScriptMgr->OnDummyEffect(m_caster, m_spellInfo->Id, effIndex, itemTarget);
  800. }
  801.  
  802. void Spell::EffectTriggerSpell(SpellEffIndex effIndex)
  803. {
  804. if (effectHandleMode != SPELL_EFFECT_HANDLE_LAUNCH_TARGET
  805. && effectHandleMode != SPELL_EFFECT_HANDLE_LAUNCH)
  806. return;
  807.  
  808. uint32 triggered_spell_id = m_spellInfo->Effects[effIndex].TriggerSpell;
  809.  
  810. // todo: move those to spell scripts
  811. if (m_spellInfo->Effects[effIndex].Effect == SPELL_EFFECT_TRIGGER_SPELL
  812. && effectHandleMode == SPELL_EFFECT_HANDLE_LAUNCH_TARGET)
  813. {
  814. // special cases
  815. switch (triggered_spell_id)
  816. {
  817. // Mirror Image
  818. case 58832:
  819. {
  820. // Glyph of Mirror Image
  821. if (m_caster->HasAura(63093))
  822. m_caster->CastSpell(m_caster, 65047, true); // Mirror Image
  823.  
  824. break;
  825. }
  826. // Vanish (not exist)
  827. case 18461:
  828. {
  829. unitTarget->RemoveMovementImpairingAuras();
  830. unitTarget->RemoveAurasByType(SPELL_AURA_MOD_STALKED);
  831.  
  832. // If this spell is given to an NPC, it must handle the rest using its own AI
  833. if (unitTarget->GetTypeId() != TYPEID_PLAYER)
  834. return;
  835.  
  836. // See if we already are stealthed. If so, we're done.
  837. if (unitTarget->HasAura(1784))
  838. return;
  839.  
  840. // Reset cooldown on stealth if needed
  841. if (unitTarget->ToPlayer()->HasSpellCooldown(1784))
  842. unitTarget->ToPlayer()->RemoveSpellCooldown(1784);
  843.  
  844. unitTarget->CastSpell(unitTarget, 1784, true);
  845. return;
  846. }
  847. // Demonic Empowerment -- succubus
  848. case 54437:
  849. {
  850. unitTarget->RemoveMovementImpairingAuras();
  851. unitTarget->RemoveAurasByType(SPELL_AURA_MOD_STALKED);
  852. unitTarget->RemoveAurasByType(SPELL_AURA_MOD_STUN);
  853.  
  854. // Cast Lesser Invisibility
  855. unitTarget->CastSpell(unitTarget, 7870, true);
  856. return;
  857. }
  858. // just skip
  859. case 23770: // Sayge's Dark Fortune of *
  860. // not exist, common cooldown can be implemented in scripts if need.
  861. return;
  862. // Brittle Armor - (need add max stack of 24575 Brittle Armor)
  863. case 29284:
  864. {
  865. // Brittle Armor
  866. SpellInfo const* spell = sSpellMgr->GetSpellInfo(24575);
  867. if (!spell)
  868. return;
  869.  
  870. for (uint32 j = 0; j < spell->StackAmount; ++j)
  871. m_caster->CastSpell(unitTarget, spell->Id, true);
  872. return;
  873. }
  874. // Mercurial Shield - (need add max stack of 26464 Mercurial Shield)
  875. case 29286:
  876. {
  877. // Mercurial Shield
  878. SpellInfo const* spell = sSpellMgr->GetSpellInfo(26464);
  879. if (!spell)
  880. return;
  881.  
  882. for (uint32 j = 0; j < spell->StackAmount; ++j)
  883. m_caster->CastSpell(unitTarget, spell->Id, true);
  884. return;
  885. }
  886. // Righteous Defense
  887. case 31980:
  888. {
  889. m_caster->CastSpell(unitTarget, 31790, true);
  890. return;
  891. }
  892. // Cloak of Shadows
  893. case 35729:
  894. {
  895. uint32 dispelMask = SpellInfo::GetDispelMask(DISPEL_ALL);
  896. Unit::AuraApplicationMap& Auras = unitTarget->GetAppliedAuras();
  897. for (Unit::AuraApplicationMap::iterator iter = Auras.begin(); iter != Auras.end();)
  898. {
  899. // remove all harmful spells on you...
  900. SpellInfo const* spell = iter->second->GetBase()->GetSpellInfo();
  901. if ((spell->DmgClass == SPELL_DAMAGE_CLASS_MAGIC // only affect magic spells
  902. || ((spell->GetDispelMask()) & dispelMask))
  903. // ignore positive and passive auras
  904. && !iter->second->IsPositive() && !iter->second->GetBase()->IsPassive())
  905. {
  906. m_caster->RemoveAura(iter);
  907. }
  908. else
  909. ++iter;
  910. }
  911. return;
  912. }
  913. }
  914. }
  915.  
  916. // normal case
  917. SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(triggered_spell_id);
  918. if (!spellInfo)
  919. {
  920. sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "Spell::EffectTriggerSpell spell %u tried to trigger unknown spell %u", m_spellInfo->Id, triggered_spell_id);
  921. return;
  922. }
  923.  
  924. SpellCastTargets targets;
  925. if (effectHandleMode == SPELL_EFFECT_HANDLE_LAUNCH_TARGET)
  926. {
  927. if (!spellInfo->NeedsToBeTriggeredByCaster())
  928. return;
  929. targets.SetUnitTarget(unitTarget);
  930. }
  931. else //if (effectHandleMode == SPELL_EFFECT_HANDLE_LAUNCH)
  932. {
  933. if (spellInfo->NeedsToBeTriggeredByCaster() && (m_spellInfo->Effects[effIndex].GetProvidedTargetMask() & TARGET_FLAG_UNIT_MASK))
  934. return;
  935.  
  936. if (spellInfo->GetExplicitTargetMask() & TARGET_FLAG_DEST_LOCATION)
  937. targets.SetDst(m_targets);
  938.  
  939. targets.SetUnitTarget(m_caster);
  940. }
  941.  
  942. CustomSpellValues values;
  943. // set basepoints for trigger with value effect
  944. if (m_spellInfo->Effects[effIndex].Effect == SPELL_EFFECT_TRIGGER_SPELL_WITH_VALUE)
  945. {
  946. // maybe need to set value only when basepoints == 0?
  947. values.AddSpellMod(SPELLVALUE_BASE_POINT0, damage);
  948. values.AddSpellMod(SPELLVALUE_BASE_POINT1, damage);
  949. values.AddSpellMod(SPELLVALUE_BASE_POINT2, damage);
  950. }
  951.  
  952. // Remove spell cooldown (not category) if spell triggering spell with cooldown and same category
  953. if (m_caster->GetTypeId() == TYPEID_PLAYER && m_spellInfo->CategoryRecoveryTime && spellInfo->CategoryRecoveryTime
  954. && m_spellInfo->Category == spellInfo->Category)
  955. m_caster->ToPlayer()->RemoveSpellCooldown(spellInfo->Id);
  956.  
  957. // original caster guid only for GO cast
  958. m_caster->CastSpell(targets, spellInfo, &values, TRIGGERED_FULL_MASK, NULL, NULL, m_originalCasterGUID);
  959. }
  960.  
  961. void Spell::EffectTriggerMissileSpell(SpellEffIndex effIndex)
  962. {
  963. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET
  964. && effectHandleMode != SPELL_EFFECT_HANDLE_HIT)
  965. return;
  966.  
  967. uint32 triggered_spell_id = m_spellInfo->Effects[effIndex].TriggerSpell;
  968.  
  969. // normal case
  970. SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(triggered_spell_id);
  971. if (!spellInfo)
  972. {
  973. sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "Spell::EffectTriggerMissileSpell spell %u tried to trigger unknown spell %u", m_spellInfo->Id, triggered_spell_id);
  974. return;
  975. }
  976.  
  977. SpellCastTargets targets;
  978. if (effectHandleMode == SPELL_EFFECT_HANDLE_HIT_TARGET)
  979. {
  980. if (!spellInfo->NeedsToBeTriggeredByCaster())
  981. return;
  982. targets.SetUnitTarget(unitTarget);
  983. }
  984. else //if (effectHandleMode == SPELL_EFFECT_HANDLE_HIT)
  985. {
  986. if (spellInfo->NeedsToBeTriggeredByCaster() && (m_spellInfo->Effects[effIndex].GetProvidedTargetMask() & TARGET_FLAG_UNIT_MASK))
  987. return;
  988.  
  989. if (spellInfo->GetExplicitTargetMask() & TARGET_FLAG_DEST_LOCATION)
  990. targets.SetDst(m_targets);
  991.  
  992. targets.SetUnitTarget(m_caster);
  993. }
  994.  
  995. CustomSpellValues values;
  996. // set basepoints for trigger with value effect
  997. if (m_spellInfo->Effects[effIndex].Effect == SPELL_EFFECT_TRIGGER_MISSILE_SPELL_WITH_VALUE)
  998. {
  999. // maybe need to set value only when basepoints == 0?
  1000. values.AddSpellMod(SPELLVALUE_BASE_POINT0, damage);
  1001. values.AddSpellMod(SPELLVALUE_BASE_POINT1, damage);
  1002. values.AddSpellMod(SPELLVALUE_BASE_POINT2, damage);
  1003. }
  1004.  
  1005. // Remove spell cooldown (not category) if spell triggering spell with cooldown and same category
  1006. if (m_caster->GetTypeId() == TYPEID_PLAYER && m_spellInfo->CategoryRecoveryTime && spellInfo->CategoryRecoveryTime
  1007. && m_spellInfo->Category == spellInfo->Category)
  1008. m_caster->ToPlayer()->RemoveSpellCooldown(spellInfo->Id);
  1009.  
  1010. // original caster guid only for GO cast
  1011. m_caster->CastSpell(targets, spellInfo, &values, TRIGGERED_FULL_MASK, NULL, NULL, m_originalCasterGUID);
  1012. }
  1013.  
  1014. void Spell::EffectForceCast(SpellEffIndex effIndex)
  1015. {
  1016. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
  1017. return;
  1018.  
  1019. if (!unitTarget)
  1020. return;
  1021.  
  1022. uint32 triggered_spell_id = m_spellInfo->Effects[effIndex].TriggerSpell;
  1023.  
  1024. // normal case
  1025. SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(triggered_spell_id);
  1026.  
  1027. if (!spellInfo)
  1028. {
  1029. sLog->outError(LOG_FILTER_SPELLS_AURAS, "Spell::EffectForceCast of spell %u: triggering unknown spell id %i", m_spellInfo->Id, triggered_spell_id);
  1030. return;
  1031. }
  1032.  
  1033. if (m_spellInfo->Effects[effIndex].Effect == SPELL_EFFECT_FORCE_CAST && damage)
  1034. {
  1035. switch (m_spellInfo->Id)
  1036. {
  1037. case 52588: // Skeletal Gryphon Escape
  1038. case 48598: // Ride Flamebringer Cue
  1039. unitTarget->RemoveAura(damage);
  1040. break;
  1041. case 52463: // Hide In Mine Car
  1042. case 52349: // Overtake
  1043. unitTarget->CastCustomSpell(unitTarget, spellInfo->Id, &damage, NULL, NULL, true, NULL, NULL, m_originalCasterGUID);
  1044. return;
  1045. }
  1046. }
  1047.  
  1048. CustomSpellValues values;
  1049. // set basepoints for trigger with value effect
  1050. if (m_spellInfo->Effects[effIndex].Effect == SPELL_EFFECT_FORCE_CAST_WITH_VALUE)
  1051. {
  1052. // maybe need to set value only when basepoints == 0?
  1053. values.AddSpellMod(SPELLVALUE_BASE_POINT0, damage);
  1054. values.AddSpellMod(SPELLVALUE_BASE_POINT1, damage);
  1055. values.AddSpellMod(SPELLVALUE_BASE_POINT2, damage);
  1056. }
  1057.  
  1058. SpellCastTargets targets;
  1059. targets.SetUnitTarget(m_caster);
  1060.  
  1061. unitTarget->CastSpell(targets, spellInfo, &values, TRIGGERED_FULL_MASK);
  1062. }
  1063.  
  1064. void Spell::EffectTriggerRitualOfSummoning(SpellEffIndex effIndex)
  1065. {
  1066. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT)
  1067. return;
  1068.  
  1069. uint32 triggered_spell_id = m_spellInfo->Effects[effIndex].TriggerSpell;
  1070. SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(triggered_spell_id);
  1071.  
  1072. if (!spellInfo)
  1073. {
  1074. sLog->outError(LOG_FILTER_SPELLS_AURAS, "EffectTriggerRitualOfSummoning of spell %u: triggering unknown spell id %i", m_spellInfo->Id, triggered_spell_id);
  1075. return;
  1076. }
  1077.  
  1078. finish();
  1079.  
  1080. m_caster->CastSpell((Unit*)NULL, spellInfo, false);
  1081. }
  1082.  
  1083. void Spell::EffectJump(SpellEffIndex effIndex)
  1084. {
  1085. if (effectHandleMode != SPELL_EFFECT_HANDLE_LAUNCH_TARGET)
  1086. return;
  1087.  
  1088. if (m_caster->isInFlight())
  1089. return;
  1090.  
  1091. if (!unitTarget)
  1092. return;
  1093.  
  1094. float x, y, z;
  1095. unitTarget->GetContactPoint(m_caster, x, y, z, CONTACT_DISTANCE);
  1096.  
  1097. float speedXY, speedZ;
  1098. CalculateJumpSpeeds(effIndex, m_caster->GetExactDist2d(x, y), speedXY, speedZ);
  1099. m_caster->GetMotionMaster()->MoveJump(x, y, z, speedXY, speedZ);
  1100. }
  1101.  
  1102. void Spell::EffectJumpDest(SpellEffIndex effIndex)
  1103. {
  1104. if (effectHandleMode != SPELL_EFFECT_HANDLE_LAUNCH)
  1105. return;
  1106.  
  1107. if (m_caster->isInFlight())
  1108. return;
  1109.  
  1110. if (!m_targets.HasDst())
  1111. return;
  1112.  
  1113. // Init dest coordinates
  1114. float x, y, z;
  1115. destTarget->GetPosition(x, y, z);
  1116.  
  1117. float speedXY, speedZ;
  1118. CalculateJumpSpeeds(effIndex, m_caster->GetExactDist2d(x, y), speedXY, speedZ);
  1119. m_caster->GetMotionMaster()->MoveJump(x, y, z, speedXY, speedZ);
  1120. }
  1121.  
  1122. void Spell::CalculateJumpSpeeds(uint8 i, float dist, float & speedXY, float & speedZ)
  1123. {
  1124. if (m_spellInfo->Effects[i].MiscValue)
  1125. speedZ = float(m_spellInfo->Effects[i].MiscValue)/10;
  1126. else if (m_spellInfo->Effects[i].MiscValueB)
  1127. speedZ = float(m_spellInfo->Effects[i].MiscValueB)/10;
  1128. else
  1129. speedZ = 10.0f;
  1130. speedXY = dist * 10.0f / speedZ;
  1131. }
  1132.  
  1133. void Spell::EffectTeleportUnits(SpellEffIndex /*effIndex*/)
  1134. {
  1135. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
  1136. return;
  1137.  
  1138. if (!unitTarget || unitTarget->isInFlight())
  1139. return;
  1140.  
  1141. // Pre effects
  1142. uint8 uiMaxSafeLevel = 0;
  1143. switch (m_spellInfo->Id)
  1144. {
  1145. case 48129: // Scroll of Recall
  1146. uiMaxSafeLevel = 40;
  1147. case 60320: // Scroll of Recall II
  1148. if (!uiMaxSafeLevel)
  1149. uiMaxSafeLevel = 70;
  1150. case 60321: // Scroll of Recal III
  1151. if (!uiMaxSafeLevel)
  1152. uiMaxSafeLevel = 80;
  1153.  
  1154. if (unitTarget->getLevel() > uiMaxSafeLevel)
  1155. {
  1156. unitTarget->AddAura(60444, unitTarget); //Apply Lost! Aura
  1157.  
  1158. // ALLIANCE from 60323 to 60330 - HORDE from 60328 to 60335
  1159. uint32 spellId = 60323;
  1160. if (m_caster->ToPlayer()->GetTeam() == HORDE)
  1161. spellId += 5;
  1162.  
  1163. spellId += urand(0, 7);
  1164. m_caster->CastSpell(m_caster, spellId, true);
  1165. return;
  1166. }
  1167. break;
  1168. case 66550: // teleports outside (Isle of Conquest)
  1169. if (Player* target = unitTarget->ToPlayer())
  1170. {
  1171. if (target->GetTeamId() == TEAM_ALLIANCE)
  1172. m_targets.SetDst(442.24f, -835.25f, 44.30f, 0.06f, 628);
  1173. else
  1174. m_targets.SetDst(1120.43f, -762.11f, 47.92f, 2.94f, 628);
  1175. }
  1176. break;
  1177. case 66551: // teleports inside (Isle of Conquest)
  1178. if (Player* target = unitTarget->ToPlayer())
  1179. {
  1180. if (target->GetTeamId() == TEAM_ALLIANCE)
  1181. m_targets.SetDst(389.57f, -832.38f, 48.65f, 3.00f, 628);
  1182. else
  1183. m_targets.SetDst(1174.85f, -763.24f, 48.72f, 6.26f, 628);
  1184. }
  1185. break;
  1186. }
  1187.  
  1188. // If not exist data for dest location - return
  1189. if (!m_targets.HasDst())
  1190. {
  1191. sLog->outError(LOG_FILTER_SPELLS_AURAS, "Spell::EffectTeleportUnits - does not have destination for spell ID %u\n", m_spellInfo->Id);
  1192. return;
  1193. }
  1194.  
  1195. // Init dest coordinates
  1196. uint32 mapid = destTarget->GetMapId();
  1197. if (mapid == MAPID_INVALID)
  1198. mapid = unitTarget->GetMapId();
  1199. float x, y, z, orientation;
  1200. destTarget->GetPosition(x, y, z, orientation);
  1201. if (!orientation && m_targets.GetUnitTarget())
  1202. orientation = m_targets.GetUnitTarget()->GetOrientation();
  1203. sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "Spell::EffectTeleportUnits - teleport unit to %u %f %f %f %f\n", mapid, x, y, z, orientation);
  1204.  
  1205. if (mapid == unitTarget->GetMapId())
  1206. unitTarget->NearTeleportTo(x, y, z, orientation, unitTarget == m_caster);
  1207. else if (unitTarget->GetTypeId() == TYPEID_PLAYER)
  1208. unitTarget->ToPlayer()->TeleportTo(mapid, x, y, z, orientation, unitTarget == m_caster ? TELE_TO_SPELL : 0);
  1209.  
  1210. // post effects for TARGET_DEST_DB
  1211. switch (m_spellInfo->Id)
  1212. {
  1213. // Dimensional Ripper - Everlook
  1214. case 23442:
  1215. {
  1216. int32 r = irand(0, 119);
  1217. if (r >= 70) // 7/12 success
  1218. {
  1219. if (r < 100) // 4/12 evil twin
  1220. m_caster->CastSpell(m_caster, 23445, true);
  1221. else // 1/12 fire
  1222. m_caster->CastSpell(m_caster, 23449, true);
  1223. }
  1224. return;
  1225. }
  1226. // Ultrasafe Transporter: Toshley's Station
  1227. case 36941:
  1228. {
  1229. if (roll_chance_i(50)) // 50% success
  1230. {
  1231. int32 rand_eff = urand(1, 7);
  1232. switch (rand_eff)
  1233. {
  1234. case 1:
  1235. // soul split - evil
  1236. m_caster->CastSpell(m_caster, 36900, true);
  1237. break;
  1238. case 2:
  1239. // soul split - good
  1240. m_caster->CastSpell(m_caster, 36901, true);
  1241. break;
  1242. case 3:
  1243. // Increase the size
  1244. m_caster->CastSpell(m_caster, 36895, true);
  1245. break;
  1246. case 4:
  1247. // Decrease the size
  1248. m_caster->CastSpell(m_caster, 36893, true);
  1249. break;
  1250. case 5:
  1251. // Transform
  1252. {
  1253. if (m_caster->ToPlayer()->GetTeam() == ALLIANCE)
  1254. m_caster->CastSpell(m_caster, 36897, true);
  1255. else
  1256. m_caster->CastSpell(m_caster, 36899, true);
  1257. break;
  1258. }
  1259. case 6:
  1260. // chicken
  1261. m_caster->CastSpell(m_caster, 36940, true);
  1262. break;
  1263. case 7:
  1264. // evil twin
  1265. m_caster->CastSpell(m_caster, 23445, true);
  1266. break;
  1267. }
  1268. }
  1269. return;
  1270. }
  1271. // Dimensional Ripper - Area 52
  1272. case 36890:
  1273. {
  1274. if (roll_chance_i(50)) // 50% success
  1275. {
  1276. int32 rand_eff = urand(1, 4);
  1277. switch (rand_eff)
  1278. {
  1279. case 1:
  1280. // soul split - evil
  1281. m_caster->CastSpell(m_caster, 36900, true);
  1282. break;
  1283. case 2:
  1284. // soul split - good
  1285. m_caster->CastSpell(m_caster, 36901, true);
  1286. break;
  1287. case 3:
  1288. // Increase the size
  1289. m_caster->CastSpell(m_caster, 36895, true);
  1290. break;
  1291. case 4:
  1292. // Transform
  1293. {
  1294. if (m_caster->ToPlayer()->GetTeam() == ALLIANCE)
  1295. m_caster->CastSpell(m_caster, 36897, true);
  1296. else
  1297. m_caster->CastSpell(m_caster, 36899, true);
  1298. break;
  1299. }
  1300. }
  1301. }
  1302. return;
  1303. }
  1304. }
  1305. }
  1306.  
  1307. void Spell::EffectApplyAura(SpellEffIndex effIndex)
  1308. {
  1309. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
  1310. return;
  1311.  
  1312. if (!m_spellAura || !unitTarget)
  1313. return;
  1314. ASSERT(unitTarget == m_spellAura->GetOwner());
  1315. m_spellAura->_ApplyEffectForTargets(effIndex);
  1316. }
  1317.  
  1318. void Spell::EffectApplyAreaAura(SpellEffIndex effIndex)
  1319. {
  1320. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
  1321. return;
  1322.  
  1323. if (!m_spellAura || !unitTarget)
  1324. return;
  1325. ASSERT (unitTarget == m_spellAura->GetOwner());
  1326. m_spellAura->_ApplyEffectForTargets(effIndex);
  1327. }
  1328.  
  1329. void Spell::EffectUnlearnSpecialization(SpellEffIndex effIndex)
  1330. {
  1331. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
  1332. return;
  1333.  
  1334. if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
  1335. return;
  1336.  
  1337. Player* player = unitTarget->ToPlayer();
  1338. uint32 spellToUnlearn = m_spellInfo->Effects[effIndex].TriggerSpell;
  1339.  
  1340. player->removeSpell(spellToUnlearn);
  1341.  
  1342. sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "Spell: Player %u has unlearned spell %u from NpcGUID: %u", player->GetGUIDLow(), spellToUnlearn, m_caster->GetGUIDLow());
  1343. }
  1344.  
  1345. void Spell::EffectPowerDrain(SpellEffIndex effIndex)
  1346. {
  1347. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
  1348. return;
  1349.  
  1350. if (m_spellInfo->Effects[effIndex].MiscValue < 0 || m_spellInfo->Effects[effIndex].MiscValue >= int8(MAX_POWERS))
  1351. return;
  1352.  
  1353. Powers powerType = Powers(m_spellInfo->Effects[effIndex].MiscValue);
  1354.  
  1355. if (!unitTarget || !unitTarget->isAlive() || unitTarget->getPowerType() != powerType || damage < 0)
  1356. return;
  1357.  
  1358. // add spell damage bonus
  1359. damage = m_caster->SpellDamageBonusDone(unitTarget, m_spellInfo, uint32(damage), SPELL_DIRECT_DAMAGE);
  1360. damage = unitTarget->SpellDamageBonusTaken(m_caster, m_spellInfo, uint32(damage), SPELL_DIRECT_DAMAGE);
  1361.  
  1362. // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
  1363. int32 power = damage;
  1364. if (powerType == POWER_MANA)
  1365. power -= unitTarget->GetSpellCritDamageReduction(power);
  1366.  
  1367. int32 newDamage = -(unitTarget->ModifyPower(powerType, -int32(power)));
  1368.  
  1369. float gainMultiplier = 0.0f;
  1370.  
  1371. // Don`t restore from self drain
  1372. if (m_caster != unitTarget)
  1373. {
  1374. gainMultiplier = m_spellInfo->Effects[effIndex].CalcValueMultiplier(m_originalCaster, this);
  1375.  
  1376. int32 gain = int32(newDamage* gainMultiplier);
  1377.  
  1378. m_caster->EnergizeBySpell(m_caster, m_spellInfo->Id, gain, powerType);
  1379. }
  1380. ExecuteLogEffectTakeTargetPower(effIndex, unitTarget, powerType, newDamage, gainMultiplier);
  1381. }
  1382.  
  1383. void Spell::EffectSendEvent(SpellEffIndex effIndex)
  1384. {
  1385. // we do not handle a flag dropping or clicking on flag in battleground by sendevent system
  1386. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET
  1387. && effectHandleMode != SPELL_EFFECT_HANDLE_HIT)
  1388. return;
  1389.  
  1390. WorldObject* target = NULL;
  1391.  
  1392. // call events for object target if present
  1393. if (effectHandleMode == SPELL_EFFECT_HANDLE_HIT_TARGET)
  1394. {
  1395. if (unitTarget)
  1396. target = unitTarget;
  1397. else if (gameObjTarget)
  1398. target = gameObjTarget;
  1399. }
  1400. else // if (effectHandleMode == SPELL_EFFECT_HANDLE_HIT)
  1401. {
  1402. // let's prevent executing effect handler twice in case when spell effect is capable of targeting an object
  1403. // this check was requested by scripters, but it has some downsides:
  1404. // now it's impossible to script (using sEventScripts) a cast which misses all targets
  1405. // or to have an ability to script the moment spell hits dest (in a case when there are object targets present)
  1406. if (m_spellInfo->Effects[effIndex].GetProvidedTargetMask() & (TARGET_FLAG_UNIT_MASK | TARGET_FLAG_GAMEOBJECT_MASK))
  1407. return;
  1408. // some spells have no target entries in dbc and they use focus target
  1409. if (focusObject)
  1410. target = focusObject;
  1411. // TODO: there should be a possibility to pass dest target to event script
  1412. }
  1413.  
  1414. sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "Spell ScriptStart %u for spellid %u in EffectSendEvent ", m_spellInfo->Effects[effIndex].MiscValue, m_spellInfo->Id);
  1415.  
  1416. if (ZoneScript* zoneScript = m_caster->GetZoneScript())
  1417. zoneScript->ProcessEvent(target, m_spellInfo->Effects[effIndex].MiscValue);
  1418. else if (InstanceScript* instanceScript = m_caster->GetInstanceScript()) // needed in case Player is the caster
  1419. instanceScript->ProcessEvent(target, m_spellInfo->Effects[effIndex].MiscValue);
  1420.  
  1421. m_caster->GetMap()->ScriptsStart(sEventScripts, m_spellInfo->Effects[effIndex].MiscValue, m_caster, target);
  1422. }
  1423.  
  1424. void Spell::EffectPowerBurn(SpellEffIndex effIndex)
  1425. {
  1426. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
  1427. return;
  1428.  
  1429. if (m_spellInfo->Effects[effIndex].MiscValue < 0 || m_spellInfo->Effects[effIndex].MiscValue >= int8(MAX_POWERS))
  1430. return;
  1431.  
  1432. Powers powerType = Powers(m_spellInfo->Effects[effIndex].MiscValue);
  1433.  
  1434. if (!unitTarget || !unitTarget->isAlive() || unitTarget->getPowerType() != powerType || damage < 0)
  1435. return;
  1436.  
  1437. // burn x% of target's mana, up to maximum of 2x% of caster's mana (Mana Burn)
  1438. if (m_spellInfo->Id == 8129)
  1439. {
  1440. int32 maxDamage = int32(CalculatePct(m_caster->GetMaxPower(powerType), damage * 2));
  1441. damage = int32(CalculatePct(unitTarget->GetMaxPower(powerType), damage));
  1442. damage = std::min(damage, maxDamage);
  1443. }
  1444.  
  1445. int32 power = damage;
  1446. // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
  1447. if (powerType == POWER_MANA)
  1448. power -= unitTarget->GetSpellCritDamageReduction(power);
  1449.  
  1450. int32 newDamage = -(unitTarget->ModifyPower(powerType, -power));
  1451.  
  1452. // NO - Not a typo - EffectPowerBurn uses effect value multiplier - not effect damage multiplier
  1453. float dmgMultiplier = m_spellInfo->Effects[effIndex].CalcValueMultiplier(m_originalCaster, this);
  1454.  
  1455. // add log data before multiplication (need power amount, not damage)
  1456. ExecuteLogEffectTakeTargetPower(effIndex, unitTarget, powerType, newDamage, 0.0f);
  1457.  
  1458. newDamage = int32(newDamage* dmgMultiplier);
  1459.  
  1460. m_damage += newDamage;
  1461. }
  1462.  
  1463. void Spell::EffectHeal(SpellEffIndex /*effIndex*/)
  1464. {
  1465. if (effectHandleMode != SPELL_EFFECT_HANDLE_LAUNCH_TARGET)
  1466. return;
  1467.  
  1468. if (unitTarget && unitTarget->isAlive() && damage >= 0)
  1469. {
  1470. // Try to get original caster
  1471. Unit* caster = m_originalCasterGUID ? m_originalCaster : m_caster;
  1472.  
  1473. // Skip if m_originalCaster not available
  1474. if (!caster)
  1475. return;
  1476.  
  1477. int32 addhealth = damage;
  1478.  
  1479. // Vessel of the Naaru (Vial of the Sunwell trinket)
  1480. if (m_spellInfo->Id == 45064)
  1481. {
  1482. // Amount of heal - depends from stacked Holy Energy
  1483. int damageAmount = 0;
  1484. if (AuraEffect const* aurEff = m_caster->GetAuraEffect(45062, 0))
  1485. {
  1486. damageAmount+= aurEff->GetAmount();
  1487. m_caster->RemoveAurasDueToSpell(45062);
  1488. }
  1489.  
  1490. addhealth += damageAmount;
  1491. }
  1492. // Runic Healing Injector (heal increased by 25% for engineers - 3.2.0 patch change)
  1493. else if (m_spellInfo->Id == 67489)
  1494. {
  1495. if (Player* player = m_caster->ToPlayer())
  1496. if (player->HasSkill(SKILL_ENGINEERING))
  1497. AddPct(addhealth, 25);
  1498. }
  1499. // Swiftmend - consumes Regrowth or Rejuvenation
  1500. else if (m_spellInfo->TargetAuraState == AURA_STATE_SWIFTMEND && unitTarget->HasAuraState(AURA_STATE_SWIFTMEND, m_spellInfo, m_caster))
  1501. {
  1502. Unit::AuraEffectList const& RejorRegr = unitTarget->GetAuraEffectsByType(SPELL_AURA_PERIODIC_HEAL);
  1503. // find most short by duration
  1504. AuraEffect* targetAura = NULL;
  1505. for (Unit::AuraEffectList::const_iterator i = RejorRegr.begin(); i != RejorRegr.end(); ++i)
  1506. {
  1507. if ((*i)->GetSpellInfo()->SpellFamilyName == SPELLFAMILY_DRUID
  1508. && (*i)->GetSpellInfo()->SpellFamilyFlags[0] & 0x50)
  1509. {
  1510. if (!targetAura || (*i)->GetBase()->GetDuration() < targetAura->GetBase()->GetDuration())
  1511. targetAura = *i;
  1512. }
  1513. }
  1514.  
  1515. if (!targetAura)
  1516. {
  1517. sLog->outError(LOG_FILTER_SPELLS_AURAS, "Target(GUID:" UI64FMTD ") has aurastate AURA_STATE_SWIFTMEND but no matching aura.", unitTarget->GetGUID());
  1518. return;
  1519. }
  1520.  
  1521. int32 tickheal = targetAura->GetAmount();
  1522. if (Unit* auraCaster = targetAura->GetCaster())
  1523. tickheal = auraCaster->SpellHealingBonusDone(unitTarget, targetAura->GetSpellInfo(), tickheal, DOT);
  1524. //int32 tickheal = targetAura->GetSpellInfo()->EffectBasePoints[idx] + 1;
  1525. //It is said that talent bonus should not be included
  1526.  
  1527. int32 tickcount = 0;
  1528. // Rejuvenation
  1529. if (targetAura->GetSpellInfo()->SpellFamilyFlags[0] & 0x10)
  1530. tickcount = 4;
  1531. // Regrowth
  1532. else // if (targetAura->GetSpellInfo()->SpellFamilyFlags[0] & 0x40)
  1533. tickcount = 6;
  1534.  
  1535. addhealth += tickheal * tickcount;
  1536.  
  1537. // Glyph of Swiftmend
  1538. if (!caster->HasAura(54824))
  1539. unitTarget->RemoveAura(targetAura->GetId(), targetAura->GetCasterGUID());
  1540.  
  1541. //addhealth += tickheal * tickcount;
  1542. //addhealth = caster->SpellHealingBonus(m_spellInfo, addhealth, HEAL, unitTarget);
  1543. }
  1544. // Nourish
  1545. else if (m_spellInfo->SpellFamilyName == SPELLFAMILY_DRUID && m_spellInfo->SpellFamilyFlags[1] & 0x2000000)
  1546. {
  1547. addhealth = caster->SpellHealingBonusDone(unitTarget, m_spellInfo, addhealth, HEAL);
  1548.  
  1549. // Glyph of Nourish
  1550. if (AuraEffect const* aurEff = m_caster->GetAuraEffect(62971, 0))
  1551. {
  1552. Unit::AuraEffectList const& Periodic = unitTarget->GetAuraEffectsByType(SPELL_AURA_PERIODIC_HEAL);
  1553. for (Unit::AuraEffectList::const_iterator i = Periodic.begin(); i != Periodic.end(); ++i)
  1554. {
  1555. if (m_caster->GetGUID() == (*i)->GetCasterGUID())
  1556. AddPct(addhealth, aurEff->GetAmount());
  1557. }
  1558. }
  1559. }
  1560. // Death Pact - return pct of max health to caster
  1561. else if (m_spellInfo->SpellFamilyName == SPELLFAMILY_DEATHKNIGHT && m_spellInfo->SpellFamilyFlags[0] & 0x00080000)
  1562. addhealth = caster->SpellHealingBonusDone(unitTarget, m_spellInfo, int32(caster->CountPctFromMaxHealth(damage)), HEAL);
  1563. else
  1564. addhealth = caster->SpellHealingBonusDone(unitTarget, m_spellInfo, addhealth, HEAL);
  1565.  
  1566. addhealth = unitTarget->SpellHealingBonusTaken(caster, m_spellInfo, addhealth, HEAL);
  1567.  
  1568. // Remove Grievious bite if fully healed
  1569. if (unitTarget->HasAura(48920) && (unitTarget->GetHealth() + addhealth >= unitTarget->GetMaxHealth()))
  1570. unitTarget->RemoveAura(48920);
  1571.  
  1572. m_damage -= addhealth;
  1573. }
  1574. }
  1575.  
  1576. void Spell::EffectHealPct(SpellEffIndex /*effIndex*/)
  1577. {
  1578. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
  1579. return;
  1580.  
  1581. if (!unitTarget || !unitTarget->isAlive() || damage < 0)
  1582. return;
  1583.  
  1584. // Skip if m_originalCaster not available
  1585. if (!m_originalCaster)
  1586. return;
  1587.  
  1588. // Rune Tap - Party
  1589. if (m_spellInfo->Id == 59754 && unitTarget == m_caster)
  1590. return;
  1591.  
  1592. uint32 heal = m_originalCaster->SpellHealingBonusDone(unitTarget, m_spellInfo, unitTarget->CountPctFromMaxHealth(damage), HEAL);
  1593. heal = unitTarget->SpellHealingBonusTaken(m_originalCaster, m_spellInfo, heal, HEAL);
  1594.  
  1595. m_healing += heal;
  1596. }
  1597.  
  1598. void Spell::EffectHealMechanical(SpellEffIndex /*effIndex*/)
  1599. {
  1600. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
  1601. return;
  1602.  
  1603. if (!unitTarget || !unitTarget->isAlive() || damage < 0)
  1604. return;
  1605.  
  1606. // Skip if m_originalCaster not available
  1607. if (!m_originalCaster)
  1608. return;
  1609.  
  1610. uint32 heal = m_originalCaster->SpellHealingBonusDone(unitTarget, m_spellInfo, uint32(damage), HEAL);
  1611.  
  1612. m_healing += unitTarget->SpellHealingBonusTaken(m_originalCaster, m_spellInfo, heal, HEAL);
  1613. }
  1614.  
  1615. void Spell::EffectHealthLeech(SpellEffIndex effIndex)
  1616. {
  1617. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
  1618. return;
  1619.  
  1620. if (!unitTarget || !unitTarget->isAlive() || damage < 0)
  1621. return;
  1622.  
  1623. damage = m_caster->SpellDamageBonusDone(unitTarget, m_spellInfo, uint32(damage), SPELL_DIRECT_DAMAGE);
  1624. damage = unitTarget->SpellDamageBonusTaken(m_caster, m_spellInfo, uint32(damage), SPELL_DIRECT_DAMAGE);
  1625.  
  1626. sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "HealthLeech :%i", damage);
  1627.  
  1628. float healMultiplier = m_spellInfo->Effects[effIndex].CalcValueMultiplier(m_originalCaster, this);
  1629.  
  1630. m_damage += damage;
  1631. // get max possible damage, don't count overkill for heal
  1632. uint32 healthGain = uint32(-unitTarget->GetHealthGain(-damage) * healMultiplier);
  1633.  
  1634. if (m_caster->isAlive())
  1635. {
  1636. healthGain = m_caster->SpellHealingBonusDone(m_caster, m_spellInfo, healthGain, HEAL);
  1637. healthGain = m_caster->SpellHealingBonusTaken(m_caster, m_spellInfo, healthGain, HEAL);
  1638.  
  1639. m_caster->HealBySpell(m_caster, m_spellInfo, uint32(healthGain));
  1640. }
  1641. }
  1642.  
  1643. void Spell::DoCreateItem(uint32 /*i*/, uint32 itemtype)
  1644. {
  1645. if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
  1646. return;
  1647.  
  1648. Player* player = unitTarget->ToPlayer();
  1649.  
  1650. uint32 newitemid = itemtype;
  1651. ItemTemplate const* pProto = sObjectMgr->GetItemTemplate(newitemid);
  1652. if (!pProto)
  1653. {
  1654. player->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL);
  1655. return;
  1656. }
  1657.  
  1658. // bg reward have some special in code work
  1659. uint32 bgType = 0;
  1660. switch (m_spellInfo->Id)
  1661. {
  1662. case SPELL_AV_MARK_WINNER:
  1663. case SPELL_AV_MARK_LOSER:
  1664. bgType = BATTLEGROUND_AV;
  1665. break;
  1666. case SPELL_WS_MARK_WINNER:
  1667. case SPELL_WS_MARK_LOSER:
  1668. bgType = BATTLEGROUND_WS;
  1669. break;
  1670. case SPELL_AB_MARK_WINNER:
  1671. case SPELL_AB_MARK_LOSER:
  1672. bgType = BATTLEGROUND_AB;
  1673. break;
  1674. default:
  1675. break;
  1676. }
  1677.  
  1678. uint32 num_to_add = damage;
  1679.  
  1680. if (num_to_add < 1)
  1681. num_to_add = 1;
  1682. if (num_to_add > pProto->GetMaxStackSize())
  1683. num_to_add = pProto->GetMaxStackSize();
  1684.  
  1685. // init items_count to 1, since 1 item will be created regardless of specialization
  1686. int items_count=1;
  1687. // the chance to create additional items
  1688. float additionalCreateChance=0.0f;
  1689. // the maximum number of created additional items
  1690. uint8 additionalMaxNum=0;
  1691. // get the chance and maximum number for creating extra items
  1692. if (canCreateExtraItems(player, m_spellInfo->Id, additionalCreateChance, additionalMaxNum))
  1693. {
  1694. // roll with this chance till we roll not to create or we create the max num
  1695. while (roll_chance_f(additionalCreateChance) && items_count <= additionalMaxNum)
  1696. ++items_count;
  1697. }
  1698.  
  1699. // really will be created more items
  1700. num_to_add *= items_count;
  1701.  
  1702. // can the player store the new item?
  1703. ItemPosCountVec dest;
  1704. uint32 no_space = 0;
  1705. InventoryResult msg = player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, newitemid, num_to_add, &no_space);
  1706. if (msg != EQUIP_ERR_OK)
  1707. {
  1708. // convert to possible store amount
  1709. if (msg == EQUIP_ERR_INVENTORY_FULL || msg == EQUIP_ERR_CANT_CARRY_MORE_OF_THIS)
  1710. num_to_add -= no_space;
  1711. else
  1712. {
  1713. // if not created by another reason from full inventory or unique items amount limitation
  1714. player->SendEquipError(msg, NULL, NULL, newitemid);
  1715. return;
  1716. }
  1717. }
  1718.  
  1719. if (num_to_add)
  1720. {
  1721. // create the new item and store it
  1722. Item* pItem = player->StoreNewItem(dest, newitemid, true, Item::GenerateItemRandomPropertyId(newitemid));
  1723.  
  1724. // was it successful? return error if not
  1725. if (!pItem)
  1726. {
  1727. player->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL);
  1728. return;
  1729. }
  1730.  
  1731. // set the "Crafted by ..." property of the item
  1732. if (pItem->GetTemplate()->Class != ITEM_CLASS_CONSUMABLE && pItem->GetTemplate()->Class != ITEM_CLASS_QUEST && newitemid != 6265 && newitemid != 6948)
  1733. pItem->SetUInt32Value(ITEM_FIELD_CREATOR, player->GetGUIDLow());
  1734.  
  1735. // send info to the client
  1736. player->SendNewItem(pItem, num_to_add, true, bgType == 0);
  1737.  
  1738. // we succeeded in creating at least one item, so a levelup is possible
  1739. if (bgType == 0)
  1740. player->UpdateCraftSkill(m_spellInfo->Id);
  1741. }
  1742.  
  1743. /*
  1744. // for battleground marks send by mail if not add all expected
  1745. if (no_space > 0 && bgType)
  1746. {
  1747. if (Battleground* bg = sBattlegroundMgr->GetBattlegroundTemplate(BattlegroundTypeId(bgType)))
  1748. bg->SendRewardMarkByMail(player, newitemid, no_space);
  1749. }
  1750. */
  1751. }
  1752.  
  1753. void Spell::EffectCreateItem(SpellEffIndex effIndex)
  1754. {
  1755. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
  1756. return;
  1757.  
  1758. DoCreateItem(effIndex, m_spellInfo->Effects[effIndex].ItemType);
  1759. ExecuteLogEffectCreateItem(effIndex, m_spellInfo->Effects[effIndex].ItemType);
  1760. }
  1761.  
  1762. void Spell::EffectCreateItem2(SpellEffIndex effIndex)
  1763. {
  1764. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
  1765. return;
  1766.  
  1767. if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
  1768. return;
  1769.  
  1770. Player* player = unitTarget->ToPlayer();
  1771.  
  1772. uint32 item_id = m_spellInfo->Effects[effIndex].ItemType;
  1773.  
  1774. if (item_id)
  1775. DoCreateItem(effIndex, item_id);
  1776.  
  1777. // special case: fake item replaced by generate using spell_loot_template
  1778. if (m_spellInfo->IsLootCrafting())
  1779. {
  1780. if (item_id)
  1781. {
  1782. if (!player->HasItemCount(item_id))
  1783. return;
  1784.  
  1785. // remove reagent
  1786. uint32 count = 1;
  1787. player->DestroyItemCount(item_id, count, true);
  1788.  
  1789. // create some random items
  1790. player->AutoStoreLoot(m_spellInfo->Id, LootTemplates_Spell);
  1791. }
  1792. else
  1793. player->AutoStoreLoot(m_spellInfo->Id, LootTemplates_Spell); // create some random items
  1794. }
  1795. // TODO: ExecuteLogEffectCreateItem(i, m_spellInfo->Effects[i].ItemType);
  1796. }
  1797.  
  1798. void Spell::EffectCreateRandomItem(SpellEffIndex /*effIndex*/)
  1799. {
  1800. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
  1801. return;
  1802.  
  1803. if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
  1804. return;
  1805. Player* player = unitTarget->ToPlayer();
  1806.  
  1807. // create some random items
  1808. player->AutoStoreLoot(m_spellInfo->Id, LootTemplates_Spell);
  1809. // TODO: ExecuteLogEffectCreateItem(i, m_spellInfo->Effects[i].ItemType);
  1810. }
  1811.  
  1812. void Spell::EffectPersistentAA(SpellEffIndex effIndex)
  1813. {
  1814. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT)
  1815. return;
  1816.  
  1817. if (!m_spellAura)
  1818. {
  1819. Unit* caster = m_caster->GetEntry() == WORLD_TRIGGER ? m_originalCaster : m_caster;
  1820. float radius = m_spellInfo->Effects[effIndex].CalcRadius(caster);
  1821.  
  1822. // Caster not in world, might be spell triggered from aura removal
  1823. if (!caster->IsInWorld())
  1824. return;
  1825. DynamicObject* dynObj = new DynamicObject(false);
  1826. if (!dynObj->CreateDynamicObject(sObjectMgr->GenerateLowGuid(HIGHGUID_DYNAMICOBJECT), caster, m_spellInfo->Id, *destTarget, radius, DYNAMIC_OBJECT_AREA_SPELL))
  1827. {
  1828. delete dynObj;
  1829. return;
  1830. }
  1831.  
  1832. if (Aura* aura = Aura::TryCreate(m_spellInfo, MAX_EFFECT_MASK, dynObj, caster, &m_spellValue->EffectBasePoints[0]))
  1833. {
  1834. m_spellAura = aura;
  1835. m_spellAura->_RegisterForTargets();
  1836. }
  1837. else
  1838. return;
  1839. }
  1840.  
  1841. ASSERT(m_spellAura->GetDynobjOwner());
  1842. m_spellAura->_ApplyEffectForTargets(effIndex);
  1843. }
  1844.  
  1845. void Spell::EffectEnergize(SpellEffIndex effIndex)
  1846. {
  1847. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
  1848. return;
  1849.  
  1850. if (!unitTarget)
  1851. return;
  1852. if (!unitTarget->isAlive())
  1853. return;
  1854.  
  1855. if (m_spellInfo->Effects[effIndex].MiscValue < 0 || m_spellInfo->Effects[effIndex].MiscValue >= int8(MAX_POWERS))
  1856. return;
  1857.  
  1858. Powers power = Powers(m_spellInfo->Effects[effIndex].MiscValue);
  1859.  
  1860. // Some level depends spells
  1861. int level_multiplier = 0;
  1862. int level_diff = 0;
  1863. switch (m_spellInfo->Id)
  1864. {
  1865. case 9512: // Restore Energy
  1866. level_diff = m_caster->getLevel() - 40;
  1867. level_multiplier = 2;
  1868. break;
  1869. case 24571: // Blood Fury
  1870. level_diff = m_caster->getLevel() - 60;
  1871. level_multiplier = 10;
  1872. break;
  1873. case 24532: // Burst of Energy
  1874. level_diff = m_caster->getLevel() - 60;
  1875. level_multiplier = 4;
  1876. break;
  1877. case 31930: // Judgements of the Wise
  1878. case 63375: // Improved Stormstrike
  1879. case 68082: // Glyph of Seal of Command
  1880. damage = int32(CalculatePct(unitTarget->GetCreateMana(), damage));
  1881. break;
  1882. case 48542: // Revitalize
  1883. damage = int32(CalculatePct(unitTarget->GetMaxPower(power), damage));
  1884. break;
  1885. case 67490: // Runic Mana Injector (mana gain increased by 25% for engineers - 3.2.0 patch change)
  1886. {
  1887. if (Player* player = m_caster->ToPlayer())
  1888. if (player->HasSkill(SKILL_ENGINEERING))
  1889. AddPct(damage, 25);
  1890. break;
  1891. }
  1892. case 71132: // Glyph of Shadow Word: Pain
  1893. damage = int32(CalculatePct(unitTarget->GetCreateMana(), 1)); // set 1 as value, missing in dbc
  1894. break;
  1895. default:
  1896. break;
  1897. }
  1898.  
  1899. if (level_diff > 0)
  1900. damage -= level_multiplier * level_diff;
  1901.  
  1902. if (damage < 0)
  1903. return;
  1904.  
  1905. if (unitTarget->GetMaxPower(power) == 0)
  1906. return;
  1907.  
  1908. m_caster->EnergizeBySpell(unitTarget, m_spellInfo->Id, damage, power);
  1909.  
  1910. // Mad Alchemist's Potion
  1911. if (m_spellInfo->Id == 45051)
  1912. {
  1913. // find elixirs on target
  1914. bool guardianFound = false;
  1915. bool battleFound = false;
  1916. Unit::AuraApplicationMap& Auras = unitTarget->GetAppliedAuras();
  1917. for (Unit::AuraApplicationMap::iterator itr = Auras.begin(); itr != Auras.end(); ++itr)
  1918. {
  1919. uint32 spell_id = itr->second->GetBase()->GetId();
  1920. if (!guardianFound)
  1921. if (sSpellMgr->IsSpellMemberOfSpellGroup(spell_id, SPELL_GROUP_ELIXIR_GUARDIAN))
  1922. guardianFound = true;
  1923. if (!battleFound)
  1924. if (sSpellMgr->IsSpellMemberOfSpellGroup(spell_id, SPELL_GROUP_ELIXIR_BATTLE))
  1925. battleFound = true;
  1926. if (battleFound && guardianFound)
  1927. break;
  1928. }
  1929.  
  1930. // get all available elixirs by mask and spell level
  1931. std::set<uint32> avalibleElixirs;
  1932. if (!guardianFound)
  1933. sSpellMgr->GetSetOfSpellsInSpellGroup(SPELL_GROUP_ELIXIR_GUARDIAN, avalibleElixirs);
  1934. if (!battleFound)
  1935. sSpellMgr->GetSetOfSpellsInSpellGroup(SPELL_GROUP_ELIXIR_BATTLE, avalibleElixirs);
  1936. for (std::set<uint32>::iterator itr = avalibleElixirs.begin(); itr != avalibleElixirs.end();)
  1937. {
  1938. SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(*itr);
  1939. if (spellInfo->SpellLevel < m_spellInfo->SpellLevel || spellInfo->SpellLevel > unitTarget->getLevel())
  1940. avalibleElixirs.erase(itr++);
  1941. else if (sSpellMgr->IsSpellMemberOfSpellGroup(*itr, SPELL_GROUP_ELIXIR_SHATTRATH))
  1942. avalibleElixirs.erase(itr++);
  1943. else if (sSpellMgr->IsSpellMemberOfSpellGroup(*itr, SPELL_GROUP_ELIXIR_UNSTABLE))
  1944. avalibleElixirs.erase(itr++);
  1945. else
  1946. ++itr;
  1947. }
  1948.  
  1949. if (!avalibleElixirs.empty())
  1950. {
  1951. // cast random elixir on target
  1952. m_caster->CastSpell(unitTarget, Trinity::Containers::SelectRandomContainerElement(avalibleElixirs), true, m_CastItem);
  1953. }
  1954. }
  1955. }
  1956.  
  1957. void Spell::EffectEnergizePct(SpellEffIndex effIndex)
  1958. {
  1959. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
  1960. return;
  1961.  
  1962. if (!unitTarget)
  1963. return;
  1964. if (!unitTarget->isAlive())
  1965. return;
  1966.  
  1967. if (m_spellInfo->Effects[effIndex].MiscValue < 0 || m_spellInfo->Effects[effIndex].MiscValue >= int8(MAX_POWERS))
  1968. return;
  1969.  
  1970. Powers power = Powers(m_spellInfo->Effects[effIndex].MiscValue);
  1971.  
  1972. uint32 maxPower = unitTarget->GetMaxPower(power);
  1973. if (maxPower == 0)
  1974. return;
  1975.  
  1976. uint32 gain = CalculatePct(maxPower, damage);
  1977. m_caster->EnergizeBySpell(unitTarget, m_spellInfo->Id, gain, power);
  1978. }
  1979.  
  1980. void Spell::SendLoot(uint64 guid, LootType loottype)
  1981. {
  1982. Player* player = m_caster->ToPlayer();
  1983. if (!player)
  1984. return;
  1985.  
  1986. if (gameObjTarget)
  1987. {
  1988. // Players shouldn't be able to loot gameobjects that are currently despawned
  1989. if (!gameObjTarget->isSpawned() && !player->isGameMaster())
  1990. {
  1991. sLog->outError(LOG_FILTER_SPELLS_AURAS, "Possible hacking attempt: Player %s [guid: %u] tried to loot a gameobject [entry: %u id: %u] which is on respawn time without being in GM mode!",
  1992. player->GetName().c_str(), player->GetGUIDLow(), gameObjTarget->GetEntry(), gameObjTarget->GetGUIDLow());
  1993. return;
  1994. }
  1995. // special case, already has GossipHello inside so return and avoid calling twice
  1996. if (gameObjTarget->GetGoType() == GAMEOBJECT_TYPE_GOOBER)
  1997. {
  1998. gameObjTarget->Use(m_caster);
  1999. return;
  2000. }
  2001.  
  2002. if (sScriptMgr->OnGossipHello(player, gameObjTarget))
  2003. return;
  2004.  
  2005. if (gameObjTarget->AI()->GossipHello(player))
  2006. return;
  2007.  
  2008. switch (gameObjTarget->GetGoType())
  2009. {
  2010. case GAMEOBJECT_TYPE_DOOR:
  2011. case GAMEOBJECT_TYPE_BUTTON:
  2012. gameObjTarget->UseDoorOrButton(0, false, player);
  2013. player->GetMap()->ScriptsStart(sGameObjectScripts, gameObjTarget->GetDBTableGUIDLow(), player, gameObjTarget);
  2014. return;
  2015.  
  2016. case GAMEOBJECT_TYPE_QUESTGIVER:
  2017. player->PrepareGossipMenu(gameObjTarget, gameObjTarget->GetGOInfo()->questgiver.gossipID);
  2018. player->SendPreparedGossip(gameObjTarget);
  2019. return;
  2020.  
  2021. case GAMEOBJECT_TYPE_SPELL_FOCUS:
  2022. // triggering linked GO
  2023. if (uint32 trapEntry = gameObjTarget->GetGOInfo()->spellFocus.linkedTrapId)
  2024. gameObjTarget->TriggeringLinkedGameObject(trapEntry, m_caster);
  2025. return;
  2026.  
  2027. case GAMEOBJECT_TYPE_CHEST:
  2028. // TODO: possible must be moved to loot release (in different from linked triggering)
  2029. if (gameObjTarget->GetGOInfo()->chest.eventId)
  2030. {
  2031. sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "Chest ScriptStart id %u for GO %u", gameObjTarget->GetGOInfo()->chest.eventId, gameObjTarget->GetDBTableGUIDLow());
  2032. player->GetMap()->ScriptsStart(sEventScripts, gameObjTarget->GetGOInfo()->chest.eventId, player, gameObjTarget);
  2033. }
  2034.  
  2035. // triggering linked GO
  2036. if (uint32 trapEntry = gameObjTarget->GetGOInfo()->chest.linkedTrapId)
  2037. gameObjTarget->TriggeringLinkedGameObject(trapEntry, m_caster);
  2038.  
  2039. // Don't return, let loots been taken
  2040. default:
  2041. break;
  2042. }
  2043. }
  2044.  
  2045. // Send loot
  2046. player->SendLoot(guid, loottype);
  2047. }
  2048.  
  2049. void Spell::EffectOpenLock(SpellEffIndex effIndex)
  2050. {
  2051. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
  2052. return;
  2053.  
  2054. if (m_caster->GetTypeId() != TYPEID_PLAYER)
  2055. {
  2056. sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "WORLD: Open Lock - No Player Caster!");
  2057. return;
  2058. }
  2059.  
  2060. Player* player = m_caster->ToPlayer();
  2061.  
  2062. uint32 lockId = 0;
  2063. uint64 guid = 0;
  2064.  
  2065. // Get lockId
  2066. if (gameObjTarget)
  2067. {
  2068. GameObjectTemplate const* goInfo = gameObjTarget->GetGOInfo();
  2069. // Arathi Basin banner opening. // TODO: Verify correctness of this check
  2070. if ((goInfo->type == GAMEOBJECT_TYPE_BUTTON && goInfo->button.noDamageImmune) ||
  2071. (goInfo->type == GAMEOBJECT_TYPE_GOOBER && goInfo->goober.losOK))
  2072. {
  2073. //CanUseBattlegroundObject() already called in CheckCast()
  2074. // in battleground check
  2075. if (Battleground* bg = player->GetBattleground())
  2076. {
  2077. bg->EventPlayerClickedOnFlag(player, gameObjTarget);
  2078. return;
  2079. }
  2080. }
  2081. else if (goInfo->type == GAMEOBJECT_TYPE_FLAGSTAND)
  2082. {
  2083. //CanUseBattlegroundObject() already called in CheckCast()
  2084. // in battleground check
  2085. if (Battleground* bg = player->GetBattleground())
  2086. {
  2087. if (bg->GetTypeID(true) == BATTLEGROUND_EY)
  2088. bg->EventPlayerClickedOnFlag(player, gameObjTarget);
  2089. return;
  2090. }
  2091. }
  2092. else if (m_spellInfo->Id == 1842 && gameObjTarget->GetGOInfo()->type == GAMEOBJECT_TYPE_TRAP && gameObjTarget->GetOwner())
  2093. {
  2094. gameObjTarget->SetLootState(GO_JUST_DEACTIVATED);
  2095. return;
  2096. }
  2097. // TODO: Add script for spell 41920 - Filling, becouse server it freze when use this spell
  2098. // handle outdoor pvp object opening, return true if go was registered for handling
  2099. // these objects must have been spawned by outdoorpvp!
  2100. else if (gameObjTarget->GetGOInfo()->type == GAMEOBJECT_TYPE_GOOBER && sOutdoorPvPMgr->HandleOpenGo(player, gameObjTarget->GetGUID()))
  2101. return;
  2102. lockId = goInfo->GetLockId();
  2103. guid = gameObjTarget->GetGUID();
  2104. }
  2105. else if (itemTarget)
  2106. {
  2107. lockId = itemTarget->GetTemplate()->LockID;
  2108. guid = itemTarget->GetGUID();
  2109. }
  2110. else
  2111. {
  2112. sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "WORLD: Open Lock - No GameObject/Item Target!");
  2113. return;
  2114. }
  2115.  
  2116. SkillType skillId = SKILL_NONE;
  2117. int32 reqSkillValue = 0;
  2118. int32 skillValue;
  2119.  
  2120. SpellCastResult res = CanOpenLock(effIndex, lockId, skillId, reqSkillValue, skillValue);
  2121. if (res != SPELL_CAST_OK)
  2122. {
  2123. SendCastResult(res);
  2124. return;
  2125. }
  2126.  
  2127. if (gameObjTarget)
  2128. SendLoot(guid, LOOT_SKINNING);
  2129. else if (itemTarget)
  2130. itemTarget->SetFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_UNLOCKED);
  2131.  
  2132. // not allow use skill grow at item base open
  2133. if (!m_CastItem && skillId != SKILL_NONE)
  2134. {
  2135. // update skill if really known
  2136. if (uint32 pureSkillValue = player->GetPureSkillValue(skillId))
  2137. {
  2138. if (gameObjTarget)
  2139. {
  2140. // Allow one skill-up until respawned
  2141. if (!gameObjTarget->IsInSkillupList(player->GetGUIDLow()) &&
  2142. player->UpdateGatherSkill(skillId, pureSkillValue, reqSkillValue))
  2143. gameObjTarget->AddToSkillupList(player->GetGUIDLow());
  2144. }
  2145. else if (itemTarget)
  2146. {
  2147. // Do one skill-up
  2148. player->UpdateGatherSkill(skillId, pureSkillValue, reqSkillValue);
  2149. }
  2150. }
  2151. }
  2152. ExecuteLogEffectOpenLock(effIndex, gameObjTarget ? (Object*)gameObjTarget : (Object*)itemTarget);
  2153. }
  2154.  
  2155. void Spell::EffectSummonChangeItem(SpellEffIndex effIndex)
  2156. {
  2157. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT)
  2158. return;
  2159.  
  2160. if (m_caster->GetTypeId() != TYPEID_PLAYER)
  2161. return;
  2162.  
  2163. Player* player = m_caster->ToPlayer();
  2164.  
  2165. // applied only to using item
  2166. if (!m_CastItem)
  2167. return;
  2168.  
  2169. // ... only to item in own inventory/bank/equip_slot
  2170. if (m_CastItem->GetOwnerGUID() != player->GetGUID())
  2171. return;
  2172.  
  2173. uint32 newitemid = m_spellInfo->Effects[effIndex].ItemType;
  2174. if (!newitemid)
  2175. return;
  2176.  
  2177. uint16 pos = m_CastItem->GetPos();
  2178.  
  2179. Item* pNewItem = Item::CreateItem(newitemid, 1, player);
  2180. if (!pNewItem)
  2181. return;
  2182.  
  2183. for (uint8 j = PERM_ENCHANTMENT_SLOT; j <= TEMP_ENCHANTMENT_SLOT; ++j)
  2184. if (m_CastItem->GetEnchantmentId(EnchantmentSlot(j)))
  2185. pNewItem->SetEnchantment(EnchantmentSlot(j), m_CastItem->GetEnchantmentId(EnchantmentSlot(j)), m_CastItem->GetEnchantmentDuration(EnchantmentSlot(j)), m_CastItem->GetEnchantmentCharges(EnchantmentSlot(j)));
  2186.  
  2187. if (m_CastItem->GetUInt32Value(ITEM_FIELD_DURABILITY) < m_CastItem->GetUInt32Value(ITEM_FIELD_MAXDURABILITY))
  2188. {
  2189. double lossPercent = 1 - m_CastItem->GetUInt32Value(ITEM_FIELD_DURABILITY) / double(m_CastItem->GetUInt32Value(ITEM_FIELD_MAXDURABILITY));
  2190. player->DurabilityLoss(pNewItem, lossPercent);
  2191. }
  2192.  
  2193. if (player->IsInventoryPos(pos))
  2194. {
  2195. ItemPosCountVec dest;
  2196. InventoryResult msg = player->CanStoreItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), dest, pNewItem, true);
  2197. if (msg == EQUIP_ERR_OK)
  2198. {
  2199. player->DestroyItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), true);
  2200.  
  2201. // prevent crash at access and unexpected charges counting with item update queue corrupt
  2202. if (m_CastItem == m_targets.GetItemTarget())
  2203. m_targets.SetItemTarget(NULL);
  2204.  
  2205. m_CastItem = NULL;
  2206.  
  2207. player->StoreItem(dest, pNewItem, true);
  2208. return;
  2209. }
  2210. }
  2211. else if (player->IsBankPos(pos))
  2212. {
  2213. ItemPosCountVec dest;
  2214. uint8 msg = player->CanBankItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), dest, pNewItem, true);
  2215. if (msg == EQUIP_ERR_OK)
  2216. {
  2217. player->DestroyItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), true);
  2218.  
  2219. // prevent crash at access and unexpected charges counting with item update queue corrupt
  2220. if (m_CastItem == m_targets.GetItemTarget())
  2221. m_targets.SetItemTarget(NULL);
  2222.  
  2223. m_CastItem = NULL;
  2224.  
  2225. player->BankItem(dest, pNewItem, true);
  2226. return;
  2227. }
  2228. }
  2229. else if (player->IsEquipmentPos(pos))
  2230. {
  2231. uint16 dest;
  2232.  
  2233. player->DestroyItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), true);
  2234.  
  2235. uint8 msg = player->CanEquipItem(m_CastItem->GetSlot(), dest, pNewItem, true);
  2236.  
  2237. if (msg == EQUIP_ERR_OK || msg == EQUIP_ERR_CANT_DO_RIGHT_NOW)
  2238. {
  2239. if (msg == EQUIP_ERR_CANT_DO_RIGHT_NOW) dest = EQUIPMENT_SLOT_MAINHAND;
  2240.  
  2241. // prevent crash at access and unexpected charges counting with item update queue corrupt
  2242. if (m_CastItem == m_targets.GetItemTarget())
  2243. m_targets.SetItemTarget(NULL);
  2244.  
  2245. m_CastItem = NULL;
  2246.  
  2247. player->EquipItem(dest, pNewItem, true);
  2248. player->AutoUnequipOffhandIfNeed();
  2249. return;
  2250. }
  2251. }
  2252.  
  2253. // fail
  2254. delete pNewItem;
  2255. }
  2256.  
  2257. void Spell::EffectProficiency(SpellEffIndex /*effIndex*/)
  2258. {
  2259. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT)
  2260. return;
  2261.  
  2262. if (m_caster->GetTypeId() != TYPEID_PLAYER)
  2263. return;
  2264. Player* p_target = m_caster->ToPlayer();
  2265.  
  2266. uint32 subClassMask = m_spellInfo->EquippedItemSubClassMask;
  2267. if (m_spellInfo->EquippedItemClass == ITEM_CLASS_WEAPON && !(p_target->GetWeaponProficiency() & subClassMask))
  2268. {
  2269. p_target->AddWeaponProficiency(subClassMask);
  2270. p_target->SendProficiency(ITEM_CLASS_WEAPON, p_target->GetWeaponProficiency());
  2271. }
  2272. if (m_spellInfo->EquippedItemClass == ITEM_CLASS_ARMOR && !(p_target->GetArmorProficiency() & subClassMask))
  2273. {
  2274. p_target->AddArmorProficiency(subClassMask);
  2275. p_target->SendProficiency(ITEM_CLASS_ARMOR, p_target->GetArmorProficiency());
  2276. }
  2277. }
  2278.  
  2279. void Spell::EffectSummonType(SpellEffIndex effIndex)
  2280. {
  2281. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT)
  2282. return;
  2283.  
  2284. uint32 entry = m_spellInfo->Effects[effIndex].MiscValue;
  2285. if (!entry)
  2286. return;
  2287.  
  2288. SummonPropertiesEntry const* properties = sSummonPropertiesStore.LookupEntry(m_spellInfo->Effects[effIndex].MiscValueB);
  2289. if (!properties)
  2290. {
  2291. sLog->outError(LOG_FILTER_SPELLS_AURAS, "EffectSummonType: Unhandled summon type %u", m_spellInfo->Effects[effIndex].MiscValueB);
  2292. return;
  2293. }
  2294.  
  2295. if (!m_originalCaster)
  2296. return;
  2297.  
  2298. int32 duration = m_spellInfo->GetDuration();
  2299. if (Player* modOwner = m_originalCaster->GetSpellModOwner())
  2300. modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_DURATION, duration);
  2301.  
  2302. TempSummon* summon = NULL;
  2303.  
  2304. // determine how many units should be summoned
  2305. uint32 numSummons;
  2306.  
  2307. // some spells need to summon many units, for those spells number of summons is stored in effect value
  2308. // however so far noone found a generic check to find all of those (there's no related data in summonproperties.dbc
  2309. // and in spell attributes, possibly we need to add a table for those)
  2310. // so here's a list of MiscValueB values, which is currently most generic check
  2311. switch (properties->Id)
  2312. {
  2313. case 64:
  2314. case 61:
  2315. case 1101:
  2316. case 66:
  2317. case 648:
  2318. case 2301:
  2319. case 1061:
  2320. case 1261:
  2321. case 629:
  2322. case 181:
  2323. case 715:
  2324. case 1562:
  2325. case 833:
  2326. case 1161:
  2327. numSummons = (damage > 0) ? damage : 1;
  2328. break;
  2329. default:
  2330. numSummons = 1;
  2331. break;
  2332. }
  2333.  
  2334. switch (properties->Category)
  2335. {
  2336. case SUMMON_CATEGORY_WILD:
  2337. case SUMMON_CATEGORY_ALLY:
  2338. case SUMMON_CATEGORY_UNK:
  2339. if (properties->Flags & 512)
  2340. {
  2341. SummonGuardian(effIndex, entry, properties, numSummons);
  2342. break;
  2343. }
  2344. switch (properties->Type)
  2345. {
  2346. case SUMMON_TYPE_PET:
  2347. case SUMMON_TYPE_GUARDIAN:
  2348. case SUMMON_TYPE_GUARDIAN2:
  2349. case SUMMON_TYPE_MINION:
  2350. SummonGuardian(effIndex, entry, properties, numSummons);
  2351. break;
  2352. // Summons a vehicle, but doesn't force anyone to enter it (see SUMMON_CATEGORY_VEHICLE)
  2353. case SUMMON_TYPE_VEHICLE:
  2354. case SUMMON_TYPE_VEHICLE2:
  2355. summon = m_caster->GetMap()->SummonCreature(entry, *destTarget, properties, duration, m_originalCaster, m_spellInfo->Id);
  2356. break;
  2357. case SUMMON_TYPE_TOTEM:
  2358. {
  2359. summon = m_caster->GetMap()->SummonCreature(entry, *destTarget, properties, duration, m_originalCaster, m_spellInfo->Id);
  2360. if (!summon || !summon->isTotem())
  2361. return;
  2362.  
  2363. // Mana Tide Totem
  2364. if (m_spellInfo->Id == 16190)
  2365. damage = m_caster->CountPctFromMaxHealth(10);
  2366.  
  2367. if (damage) // if not spell info, DB values used
  2368. {
  2369. summon->SetMaxHealth(damage);
  2370. summon->SetHealth(damage);
  2371. }
  2372. break;
  2373. }
  2374. case SUMMON_TYPE_MINIPET:
  2375. {
  2376. summon = m_caster->GetMap()->SummonCreature(entry, *destTarget, properties, duration, m_originalCaster, m_spellInfo->Id);
  2377. if (!summon || !summon->HasUnitTypeMask(UNIT_MASK_MINION))
  2378. return;
  2379.  
  2380. summon->SelectLevel(summon->GetCreatureTemplate()); // some summoned creaters have different from 1 DB data for level/hp
  2381. summon->SetUInt32Value(UNIT_NPC_FLAGS, summon->GetCreatureTemplate()->npcflag);
  2382.  
  2383. summon->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC);
  2384.  
  2385. summon->AI()->EnterEvadeMode();
  2386. break;
  2387. }
  2388. default:
  2389. {
  2390. float radius = m_spellInfo->Effects[effIndex].CalcRadius();
  2391.  
  2392. TempSummonType summonType = (duration == 0) ? TEMPSUMMON_DEAD_DESPAWN : TEMPSUMMON_TIMED_DESPAWN;
  2393.  
  2394. for (uint32 count = 0; count < numSummons; ++count)
  2395. {
  2396. Position pos;
  2397. if (count == 0)
  2398. pos = *destTarget;
  2399. else
  2400. // randomize position for multiple summons
  2401. m_caster->GetRandomPoint(*destTarget, radius, pos);
  2402.  
  2403. summon = m_originalCaster->SummonCreature(entry, pos, summonType, duration);
  2404. if (!summon)
  2405. continue;
  2406.  
  2407. if (properties->Category == SUMMON_CATEGORY_ALLY)
  2408. {
  2409. summon->SetOwnerGUID(m_originalCaster->GetGUID());
  2410. summon->setFaction(m_originalCaster->getFaction());
  2411. summon->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
  2412. }
  2413.  
  2414. ExecuteLogEffectSummonObject(effIndex, summon);
  2415. }
  2416. return;
  2417. }
  2418. }//switch
  2419. break;
  2420. case SUMMON_CATEGORY_PET:
  2421. SummonGuardian(effIndex, entry, properties, numSummons);
  2422. break;
  2423. case SUMMON_CATEGORY_PUPPET:
  2424. summon = m_caster->GetMap()->SummonCreature(entry, *destTarget, properties, duration, m_originalCaster, m_spellInfo->Id);
  2425. break;
  2426. case SUMMON_CATEGORY_VEHICLE:
  2427. // Summoning spells (usually triggered by npc_spellclick) that spawn a vehicle and that cause the clicker
  2428. // to cast a ride vehicle spell on the summoned unit.
  2429. float x, y, z;
  2430. m_caster->GetClosePoint(x, y, z, DEFAULT_WORLD_OBJECT_SIZE);
  2431. summon = m_originalCaster->GetMap()->SummonCreature(entry, *destTarget, properties, duration, m_caster, m_spellInfo->Id);
  2432. if (!summon || !summon->IsVehicle())
  2433. return;
  2434.  
  2435. // The spell that this effect will trigger. It has SPELL_AURA_CONTROL_VEHICLE
  2436. uint32 spellId = VEHICLE_SPELL_RIDE_HARDCODED;
  2437. SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(m_spellInfo->Effects[effIndex].CalcValue());
  2438. if (spellInfo && spellInfo->HasAura(SPELL_AURA_CONTROL_VEHICLE))
  2439. spellId = spellInfo->Id;
  2440.  
  2441. // Hard coded enter vehicle spell
  2442. m_originalCaster->CastSpell(summon, spellId, true);
  2443.  
  2444. uint32 faction = properties->Faction;
  2445. if (!faction)
  2446. faction = m_originalCaster->getFaction();
  2447.  
  2448. summon->setFaction(faction);
  2449. break;
  2450. }
  2451.  
  2452. if (summon)
  2453. {
  2454. summon->SetCreatorGUID(m_originalCaster->GetGUID());
  2455. ExecuteLogEffectSummonObject(effIndex, summon);
  2456. }
  2457. }
  2458.  
  2459. void Spell::EffectLearnSpell(SpellEffIndex effIndex)
  2460. {
  2461. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
  2462. return;
  2463.  
  2464. if (!unitTarget)
  2465. return;
  2466.  
  2467. if (unitTarget->GetTypeId() != TYPEID_PLAYER)
  2468. {
  2469. if (unitTarget->ToPet())
  2470. EffectLearnPetSpell(effIndex);
  2471. return;
  2472. }
  2473.  
  2474. Player* player = unitTarget->ToPlayer();
  2475.  
  2476. uint32 spellToLearn = (m_spellInfo->Id == 483 || m_spellInfo->Id == 55884) ? damage : m_spellInfo->Effects[effIndex].TriggerSpell;
  2477. player->learnSpell(spellToLearn, false);
  2478.  
  2479. sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "Spell: Player %u has learned spell %u from NpcGUID=%u", player->GetGUIDLow(), spellToLearn, m_caster->GetGUIDLow());
  2480. }
  2481.  
  2482. typedef std::list< std::pair<uint32, uint64> > DispelList;
  2483. void Spell::EffectDispel(SpellEffIndex effIndex)
  2484. {
  2485. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
  2486. return;
  2487.  
  2488. if (!unitTarget)
  2489. return;
  2490.  
  2491. // Create dispel mask by dispel type
  2492. uint32 dispel_type = m_spellInfo->Effects[effIndex].MiscValue;
  2493. uint32 dispelMask = SpellInfo::GetDispelMask(DispelType(dispel_type));
  2494.  
  2495. DispelChargesList dispel_list;
  2496. unitTarget->GetDispellableAuraList(m_caster, dispelMask, dispel_list);
  2497. if (dispel_list.empty())
  2498. return;
  2499.  
  2500. // Ok if exist some buffs for dispel try dispel it
  2501. uint32 failCount = 0;
  2502. DispelChargesList success_list;
  2503. WorldPacket dataFail(SMSG_DISPEL_FAILED, 8+8+4+4+damage*4);
  2504. // dispel N = damage buffs (or while exist buffs for dispel)
  2505. for (int32 count = 0; count < damage && !dispel_list.empty();)
  2506. {
  2507. // Random select buff for dispel
  2508. DispelChargesList::iterator itr = dispel_list.begin();
  2509. std::advance(itr, urand(0, dispel_list.size() - 1));
  2510.  
  2511. int32 chance = itr->first->CalcDispelChance(unitTarget, !unitTarget->IsFriendlyTo(m_caster));
  2512. // 2.4.3 Patch Notes: "Dispel effects will no longer attempt to remove effects that have 100% dispel resistance."
  2513. if (!chance)
  2514. {
  2515. dispel_list.erase(itr);
  2516. continue;
  2517. }
  2518. else
  2519. {
  2520. if (roll_chance_i(chance))
  2521. {
  2522. bool alreadyListed = false;
  2523. for (DispelChargesList::iterator successItr = success_list.begin(); successItr != success_list.end(); ++successItr)
  2524. {
  2525. if (successItr->first->GetId() == itr->first->GetId())
  2526. {
  2527. ++successItr->second;
  2528. alreadyListed = true;
  2529. }
  2530. }
  2531. if (!alreadyListed)
  2532. success_list.push_back(std::make_pair(itr->first, 1));
  2533. --itr->second;
  2534. if (itr->second <= 0)
  2535. dispel_list.erase(itr);
  2536. }
  2537. else
  2538. {
  2539. if (!failCount)
  2540. {
  2541. // Failed to dispell
  2542. dataFail << uint64(m_caster->GetGUID()); // Caster GUID
  2543. dataFail << uint64(unitTarget->GetGUID()); // Victim GUID
  2544. dataFail << uint32(m_spellInfo->Id); // dispel spell id
  2545. }
  2546. ++failCount;
  2547. dataFail << uint32(itr->first->GetId()); // Spell Id
  2548. }
  2549. ++count;
  2550. }
  2551. }
  2552.  
  2553. if (failCount)
  2554. m_caster->SendMessageToSet(&dataFail, true);
  2555.  
  2556. if (success_list.empty())
  2557. return;
  2558.  
  2559. WorldPacket dataSuccess(SMSG_SPELLDISPELLOG, 8+8+4+1+4+success_list.size()*5);
  2560. // Send packet header
  2561. dataSuccess.append(unitTarget->GetPackGUID()); // Victim GUID
  2562. dataSuccess.append(m_caster->GetPackGUID()); // Caster GUID
  2563. dataSuccess << uint32(m_spellInfo->Id); // dispel spell id
  2564. dataSuccess << uint8(0); // not used
  2565. dataSuccess << uint32(success_list.size()); // count
  2566. for (DispelChargesList::iterator itr = success_list.begin(); itr != success_list.end(); ++itr)
  2567. {
  2568. // Send dispelled spell info
  2569. dataSuccess << uint32(itr->first->GetId()); // Spell Id
  2570. dataSuccess << uint8(0); // 0 - dispelled !=0 cleansed
  2571. unitTarget->RemoveAurasDueToSpellByDispel(itr->first->GetId(), m_spellInfo->Id, itr->first->GetCasterGUID(), m_caster, itr->second);
  2572. }
  2573. m_caster->SendMessageToSet(&dataSuccess, true);
  2574.  
  2575. // On success dispel
  2576. // Devour Magic
  2577. if (m_spellInfo->SpellFamilyName == SPELLFAMILY_WARLOCK && m_spellInfo->Category == SPELLCATEGORY_DEVOUR_MAGIC)
  2578. {
  2579. int32 heal_amount = m_spellInfo->Effects[EFFECT_1].CalcValue();
  2580. m_caster->CastCustomSpell(m_caster, 19658, &heal_amount, NULL, NULL, true);
  2581. // Glyph of Felhunter
  2582. if (Unit* owner = m_caster->GetOwner())
  2583. if (owner->GetAura(56249))
  2584. owner->CastCustomSpell(owner, 19658, &heal_amount, NULL, NULL, true);
  2585. }
  2586. }
  2587.  
  2588. void Spell::EffectDualWield(SpellEffIndex /*effIndex*/)
  2589. {
  2590. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
  2591. return;
  2592.  
  2593. unitTarget->SetCanDualWield(true);
  2594. if (unitTarget->GetTypeId() == TYPEID_UNIT)
  2595. unitTarget->ToCreature()->UpdateDamagePhysical(OFF_ATTACK);
  2596. }
  2597.  
  2598. void Spell::EffectPull(SpellEffIndex effIndex)
  2599. {
  2600. // TODO: create a proper pull towards distract spell center for distract
  2601. EffectNULL(effIndex);
  2602. }
  2603.  
  2604. void Spell::EffectDistract(SpellEffIndex /*effIndex*/)
  2605. {
  2606. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
  2607. return;
  2608.  
  2609. // Check for possible target
  2610. if (!unitTarget || unitTarget->isInCombat())
  2611. return;
  2612.  
  2613. // target must be OK to do this
  2614. if (unitTarget->HasUnitState(UNIT_STATE_CONFUSED | UNIT_STATE_STUNNED | UNIT_STATE_FLEEING))
  2615. return;
  2616.  
  2617. unitTarget->SetFacingTo(unitTarget->GetAngle(destTarget));
  2618. unitTarget->ClearUnitState(UNIT_STATE_MOVING);
  2619.  
  2620. if (unitTarget->GetTypeId() == TYPEID_UNIT)
  2621. unitTarget->GetMotionMaster()->MoveDistract(damage * IN_MILLISECONDS);
  2622. }
  2623.  
  2624. void Spell::EffectPickPocket(SpellEffIndex /*effIndex*/)
  2625. {
  2626. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
  2627. return;
  2628.  
  2629. if (m_caster->GetTypeId() != TYPEID_PLAYER)
  2630. return;
  2631.  
  2632. // victim must be creature and attackable
  2633. if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT || m_caster->IsFriendlyTo(unitTarget))
  2634. return;
  2635.  
  2636. // victim have to be alive and humanoid or undead
  2637. if (unitTarget->isAlive() && (unitTarget->GetCreatureTypeMask() &CREATURE_TYPEMASK_HUMANOID_OR_UNDEAD) != 0)
  2638. m_caster->ToPlayer()->SendLoot(unitTarget->GetGUID(), LOOT_PICKPOCKETING);
  2639. }
  2640.  
  2641. void Spell::EffectAddFarsight(SpellEffIndex effIndex)
  2642. {
  2643. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT)
  2644. return;
  2645.  
  2646. if (m_caster->GetTypeId() != TYPEID_PLAYER)
  2647. return;
  2648.  
  2649. float radius = m_spellInfo->Effects[effIndex].CalcRadius();
  2650. int32 duration = m_spellInfo->GetDuration();
  2651. // Caster not in world, might be spell triggered from aura removal
  2652. if (!m_caster->IsInWorld())
  2653. return;
  2654.  
  2655. DynamicObject* dynObj = new DynamicObject(true);
  2656. if (!dynObj->CreateDynamicObject(sObjectMgr->GenerateLowGuid(HIGHGUID_DYNAMICOBJECT), m_caster, m_spellInfo->Id, *destTarget, radius, DYNAMIC_OBJECT_FARSIGHT_FOCUS))
  2657. {
  2658. delete dynObj;
  2659. return;
  2660. }
  2661.  
  2662. dynObj->SetDuration(duration);
  2663. dynObj->SetCasterViewpoint();
  2664. }
  2665.  
  2666. void Spell::EffectUntrainTalents(SpellEffIndex /*effIndex*/)
  2667. {
  2668. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
  2669. return;
  2670.  
  2671. if (!unitTarget || m_caster->GetTypeId() == TYPEID_PLAYER)
  2672. return;
  2673.  
  2674. if (uint64 guid = m_caster->GetGUID()) // the trainer is the caster
  2675. unitTarget->ToPlayer()->SendTalentWipeConfirm(guid);
  2676. }
  2677.  
  2678. void Spell::EffectTeleUnitsFaceCaster(SpellEffIndex effIndex)
  2679. {
  2680. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
  2681. return;
  2682.  
  2683. if (!unitTarget)
  2684. return;
  2685.  
  2686. if (unitTarget->isInFlight())
  2687. return;
  2688.  
  2689. float dis = m_spellInfo->Effects[effIndex].CalcRadius(m_caster);
  2690.  
  2691. float fx, fy, fz;
  2692. m_caster->GetClosePoint(fx, fy, fz, unitTarget->GetObjectSize(), dis);
  2693.  
  2694. unitTarget->NearTeleportTo(fx, fy, fz, -m_caster->GetOrientation(), unitTarget == m_caster);
  2695. }
  2696.  
  2697. void Spell::EffectLearnSkill(SpellEffIndex effIndex)
  2698. {
  2699. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
  2700. return;
  2701.  
  2702. if (unitTarget->GetTypeId() != TYPEID_PLAYER)
  2703. return;
  2704.  
  2705. if (damage < 0)
  2706. return;
  2707.  
  2708. uint32 skillid = m_spellInfo->Effects[effIndex].MiscValue;
  2709. uint16 skillval = unitTarget->ToPlayer()->GetPureSkillValue(skillid);
  2710. unitTarget->ToPlayer()->SetSkill(skillid, m_spellInfo->Effects[effIndex].CalcValue(), skillval?skillval:1, damage*75);
  2711. }
  2712.  
  2713. void Spell::EffectAddHonor(SpellEffIndex /*effIndex*/)
  2714. {
  2715. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
  2716. return;
  2717.  
  2718. if (unitTarget->GetTypeId() != TYPEID_PLAYER)
  2719. return;
  2720.  
  2721. // not scale value for item based reward (/10 value expected)
  2722. if (m_CastItem)
  2723. {
  2724. unitTarget->ToPlayer()->RewardHonor(NULL, 1, damage/10);
  2725. sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "SpellEffect::AddHonor (spell_id %u) rewards %d honor points (item %u) for player: %u", m_spellInfo->Id, damage/10, m_CastItem->GetEntry(), unitTarget->ToPlayer()->GetGUIDLow());
  2726. return;
  2727. }
  2728.  
  2729. // do not allow to add too many honor for player (50 * 21) = 1040 at level 70, or (50 * 31) = 1550 at level 80
  2730. if (damage <= 50)
  2731. {
  2732. uint32 honor_reward = Trinity::Honor::hk_honor_at_level(unitTarget->getLevel(), float(damage));
  2733. unitTarget->ToPlayer()->RewardHonor(NULL, 1, honor_reward);
  2734. sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "SpellEffect::AddHonor (spell_id %u) rewards %u honor points (scale) to player: %u", m_spellInfo->Id, honor_reward, unitTarget->ToPlayer()->GetGUIDLow());
  2735. }
  2736. else
  2737. {
  2738. //maybe we have correct honor_gain in damage already
  2739. unitTarget->ToPlayer()->RewardHonor(NULL, 1, damage);
  2740. sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "SpellEffect::AddHonor (spell_id %u) rewards %u honor points (non scale) for player: %u", m_spellInfo->Id, damage, unitTarget->ToPlayer()->GetGUIDLow());
  2741. }
  2742. }
  2743.  
  2744. void Spell::EffectTradeSkill(SpellEffIndex /*effIndex*/)
  2745. {
  2746. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT)
  2747. return;
  2748.  
  2749. if (m_caster->GetTypeId() != TYPEID_PLAYER)
  2750. return;
  2751. // uint32 skillid = m_spellInfo->Effects[i].MiscValue;
  2752. // uint16 skillmax = unitTarget->ToPlayer()->(skillid);
  2753. // m_caster->ToPlayer()->SetSkill(skillid, skillval?skillval:1, skillmax+75);
  2754. }
  2755.  
  2756. void Spell::EffectEnchantItemPerm(SpellEffIndex effIndex)
  2757. {
  2758. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
  2759. return;
  2760.  
  2761. if (m_caster->GetTypeId() != TYPEID_PLAYER)
  2762. return;
  2763. if (!itemTarget)
  2764. return;
  2765.  
  2766. Player* p_caster = (Player*)m_caster;
  2767.  
  2768. // Handle vellums
  2769. if (itemTarget->IsWeaponVellum() || itemTarget->IsArmorVellum())
  2770. {
  2771. // destroy one vellum from stack
  2772. uint32 count = 1;
  2773. p_caster->DestroyItemCount(itemTarget, count, true);
  2774. unitTarget=p_caster;
  2775. // and add a scroll
  2776. DoCreateItem(effIndex, m_spellInfo->Effects[effIndex].ItemType);
  2777. itemTarget=NULL;
  2778. m_targets.SetItemTarget(NULL);
  2779. }
  2780. else
  2781. {
  2782. // do not increase skill if vellum used
  2783. if (!(m_CastItem && m_CastItem->GetTemplate()->Flags & ITEM_PROTO_FLAG_TRIGGERED_CAST))
  2784. p_caster->UpdateCraftSkill(m_spellInfo->Id);
  2785.  
  2786. uint32 enchant_id = m_spellInfo->Effects[effIndex].MiscValue;
  2787. if (!enchant_id)
  2788. return;
  2789.  
  2790. SpellItemEnchantmentEntry const* pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
  2791. if (!pEnchant)
  2792. return;
  2793.  
  2794. // item can be in trade slot and have owner diff. from caster
  2795. Player* item_owner = itemTarget->GetOwner();
  2796. if (!item_owner)
  2797. return;
  2798.  
  2799. if (item_owner != p_caster && !AccountMgr::IsPlayerAccount(p_caster->GetSession()->GetSecurity()) && sWorld->getBoolConfig(CONFIG_GM_LOG_TRADE))
  2800. {
  2801. sLog->outCommand(p_caster->GetSession()->GetAccountId(), "GM %s (Account: %u) enchanting(perm): %s (Entry: %d) for player: %s (Account: %u)",
  2802. p_caster->GetName().c_str(), p_caster->GetSession()->GetAccountId(),
  2803. itemTarget->GetTemplate()->Name1.c_str(), itemTarget->GetEntry(),
  2804. item_owner->GetName().c_str(), item_owner->GetSession()->GetAccountId());
  2805. }
  2806.  
  2807. // remove old enchanting before applying new if equipped
  2808. item_owner->ApplyEnchantment(itemTarget, PERM_ENCHANTMENT_SLOT, false);
  2809.  
  2810. itemTarget->SetEnchantment(PERM_ENCHANTMENT_SLOT, enchant_id, 0, 0);
  2811.  
  2812. // add new enchanting if equipped
  2813. item_owner->ApplyEnchantment(itemTarget, PERM_ENCHANTMENT_SLOT, true);
  2814.  
  2815. item_owner->RemoveTradeableItem(itemTarget);
  2816. itemTarget->ClearSoulboundTradeable(item_owner);
  2817. }
  2818. }
  2819.  
  2820. void Spell::EffectEnchantItemPrismatic(SpellEffIndex effIndex)
  2821. {
  2822. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
  2823. return;
  2824.  
  2825. if (m_caster->GetTypeId() != TYPEID_PLAYER)
  2826. return;
  2827. if (!itemTarget)
  2828. return;
  2829.  
  2830. Player* p_caster = (Player*)m_caster;
  2831.  
  2832. uint32 enchant_id = m_spellInfo->Effects[effIndex].MiscValue;
  2833. if (!enchant_id)
  2834. return;
  2835.  
  2836. SpellItemEnchantmentEntry const* pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
  2837. if (!pEnchant)
  2838. return;
  2839.  
  2840. // support only enchantings with add socket in this slot
  2841. {
  2842. bool add_socket = false;
  2843. for (uint8 i = 0; i < MAX_ITEM_ENCHANTMENT_EFFECTS; ++i)
  2844. {
  2845. if (pEnchant->type[i] == ITEM_ENCHANTMENT_TYPE_PRISMATIC_SOCKET)
  2846. {
  2847. add_socket = true;
  2848. break;
  2849. }
  2850. }
  2851. if (!add_socket)
  2852. {
  2853. sLog->outError(LOG_FILTER_SPELLS_AURAS, "Spell::EffectEnchantItemPrismatic: attempt apply enchant spell %u with SPELL_EFFECT_ENCHANT_ITEM_PRISMATIC (%u) but without ITEM_ENCHANTMENT_TYPE_PRISMATIC_SOCKET (%u), not suppoted yet.",
  2854. m_spellInfo->Id, SPELL_EFFECT_ENCHANT_ITEM_PRISMATIC, ITEM_ENCHANTMENT_TYPE_PRISMATIC_SOCKET);
  2855. return;
  2856. }
  2857. }
  2858.  
  2859. // item can be in trade slot and have owner diff. from caster
  2860. Player* item_owner = itemTarget->GetOwner();
  2861. if (!item_owner)
  2862. return;
  2863.  
  2864. if (item_owner != p_caster && !AccountMgr::IsPlayerAccount(p_caster->GetSession()->GetSecurity()) && sWorld->getBoolConfig(CONFIG_GM_LOG_TRADE))
  2865. {
  2866. sLog->outCommand(p_caster->GetSession()->GetAccountId(), "GM %s (Account: %u) enchanting(perm): %s (Entry: %d) for player: %s (Account: %u)",
  2867. p_caster->GetName().c_str(), p_caster->GetSession()->GetAccountId(),
  2868. itemTarget->GetTemplate()->Name1.c_str(), itemTarget->GetEntry(),
  2869. item_owner->GetName().c_str(), item_owner->GetSession()->GetAccountId());
  2870. }
  2871.  
  2872. // remove old enchanting before applying new if equipped
  2873. item_owner->ApplyEnchantment(itemTarget, PRISMATIC_ENCHANTMENT_SLOT, false);
  2874.  
  2875. itemTarget->SetEnchantment(PRISMATIC_ENCHANTMENT_SLOT, enchant_id, 0, 0);
  2876.  
  2877. // add new enchanting if equipped
  2878. item_owner->ApplyEnchantment(itemTarget, PRISMATIC_ENCHANTMENT_SLOT, true);
  2879.  
  2880. item_owner->RemoveTradeableItem(itemTarget);
  2881. itemTarget->ClearSoulboundTradeable(item_owner);
  2882. }
  2883.  
  2884. void Spell::EffectEnchantItemTmp(SpellEffIndex effIndex)
  2885. {
  2886. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
  2887. return;
  2888.  
  2889. if (m_caster->GetTypeId() != TYPEID_PLAYER)
  2890. return;
  2891.  
  2892. Player* p_caster = (Player*)m_caster;
  2893.  
  2894. // Rockbiter Weapon apply to both weapon
  2895. if (!itemTarget)
  2896. return;
  2897. if (m_spellInfo->SpellFamilyName == SPELLFAMILY_SHAMAN && m_spellInfo->SpellFamilyFlags[0] & 0x400000)
  2898. {
  2899. uint32 spell_id = 0;
  2900.  
  2901. // enchanting spell selected by calculated damage-per-sec stored in Effect[1] base value
  2902. // Note: damage calculated (correctly) with rounding int32(float(v)) but
  2903. // RW enchantments applied damage int32(float(v)+0.5), this create 0..1 difference sometime
  2904. switch (damage)
  2905. {
  2906. // Rank 1
  2907. case 2: spell_id = 36744; break; // 0% [ 7% == 2, 14% == 2, 20% == 2]
  2908. // Rank 2
  2909. case 4: spell_id = 36753; break; // 0% [ 7% == 4, 14% == 4]
  2910. case 5: spell_id = 36751; break; // 20%
  2911. // Rank 3
  2912. case 6: spell_id = 36754; break; // 0% [ 7% == 6, 14% == 6]
  2913. case 7: spell_id = 36755; break; // 20%
  2914. // Rank 4
  2915. case 9: spell_id = 36761; break; // 0% [ 7% == 6]
  2916. case 10: spell_id = 36758; break; // 14%
  2917. case 11: spell_id = 36760; break; // 20%
  2918. default:
  2919. sLog->outError(LOG_FILTER_SPELLS_AURAS, "Spell::EffectEnchantItemTmp: Damage %u not handled in S'RW", damage);
  2920. return;
  2921. }
  2922.  
  2923. SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spell_id);
  2924. if (!spellInfo)
  2925. {
  2926. sLog->outError(LOG_FILTER_SPELLS_AURAS, "Spell::EffectEnchantItemTmp: unknown spell id %i", spell_id);
  2927. return;
  2928.  
  2929. }
  2930.  
  2931. for (int j = BASE_ATTACK; j <= OFF_ATTACK; ++j)
  2932. {
  2933. if (Item* item = p_caster->GetWeaponForAttack(WeaponAttackType(j)))
  2934. {
  2935. if (item->IsFitToSpellRequirements(m_spellInfo))
  2936. {
  2937. Spell* spell = new Spell(m_caster, spellInfo, TRIGGERED_FULL_MASK);
  2938. SpellCastTargets targets;
  2939. targets.SetItemTarget(item);
  2940. spell->prepare(&targets);
  2941. }
  2942. }
  2943. }
  2944. return;
  2945. }
  2946. if (!itemTarget)
  2947. return;
  2948.  
  2949. uint32 enchant_id = m_spellInfo->Effects[effIndex].MiscValue;
  2950.  
  2951. if (!enchant_id)
  2952. {
  2953. sLog->outError(LOG_FILTER_SPELLS_AURAS, "Spell %u Effect %u (SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY) have 0 as enchanting id", m_spellInfo->Id, effIndex);
  2954. return;
  2955. }
  2956.  
  2957. SpellItemEnchantmentEntry const* pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
  2958. if (!pEnchant)
  2959. {
  2960. sLog->outError(LOG_FILTER_SPELLS_AURAS, "Spell %u Effect %u (SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY) have not existed enchanting id %u ", m_spellInfo->Id, effIndex, enchant_id);
  2961. return;
  2962. }
  2963.  
  2964. // select enchantment duration
  2965. uint32 duration;
  2966.  
  2967. // rogue family enchantments exception by duration
  2968. if (m_spellInfo->Id == 38615)
  2969. duration = 1800; // 30 mins
  2970. // other rogue family enchantments always 1 hour (some have spell damage=0, but some have wrong data in EffBasePoints)
  2971. else if (m_spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE)
  2972. duration = 3600; // 1 hour
  2973. // shaman family enchantments
  2974. else if (m_spellInfo->SpellFamilyName == SPELLFAMILY_SHAMAN)
  2975. duration = 1800; // 30 mins
  2976. // other cases with this SpellVisual already selected
  2977. else if (m_spellInfo->SpellVisual[0] == 215)
  2978. duration = 1800; // 30 mins
  2979. // some fishing pole bonuses except Glow Worm which lasts full hour
  2980. else if (m_spellInfo->SpellVisual[0] == 563 && m_spellInfo->Id != 64401)
  2981. duration = 600; // 10 mins
  2982. // shaman rockbiter enchantments
  2983. else if (m_spellInfo->SpellVisual[0] == 0)
  2984. duration = 1800; // 30 mins
  2985. else if (m_spellInfo->Id == 29702)
  2986. duration = 300; // 5 mins
  2987. else if (m_spellInfo->Id == 37360)
  2988. duration = 300; // 5 mins
  2989. // default case
  2990. else
  2991. duration = 3600; // 1 hour
  2992.  
  2993. // item can be in trade slot and have owner diff. from caster
  2994. Player* item_owner = itemTarget->GetOwner();
  2995. if (!item_owner)
  2996. return;
  2997.  
  2998. if (item_owner != p_caster && !AccountMgr::IsPlayerAccount(p_caster->GetSession()->GetSecurity()) && sWorld->getBoolConfig(CONFIG_GM_LOG_TRADE))
  2999. {
  3000. sLog->outCommand(p_caster->GetSession()->GetAccountId(), "GM %s (Account: %u) enchanting(temp): %s (Entry: %d) for player: %s (Account: %u)",
  3001. p_caster->GetName().c_str(), p_caster->GetSession()->GetAccountId(),
  3002. itemTarget->GetTemplate()->Name1.c_str(), itemTarget->GetEntry(),
  3003. item_owner->GetName().c_str(), item_owner->GetSession()->GetAccountId());
  3004. }
  3005.  
  3006. // remove old enchanting before applying new if equipped
  3007. item_owner->ApplyEnchantment(itemTarget, TEMP_ENCHANTMENT_SLOT, false);
  3008.  
  3009. itemTarget->SetEnchantment(TEMP_ENCHANTMENT_SLOT, enchant_id, duration * 1000, 0);
  3010.  
  3011. // add new enchanting if equipped
  3012. item_owner->ApplyEnchantment(itemTarget, TEMP_ENCHANTMENT_SLOT, true);
  3013. }
  3014.  
  3015. void Spell::EffectTameCreature(SpellEffIndex /*effIndex*/)
  3016. {
  3017. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
  3018. return;
  3019.  
  3020. if (m_caster->GetPetGUID())
  3021. return;
  3022.  
  3023. if (!unitTarget)
  3024. return;
  3025.  
  3026. if (unitTarget->GetTypeId() != TYPEID_UNIT)
  3027. return;
  3028.  
  3029. Creature* creatureTarget = unitTarget->ToCreature();
  3030.  
  3031. if (creatureTarget->isPet())
  3032. return;
  3033.  
  3034. if (m_caster->getClass() != CLASS_HUNTER)
  3035. return;
  3036.  
  3037. // cast finish successfully
  3038. //SendChannelUpdate(0);
  3039. finish();
  3040.  
  3041. Pet* pet = m_caster->CreateTamedPetFrom(creatureTarget, m_spellInfo->Id);
  3042. if (!pet) // in very specific state like near world end/etc.
  3043. return;
  3044.  
  3045. // "kill" original creature
  3046. creatureTarget->DespawnOrUnsummon();
  3047.  
  3048. uint8 level = (creatureTarget->getLevel() < (m_caster->getLevel() - 5)) ? (m_caster->getLevel() - 5) : creatureTarget->getLevel();
  3049.  
  3050. // prepare visual effect for levelup
  3051. pet->SetUInt32Value(UNIT_FIELD_LEVEL, level - 1);
  3052.  
  3053. // add to world
  3054. pet->GetMap()->AddToMap(pet->ToCreature());
  3055.  
  3056. // visual effect for levelup
  3057. pet->SetUInt32Value(UNIT_FIELD_LEVEL, level);
  3058.  
  3059. // caster have pet now
  3060. m_caster->SetMinion(pet, true);
  3061.  
  3062. pet->InitTalentForLevel();
  3063.  
  3064. if (m_caster->GetTypeId() == TYPEID_PLAYER)
  3065. {
  3066. pet->SavePetToDB(PET_SAVE_AS_CURRENT);
  3067. m_caster->ToPlayer()->PetSpellInitialize();
  3068. }
  3069. }
  3070.  
  3071. void Spell::EffectSummonPet(SpellEffIndex effIndex)
  3072. {
  3073. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT)
  3074. return;
  3075.  
  3076. Player* owner = NULL;
  3077. if (m_originalCaster)
  3078. {
  3079. owner = m_originalCaster->ToPlayer();
  3080. if (!owner && m_originalCaster->ToCreature()->isTotem())
  3081. owner = m_originalCaster->GetCharmerOrOwnerPlayerOrPlayerItself();
  3082. }
  3083.  
  3084. uint32 petentry = m_spellInfo->Effects[effIndex].MiscValue;
  3085.  
  3086. if (!owner)
  3087. {
  3088. SummonPropertiesEntry const* properties = sSummonPropertiesStore.LookupEntry(67);
  3089. if (properties)
  3090. SummonGuardian(effIndex, petentry, properties, 1);
  3091. return;
  3092. }
  3093.  
  3094. Pet* OldSummon = owner->GetPet();
  3095.  
  3096. // if pet requested type already exist
  3097. if (OldSummon)
  3098. {
  3099. if (petentry == 0 || OldSummon->GetEntry() == petentry)
  3100. {
  3101. // pet in corpse state can't be summoned
  3102. if (OldSummon->isDead())
  3103. return;
  3104.  
  3105. ASSERT(OldSummon->GetMap() == owner->GetMap());
  3106.  
  3107. //OldSummon->GetMap()->Remove(OldSummon->ToCreature(), false);
  3108.  
  3109. float px, py, pz;
  3110. owner->GetClosePoint(px, py, pz, OldSummon->GetObjectSize());
  3111.  
  3112. OldSummon->NearTeleportTo(px, py, pz, OldSummon->GetOrientation());
  3113. //OldSummon->Relocate(px, py, pz, OldSummon->GetOrientation());
  3114. //OldSummon->SetMap(owner->GetMap());
  3115. //owner->GetMap()->Add(OldSummon->ToCreature());
  3116.  
  3117. if (owner->GetTypeId() == TYPEID_PLAYER && OldSummon->isControlled())
  3118. owner->ToPlayer()->PetSpellInitialize();
  3119.  
  3120. return;
  3121. }
  3122.  
  3123. if (owner->GetTypeId() == TYPEID_PLAYER)
  3124. owner->ToPlayer()->RemovePet(OldSummon, (OldSummon->getPetType() == HUNTER_PET ? PET_SAVE_AS_DELETED : PET_SAVE_NOT_IN_SLOT), false);
  3125. else
  3126. return;
  3127. }
  3128.  
  3129. float x, y, z;
  3130. owner->GetClosePoint(x, y, z, owner->GetObjectSize());
  3131. Pet* pet = owner->SummonPet(petentry, x, y, z, owner->GetOrientation(), SUMMON_PET, 0);
  3132. if (!pet)
  3133. return;
  3134.  
  3135. if (m_caster->GetTypeId() == TYPEID_UNIT)
  3136. {
  3137. if (m_caster->ToCreature()->isTotem())
  3138. pet->SetReactState(REACT_AGGRESSIVE);
  3139. else
  3140. pet->SetReactState(REACT_DEFENSIVE);
  3141. }
  3142.  
  3143. pet->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
  3144.  
  3145. // generate new name for summon pet
  3146. std::string new_name=sObjectMgr->GeneratePetName(petentry);
  3147. if (!new_name.empty())
  3148. pet->SetName(new_name);
  3149.  
  3150. ExecuteLogEffectSummonObject(effIndex, pet);
  3151. }
  3152.  
  3153. void Spell::EffectLearnPetSpell(SpellEffIndex effIndex)
  3154. {
  3155. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
  3156. return;
  3157.  
  3158. if (!unitTarget)
  3159. return;
  3160.  
  3161. if (unitTarget->ToPlayer())
  3162. {
  3163. EffectLearnSpell(effIndex);
  3164. return;
  3165. }
  3166. Pet* pet = unitTarget->ToPet();
  3167. if (!pet)
  3168. return;
  3169.  
  3170. SpellInfo const* learn_spellproto = sSpellMgr->GetSpellInfo(m_spellInfo->Effects[effIndex].TriggerSpell);
  3171. if (!learn_spellproto)
  3172. return;
  3173.  
  3174. pet->learnSpell(learn_spellproto->Id);
  3175. pet->SavePetToDB(PET_SAVE_AS_CURRENT);
  3176. pet->GetOwner()->PetSpellInitialize();
  3177. }
  3178.  
  3179. void Spell::EffectTaunt(SpellEffIndex /*effIndex*/)
  3180. {
  3181. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
  3182. return;
  3183.  
  3184. if (!unitTarget)
  3185. return;
  3186.  
  3187. // this effect use before aura Taunt apply for prevent taunt already attacking target
  3188. // for spell as marked "non effective at already attacking target"
  3189. if (!unitTarget || !unitTarget->CanHaveThreatList()
  3190. || unitTarget->getVictim() == m_caster)
  3191. {
  3192. SendCastResult(SPELL_FAILED_DONT_REPORT);
  3193. return;
  3194. }
  3195.  
  3196. if (m_spellInfo->Id == 62124)
  3197. m_caster->CastSpell(unitTarget, 67485, true);
  3198.  
  3199. // Also use this effect to set the taunter's threat to the taunted creature's highest value
  3200. if (unitTarget->getThreatManager().getCurrentVictim())
  3201. {
  3202. float myThreat = unitTarget->getThreatManager().getThreat(m_caster);
  3203. float itsThreat = unitTarget->getThreatManager().getCurrentVictim()->getThreat();
  3204. if (itsThreat > myThreat)
  3205. unitTarget->getThreatManager().addThreat(m_caster, itsThreat - myThreat);
  3206. }
  3207.  
  3208. //Set aggro victim to caster
  3209. if (!unitTarget->getThreatManager().getOnlineContainer().empty())
  3210. if (HostileReference* forcedVictim = unitTarget->getThreatManager().getOnlineContainer().getReferenceByTarget(m_caster))
  3211. unitTarget->getThreatManager().setCurrentVictim(forcedVictim);
  3212.  
  3213. if (unitTarget->ToCreature()->IsAIEnabled && !unitTarget->ToCreature()->HasReactState(REACT_PASSIVE))
  3214. unitTarget->ToCreature()->AI()->AttackStart(m_caster);
  3215. }
  3216.  
  3217. void Spell::EffectWeaponDmg(SpellEffIndex effIndex)
  3218. {
  3219. if (effectHandleMode != SPELL_EFFECT_HANDLE_LAUNCH_TARGET)
  3220. return;
  3221.  
  3222. if (!unitTarget || !unitTarget->isAlive())
  3223. return;
  3224.  
  3225. // multiple weapon dmg effect workaround
  3226. // execute only the last weapon damage
  3227. // and handle all effects at once
  3228. for (uint32 j = effIndex + 1; j < MAX_SPELL_EFFECTS; ++j)
  3229. {
  3230. switch (m_spellInfo->Effects[j].Effect)
  3231. {
  3232. case SPELL_EFFECT_WEAPON_DAMAGE:
  3233. case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL:
  3234. case SPELL_EFFECT_NORMALIZED_WEAPON_DMG:
  3235. case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE:
  3236. return; // we must calculate only at last weapon effect
  3237. break;
  3238. }
  3239. }
  3240.  
  3241. // some spell specific modifiers
  3242. float totalDamagePercentMod = 1.0f; // applied to final bonus+weapon damage
  3243. int32 fixed_bonus = 0;
  3244. int32 spell_bonus = 0; // bonus specific for spell
  3245.  
  3246. switch (m_spellInfo->SpellFamilyName)
  3247. {
  3248. case SPELLFAMILY_GENERIC:
  3249. {
  3250. switch (m_spellInfo->Id)
  3251. {
  3252. case 69055: // Saber Lash
  3253. case 70814: // Saber Lash
  3254. {
  3255. uint32 count = 0;
  3256. for (std::list<TargetInfo>::iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
  3257. if (ihit->effectMask & (1 << effIndex))
  3258. ++count;
  3259.  
  3260. totalDamagePercentMod /= count;
  3261. break;
  3262. }
  3263. }
  3264. break;
  3265. }
  3266. case SPELLFAMILY_WARRIOR:
  3267. {
  3268. // Devastate (player ones)
  3269. if (m_spellInfo->SpellFamilyFlags[1] & 0x40)
  3270. {
  3271. // Player can apply only 58567 Sunder Armor effect.
  3272. bool needCast = !unitTarget->HasAura(58567, m_caster->GetGUID());
  3273. if (needCast)
  3274. m_caster->CastSpell(unitTarget, 58567, true);
  3275.  
  3276. if (Aura* aur = unitTarget->GetAura(58567, m_caster->GetGUID()))
  3277. {
  3278. // 58388 - Glyph of Devastate dummy aura.
  3279. if (int32 num = (needCast ? 0 : 1) + (m_caster->HasAura(58388) ? 1 : 0))
  3280. aur->ModStackAmount(num);
  3281. fixed_bonus += (aur->GetStackAmount() - 1) * CalculateDamage(2, unitTarget);
  3282. }
  3283. }
  3284. if (m_spellInfo->SpellFamilyFlags[0] & 0x8000000) // Mocking Blow
  3285. {
  3286. if (unitTarget->IsImmunedToSpellEffect(m_spellInfo,EFFECT_1) || unitTarget->GetTypeId() == TYPEID_PLAYER)
  3287. {
  3288. m_damage = 0;
  3289. return;
  3290. }
  3291. }
  3292. break;
  3293. }
  3294. case SPELLFAMILY_ROGUE:
  3295. {
  3296. // Fan of Knives, Hemorrhage, Ghostly Strike
  3297. if ((m_spellInfo->SpellFamilyFlags[1] & 0x40000)
  3298. || (m_spellInfo->SpellFamilyFlags[0] & 0x6000000))
  3299. {
  3300. // Hemorrhage
  3301. if (m_spellInfo->SpellFamilyFlags[0] & 0x2000000)
  3302. {
  3303. if (m_caster->GetTypeId() == TYPEID_PLAYER)
  3304. m_caster->ToPlayer()->AddComboPoints(unitTarget, 1, this);
  3305. }
  3306. // 50% more damage with daggers
  3307. if (m_caster->GetTypeId() == TYPEID_PLAYER)
  3308. if (Item* item = m_caster->ToPlayer()->GetWeaponForAttack(m_attackType, true))
  3309. if (item->GetTemplate()->SubClass == ITEM_SUBCLASS_WEAPON_DAGGER)
  3310. totalDamagePercentMod *= 1.5f;
  3311. }
  3312. // Mutilate (for each hand)
  3313. else if (m_spellInfo->SpellFamilyFlags[1] & 0x6)
  3314. {
  3315. bool found = false;
  3316. // fast check
  3317. if (unitTarget->HasAuraState(AURA_STATE_DEADLY_POISON, m_spellInfo, m_caster))
  3318. found = true;
  3319. // full aura scan
  3320. else
  3321. {
  3322. Unit::AuraApplicationMap const& auras = unitTarget->GetAppliedAuras();
  3323. for (Unit::AuraApplicationMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
  3324. {
  3325. if (itr->second->GetBase()->GetSpellInfo()->Dispel == DISPEL_POISON)
  3326. {
  3327. found = true;
  3328. break;
  3329. }
  3330. }
  3331. }
  3332.  
  3333. if (found)
  3334. totalDamagePercentMod *= 1.2f; // 120% if poisoned
  3335. }
  3336. break;
  3337. }
  3338. case SPELLFAMILY_PALADIN:
  3339. {
  3340. // Seal of Command Unleashed
  3341. if (m_spellInfo->Id == 20467)
  3342. {
  3343. spell_bonus += int32(0.08f * m_caster->GetTotalAttackPowerValue(BASE_ATTACK));
  3344. spell_bonus += int32(0.13f * m_caster->SpellBaseDamageBonusDone(m_spellInfo->GetSchoolMask()));
  3345. }
  3346. break;
  3347. }
  3348. case SPELLFAMILY_SHAMAN:
  3349. {
  3350. // Skyshatter Harness item set bonus
  3351. // Stormstrike
  3352. if (AuraEffect* aurEff = m_caster->IsScriptOverriden(m_spellInfo, 5634))
  3353. m_caster->CastSpell(m_caster, 38430, true, NULL, aurEff);
  3354. break;
  3355. }
  3356. case SPELLFAMILY_DRUID:
  3357. {
  3358. // Mangle (Cat): CP
  3359. if (m_spellInfo->SpellFamilyFlags[1] & 0x400)
  3360. {
  3361. if (m_caster->GetTypeId() == TYPEID_PLAYER)
  3362. m_caster->ToPlayer()->AddComboPoints(unitTarget, 1, this);
  3363. }
  3364. // Shred, Maul - Rend and Tear
  3365. else if (m_spellInfo->SpellFamilyFlags[0] & 0x00008800 && unitTarget->HasAuraState(AURA_STATE_BLEEDING))
  3366. {
  3367. if (AuraEffect const* rendAndTear = m_caster->GetDummyAuraEffect(SPELLFAMILY_DRUID, 2859, 0))
  3368. AddPct(totalDamagePercentMod, rendAndTear->GetAmount());
  3369. }
  3370. break;
  3371. }
  3372. case SPELLFAMILY_HUNTER:
  3373. {
  3374. // Kill Shot - bonus damage from Ranged Attack Power
  3375. if (m_spellInfo->SpellFamilyFlags[1] & 0x800000)
  3376. spell_bonus += int32(0.4f * m_caster->GetTotalAttackPowerValue(RANGED_ATTACK));
  3377. break;
  3378. }
  3379. case SPELLFAMILY_DEATHKNIGHT:
  3380. {
  3381. // Plague Strike
  3382. if (m_spellInfo->SpellFamilyFlags[0] & 0x1)
  3383. {
  3384. // Glyph of Plague Strike
  3385. if (AuraEffect const* aurEff = m_caster->GetAuraEffect(58657, EFFECT_0))
  3386. AddPct(totalDamagePercentMod, aurEff->GetAmount());
  3387. break;
  3388. }
  3389. // Blood Strike
  3390. if (m_spellInfo->SpellFamilyFlags[0] & 0x400000)
  3391. {
  3392. float bonusPct = m_spellInfo->Effects[EFFECT_2].CalcValue() * unitTarget->GetDiseasesByCaster(m_caster->GetGUID()) / 2.0f;
  3393. // Death Knight T8 Melee 4P Bonus
  3394. if (AuraEffect const* aurEff = m_caster->GetAuraEffect(64736, EFFECT_0))
  3395. AddPct(bonusPct, aurEff->GetAmount());
  3396. AddPct(totalDamagePercentMod, bonusPct);
  3397.  
  3398. // Glyph of Blood Strike
  3399. if (m_caster->GetAuraEffect(59332, EFFECT_0))
  3400. if (unitTarget->HasAuraType(SPELL_AURA_MOD_DECREASE_SPEED))
  3401. AddPct(totalDamagePercentMod, 20);
  3402. break;
  3403. }
  3404. // Death Strike
  3405. if (m_spellInfo->SpellFamilyFlags[0] & 0x10)
  3406. {
  3407. // Glyph of Death Strike
  3408. if (AuraEffect const* aurEff = m_caster->GetAuraEffect(59336, EFFECT_0))
  3409. if (uint32 runic = std::min<uint32>(m_caster->GetPower(POWER_RUNIC_POWER), aurEff->GetSpellInfo()->Effects[EFFECT_1].CalcValue()))
  3410. AddPct(totalDamagePercentMod, runic);
  3411. break;
  3412. }
  3413. // Obliterate (12.5% more damage per disease)
  3414. if (m_spellInfo->SpellFamilyFlags[1] & 0x20000)
  3415. {
  3416. bool consumeDiseases = true;
  3417. // Annihilation
  3418. if (AuraEffect const* aurEff = m_caster->GetDummyAuraEffect(SPELLFAMILY_DEATHKNIGHT, 2710, EFFECT_0))
  3419. // Do not consume diseases if roll sucesses
  3420. if (roll_chance_i(aurEff->GetAmount()))
  3421. consumeDiseases = false;
  3422.  
  3423. float bonusPct = m_spellInfo->Effects[EFFECT_2].CalcValue() * unitTarget->GetDiseasesByCaster(m_caster->GetGUID(), consumeDiseases) / 2.0f;
  3424. // Death Knight T8 Melee 4P Bonus
  3425. if (AuraEffect const* aurEff = m_caster->GetAuraEffect(64736, EFFECT_0))
  3426. AddPct(bonusPct, aurEff->GetAmount());
  3427. AddPct(totalDamagePercentMod, bonusPct);
  3428. break;
  3429. }
  3430. // Blood-Caked Strike - Blood-Caked Blade
  3431. if (m_spellInfo->SpellIconID == 1736)
  3432. {
  3433. AddPct(totalDamagePercentMod, unitTarget->GetDiseasesByCaster(m_caster->GetGUID()) * 12.5f);
  3434. break;
  3435. }
  3436. // Heart Strike
  3437. if (m_spellInfo->SpellFamilyFlags[0] & 0x1000000)
  3438. {
  3439. float bonusPct = m_spellInfo->Effects[EFFECT_2].CalcValue() * unitTarget->GetDiseasesByCaster(m_caster->GetGUID());
  3440. // Death Knight T8 Melee 4P Bonus
  3441. if (AuraEffect const* aurEff = m_caster->GetAuraEffect(64736, EFFECT_0))
  3442. AddPct(bonusPct, aurEff->GetAmount());
  3443.  
  3444. AddPct(totalDamagePercentMod, bonusPct);
  3445. break;
  3446. }
  3447. break;
  3448. }
  3449. }
  3450.  
  3451. bool normalized = false;
  3452. float weaponDamagePercentMod = 1.0f;
  3453. for (int j = 0; j < MAX_SPELL_EFFECTS; ++j)
  3454. {
  3455. switch (m_spellInfo->Effects[j].Effect)
  3456. {
  3457. case SPELL_EFFECT_WEAPON_DAMAGE:
  3458. case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL:
  3459. fixed_bonus += CalculateDamage(j, unitTarget);
  3460. break;
  3461. case SPELL_EFFECT_NORMALIZED_WEAPON_DMG:
  3462. fixed_bonus += CalculateDamage(j, unitTarget);
  3463. normalized = true;
  3464. break;
  3465. case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE:
  3466. ApplyPct(weaponDamagePercentMod, CalculateDamage(j, unitTarget));
  3467. break;
  3468. default:
  3469. break; // not weapon damage effect, just skip
  3470. }
  3471. }
  3472.  
  3473. // apply to non-weapon bonus weapon total pct effect, weapon total flat effect included in weapon damage
  3474. if (fixed_bonus || spell_bonus)
  3475. {
  3476. UnitMods unitMod;
  3477. switch (m_attackType)
  3478. {
  3479. default:
  3480. case BASE_ATTACK: unitMod = UNIT_MOD_DAMAGE_MAINHAND; break;
  3481. case OFF_ATTACK: unitMod = UNIT_MOD_DAMAGE_OFFHAND; break;
  3482. case RANGED_ATTACK: unitMod = UNIT_MOD_DAMAGE_RANGED; break;
  3483. }
  3484.  
  3485. float weapon_total_pct = 1.0f;
  3486. if (m_spellInfo->SchoolMask & SPELL_SCHOOL_MASK_NORMAL)
  3487. weapon_total_pct = m_caster->GetModifierValue(unitMod, TOTAL_PCT);
  3488.  
  3489. if (fixed_bonus)
  3490. fixed_bonus = int32(fixed_bonus * weapon_total_pct);
  3491. if (spell_bonus)
  3492. spell_bonus = int32(spell_bonus * weapon_total_pct);
  3493. }
  3494.  
  3495. int32 weaponDamage = m_caster->CalculateDamage(m_attackType, normalized, true);
  3496.  
  3497. // Sequence is important
  3498. for (int j = 0; j < MAX_SPELL_EFFECTS; ++j)
  3499. {
  3500. // We assume that a spell have at most one fixed_bonus
  3501. // and at most one weaponDamagePercentMod
  3502. switch (m_spellInfo->Effects[j].Effect)
  3503. {
  3504. case SPELL_EFFECT_WEAPON_DAMAGE:
  3505. case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL:
  3506. case SPELL_EFFECT_NORMALIZED_WEAPON_DMG:
  3507. weaponDamage += fixed_bonus;
  3508. break;
  3509. case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE:
  3510. weaponDamage = int32(weaponDamage* weaponDamagePercentMod);
  3511. default:
  3512. break; // not weapon damage effect, just skip
  3513. }
  3514. }
  3515.  
  3516. if (spell_bonus)
  3517. weaponDamage += spell_bonus;
  3518.  
  3519. if (totalDamagePercentMod != 1.0f)
  3520. weaponDamage = int32(weaponDamage* totalDamagePercentMod);
  3521.  
  3522. // prevent negative damage
  3523. uint32 eff_damage(std::max(weaponDamage, 0));
  3524.  
  3525. // Add melee damage bonuses (also check for negative)
  3526. uint32 damage = m_caster->MeleeDamageBonusDone(unitTarget, eff_damage, m_attackType, m_spellInfo);
  3527.  
  3528. m_damage += unitTarget->MeleeDamageBonusTaken(m_caster, damage, m_attackType, m_spellInfo);
  3529. }
  3530.  
  3531. void Spell::EffectThreat(SpellEffIndex /*effIndex*/)
  3532. {
  3533. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
  3534. return;
  3535.  
  3536. if (!unitTarget || !unitTarget->isAlive() || !m_caster->isAlive())
  3537. return;
  3538.  
  3539. if (!unitTarget->CanHaveThreatList())
  3540. return;
  3541.  
  3542. unitTarget->AddThreat(m_caster, float(damage));
  3543. }
  3544.  
  3545. void Spell::EffectHealMaxHealth(SpellEffIndex /*effIndex*/)
  3546. {
  3547. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
  3548. return;
  3549.  
  3550. if (!unitTarget || !unitTarget->isAlive())
  3551. return;
  3552.  
  3553. int32 addhealth = 0;
  3554.  
  3555. // damage == 0 - heal for caster max health
  3556. if (damage == 0)
  3557. addhealth = m_caster->GetMaxHealth();
  3558. else
  3559. addhealth = unitTarget->GetMaxHealth() - unitTarget->GetHealth();
  3560.  
  3561. m_healing += addhealth;
  3562. }
  3563.  
  3564. void Spell::EffectInterruptCast(SpellEffIndex effIndex)
  3565. {
  3566. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
  3567. return;
  3568.  
  3569. if (!unitTarget || !unitTarget->isAlive())
  3570. return;
  3571.  
  3572. // TODO: not all spells that used this effect apply cooldown at school spells
  3573. // also exist case: apply cooldown to interrupted cast only and to all spells
  3574. // there is no CURRENT_AUTOREPEAT_SPELL spells that can be interrupted
  3575. for (uint32 i = CURRENT_FIRST_NON_MELEE_SPELL; i < CURRENT_AUTOREPEAT_SPELL; ++i)
  3576. {
  3577. if (Spell* spell = unitTarget->GetCurrentSpell(CurrentSpellTypes(i)))
  3578. {
  3579. SpellInfo const* curSpellInfo = spell->m_spellInfo;
  3580. // check if we can interrupt spell
  3581. if ((spell->getState() == SPELL_STATE_CASTING
  3582. || (spell->getState() == SPELL_STATE_PREPARING && spell->GetCastTime() > 0.0f))
  3583. && curSpellInfo->PreventionType == SPELL_PREVENTION_TYPE_SILENCE
  3584. && ((i == CURRENT_GENERIC_SPELL && curSpellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_INTERRUPT)
  3585. || (i == CURRENT_CHANNELED_SPELL && curSpellInfo->ChannelInterruptFlags & CHANNEL_INTERRUPT_FLAG_INTERRUPT)))
  3586. {
  3587. if (m_originalCaster)
  3588. {
  3589. int32 duration = m_spellInfo->GetDuration();
  3590. unitTarget->ProhibitSpellSchool(curSpellInfo->GetSchoolMask(), unitTarget->ModSpellDuration(m_spellInfo, unitTarget, duration, false, 1 << effIndex));
  3591. }
  3592. ExecuteLogEffectInterruptCast(effIndex, unitTarget, curSpellInfo->Id);
  3593. unitTarget->InterruptSpell(CurrentSpellTypes(i), false);
  3594. }
  3595. }
  3596. }
  3597. }
  3598.  
  3599. void Spell::EffectSummonObjectWild(SpellEffIndex effIndex)
  3600. {
  3601. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT)
  3602. return;
  3603.  
  3604. uint32 gameobject_id = m_spellInfo->Effects[effIndex].MiscValue;
  3605.  
  3606. GameObject* pGameObj = new GameObject;
  3607.  
  3608. WorldObject* target = focusObject;
  3609. if (!target)
  3610. target = m_caster;
  3611.  
  3612. float x, y, z;
  3613. if (m_targets.HasDst())
  3614. destTarget->GetPosition(x, y, z);
  3615. else
  3616. m_caster->GetClosePoint(x, y, z, DEFAULT_WORLD_OBJECT_SIZE);
  3617.  
  3618. Map* map = target->GetMap();
  3619.  
  3620. if (!pGameObj->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_GAMEOBJECT), gameobject_id, map,
  3621. m_caster->GetPhaseMask(), x, y, z, target->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, GO_STATE_READY))
  3622. {
  3623. delete pGameObj;
  3624. return;
  3625. }
  3626.  
  3627. int32 duration = m_spellInfo->GetDuration();
  3628.  
  3629. pGameObj->SetRespawnTime(duration > 0 ? duration/IN_MILLISECONDS : 0);
  3630. pGameObj->SetSpellId(m_spellInfo->Id);
  3631.  
  3632. ExecuteLogEffectSummonObject(effIndex, pGameObj);
  3633.  
  3634. // Wild object not have owner and check clickable by players
  3635. map->AddToMap(pGameObj);
  3636.  
  3637. if (pGameObj->GetGoType() == GAMEOBJECT_TYPE_FLAGDROP)
  3638. if (Player* player = m_caster->ToPlayer())
  3639. if (Battleground* bg = player->GetBattleground())
  3640. bg->SetDroppedFlagGUID(pGameObj->GetGUID(), player->GetTeam() == ALLIANCE ? TEAM_HORDE: TEAM_ALLIANCE);
  3641.  
  3642. if (uint32 linkedEntry = pGameObj->GetGOInfo()->GetLinkedGameObjectEntry())
  3643. {
  3644. GameObject* linkedGO = new GameObject;
  3645. if (linkedGO->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_GAMEOBJECT), linkedEntry, map,
  3646. m_caster->GetPhaseMask(), x, y, z, target->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, GO_STATE_READY))
  3647. {
  3648. linkedGO->SetRespawnTime(duration > 0 ? duration/IN_MILLISECONDS : 0);
  3649. linkedGO->SetSpellId(m_spellInfo->Id);
  3650.  
  3651. ExecuteLogEffectSummonObject(effIndex, linkedGO);
  3652.  
  3653. // Wild object not have owner and check clickable by players
  3654. map->AddToMap(linkedGO);
  3655. }
  3656. else
  3657. {
  3658. delete linkedGO;
  3659. linkedGO = NULL;
  3660. return;
  3661. }
  3662. }
  3663. }
  3664.  
  3665. void Spell::EffectScriptEffect(SpellEffIndex effIndex)
  3666. {
  3667. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
  3668. return;
  3669.  
  3670. // TODO: we must implement hunter pet summon at login there (spell 6962)
  3671.  
  3672. switch (m_spellInfo->SpellFamilyName)
  3673. {
  3674. case SPELLFAMILY_GENERIC:
  3675. {
  3676. switch (m_spellInfo->Id)
  3677. {
  3678. // Glyph of Backstab
  3679. case 63975:
  3680. {
  3681. // search our Rupture aura on target
  3682. if (AuraEffect const* aurEff = unitTarget->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_ROGUE, 0x00100000, 0, 0, m_caster->GetGUID()))
  3683. {
  3684. uint32 countMin = aurEff->GetBase()->GetMaxDuration();
  3685. uint32 countMax = 12000; // this can be wrong, duration should be based on combo-points
  3686. countMax += m_caster->HasAura(56801) ? 4000 : 0;
  3687.  
  3688. if (countMin < countMax)
  3689. {
  3690. aurEff->GetBase()->SetDuration(uint32(aurEff->GetBase()->GetDuration() + 3000));
  3691. aurEff->GetBase()->SetMaxDuration(countMin + 2000);
  3692. }
  3693.  
  3694. }
  3695. return;
  3696. }
  3697. // Glyph of Scourge Strike
  3698. case 69961:
  3699. {
  3700. Unit::AuraEffectList const &mPeriodic = unitTarget->GetAuraEffectsByType(SPELL_AURA_PERIODIC_DAMAGE);
  3701. for (Unit::AuraEffectList::const_iterator i = mPeriodic.begin(); i != mPeriodic.end(); ++i)
  3702. {
  3703. AuraEffect const* aurEff = *i;
  3704. SpellInfo const* spellInfo = aurEff->GetSpellInfo();
  3705. // search our Blood Plague and Frost Fever on target
  3706. if (spellInfo->SpellFamilyName == SPELLFAMILY_DEATHKNIGHT && spellInfo->SpellFamilyFlags[2] & 0x2 &&
  3707. aurEff->GetCasterGUID() == m_caster->GetGUID())
  3708. {
  3709. uint32 countMin = aurEff->GetBase()->GetMaxDuration();
  3710. uint32 countMax = spellInfo->GetMaxDuration();
  3711.  
  3712. // this Glyph
  3713. countMax += 9000;
  3714. // talent Epidemic
  3715. if (AuraEffect const* epidemic = m_caster->GetAuraEffect(SPELL_AURA_ADD_FLAT_MODIFIER, SPELLFAMILY_DEATHKNIGHT, 234, EFFECT_0))
  3716. countMax += epidemic->GetAmount();
  3717.  
  3718. if (countMin < countMax)
  3719. {
  3720. aurEff->GetBase()->SetDuration(aurEff->GetBase()->GetDuration() + 3000);
  3721. aurEff->GetBase()->SetMaxDuration(countMin + 3000);
  3722. }
  3723. }
  3724. }
  3725. return;
  3726. }
  3727. case 45204: // Clone Me!
  3728. m_caster->CastSpell(unitTarget, damage, true);
  3729. break;
  3730. case 55693: // Remove Collapsing Cave Aura
  3731. if (!unitTarget)
  3732. return;
  3733. unitTarget->RemoveAurasDueToSpell(m_spellInfo->Effects[effIndex].CalcValue());
  3734. break;
  3735. // PX-238 Winter Wondervolt TRAP
  3736. case 26275:
  3737. {
  3738. uint32 spells[4] = { 26272, 26157, 26273, 26274 };
  3739.  
  3740. // check presence
  3741. for (uint8 j = 0; j < 4; ++j)
  3742. if (unitTarget->HasAuraEffect(spells[j], 0))
  3743. return;
  3744.  
  3745. // select spell
  3746. uint32 iTmpSpellId = spells[urand(0, 3)];
  3747.  
  3748. // cast
  3749. unitTarget->CastSpell(unitTarget, iTmpSpellId, true);
  3750. return;
  3751. }
  3752. // Bending Shinbone
  3753. case 8856:
  3754. {
  3755. if (!itemTarget && m_caster->GetTypeId() != TYPEID_PLAYER)
  3756. return;
  3757.  
  3758. uint32 spell_id = roll_chance_i(20) ? 8854 : 8855;
  3759.  
  3760. m_caster->CastSpell(m_caster, spell_id, true, NULL);
  3761. return;
  3762. }
  3763. // Brittle Armor - need remove one 24575 Brittle Armor aura
  3764. case 24590:
  3765. unitTarget->RemoveAuraFromStack(24575);
  3766. return;
  3767. // Mercurial Shield - need remove one 26464 Mercurial Shield aura
  3768. case 26465:
  3769. unitTarget->RemoveAuraFromStack(26464);
  3770. return;
  3771. // Shadow Flame (All script effects, not just end ones to prevent player from dodging the last triggered spell)
  3772. case 22539:
  3773. case 22972:
  3774. case 22975:
  3775. case 22976:
  3776. case 22977:
  3777. case 22978:
  3778. case 22979:
  3779. case 22980:
  3780. case 22981:
  3781. case 22982:
  3782. case 22983:
  3783. case 22984:
  3784. case 22985:
  3785. {
  3786. if (!unitTarget || !unitTarget->isAlive())
  3787. return;
  3788.  
  3789. // Onyxia Scale Cloak
  3790. if (unitTarget->HasAura(22683))
  3791. return;
  3792.  
  3793. // Shadow Flame
  3794. m_caster->CastSpell(unitTarget, 22682, true);
  3795. return;
  3796. }
  3797. // Piccolo of the Flaming Fire
  3798. case 17512:
  3799. {
  3800. if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
  3801. return;
  3802. unitTarget->HandleEmoteCommand(EMOTE_STATE_DANCE);
  3803. return;
  3804. }
  3805. // Decimate
  3806. case 28374:
  3807. case 54426:
  3808. if (unitTarget)
  3809. {
  3810. int32 damage = int32(unitTarget->GetHealth()) - int32(unitTarget->CountPctFromMaxHealth(5));
  3811. if (damage > 0)
  3812. m_caster->CastCustomSpell(28375, SPELLVALUE_BASE_POINT0, damage, unitTarget);
  3813. }
  3814. return;
  3815. // Mirren's Drinking Hat
  3816. case 29830:
  3817. {
  3818. uint32 item = 0;
  3819. switch (urand(1, 6))
  3820. {
  3821. case 1:
  3822. case 2:
  3823. case 3:
  3824. item = 23584; break; // Loch Modan Lager
  3825. case 4:
  3826. case 5:
  3827. item = 23585; break; // Stouthammer Lite
  3828. case 6:
  3829. item = 23586; break; // Aerie Peak Pale Ale
  3830. }
  3831. if (item)
  3832. DoCreateItem(effIndex, item);
  3833. break;
  3834. }
  3835. case 20589: // Escape artist
  3836. case 30918: // Improved Sprint
  3837. {
  3838. // Removes snares and roots.
  3839. unitTarget->RemoveMovementImpairingAuras();
  3840. break;
  3841. }
  3842. // Plant Warmaul Ogre Banner
  3843. case 32307:
  3844. if (Player* caster = m_caster->ToPlayer())
  3845. {
  3846. caster->RewardPlayerAndGroupAtEvent(18388, unitTarget);
  3847. if (Creature* target = unitTarget->ToCreature())
  3848. {
  3849. target->setDeathState(CORPSE);
  3850. target->RemoveCorpse();
  3851. }
  3852. }
  3853. break;
  3854. // Mug Transformation
  3855. case 41931:
  3856. {
  3857. if (m_caster->GetTypeId() != TYPEID_PLAYER)
  3858. return;
  3859.  
  3860. uint8 bag = 19;
  3861. uint8 slot = 0;
  3862. Item* item = NULL;
  3863.  
  3864. while (bag) // 256 = 0 due to var type
  3865. {
  3866. item = m_caster->ToPlayer()->GetItemByPos(bag, slot);
  3867. if (item && item->GetEntry() == 38587)
  3868. break;
  3869.  
  3870. ++slot;
  3871. if (slot == 39)
  3872. {
  3873. slot = 0;
  3874. ++bag;
  3875. }
  3876. }
  3877. if (bag)
  3878. {
  3879. if (m_caster->ToPlayer()->GetItemByPos(bag, slot)->GetCount() == 1) m_caster->ToPlayer()->RemoveItem(bag, slot, true);
  3880. else m_caster->ToPlayer()->GetItemByPos(bag, slot)->SetCount(m_caster->ToPlayer()->GetItemByPos(bag, slot)->GetCount()-1);
  3881. // Spell 42518 (Braufest - Gratisprobe des Braufest herstellen)
  3882. m_caster->CastSpell(m_caster, 42518, true);
  3883. return;
  3884. }
  3885. break;
  3886. }
  3887. // Brutallus - Burn
  3888. case 45141:
  3889. case 45151:
  3890. {
  3891. //Workaround for Range ... should be global for every ScriptEffect
  3892. float radius = m_spellInfo->Effects[effIndex].CalcRadius();
  3893. if (unitTarget && unitTarget->GetTypeId() == TYPEID_PLAYER && unitTarget->GetDistance(m_caster) >= radius && !unitTarget->HasAura(46394) && unitTarget != m_caster)
  3894. unitTarget->CastSpell(unitTarget, 46394, true);
  3895.  
  3896. break;
  3897. }
  3898. // Goblin Weather Machine
  3899. case 46203:
  3900. {
  3901. if (!unitTarget)
  3902. return;
  3903.  
  3904. uint32 spellId = 0;
  3905. switch (rand() % 4)
  3906. {
  3907. case 0: spellId = 46740; break;
  3908. case 1: spellId = 46739; break;
  3909. case 2: spellId = 46738; break;
  3910. case 3: spellId = 46736; break;
  3911. }
  3912. unitTarget->CastSpell(unitTarget, spellId, true);
  3913. break;
  3914. }
  3915. // 5, 000 Gold
  3916. case 46642:
  3917. {
  3918. if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
  3919. return;
  3920.  
  3921. unitTarget->ToPlayer()->ModifyMoney(5000 * GOLD);
  3922.  
  3923. break;
  3924. }
  3925. // Roll Dice - Decahedral Dwarven Dice
  3926. case 47770:
  3927. {
  3928. char buf[128];
  3929. const char *gender = "his";
  3930. if (m_caster->getGender() > 0)
  3931. gender = "her";
  3932. sprintf(buf, "%s rubs %s [Decahedral Dwarven Dice] between %s hands and rolls. One %u and one %u.", m_caster->GetName().c_str(), gender, gender, urand(1, 10), urand(1, 10));
  3933. m_caster->MonsterTextEmote(buf, 0);
  3934. break;
  3935. }
  3936. // Roll 'dem Bones - Worn Troll Dice
  3937. case 47776:
  3938. {
  3939. char buf[128];
  3940. const char *gender = "his";
  3941. if (m_caster->getGender() > 0)
  3942. gender = "her";
  3943. sprintf(buf, "%s causually tosses %s [Worn Troll Dice]. One %u and one %u.", m_caster->GetName().c_str(), gender, urand(1, 6), urand(1, 6));
  3944. m_caster->MonsterTextEmote(buf, 0);
  3945. break;
  3946. }
  3947. // Vigilance
  3948. case 50725:
  3949. {
  3950. if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
  3951. return;
  3952.  
  3953. // Remove Taunt cooldown
  3954. unitTarget->ToPlayer()->RemoveSpellCooldown(355, true);
  3955.  
  3956. return;
  3957. }
  3958. // Death Knight Initiate Visual
  3959. case 51519:
  3960. {
  3961. if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT)
  3962. return;
  3963.  
  3964. uint32 iTmpSpellId = 0;
  3965. switch (unitTarget->GetDisplayId())
  3966. {
  3967. case 25369: iTmpSpellId = 51552; break; // bloodelf female
  3968. case 25373: iTmpSpellId = 51551; break; // bloodelf male
  3969. case 25363: iTmpSpellId = 51542; break; // draenei female
  3970. case 25357: iTmpSpellId = 51541; break; // draenei male
  3971. case 25361: iTmpSpellId = 51537; break; // dwarf female
  3972. case 25356: iTmpSpellId = 51538; break; // dwarf male
  3973. case 25372: iTmpSpellId = 51550; break; // forsaken female
  3974. case 25367: iTmpSpellId = 51549; break; // forsaken male
  3975. case 25362: iTmpSpellId = 51540; break; // gnome female
  3976. case 25359: iTmpSpellId = 51539; break; // gnome male
  3977. case 25355: iTmpSpellId = 51534; break; // human female
  3978. case 25354: iTmpSpellId = 51520; break; // human male
  3979. case 25360: iTmpSpellId = 51536; break; // nightelf female
  3980. case 25358: iTmpSpellId = 51535; break; // nightelf male
  3981. case 25368: iTmpSpellId = 51544; break; // orc female
  3982. case 25364: iTmpSpellId = 51543; break; // orc male
  3983. case 25371: iTmpSpellId = 51548; break; // tauren female
  3984. case 25366: iTmpSpellId = 51547; break; // tauren male
  3985. case 25370: iTmpSpellId = 51545; break; // troll female
  3986. case 25365: iTmpSpellId = 51546; break; // troll male
  3987. default: return;
  3988. }
  3989.  
  3990. unitTarget->CastSpell(unitTarget, iTmpSpellId, true);
  3991. Creature* npc = unitTarget->ToCreature();
  3992. npc->LoadEquipment(npc->GetEquipmentId());
  3993. return;
  3994. }
  3995. // Emblazon Runeblade
  3996. case 51770:
  3997. {
  3998. if (!m_originalCaster)
  3999. return;
  4000.  
  4001. m_originalCaster->CastSpell(m_originalCaster, damage, false);
  4002. break;
  4003. }
  4004. // Deathbolt from Thalgran Blightbringer
  4005. // reflected by Freya's Ward
  4006. // Retribution by Sevenfold Retribution
  4007. case 51854:
  4008. {
  4009. if (!unitTarget)
  4010. return;
  4011. if (unitTarget->HasAura(51845))
  4012. unitTarget->CastSpell(m_caster, 51856, true);
  4013. else
  4014. m_caster->CastSpell(unitTarget, 51855, true);
  4015. break;
  4016. }
  4017. // Summon Ghouls On Scarlet Crusade
  4018. case 51904:
  4019. {
  4020. if (!m_targets.HasDst())
  4021. return;
  4022.  
  4023. float x, y, z;
  4024. float radius = m_spellInfo->Effects[effIndex].CalcRadius();
  4025. for (uint8 i = 0; i < 15; ++i)
  4026. {
  4027. m_caster->GetRandomPoint(*destTarget, radius, x, y, z);
  4028. m_caster->CastSpell(x, y, z, 54522, true);
  4029. }
  4030. break;
  4031. }
  4032. case 52173: // Coyote Spirit Despawn
  4033. case 60243: // Blood Parrot Despawn
  4034. if (unitTarget->GetTypeId() == TYPEID_UNIT && unitTarget->ToCreature()->isSummon())
  4035. unitTarget->ToTempSummon()->UnSummon();
  4036. return;
  4037. case 52479: // Gift of the Harvester
  4038. if (unitTarget && m_originalCaster)
  4039. m_originalCaster->CastSpell(unitTarget, urand(0, 1) ? damage : 52505, true);
  4040. return;
  4041. case 53110: // Devour Humanoid
  4042. if (unitTarget)
  4043. unitTarget->CastSpell(m_caster, damage, true);
  4044. return;
  4045. case 57347: // Retrieving (Wintergrasp RP-GG pickup spell)
  4046. {
  4047. if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT || m_caster->GetTypeId() != TYPEID_PLAYER)
  4048. return;
  4049.  
  4050. unitTarget->ToCreature()->DespawnOrUnsummon();
  4051.  
  4052. return;
  4053. }
  4054. case 57349: // Drop RP-GG (Wintergrasp RP-GG at death drop spell)
  4055. {
  4056. if (m_caster->GetTypeId() != TYPEID_PLAYER)
  4057. return;
  4058.  
  4059. // Delete item from inventory at death
  4060. m_caster->ToPlayer()->DestroyItemCount(damage, 5, true);
  4061.  
  4062. return;
  4063. }
  4064. case 58418: // Portal to Orgrimmar
  4065. case 58420: // Portal to Stormwind
  4066. {
  4067. if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER || effIndex != 0)
  4068. return;
  4069.  
  4070. uint32 spellID = m_spellInfo->Effects[EFFECT_0].CalcValue();
  4071. uint32 questID = m_spellInfo->Effects[EFFECT_1].CalcValue();
  4072.  
  4073. if (unitTarget->ToPlayer()->GetQuestStatus(questID) == QUEST_STATUS_COMPLETE)
  4074. unitTarget->CastSpell(unitTarget, spellID, true);
  4075.  
  4076. return;
  4077. }
  4078. case 58941: // Rock Shards
  4079. if (unitTarget && m_originalCaster)
  4080. {
  4081. for (uint32 i = 0; i < 3; ++i)
  4082. {
  4083. m_originalCaster->CastSpell(unitTarget, 58689, true);
  4084. m_originalCaster->CastSpell(unitTarget, 58692, true);
  4085. }
  4086. if (((InstanceMap*)m_originalCaster->GetMap())->GetDifficulty() == REGULAR_DIFFICULTY)
  4087. {
  4088. m_originalCaster->CastSpell(unitTarget, 58695, true);
  4089. m_originalCaster->CastSpell(unitTarget, 58696, true);
  4090. }
  4091. else
  4092. {
  4093. m_originalCaster->CastSpell(unitTarget, 60883, true);
  4094. m_originalCaster->CastSpell(unitTarget, 60884, true);
  4095. }
  4096. }
  4097. return;
  4098. case 58983: // Big Blizzard Bear
  4099. {
  4100. if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
  4101. return;
  4102.  
  4103. // Prevent stacking of mounts and client crashes upon dismounting
  4104. unitTarget->RemoveAurasByType(SPELL_AURA_MOUNTED);
  4105.  
  4106. // Triggered spell id dependent on riding skill
  4107. if (uint16 skillval = unitTarget->ToPlayer()->GetSkillValue(SKILL_RIDING))
  4108. {
  4109. if (skillval >= 150)
  4110. unitTarget->CastSpell(unitTarget, 58999, true);
  4111. else
  4112. unitTarget->CastSpell(unitTarget, 58997, true);
  4113. }
  4114. return;
  4115. }
  4116. case 63845: // Create Lance
  4117. {
  4118. if (m_caster->GetTypeId() != TYPEID_PLAYER)
  4119. return;
  4120.  
  4121. if (m_caster->ToPlayer()->GetTeam() == ALLIANCE)
  4122. m_caster->CastSpell(m_caster, 63914, true);
  4123. else
  4124. m_caster->CastSpell(m_caster, 63919, true);
  4125. return;
  4126. }
  4127. case 59317: // Teleporting
  4128. {
  4129.  
  4130. if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
  4131. return;
  4132.  
  4133. // return from top
  4134. if (unitTarget->ToPlayer()->GetAreaId() == 4637)
  4135. unitTarget->CastSpell(unitTarget, 59316, true);
  4136. // teleport atop
  4137. else
  4138. unitTarget->CastSpell(unitTarget, 59314, true);
  4139.  
  4140. return;
  4141. }
  4142. case 62482: // Grab Crate
  4143. {
  4144. if (unitTarget)
  4145. {
  4146. if (Unit* seat = m_caster->GetVehicleBase())
  4147. {
  4148. if (Unit* parent = seat->GetVehicleBase())
  4149. {
  4150. // TODO: a hack, range = 11, should after some time cast, otherwise too far
  4151. m_caster->CastSpell(parent, 62496, true);
  4152. unitTarget->CastSpell(parent, m_spellInfo->Effects[EFFECT_0].CalcValue());
  4153. }
  4154. }
  4155. }
  4156. return;
  4157. }
  4158. case 60123: // Lightwell
  4159. {
  4160. if (m_caster->GetTypeId() != TYPEID_UNIT || !m_caster->ToCreature()->isSummon())
  4161. return;
  4162.  
  4163. uint32 spell_heal;
  4164.  
  4165. switch (m_caster->GetEntry())
  4166. {
  4167. case 31897: spell_heal = 7001; break;
  4168. case 31896: spell_heal = 27873; break;
  4169. case 31895: spell_heal = 27874; break;
  4170. case 31894: spell_heal = 28276; break;
  4171. case 31893: spell_heal = 48084; break;
  4172. case 31883: spell_heal = 48085; break;
  4173. default:
  4174. sLog->outError(LOG_FILTER_SPELLS_AURAS, "Unknown Lightwell spell caster %u", m_caster->GetEntry());
  4175. return;
  4176. }
  4177.  
  4178. // proc a spellcast
  4179. if (Aura* chargesAura = m_caster->GetAura(59907))
  4180. {
  4181. m_caster->CastSpell(unitTarget, spell_heal, true, NULL, NULL, m_caster->ToTempSummon()->GetSummonerGUID());
  4182. if (chargesAura->ModCharges(-1))
  4183. m_caster->ToTempSummon()->UnSummon();
  4184. }
  4185.  
  4186. return;
  4187. }
  4188. // Stoneclaw Totem
  4189. case 55328: // Rank 1
  4190. case 55329: // Rank 2
  4191. case 55330: // Rank 3
  4192. case 55332: // Rank 4
  4193. case 55333: // Rank 5
  4194. case 55335: // Rank 6
  4195. case 55278: // Rank 7
  4196. case 58589: // Rank 8
  4197. case 58590: // Rank 9
  4198. case 58591: // Rank 10
  4199. {
  4200. int32 basepoints0 = damage;
  4201. // Cast Absorb on totems
  4202. for (uint8 slot = SUMMON_SLOT_TOTEM; slot < MAX_TOTEM_SLOT; ++slot)
  4203. {
  4204. if (!unitTarget->m_SummonSlot[slot])
  4205. continue;
  4206.  
  4207. Creature* totem = unitTarget->GetMap()->GetCreature(unitTarget->m_SummonSlot[slot]);
  4208. if (totem && totem->isTotem())
  4209. {
  4210. m_caster->CastCustomSpell(totem, 55277, &basepoints0, NULL, NULL, true);
  4211. }
  4212. }
  4213. // Glyph of Stoneclaw Totem
  4214. if (AuraEffect* aur=unitTarget->GetAuraEffect(63298, 0))
  4215. {
  4216. basepoints0 *= aur->GetAmount();
  4217. m_caster->CastCustomSpell(unitTarget, 55277, &basepoints0, NULL, NULL, true);
  4218. }
  4219. break;
  4220. }
  4221. case 66545: //Summon Memory
  4222. {
  4223. uint8 uiRandom = urand(0, 25);
  4224. uint32 uiSpells[26] = {66704, 66705, 66706, 66707, 66709, 66710, 66711, 66712, 66713, 66714, 66715, 66708, 66708, 66691, 66692, 66694, 66695, 66696, 66697, 66698, 66699, 66700, 66701, 66702, 66703, 66543};
  4225.  
  4226. m_caster->CastSpell(m_caster, uiSpells[uiRandom], true);
  4227. break;
  4228. }
  4229. case 45668: // Ultra-Advanced Proto-Typical Shortening Blaster
  4230. {
  4231. if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT)
  4232. return;
  4233.  
  4234. if (roll_chance_i(50)) // chance unknown, using 50
  4235. return;
  4236.  
  4237. static uint32 const spellPlayer[5] =
  4238. {
  4239. 45674, // Bigger!
  4240. 45675, // Shrunk
  4241. 45678, // Yellow
  4242. 45682, // Ghost
  4243. 45684 // Polymorph
  4244. };
  4245.  
  4246. static uint32 const spellTarget[5] =
  4247. {
  4248. 45673, // Bigger!
  4249. 45672, // Shrunk
  4250. 45677, // Yellow
  4251. 45681, // Ghost
  4252. 45683 // Polymorph
  4253. };
  4254.  
  4255. m_caster->CastSpell(m_caster, spellPlayer[urand(0, 4)], true);
  4256. unitTarget->CastSpell(unitTarget, spellTarget[urand(0, 4)], true);
  4257. break;
  4258. }
  4259. }
  4260. break;
  4261. }
  4262. case SPELLFAMILY_PALADIN:
  4263. {
  4264. // Judgement (seal trigger)
  4265. if (m_spellInfo->Category == SPELLCATEGORY_JUDGEMENT)
  4266. {
  4267. if (!unitTarget || !unitTarget->isAlive())
  4268. return;
  4269. uint32 spellId1 = 0;
  4270. uint32 spellId2 = 0;
  4271.  
  4272. // Judgement self add switch
  4273. switch (m_spellInfo->Id)
  4274. {
  4275. case 53407: spellId1 = 20184; break; // Judgement of Justice
  4276. case 20271: // Judgement of Light
  4277. case 57774: spellId1 = 20185; break; // Judgement of Light
  4278. case 53408: spellId1 = 20186; break; // Judgement of Wisdom
  4279. default:
  4280. sLog->outError(LOG_FILTER_SPELLS_AURAS, "Unsupported Judgement (seal trigger) spell (Id: %u) in Spell::EffectScriptEffect", m_spellInfo->Id);
  4281. return;
  4282. }
  4283. // all seals have aura dummy in 2 effect
  4284. Unit::AuraApplicationMap & sealAuras = m_caster->GetAppliedAuras();
  4285. for (Unit::AuraApplicationMap::iterator iter = sealAuras.begin(); iter != sealAuras.end();)
  4286. {
  4287. Aura* aura = iter->second->GetBase();
  4288. if (aura->GetSpellInfo()->GetSpellSpecific() == SPELL_SPECIFIC_SEAL)
  4289. {
  4290. if (AuraEffect* aureff = aura->GetEffect(2))
  4291. if (aureff->GetAuraType() == SPELL_AURA_DUMMY)
  4292. {
  4293. if (sSpellMgr->GetSpellInfo(aureff->GetAmount()))
  4294. spellId2 = aureff->GetAmount();
  4295. break;
  4296. }
  4297. if (!spellId2)
  4298. {
  4299. switch (iter->first)
  4300. {
  4301. // Seal of light, Seal of wisdom, Seal of justice
  4302. case 20165:
  4303. case 20166:
  4304. case 20164:
  4305. spellId2 = 54158;
  4306. }
  4307. }
  4308. break;
  4309. }
  4310. else
  4311. ++iter;
  4312. }
  4313. if (spellId1)
  4314. m_caster->CastSpell(unitTarget, spellId1, true);
  4315. if (spellId2)
  4316. m_caster->CastSpell(unitTarget, spellId2, true);
  4317. return;
  4318. }
  4319. }
  4320. case SPELLFAMILY_POTION:
  4321. {
  4322. switch (m_spellInfo->Id)
  4323. {
  4324. // Netherbloom
  4325. case 28702:
  4326. {
  4327. if (!unitTarget)
  4328. return;
  4329. // 25% chance of casting a random buff
  4330. if (roll_chance_i(75))
  4331. return;
  4332.  
  4333. // triggered spells are 28703 to 28707
  4334. // Note: some sources say, that there was the possibility of
  4335. // receiving a debuff. However, this seems to be removed by a patch.
  4336. const uint32 spellid = 28703;
  4337.  
  4338. // don't overwrite an existing aura
  4339. for (uint8 i = 0; i < 5; ++i)
  4340. if (unitTarget->HasAura(spellid + i))
  4341. return;
  4342. unitTarget->CastSpell(unitTarget, spellid+urand(0, 4), true);
  4343. break;
  4344. }
  4345.  
  4346. // Nightmare Vine
  4347. case 28720:
  4348. {
  4349. if (!unitTarget)
  4350. return;
  4351. // 25% chance of casting Nightmare Pollen
  4352. if (roll_chance_i(75))
  4353. return;
  4354. unitTarget->CastSpell(unitTarget, 28721, true);
  4355. break;
  4356. }
  4357. }
  4358. break;
  4359. }
  4360. case SPELLFAMILY_DEATHKNIGHT:
  4361. {
  4362. // Pestilence
  4363. if (m_spellInfo->SpellFamilyFlags[1]&0x10000)
  4364. {
  4365. // Get diseases on target of spell
  4366. if (m_targets.GetUnitTarget() && // Glyph of Disease - cast on unit target too to refresh aura
  4367. (m_targets.GetUnitTarget() != unitTarget || m_caster->GetAura(63334)))
  4368. {
  4369. // And spread them on target
  4370. // Blood Plague
  4371. if (m_targets.GetUnitTarget()->GetAura(55078))
  4372. m_caster->CastSpell(unitTarget, 55078, true);
  4373. // Frost Fever
  4374. if (m_targets.GetUnitTarget()->GetAura(55095))
  4375. m_caster->CastSpell(unitTarget, 55095, true);
  4376. }
  4377. }
  4378. break;
  4379. }
  4380. case SPELLFAMILY_WARRIOR:
  4381. {
  4382. // Shattering Throw
  4383. if (m_spellInfo->SpellFamilyFlags[1] & 0x00400000)
  4384. {
  4385. if (!unitTarget)
  4386. return;
  4387. // remove shields, will still display immune to damage part
  4388. unitTarget->RemoveAurasWithMechanic(1<<MECHANIC_IMMUNE_SHIELD, AURA_REMOVE_BY_ENEMY_SPELL);
  4389. return;
  4390. }
  4391. break;
  4392. }
  4393. }
  4394.  
  4395. // normal DB scripted effect
  4396. sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "Spell ScriptStart spellid %u in EffectScriptEffect(%u)", m_spellInfo->Id, effIndex);
  4397. m_caster->GetMap()->ScriptsStart(sSpellScripts, uint32(m_spellInfo->Id | (effIndex << 24)), m_caster, unitTarget);
  4398. }
  4399.  
  4400. void Spell::EffectSanctuary(SpellEffIndex /*effIndex*/)
  4401. {
  4402. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
  4403. return;
  4404.  
  4405. if (!unitTarget)
  4406. return;
  4407.  
  4408. unitTarget->getHostileRefManager().UpdateVisibility();
  4409.  
  4410. Unit::AttackerSet const& attackers = unitTarget->getAttackers();
  4411. for (Unit::AttackerSet::const_iterator itr = attackers.begin(); itr != attackers.end();)
  4412. {
  4413. if (!(*itr)->canSeeOrDetect(unitTarget))
  4414. (*(itr++))->AttackStop();
  4415. else
  4416. ++itr;
  4417. }
  4418.  
  4419. unitTarget->m_lastSanctuaryTime = getMSTime();
  4420.  
  4421. // Vanish allows to remove all threat and cast regular stealth so other spells can be used
  4422. if (m_caster->GetTypeId() == TYPEID_PLAYER
  4423. && m_spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE
  4424. && (m_spellInfo->SpellFamilyFlags[0] & SPELLFAMILYFLAG_ROGUE_VANISH))
  4425. {
  4426. m_caster->ToPlayer()->RemoveAurasByType(SPELL_AURA_MOD_ROOT);
  4427. // Overkill
  4428. if (m_caster->ToPlayer()->HasSpell(58426))
  4429. m_caster->CastSpell(m_caster, 58427, true);
  4430. }
  4431. }
  4432.  
  4433. void Spell::EffectAddComboPoints(SpellEffIndex /*effIndex*/)
  4434. {
  4435. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
  4436. return;
  4437.  
  4438. if (!unitTarget)
  4439. return;
  4440.  
  4441. if (!m_caster->m_movedPlayer)
  4442. return;
  4443.  
  4444. if (damage <= 0)
  4445. return;
  4446.  
  4447. m_caster->m_movedPlayer->AddComboPoints(unitTarget, damage, this);
  4448. }
  4449.  
  4450. void Spell::EffectDuel(SpellEffIndex effIndex)
  4451. {
  4452. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
  4453. return;
  4454.  
  4455. if (!unitTarget || m_caster->GetTypeId() != TYPEID_PLAYER || unitTarget->GetTypeId() != TYPEID_PLAYER)
  4456. return;
  4457.  
  4458. Player* caster = m_caster->ToPlayer();
  4459. Player* target = unitTarget->ToPlayer();
  4460.  
  4461. // caster or target already have requested duel
  4462. if (caster->duel || target->duel || !target->GetSocial() || target->GetSocial()->HasIgnore(caster->GetGUIDLow()))
  4463. return;
  4464.  
  4465. // Players can only fight a duel in zones with this flag
  4466. AreaTableEntry const* casterAreaEntry = GetAreaEntryByAreaID(caster->GetAreaId());
  4467. if (casterAreaEntry && !(casterAreaEntry->flags & AREA_FLAG_ALLOW_DUELS))
  4468. {
  4469. SendCastResult(SPELL_FAILED_NO_DUELING); // Dueling isn't allowed here
  4470. return;
  4471. }
  4472.  
  4473. AreaTableEntry const* targetAreaEntry = GetAreaEntryByAreaID(target->GetAreaId());
  4474. if (targetAreaEntry && !(targetAreaEntry->flags & AREA_FLAG_ALLOW_DUELS))
  4475. {
  4476. SendCastResult(SPELL_FAILED_NO_DUELING); // Dueling isn't allowed here
  4477. return;
  4478. }
  4479.  
  4480. //CREATE DUEL FLAG OBJECT
  4481. GameObject* pGameObj = new GameObject;
  4482.  
  4483. uint32 gameobject_id = m_spellInfo->Effects[effIndex].MiscValue;
  4484.  
  4485. Map* map = m_caster->GetMap();
  4486. if (!pGameObj->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_GAMEOBJECT), gameobject_id,
  4487. map, m_caster->GetPhaseMask(),
  4488. m_caster->GetPositionX()+(unitTarget->GetPositionX()-m_caster->GetPositionX())/2,
  4489. m_caster->GetPositionY()+(unitTarget->GetPositionY()-m_caster->GetPositionY())/2,
  4490. m_caster->GetPositionZ(),
  4491. m_caster->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 0, GO_STATE_READY))
  4492. {
  4493. delete pGameObj;
  4494. return;
  4495. }
  4496.  
  4497. pGameObj->SetUInt32Value(GAMEOBJECT_FACTION, m_caster->getFaction());
  4498. pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel()+1);
  4499. int32 duration = m_spellInfo->GetDuration();
  4500. pGameObj->SetRespawnTime(duration > 0 ? duration/IN_MILLISECONDS : 0);
  4501. pGameObj->SetSpellId(m_spellInfo->Id);
  4502.  
  4503. ExecuteLogEffectSummonObject(effIndex, pGameObj);
  4504.  
  4505. m_caster->AddGameObject(pGameObj);
  4506. map->AddToMap(pGameObj);
  4507. //END
  4508.  
  4509. // Send request
  4510. WorldPacket data(SMSG_DUEL_REQUESTED, 8 + 8);
  4511. data << uint64(pGameObj->GetGUID());
  4512. data << uint64(caster->GetGUID());
  4513. caster->GetSession()->SendPacket(&data);
  4514. target->GetSession()->SendPacket(&data);
  4515.  
  4516. // create duel-info
  4517. DuelInfo* duel = new DuelInfo;
  4518. duel->initiator = caster;
  4519. duel->opponent = target;
  4520. duel->startTime = 0;
  4521. duel->startTimer = 0;
  4522. duel->isMounted = (GetSpellInfo()->Id == 62875); // Mounted Duel
  4523. caster->duel = duel;
  4524.  
  4525. DuelInfo* duel2 = new DuelInfo;
  4526. duel2->initiator = caster;
  4527. duel2->opponent = caster;
  4528. duel2->startTime = 0;
  4529. duel2->startTimer = 0;
  4530. duel2->isMounted = (GetSpellInfo()->Id == 62875); // Mounted Duel
  4531. target->duel = duel2;
  4532.  
  4533. caster->SetUInt64Value(PLAYER_DUEL_ARBITER, pGameObj->GetGUID());
  4534. target->SetUInt64Value(PLAYER_DUEL_ARBITER, pGameObj->GetGUID());
  4535.  
  4536. sScriptMgr->OnPlayerDuelRequest(target, caster);
  4537. }
  4538.  
  4539. void Spell::EffectStuck(SpellEffIndex /*effIndex*/)
  4540. {
  4541. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT)
  4542. return;
  4543.  
  4544. if (!m_caster || m_caster->GetTypeId() != TYPEID_PLAYER)
  4545. return;
  4546.  
  4547. if (!sWorld->getBoolConfig(CONFIG_CAST_UNSTUCK))
  4548. return;
  4549.  
  4550. Player* target = (Player*)m_caster;
  4551.  
  4552. sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "Spell Effect: Stuck");
  4553. sLog->outInfo(LOG_FILTER_SPELLS_AURAS, "Player %s (guid %u) used auto-unstuck future at map %u (%f, %f, %f)", target->GetName().c_str(), target->GetGUIDLow(), m_caster->GetMapId(), m_caster->GetPositionX(), target->GetPositionY(), target->GetPositionZ());
  4554.  
  4555. if (target->isInFlight())
  4556. return;
  4557.  
  4558. target->TeleportTo(target->GetStartPosition(), TELE_TO_SPELL);
  4559. // homebind location is loaded always
  4560. // target->TeleportTo(target->m_homebindMapId, target->m_homebindX, target->m_homebindY, target->m_homebindZ, target->GetOrientation(), (m_caster == m_caster ? TELE_TO_SPELL : 0));
  4561.  
  4562. // Stuck spell trigger Hearthstone cooldown
  4563. SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(8690);
  4564. if (!spellInfo)
  4565. return;
  4566. Spell spell(target, spellInfo, TRIGGERED_FULL_MASK);
  4567. spell.SendSpellCooldown();
  4568. }
  4569.  
  4570. void Spell::EffectSummonPlayer(SpellEffIndex /*effIndex*/)
  4571. {
  4572. // workaround - this effect should not use target map
  4573. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
  4574. return;
  4575.  
  4576. if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
  4577. return;
  4578.  
  4579. // Evil Twin (ignore player summon, but hide this for summoner)
  4580. if (unitTarget->HasAura(23445))
  4581. return;
  4582.  
  4583. float x, y, z;
  4584. m_caster->GetPosition(x, y, z);
  4585.  
  4586. unitTarget->ToPlayer()->SetSummonPoint(m_caster->GetMapId(), x, y, z);
  4587.  
  4588. WorldPacket data(SMSG_SUMMON_REQUEST, 8+4+4);
  4589. data << uint64(m_caster->GetGUID()); // summoner guid
  4590. data << uint32(m_caster->GetZoneId()); // summoner zone
  4591. data << uint32(MAX_PLAYER_SUMMON_DELAY*IN_MILLISECONDS); // auto decline after msecs
  4592. unitTarget->ToPlayer()->GetSession()->SendPacket(&data);
  4593. }
  4594.  
  4595. void Spell::EffectActivateObject(SpellEffIndex /*effIndex*/)
  4596. {
  4597. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
  4598. return;
  4599.  
  4600. if (!gameObjTarget)
  4601. return;
  4602.  
  4603. ScriptInfo activateCommand;
  4604. activateCommand.command = SCRIPT_COMMAND_ACTIVATE_OBJECT;
  4605.  
  4606. // int32 unk = m_spellInfo->Effects[effIndex].MiscValue; // This is set for EffectActivateObject spells; needs research
  4607.  
  4608. gameObjTarget->GetMap()->ScriptCommandStart(activateCommand, 0, m_caster, gameObjTarget);
  4609. }
  4610.  
  4611. void Spell::EffectApplyGlyph(SpellEffIndex effIndex)
  4612. {
  4613. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT)
  4614. return;
  4615.  
  4616. if (m_caster->GetTypeId() != TYPEID_PLAYER || m_glyphIndex >= MAX_GLYPH_SLOT_INDEX)
  4617. return;
  4618.  
  4619. Player* player = (Player*)m_caster;
  4620.  
  4621. // glyph sockets level requirement
  4622. uint8 minLevel = 0;
  4623. switch (m_glyphIndex)
  4624. {
  4625. case 0:
  4626. case 1: minLevel = 15; break;
  4627. case 2: minLevel = 50; break;
  4628. case 3: minLevel = 30; break;
  4629. case 4: minLevel = 70; break;
  4630. case 5: minLevel = 80; break;
  4631. }
  4632. if (minLevel && m_caster->getLevel() < minLevel)
  4633. {
  4634. SendCastResult(SPELL_FAILED_GLYPH_SOCKET_LOCKED);
  4635. return;
  4636. }
  4637.  
  4638. // apply new one
  4639. if (uint32 glyph = m_spellInfo->Effects[effIndex].MiscValue)
  4640. {
  4641. if (GlyphPropertiesEntry const* gp = sGlyphPropertiesStore.LookupEntry(glyph))
  4642. {
  4643. if (GlyphSlotEntry const* gs = sGlyphSlotStore.LookupEntry(player->GetGlyphSlot(m_glyphIndex)))
  4644. {
  4645. if (gp->TypeFlags != gs->TypeFlags)
  4646. {
  4647. SendCastResult(SPELL_FAILED_INVALID_GLYPH);
  4648. return; // glyph slot mismatch
  4649. }
  4650. }
  4651.  
  4652. // remove old glyph
  4653. if (uint32 oldglyph = player->GetGlyph(m_glyphIndex))
  4654. {
  4655. if (GlyphPropertiesEntry const* old_gp = sGlyphPropertiesStore.LookupEntry(oldglyph))
  4656. {
  4657. player->RemoveAurasDueToSpell(old_gp->SpellId);
  4658. player->SetGlyph(m_glyphIndex, 0);
  4659. }
  4660. }
  4661.  
  4662. player->CastSpell(m_caster, gp->SpellId, true);
  4663. player->SetGlyph(m_glyphIndex, glyph);
  4664. player->SendTalentsInfoData(false);
  4665. }
  4666. }
  4667. }
  4668.  
  4669. void Spell::EffectEnchantHeldItem(SpellEffIndex effIndex)
  4670. {
  4671. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
  4672. return;
  4673.  
  4674. // this is only item spell effect applied to main-hand weapon of target player (players in area)
  4675. if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
  4676. return;
  4677.  
  4678. Player* item_owner = (Player*)unitTarget;
  4679. Item* item = item_owner->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND);
  4680.  
  4681. if (!item)
  4682. return;
  4683.  
  4684. // must be equipped
  4685. if (!item->IsEquipped())
  4686. return;
  4687.  
  4688. if (m_spellInfo->Effects[effIndex].MiscValue)
  4689. {
  4690. uint32 enchant_id = m_spellInfo->Effects[effIndex].MiscValue;
  4691. int32 duration = m_spellInfo->GetDuration(); //Try duration index first ..
  4692. if (!duration)
  4693. duration = damage;//+1; //Base points after ..
  4694. if (!duration)
  4695. duration = 10; //10 seconds for enchants which don't have listed duration
  4696.  
  4697. SpellItemEnchantmentEntry const* pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
  4698. if (!pEnchant)
  4699. return;
  4700.  
  4701. // Always go to temp enchantment slot
  4702. EnchantmentSlot slot = TEMP_ENCHANTMENT_SLOT;
  4703.  
  4704. // Enchantment will not be applied if a different one already exists
  4705. if (item->GetEnchantmentId(slot) && item->GetEnchantmentId(slot) != enchant_id)
  4706. return;
  4707.  
  4708. // Apply the temporary enchantment
  4709. item->SetEnchantment(slot, enchant_id, duration*IN_MILLISECONDS, 0);
  4710. item_owner->ApplyEnchantment(item, slot, true);
  4711. }
  4712. }
  4713.  
  4714. void Spell::EffectDisEnchant(SpellEffIndex /*effIndex*/)
  4715. {
  4716. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
  4717. return;
  4718.  
  4719. if (!itemTarget || !itemTarget->GetTemplate()->DisenchantID)
  4720. return;
  4721.  
  4722. if (Player* caster = m_caster->ToPlayer())
  4723. {
  4724. caster->UpdateCraftSkill(m_spellInfo->Id);
  4725. caster->SendLoot(itemTarget->GetGUID(), LOOT_DISENCHANTING);
  4726. }
  4727.  
  4728. // item will be removed at disenchanting end
  4729. }
  4730.  
  4731. void Spell::EffectInebriate(SpellEffIndex /*effIndex*/)
  4732. {
  4733. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
  4734. return;
  4735.  
  4736. if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
  4737. return;
  4738.  
  4739. Player* player = unitTarget->ToPlayer();
  4740. uint8 currentDrunk = player->GetDrunkValue();
  4741. uint8 drunkMod = damage;
  4742. if (currentDrunk + drunkMod > 100)
  4743. {
  4744. currentDrunk = 100;
  4745. if (rand_chance() < 25.0f)
  4746. player->CastSpell(player, 67468, false); // Drunken Vomit
  4747. }
  4748. else
  4749. currentDrunk += drunkMod;
  4750.  
  4751. player->SetDrunkValue(currentDrunk, m_CastItem ? m_CastItem->GetEntry() : 0);
  4752. }
  4753.  
  4754. void Spell::EffectFeedPet(SpellEffIndex effIndex)
  4755. {
  4756. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
  4757. return;
  4758.  
  4759. Player* player = m_caster->ToPlayer();
  4760. if (!player)
  4761. return;
  4762.  
  4763. Item* foodItem = itemTarget;
  4764. if (!foodItem)
  4765. return;
  4766.  
  4767. Pet* pet = player->GetPet();
  4768. if (!pet)
  4769. return;
  4770.  
  4771. if (!pet->isAlive())
  4772. return;
  4773.  
  4774. int32 benefit = pet->GetCurrentFoodBenefitLevel(foodItem->GetTemplate()->ItemLevel);
  4775. if (benefit <= 0)
  4776. return;
  4777.  
  4778. ExecuteLogEffectDestroyItem(effIndex, foodItem->GetEntry());
  4779.  
  4780. uint32 count = 1;
  4781. player->DestroyItemCount(foodItem, count, true);
  4782. // TODO: fix crash when a spell has two effects, both pointed at the same item target
  4783.  
  4784. m_caster->CastCustomSpell(pet, m_spellInfo->Effects[effIndex].TriggerSpell, &benefit, NULL, NULL, true);
  4785. }
  4786.  
  4787. void Spell::EffectDismissPet(SpellEffIndex effIndex)
  4788. {
  4789. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
  4790. return;
  4791.  
  4792. if (!unitTarget || !unitTarget->isPet())
  4793. return;
  4794.  
  4795. Pet* pet = unitTarget->ToPet();
  4796.  
  4797. ExecuteLogEffectUnsummonObject(effIndex, pet);
  4798. pet->GetOwner()->RemovePet(pet, PET_SAVE_NOT_IN_SLOT);
  4799. }
  4800.  
  4801. void Spell::EffectSummonObject(SpellEffIndex effIndex)
  4802. {
  4803. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT)
  4804. return;
  4805.  
  4806. uint32 go_id = m_spellInfo->Effects[effIndex].MiscValue;
  4807.  
  4808. uint8 slot = 0;
  4809. switch (m_spellInfo->Effects[effIndex].Effect)
  4810. {
  4811. case SPELL_EFFECT_SUMMON_OBJECT_SLOT1: slot = 0; break;
  4812. case SPELL_EFFECT_SUMMON_OBJECT_SLOT2: slot = 1; break;
  4813. case SPELL_EFFECT_SUMMON_OBJECT_SLOT3: slot = 2; break;
  4814. case SPELL_EFFECT_SUMMON_OBJECT_SLOT4: slot = 3; break;
  4815. default: return;
  4816. }
  4817.  
  4818. uint64 guid = m_caster->m_ObjectSlot[slot];
  4819. if (guid != 0)
  4820. {
  4821. GameObject* obj = NULL;
  4822. if (m_caster)
  4823. obj = m_caster->GetMap()->GetGameObject(guid);
  4824.  
  4825. if (obj)
  4826. {
  4827. // Recast case - null spell id to make auras not be removed on object remove from world
  4828. if (m_spellInfo->Id == obj->GetSpellId())
  4829. obj->SetSpellId(0);
  4830. m_caster->RemoveGameObject(obj, true);
  4831. }
  4832. m_caster->m_ObjectSlot[slot] = 0;
  4833. }
  4834.  
  4835. GameObject* pGameObj = new GameObject;
  4836.  
  4837. float x, y, z;
  4838. // If dest location if present
  4839. if (m_targets.HasDst())
  4840. destTarget->GetPosition(x, y, z);
  4841. // Summon in random point all other units if location present
  4842. else
  4843. m_caster->GetClosePoint(x, y, z, DEFAULT_WORLD_OBJECT_SIZE);
  4844.  
  4845. Map* map = m_caster->GetMap();
  4846. if (!pGameObj->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_GAMEOBJECT), go_id, map,
  4847. m_caster->GetPhaseMask(), x, y, z, m_caster->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 0, GO_STATE_READY))
  4848. {
  4849. delete pGameObj;
  4850. return;
  4851. }
  4852.  
  4853. //pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel());
  4854. int32 duration = m_spellInfo->GetDuration();
  4855. pGameObj->SetRespawnTime(duration > 0 ? duration/IN_MILLISECONDS : 0);
  4856. pGameObj->SetSpellId(m_spellInfo->Id);
  4857. m_caster->AddGameObject(pGameObj);
  4858.  
  4859. ExecuteLogEffectSummonObject(effIndex, pGameObj);
  4860.  
  4861. map->AddToMap(pGameObj);
  4862.  
  4863. m_caster->m_ObjectSlot[slot] = pGameObj->GetGUID();
  4864. }
  4865.  
  4866. void Spell::EffectResurrect(SpellEffIndex effIndex)
  4867. {
  4868. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
  4869. return;
  4870.  
  4871. if (!unitTarget)
  4872. return;
  4873. if (unitTarget->GetTypeId() != TYPEID_PLAYER)
  4874. return;
  4875.  
  4876. if (unitTarget->isAlive())
  4877. return;
  4878. if (!unitTarget->IsInWorld())
  4879. return;
  4880.  
  4881. switch (m_spellInfo->Id)
  4882. {
  4883. // Defibrillate (Goblin Jumper Cables) have 33% chance on success
  4884. case 8342:
  4885. if (roll_chance_i(67))
  4886. {
  4887. m_caster->CastSpell(m_caster, 8338, true, m_CastItem);
  4888. return;
  4889. }
  4890. break;
  4891. // Defibrillate (Goblin Jumper Cables XL) have 50% chance on success
  4892. case 22999:
  4893. if (roll_chance_i(50))
  4894. {
  4895. m_caster->CastSpell(m_caster, 23055, true, m_CastItem);
  4896. return;
  4897. }
  4898. break;
  4899. // Defibrillate (Gnomish Army Knife) have 67% chance on success_list
  4900. case 54732:
  4901. if (roll_chance_i(33))
  4902. {
  4903. return;
  4904. }
  4905. break;
  4906. default:
  4907. break;
  4908. }
  4909.  
  4910. Player* target = unitTarget->ToPlayer();
  4911.  
  4912. if (target->isRessurectRequested()) // already have one active request
  4913. return;
  4914.  
  4915. uint32 health = target->CountPctFromMaxHealth(damage);
  4916. uint32 mana = CalculatePct(target->GetMaxPower(POWER_MANA), damage);
  4917.  
  4918. ExecuteLogEffectResurrect(effIndex, target);
  4919.  
  4920. target->setResurrectRequestData(m_caster->GetGUID(), m_caster->GetMapId(), m_caster->GetPositionX(), m_caster->GetPositionY(), m_caster->GetPositionZ(), health, mana);
  4921. SendResurrectRequest(target);
  4922. }
  4923.  
  4924. void Spell::EffectAddExtraAttacks(SpellEffIndex effIndex)
  4925. {
  4926. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
  4927. return;
  4928.  
  4929. if (!unitTarget || !unitTarget->isAlive() || !unitTarget->getVictim())
  4930. return;
  4931.  
  4932. if (unitTarget->m_extraAttacks)
  4933. return;
  4934.  
  4935. unitTarget->m_extraAttacks = damage;
  4936.  
  4937. ExecuteLogEffectExtraAttacks(effIndex, unitTarget->getVictim(), damage);
  4938. }
  4939.  
  4940. void Spell::EffectParry(SpellEffIndex /*effIndex*/)
  4941. {
  4942. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT)
  4943. return;
  4944.  
  4945. if (m_caster->GetTypeId() == TYPEID_PLAYER)
  4946. m_caster->ToPlayer()->SetCanParry(true);
  4947. }
  4948.  
  4949. void Spell::EffectBlock(SpellEffIndex /*effIndex*/)
  4950. {
  4951. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT)
  4952. return;
  4953.  
  4954. if (m_caster->GetTypeId() == TYPEID_PLAYER)
  4955. m_caster->ToPlayer()->SetCanBlock(true);
  4956. }
  4957.  
  4958. void Spell::EffectLeap(SpellEffIndex /*effIndex*/)
  4959. {
  4960. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
  4961. return;
  4962.  
  4963. if (!unitTarget || unitTarget->isInFlight())
  4964. return;
  4965.  
  4966. if (!m_targets.HasDst())
  4967. return;
  4968.  
  4969. Position pos;
  4970. destTarget->GetPosition(&pos);
  4971. unitTarget->GetFirstCollisionPosition(pos, unitTarget->GetDistance(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ() + 2.0f), 0.0f);
  4972. unitTarget->NearTeleportTo(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation(), unitTarget == m_caster);
  4973. }
  4974.  
  4975. void Spell::EffectReputation(SpellEffIndex effIndex)
  4976. {
  4977. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
  4978. return;
  4979.  
  4980. if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
  4981. return;
  4982.  
  4983. Player* player = unitTarget->ToPlayer();
  4984.  
  4985. int32 rep_change = damage;
  4986.  
  4987. uint32 faction_id = m_spellInfo->Effects[effIndex].MiscValue;
  4988. FactionEntry const* factionEntry = sFactionStore.LookupEntry(faction_id);
  4989.  
  4990. if (!factionEntry)
  4991. return;
  4992.  
  4993. if (RepRewardRate const* repData = sObjectMgr->GetRepRewardRate(faction_id))
  4994. {
  4995. rep_change = int32((float)rep_change * repData->spell_rate);
  4996. }
  4997. // Bonus from spells that increase reputation gain
  4998. float bonus = rep_change * player->GetTotalAuraModifier(SPELL_AURA_MOD_REPUTATION_GAIN) / 100.0f; // 10%
  4999. rep_change += (int32)bonus;
  5000.  
  5001. player->GetReputationMgr().ModifyReputation(factionEntry, rep_change);
  5002. }
  5003.  
  5004. void Spell::EffectQuestComplete(SpellEffIndex effIndex)
  5005. {
  5006. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
  5007. return;
  5008.  
  5009. if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
  5010. return;
  5011. Player* player = unitTarget->ToPlayer();
  5012.  
  5013. uint32 questId = m_spellInfo->Effects[effIndex].MiscValue;
  5014. if (questId)
  5015. {
  5016. Quest const* quest = sObjectMgr->GetQuestTemplate(questId);
  5017. if (!quest)
  5018. return;
  5019.  
  5020. uint16 logSlot = player->FindQuestSlot(questId);
  5021. if (logSlot < MAX_QUEST_LOG_SIZE)
  5022. player->AreaExploredOrEventHappens(questId);
  5023. else if (player->CanTakeQuest(quest, false)) // never rewarded before
  5024. player->CompleteQuest(questId); // quest not in log - for internal use
  5025. }
  5026. }
  5027.  
  5028. void Spell::EffectForceDeselect(SpellEffIndex /*effIndex*/)
  5029. {
  5030. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT)
  5031. return;
  5032.  
  5033. WorldPacket data(SMSG_CLEAR_TARGET, 8);
  5034. data << uint64(m_caster->GetGUID());
  5035. m_caster->SendMessageToSet(&data, true);
  5036. }
  5037.  
  5038. void Spell::EffectSelfResurrect(SpellEffIndex effIndex)
  5039. {
  5040. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT)
  5041. return;
  5042.  
  5043. if (!m_caster || m_caster->isAlive())
  5044. return;
  5045. if (m_caster->GetTypeId() != TYPEID_PLAYER)
  5046. return;
  5047. if (!m_caster->IsInWorld())
  5048. return;
  5049.  
  5050. uint32 health = 0;
  5051. uint32 mana = 0;
  5052.  
  5053. // flat case
  5054. if (damage < 0)
  5055. {
  5056. health = uint32(-damage);
  5057. mana = m_spellInfo->Effects[effIndex].MiscValue;
  5058. }
  5059. // percent case
  5060. else
  5061. {
  5062. health = m_caster->CountPctFromMaxHealth(damage);
  5063. if (m_caster->GetMaxPower(POWER_MANA) > 0)
  5064. mana = CalculatePct(m_caster->GetMaxPower(POWER_MANA), damage);
  5065. }
  5066.  
  5067. Player* player = m_caster->ToPlayer();
  5068. player->ResurrectPlayer(0.0f);
  5069.  
  5070. player->SetHealth(health);
  5071. player->SetPower(POWER_MANA, mana);
  5072. player->SetPower(POWER_RAGE, 0);
  5073. player->SetPower(POWER_ENERGY, player->GetMaxPower(POWER_ENERGY));
  5074.  
  5075. player->SpawnCorpseBones();
  5076. }
  5077.  
  5078. void Spell::EffectSkinning(SpellEffIndex /*effIndex*/)
  5079. {
  5080. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
  5081. return;
  5082.  
  5083. if (unitTarget->GetTypeId() != TYPEID_UNIT)
  5084. return;
  5085. if (m_caster->GetTypeId() != TYPEID_PLAYER)
  5086. return;
  5087.  
  5088. Creature* creature = unitTarget->ToCreature();
  5089. int32 targetLevel = creature->getLevel();
  5090.  
  5091. uint32 skill = creature->GetCreatureTemplate()->GetRequiredLootSkill();
  5092.  
  5093. m_caster->ToPlayer()->SendLoot(creature->GetGUID(), LOOT_SKINNING);
  5094. creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE);
  5095.  
  5096. int32 reqValue = targetLevel < 10 ? 0 : targetLevel < 20 ? (targetLevel-10)*10 : targetLevel*5;
  5097.  
  5098. int32 skillValue = m_caster->ToPlayer()->GetPureSkillValue(skill);
  5099.  
  5100. // Double chances for elites
  5101. m_caster->ToPlayer()->UpdateGatherSkill(skill, skillValue, reqValue, creature->isElite() ? 2 : 1);
  5102. }
  5103.  
  5104. void Spell::EffectCharge(SpellEffIndex /*effIndex*/)
  5105. {
  5106. if (effectHandleMode == SPELL_EFFECT_HANDLE_LAUNCH_TARGET)
  5107. {
  5108. if (!unitTarget)
  5109. return;
  5110.  
  5111. float angle = unitTarget->GetRelativeAngle(m_caster);
  5112. Position pos;
  5113.  
  5114. unitTarget->GetContactPoint(m_caster, pos.m_positionX, pos.m_positionY, pos.m_positionZ);
  5115. unitTarget->GetFirstCollisionPosition(pos, unitTarget->GetObjectSize(), angle);
  5116.  
  5117. m_caster->GetMotionMaster()->MoveCharge(pos.m_positionX, pos.m_positionY, pos.m_positionZ + unitTarget->GetObjectSize());
  5118. }
  5119.  
  5120. if (effectHandleMode == SPELL_EFFECT_HANDLE_HIT_TARGET)
  5121. {
  5122. if (!unitTarget)
  5123. return;
  5124.  
  5125. // not all charge effects used in negative spells
  5126. if (!m_spellInfo->IsPositive() && m_caster->GetTypeId() == TYPEID_PLAYER)
  5127. m_caster->Attack(unitTarget, true);
  5128. }
  5129. }
  5130.  
  5131. void Spell::EffectChargeDest(SpellEffIndex /*effIndex*/)
  5132. {
  5133. if (effectHandleMode != SPELL_EFFECT_HANDLE_LAUNCH)
  5134. return;
  5135.  
  5136. if (m_targets.HasDst())
  5137. {
  5138. Position pos;
  5139. destTarget->GetPosition(&pos);
  5140. float angle = m_caster->GetRelativeAngle(pos.GetPositionX(), pos.GetPositionY());
  5141. float dist = m_caster->GetDistance(pos);
  5142. m_caster->GetFirstCollisionPosition(pos, dist, angle);
  5143.  
  5144. m_caster->GetMotionMaster()->MoveCharge(pos.m_positionX, pos.m_positionY, pos.m_positionZ);
  5145. }
  5146. }
  5147.  
  5148. void Spell::EffectKnockBack(SpellEffIndex effIndex)
  5149. {
  5150. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
  5151. return;
  5152.  
  5153. if (!unitTarget)
  5154. return;
  5155.  
  5156. if (Creature* creatureTarget = unitTarget->ToCreature())
  5157. if (creatureTarget->isWorldBoss() || creatureTarget->IsDungeonBoss())
  5158. return;
  5159.  
  5160. // Spells with SPELL_EFFECT_KNOCK_BACK(like Thunderstorm) can't knoback target if target has ROOT/STUN
  5161. if (unitTarget->HasUnitState(UNIT_STATE_ROOT | UNIT_STATE_STUNNED))
  5162. return;
  5163.  
  5164. // Typhoon
  5165. if (m_spellInfo->SpellFamilyName == SPELLFAMILY_DRUID && m_spellInfo->SpellFamilyFlags[1] & 0x01000000)
  5166. {
  5167. // Glyph of Typhoon
  5168. if (m_caster->HasAura(62135))
  5169. return;
  5170. }
  5171.  
  5172. // Thunderstorm
  5173. if (m_spellInfo->SpellFamilyName == SPELLFAMILY_SHAMAN && m_spellInfo->SpellFamilyFlags[1] & 0x00002000)
  5174. {
  5175. // Glyph of Thunderstorm
  5176. if (m_caster->HasAura(62132))
  5177. return;
  5178. }
  5179.  
  5180. // Instantly interrupt non melee spells being casted
  5181. if (unitTarget->IsNonMeleeSpellCasted(true))
  5182. unitTarget->InterruptNonMeleeSpells(true);
  5183.  
  5184. float ratio = 0.1f;
  5185. float speedxy = float(m_spellInfo->Effects[effIndex].MiscValue) * ratio;
  5186. float speedz = float(damage) * ratio;
  5187. if (speedxy < 0.1f && speedz < 0.1f)
  5188. return;
  5189.  
  5190. float x, y;
  5191. if (m_spellInfo->Effects[effIndex].Effect == SPELL_EFFECT_KNOCK_BACK_DEST)
  5192. {
  5193. if (m_targets.HasDst())
  5194. destTarget->GetPosition(x, y);
  5195. else
  5196. return;
  5197. }
  5198. else //if (m_spellInfo->Effects[i].Effect == SPELL_EFFECT_KNOCK_BACK)
  5199. {
  5200. m_caster->GetPosition(x, y);
  5201. }
  5202.  
  5203. unitTarget->KnockbackFrom(x, y, speedxy, speedz);
  5204. }
  5205.  
  5206. void Spell::EffectLeapBack(SpellEffIndex effIndex)
  5207. {
  5208. if (effectHandleMode != SPELL_EFFECT_HANDLE_LAUNCH_TARGET)
  5209. return;
  5210.  
  5211. if (!unitTarget)
  5212. return;
  5213.  
  5214. float speedxy = float(m_spellInfo->Effects[effIndex].MiscValue)/10;
  5215. float speedz = float(damage/10);
  5216. //1891: Disengage
  5217. m_caster->JumpTo(speedxy, speedz, m_spellInfo->SpellIconID != 1891);
  5218. }
  5219.  
  5220. void Spell::EffectQuestClear(SpellEffIndex effIndex)
  5221. {
  5222. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
  5223. return;
  5224.  
  5225. if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
  5226. return;
  5227. Player* player = unitTarget->ToPlayer();
  5228.  
  5229. uint32 quest_id = m_spellInfo->Effects[effIndex].MiscValue;
  5230.  
  5231. Quest const* quest = sObjectMgr->GetQuestTemplate(quest_id);
  5232.  
  5233. if (!quest)
  5234. return;
  5235.  
  5236. // Player has never done this quest
  5237. if (player->GetQuestStatus(quest_id) == QUEST_STATUS_NONE)
  5238. return;
  5239.  
  5240. // remove all quest entries for 'entry' from quest log
  5241. for (uint8 slot = 0; slot < MAX_QUEST_LOG_SIZE; ++slot)
  5242. {
  5243. uint32 logQuest = player->GetQuestSlotQuestId(slot);
  5244. if (logQuest == quest_id)
  5245. {
  5246. player->SetQuestSlot(slot, 0);
  5247.  
  5248. // we ignore unequippable quest items in this case, it's still be equipped
  5249. player->TakeQuestSourceItem(logQuest, false);
  5250. }
  5251. }
  5252.  
  5253. player->RemoveActiveQuest(quest_id);
  5254. player->RemoveRewardedQuest(quest_id);
  5255. }
  5256.  
  5257. void Spell::EffectSendTaxi(SpellEffIndex effIndex)
  5258. {
  5259. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
  5260. return;
  5261.  
  5262. if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
  5263. return;
  5264.  
  5265. unitTarget->ToPlayer()->ActivateTaxiPathTo(m_spellInfo->Effects[effIndex].MiscValue, m_spellInfo->Id);
  5266. }
  5267.  
  5268. void Spell::EffectPullTowards(SpellEffIndex effIndex)
  5269. {
  5270. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
  5271. return;
  5272.  
  5273. if (!unitTarget)
  5274. return;
  5275.  
  5276. float speedZ = (float)(m_spellInfo->Effects[effIndex].CalcValue() / 10);
  5277. float speedXY = (float)(m_spellInfo->Effects[effIndex].MiscValue/10);
  5278. Position pos;
  5279. if (m_spellInfo->Effects[effIndex].Effect == SPELL_EFFECT_PULL_TOWARDS_DEST)
  5280. {
  5281. if (m_targets.HasDst())
  5282. pos.Relocate(*destTarget);
  5283. else
  5284. return;
  5285. }
  5286. else //if (m_spellInfo->Effects[i].Effect == SPELL_EFFECT_PULL_TOWARDS)
  5287. {
  5288. pos.Relocate(m_caster);
  5289. }
  5290.  
  5291. unitTarget->GetMotionMaster()->MoveJump(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), speedXY, speedZ);
  5292. }
  5293.  
  5294. void Spell::EffectDispelMechanic(SpellEffIndex effIndex)
  5295. {
  5296. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
  5297. return;
  5298.  
  5299. if (!unitTarget)
  5300. return;
  5301.  
  5302. uint32 mechanic = m_spellInfo->Effects[effIndex].MiscValue;
  5303.  
  5304. std::queue < std::pair < uint32, uint64 > > dispel_list;
  5305.  
  5306. Unit::AuraMap const& auras = unitTarget->GetOwnedAuras();
  5307. for (Unit::AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
  5308. {
  5309. Aura* aura = itr->second;
  5310. if (!aura->GetApplicationOfTarget(unitTarget->GetGUID()))
  5311. continue;
  5312. if (roll_chance_i(aura->CalcDispelChance(unitTarget, !unitTarget->IsFriendlyTo(m_caster))))
  5313. if ((aura->GetSpellInfo()->GetAllEffectsMechanicMask() & (1 << mechanic)))
  5314. dispel_list.push(std::make_pair(aura->GetId(), aura->GetCasterGUID()));
  5315. }
  5316.  
  5317. for (; dispel_list.size(); dispel_list.pop())
  5318. {
  5319. unitTarget->RemoveAura(dispel_list.front().first, dispel_list.front().second, 0, AURA_REMOVE_BY_ENEMY_SPELL);
  5320. }
  5321. }
  5322.  
  5323. void Spell::EffectSummonDeadPet(SpellEffIndex /*effIndex*/)
  5324. {
  5325. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT)
  5326. return;
  5327.  
  5328. Player* player = m_caster->ToPlayer();
  5329. if (!player)
  5330. return;
  5331.  
  5332. Pet* pet = player->GetPet();
  5333. if (pet && pet->isAlive())
  5334. return;
  5335.  
  5336. if (damage < 0)
  5337. return;
  5338.  
  5339. float x, y, z;
  5340. player->GetPosition(x, y, z);
  5341. if (!pet)
  5342. {
  5343. player->SummonPet(0, x, y, z, player->GetOrientation(), SUMMON_PET, 0);
  5344. pet = player->GetPet();
  5345. }
  5346. if (!pet)
  5347. return;
  5348.  
  5349. player->GetMap()->CreatureRelocation(pet, x, y, z, player->GetOrientation());
  5350.  
  5351. pet->SetUInt32Value(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_NONE);
  5352. pet->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE);
  5353. pet->setDeathState(ALIVE);
  5354. pet->ClearUnitState(uint32(UNIT_STATE_ALL_STATE));
  5355. pet->SetHealth(pet->CountPctFromMaxHealth(damage));
  5356.  
  5357. //pet->AIM_Initialize();
  5358. //player->PetSpellInitialize();
  5359. pet->SavePetToDB(PET_SAVE_AS_CURRENT);
  5360. }
  5361.  
  5362. void Spell::EffectDestroyAllTotems(SpellEffIndex /*effIndex*/)
  5363. {
  5364. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT)
  5365. return;
  5366.  
  5367. int32 mana = 0;
  5368. for (uint8 slot = SUMMON_SLOT_TOTEM; slot < MAX_TOTEM_SLOT; ++slot)
  5369. {
  5370. if (!m_caster->m_SummonSlot[slot])
  5371. continue;
  5372.  
  5373. Creature* totem = m_caster->GetMap()->GetCreature(m_caster->m_SummonSlot[slot]);
  5374. if (totem && totem->isTotem())
  5375. {
  5376. uint32 spell_id = totem->GetUInt32Value(UNIT_CREATED_BY_SPELL);
  5377. SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spell_id);
  5378. if (spellInfo)
  5379. {
  5380. mana += spellInfo->ManaCost;
  5381. mana += int32(CalculatePct(m_caster->GetCreateMana(), spellInfo->ManaCostPercentage));
  5382. }
  5383. totem->ToTotem()->UnSummon();
  5384. }
  5385. }
  5386. ApplyPct(mana, damage);
  5387. if (mana)
  5388. m_caster->CastCustomSpell(m_caster, 39104, &mana, NULL, NULL, true);
  5389. }
  5390.  
  5391. void Spell::EffectDurabilityDamage(SpellEffIndex effIndex)
  5392. {
  5393. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
  5394. return;
  5395.  
  5396. if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
  5397. return;
  5398.  
  5399. int32 slot = m_spellInfo->Effects[effIndex].MiscValue;
  5400.  
  5401. // -1 means all player equipped items and -2 all items
  5402. if (slot < 0)
  5403. {
  5404. unitTarget->ToPlayer()->DurabilityPointsLossAll(damage, (slot < -1));
  5405. ExecuteLogEffectDurabilityDamage(effIndex, unitTarget, -1, -1);
  5406. return;
  5407. }
  5408.  
  5409. // invalid slot value
  5410. if (slot >= INVENTORY_SLOT_BAG_END)
  5411. return;
  5412.  
  5413. if (Item* item = unitTarget->ToPlayer()->GetItemByPos(INVENTORY_SLOT_BAG_0, slot))
  5414. {
  5415. unitTarget->ToPlayer()->DurabilityPointsLoss(item, damage);
  5416. ExecuteLogEffectDurabilityDamage(effIndex, unitTarget, item->GetEntry(), slot);
  5417. }
  5418. }
  5419.  
  5420. void Spell::EffectDurabilityDamagePCT(SpellEffIndex effIndex)
  5421. {
  5422. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
  5423. return;
  5424.  
  5425. if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
  5426. return;
  5427.  
  5428. int32 slot = m_spellInfo->Effects[effIndex].MiscValue;
  5429.  
  5430. // FIXME: some spells effects have value -1/-2
  5431. // Possibly its mean -1 all player equipped items and -2 all items
  5432. if (slot < 0)
  5433. {
  5434. unitTarget->ToPlayer()->DurabilityLossAll(float(damage) / 100.0f, (slot < -1));
  5435. return;
  5436. }
  5437.  
  5438. // invalid slot value
  5439. if (slot >= INVENTORY_SLOT_BAG_END)
  5440. return;
  5441.  
  5442. if (damage <= 0)
  5443. return;
  5444.  
  5445. if (Item* item = unitTarget->ToPlayer()->GetItemByPos(INVENTORY_SLOT_BAG_0, slot))
  5446. unitTarget->ToPlayer()->DurabilityLoss(item, float(damage) / 100.0f);
  5447. }
  5448.  
  5449. void Spell::EffectModifyThreatPercent(SpellEffIndex /*effIndex*/)
  5450. {
  5451. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
  5452. return;
  5453.  
  5454. if (!unitTarget)
  5455. return;
  5456.  
  5457. unitTarget->getThreatManager().modifyThreatPercent(m_caster, damage);
  5458. }
  5459.  
  5460. void Spell::EffectTransmitted(SpellEffIndex effIndex)
  5461. {
  5462. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT)
  5463. return;
  5464.  
  5465. uint32 name_id = m_spellInfo->Effects[effIndex].MiscValue;
  5466.  
  5467. GameObjectTemplate const* goinfo = sObjectMgr->GetGameObjectTemplate(name_id);
  5468.  
  5469. if (!goinfo)
  5470. {
  5471. sLog->outError(LOG_FILTER_SQL, "Gameobject (Entry: %u) not exist and not created at spell (ID: %u) cast", name_id, m_spellInfo->Id);
  5472. return;
  5473. }
  5474.  
  5475. float fx, fy, fz;
  5476.  
  5477. if (m_targets.HasDst())
  5478. destTarget->GetPosition(fx, fy, fz);
  5479. //FIXME: this can be better check for most objects but still hack
  5480. else if (m_spellInfo->Effects[effIndex].HasRadius() && m_spellInfo->Speed == 0)
  5481. {
  5482. float dis = m_spellInfo->Effects[effIndex].CalcRadius(m_originalCaster);
  5483. m_caster->GetClosePoint(fx, fy, fz, DEFAULT_WORLD_OBJECT_SIZE, dis);
  5484. }
  5485. else
  5486. {
  5487. //GO is always friendly to it's creator, get range for friends
  5488. float min_dis = m_spellInfo->GetMinRange(true);
  5489. float max_dis = m_spellInfo->GetMaxRange(true);
  5490. float dis = (float)rand_norm() * (max_dis - min_dis) + min_dis;
  5491.  
  5492. m_caster->GetClosePoint(fx, fy, fz, DEFAULT_WORLD_OBJECT_SIZE, dis);
  5493. }
  5494.  
  5495. Map* cMap = m_caster->GetMap();
  5496. if (goinfo->type == GAMEOBJECT_TYPE_FISHINGNODE || goinfo->type == GAMEOBJECT_TYPE_FISHINGHOLE)
  5497. {
  5498. LiquidData liqData;
  5499. if (!cMap->IsInWater(fx, fy, fz + 1.f/* -0.5f */, &liqData)) // Hack to prevent fishing bobber from failing to land on fishing hole
  5500. { // but this is not proper, we really need to ignore not materialized objects
  5501. SendCastResult(SPELL_FAILED_NOT_HERE);
  5502. SendChannelUpdate(0);
  5503. return;
  5504. }
  5505.  
  5506. // replace by water level in this case
  5507. //fz = cMap->GetWaterLevel(fx, fy);
  5508. fz = liqData.level;
  5509. }
  5510. // if gameobject is summoning object, it should be spawned right on caster's position
  5511. else if (goinfo->type == GAMEOBJECT_TYPE_SUMMONING_RITUAL)
  5512. {
  5513. m_caster->GetPosition(fx, fy, fz);
  5514. }
  5515.  
  5516. GameObject* pGameObj = new GameObject;
  5517.  
  5518. if (!pGameObj->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_GAMEOBJECT), name_id, cMap,
  5519. m_caster->GetPhaseMask(), fx, fy, fz, m_caster->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, GO_STATE_READY))
  5520. {
  5521. delete pGameObj;
  5522. return;
  5523. }
  5524.  
  5525. int32 duration = m_spellInfo->GetDuration();
  5526.  
  5527. switch (goinfo->type)
  5528. {
  5529. case GAMEOBJECT_TYPE_FISHINGNODE:
  5530. {
  5531. m_caster->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT, pGameObj->GetGUID());
  5532. m_caster->AddGameObject(pGameObj); // will removed at spell cancel
  5533.  
  5534. // end time of range when possible catch fish (FISHING_BOBBER_READY_TIME..GetDuration(m_spellInfo))
  5535. // start time == fish-FISHING_BOBBER_READY_TIME (0..GetDuration(m_spellInfo)-FISHING_BOBBER_READY_TIME)
  5536. int32 lastSec = 0;
  5537. switch (urand(0, 3))
  5538. {
  5539. case 0: lastSec = 3; break;
  5540. case 1: lastSec = 7; break;
  5541. case 2: lastSec = 13; break;
  5542. case 3: lastSec = 17; break;
  5543. }
  5544.  
  5545. duration = duration - lastSec*IN_MILLISECONDS + FISHING_BOBBER_READY_TIME*IN_MILLISECONDS;
  5546. break;
  5547. }
  5548. case GAMEOBJECT_TYPE_SUMMONING_RITUAL:
  5549. {
  5550. if (m_caster->GetTypeId() == TYPEID_PLAYER)
  5551. {
  5552. pGameObj->AddUniqueUse(m_caster->ToPlayer());
  5553. m_caster->AddGameObject(pGameObj); // will be removed at spell cancel
  5554. }
  5555. break;
  5556. }
  5557. case GAMEOBJECT_TYPE_DUEL_ARBITER: // 52991
  5558. m_caster->AddGameObject(pGameObj);
  5559. break;
  5560. case GAMEOBJECT_TYPE_FISHINGHOLE:
  5561. case GAMEOBJECT_TYPE_CHEST:
  5562. default:
  5563. break;
  5564. }
  5565.  
  5566. pGameObj->SetRespawnTime(duration > 0 ? duration/IN_MILLISECONDS : 0);
  5567.  
  5568. pGameObj->SetOwnerGUID(m_caster->GetGUID());
  5569.  
  5570. //pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel());
  5571. pGameObj->SetSpellId(m_spellInfo->Id);
  5572.  
  5573. ExecuteLogEffectSummonObject(effIndex, pGameObj);
  5574.  
  5575. sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "AddObject at SpellEfects.cpp EffectTransmitted");
  5576. //m_caster->AddGameObject(pGameObj);
  5577. //m_ObjToDel.push_back(pGameObj);
  5578.  
  5579. cMap->AddToMap(pGameObj);
  5580.  
  5581. if (uint32 linkedEntry = pGameObj->GetGOInfo()->GetLinkedGameObjectEntry())
  5582. {
  5583. GameObject* linkedGO = new GameObject;
  5584. if (linkedGO->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_GAMEOBJECT), linkedEntry, cMap,
  5585. m_caster->GetPhaseMask(), fx, fy, fz, m_caster->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, GO_STATE_READY))
  5586. {
  5587. linkedGO->SetRespawnTime(duration > 0 ? duration/IN_MILLISECONDS : 0);
  5588. //linkedGO->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel());
  5589. linkedGO->SetSpellId(m_spellInfo->Id);
  5590. linkedGO->SetOwnerGUID(m_caster->GetGUID());
  5591.  
  5592. ExecuteLogEffectSummonObject(effIndex, linkedGO);
  5593.  
  5594. linkedGO->GetMap()->AddToMap(linkedGO);
  5595. }
  5596. else
  5597. {
  5598. delete linkedGO;
  5599. linkedGO = NULL;
  5600. return;
  5601. }
  5602. }
  5603. }
  5604.  
  5605. void Spell::EffectProspecting(SpellEffIndex /*effIndex*/)
  5606. {
  5607. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
  5608. return;
  5609.  
  5610. if (m_caster->GetTypeId() != TYPEID_PLAYER)
  5611. return;
  5612.  
  5613. Player* p_caster = (Player*)m_caster;
  5614. if (!itemTarget || !(itemTarget->GetTemplate()->Flags & ITEM_PROTO_FLAG_PROSPECTABLE))
  5615. return;
  5616.  
  5617. if (itemTarget->GetCount() < 5)
  5618. return;
  5619.  
  5620. if (sWorld->getBoolConfig(CONFIG_SKILL_PROSPECTING))
  5621. {
  5622. uint32 SkillValue = p_caster->GetPureSkillValue(SKILL_JEWELCRAFTING);
  5623. uint32 reqSkillValue = itemTarget->GetTemplate()->RequiredSkillRank;
  5624. p_caster->UpdateGatherSkill(SKILL_JEWELCRAFTING, SkillValue, reqSkillValue);
  5625. }
  5626.  
  5627. m_caster->ToPlayer()->SendLoot(itemTarget->GetGUID(), LOOT_PROSPECTING);
  5628. }
  5629.  
  5630. void Spell::EffectMilling(SpellEffIndex /*effIndex*/)
  5631. {
  5632. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
  5633. return;
  5634.  
  5635. if (m_caster->GetTypeId() != TYPEID_PLAYER)
  5636. return;
  5637.  
  5638. Player* p_caster = (Player*)m_caster;
  5639. if (!itemTarget || !(itemTarget->GetTemplate()->Flags & ITEM_PROTO_FLAG_MILLABLE))
  5640. return;
  5641.  
  5642. if (itemTarget->GetCount() < 5)
  5643. return;
  5644.  
  5645. if (sWorld->getBoolConfig(CONFIG_SKILL_MILLING))
  5646. {
  5647. uint32 SkillValue = p_caster->GetPureSkillValue(SKILL_INSCRIPTION);
  5648. uint32 reqSkillValue = itemTarget->GetTemplate()->RequiredSkillRank;
  5649. p_caster->UpdateGatherSkill(SKILL_INSCRIPTION, SkillValue, reqSkillValue);
  5650. }
  5651.  
  5652. m_caster->ToPlayer()->SendLoot(itemTarget->GetGUID(), LOOT_MILLING);
  5653. }
  5654.  
  5655. void Spell::EffectSkill(SpellEffIndex /*effIndex*/)
  5656. {
  5657. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT)
  5658. return;
  5659.  
  5660. sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "WORLD: SkillEFFECT");
  5661. }
  5662.  
  5663. /* There is currently no need for this effect. We handle it in Battleground.cpp
  5664. If we would handle the resurrection here, the spiritguide would instantly disappear as the
  5665. player revives, and so we wouldn't see the spirit heal visual effect on the npc.
  5666. This is why we use a half sec delay between the visual effect and the resurrection itself */
  5667. void Spell::EffectSpiritHeal(SpellEffIndex /*effIndex*/)
  5668. {
  5669. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
  5670. return;
  5671.  
  5672. /*
  5673. if (unitTarget->GetTypeId() != TYPEID_PLAYER)
  5674. return;
  5675. if (!unitTarget->IsInWorld())
  5676. return;
  5677.  
  5678. //m_spellInfo->Effects[i].BasePoints; == 99 (percent?)
  5679. //unitTarget->ToPlayer()->setResurrect(m_caster->GetGUID(), unitTarget->GetPositionX(), unitTarget->GetPositionY(), unitTarget->GetPositionZ(), unitTarget->GetMaxHealth(), unitTarget->GetMaxPower(POWER_MANA));
  5680. unitTarget->ToPlayer()->ResurrectPlayer(1.0f);
  5681. unitTarget->ToPlayer()->SpawnCorpseBones();
  5682. */
  5683. }
  5684.  
  5685. // remove insignia spell effect
  5686. void Spell::EffectSkinPlayerCorpse(SpellEffIndex /*effIndex*/)
  5687. {
  5688. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
  5689. return;
  5690.  
  5691. sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "Effect: SkinPlayerCorpse");
  5692. if ((m_caster->GetTypeId() != TYPEID_PLAYER) || (unitTarget->GetTypeId() != TYPEID_PLAYER) || (unitTarget->isAlive()))
  5693. return;
  5694.  
  5695. unitTarget->ToPlayer()->RemovedInsignia((Player*)m_caster);
  5696. }
  5697.  
  5698. void Spell::EffectStealBeneficialBuff(SpellEffIndex effIndex)
  5699. {
  5700. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
  5701. return;
  5702.  
  5703. sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "Effect: StealBeneficialBuff");
  5704.  
  5705. if (!unitTarget || unitTarget == m_caster) // can't steal from self
  5706. return;
  5707.  
  5708. DispelChargesList steal_list;
  5709.  
  5710. // Create dispel mask by dispel type
  5711. uint32 dispelMask = SpellInfo::GetDispelMask(DispelType(m_spellInfo->Effects[effIndex].MiscValue));
  5712. Unit::AuraMap const& auras = unitTarget->GetOwnedAuras();
  5713. for (Unit::AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
  5714. {
  5715. Aura* aura = itr->second;
  5716. AuraApplication * aurApp = aura->GetApplicationOfTarget(unitTarget->GetGUID());
  5717. if (!aurApp)
  5718. continue;
  5719.  
  5720. if ((aura->GetSpellInfo()->GetDispelMask()) & dispelMask)
  5721. {
  5722. // Need check for passive? this
  5723. if (!aurApp->IsPositive() || aura->IsPassive() || aura->GetSpellInfo()->AttributesEx4 & SPELL_ATTR4_NOT_STEALABLE)
  5724. continue;
  5725.  
  5726. // The charges / stack amounts don't count towards the total number of auras that can be dispelled.
  5727. // Ie: A dispel on a target with 5 stacks of Winters Chill and a Polymorph has 1 / (1 + 1) -> 50% chance to dispell
  5728. // Polymorph instead of 1 / (5 + 1) -> 16%.
  5729. bool dispel_charges = aura->GetSpellInfo()->AttributesEx7 & SPELL_ATTR7_DISPEL_CHARGES;
  5730. uint8 charges = dispel_charges ? aura->GetCharges() : aura->GetStackAmount();
  5731. if (charges > 0)
  5732. steal_list.push_back(std::make_pair(aura, charges));
  5733. }
  5734. }
  5735.  
  5736. if (steal_list.empty())
  5737. return;
  5738.  
  5739. // Ok if exist some buffs for dispel try dispel it
  5740. uint32 failCount = 0;
  5741. DispelList success_list;
  5742. WorldPacket dataFail(SMSG_DISPEL_FAILED, 8+8+4+4+damage*4);
  5743. // dispel N = damage buffs (or while exist buffs for dispel)
  5744. for (int32 count = 0; count < damage && !steal_list.empty();)
  5745. {
  5746. // Random select buff for dispel
  5747. DispelChargesList::iterator itr = steal_list.begin();
  5748. std::advance(itr, urand(0, steal_list.size() - 1));
  5749.  
  5750. int32 chance = itr->first->CalcDispelChance(unitTarget, !unitTarget->IsFriendlyTo(m_caster));
  5751. // 2.4.3 Patch Notes: "Dispel effects will no longer attempt to remove effects that have 100% dispel resistance."
  5752. if (!chance)
  5753. {
  5754. steal_list.erase(itr);
  5755. continue;
  5756. }
  5757. else
  5758. {
  5759. if (roll_chance_i(chance))
  5760. {
  5761. success_list.push_back(std::make_pair(itr->first->GetId(), itr->first->GetCasterGUID()));
  5762. --itr->second;
  5763. if (itr->second <= 0)
  5764. steal_list.erase(itr);
  5765. }
  5766. else
  5767. {
  5768. if (!failCount)
  5769. {
  5770. // Failed to dispell
  5771. dataFail << uint64(m_caster->GetGUID()); // Caster GUID
  5772. dataFail << uint64(unitTarget->GetGUID()); // Victim GUID
  5773. dataFail << uint32(m_spellInfo->Id); // dispel spell id
  5774. }
  5775. ++failCount;
  5776. dataFail << uint32(itr->first->GetId()); // Spell Id
  5777. }
  5778. ++count;
  5779. }
  5780. }
  5781.  
  5782. if (failCount)
  5783. m_caster->SendMessageToSet(&dataFail, true);
  5784.  
  5785. if (success_list.empty())
  5786. return;
  5787.  
  5788. WorldPacket dataSuccess(SMSG_SPELLSTEALLOG, 8+8+4+1+4+damage*5);
  5789. dataSuccess.append(unitTarget->GetPackGUID()); // Victim GUID
  5790. dataSuccess.append(m_caster->GetPackGUID()); // Caster GUID
  5791. dataSuccess << uint32(m_spellInfo->Id); // dispel spell id
  5792. dataSuccess << uint8(0); // not used
  5793. dataSuccess << uint32(success_list.size()); // count
  5794. for (DispelList::iterator itr = success_list.begin(); itr!=success_list.end(); ++itr)
  5795. {
  5796. dataSuccess << uint32(itr->first); // Spell Id
  5797. dataSuccess << uint8(0); // 0 - steals !=0 transfers
  5798. unitTarget->RemoveAurasDueToSpellBySteal(itr->first, itr->second, m_caster);
  5799. }
  5800. m_caster->SendMessageToSet(&dataSuccess, true);
  5801. }
  5802.  
  5803. void Spell::EffectKillCreditPersonal(SpellEffIndex effIndex)
  5804. {
  5805. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
  5806. return;
  5807.  
  5808. if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
  5809. return;
  5810.  
  5811. unitTarget->ToPlayer()->KilledMonsterCredit(m_spellInfo->Effects[effIndex].MiscValue, 0);
  5812. }
  5813.  
  5814. void Spell::EffectKillCredit(SpellEffIndex effIndex)
  5815. {
  5816. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
  5817. return;
  5818.  
  5819. if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
  5820. return;
  5821.  
  5822. int32 creatureEntry = m_spellInfo->Effects[effIndex].MiscValue;
  5823. if (!creatureEntry)
  5824. {
  5825. if (m_spellInfo->Id == 42793) // Burn Body
  5826. creatureEntry = 24008; // Fallen Combatant
  5827. }
  5828.  
  5829. if (creatureEntry)
  5830. unitTarget->ToPlayer()->RewardPlayerAndGroupAtEvent(creatureEntry, unitTarget);
  5831. }
  5832.  
  5833. void Spell::EffectQuestFail(SpellEffIndex effIndex)
  5834. {
  5835. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
  5836. return;
  5837.  
  5838. if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
  5839. return;
  5840.  
  5841. unitTarget->ToPlayer()->FailQuest(m_spellInfo->Effects[effIndex].MiscValue);
  5842. }
  5843.  
  5844. void Spell::EffectQuestStart(SpellEffIndex effIndex)
  5845. {
  5846. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
  5847. return;
  5848.  
  5849. if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
  5850. return;
  5851.  
  5852. Player* player = unitTarget->ToPlayer();
  5853. if (Quest const* qInfo = sObjectMgr->GetQuestTemplate(m_spellInfo->Effects[effIndex].MiscValue))
  5854. {
  5855. if (player->CanTakeQuest(qInfo, false) && player->CanAddQuest(qInfo, false))
  5856. {
  5857. player->AddQuest(qInfo, NULL);
  5858. }
  5859. }
  5860. }
  5861.  
  5862. void Spell::EffectActivateRune(SpellEffIndex effIndex)
  5863. {
  5864. if (effectHandleMode != SPELL_EFFECT_HANDLE_LAUNCH)
  5865. return;
  5866.  
  5867. if (m_caster->GetTypeId() != TYPEID_PLAYER)
  5868. return;
  5869.  
  5870. Player* player = m_caster->ToPlayer();
  5871.  
  5872. if (player->getClass() != CLASS_DEATH_KNIGHT)
  5873. return;
  5874.  
  5875. // needed later
  5876. m_runesState = m_caster->ToPlayer()->GetRunesState();
  5877.  
  5878. uint32 count = damage;
  5879. if (count == 0) count = 1;
  5880. for (uint32 j = 0; j < MAX_RUNES && count > 0; ++j)
  5881. {
  5882. if (player->GetRuneCooldown(j) && player->GetCurrentRune(j) == RuneType(m_spellInfo->Effects[effIndex].MiscValue))
  5883. {
  5884. if (m_spellInfo->Id == 45529)
  5885. if (player->GetBaseRune(j) != RuneType(m_spellInfo->Effects[effIndex].MiscValueB))
  5886. continue;
  5887. player->SetRuneCooldown(j, 0);
  5888. --count;
  5889. }
  5890. }
  5891.  
  5892. // Blood Tap
  5893. if (m_spellInfo->Id == 45529 && count > 0)
  5894. {
  5895. for (uint32 l = 0; l < MAX_RUNES && count > 0; ++l)
  5896. {
  5897. // Check if both runes are on cd as that is the only time when this needs to come into effect
  5898. if ((player->GetRuneCooldown(l) && player->GetCurrentRune(l) == RuneType(m_spellInfo->Effects[effIndex].MiscValueB)) && (player->GetRuneCooldown(l+1) && player->GetCurrentRune(l+1) == RuneType(m_spellInfo->Effects[effIndex].MiscValueB)))
  5899. {
  5900. // Should always update the rune with the lowest cd
  5901. if (player->GetRuneCooldown(l) >= player->GetRuneCooldown(l+1))
  5902. l++;
  5903. player->SetRuneCooldown(l, 0);
  5904. --count;
  5905. // is needed to push through to the client that the rune is active
  5906. player->ResyncRunes(MAX_RUNES);
  5907. }
  5908. else
  5909. break;
  5910. }
  5911. }
  5912.  
  5913. // Empower rune weapon
  5914. if (m_spellInfo->Id == 47568)
  5915. {
  5916. // Need to do this just once
  5917. if (effIndex != 0)
  5918. return;
  5919.  
  5920. for (uint32 i = 0; i < MAX_RUNES; ++i)
  5921. {
  5922. if (player->GetRuneCooldown(i) && (player->GetCurrentRune(i) == RUNE_FROST || player->GetCurrentRune(i) == RUNE_DEATH))
  5923. player->SetRuneCooldown(i, 0);
  5924. }
  5925. }
  5926. }
  5927.  
  5928. void Spell::EffectCreateTamedPet(SpellEffIndex effIndex)
  5929. {
  5930. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
  5931. return;
  5932.  
  5933. if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER || unitTarget->GetPetGUID() || unitTarget->getClass() != CLASS_HUNTER)
  5934. return;
  5935.  
  5936. uint32 creatureEntry = m_spellInfo->Effects[effIndex].MiscValue;
  5937. Pet* pet = unitTarget->CreateTamedPetFrom(creatureEntry, m_spellInfo->Id);
  5938. if (!pet)
  5939. return;
  5940.  
  5941. // add to world
  5942. pet->GetMap()->AddToMap(pet->ToCreature());
  5943.  
  5944. // unitTarget has pet now
  5945. unitTarget->SetMinion(pet, true);
  5946.  
  5947. pet->InitTalentForLevel();
  5948.  
  5949. if (unitTarget->GetTypeId() == TYPEID_PLAYER)
  5950. {
  5951. pet->SavePetToDB(PET_SAVE_AS_CURRENT);
  5952. unitTarget->ToPlayer()->PetSpellInitialize();
  5953. }
  5954. }
  5955.  
  5956. void Spell::EffectDiscoverTaxi(SpellEffIndex effIndex)
  5957. {
  5958. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
  5959. return;
  5960.  
  5961. if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
  5962. return;
  5963. uint32 nodeid = m_spellInfo->Effects[effIndex].MiscValue;
  5964. if (sTaxiNodesStore.LookupEntry(nodeid))
  5965. unitTarget->ToPlayer()->GetSession()->SendDiscoverNewTaxiNode(nodeid);
  5966. }
  5967.  
  5968. void Spell::EffectTitanGrip(SpellEffIndex /*effIndex*/)
  5969. {
  5970. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT)
  5971. return;
  5972.  
  5973. if (m_caster->GetTypeId() == TYPEID_PLAYER)
  5974. m_caster->ToPlayer()->SetCanTitanGrip(true);
  5975. }
  5976.  
  5977. void Spell::EffectRedirectThreat(SpellEffIndex /*effIndex*/)
  5978. {
  5979. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
  5980. return;
  5981.  
  5982. if (unitTarget)
  5983. m_caster->SetReducedThreatPercent((uint32)damage, unitTarget->GetGUID());
  5984. }
  5985.  
  5986. void Spell::EffectGameObjectDamage(SpellEffIndex /*effIndex*/)
  5987. {
  5988. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
  5989. return;
  5990.  
  5991. if (!gameObjTarget)
  5992. return;
  5993.  
  5994. Unit* caster = m_originalCaster;
  5995. if (!caster)
  5996. return;
  5997.  
  5998. FactionTemplateEntry const* casterFaction = caster->getFactionTemplateEntry();
  5999. FactionTemplateEntry const* targetFaction = sFactionTemplateStore.LookupEntry(gameObjTarget->GetUInt32Value(GAMEOBJECT_FACTION));
  6000. // Do not allow to damage GO's of friendly factions (ie: Wintergrasp Walls/Ulduar Storm Beacons)
  6001. if ((casterFaction && targetFaction && !casterFaction->IsFriendlyTo(*targetFaction)) || !targetFaction)
  6002. gameObjTarget->ModifyHealth(-damage, caster, GetSpellInfo()->Id);
  6003. }
  6004.  
  6005. void Spell::EffectGameObjectRepair(SpellEffIndex /*effIndex*/)
  6006. {
  6007. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
  6008. return;
  6009.  
  6010. if (!gameObjTarget)
  6011. return;
  6012.  
  6013. gameObjTarget->ModifyHealth(damage, m_caster);
  6014. }
  6015.  
  6016. void Spell::EffectGameObjectSetDestructionState(SpellEffIndex effIndex)
  6017. {
  6018. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
  6019. return;
  6020.  
  6021. if (!gameObjTarget || !m_originalCaster)
  6022. return;
  6023.  
  6024. Player* player = m_originalCaster->GetCharmerOrOwnerPlayerOrPlayerItself();
  6025. gameObjTarget->SetDestructibleState(GameObjectDestructibleState(m_spellInfo->Effects[effIndex].MiscValue), player, true);
  6026. }
  6027.  
  6028. void Spell::SummonGuardian(uint32 i, uint32 entry, SummonPropertiesEntry const* properties, uint32 numGuardians)
  6029. {
  6030. Unit* caster = m_originalCaster;
  6031. if (!caster)
  6032. return;
  6033.  
  6034. if (caster->isTotem())
  6035. caster = caster->ToTotem()->GetOwner();
  6036.  
  6037. // in another case summon new
  6038. uint8 level = caster->getLevel();
  6039.  
  6040. // level of pet summoned using engineering item based at engineering skill level
  6041. if (m_CastItem && caster->GetTypeId() == TYPEID_PLAYER)
  6042. if (ItemTemplate const* proto = m_CastItem->GetTemplate())
  6043. if (proto->RequiredSkill == SKILL_ENGINEERING)
  6044. if (uint16 skill202 = caster->ToPlayer()->GetSkillValue(SKILL_ENGINEERING))
  6045. level = skill202 / 5;
  6046.  
  6047. float radius = 5.0f;
  6048. int32 duration = m_spellInfo->GetDuration();
  6049.  
  6050. if (Player* modOwner = m_originalCaster->GetSpellModOwner())
  6051. modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_DURATION, duration);
  6052.  
  6053. //TempSummonType summonType = (duration == 0) ? TEMPSUMMON_DEAD_DESPAWN : TEMPSUMMON_TIMED_DESPAWN;
  6054. Map* map = caster->GetMap();
  6055.  
  6056. for (uint32 count = 0; count < numGuardians; ++count)
  6057. {
  6058. Position pos;
  6059. if (count == 0)
  6060. pos = *destTarget;
  6061. else
  6062. // randomize position for multiple summons
  6063. m_caster->GetRandomPoint(*destTarget, radius, pos);
  6064.  
  6065. TempSummon* summon = map->SummonCreature(entry, pos, properties, duration, caster, m_spellInfo->Id);
  6066. if (!summon)
  6067. return;
  6068. if (summon->HasUnitTypeMask(UNIT_MASK_GUARDIAN))
  6069. ((Guardian*)summon)->InitStatsForLevel(level);
  6070.  
  6071. if (properties && properties->Category == SUMMON_CATEGORY_ALLY)
  6072. summon->setFaction(caster->getFaction());
  6073.  
  6074. if (summon->HasUnitTypeMask(UNIT_MASK_MINION) && m_targets.HasDst())
  6075. ((Minion*)summon)->SetFollowAngle(m_caster->GetAngle(summon));
  6076.  
  6077. if (summon->GetEntry() == 27893)
  6078. {
  6079. if (uint32 weapon = m_caster->GetUInt32Value(PLAYER_VISIBLE_ITEM_16_ENTRYID))
  6080. {
  6081. summon->SetDisplayId(11686);
  6082. summon->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, weapon);
  6083. }
  6084. else
  6085. summon->SetDisplayId(1126);
  6086. }
  6087.  
  6088. summon->AI()->EnterEvadeMode();
  6089.  
  6090. ExecuteLogEffectSummonObject(i, summon);
  6091. }
  6092. }
  6093.  
  6094. void Spell::EffectRenamePet(SpellEffIndex /*effIndex*/)
  6095. {
  6096. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
  6097. return;
  6098.  
  6099. if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT ||
  6100. !unitTarget->ToCreature()->isPet() || ((Pet*)unitTarget)->getPetType() != HUNTER_PET)
  6101. return;
  6102.  
  6103. unitTarget->SetByteFlag(UNIT_FIELD_BYTES_2, 2, UNIT_CAN_BE_RENAMED);
  6104. }
  6105.  
  6106. void Spell::EffectPlayMusic(SpellEffIndex effIndex)
  6107. {
  6108. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
  6109. return;
  6110.  
  6111. if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
  6112. return;
  6113.  
  6114. uint32 soundid = m_spellInfo->Effects[effIndex].MiscValue;
  6115.  
  6116. if (!sSoundEntriesStore.LookupEntry(soundid))
  6117. {
  6118. sLog->outError(LOG_FILTER_SPELLS_AURAS, "EffectPlayMusic: Sound (Id: %u) not exist in spell %u.", soundid, m_spellInfo->Id);
  6119. return;
  6120. }
  6121.  
  6122. WorldPacket data(SMSG_PLAY_MUSIC, 4);
  6123. data << uint32(soundid);
  6124. unitTarget->ToPlayer()->GetSession()->SendPacket(&data);
  6125. }
  6126.  
  6127. void Spell::EffectSpecCount(SpellEffIndex /*effIndex*/)
  6128. {
  6129. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
  6130. return;
  6131.  
  6132. if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
  6133. return;
  6134.  
  6135. unitTarget->ToPlayer()->UpdateSpecCount(damage);
  6136. }
  6137.  
  6138. void Spell::EffectActivateSpec(SpellEffIndex /*effIndex*/)
  6139. {
  6140. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
  6141. return;
  6142.  
  6143. if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
  6144. return;
  6145.  
  6146. unitTarget->ToPlayer()->ActivateSpec(damage-1); // damage is 1 or 2, spec is 0 or 1
  6147. }
  6148.  
  6149. void Spell::EffectPlayerNotification(SpellEffIndex effIndex)
  6150. {
  6151. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
  6152. return;
  6153.  
  6154. if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
  6155. return;
  6156.  
  6157. switch (m_spellInfo->Id)
  6158. {
  6159. case 58730: // Restricted Flight Area
  6160. case 58600: // Restricted Flight Area
  6161. unitTarget->ToPlayer()->GetSession()->SendNotification(LANG_ZONE_NOFLYZONE);
  6162. unitTarget->PlayDirectSound(9417); // Fel Reaver sound
  6163. break;
  6164. }
  6165.  
  6166. uint32 soundid = m_spellInfo->Effects[effIndex].MiscValue;
  6167.  
  6168. if (!sSoundEntriesStore.LookupEntry(soundid))
  6169. {
  6170. sLog->outError(LOG_FILTER_SPELLS_AURAS, "EffectPlayerNotification: Sound (Id: %u) not exist in spell %u.", soundid, m_spellInfo->Id);
  6171. return;
  6172. }
  6173.  
  6174. WorldPacket data(SMSG_PLAY_SOUND, 4);
  6175. data << uint32(soundid);
  6176. unitTarget->ToPlayer()->GetSession()->SendPacket(&data);
  6177. }
  6178.  
  6179. void Spell::EffectRemoveAura(SpellEffIndex effIndex)
  6180. {
  6181. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
  6182. return;
  6183.  
  6184. if (!unitTarget)
  6185. return;
  6186. // there may be need of specifying casterguid of removed auras
  6187. unitTarget->RemoveAurasDueToSpell(m_spellInfo->Effects[effIndex].TriggerSpell);
  6188. }
  6189.  
  6190. void Spell::EffectCastButtons(SpellEffIndex effIndex)
  6191. {
  6192. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT)
  6193. return;
  6194.  
  6195. if (m_caster->GetTypeId() != TYPEID_PLAYER)
  6196. return;
  6197.  
  6198. Player* p_caster = m_caster->ToPlayer();
  6199. uint32 button_id = m_spellInfo->Effects[effIndex].MiscValue + 132;
  6200. uint32 n_buttons = m_spellInfo->Effects[effIndex].MiscValueB;
  6201.  
  6202. for (; n_buttons; --n_buttons, ++button_id)
  6203. {
  6204. ActionButton const* ab = p_caster->GetActionButton(button_id);
  6205. if (!ab || ab->GetType() != ACTION_BUTTON_SPELL)
  6206. continue;
  6207.  
  6208. //! Action button data is unverified when it's set so it can be "hacked"
  6209. //! to contain invalid spells, so filter here.
  6210. uint32 spell_id = ab->GetAction();
  6211. if (!spell_id)
  6212. continue;
  6213.  
  6214. SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spell_id);
  6215. if (!spellInfo)
  6216. continue;
  6217.  
  6218. if (!p_caster->HasSpell(spell_id) || p_caster->HasSpellCooldown(spell_id))
  6219. continue;
  6220.  
  6221. if (!(spellInfo->AttributesEx7 & SPELL_ATTR7_SUMMON_PLAYER_TOTEM))
  6222. continue;
  6223.  
  6224. uint32 cost = spellInfo->CalcPowerCost(m_caster, spellInfo->GetSchoolMask());
  6225. if (m_caster->GetPower(POWER_MANA) < cost)
  6226. continue;
  6227.  
  6228. TriggerCastFlags triggerFlags = TriggerCastFlags(TRIGGERED_IGNORE_GCD | TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_CAST_DIRECTLY);
  6229. m_caster->CastSpell(m_caster, spell_id, triggerFlags);
  6230. }
  6231. }
  6232.  
  6233. void Spell::EffectRechargeManaGem(SpellEffIndex /*effIndex*/)
  6234. {
  6235. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
  6236. return;
  6237.  
  6238. if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
  6239. return;
  6240.  
  6241. Player* player = m_caster->ToPlayer();
  6242.  
  6243. if (!player)
  6244. return;
  6245.  
  6246. uint32 item_id = m_spellInfo->Effects[EFFECT_0].ItemType;
  6247.  
  6248. ItemTemplate const* pProto = sObjectMgr->GetItemTemplate(item_id);
  6249. if (!pProto)
  6250. {
  6251. player->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL);
  6252. return;
  6253. }
  6254.  
  6255. if (Item* pItem = player->GetItemByEntry(item_id))
  6256. {
  6257. for (int x = 0; x < MAX_ITEM_PROTO_SPELLS; ++x)
  6258. pItem->SetSpellCharges(x, pProto->Spells[x].SpellCharges);
  6259. pItem->SetState(ITEM_CHANGED, player);
  6260. }
  6261. }
  6262.  
  6263. void Spell::EffectBind(SpellEffIndex effIndex)
  6264. {
  6265. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
  6266. return;
  6267.  
  6268. if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
  6269. return;
  6270.  
  6271. Player* player = unitTarget->ToPlayer();
  6272.  
  6273. WorldLocation homeLoc;
  6274. uint32 areaId = player->GetAreaId();
  6275.  
  6276. if (m_spellInfo->Effects[effIndex].MiscValue)
  6277. areaId = m_spellInfo->Effects[effIndex].MiscValue;
  6278.  
  6279. if (m_targets.HasDst())
  6280. homeLoc.WorldRelocate(*destTarget);
  6281. else
  6282. {
  6283. player->GetPosition(&homeLoc);
  6284. homeLoc.m_mapId = player->GetMapId();
  6285. }
  6286.  
  6287. player->SetHomebind(homeLoc, areaId);
  6288.  
  6289. // binding
  6290. WorldPacket data(SMSG_BINDPOINTUPDATE, (4+4+4+4+4));
  6291. data << float(homeLoc.GetPositionX());
  6292. data << float(homeLoc.GetPositionY());
  6293. data << float(homeLoc.GetPositionZ());
  6294. data << uint32(homeLoc.GetMapId());
  6295. data << uint32(areaId);
  6296. player->SendDirectMessage(&data);
  6297.  
  6298. sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "EffectBind: New homebind X: %f, Y: %f, Z: %f, MapId: %u, AreaId: %u",
  6299. homeLoc.GetPositionX(), homeLoc.GetPositionY(), homeLoc.GetPositionZ(), homeLoc.GetMapId(), areaId);
  6300.  
  6301. // zone update
  6302. data.Initialize(SMSG_PLAYERBOUND, 8+4);
  6303. data << uint64(player->GetGUID());
  6304. data << uint32(areaId);
  6305. player->SendDirectMessage(&data);
  6306. }
  6307.  
  6308. void Spell::EffectSummonRaFFriend(SpellEffIndex effIndex)
  6309. {
  6310. if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
  6311. return;
  6312.  
  6313. if (m_caster->GetTypeId() != TYPEID_PLAYER || !unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
  6314. return;
  6315.  
  6316. m_caster->CastSpell(unitTarget, m_spellInfo->Effects[effIndex].TriggerSpell, true);
  6317. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement