1 | /* |
---|
2 | * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> |
---|
3 | * |
---|
4 | * This program is free software; you can redistribute it and/or modify |
---|
5 | * it under the terms of the GNU General Public License as published by |
---|
6 | * the Free Software Foundation; either version 2 of the License, or |
---|
7 | * (at your option) any later version. |
---|
8 | * |
---|
9 | * This program is distributed in the hope that it will be useful, |
---|
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
12 | * GNU General Public License for more details. |
---|
13 | * |
---|
14 | * You should have received a copy of the GNU General Public License |
---|
15 | * along with this program; if not, write to the Free Software |
---|
16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
---|
17 | */ |
---|
18 | |
---|
19 | #include "Common.h" |
---|
20 | #include "SharedDefines.h" |
---|
21 | #include "Database/DatabaseEnv.h" |
---|
22 | #include "WorldPacket.h" |
---|
23 | #include "WorldSession.h" |
---|
24 | #include "Opcodes.h" |
---|
25 | #include "Log.h" |
---|
26 | #include "UpdateMask.h" |
---|
27 | #include "World.h" |
---|
28 | #include "ObjectMgr.h" |
---|
29 | #include "SpellMgr.h" |
---|
30 | #include "Player.h" |
---|
31 | #include "SkillExtraItems.h" |
---|
32 | #include "Unit.h" |
---|
33 | #include "CreatureAI.h" |
---|
34 | #include "Spell.h" |
---|
35 | #include "DynamicObject.h" |
---|
36 | #include "SpellAuras.h" |
---|
37 | #include "Group.h" |
---|
38 | #include "UpdateData.h" |
---|
39 | #include "MapManager.h" |
---|
40 | #include "ObjectAccessor.h" |
---|
41 | #include "SharedDefines.h" |
---|
42 | #include "Pet.h" |
---|
43 | #include "GameObject.h" |
---|
44 | #include "GossipDef.h" |
---|
45 | #include "Creature.h" |
---|
46 | #include "Totem.h" |
---|
47 | #include "CreatureAI.h" |
---|
48 | #include "BattleGround.h" |
---|
49 | #include "BattleGroundEY.h" |
---|
50 | #include "BattleGroundWS.h" |
---|
51 | #include "VMapFactory.h" |
---|
52 | #include "Language.h" |
---|
53 | #include "SocialMgr.h" |
---|
54 | #include "Util.h" |
---|
55 | #include "TemporarySummon.h" |
---|
56 | |
---|
57 | |
---|
58 | pEffect SpellEffects[TOTAL_SPELL_EFFECTS]= |
---|
59 | { |
---|
60 | &Spell::EffectNULL, // 0 |
---|
61 | &Spell::EffectInstaKill, // 1 SPELL_EFFECT_INSTAKILL |
---|
62 | &Spell::EffectSchoolDMG, // 2 SPELL_EFFECT_SCHOOL_DAMAGE |
---|
63 | &Spell::EffectDummy, // 3 SPELL_EFFECT_DUMMY |
---|
64 | &Spell::EffectUnused, // 4 SPELL_EFFECT_PORTAL_TELEPORT unused |
---|
65 | &Spell::EffectTeleportUnits, // 5 SPELL_EFFECT_TELEPORT_UNITS |
---|
66 | &Spell::EffectApplyAura, // 6 SPELL_EFFECT_APPLY_AURA |
---|
67 | &Spell::EffectEnvirinmentalDMG, // 7 SPELL_EFFECT_ENVIRONMENTAL_DAMAGE |
---|
68 | &Spell::EffectPowerDrain, // 8 SPELL_EFFECT_POWER_DRAIN |
---|
69 | &Spell::EffectHealthLeech, // 9 SPELL_EFFECT_HEALTH_LEECH |
---|
70 | &Spell::EffectHeal, // 10 SPELL_EFFECT_HEAL |
---|
71 | &Spell::EffectUnused, // 11 SPELL_EFFECT_BIND |
---|
72 | &Spell::EffectNULL, // 12 SPELL_EFFECT_PORTAL |
---|
73 | &Spell::EffectUnused, // 13 SPELL_EFFECT_RITUAL_BASE unused |
---|
74 | &Spell::EffectUnused, // 14 SPELL_EFFECT_RITUAL_SPECIALIZE unused |
---|
75 | &Spell::EffectUnused, // 15 SPELL_EFFECT_RITUAL_ACTIVATE_PORTAL unused |
---|
76 | &Spell::EffectQuestComplete, // 16 SPELL_EFFECT_QUEST_COMPLETE |
---|
77 | &Spell::EffectWeaponDmg, // 17 SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL |
---|
78 | &Spell::EffectResurrect, // 18 SPELL_EFFECT_RESURRECT |
---|
79 | &Spell::EffectAddExtraAttacks, // 19 SPELL_EFFECT_ADD_EXTRA_ATTACKS |
---|
80 | &Spell::EffectUnused, // 20 SPELL_EFFECT_DODGE one spell: Dodge |
---|
81 | &Spell::EffectUnused, // 21 SPELL_EFFECT_EVADE one spell: Evade (DND) |
---|
82 | &Spell::EffectParry, // 22 SPELL_EFFECT_PARRY |
---|
83 | &Spell::EffectBlock, // 23 SPELL_EFFECT_BLOCK one spell: Block |
---|
84 | &Spell::EffectCreateItem, // 24 SPELL_EFFECT_CREATE_ITEM |
---|
85 | &Spell::EffectUnused, // 25 SPELL_EFFECT_WEAPON |
---|
86 | &Spell::EffectUnused, // 26 SPELL_EFFECT_DEFENSE one spell: Defense |
---|
87 | &Spell::EffectPersistentAA, // 27 SPELL_EFFECT_PERSISTENT_AREA_AURA |
---|
88 | &Spell::EffectSummonType, // 28 SPELL_EFFECT_SUMMON |
---|
89 | &Spell::EffectMomentMove, // 29 SPELL_EFFECT_LEAP |
---|
90 | &Spell::EffectEnergize, // 30 SPELL_EFFECT_ENERGIZE |
---|
91 | &Spell::EffectWeaponDmg, // 31 SPELL_EFFECT_WEAPON_PERCENT_DAMAGE |
---|
92 | &Spell::EffectTriggerMissileSpell, // 32 SPELL_EFFECT_TRIGGER_MISSILE |
---|
93 | &Spell::EffectOpenLock, // 33 SPELL_EFFECT_OPEN_LOCK |
---|
94 | &Spell::EffectSummonChangeItem, // 34 SPELL_EFFECT_SUMMON_CHANGE_ITEM |
---|
95 | &Spell::EffectApplyAreaAura, // 35 SPELL_EFFECT_APPLY_AREA_AURA_PARTY |
---|
96 | &Spell::EffectLearnSpell, // 36 SPELL_EFFECT_LEARN_SPELL |
---|
97 | &Spell::EffectUnused, // 37 SPELL_EFFECT_SPELL_DEFENSE one spell: SPELLDEFENSE (DND) |
---|
98 | &Spell::EffectDispel, // 38 SPELL_EFFECT_DISPEL |
---|
99 | &Spell::EffectUnused, // 39 SPELL_EFFECT_LANGUAGE |
---|
100 | &Spell::EffectDualWield, // 40 SPELL_EFFECT_DUAL_WIELD |
---|
101 | &Spell::EffectSummonWild, // 41 SPELL_EFFECT_SUMMON_WILD |
---|
102 | &Spell::EffectSummonGuardian, // 42 SPELL_EFFECT_SUMMON_GUARDIAN |
---|
103 | &Spell::EffectTeleUnitsFaceCaster, // 43 SPELL_EFFECT_TELEPORT_UNITS_FACE_CASTER |
---|
104 | &Spell::EffectLearnSkill, // 44 SPELL_EFFECT_SKILL_STEP |
---|
105 | &Spell::EffectAddHonor, // 45 SPELL_EFFECT_ADD_HONOR honor/pvp related |
---|
106 | &Spell::EffectNULL, // 46 SPELL_EFFECT_SPAWN we must spawn pet there |
---|
107 | &Spell::EffectTradeSkill, // 47 SPELL_EFFECT_TRADE_SKILL |
---|
108 | &Spell::EffectUnused, // 48 SPELL_EFFECT_STEALTH one spell: Base Stealth |
---|
109 | &Spell::EffectUnused, // 49 SPELL_EFFECT_DETECT one spell: Detect |
---|
110 | &Spell::EffectTransmitted, // 50 SPELL_EFFECT_TRANS_DOOR |
---|
111 | &Spell::EffectUnused, // 51 SPELL_EFFECT_FORCE_CRITICAL_HIT unused |
---|
112 | &Spell::EffectUnused, // 52 SPELL_EFFECT_GUARANTEE_HIT one spell: zzOLDCritical Shot |
---|
113 | &Spell::EffectEnchantItemPerm, // 53 SPELL_EFFECT_ENCHANT_ITEM |
---|
114 | &Spell::EffectEnchantItemTmp, // 54 SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY |
---|
115 | &Spell::EffectTameCreature, // 55 SPELL_EFFECT_TAMECREATURE |
---|
116 | &Spell::EffectSummonPet, // 56 SPELL_EFFECT_SUMMON_PET |
---|
117 | &Spell::EffectLearnPetSpell, // 57 SPELL_EFFECT_LEARN_PET_SPELL |
---|
118 | &Spell::EffectWeaponDmg, // 58 SPELL_EFFECT_WEAPON_DAMAGE |
---|
119 | &Spell::EffectOpenSecretSafe, // 59 SPELL_EFFECT_OPEN_LOCK_ITEM |
---|
120 | &Spell::EffectProficiency, // 60 SPELL_EFFECT_PROFICIENCY |
---|
121 | &Spell::EffectSendEvent, // 61 SPELL_EFFECT_SEND_EVENT |
---|
122 | &Spell::EffectPowerBurn, // 62 SPELL_EFFECT_POWER_BURN |
---|
123 | &Spell::EffectThreat, // 63 SPELL_EFFECT_THREAT |
---|
124 | &Spell::EffectTriggerSpell, // 64 SPELL_EFFECT_TRIGGER_SPELL |
---|
125 | &Spell::EffectUnused, // 65 SPELL_EFFECT_HEALTH_FUNNEL unused |
---|
126 | &Spell::EffectUnused, // 66 SPELL_EFFECT_POWER_FUNNEL unused |
---|
127 | &Spell::EffectHealMaxHealth, // 67 SPELL_EFFECT_HEAL_MAX_HEALTH |
---|
128 | &Spell::EffectInterruptCast, // 68 SPELL_EFFECT_INTERRUPT_CAST |
---|
129 | &Spell::EffectDistract, // 69 SPELL_EFFECT_DISTRACT |
---|
130 | &Spell::EffectPull, // 70 SPELL_EFFECT_PULL one spell: Distract Move |
---|
131 | &Spell::EffectPickPocket, // 71 SPELL_EFFECT_PICKPOCKET |
---|
132 | &Spell::EffectAddFarsight, // 72 SPELL_EFFECT_ADD_FARSIGHT |
---|
133 | &Spell::EffectSummonGuardian, // 73 SPELL_EFFECT_SUMMON_POSSESSED |
---|
134 | &Spell::EffectSummonTotem, // 74 SPELL_EFFECT_SUMMON_TOTEM |
---|
135 | &Spell::EffectHealMechanical, // 75 SPELL_EFFECT_HEAL_MECHANICAL one spell: Mechanical Patch Kit |
---|
136 | &Spell::EffectSummonObjectWild, // 76 SPELL_EFFECT_SUMMON_OBJECT_WILD |
---|
137 | &Spell::EffectScriptEffect, // 77 SPELL_EFFECT_SCRIPT_EFFECT |
---|
138 | &Spell::EffectUnused, // 78 SPELL_EFFECT_ATTACK |
---|
139 | &Spell::EffectSanctuary, // 79 SPELL_EFFECT_SANCTUARY |
---|
140 | &Spell::EffectAddComboPoints, // 80 SPELL_EFFECT_ADD_COMBO_POINTS |
---|
141 | &Spell::EffectUnused, // 81 SPELL_EFFECT_CREATE_HOUSE one spell: Create House (TEST) |
---|
142 | &Spell::EffectNULL, // 82 SPELL_EFFECT_BIND_SIGHT |
---|
143 | &Spell::EffectDuel, // 83 SPELL_EFFECT_DUEL |
---|
144 | &Spell::EffectStuck, // 84 SPELL_EFFECT_STUCK |
---|
145 | &Spell::EffectSummonPlayer, // 85 SPELL_EFFECT_SUMMON_PLAYER |
---|
146 | &Spell::EffectActivateObject, // 86 SPELL_EFFECT_ACTIVATE_OBJECT |
---|
147 | &Spell::EffectSummonTotem, // 87 SPELL_EFFECT_SUMMON_TOTEM_SLOT1 |
---|
148 | &Spell::EffectSummonTotem, // 88 SPELL_EFFECT_SUMMON_TOTEM_SLOT2 |
---|
149 | &Spell::EffectSummonTotem, // 89 SPELL_EFFECT_SUMMON_TOTEM_SLOT3 |
---|
150 | &Spell::EffectSummonTotem, // 90 SPELL_EFFECT_SUMMON_TOTEM_SLOT4 |
---|
151 | &Spell::EffectUnused, // 91 SPELL_EFFECT_THREAT_ALL one spell: zzOLDBrainwash |
---|
152 | &Spell::EffectEnchantHeldItem, // 92 SPELL_EFFECT_ENCHANT_HELD_ITEM |
---|
153 | &Spell::EffectUnused, // 93 SPELL_EFFECT_SUMMON_PHANTASM |
---|
154 | &Spell::EffectSelfResurrect, // 94 SPELL_EFFECT_SELF_RESURRECT |
---|
155 | &Spell::EffectSkinning, // 95 SPELL_EFFECT_SKINNING |
---|
156 | &Spell::EffectCharge, // 96 SPELL_EFFECT_CHARGE |
---|
157 | &Spell::EffectSummonCritter, // 97 SPELL_EFFECT_SUMMON_CRITTER |
---|
158 | &Spell::EffectKnockBack, // 98 SPELL_EFFECT_KNOCK_BACK |
---|
159 | &Spell::EffectDisEnchant, // 99 SPELL_EFFECT_DISENCHANT |
---|
160 | &Spell::EffectInebriate, //100 SPELL_EFFECT_INEBRIATE |
---|
161 | &Spell::EffectFeedPet, //101 SPELL_EFFECT_FEED_PET |
---|
162 | &Spell::EffectDismissPet, //102 SPELL_EFFECT_DISMISS_PET |
---|
163 | &Spell::EffectReputation, //103 SPELL_EFFECT_REPUTATION |
---|
164 | &Spell::EffectSummonObject, //104 SPELL_EFFECT_SUMMON_OBJECT_SLOT1 |
---|
165 | &Spell::EffectSummonObject, //105 SPELL_EFFECT_SUMMON_OBJECT_SLOT2 |
---|
166 | &Spell::EffectSummonObject, //106 SPELL_EFFECT_SUMMON_OBJECT_SLOT3 |
---|
167 | &Spell::EffectSummonObject, //107 SPELL_EFFECT_SUMMON_OBJECT_SLOT4 |
---|
168 | &Spell::EffectDispelMechanic, //108 SPELL_EFFECT_DISPEL_MECHANIC |
---|
169 | &Spell::EffectSummonDeadPet, //109 SPELL_EFFECT_SUMMON_DEAD_PET |
---|
170 | &Spell::EffectDestroyAllTotems, //110 SPELL_EFFECT_DESTROY_ALL_TOTEMS |
---|
171 | &Spell::EffectDurabilityDamage, //111 SPELL_EFFECT_DURABILITY_DAMAGE |
---|
172 | &Spell::EffectSummonDemon, //112 SPELL_EFFECT_SUMMON_DEMON |
---|
173 | &Spell::EffectResurrectNew, //113 SPELL_EFFECT_RESURRECT_NEW |
---|
174 | &Spell::EffectTaunt, //114 SPELL_EFFECT_ATTACK_ME |
---|
175 | &Spell::EffectDurabilityDamagePCT, //115 SPELL_EFFECT_DURABILITY_DAMAGE_PCT |
---|
176 | &Spell::EffectSkinPlayerCorpse, //116 SPELL_EFFECT_SKIN_PLAYER_CORPSE one spell: Remove Insignia, bg usage, required special corpse flags... |
---|
177 | &Spell::EffectSpiritHeal, //117 SPELL_EFFECT_SPIRIT_HEAL one spell: Spirit Heal |
---|
178 | &Spell::EffectSkill, //118 SPELL_EFFECT_SKILL professions and more |
---|
179 | &Spell::EffectApplyAreaAura, //119 SPELL_EFFECT_APPLY_AREA_AURA_PET |
---|
180 | &Spell::EffectUnused, //120 SPELL_EFFECT_TELEPORT_GRAVEYARD one spell: Graveyard Teleport Test |
---|
181 | &Spell::EffectWeaponDmg, //121 SPELL_EFFECT_NORMALIZED_WEAPON_DMG |
---|
182 | &Spell::EffectUnused, //122 SPELL_EFFECT_122 unused |
---|
183 | &Spell::EffectSendTaxi, //123 SPELL_EFFECT_SEND_TAXI taxi/flight related (misc value is taxi path id) |
---|
184 | &Spell::EffectPlayerPull, //124 SPELL_EFFECT_PLAYER_PULL opposite of knockback effect (pulls player twoard caster) |
---|
185 | &Spell::EffectModifyThreatPercent, //125 SPELL_EFFECT_MODIFY_THREAT_PERCENT |
---|
186 | &Spell::EffectStealBeneficialBuff, //126 SPELL_EFFECT_STEAL_BENEFICIAL_BUFF spell steal effect? |
---|
187 | &Spell::EffectProspecting, //127 SPELL_EFFECT_PROSPECTING Prospecting spell |
---|
188 | &Spell::EffectApplyAreaAura, //128 SPELL_EFFECT_APPLY_AREA_AURA_FRIEND |
---|
189 | &Spell::EffectApplyAreaAura, //129 SPELL_EFFECT_APPLY_AREA_AURA_ENEMY |
---|
190 | &Spell::EffectNULL, //130 SPELL_EFFECT_REDIRECT_THREAT |
---|
191 | &Spell::EffectUnused, //131 SPELL_EFFECT_131 used in some test spells |
---|
192 | &Spell::EffectNULL, //132 SPELL_EFFECT_PLAY_MUSIC sound id in misc value |
---|
193 | &Spell::EffectUnlearnSpecialization, //133 SPELL_EFFECT_UNLEARN_SPECIALIZATION unlearn profession specialization |
---|
194 | &Spell::EffectKillCredit, //134 SPELL_EFFECT_KILL_CREDIT misc value is creature entry |
---|
195 | &Spell::EffectNULL, //135 SPELL_EFFECT_CALL_PET |
---|
196 | &Spell::EffectHealPct, //136 SPELL_EFFECT_HEAL_PCT |
---|
197 | &Spell::EffectEnergisePct, //137 SPELL_EFFECT_ENERGIZE_PCT |
---|
198 | &Spell::EffectNULL, //138 SPELL_EFFECT_138 Leap |
---|
199 | &Spell::EffectUnused, //139 SPELL_EFFECT_139 unused |
---|
200 | &Spell::EffectForceCast, //140 SPELL_EFFECT_FORCE_CAST |
---|
201 | &Spell::EffectNULL, //141 SPELL_EFFECT_141 damage and reduce speed? |
---|
202 | &Spell::EffectTriggerSpellWithValue, //142 SPELL_EFFECT_TRIGGER_SPELL_WITH_VALUE |
---|
203 | &Spell::EffectApplyAreaAura, //143 SPELL_EFFECT_APPLY_AREA_AURA_OWNER |
---|
204 | &Spell::EffectNULL, //144 SPELL_EFFECT_144 Spectral Blast |
---|
205 | &Spell::EffectNULL, //145 SPELL_EFFECT_145 Black Hole Effect |
---|
206 | &Spell::EffectUnused, //146 SPELL_EFFECT_146 unused |
---|
207 | &Spell::EffectQuestFail, //147 SPELL_EFFECT_QUEST_FAIL quest fail |
---|
208 | &Spell::EffectUnused, //148 SPELL_EFFECT_148 unused |
---|
209 | &Spell::EffectNULL, //149 SPELL_EFFECT_149 swoop |
---|
210 | &Spell::EffectUnused, //150 SPELL_EFFECT_150 unused |
---|
211 | &Spell::EffectTriggerRitualOfSummoning, //151 SPELL_EFFECT_TRIGGER_SPELL_2 |
---|
212 | &Spell::EffectNULL, //152 SPELL_EFFECT_152 summon Refer-a-Friend |
---|
213 | &Spell::EffectNULL, //153 SPELL_EFFECT_CREATE_PET misc value is creature entry |
---|
214 | }; |
---|
215 | |
---|
216 | void Spell::EffectNULL(uint32 /*i*/) |
---|
217 | { |
---|
218 | sLog.outDebug("WORLD: Spell Effect DUMMY"); |
---|
219 | } |
---|
220 | |
---|
221 | void Spell::EffectUnused(uint32 /*i*/) |
---|
222 | { |
---|
223 | // NOT USED BY ANY SPELL OR USELESS OR IMPLEMENTED IN DIFFERENT WAY IN MANGOS |
---|
224 | } |
---|
225 | |
---|
226 | void Spell::EffectResurrectNew(uint32 i) |
---|
227 | { |
---|
228 | if(!unitTarget || unitTarget->isAlive()) |
---|
229 | return; |
---|
230 | |
---|
231 | if(unitTarget->GetTypeId() != TYPEID_PLAYER) |
---|
232 | return; |
---|
233 | |
---|
234 | if(!unitTarget->IsInWorld()) |
---|
235 | return; |
---|
236 | |
---|
237 | Player* pTarget = ((Player*)unitTarget); |
---|
238 | |
---|
239 | if(pTarget->isRessurectRequested()) // already have one active request |
---|
240 | return; |
---|
241 | |
---|
242 | uint32 health = damage; |
---|
243 | uint32 mana = m_spellInfo->EffectMiscValue[i]; |
---|
244 | pTarget->setResurrectRequestData(m_caster->GetGUID(), m_caster->GetMapId(), m_caster->GetPositionX(), m_caster->GetPositionY(), m_caster->GetPositionZ(), health, mana); |
---|
245 | SendResurrectRequest(pTarget); |
---|
246 | } |
---|
247 | |
---|
248 | void Spell::EffectInstaKill(uint32 /*i*/) |
---|
249 | { |
---|
250 | if( !unitTarget || !unitTarget->isAlive() ) |
---|
251 | return; |
---|
252 | |
---|
253 | // Demonic Sacrifice |
---|
254 | if(m_spellInfo->Id==18788 && unitTarget->GetTypeId()==TYPEID_UNIT) |
---|
255 | { |
---|
256 | uint32 entry = unitTarget->GetEntry(); |
---|
257 | uint32 spellID; |
---|
258 | switch(entry) |
---|
259 | { |
---|
260 | case 416: spellID=18789; break; //imp |
---|
261 | case 417: spellID=18792; break; //fellhunter |
---|
262 | case 1860: spellID=18790; break; //void |
---|
263 | case 1863: spellID=18791; break; //succubus |
---|
264 | case 17252: spellID=35701; break; //fellguard |
---|
265 | default: |
---|
266 | sLog.outError("EffectInstaKill: Unhandled creature entry (%u) case.",entry); |
---|
267 | return; |
---|
268 | } |
---|
269 | |
---|
270 | m_caster->CastSpell(m_caster,spellID,true); |
---|
271 | } |
---|
272 | |
---|
273 | if(m_caster==unitTarget) // prevent interrupt message |
---|
274 | finish(); |
---|
275 | |
---|
276 | uint32 health = unitTarget->GetHealth(); |
---|
277 | m_caster->DealDamage(unitTarget, health, NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); |
---|
278 | } |
---|
279 | |
---|
280 | void Spell::EffectEnvirinmentalDMG(uint32 i) |
---|
281 | { |
---|
282 | uint32 absorb = 0; |
---|
283 | uint32 resist = 0; |
---|
284 | |
---|
285 | // Note: this hack with damage replace required until GO casting not implemented |
---|
286 | // environment damage spells already have around enemies targeting but this not help in case not existed GO casting support |
---|
287 | // currently each enemy selected explicitly and self cast damage, we prevent apply self casted spell bonuses/etc |
---|
288 | damage = m_spellInfo->EffectBasePoints[i]+m_spellInfo->EffectBaseDice[i]; |
---|
289 | |
---|
290 | m_caster->CalcAbsorbResist(m_caster,GetSpellSchoolMask(m_spellInfo), SPELL_DIRECT_DAMAGE, damage, &absorb, &resist); |
---|
291 | |
---|
292 | m_caster->SendSpellNonMeleeDamageLog(m_caster, m_spellInfo->Id, damage, GetSpellSchoolMask(m_spellInfo), absorb, resist, false, 0, false); |
---|
293 | if(m_caster->GetTypeId() == TYPEID_PLAYER) |
---|
294 | ((Player*)m_caster)->EnvironmentalDamage(m_caster->GetGUID(),DAMAGE_FIRE,damage); |
---|
295 | } |
---|
296 | |
---|
297 | void Spell::EffectSchoolDMG(uint32 effect_idx) |
---|
298 | { |
---|
299 | if( unitTarget && unitTarget->isAlive()) |
---|
300 | { |
---|
301 | switch(m_spellInfo->SpellFamilyName) |
---|
302 | { |
---|
303 | case SPELLFAMILY_GENERIC: |
---|
304 | { |
---|
305 | //Gore |
---|
306 | if(m_spellInfo->SpellIconID == 2269 ) |
---|
307 | { |
---|
308 | damage+= rand()%2 ? damage : 0; |
---|
309 | } |
---|
310 | |
---|
311 | switch(m_spellInfo->Id) // better way to check unknown |
---|
312 | { |
---|
313 | // Meteor like spells (divided damage to targets) |
---|
314 | case 24340: case 26558: case 28884: // Meteor |
---|
315 | case 36837: case 38903: case 41276: // Meteor |
---|
316 | case 26789: // Shard of the Fallen Star |
---|
317 | case 31436: // Malevolent Cleave |
---|
318 | case 35181: // Dive Bomb |
---|
319 | case 40810: case 43267: case 43268: // Saber Lash |
---|
320 | case 42384: // Brutal Swipe |
---|
321 | case 45150: // Meteor Slash |
---|
322 | { |
---|
323 | uint32 count = 0; |
---|
324 | for(std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit) |
---|
325 | if(ihit->effectMask & (1<<effect_idx)) |
---|
326 | ++count; |
---|
327 | |
---|
328 | damage /= count; // divide to all targets |
---|
329 | break; |
---|
330 | } |
---|
331 | // percent from health with min |
---|
332 | case 25599: // Thundercrash |
---|
333 | { |
---|
334 | damage = unitTarget->GetHealth() / 2; |
---|
335 | if(damage < 200) |
---|
336 | damage = 200; |
---|
337 | break; |
---|
338 | } |
---|
339 | } |
---|
340 | break; |
---|
341 | } |
---|
342 | |
---|
343 | case SPELLFAMILY_MAGE: |
---|
344 | { |
---|
345 | // Arcane Blast |
---|
346 | if(m_spellInfo->SpellFamilyFlags & 0x20000000LL) |
---|
347 | { |
---|
348 | m_caster->CastSpell(m_caster,36032,true); |
---|
349 | } |
---|
350 | break; |
---|
351 | } |
---|
352 | case SPELLFAMILY_WARRIOR: |
---|
353 | { |
---|
354 | // Bloodthirst |
---|
355 | if(m_spellInfo->SpellFamilyFlags & 0x40000000000LL) |
---|
356 | { |
---|
357 | damage = uint32(damage * (m_caster->GetTotalAttackPowerValue(BASE_ATTACK)) / 100); |
---|
358 | } |
---|
359 | // Shield Slam |
---|
360 | else if(m_spellInfo->SpellFamilyFlags & 0x100000000LL) |
---|
361 | damage += int32(m_caster->GetShieldBlockValue()); |
---|
362 | // Victory Rush |
---|
363 | else if(m_spellInfo->SpellFamilyFlags & 0x10000000000LL) |
---|
364 | { |
---|
365 | damage = uint32(damage * m_caster->GetTotalAttackPowerValue(BASE_ATTACK) / 100); |
---|
366 | m_caster->ModifyAuraState(AURA_STATE_WARRIOR_VICTORY_RUSH, false); |
---|
367 | } |
---|
368 | break; |
---|
369 | } |
---|
370 | case SPELLFAMILY_WARLOCK: |
---|
371 | { |
---|
372 | // Incinerate Rank 1 & 2 |
---|
373 | if((m_spellInfo->SpellFamilyFlags & 0x00004000000000LL) && m_spellInfo->SpellIconID==2128) |
---|
374 | { |
---|
375 | // Incinerate does more dmg (dmg*0.25) if the target is Immolated. |
---|
376 | if(unitTarget->HasAuraState(AURA_STATE_IMMOLATE)) |
---|
377 | damage += int32(damage*0.25); |
---|
378 | } |
---|
379 | break; |
---|
380 | } |
---|
381 | case SPELLFAMILY_DRUID: |
---|
382 | { |
---|
383 | // Ferocious Bite |
---|
384 | if((m_spellInfo->SpellFamilyFlags & 0x000800000) && m_spellInfo->SpellVisual==6587) |
---|
385 | { |
---|
386 | // converts each extra point of energy into ($f1+$AP/630) additional damage |
---|
387 | float multiple = m_caster->GetTotalAttackPowerValue(BASE_ATTACK) / 630 + m_spellInfo->DmgMultiplier[effect_idx]; |
---|
388 | damage += int32(m_caster->GetPower(POWER_ENERGY) * multiple); |
---|
389 | m_caster->SetPower(POWER_ENERGY,0); |
---|
390 | } |
---|
391 | // Rake |
---|
392 | else if(m_spellInfo->SpellFamilyFlags & 0x0000000000001000LL) |
---|
393 | { |
---|
394 | damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) / 100); |
---|
395 | } |
---|
396 | // Swipe |
---|
397 | else if(m_spellInfo->SpellFamilyFlags & 0x0010000000000000LL) |
---|
398 | { |
---|
399 | damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.08f); |
---|
400 | } |
---|
401 | // Starfire |
---|
402 | else if ( m_spellInfo->SpellFamilyFlags & 0x0004LL ) |
---|
403 | { |
---|
404 | Unit::AuraList const& m_OverrideClassScript = m_caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS); |
---|
405 | for(Unit::AuraList::const_iterator i = m_OverrideClassScript.begin(); i != m_OverrideClassScript.end(); ++i) |
---|
406 | { |
---|
407 | // Starfire Bonus (caster) |
---|
408 | switch((*i)->GetModifier()->m_miscvalue) |
---|
409 | { |
---|
410 | case 5481: // Nordrassil Regalia - bonus |
---|
411 | { |
---|
412 | Unit::AuraList const& m_periodicDamageAuras = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE); |
---|
413 | for(Unit::AuraList::const_iterator itr = m_periodicDamageAuras.begin(); itr != m_periodicDamageAuras.end(); ++itr) |
---|
414 | { |
---|
415 | // Moonfire or Insect Swarm (target debuff from any casters) |
---|
416 | if ( (*itr)->GetSpellProto()->SpellFamilyFlags & 0x00200002LL ) |
---|
417 | { |
---|
418 | int32 mod = (*i)->GetModifier()->m_amount; |
---|
419 | damage += damage*mod/100; |
---|
420 | break; |
---|
421 | } |
---|
422 | } |
---|
423 | break; |
---|
424 | } |
---|
425 | case 5148: //Improved Starfire - Ivory Idol of the Moongoddes Aura |
---|
426 | { |
---|
427 | damage += (*i)->GetModifier()->m_amount; |
---|
428 | break; |
---|
429 | } |
---|
430 | } |
---|
431 | } |
---|
432 | } |
---|
433 | //Mangle Bonus for the initial damage of Lacerate and Rake |
---|
434 | if((m_spellInfo->SpellFamilyFlags==0x0000000000001000LL && m_spellInfo->SpellIconID==494) || |
---|
435 | (m_spellInfo->SpellFamilyFlags==0x0000010000000000LL && m_spellInfo->SpellIconID==2246)) |
---|
436 | { |
---|
437 | Unit::AuraList const& mDummyAuras = unitTarget->GetAurasByType(SPELL_AURA_DUMMY); |
---|
438 | for(Unit::AuraList::const_iterator i = mDummyAuras.begin(); i != mDummyAuras.end(); ++i) |
---|
439 | if((*i)->GetSpellProto()->SpellFamilyFlags & 0x0000044000000000LL && (*i)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_DRUID) |
---|
440 | { |
---|
441 | damage = int32(damage*(100.0f+(*i)->GetModifier()->m_amount)/100.0f); |
---|
442 | break; |
---|
443 | } |
---|
444 | } |
---|
445 | break; |
---|
446 | } |
---|
447 | case SPELLFAMILY_ROGUE: |
---|
448 | { |
---|
449 | // Envenom |
---|
450 | if(m_caster->GetTypeId()==TYPEID_PLAYER && (m_spellInfo->SpellFamilyFlags & 0x800000000LL)) |
---|
451 | { |
---|
452 | // consume from stack dozes not more that have combo-points |
---|
453 | if(uint32 combo = ((Player*)m_caster)->GetComboPoints()) |
---|
454 | { |
---|
455 | // count consumed deadly poison doses at target |
---|
456 | uint32 doses = 0; |
---|
457 | |
---|
458 | // remove consumed poison doses |
---|
459 | Unit::AuraList const& auras = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE); |
---|
460 | for(Unit::AuraList::const_iterator itr = auras.begin(); itr!=auras.end() && combo;) |
---|
461 | { |
---|
462 | // Deadly poison (only attacker applied) |
---|
463 | if( (*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_ROGUE && ((*itr)->GetSpellProto()->SpellFamilyFlags & 0x10000) && |
---|
464 | (*itr)->GetSpellProto()->SpellVisual==5100 && (*itr)->GetCasterGUID()==m_caster->GetGUID() ) |
---|
465 | { |
---|
466 | --combo; |
---|
467 | ++doses; |
---|
468 | |
---|
469 | unitTarget->RemoveSingleAuraFromStack((*itr)->GetId(), (*itr)->GetEffIndex()); |
---|
470 | |
---|
471 | itr = auras.begin(); |
---|
472 | } |
---|
473 | else |
---|
474 | ++itr; |
---|
475 | } |
---|
476 | |
---|
477 | damage *= doses; |
---|
478 | damage += int32(((Player*)m_caster)->GetTotalAttackPowerValue(BASE_ATTACK) * 0.03f * doses); |
---|
479 | |
---|
480 | // Eviscerate and Envenom Bonus Damage (item set effect) |
---|
481 | if(m_caster->GetDummyAura(37169)) |
---|
482 | damage += ((Player*)m_caster)->GetComboPoints()*40; |
---|
483 | } |
---|
484 | } |
---|
485 | // Eviscerate |
---|
486 | else if((m_spellInfo->SpellFamilyFlags & 0x00020000LL) && m_caster->GetTypeId()==TYPEID_PLAYER) |
---|
487 | { |
---|
488 | if(uint32 combo = ((Player*)m_caster)->GetComboPoints()) |
---|
489 | { |
---|
490 | damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * combo * 0.03f); |
---|
491 | |
---|
492 | // Eviscerate and Envenom Bonus Damage (item set effect) |
---|
493 | if(m_caster->GetDummyAura(37169)) |
---|
494 | damage += combo*40; |
---|
495 | } |
---|
496 | } |
---|
497 | break; |
---|
498 | } |
---|
499 | case SPELLFAMILY_HUNTER: |
---|
500 | { |
---|
501 | // Mongoose Bite |
---|
502 | if((m_spellInfo->SpellFamilyFlags & 0x000000002) && m_spellInfo->SpellVisual==342) |
---|
503 | { |
---|
504 | damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.2); |
---|
505 | } |
---|
506 | // Arcane Shot |
---|
507 | else if((m_spellInfo->SpellFamilyFlags & 0x00000800) && m_spellInfo->maxLevel > 0) |
---|
508 | { |
---|
509 | damage += int32(m_caster->GetTotalAttackPowerValue(RANGED_ATTACK)*0.15); |
---|
510 | } |
---|
511 | // Steady Shot |
---|
512 | else if(m_spellInfo->SpellFamilyFlags & 0x100000000LL) |
---|
513 | { |
---|
514 | int32 base = irand((int32)m_caster->GetWeaponDamageRange(RANGED_ATTACK, MINDAMAGE),(int32)m_caster->GetWeaponDamageRange(RANGED_ATTACK, MAXDAMAGE)); |
---|
515 | damage += int32(float(base)/m_caster->GetAttackTime(RANGED_ATTACK)*2800 + m_caster->GetTotalAttackPowerValue(RANGED_ATTACK)*0.2f); |
---|
516 | } |
---|
517 | //Explosive Trap Effect |
---|
518 | else if(m_spellInfo->SpellFamilyFlags & 0x00000004) |
---|
519 | { |
---|
520 | damage += int32(m_caster->GetTotalAttackPowerValue(RANGED_ATTACK)*0.1); |
---|
521 | } |
---|
522 | break; |
---|
523 | } |
---|
524 | case SPELLFAMILY_PALADIN: |
---|
525 | { |
---|
526 | //Judgement of Vengeance |
---|
527 | if((m_spellInfo->SpellFamilyFlags & 0x800000000LL) && m_spellInfo->SpellIconID==2292) |
---|
528 | { |
---|
529 | uint32 stacks = 0; |
---|
530 | Unit::AuraList const& auras = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE); |
---|
531 | for(Unit::AuraList::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr) |
---|
532 | if((*itr)->GetId() == 31803 && (*itr)->GetCasterGUID()==m_caster->GetGUID()) |
---|
533 | ++stacks; |
---|
534 | if(!stacks) |
---|
535 | //No damage if the target isn't affected by this |
---|
536 | damage = -1; |
---|
537 | else |
---|
538 | damage *= stacks; |
---|
539 | } |
---|
540 | break; |
---|
541 | } |
---|
542 | } |
---|
543 | |
---|
544 | if(damage >= 0) |
---|
545 | { |
---|
546 | uint32 finalDamage; |
---|
547 | if(m_originalCaster) // m_caster only passive source of cast |
---|
548 | finalDamage = m_originalCaster->SpellNonMeleeDamageLog(unitTarget, m_spellInfo->Id, damage, m_IsTriggeredSpell, true); |
---|
549 | else |
---|
550 | finalDamage = m_caster->SpellNonMeleeDamageLog(unitTarget, m_spellInfo->Id, damage, m_IsTriggeredSpell, true); |
---|
551 | |
---|
552 | // post effects |
---|
553 | switch(m_spellInfo->SpellFamilyName) |
---|
554 | { |
---|
555 | case SPELLFAMILY_WARRIOR: |
---|
556 | { |
---|
557 | // Bloodthirst |
---|
558 | if(m_spellInfo->SpellFamilyFlags & 0x40000000000LL) |
---|
559 | { |
---|
560 | uint32 BTAura = 0; |
---|
561 | switch(m_spellInfo->Id) |
---|
562 | { |
---|
563 | case 23881: BTAura = 23885; break; |
---|
564 | case 23892: BTAura = 23886; break; |
---|
565 | case 23893: BTAura = 23887; break; |
---|
566 | case 23894: BTAura = 23888; break; |
---|
567 | case 25251: BTAura = 25252; break; |
---|
568 | case 30335: BTAura = 30339; break; |
---|
569 | default: |
---|
570 | sLog.outError("Spell::EffectSchoolDMG: Spell %u not handled in BTAura",m_spellInfo->Id); |
---|
571 | break; |
---|
572 | } |
---|
573 | |
---|
574 | if (BTAura) |
---|
575 | m_caster->CastSpell(m_caster,BTAura,true); |
---|
576 | } |
---|
577 | break; |
---|
578 | } |
---|
579 | case SPELLFAMILY_PRIEST: |
---|
580 | { |
---|
581 | // Shadow Word: Death |
---|
582 | if(finalDamage > 0 && (m_spellInfo->SpellFamilyFlags & 0x0000000200000000LL) && unitTarget->isAlive()) |
---|
583 | // deals damage equal to damage done to caster if victim is not killed |
---|
584 | m_caster->SpellNonMeleeDamageLog( m_caster, m_spellInfo->Id, finalDamage, m_IsTriggeredSpell, false); |
---|
585 | |
---|
586 | break; |
---|
587 | } |
---|
588 | case SPELLFAMILY_PALADIN: |
---|
589 | { |
---|
590 | // Judgement of Blood |
---|
591 | if(finalDamage > 0 && (m_spellInfo->SpellFamilyFlags & 0x0000000800000000LL) && m_spellInfo->SpellIconID==153) |
---|
592 | { |
---|
593 | int32 damagePoint = finalDamage * 33 / 100; |
---|
594 | m_caster->CastCustomSpell(m_caster, 32220, &damagePoint, NULL, NULL, true); |
---|
595 | } |
---|
596 | break; |
---|
597 | } |
---|
598 | } |
---|
599 | } |
---|
600 | } |
---|
601 | } |
---|
602 | |
---|
603 | void Spell::EffectDummy(uint32 i) |
---|
604 | { |
---|
605 | if(!unitTarget && !gameObjTarget && !itemTarget) |
---|
606 | return; |
---|
607 | |
---|
608 | // selection by spell family |
---|
609 | switch(m_spellInfo->SpellFamilyName) |
---|
610 | { |
---|
611 | case SPELLFAMILY_GENERIC: |
---|
612 | // Gnomish Poultryizer trinket |
---|
613 | switch(m_spellInfo->Id ) |
---|
614 | { |
---|
615 | case 8063: // Deviate Fish |
---|
616 | { |
---|
617 | if(m_caster->GetTypeId() != TYPEID_PLAYER) |
---|
618 | return; |
---|
619 | |
---|
620 | uint32 spell_id = 0; |
---|
621 | switch(urand(1,5)) |
---|
622 | { |
---|
623 | case 1: spell_id = 8064; break; // Sleepy |
---|
624 | case 2: spell_id = 8065; break; // Invigorate |
---|
625 | case 3: spell_id = 8066; break; // Shrink |
---|
626 | case 4: spell_id = 8067; break; // Party Time! |
---|
627 | case 5: spell_id = 8068; break; // Healthy Spirit |
---|
628 | } |
---|
629 | m_caster->CastSpell(m_caster,spell_id,true,NULL); |
---|
630 | return; |
---|
631 | } |
---|
632 | case 8213: // Savory Deviate Delight |
---|
633 | { |
---|
634 | if(m_caster->GetTypeId() != TYPEID_PLAYER) |
---|
635 | return; |
---|
636 | |
---|
637 | uint32 spell_id = 0; |
---|
638 | switch(urand(1,2)) |
---|
639 | { |
---|
640 | // Flip Out - ninja |
---|
641 | case 1: spell_id = (m_caster->getGender() == GENDER_MALE ? 8219 : 8220); break; |
---|
642 | // Yaaarrrr - pirate |
---|
643 | case 2: spell_id = (m_caster->getGender() == GENDER_MALE ? 8221 : 8222); break; |
---|
644 | } |
---|
645 | m_caster->CastSpell(m_caster,spell_id,true,NULL); |
---|
646 | return; |
---|
647 | } |
---|
648 | case 8593: // Symbol of life (restore creature to life) |
---|
649 | case 31225: // Shimmering Vessel (restore creature to life) |
---|
650 | { |
---|
651 | if(!unitTarget || unitTarget->GetTypeId()!=TYPEID_UNIT) |
---|
652 | return; |
---|
653 | ((Creature*)unitTarget)->setDeathState(JUST_ALIVED); |
---|
654 | return; |
---|
655 | } |
---|
656 | case 12162: // Deep wounds |
---|
657 | case 12850: // (now good common check for this spells) |
---|
658 | case 12868: |
---|
659 | { |
---|
660 | if(!unitTarget) |
---|
661 | return; |
---|
662 | |
---|
663 | float damage; |
---|
664 | // DW should benefit of attack power, damage percent mods etc. |
---|
665 | // TODO: check if using offhand damage is correct and if it should be divided by 2 |
---|
666 | if (m_caster->haveOffhandWeapon() && m_caster->getAttackTimer(BASE_ATTACK) > m_caster->getAttackTimer(OFF_ATTACK)) |
---|
667 | damage = (m_caster->GetFloatValue(UNIT_FIELD_MINOFFHANDDAMAGE) + m_caster->GetFloatValue(UNIT_FIELD_MAXOFFHANDDAMAGE))/2; |
---|
668 | else |
---|
669 | damage = (m_caster->GetFloatValue(UNIT_FIELD_MINDAMAGE) + m_caster->GetFloatValue(UNIT_FIELD_MAXDAMAGE))/2; |
---|
670 | |
---|
671 | switch (m_spellInfo->Id) |
---|
672 | { |
---|
673 | case 12850: damage *= 0.2f; break; |
---|
674 | case 12162: damage *= 0.4f; break; |
---|
675 | case 12868: damage *= 0.6f; break; |
---|
676 | default: |
---|
677 | sLog.outError("Spell::EffectDummy: Spell %u not handled in DW",m_spellInfo->Id); |
---|
678 | return; |
---|
679 | }; |
---|
680 | |
---|
681 | int32 deepWoundsDotBasePoints0 = int32(damage / 4); |
---|
682 | m_caster->CastCustomSpell(unitTarget, 12721, &deepWoundsDotBasePoints0, NULL, NULL, true, NULL); |
---|
683 | return; |
---|
684 | } |
---|
685 | case 12975: //Last Stand |
---|
686 | { |
---|
687 | int32 healthModSpellBasePoints0 = int32(m_caster->GetMaxHealth()*0.3); |
---|
688 | m_caster->CastCustomSpell(m_caster, 12976, &healthModSpellBasePoints0, NULL, NULL, true, NULL); |
---|
689 | return; |
---|
690 | } |
---|
691 | case 13120: // net-o-matic |
---|
692 | { |
---|
693 | if(!unitTarget) |
---|
694 | return; |
---|
695 | |
---|
696 | uint32 spell_id = 0; |
---|
697 | |
---|
698 | uint32 roll = urand(0, 99); |
---|
699 | |
---|
700 | if(roll < 2) // 2% for 30 sec self root (off-like chance unknown) |
---|
701 | spell_id = 16566; |
---|
702 | else if(roll < 4) // 2% for 20 sec root, charge to target (off-like chance unknown) |
---|
703 | spell_id = 13119; |
---|
704 | else // normal root |
---|
705 | spell_id = 13099; |
---|
706 | |
---|
707 | m_caster->CastSpell(unitTarget,spell_id,true,NULL); |
---|
708 | return; |
---|
709 | } |
---|
710 | case 13567: // Dummy Trigger |
---|
711 | { |
---|
712 | // can be used for different aura triggreing, so select by aura |
---|
713 | if(!m_triggeredByAuraSpell || !unitTarget) |
---|
714 | return; |
---|
715 | |
---|
716 | switch(m_triggeredByAuraSpell->Id) |
---|
717 | { |
---|
718 | case 26467: // Persistent Shield |
---|
719 | m_caster->CastCustomSpell(unitTarget, 26470, &damage, NULL, NULL, true); |
---|
720 | break; |
---|
721 | default: |
---|
722 | sLog.outError("EffectDummy: Non-handled case for spell 13567 for triggered aura %u",m_triggeredByAuraSpell->Id); |
---|
723 | break; |
---|
724 | } |
---|
725 | return; |
---|
726 | } |
---|
727 | case 14185: // Preparation Rogue |
---|
728 | { |
---|
729 | if(m_caster->GetTypeId()!=TYPEID_PLAYER) |
---|
730 | return; |
---|
731 | |
---|
732 | //immediately finishes the cooldown on certain Rogue abilities |
---|
733 | const PlayerSpellMap& sp_list = ((Player *)m_caster)->GetSpellMap(); |
---|
734 | for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr) |
---|
735 | { |
---|
736 | uint32 classspell = itr->first; |
---|
737 | SpellEntry const *spellInfo = sSpellStore.LookupEntry(classspell); |
---|
738 | |
---|
739 | if (spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && (spellInfo->SpellFamilyFlags & 0x26000000860LL)) |
---|
740 | { |
---|
741 | ((Player*)m_caster)->RemoveSpellCooldown(classspell); |
---|
742 | |
---|
743 | WorldPacket data(SMSG_CLEAR_COOLDOWN, (4+8)); |
---|
744 | data << uint32(classspell); |
---|
745 | data << uint64(m_caster->GetGUID()); |
---|
746 | ((Player*)m_caster)->GetSession()->SendPacket(&data); |
---|
747 | } |
---|
748 | } |
---|
749 | return; |
---|
750 | } |
---|
751 | case 15998: // Capture Worg Pup |
---|
752 | case 29435: // Capture Female Kaliri Hatchling |
---|
753 | { |
---|
754 | if(!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT) |
---|
755 | return; |
---|
756 | |
---|
757 | Creature* creatureTarget = (Creature*)unitTarget; |
---|
758 | creatureTarget->setDeathState(JUST_DIED); |
---|
759 | creatureTarget->RemoveCorpse(); |
---|
760 | creatureTarget->SetHealth(0); // just for nice GM-mode view |
---|
761 | return; |
---|
762 | } |
---|
763 | case 16589: // Noggenfogger Elixir |
---|
764 | { |
---|
765 | if(m_caster->GetTypeId()!=TYPEID_PLAYER) |
---|
766 | return; |
---|
767 | |
---|
768 | uint32 spell_id = 0; |
---|
769 | switch(urand(1,3)) |
---|
770 | { |
---|
771 | case 1: spell_id = 16595; break; |
---|
772 | case 2: spell_id = 16593; break; |
---|
773 | default:spell_id = 16591; break; |
---|
774 | } |
---|
775 | |
---|
776 | m_caster->CastSpell(m_caster,spell_id,true,NULL); |
---|
777 | return; |
---|
778 | } |
---|
779 | case 17251: // Spirit Healer Res |
---|
780 | { |
---|
781 | if(!unitTarget || !m_originalCaster) |
---|
782 | return; |
---|
783 | |
---|
784 | if(m_originalCaster->GetTypeId() == TYPEID_PLAYER) |
---|
785 | { |
---|
786 | WorldPacket data(SMSG_SPIRIT_HEALER_CONFIRM, 8); |
---|
787 | data << unitTarget->GetGUID(); |
---|
788 | ((Player*)m_originalCaster)->GetSession()->SendPacket( &data ); |
---|
789 | } |
---|
790 | return; |
---|
791 | } |
---|
792 | case 17271: // Test Fetid Skull |
---|
793 | { |
---|
794 | if(!itemTarget && m_caster->GetTypeId()!=TYPEID_PLAYER) |
---|
795 | return; |
---|
796 | |
---|
797 | uint32 spell_id = roll_chance_i(50) ? 17269 : 17270; |
---|
798 | |
---|
799 | m_caster->CastSpell(m_caster,spell_id,true,NULL); |
---|
800 | return; |
---|
801 | } |
---|
802 | case 20577: // Cannibalize |
---|
803 | if (unitTarget) |
---|
804 | m_caster->CastSpell(m_caster,20578,false,NULL); |
---|
805 | return; |
---|
806 | case 23019: // Crystal Prison Dummy DND |
---|
807 | { |
---|
808 | if(!unitTarget || !unitTarget->isAlive() || unitTarget->GetTypeId() != TYPEID_UNIT || ((Creature*)unitTarget)->isPet()) |
---|
809 | return; |
---|
810 | |
---|
811 | Creature* creatureTarget = (Creature*)unitTarget; |
---|
812 | if(creatureTarget->isPet()) |
---|
813 | return; |
---|
814 | |
---|
815 | creatureTarget->setDeathState(JUST_DIED); |
---|
816 | creatureTarget->RemoveCorpse(); |
---|
817 | creatureTarget->SetHealth(0); // just for nice GM-mode view |
---|
818 | |
---|
819 | GameObject* pGameObj = new GameObject; |
---|
820 | |
---|
821 | Map *map = creatureTarget->GetMap(); |
---|
822 | |
---|
823 | if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), 179644, map, |
---|
824 | creatureTarget->GetPositionX(), creatureTarget->GetPositionY(), creatureTarget->GetPositionZ(), |
---|
825 | creatureTarget->GetOrientation(), 0, 0, 0, 0, 100, 1) ) |
---|
826 | { |
---|
827 | delete pGameObj; |
---|
828 | return; |
---|
829 | } |
---|
830 | |
---|
831 | pGameObj->SetRespawnTime(creatureTarget->GetRespawnTime()-time(NULL)); |
---|
832 | pGameObj->SetOwnerGUID(m_caster->GetGUID() ); |
---|
833 | pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel() ); |
---|
834 | pGameObj->SetSpellId(m_spellInfo->Id); |
---|
835 | |
---|
836 | DEBUG_LOG("AddObject at SpellEfects.cpp EffectDummy\n"); |
---|
837 | map->Add(pGameObj); |
---|
838 | |
---|
839 | WorldPacket data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE, 8); |
---|
840 | data << uint64(pGameObj->GetGUID()); |
---|
841 | m_caster->SendMessageToSet(&data,true); |
---|
842 | |
---|
843 | return; |
---|
844 | } |
---|
845 | case 23074: // Arc. Dragonling |
---|
846 | if (!m_CastItem) return; |
---|
847 | m_caster->CastSpell(m_caster,19804,true,m_CastItem); |
---|
848 | return; |
---|
849 | case 23075: // Mithril Mechanical Dragonling |
---|
850 | if (!m_CastItem) return; |
---|
851 | m_caster->CastSpell(m_caster,12749,true,m_CastItem); |
---|
852 | return; |
---|
853 | case 23076: // Mechanical Dragonling |
---|
854 | if (!m_CastItem) return; |
---|
855 | m_caster->CastSpell(m_caster,4073,true,m_CastItem); |
---|
856 | return; |
---|
857 | case 23133: // Gnomish Battle Chicken |
---|
858 | if (!m_CastItem) return; |
---|
859 | m_caster->CastSpell(m_caster,13166,true,m_CastItem); |
---|
860 | return; |
---|
861 | case 23448: // Ultrasafe Transporter: Gadgetzan - backfires |
---|
862 | { |
---|
863 | int32 r = irand(0, 119); |
---|
864 | if ( r < 20 ) // 1/6 polymorph |
---|
865 | m_caster->CastSpell(m_caster,23444,true); |
---|
866 | else if ( r < 100 ) // 4/6 evil twin |
---|
867 | m_caster->CastSpell(m_caster,23445,true); |
---|
868 | else // 1/6 miss the target |
---|
869 | m_caster->CastSpell(m_caster,36902,true); |
---|
870 | return; |
---|
871 | } |
---|
872 | case 23453: // Ultrasafe Transporter: Gadgetzan |
---|
873 | if ( roll_chance_i(50) ) // success |
---|
874 | m_caster->CastSpell(m_caster,23441,true); |
---|
875 | else // failure |
---|
876 | m_caster->CastSpell(m_caster,23446,true); |
---|
877 | return; |
---|
878 | case 23645: // Hourglass Sand |
---|
879 | m_caster->RemoveAurasDueToSpell(23170); |
---|
880 | return; |
---|
881 | case 23725: // Gift of Life (warrior bwl trinket) |
---|
882 | m_caster->CastSpell(m_caster,23782,true); |
---|
883 | m_caster->CastSpell(m_caster,23783,true); |
---|
884 | return; |
---|
885 | case 25860: // Reindeer Transformation |
---|
886 | { |
---|
887 | if (!m_caster->HasAuraType(SPELL_AURA_MOUNTED)) |
---|
888 | return; |
---|
889 | |
---|
890 | float flyspeed = m_caster->GetSpeedRate(MOVE_FLY); |
---|
891 | float speed = m_caster->GetSpeedRate(MOVE_RUN); |
---|
892 | |
---|
893 | m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED); |
---|
894 | |
---|
895 | //5 different spells used depending on mounted speed and if mount can fly or not |
---|
896 | if (flyspeed >= 4.1f) |
---|
897 | m_caster->CastSpell(m_caster, 44827, true); //310% flying Reindeer |
---|
898 | else if (flyspeed >= 3.8f) |
---|
899 | m_caster->CastSpell(m_caster, 44825, true); //280% flying Reindeer |
---|
900 | else if (flyspeed >= 1.6f) |
---|
901 | m_caster->CastSpell(m_caster, 44824, true); //60% flying Reindeer |
---|
902 | else if (speed >= 2.0f) |
---|
903 | m_caster->CastSpell(m_caster, 25859, true); //100% ground Reindeer |
---|
904 | else |
---|
905 | m_caster->CastSpell(m_caster, 25858, true); //60% ground Reindeer |
---|
906 | |
---|
907 | return; |
---|
908 | } |
---|
909 | //case 26074: // Holiday Cheer |
---|
910 | // return; -- implemented at client side |
---|
911 | case 28006: // Arcane Cloaking |
---|
912 | { |
---|
913 | if( unitTarget->GetTypeId() == TYPEID_PLAYER ) |
---|
914 | m_caster->CastSpell(unitTarget,29294,true); |
---|
915 | return; |
---|
916 | } |
---|
917 | case 28730: // Arcane Torrent (Mana) |
---|
918 | { |
---|
919 | int32 count = 0; |
---|
920 | Unit::AuraList const& m_dummyAuras = m_caster->GetAurasByType(SPELL_AURA_DUMMY); |
---|
921 | for(Unit::AuraList::const_iterator i = m_dummyAuras.begin(); i != m_dummyAuras.end(); ++i) |
---|
922 | if ((*i)->GetId() == 28734) |
---|
923 | ++count; |
---|
924 | if (count) |
---|
925 | { |
---|
926 | m_caster->RemoveAurasDueToSpell(28734); |
---|
927 | int32 bp = damage * count; |
---|
928 | m_caster->CastCustomSpell(m_caster, 28733, &bp, NULL, NULL, true); |
---|
929 | } |
---|
930 | return; |
---|
931 | } |
---|
932 | case 29200: // Purify Helboar Meat |
---|
933 | { |
---|
934 | if( m_caster->GetTypeId() != TYPEID_PLAYER ) |
---|
935 | return; |
---|
936 | |
---|
937 | uint32 spell_id = roll_chance_i(50) ? 29277 : 29278; |
---|
938 | |
---|
939 | m_caster->CastSpell(m_caster,spell_id,true,NULL); |
---|
940 | return; |
---|
941 | } |
---|
942 | case 29858: // Soulshatter |
---|
943 | if (unitTarget && unitTarget->GetTypeId() == TYPEID_UNIT && unitTarget->IsHostileTo(m_caster)) |
---|
944 | m_caster->CastSpell(unitTarget,32835,true); |
---|
945 | return; |
---|
946 | case 30458: // Nigh Invulnerability |
---|
947 | if (!m_CastItem) return; |
---|
948 | if(roll_chance_i(86)) // success |
---|
949 | m_caster->CastSpell(m_caster, 30456, true, m_CastItem); |
---|
950 | else // backfire in 14% casts |
---|
951 | m_caster->CastSpell(m_caster, 30457, true, m_CastItem); |
---|
952 | return; |
---|
953 | case 30507: // Poultryizer |
---|
954 | if (!m_CastItem) return; |
---|
955 | if(roll_chance_i(80)) // success |
---|
956 | m_caster->CastSpell(unitTarget, 30501, true, m_CastItem); |
---|
957 | else // backfire 20% |
---|
958 | m_caster->CastSpell(unitTarget, 30504, true, m_CastItem); |
---|
959 | return; |
---|
960 | case 33060: // Make a Wish |
---|
961 | { |
---|
962 | if(m_caster->GetTypeId()!=TYPEID_PLAYER) |
---|
963 | return; |
---|
964 | |
---|
965 | uint32 spell_id = 0; |
---|
966 | |
---|
967 | switch(urand(1,5)) |
---|
968 | { |
---|
969 | case 1: spell_id = 33053; break; |
---|
970 | case 2: spell_id = 33057; break; |
---|
971 | case 3: spell_id = 33059; break; |
---|
972 | case 4: spell_id = 33062; break; |
---|
973 | case 5: spell_id = 33064; break; |
---|
974 | } |
---|
975 | |
---|
976 | m_caster->CastSpell(m_caster,spell_id,true,NULL); |
---|
977 | return; |
---|
978 | } |
---|
979 | case 35745: |
---|
980 | { |
---|
981 | uint32 spell_id; |
---|
982 | switch(m_caster->GetAreaId()) |
---|
983 | { |
---|
984 | case 3900: spell_id = 35743; break; |
---|
985 | case 3742: spell_id = 35744; break; |
---|
986 | default: return; |
---|
987 | } |
---|
988 | |
---|
989 | m_caster->CastSpell(m_caster,spell_id,true); |
---|
990 | return; |
---|
991 | } |
---|
992 | case 37674: // Chaos Blast |
---|
993 | if(unitTarget) |
---|
994 | m_caster->CastSpell(unitTarget,37675,true); |
---|
995 | return; |
---|
996 | case 44875: // Complete Raptor Capture |
---|
997 | { |
---|
998 | if(!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT) |
---|
999 | return; |
---|
1000 | |
---|
1001 | Creature* creatureTarget = (Creature*)unitTarget; |
---|
1002 | |
---|
1003 | creatureTarget->setDeathState(JUST_DIED); |
---|
1004 | creatureTarget->RemoveCorpse(); |
---|
1005 | creatureTarget->SetHealth(0); // just for nice GM-mode view |
---|
1006 | |
---|
1007 | //cast spell Raptor Capture Credit |
---|
1008 | m_caster->CastSpell(m_caster,42337,true,NULL); |
---|
1009 | return; |
---|
1010 | } |
---|
1011 | case 37573: //Temporal Phase Modulator |
---|
1012 | { |
---|
1013 | if(!unitTarget) |
---|
1014 | return; |
---|
1015 | |
---|
1016 | TemporarySummon* tempSummon = dynamic_cast<TemporarySummon*>(unitTarget); |
---|
1017 | if(!tempSummon) |
---|
1018 | return; |
---|
1019 | |
---|
1020 | uint32 health = tempSummon->GetHealth(); |
---|
1021 | const uint32 entry_list[6] = {21821, 21820, 21817}; |
---|
1022 | |
---|
1023 | float x = tempSummon->GetPositionX(); |
---|
1024 | float y = tempSummon->GetPositionY(); |
---|
1025 | float z = tempSummon->GetPositionZ(); |
---|
1026 | float o = tempSummon->GetOrientation(); |
---|
1027 | |
---|
1028 | tempSummon->UnSummon(); |
---|
1029 | |
---|
1030 | Creature* pCreature = m_caster->SummonCreature(entry_list[urand(0, 2)], x, y, z, o,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,180000); |
---|
1031 | if (!pCreature) |
---|
1032 | return; |
---|
1033 | |
---|
1034 | pCreature->SetHealth(health); |
---|
1035 | |
---|
1036 | if(pCreature->AI()) |
---|
1037 | pCreature->AI()->AttackStart(m_caster); |
---|
1038 | |
---|
1039 | return; |
---|
1040 | } |
---|
1041 | case 34665: //Administer Antidote |
---|
1042 | { |
---|
1043 | if(!unitTarget || m_caster->GetTypeId() != TYPEID_PLAYER ) |
---|
1044 | return; |
---|
1045 | |
---|
1046 | if(!unitTarget) |
---|
1047 | return; |
---|
1048 | |
---|
1049 | TemporarySummon* tempSummon = dynamic_cast<TemporarySummon*>(unitTarget); |
---|
1050 | if(!tempSummon) |
---|
1051 | return; |
---|
1052 | |
---|
1053 | uint32 health = tempSummon->GetHealth(); |
---|
1054 | |
---|
1055 | float x = tempSummon->GetPositionX(); |
---|
1056 | float y = tempSummon->GetPositionY(); |
---|
1057 | float z = tempSummon->GetPositionZ(); |
---|
1058 | float o = tempSummon->GetOrientation(); |
---|
1059 | tempSummon->UnSummon(); |
---|
1060 | |
---|
1061 | Creature* pCreature = m_caster->SummonCreature(16992, x, y, z, o,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,180000); |
---|
1062 | if (!pCreature) |
---|
1063 | return; |
---|
1064 | |
---|
1065 | pCreature->SetHealth(health); |
---|
1066 | ((Player*)m_caster)->KilledMonster(16992,pCreature->GetGUID()); |
---|
1067 | |
---|
1068 | if (pCreature->AI()) |
---|
1069 | pCreature->AI()->AttackStart(m_caster); |
---|
1070 | |
---|
1071 | return; |
---|
1072 | } |
---|
1073 | case 44997: // Converting Sentry |
---|
1074 | { |
---|
1075 | //Converted Sentry Credit |
---|
1076 | m_caster->CastSpell(m_caster, 45009, true); |
---|
1077 | return; |
---|
1078 | } |
---|
1079 | case 45030: // Impale Emissary |
---|
1080 | { |
---|
1081 | // Emissary of Hate Credit |
---|
1082 | m_caster->CastSpell(m_caster, 45088, true); |
---|
1083 | return; |
---|
1084 | } |
---|
1085 | case 50243: // Teach Language |
---|
1086 | { |
---|
1087 | if(m_caster->GetTypeId() != TYPEID_PLAYER) |
---|
1088 | return; |
---|
1089 | |
---|
1090 | // spell has a 1/3 chance to trigger one of the below |
---|
1091 | if(roll_chance_i(66)) |
---|
1092 | return; |
---|
1093 | if(((Player*)m_caster)->GetTeam() == ALLIANCE) |
---|
1094 | { |
---|
1095 | // 1000001 - gnomish binary |
---|
1096 | m_caster->CastSpell(m_caster, 50242, true); |
---|
1097 | } |
---|
1098 | else |
---|
1099 | { |
---|
1100 | // 01001000 - goblin binary |
---|
1101 | m_caster->CastSpell(m_caster, 50246, true); |
---|
1102 | } |
---|
1103 | |
---|
1104 | return; |
---|
1105 | } |
---|
1106 | case 51582: //Rocket Boots Engaged (Rocket Boots Xtreme and Rocket Boots Xtreme Lite) |
---|
1107 | { |
---|
1108 | if(m_caster->GetTypeId() != TYPEID_PLAYER) |
---|
1109 | return; |
---|
1110 | |
---|
1111 | if(BattleGround* bg = ((Player*)m_caster)->GetBattleGround()) |
---|
1112 | bg->EventPlayerDroppedFlag((Player*)m_caster); |
---|
1113 | |
---|
1114 | m_caster->CastSpell(m_caster, 30452, true, NULL); |
---|
1115 | return; |
---|
1116 | } |
---|
1117 | } |
---|
1118 | |
---|
1119 | //All IconID Check in there |
---|
1120 | switch(m_spellInfo->SpellIconID) |
---|
1121 | { |
---|
1122 | // Berserking (troll racial traits) |
---|
1123 | case 1661: |
---|
1124 | { |
---|
1125 | uint32 healthPerc = uint32((float(m_caster->GetHealth())/m_caster->GetMaxHealth())*100); |
---|
1126 | int32 melee_mod = 10; |
---|
1127 | if (healthPerc <= 40) |
---|
1128 | melee_mod = 30; |
---|
1129 | if (healthPerc < 100 && healthPerc > 40) |
---|
1130 | melee_mod = 10+(100-healthPerc)/3; |
---|
1131 | |
---|
1132 | int32 hasteModBasePoints0 = melee_mod; // (EffectBasePoints[0]+1)-1+(5-melee_mod) = (melee_mod-1+1)-1+5-melee_mod = 5-1 |
---|
1133 | int32 hasteModBasePoints1 = (5-melee_mod); |
---|
1134 | int32 hasteModBasePoints2 = 5; |
---|
1135 | |
---|
1136 | // FIXME: custom spell required this aura state by some unknown reason, we not need remove it anyway |
---|
1137 | m_caster->ModifyAuraState(AURA_STATE_BERSERKING,true); |
---|
1138 | m_caster->CastCustomSpell(m_caster,26635,&hasteModBasePoints0,&hasteModBasePoints1,&hasteModBasePoints2,true,NULL); |
---|
1139 | return; |
---|
1140 | } |
---|
1141 | } |
---|
1142 | break; |
---|
1143 | case SPELLFAMILY_MAGE: |
---|
1144 | switch(m_spellInfo->Id ) |
---|
1145 | { |
---|
1146 | case 11958: // Cold Snap |
---|
1147 | { |
---|
1148 | if(m_caster->GetTypeId()!=TYPEID_PLAYER) |
---|
1149 | return; |
---|
1150 | |
---|
1151 | // immediately finishes the cooldown on Frost spells |
---|
1152 | const PlayerSpellMap& sp_list = ((Player *)m_caster)->GetSpellMap(); |
---|
1153 | for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr) |
---|
1154 | { |
---|
1155 | if (itr->second->state == PLAYERSPELL_REMOVED) |
---|
1156 | continue; |
---|
1157 | |
---|
1158 | uint32 classspell = itr->first; |
---|
1159 | SpellEntry const *spellInfo = sSpellStore.LookupEntry(classspell); |
---|
1160 | |
---|
1161 | if( spellInfo->SpellFamilyName == SPELLFAMILY_MAGE && |
---|
1162 | (GetSpellSchoolMask(spellInfo) & SPELL_SCHOOL_MASK_FROST) && |
---|
1163 | spellInfo->Id != 11958 && GetSpellRecoveryTime(spellInfo) > 0 ) |
---|
1164 | { |
---|
1165 | ((Player*)m_caster)->RemoveSpellCooldown(classspell); |
---|
1166 | |
---|
1167 | WorldPacket data(SMSG_CLEAR_COOLDOWN, (4+8)); |
---|
1168 | data << uint32(classspell); |
---|
1169 | data << uint64(m_caster->GetGUID()); |
---|
1170 | ((Player*)m_caster)->GetSession()->SendPacket(&data); |
---|
1171 | } |
---|
1172 | } |
---|
1173 | return; |
---|
1174 | } |
---|
1175 | case 32826: |
---|
1176 | { |
---|
1177 | if ( unitTarget && unitTarget->GetTypeId() == TYPEID_UNIT ) |
---|
1178 | { |
---|
1179 | //Polymorph Cast Visual Rank 1 |
---|
1180 | const uint32 spell_list[6] = {32813, 32816, 32817, 32818, 32819, 32820}; |
---|
1181 | unitTarget->CastSpell( unitTarget, spell_list[urand(0, 5)], true); |
---|
1182 | } |
---|
1183 | return; |
---|
1184 | } |
---|
1185 | } |
---|
1186 | break; |
---|
1187 | case SPELLFAMILY_WARRIOR: |
---|
1188 | // Charge |
---|
1189 | if(m_spellInfo->SpellFamilyFlags & 0x1 && m_spellInfo->SpellVisual == 867) |
---|
1190 | { |
---|
1191 | int32 chargeBasePoints0 = damage; |
---|
1192 | m_caster->CastCustomSpell(m_caster,34846,&chargeBasePoints0,NULL,NULL,true); |
---|
1193 | return; |
---|
1194 | } |
---|
1195 | // Execute |
---|
1196 | if(m_spellInfo->SpellFamilyFlags & 0x20000000) |
---|
1197 | { |
---|
1198 | if(!unitTarget) |
---|
1199 | return; |
---|
1200 | |
---|
1201 | int32 basePoints0 = damage+int32(m_caster->GetPower(POWER_RAGE) * m_spellInfo->DmgMultiplier[i]); |
---|
1202 | m_caster->CastCustomSpell(unitTarget, 20647, &basePoints0, NULL, NULL, true, 0); |
---|
1203 | m_caster->SetPower(POWER_RAGE,0); |
---|
1204 | return; |
---|
1205 | } |
---|
1206 | if(m_spellInfo->Id==21977) //Warrior's Wrath |
---|
1207 | { |
---|
1208 | if(!unitTarget) |
---|
1209 | return; |
---|
1210 | |
---|
1211 | m_caster->CastSpell(unitTarget,21887,true); // spell mod |
---|
1212 | return; |
---|
1213 | } |
---|
1214 | break; |
---|
1215 | case SPELLFAMILY_WARLOCK: |
---|
1216 | //Life Tap (only it have this with dummy effect) |
---|
1217 | if (m_spellInfo->SpellFamilyFlags == 0x40000) |
---|
1218 | { |
---|
1219 | float cost = m_currentBasePoints[0]+1; |
---|
1220 | |
---|
1221 | if(Player* modOwner = m_caster->GetSpellModOwner()) |
---|
1222 | modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_COST, cost,this); |
---|
1223 | |
---|
1224 | int32 dmg = m_caster->SpellDamageBonus(m_caster, m_spellInfo,uint32(cost > 0 ? cost : 0), SPELL_DIRECT_DAMAGE); |
---|
1225 | |
---|
1226 | if(int32(m_caster->GetHealth()) > dmg) |
---|
1227 | { |
---|
1228 | // Shouldn't Appear in Combat Log |
---|
1229 | m_caster->ModifyHealth(-dmg); |
---|
1230 | |
---|
1231 | int32 mana = dmg; |
---|
1232 | |
---|
1233 | Unit::AuraList const& auraDummy = m_caster->GetAurasByType(SPELL_AURA_DUMMY); |
---|
1234 | for(Unit::AuraList::const_iterator itr = auraDummy.begin(); itr != auraDummy.end(); ++itr) |
---|
1235 | { |
---|
1236 | // only Imp. Life Tap have this in combination with dummy aura |
---|
1237 | if((*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_WARLOCK && (*itr)->GetSpellProto()->SpellIconID == 208) |
---|
1238 | mana = ((*itr)->GetModifier()->m_amount + 100)* mana / 100; |
---|
1239 | } |
---|
1240 | |
---|
1241 | m_caster->CastCustomSpell(m_caster,31818,&mana,NULL,NULL,true,NULL); |
---|
1242 | |
---|
1243 | // Mana Feed |
---|
1244 | int32 manaFeedVal = m_caster->CalculateSpellDamage(m_spellInfo,1, m_spellInfo->EffectBasePoints[1],m_caster); |
---|
1245 | manaFeedVal = manaFeedVal * mana / 100; |
---|
1246 | if(manaFeedVal > 0) |
---|
1247 | m_caster->CastCustomSpell(m_caster,32553,&manaFeedVal,NULL,NULL,true,NULL); |
---|
1248 | } |
---|
1249 | else |
---|
1250 | SendCastResult(SPELL_FAILED_FIZZLE); |
---|
1251 | return; |
---|
1252 | } |
---|
1253 | break; |
---|
1254 | case SPELLFAMILY_PRIEST: |
---|
1255 | switch(m_spellInfo->Id ) |
---|
1256 | { |
---|
1257 | case 28598: // Touch of Weakness triggered spell |
---|
1258 | { |
---|
1259 | if(!unitTarget || !m_triggeredByAuraSpell) |
---|
1260 | return; |
---|
1261 | |
---|
1262 | uint32 spellid = 0; |
---|
1263 | switch(m_triggeredByAuraSpell->Id) |
---|
1264 | { |
---|
1265 | case 2652: spellid = 2943; break; // Rank 1 |
---|
1266 | case 19261: spellid = 19249; break; // Rank 2 |
---|
1267 | case 19262: spellid = 19251; break; // Rank 3 |
---|
1268 | case 19264: spellid = 19252; break; // Rank 4 |
---|
1269 | case 19265: spellid = 19253; break; // Rank 5 |
---|
1270 | case 19266: spellid = 19254; break; // Rank 6 |
---|
1271 | case 25461: spellid = 25460; break; // Rank 7 |
---|
1272 | default: |
---|
1273 | sLog.outError("Spell::EffectDummy: Spell 28598 triggered by unhandeled spell %u",m_triggeredByAuraSpell->Id); |
---|
1274 | return; |
---|
1275 | } |
---|
1276 | m_caster->CastSpell(unitTarget, spellid, true, NULL); |
---|
1277 | return; |
---|
1278 | } |
---|
1279 | } |
---|
1280 | break; |
---|
1281 | case SPELLFAMILY_DRUID: |
---|
1282 | switch(m_spellInfo->Id ) |
---|
1283 | { |
---|
1284 | case 5420: // Tree of Life passive |
---|
1285 | { |
---|
1286 | // Tree of Life area effect |
---|
1287 | int32 health_mod = int32(m_caster->GetStat(STAT_SPIRIT)/4); |
---|
1288 | m_caster->CastCustomSpell(m_caster,34123,&health_mod,NULL,NULL,true,NULL); |
---|
1289 | return; |
---|
1290 | } |
---|
1291 | } |
---|
1292 | break; |
---|
1293 | case SPELLFAMILY_ROGUE: |
---|
1294 | switch(m_spellInfo->Id ) |
---|
1295 | { |
---|
1296 | case 31231: // Cheat Death |
---|
1297 | { |
---|
1298 | m_caster->CastSpell(m_caster,45182,true); |
---|
1299 | return; |
---|
1300 | } |
---|
1301 | case 5938: // Shiv |
---|
1302 | { |
---|
1303 | if(m_caster->GetTypeId() != TYPEID_PLAYER) |
---|
1304 | return; |
---|
1305 | |
---|
1306 | Player *pCaster = ((Player*)m_caster); |
---|
1307 | |
---|
1308 | Item *item = pCaster->GetWeaponForAttack(OFF_ATTACK); |
---|
1309 | if(!item) |
---|
1310 | return; |
---|
1311 | |
---|
1312 | // all poison enchantments is temporary |
---|
1313 | uint32 enchant_id = item->GetEnchantmentId(TEMP_ENCHANTMENT_SLOT); |
---|
1314 | if(!enchant_id) |
---|
1315 | return; |
---|
1316 | |
---|
1317 | SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id); |
---|
1318 | if(!pEnchant) |
---|
1319 | return; |
---|
1320 | |
---|
1321 | for (int s=0;s<3;s++) |
---|
1322 | { |
---|
1323 | if(pEnchant->type[s]!=ITEM_ENCHANTMENT_TYPE_COMBAT_SPELL) |
---|
1324 | continue; |
---|
1325 | |
---|
1326 | SpellEntry const* combatEntry = sSpellStore.LookupEntry(pEnchant->spellid[s]); |
---|
1327 | if(!combatEntry || combatEntry->Dispel != DISPEL_POISON) |
---|
1328 | continue; |
---|
1329 | |
---|
1330 | m_caster->CastSpell(unitTarget, combatEntry, true, item); |
---|
1331 | } |
---|
1332 | |
---|
1333 | m_caster->CastSpell(unitTarget, 5940, true); |
---|
1334 | return; |
---|
1335 | } |
---|
1336 | } |
---|
1337 | break; |
---|
1338 | case SPELLFAMILY_HUNTER: |
---|
1339 | // Steady Shot |
---|
1340 | if(m_spellInfo->SpellFamilyFlags & 0x100000000LL) |
---|
1341 | { |
---|
1342 | if( !unitTarget || !unitTarget->isAlive()) |
---|
1343 | return; |
---|
1344 | |
---|
1345 | bool found = false; |
---|
1346 | |
---|
1347 | // check dazed affect |
---|
1348 | Unit::AuraList const& decSpeedList = unitTarget->GetAurasByType(SPELL_AURA_MOD_DECREASE_SPEED); |
---|
1349 | for(Unit::AuraList::const_iterator iter = decSpeedList.begin(); iter != decSpeedList.end(); ++iter) |
---|
1350 | { |
---|
1351 | if((*iter)->GetSpellProto()->SpellIconID==15 && (*iter)->GetSpellProto()->Dispel==0) |
---|
1352 | { |
---|
1353 | found = true; |
---|
1354 | break; |
---|
1355 | } |
---|
1356 | } |
---|
1357 | |
---|
1358 | if(found) |
---|
1359 | m_caster->SpellNonMeleeDamageLog(unitTarget, m_spellInfo->Id, damage, m_IsTriggeredSpell, true); |
---|
1360 | return; |
---|
1361 | } |
---|
1362 | // Kill command |
---|
1363 | if(m_spellInfo->SpellFamilyFlags & 0x00080000000000LL) |
---|
1364 | { |
---|
1365 | if(m_caster->getClass()!=CLASS_HUNTER) |
---|
1366 | return; |
---|
1367 | |
---|
1368 | // clear hunter crit aura state |
---|
1369 | m_caster->ModifyAuraState(AURA_STATE_HUNTER_CRIT_STRIKE,false); |
---|
1370 | |
---|
1371 | // additional damage from pet to pet target |
---|
1372 | Pet* pet = m_caster->GetPet(); |
---|
1373 | if(!pet || !pet->getVictim()) |
---|
1374 | return; |
---|
1375 | |
---|
1376 | uint32 spell_id = 0; |
---|
1377 | switch (m_spellInfo->Id) |
---|
1378 | { |
---|
1379 | case 34026: spell_id = 34027; break; // rank 1 |
---|
1380 | default: |
---|
1381 | sLog.outError("Spell::EffectDummy: Spell %u not handled in KC",m_spellInfo->Id); |
---|
1382 | return; |
---|
1383 | } |
---|
1384 | |
---|
1385 | pet->CastSpell(pet->getVictim(), spell_id, true); |
---|
1386 | return; |
---|
1387 | } |
---|
1388 | |
---|
1389 | switch(m_spellInfo->Id) |
---|
1390 | { |
---|
1391 | case 23989: //Readiness talent |
---|
1392 | { |
---|
1393 | if(m_caster->GetTypeId()!=TYPEID_PLAYER) |
---|
1394 | return; |
---|
1395 | |
---|
1396 | //immediately finishes the cooldown for hunter abilities |
---|
1397 | const PlayerSpellMap& sp_list = ((Player *)m_caster)->GetSpellMap(); |
---|
1398 | for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr) |
---|
1399 | { |
---|
1400 | uint32 classspell = itr->first; |
---|
1401 | SpellEntry const *spellInfo = sSpellStore.LookupEntry(classspell); |
---|
1402 | |
---|
1403 | if (spellInfo->SpellFamilyName == SPELLFAMILY_HUNTER && spellInfo->Id != 23989 && GetSpellRecoveryTime(spellInfo) > 0 ) |
---|
1404 | { |
---|
1405 | ((Player*)m_caster)->RemoveSpellCooldown(classspell); |
---|
1406 | |
---|
1407 | WorldPacket data(SMSG_CLEAR_COOLDOWN, (4+8)); |
---|
1408 | data << uint32(classspell); |
---|
1409 | data << uint64(m_caster->GetGUID()); |
---|
1410 | ((Player*)m_caster)->GetSession()->SendPacket(&data); |
---|
1411 | } |
---|
1412 | } |
---|
1413 | return; |
---|
1414 | } |
---|
1415 | case 37506: // Scatter Shot |
---|
1416 | { |
---|
1417 | if (m_caster->GetTypeId()!=TYPEID_PLAYER) |
---|
1418 | return; |
---|
1419 | |
---|
1420 | // break Auto Shot and autohit |
---|
1421 | m_caster->InterruptSpell(CURRENT_AUTOREPEAT_SPELL); |
---|
1422 | m_caster->AttackStop(); |
---|
1423 | ((Player*)m_caster)->SendAttackSwingCancelAttack(); |
---|
1424 | return; |
---|
1425 | } |
---|
1426 | } |
---|
1427 | break; |
---|
1428 | case SPELLFAMILY_PALADIN: |
---|
1429 | switch(m_spellInfo->SpellIconID) |
---|
1430 | { |
---|
1431 | case 156: // Holy Shock |
---|
1432 | { |
---|
1433 | if(!unitTarget) |
---|
1434 | return; |
---|
1435 | |
---|
1436 | int hurt = 0; |
---|
1437 | int heal = 0; |
---|
1438 | |
---|
1439 | switch(m_spellInfo->Id) |
---|
1440 | { |
---|
1441 | case 20473: hurt = 25912; heal = 25914; break; |
---|
1442 | case 20929: hurt = 25911; heal = 25913; break; |
---|
1443 | case 20930: hurt = 25902; heal = 25903; break; |
---|
1444 | case 27174: hurt = 27176; heal = 27175; break; |
---|
1445 | case 33072: hurt = 33073; heal = 33074; break; |
---|
1446 | default: |
---|
1447 | sLog.outError("Spell::EffectDummy: Spell %u not handled in HS",m_spellInfo->Id); |
---|
1448 | return; |
---|
1449 | } |
---|
1450 | |
---|
1451 | if(m_caster->IsFriendlyTo(unitTarget)) |
---|
1452 | m_caster->CastSpell(unitTarget, heal, true, 0); |
---|
1453 | else |
---|
1454 | m_caster->CastSpell(unitTarget, hurt, true, 0); |
---|
1455 | |
---|
1456 | return; |
---|
1457 | } |
---|
1458 | case 561: // Judgement of command |
---|
1459 | { |
---|
1460 | if(!unitTarget) |
---|
1461 | return; |
---|
1462 | |
---|
1463 | uint32 spell_id = m_currentBasePoints[i]+1; |
---|
1464 | SpellEntry const* spell_proto = sSpellStore.LookupEntry(spell_id); |
---|
1465 | if(!spell_proto) |
---|
1466 | return; |
---|
1467 | |
---|
1468 | if( !unitTarget->hasUnitState(UNIT_STAT_STUNNED) && m_caster->GetTypeId()==TYPEID_PLAYER) |
---|
1469 | { |
---|
1470 | // decreased damage (/2) for non-stunned target. |
---|
1471 | SpellModifier *mod = new SpellModifier; |
---|
1472 | mod->op = SPELLMOD_DAMAGE; |
---|
1473 | mod->value = -50; |
---|
1474 | mod->type = SPELLMOD_PCT; |
---|
1475 | mod->spellId = m_spellInfo->Id; |
---|
1476 | mod->effectId = i; |
---|
1477 | mod->lastAffected = NULL; |
---|
1478 | mod->mask = 0x0000020000000000LL; |
---|
1479 | mod->charges = 0; |
---|
1480 | |
---|
1481 | ((Player*)m_caster)->AddSpellMod(mod, true); |
---|
1482 | m_caster->CastSpell(unitTarget,spell_proto,true,NULL); |
---|
1483 | // mod deleted |
---|
1484 | ((Player*)m_caster)->AddSpellMod(mod, false); |
---|
1485 | } |
---|
1486 | else |
---|
1487 | m_caster->CastSpell(unitTarget,spell_proto,true,NULL); |
---|
1488 | |
---|
1489 | return; |
---|
1490 | } |
---|
1491 | } |
---|
1492 | |
---|
1493 | switch(m_spellInfo->Id) |
---|
1494 | { |
---|
1495 | case 31789: // Righteous Defense (step 1) |
---|
1496 | { |
---|
1497 | // 31989 -> dummy effect (step 1) + dummy effect (step 2) -> 31709 (taunt like spell for each target) |
---|
1498 | |
---|
1499 | // non-standard cast requirement check |
---|
1500 | if (!unitTarget || unitTarget->getAttackers().empty()) |
---|
1501 | { |
---|
1502 | // clear cooldown at fail |
---|
1503 | if(m_caster->GetTypeId()==TYPEID_PLAYER) |
---|
1504 | { |
---|
1505 | ((Player*)m_caster)->RemoveSpellCooldown(m_spellInfo->Id); |
---|
1506 | |
---|
1507 | WorldPacket data(SMSG_CLEAR_COOLDOWN, (4+8)); |
---|
1508 | data << uint32(m_spellInfo->Id); |
---|
1509 | data << uint64(m_caster->GetGUID()); |
---|
1510 | ((Player*)m_caster)->GetSession()->SendPacket(&data); |
---|
1511 | } |
---|
1512 | |
---|
1513 | SendCastResult(SPELL_FAILED_TARGET_AFFECTING_COMBAT); |
---|
1514 | return; |
---|
1515 | } |
---|
1516 | |
---|
1517 | // Righteous Defense (step 2) (in old version 31980 dummy effect) |
---|
1518 | // Clear targets for eff 1 |
---|
1519 | for(std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit) |
---|
1520 | ihit->effectMask &= ~(1<<1); |
---|
1521 | |
---|
1522 | // not empty (checked) |
---|
1523 | Unit::AttackerSet const& attackers = unitTarget->getAttackers(); |
---|
1524 | |
---|
1525 | // chance to be selected from list |
---|
1526 | float chance = 100.0f/attackers.size(); |
---|
1527 | uint32 count=0; |
---|
1528 | for(Unit::AttackerSet::const_iterator aItr = attackers.begin(); aItr != attackers.end() && count < 3; ++aItr) |
---|
1529 | { |
---|
1530 | if(!roll_chance_f(chance)) |
---|
1531 | continue; |
---|
1532 | ++count; |
---|
1533 | AddUnitTarget((*aItr), 1); |
---|
1534 | } |
---|
1535 | |
---|
1536 | // now let next effect cast spell at each target. |
---|
1537 | return; |
---|
1538 | } |
---|
1539 | case 37877: // Blessing of Faith |
---|
1540 | { |
---|
1541 | if(!unitTarget) |
---|
1542 | return; |
---|
1543 | |
---|
1544 | uint32 spell_id = 0; |
---|
1545 | switch(unitTarget->getClass()) |
---|
1546 | { |
---|
1547 | case CLASS_DRUID: spell_id = 37878; break; |
---|
1548 | case CLASS_PALADIN: spell_id = 37879; break; |
---|
1549 | case CLASS_PRIEST: spell_id = 37880; break; |
---|
1550 | case CLASS_SHAMAN: spell_id = 37881; break; |
---|
1551 | default: return; // ignore for not healing classes |
---|
1552 | } |
---|
1553 | |
---|
1554 | m_caster->CastSpell(m_caster,spell_id,true); |
---|
1555 | return; |
---|
1556 | } |
---|
1557 | } |
---|
1558 | break; |
---|
1559 | case SPELLFAMILY_SHAMAN: |
---|
1560 | //Shaman Rockbiter Weapon |
---|
1561 | if (m_spellInfo->SpellFamilyFlags == 0x400000) |
---|
1562 | { |
---|
1563 | uint32 spell_id = 0; |
---|
1564 | switch(m_spellInfo->Id) |
---|
1565 | { |
---|
1566 | case 8017: spell_id = 36494; break; // Rank 1 |
---|
1567 | case 8018: spell_id = 36750; break; // Rank 2 |
---|
1568 | case 8019: spell_id = 36755; break; // Rank 3 |
---|
1569 | case 10399: spell_id = 36759; break; // Rank 4 |
---|
1570 | case 16314: spell_id = 36763; break; // Rank 5 |
---|
1571 | case 16315: spell_id = 36766; break; // Rank 6 |
---|
1572 | case 16316: spell_id = 36771; break; // Rank 7 |
---|
1573 | case 25479: spell_id = 36775; break; // Rank 8 |
---|
1574 | case 25485: spell_id = 36499; break; // Rank 9 |
---|
1575 | default: |
---|
1576 | sLog.outError("Spell::EffectDummy: Spell %u not handled in RW",m_spellInfo->Id); |
---|
1577 | return; |
---|
1578 | } |
---|
1579 | |
---|
1580 | SpellEntry const *spellInfo = sSpellStore.LookupEntry( spell_id ); |
---|
1581 | |
---|
1582 | if(!spellInfo) |
---|
1583 | { |
---|
1584 | sLog.outError("WORLD: unknown spell id %i\n", spell_id); |
---|
1585 | return; |
---|
1586 | } |
---|
1587 | |
---|
1588 | if(m_caster->GetTypeId() != TYPEID_PLAYER) |
---|
1589 | return; |
---|
1590 | |
---|
1591 | for(int i = BASE_ATTACK; i <= OFF_ATTACK; ++i) |
---|
1592 | { |
---|
1593 | if(Item* item = ((Player*)m_caster)->GetWeaponForAttack(WeaponAttackType(i))) |
---|
1594 | { |
---|
1595 | if(item->IsFitToSpellRequirements(m_spellInfo)) |
---|
1596 | { |
---|
1597 | Spell *spell = new Spell(m_caster, spellInfo, true); |
---|
1598 | |
---|
1599 | // enchanting spell selected by calculated damage-per-sec in enchanting effect |
---|
1600 | // at calculation applied affect from Elemental Weapons talent |
---|
1601 | // real enchantment damage-1 |
---|
1602 | spell->m_currentBasePoints[1] = damage-1; |
---|
1603 | |
---|
1604 | SpellCastTargets targets; |
---|
1605 | targets.setItemTarget( item ); |
---|
1606 | spell->prepare(&targets); |
---|
1607 | } |
---|
1608 | } |
---|
1609 | } |
---|
1610 | return; |
---|
1611 | } |
---|
1612 | |
---|
1613 | if(m_spellInfo->Id == 39610) // Mana-Tide Totem effect |
---|
1614 | { |
---|
1615 | if(!unitTarget || unitTarget->getPowerType() != POWER_MANA) |
---|
1616 | return; |
---|
1617 | |
---|
1618 | // Regenerate 6% of Total Mana Every 3 secs |
---|
1619 | int32 EffectBasePoints0 = unitTarget->GetMaxPower(POWER_MANA) * damage / 100; |
---|
1620 | m_caster->CastCustomSpell(unitTarget,39609,&EffectBasePoints0,NULL,NULL,true,NULL,NULL,m_originalCasterGUID); |
---|
1621 | return; |
---|
1622 | } |
---|
1623 | |
---|
1624 | break; |
---|
1625 | } |
---|
1626 | |
---|
1627 | // pet auras |
---|
1628 | if(PetAura const* petSpell = spellmgr.GetPetAura(m_spellInfo->Id)) |
---|
1629 | { |
---|
1630 | m_caster->AddPetAura(petSpell); |
---|
1631 | return; |
---|
1632 | } |
---|
1633 | } |
---|
1634 | |
---|
1635 | void Spell::EffectTriggerSpellWithValue(uint32 i) |
---|
1636 | { |
---|
1637 | uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[i]; |
---|
1638 | |
---|
1639 | // normal case |
---|
1640 | SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id ); |
---|
1641 | |
---|
1642 | if(!spellInfo) |
---|
1643 | { |
---|
1644 | sLog.outError("EffectTriggerSpellWithValue of spell %u: triggering unknown spell id %i\n", m_spellInfo->Id,triggered_spell_id); |
---|
1645 | return; |
---|
1646 | } |
---|
1647 | |
---|
1648 | int32 bp = damage; |
---|
1649 | m_caster->CastCustomSpell(unitTarget,triggered_spell_id,&bp,&bp,&bp,true,NULL,NULL,m_originalCasterGUID); |
---|
1650 | } |
---|
1651 | |
---|
1652 | void Spell::EffectTriggerRitualOfSummoning(uint32 i) |
---|
1653 | { |
---|
1654 | uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[i]; |
---|
1655 | SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id ); |
---|
1656 | |
---|
1657 | if(!spellInfo) |
---|
1658 | { |
---|
1659 | sLog.outError("EffectTriggerRitualOfSummoning of spell %u: triggering unknown spell id %i", m_spellInfo->Id,triggered_spell_id); |
---|
1660 | return; |
---|
1661 | } |
---|
1662 | |
---|
1663 | finish(); |
---|
1664 | Spell *spell = new Spell(m_caster, spellInfo, true); |
---|
1665 | |
---|
1666 | SpellCastTargets targets; |
---|
1667 | targets.setUnitTarget( unitTarget); |
---|
1668 | spell->prepare(&targets); |
---|
1669 | |
---|
1670 | m_caster->SetCurrentCastedSpell(spell); |
---|
1671 | spell->m_selfContainer = &(m_caster->m_currentSpells[spell->GetCurrentContainer()]); |
---|
1672 | |
---|
1673 | } |
---|
1674 | |
---|
1675 | void Spell::EffectForceCast(uint32 i) |
---|
1676 | { |
---|
1677 | if( !unitTarget ) |
---|
1678 | return; |
---|
1679 | |
---|
1680 | uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[i]; |
---|
1681 | |
---|
1682 | // normal case |
---|
1683 | SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id ); |
---|
1684 | |
---|
1685 | if(!spellInfo) |
---|
1686 | { |
---|
1687 | sLog.outError("EffectForceCast of spell %u: triggering unknown spell id %i", m_spellInfo->Id,triggered_spell_id); |
---|
1688 | return; |
---|
1689 | } |
---|
1690 | |
---|
1691 | unitTarget->CastSpell(unitTarget,spellInfo,true,NULL,NULL,m_originalCasterGUID); |
---|
1692 | } |
---|
1693 | |
---|
1694 | void Spell::EffectTriggerSpell(uint32 i) |
---|
1695 | { |
---|
1696 | uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[i]; |
---|
1697 | |
---|
1698 | // special cases |
---|
1699 | switch(triggered_spell_id) |
---|
1700 | { |
---|
1701 | // Vanish |
---|
1702 | case 18461: |
---|
1703 | { |
---|
1704 | m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT); |
---|
1705 | m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_DECREASE_SPEED); |
---|
1706 | m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_STALKED); |
---|
1707 | |
---|
1708 | // if this spell is given to NPC it must handle rest by it's own AI |
---|
1709 | if ( m_caster->GetTypeId() != TYPEID_PLAYER ) |
---|
1710 | return; |
---|
1711 | |
---|
1712 | // get highest rank of the Stealth spell |
---|
1713 | uint32 spellId = 0; |
---|
1714 | const PlayerSpellMap& sp_list = ((Player*)m_caster)->GetSpellMap(); |
---|
1715 | for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr) |
---|
1716 | { |
---|
1717 | // only highest rank is shown in spell book, so simply check if shown in spell book |
---|
1718 | if(!itr->second->active || itr->second->disabled || itr->second->state == PLAYERSPELL_REMOVED) |
---|
1719 | continue; |
---|
1720 | |
---|
1721 | SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first); |
---|
1722 | if (!spellInfo) |
---|
1723 | continue; |
---|
1724 | |
---|
1725 | if (spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && spellInfo->SpellFamilyFlags & SPELLFAMILYFLAG_ROGUE_STEALTH) |
---|
1726 | { |
---|
1727 | spellId = spellInfo->Id; |
---|
1728 | break; |
---|
1729 | } |
---|
1730 | } |
---|
1731 | |
---|
1732 | // no Stealth spell found |
---|
1733 | if (!spellId) |
---|
1734 | return; |
---|
1735 | |
---|
1736 | // reset cooldown on it if needed |
---|
1737 | if(((Player*)m_caster)->HasSpellCooldown(spellId)) |
---|
1738 | ((Player*)m_caster)->RemoveSpellCooldown(spellId); |
---|
1739 | |
---|
1740 | m_caster->CastSpell(m_caster, spellId, true); |
---|
1741 | return; |
---|
1742 | } |
---|
1743 | // just skip |
---|
1744 | case 23770: // Sayge's Dark Fortune of * |
---|
1745 | // not exist, common cooldown can be implemented in scripts if need. |
---|
1746 | return; |
---|
1747 | // Brittle Armor - (need add max stack of 24575 Brittle Armor) |
---|
1748 | case 29284: |
---|
1749 | { |
---|
1750 | const SpellEntry *spell = sSpellStore.LookupEntry(24575); |
---|
1751 | if (!spell) |
---|
1752 | return; |
---|
1753 | |
---|
1754 | for (int i=0; i < spell->StackAmount; ++i) |
---|
1755 | m_caster->CastSpell(unitTarget,spell->Id, true, m_CastItem, NULL, m_originalCasterGUID); |
---|
1756 | return; |
---|
1757 | } |
---|
1758 | // Mercurial Shield - (need add max stack of 26464 Mercurial Shield) |
---|
1759 | case 29286: |
---|
1760 | { |
---|
1761 | const SpellEntry *spell = sSpellStore.LookupEntry(26464); |
---|
1762 | if (!spell) |
---|
1763 | return; |
---|
1764 | |
---|
1765 | for (int i=0; i < spell->StackAmount; ++i) |
---|
1766 | m_caster->CastSpell(unitTarget,spell->Id, true, m_CastItem, NULL, m_originalCasterGUID); |
---|
1767 | return; |
---|
1768 | } |
---|
1769 | // Righteous Defense |
---|
1770 | case 31980: |
---|
1771 | { |
---|
1772 | m_caster->CastSpell(unitTarget, 31790, true,m_CastItem,NULL,m_originalCasterGUID); |
---|
1773 | return; |
---|
1774 | } |
---|
1775 | // Cloak of Shadows |
---|
1776 | case 35729 : |
---|
1777 | { |
---|
1778 | Unit::AuraMap& Auras = m_caster->GetAuras(); |
---|
1779 | for(Unit::AuraMap::iterator iter = Auras.begin(); iter != Auras.end(); ++iter) |
---|
1780 | { |
---|
1781 | // remove all harmful spells on you... |
---|
1782 | if( // ignore positive and passive auras |
---|
1783 | !iter->second->IsPositive() && !iter->second->IsPassive() && |
---|
1784 | // ignore physical auras |
---|
1785 | (GetSpellSchoolMask(iter->second->GetSpellProto()) & SPELL_SCHOOL_MASK_NORMAL)==0 && |
---|
1786 | // ignore immunity persistent spells |
---|
1787 | !( iter->second->GetSpellProto()->AttributesEx & 0x10000 ) ) |
---|
1788 | { |
---|
1789 | m_caster->RemoveAurasDueToSpell(iter->second->GetSpellProto()->Id); |
---|
1790 | iter = Auras.begin(); |
---|
1791 | } |
---|
1792 | } |
---|
1793 | return; |
---|
1794 | } |
---|
1795 | // Priest Shadowfiend (34433) need apply mana gain trigger aura on pet |
---|
1796 | case 41967: |
---|
1797 | { |
---|
1798 | if (Unit *pet = m_caster->GetPet()) |
---|
1799 | pet->CastSpell(pet, 28305, true); |
---|
1800 | return; |
---|
1801 | } |
---|
1802 | } |
---|
1803 | |
---|
1804 | // normal case |
---|
1805 | SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id ); |
---|
1806 | |
---|
1807 | if(!spellInfo) |
---|
1808 | { |
---|
1809 | sLog.outError("EffectTriggerSpell of spell %u: triggering unknown spell id %i", m_spellInfo->Id,triggered_spell_id); |
---|
1810 | return; |
---|
1811 | } |
---|
1812 | |
---|
1813 | // some triggered spells require specific equipment |
---|
1814 | if(spellInfo->EquippedItemClass >=0 && m_caster->GetTypeId()==TYPEID_PLAYER) |
---|
1815 | { |
---|
1816 | // main hand weapon required |
---|
1817 | if(spellInfo->AttributesEx3 & SPELL_ATTR_EX3_MAIN_HAND) |
---|
1818 | { |
---|
1819 | Item* item = ((Player*)m_caster)->GetWeaponForAttack(BASE_ATTACK); |
---|
1820 | |
---|
1821 | // skip spell if no weapon in slot or broken |
---|
1822 | if(!item || item->IsBroken() ) |
---|
1823 | return; |
---|
1824 | |
---|
1825 | // skip spell if weapon not fit to triggered spell |
---|
1826 | if(!item->IsFitToSpellRequirements(spellInfo)) |
---|
1827 | return; |
---|
1828 | } |
---|
1829 | |
---|
1830 | // offhand hand weapon required |
---|
1831 | if(spellInfo->AttributesEx3 & SPELL_ATTR_EX3_REQ_OFFHAND) |
---|
1832 | { |
---|
1833 | Item* item = ((Player*)m_caster)->GetWeaponForAttack(OFF_ATTACK); |
---|
1834 | |
---|
1835 | // skip spell if no weapon in slot or broken |
---|
1836 | if(!item || item->IsBroken() ) |
---|
1837 | return; |
---|
1838 | |
---|
1839 | // skip spell if weapon not fit to triggered spell |
---|
1840 | if(!item->IsFitToSpellRequirements(spellInfo)) |
---|
1841 | return; |
---|
1842 | } |
---|
1843 | } |
---|
1844 | |
---|
1845 | // some triggered spells must be casted instantly (for example, if next effect case instant kill caster) |
---|
1846 | bool instant = false; |
---|
1847 | for(uint32 j = i+1; j < 3; ++j) |
---|
1848 | { |
---|
1849 | if(m_spellInfo->Effect[j]==SPELL_EFFECT_INSTAKILL && m_spellInfo->EffectImplicitTargetA[j]==TARGET_SELF) |
---|
1850 | { |
---|
1851 | instant = true; |
---|
1852 | break; |
---|
1853 | } |
---|
1854 | } |
---|
1855 | |
---|
1856 | if(instant) |
---|
1857 | { |
---|
1858 | if (unitTarget) |
---|
1859 | m_caster->CastSpell(unitTarget,spellInfo,true,m_CastItem,NULL,m_originalCasterGUID); |
---|
1860 | } |
---|
1861 | else |
---|
1862 | m_TriggerSpells.push_back(spellInfo); |
---|
1863 | } |
---|
1864 | |
---|
1865 | void Spell::EffectTriggerMissileSpell(uint32 effect_idx) |
---|
1866 | { |
---|
1867 | uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[effect_idx]; |
---|
1868 | |
---|
1869 | // normal case |
---|
1870 | SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id ); |
---|
1871 | |
---|
1872 | if(!spellInfo) |
---|
1873 | { |
---|
1874 | sLog.outError("EffectTriggerMissileSpell of spell %u: triggering unknown spell id %effect_idx", m_spellInfo->Id,triggered_spell_id); |
---|
1875 | return; |
---|
1876 | } |
---|
1877 | |
---|
1878 | if (m_CastItem) |
---|
1879 | DEBUG_LOG("WORLD: cast Item spellId - %i", spellInfo->Id); |
---|
1880 | |
---|
1881 | Spell *spell = new Spell(m_caster, spellInfo, true, m_originalCasterGUID ); |
---|
1882 | |
---|
1883 | SpellCastTargets targets; |
---|
1884 | targets.setDestination(m_targets.m_destX,m_targets.m_destY,m_targets.m_destZ); |
---|
1885 | spell->m_CastItem = m_CastItem; |
---|
1886 | spell->prepare(&targets, NULL); |
---|
1887 | } |
---|
1888 | |
---|
1889 | void Spell::EffectTeleportUnits(uint32 i) |
---|
1890 | { |
---|
1891 | if(!unitTarget || unitTarget->isInFlight()) |
---|
1892 | return; |
---|
1893 | |
---|
1894 | switch (m_spellInfo->EffectImplicitTargetB[i]) |
---|
1895 | { |
---|
1896 | case TARGET_INNKEEPER_COORDINATES: |
---|
1897 | { |
---|
1898 | // Only players can teleport to innkeeper |
---|
1899 | if (unitTarget->GetTypeId() != TYPEID_PLAYER) |
---|
1900 | return; |
---|
1901 | |
---|
1902 | ((Player*)unitTarget)->TeleportTo(((Player*)unitTarget)->m_homebindMapId,((Player*)unitTarget)->m_homebindX,((Player*)unitTarget)->m_homebindY,((Player*)unitTarget)->m_homebindZ,unitTarget->GetOrientation(),unitTarget==m_caster ? TELE_TO_SPELL : 0); |
---|
1903 | return; |
---|
1904 | } |
---|
1905 | case TARGET_TABLE_X_Y_Z_COORDINATES: |
---|
1906 | { |
---|
1907 | // TODO: Only players can teleport? |
---|
1908 | if (unitTarget->GetTypeId() != TYPEID_PLAYER) |
---|
1909 | return; |
---|
1910 | SpellTargetPosition const* st = spellmgr.GetSpellTargetPosition(m_spellInfo->Id); |
---|
1911 | if(!st) |
---|
1912 | { |
---|
1913 | sLog.outError( "Spell::EffectTeleportUnits - unknown Teleport coordinates for spell ID %u\n", m_spellInfo->Id ); |
---|
1914 | return; |
---|
1915 | } |
---|
1916 | ((Player*)unitTarget)->TeleportTo(st->target_mapId,st->target_X,st->target_Y,st->target_Z,st->target_Orientation,unitTarget==m_caster ? TELE_TO_SPELL : 0); |
---|
1917 | break; |
---|
1918 | } |
---|
1919 | case TARGET_BEHIND_VICTIM: |
---|
1920 | { |
---|
1921 | // Get selected target for player (or victim for units) |
---|
1922 | Unit *pTarget = NULL; |
---|
1923 | if(m_caster->GetTypeId() == TYPEID_PLAYER) |
---|
1924 | pTarget = ObjectAccessor::GetUnit(*m_caster, ((Player*)m_caster)->GetSelection()); |
---|
1925 | else |
---|
1926 | pTarget = m_caster->getVictim(); |
---|
1927 | // No target present - return |
---|
1928 | if (!pTarget) |
---|
1929 | return; |
---|
1930 | // Init dest coordinates |
---|
1931 | uint32 mapid = m_caster->GetMapId(); |
---|
1932 | float x = m_targets.m_destX; |
---|
1933 | float y = m_targets.m_destY; |
---|
1934 | float z = m_targets.m_destZ; |
---|
1935 | float orientation = pTarget->GetOrientation(); |
---|
1936 | // Teleport |
---|
1937 | if(unitTarget->GetTypeId() == TYPEID_PLAYER) |
---|
1938 | ((Player*)unitTarget)->TeleportTo(mapid, x, y, z, orientation, TELE_TO_NOT_LEAVE_COMBAT | TELE_TO_NOT_UNSUMMON_PET | (unitTarget==m_caster ? TELE_TO_SPELL : 0)); |
---|
1939 | else |
---|
1940 | { |
---|
1941 | MapManager::Instance().GetMap(mapid, m_caster)->CreatureRelocation((Creature*)unitTarget, x, y, z, orientation); |
---|
1942 | WorldPacket data; |
---|
1943 | unitTarget->BuildTeleportAckMsg(&data, x, y, z, orientation); |
---|
1944 | unitTarget->SendMessageToSet(&data, false); |
---|
1945 | } |
---|
1946 | return; |
---|
1947 | } |
---|
1948 | default: |
---|
1949 | { |
---|
1950 | // If not exist data for dest location - return |
---|
1951 | if(!(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)) |
---|
1952 | { |
---|
1953 | sLog.outError( "Spell::EffectTeleportUnits - unknown EffectImplicitTargetB[%u] = %u for spell ID %u\n", i, m_spellInfo->EffectImplicitTargetB[i], m_spellInfo->Id ); |
---|
1954 | return; |
---|
1955 | } |
---|
1956 | // Init dest coordinates |
---|
1957 | uint32 mapid = m_caster->GetMapId(); |
---|
1958 | float x = m_targets.m_destX; |
---|
1959 | float y = m_targets.m_destY; |
---|
1960 | float z = m_targets.m_destZ; |
---|
1961 | float orientation = unitTarget->GetOrientation(); |
---|
1962 | // Teleport |
---|
1963 | if(unitTarget->GetTypeId() == TYPEID_PLAYER) |
---|
1964 | ((Player*)unitTarget)->TeleportTo(mapid, x, y, z, orientation, TELE_TO_NOT_LEAVE_COMBAT | TELE_TO_NOT_UNSUMMON_PET | (unitTarget==m_caster ? TELE_TO_SPELL : 0)); |
---|
1965 | else |
---|
1966 | { |
---|
1967 | MapManager::Instance().GetMap(mapid, m_caster)->CreatureRelocation((Creature*)unitTarget, x, y, z, orientation); |
---|
1968 | WorldPacket data; |
---|
1969 | unitTarget->BuildTeleportAckMsg(&data, x, y, z, orientation); |
---|
1970 | unitTarget->SendMessageToSet(&data, false); |
---|
1971 | } |
---|
1972 | return; |
---|
1973 | } |
---|
1974 | } |
---|
1975 | |
---|
1976 | // post effects for TARGET_TABLE_X_Y_Z_COORDINATES |
---|
1977 | switch ( m_spellInfo->Id ) |
---|
1978 | { |
---|
1979 | // Dimensional Ripper - Everlook |
---|
1980 | case 23442: |
---|
1981 | { |
---|
1982 | int32 r = irand(0, 119); |
---|
1983 | if ( r >= 70 ) // 7/12 success |
---|
1984 | { |
---|
1985 | if ( r < 100 ) // 4/12 evil twin |
---|
1986 | m_caster->CastSpell(m_caster,23445,true); |
---|
1987 | else // 1/12 fire |
---|
1988 | m_caster->CastSpell(m_caster,23449,true); |
---|
1989 | } |
---|
1990 | return; |
---|
1991 | } |
---|
1992 | // Ultrasafe Transporter: Toshley's Station |
---|
1993 | case 36941: |
---|
1994 | { |
---|
1995 | if ( roll_chance_i(50) ) // 50% success |
---|
1996 | { |
---|
1997 | int32 rand_eff = urand(1,7); |
---|
1998 | switch ( rand_eff ) |
---|
1999 | { |
---|
2000 | case 1: |
---|
2001 | // soul split - evil |
---|
2002 | m_caster->CastSpell(m_caster,36900,true); |
---|
2003 | break; |
---|
2004 | case 2: |
---|
2005 | // soul split - good |
---|
2006 | m_caster->CastSpell(m_caster,36901,true); |
---|
2007 | break; |
---|
2008 | case 3: |
---|
2009 | // Increase the size |
---|
2010 | m_caster->CastSpell(m_caster,36895,true); |
---|
2011 | break; |
---|
2012 | case 4: |
---|
2013 | // Decrease the size |
---|
2014 | m_caster->CastSpell(m_caster,36893,true); |
---|
2015 | break; |
---|
2016 | case 5: |
---|
2017 | // Transform |
---|
2018 | { |
---|
2019 | if (((Player*)m_caster)->GetTeam() == ALLIANCE ) |
---|
2020 | m_caster->CastSpell(m_caster,36897,true); |
---|
2021 | else |
---|
2022 | m_caster->CastSpell(m_caster,36899,true); |
---|
2023 | break; |
---|
2024 | } |
---|
2025 | case 6: |
---|
2026 | // chicken |
---|
2027 | m_caster->CastSpell(m_caster,36940,true); |
---|
2028 | break; |
---|
2029 | case 7: |
---|
2030 | // evil twin |
---|
2031 | m_caster->CastSpell(m_caster,23445,true); |
---|
2032 | break; |
---|
2033 | } |
---|
2034 | } |
---|
2035 | return; |
---|
2036 | } |
---|
2037 | // Dimensional Ripper - Area 52 |
---|
2038 | case 36890: |
---|
2039 | { |
---|
2040 | if ( roll_chance_i(50) ) // 50% success |
---|
2041 | { |
---|
2042 | int32 rand_eff = urand(1,4); |
---|
2043 | switch ( rand_eff ) |
---|
2044 | { |
---|
2045 | case 1: |
---|
2046 | // soul split - evil |
---|
2047 | m_caster->CastSpell(m_caster,36900,true); |
---|
2048 | break; |
---|
2049 | case 2: |
---|
2050 | // soul split - good |
---|
2051 | m_caster->CastSpell(m_caster,36901,true); |
---|
2052 | break; |
---|
2053 | case 3: |
---|
2054 | // Increase the size |
---|
2055 | m_caster->CastSpell(m_caster,36895,true); |
---|
2056 | break; |
---|
2057 | case 4: |
---|
2058 | // Transform |
---|
2059 | { |
---|
2060 | if (((Player*)m_caster)->GetTeam() == ALLIANCE ) |
---|
2061 | m_caster->CastSpell(m_caster,36897,true); |
---|
2062 | else |
---|
2063 | m_caster->CastSpell(m_caster,36899,true); |
---|
2064 | break; |
---|
2065 | } |
---|
2066 | } |
---|
2067 | } |
---|
2068 | return; |
---|
2069 | } |
---|
2070 | } |
---|
2071 | } |
---|
2072 | |
---|
2073 | void Spell::EffectApplyAura(uint32 i) |
---|
2074 | { |
---|
2075 | if(!unitTarget) |
---|
2076 | return; |
---|
2077 | |
---|
2078 | SpellImmuneList const& list = unitTarget->m_spellImmune[IMMUNITY_STATE]; |
---|
2079 | for(SpellImmuneList::const_iterator itr = list.begin(); itr != list.end(); ++itr) |
---|
2080 | if(itr->type == m_spellInfo->EffectApplyAuraName[i]) |
---|
2081 | return; |
---|
2082 | |
---|
2083 | // ghost spell check, allow apply any auras at player loading in ghost mode (will be cleanup after load) |
---|
2084 | if( !unitTarget->isAlive() && m_spellInfo->Id != 20584 && m_spellInfo->Id != 8326 && |
---|
2085 | (unitTarget->GetTypeId()!=TYPEID_PLAYER || !((Player*)unitTarget)->GetSession()->PlayerLoading()) ) |
---|
2086 | return; |
---|
2087 | |
---|
2088 | Unit* caster = m_originalCasterGUID ? m_originalCaster : m_caster; |
---|
2089 | if(!caster) |
---|
2090 | return; |
---|
2091 | |
---|
2092 | sLog.outDebug("Spell: Aura is: %u", m_spellInfo->EffectApplyAuraName[i]); |
---|
2093 | |
---|
2094 | Aura* Aur = CreateAura(m_spellInfo, i, &m_currentBasePoints[i], unitTarget, caster, m_CastItem); |
---|
2095 | |
---|
2096 | // Now Reduce spell duration using data received at spell hit |
---|
2097 | int32 duration = Aur->GetAuraMaxDuration(); |
---|
2098 | unitTarget->ApplyDiminishingToDuration(m_diminishGroup,duration,m_caster,m_diminishLevel); |
---|
2099 | Aur->setDiminishGroup(m_diminishGroup); |
---|
2100 | |
---|
2101 | // if Aura removed and deleted, do not continue. |
---|
2102 | if(duration== 0 && !(Aur->IsPermanent())) |
---|
2103 | { |
---|
2104 | delete Aur; |
---|
2105 | return; |
---|
2106 | } |
---|
2107 | |
---|
2108 | if(duration != Aur->GetAuraMaxDuration()) |
---|
2109 | { |
---|
2110 | Aur->SetAuraMaxDuration(duration); |
---|
2111 | Aur->SetAuraDuration(duration); |
---|
2112 | } |
---|
2113 | |
---|
2114 | bool added = unitTarget->AddAura(Aur); |
---|
2115 | |
---|
2116 | // Aura not added and deleted in AddAura call; |
---|
2117 | if (!added) |
---|
2118 | return; |
---|
2119 | |
---|
2120 | // found crash at character loading, broken pointer to Aur... |
---|
2121 | // Aur was deleted in AddAura()... |
---|
2122 | if(!Aur) |
---|
2123 | return; |
---|
2124 | |
---|
2125 | // TODO Make a way so it works for every related spell! |
---|
2126 | if(unitTarget->GetTypeId()==TYPEID_PLAYER) // Negative buff should only be applied on players |
---|
2127 | { |
---|
2128 | uint32 spellId = 0; |
---|
2129 | if(m_spellInfo->CasterAuraStateNot==AURA_STATE_WEAKENED_SOUL || m_spellInfo->TargetAuraStateNot==AURA_STATE_WEAKENED_SOUL) |
---|
2130 | spellId = 6788; // Weakened Soul |
---|
2131 | else if(m_spellInfo->CasterAuraStateNot==AURA_STATE_FORBEARANCE || m_spellInfo->TargetAuraStateNot==AURA_STATE_FORBEARANCE) |
---|
2132 | spellId = 25771; // Forbearance |
---|
2133 | else if(m_spellInfo->CasterAuraStateNot==AURA_STATE_HYPOTHERMIA) |
---|
2134 | spellId = 41425; // Hypothermia |
---|
2135 | else if (m_spellInfo->Mechanic == MECHANIC_BANDAGE) // Bandages |
---|
2136 | spellId = 11196; // Recently Bandaged |
---|
2137 | else if( (m_spellInfo->AttributesEx & 0x20) && (m_spellInfo->AttributesEx2 & 0x20000) ) |
---|
2138 | spellId = 23230; // Blood Fury - Healing Reduction |
---|
2139 | |
---|
2140 | SpellEntry const *AdditionalSpellInfo = sSpellStore.LookupEntry(spellId); |
---|
2141 | if (AdditionalSpellInfo) |
---|
2142 | { |
---|
2143 | // applied at target by target |
---|
2144 | Aura* AdditionalAura = CreateAura(AdditionalSpellInfo, 0, &m_currentBasePoints[0], unitTarget,unitTarget, 0); |
---|
2145 | unitTarget->AddAura(AdditionalAura); |
---|
2146 | sLog.outDebug("Spell: Additional Aura is: %u", AdditionalSpellInfo->EffectApplyAuraName[0]); |
---|
2147 | } |
---|
2148 | } |
---|
2149 | |
---|
2150 | // Prayer of Mending (jump animation), we need formal caster instead original for correct animation |
---|
2151 | if( m_spellInfo->SpellFamilyName == SPELLFAMILY_PRIEST && (m_spellInfo->SpellFamilyFlags & 0x00002000000000LL)) |
---|
2152 | m_caster->CastSpell(unitTarget,41637,true,NULL,Aur); |
---|
2153 | } |
---|
2154 | |
---|
2155 | void Spell::EffectUnlearnSpecialization( uint32 i ) |
---|
2156 | { |
---|
2157 | if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) |
---|
2158 | return; |
---|
2159 | |
---|
2160 | Player *_player = (Player*)unitTarget; |
---|
2161 | uint32 spellToUnlearn = m_spellInfo->EffectTriggerSpell[i]; |
---|
2162 | |
---|
2163 | _player->removeSpell(spellToUnlearn); |
---|
2164 | |
---|
2165 | sLog.outDebug( "Spell: Player %u have unlearned spell %u from NpcGUID: %u", _player->GetGUIDLow(), spellToUnlearn, m_caster->GetGUIDLow() ); |
---|
2166 | } |
---|
2167 | |
---|
2168 | void Spell::EffectPowerDrain(uint32 i) |
---|
2169 | { |
---|
2170 | if(m_spellInfo->EffectMiscValue[i] < 0 || m_spellInfo->EffectMiscValue[i] >= MAX_POWERS) |
---|
2171 | return; |
---|
2172 | |
---|
2173 | Powers drain_power = Powers(m_spellInfo->EffectMiscValue[i]); |
---|
2174 | |
---|
2175 | if(!unitTarget) |
---|
2176 | return; |
---|
2177 | if(!unitTarget->isAlive()) |
---|
2178 | return; |
---|
2179 | if(unitTarget->getPowerType() != drain_power) |
---|
2180 | return; |
---|
2181 | if(damage < 0) |
---|
2182 | return; |
---|
2183 | |
---|
2184 | uint32 curPower = unitTarget->GetPower(drain_power); |
---|
2185 | |
---|
2186 | //add spell damage bonus |
---|
2187 | damage=m_caster->SpellDamageBonus(unitTarget,m_spellInfo,uint32(damage),SPELL_DIRECT_DAMAGE); |
---|
2188 | |
---|
2189 | // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4) |
---|
2190 | uint32 power = damage; |
---|
2191 | if ( drain_power == POWER_MANA && unitTarget->GetTypeId() == TYPEID_PLAYER ) |
---|
2192 | power -= ((Player*)unitTarget)->GetSpellCritDamageReduction(power); |
---|
2193 | |
---|
2194 | int32 new_damage; |
---|
2195 | if(curPower < power) |
---|
2196 | new_damage = curPower; |
---|
2197 | else |
---|
2198 | new_damage = power; |
---|
2199 | |
---|
2200 | unitTarget->ModifyPower(drain_power,-new_damage); |
---|
2201 | |
---|
2202 | if(drain_power == POWER_MANA) |
---|
2203 | { |
---|
2204 | float manaMultiplier = m_spellInfo->EffectMultipleValue[i]; |
---|
2205 | if(manaMultiplier==0) |
---|
2206 | manaMultiplier = 1; |
---|
2207 | |
---|
2208 | if(Player *modOwner = m_caster->GetSpellModOwner()) |
---|
2209 | modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_MULTIPLE_VALUE, manaMultiplier); |
---|
2210 | |
---|
2211 | int32 gain = int32(new_damage*manaMultiplier); |
---|
2212 | |
---|
2213 | m_caster->ModifyPower(POWER_MANA,gain); |
---|
2214 | //send log |
---|
2215 | m_caster->SendEnergizeSpellLog(m_caster, m_spellInfo->Id,gain,POWER_MANA,false); |
---|
2216 | } |
---|
2217 | } |
---|
2218 | |
---|
2219 | void Spell::EffectSendEvent(uint32 EffectIndex) |
---|
2220 | { |
---|
2221 | if (m_caster->GetTypeId() == TYPEID_PLAYER && ((Player*)m_caster)->InBattleGround()) |
---|
2222 | { |
---|
2223 | BattleGround* bg = ((Player *)m_caster)->GetBattleGround(); |
---|
2224 | if(bg && bg->GetStatus() == STATUS_IN_PROGRESS) |
---|
2225 | { |
---|
2226 | switch(m_spellInfo->Id) |
---|
2227 | { |
---|
2228 | case 23333: // Pickup Horde Flag |
---|
2229 | /*do not uncomment . |
---|
2230 | if(bg->GetTypeID()==BATTLEGROUND_WS) |
---|
2231 | bg->EventPlayerClickedOnFlag((Player*)m_caster, this->gameObjTarget); |
---|
2232 | sLog.outDebug("Send Event Horde Flag Picked Up"); |
---|
2233 | break; |
---|
2234 | /* not used : |
---|
2235 | case 23334: // Drop Horde Flag |
---|
2236 | if(bg->GetTypeID()==BATTLEGROUND_WS) |
---|
2237 | bg->EventPlayerDroppedFlag((Player*)m_caster); |
---|
2238 | sLog.outDebug("Drop Horde Flag"); |
---|
2239 | break; |
---|
2240 | */ |
---|
2241 | case 23335: // Pickup Alliance Flag |
---|
2242 | /*do not uncomment ... (it will cause crash, because of null targetobject!) anyway this is a bad way to call that event, because it would cause recursion |
---|
2243 | if(bg->GetTypeID()==BATTLEGROUND_WS) |
---|
2244 | bg->EventPlayerClickedOnFlag((Player*)m_caster, this->gameObjTarget); |
---|
2245 | sLog.outDebug("Send Event Alliance Flag Picked Up"); |
---|
2246 | break; |
---|
2247 | /* not used : |
---|
2248 | case 23336: // Drop Alliance Flag |
---|
2249 | if(bg->GetTypeID()==BATTLEGROUND_WS) |
---|
2250 | bg->EventPlayerDroppedFlag((Player*)m_caster); |
---|
2251 | sLog.outDebug("Drop Alliance Flag"); |
---|
2252 | break; |
---|
2253 | case 23385: // Alliance Flag Returns |
---|
2254 | if(bg->GetTypeID()==BATTLEGROUND_WS) |
---|
2255 | bg->EventPlayerClickedOnFlag((Player*)m_caster, this->gameObjTarget); |
---|
2256 | sLog.outDebug("Alliance Flag Returned"); |
---|
2257 | break; |
---|
2258 | case 23386: // Horde Flag Returns |
---|
2259 | if(bg->GetTypeID()==BATTLEGROUND_WS) |
---|
2260 | bg->EventPlayerClickedOnFlag((Player*)m_caster, this->gameObjTarget); |
---|
2261 | sLog.outDebug("Horde Flag Returned"); |
---|
2262 | break;*/ |
---|
2263 | case 34976: |
---|
2264 | /* |
---|
2265 | if(bg->GetTypeID()==BATTLEGROUND_EY) |
---|
2266 | bg->EventPlayerClickedOnFlag((Player*)m_caster, this->gameObjTarget); |
---|
2267 | */ |
---|
2268 | break; |
---|
2269 | default: |
---|
2270 | sLog.outDebug("Unknown spellid %u in BG event", m_spellInfo->Id); |
---|
2271 | break; |
---|
2272 | } |
---|
2273 | } |
---|
2274 | } |
---|
2275 | sLog.outDebug("Spell ScriptStart %u for spellid %u in EffectSendEvent ", m_spellInfo->EffectMiscValue[EffectIndex], m_spellInfo->Id); |
---|
2276 | sWorld.ScriptsStart(sEventScripts, m_spellInfo->EffectMiscValue[EffectIndex], m_caster, focusObject); |
---|
2277 | } |
---|
2278 | |
---|
2279 | void Spell::EffectPowerBurn(uint32 i) |
---|
2280 | { |
---|
2281 | if(m_spellInfo->EffectMiscValue[i] < 0 || m_spellInfo->EffectMiscValue[i] >= MAX_POWERS) |
---|
2282 | return; |
---|
2283 | |
---|
2284 | Powers powertype = Powers(m_spellInfo->EffectMiscValue[i]); |
---|
2285 | |
---|
2286 | if(!unitTarget) |
---|
2287 | return; |
---|
2288 | if(!unitTarget->isAlive()) |
---|
2289 | return; |
---|
2290 | if(unitTarget->getPowerType()!=powertype) |
---|
2291 | return; |
---|
2292 | if(damage < 0) |
---|
2293 | return; |
---|
2294 | |
---|
2295 | int32 curPower = int32(unitTarget->GetPower(powertype)); |
---|
2296 | |
---|
2297 | // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4) |
---|
2298 | uint32 power = damage; |
---|
2299 | if ( powertype == POWER_MANA && unitTarget->GetTypeId() == TYPEID_PLAYER ) |
---|
2300 | power -= ((Player*)unitTarget)->GetSpellCritDamageReduction(power); |
---|
2301 | |
---|
2302 | int32 new_damage = (curPower < power) ? curPower : power; |
---|
2303 | |
---|
2304 | unitTarget->ModifyPower(powertype,-new_damage); |
---|
2305 | float multiplier = m_spellInfo->EffectMultipleValue[i]; |
---|
2306 | |
---|
2307 | if(Player *modOwner = m_caster->GetSpellModOwner()) |
---|
2308 | modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_MULTIPLE_VALUE, multiplier); |
---|
2309 | |
---|
2310 | new_damage = int32(new_damage*multiplier); |
---|
2311 | m_caster->SpellNonMeleeDamageLog(unitTarget, m_spellInfo->Id, new_damage, m_IsTriggeredSpell, true); |
---|
2312 | } |
---|
2313 | |
---|
2314 | void Spell::EffectHeal( uint32 /*i*/ ) |
---|
2315 | { |
---|
2316 | if( unitTarget && unitTarget->isAlive() && damage >= 0) |
---|
2317 | { |
---|
2318 | // Try to get original caster |
---|
2319 | Unit *caster = m_originalCasterGUID ? m_originalCaster : m_caster; |
---|
2320 | |
---|
2321 | // Skip if m_originalCaster not available |
---|
2322 | if (!caster) |
---|
2323 | return; |
---|
2324 | |
---|
2325 | int32 addhealth = damage; |
---|
2326 | |
---|
2327 | // Vessel of the Naaru (Vial of the Sunwell trinket) |
---|
2328 | if (m_spellInfo->Id == 45064) |
---|
2329 | { |
---|
2330 | // Amount of heal - depends from stacked Holy Energy |
---|
2331 | int damageAmount = 0; |
---|
2332 | Unit::AuraList const& mDummyAuras = m_caster->GetAurasByType(SPELL_AURA_DUMMY); |
---|
2333 | for(Unit::AuraList::const_iterator i = mDummyAuras.begin();i != mDummyAuras.end(); ++i) |
---|
2334 | if((*i)->GetId() == 45062) |
---|
2335 | damageAmount+=(*i)->GetModifier()->m_amount; |
---|
2336 | if (damageAmount) |
---|
2337 | m_caster->RemoveAurasDueToSpell(45062); |
---|
2338 | |
---|
2339 | addhealth += damageAmount; |
---|
2340 | } |
---|
2341 | // Swiftmend - consumes Regrowth or Rejuvenation |
---|
2342 | else if (m_spellInfo->TargetAuraState == AURA_STATE_SWIFTMEND && unitTarget->HasAuraState(AURA_STATE_SWIFTMEND)) |
---|
2343 | { |
---|
2344 | Unit::AuraList const& RejorRegr = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_HEAL); |
---|
2345 | // find most short by duration |
---|
2346 | Aura *targetAura = NULL; |
---|
2347 | for(Unit::AuraList::const_iterator i = RejorRegr.begin(); i != RejorRegr.end(); ++i) |
---|
2348 | { |
---|
2349 | if((*i)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID |
---|
2350 | && ((*i)->GetSpellProto()->SpellFamilyFlags == 0x40 || (*i)->GetSpellProto()->SpellFamilyFlags == 0x10) ) |
---|
2351 | { |
---|
2352 | if(!targetAura || (*i)->GetAuraDuration() < targetAura->GetAuraDuration()) |
---|
2353 | targetAura = *i; |
---|
2354 | } |
---|
2355 | } |
---|
2356 | |
---|
2357 | if(!targetAura) |
---|
2358 | { |
---|
2359 | sLog.outError("Target(GUID:" I64FMTD ") has aurastate AURA_STATE_SWIFTMEND but no matching aura.", unitTarget->GetGUID()); |
---|
2360 | return; |
---|
2361 | } |
---|
2362 | int idx = 0; |
---|
2363 | while(idx < 3) |
---|
2364 | { |
---|
2365 | if(targetAura->GetSpellProto()->EffectApplyAuraName[idx] == SPELL_AURA_PERIODIC_HEAL) |
---|
2366 | break; |
---|
2367 | idx++; |
---|
2368 | } |
---|
2369 | |
---|
2370 | int32 tickheal = caster->SpellHealingBonus(targetAura->GetSpellProto(), targetAura->GetModifier()->m_amount, DOT, unitTarget); |
---|
2371 | int32 tickcount = GetSpellDuration(targetAura->GetSpellProto()) / targetAura->GetSpellProto()->EffectAmplitude[idx]; |
---|
2372 | unitTarget->RemoveAurasDueToSpell(targetAura->GetId()); |
---|
2373 | |
---|
2374 | addhealth += tickheal * tickcount; |
---|
2375 | } |
---|
2376 | else |
---|
2377 | addhealth = caster->SpellHealingBonus(m_spellInfo, addhealth,HEAL, unitTarget); |
---|
2378 | |
---|
2379 | bool crit = caster->isSpellCrit(unitTarget, m_spellInfo, m_spellSchoolMask, m_attackType); |
---|
2380 | if (crit) |
---|
2381 | addhealth = caster->SpellCriticalBonus(m_spellInfo, addhealth, unitTarget); |
---|
2382 | caster->SendHealSpellLog(unitTarget, m_spellInfo->Id, addhealth, crit); |
---|
2383 | |
---|
2384 | int32 gain = unitTarget->ModifyHealth( int32(addhealth) ); |
---|
2385 | unitTarget->getHostilRefManager().threatAssist(m_caster, float(gain) * 0.5f, m_spellInfo); |
---|
2386 | |
---|
2387 | if(caster->GetTypeId()==TYPEID_PLAYER) |
---|
2388 | if(BattleGround *bg = ((Player*)caster)->GetBattleGround()) |
---|
2389 | bg->UpdatePlayerScore(((Player*)caster), SCORE_HEALING_DONE, gain); |
---|
2390 | |
---|
2391 | // ignore item heals |
---|
2392 | if(m_CastItem) |
---|
2393 | return; |
---|
2394 | |
---|
2395 | uint32 procHealer = PROC_FLAG_HEAL; |
---|
2396 | if (crit) |
---|
2397 | procHealer |= PROC_FLAG_CRIT_HEAL; |
---|
2398 | |
---|
2399 | m_caster->ProcDamageAndSpell(unitTarget,procHealer,PROC_FLAG_HEALED,addhealth,SPELL_SCHOOL_MASK_NONE,m_spellInfo,m_IsTriggeredSpell); |
---|
2400 | } |
---|
2401 | } |
---|
2402 | |
---|
2403 | void Spell::EffectHealPct( uint32 /*i*/ ) |
---|
2404 | { |
---|
2405 | if( unitTarget && unitTarget->isAlive() && damage >= 0) |
---|
2406 | { |
---|
2407 | // Try to get original caster |
---|
2408 | Unit *caster = m_originalCasterGUID ? m_originalCaster : m_caster; |
---|
2409 | |
---|
2410 | // Skip if m_originalCaster not available |
---|
2411 | if (!caster) |
---|
2412 | return; |
---|
2413 | |
---|
2414 | uint32 addhealth = unitTarget->GetMaxHealth() * damage / 100; |
---|
2415 | caster->SendHealSpellLog(unitTarget, m_spellInfo->Id, addhealth, false); |
---|
2416 | |
---|
2417 | int32 gain = unitTarget->ModifyHealth( int32(addhealth) ); |
---|
2418 | unitTarget->getHostilRefManager().threatAssist(m_caster, float(gain) * 0.5f, m_spellInfo); |
---|
2419 | |
---|
2420 | if(caster->GetTypeId()==TYPEID_PLAYER) |
---|
2421 | if(BattleGround *bg = ((Player*)caster)->GetBattleGround()) |
---|
2422 | bg->UpdatePlayerScore(((Player*)caster), SCORE_HEALING_DONE, gain); |
---|
2423 | } |
---|
2424 | } |
---|
2425 | |
---|
2426 | void Spell::EffectHealMechanical( uint32 /*i*/ ) |
---|
2427 | { |
---|
2428 | // Mechanic creature type should be correctly checked by targetCreatureType field |
---|
2429 | if( unitTarget && unitTarget->isAlive() && damage >= 0) |
---|
2430 | { |
---|
2431 | // Try to get original caster |
---|
2432 | Unit *caster = m_originalCasterGUID ? m_originalCaster : m_caster; |
---|
2433 | |
---|
2434 | // Skip if m_originalCaster not available |
---|
2435 | if (!caster) |
---|
2436 | return; |
---|
2437 | |
---|
2438 | uint32 addhealth = caster->SpellHealingBonus(m_spellInfo, uint32(damage), HEAL, unitTarget); |
---|
2439 | caster->SendHealSpellLog(unitTarget, m_spellInfo->Id, addhealth, false); |
---|
2440 | unitTarget->ModifyHealth( int32(damage) ); |
---|
2441 | } |
---|
2442 | } |
---|
2443 | |
---|
2444 | void Spell::EffectHealthLeech(uint32 i) |
---|
2445 | { |
---|
2446 | if(!unitTarget) |
---|
2447 | return; |
---|
2448 | if(!unitTarget->isAlive()) |
---|
2449 | return; |
---|
2450 | |
---|
2451 | if(damage < 0) |
---|
2452 | return; |
---|
2453 | |
---|
2454 | sLog.outDebug("HealthLeech :%i", damage); |
---|
2455 | |
---|
2456 | float multiplier = m_spellInfo->EffectMultipleValue[i]; |
---|
2457 | |
---|
2458 | if(Player *modOwner = m_caster->GetSpellModOwner()) |
---|
2459 | modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_MULTIPLE_VALUE, multiplier); |
---|
2460 | |
---|
2461 | int32 new_damage = int32(damage*multiplier); |
---|
2462 | uint32 curHealth = unitTarget->GetHealth(); |
---|
2463 | new_damage = m_caster->SpellNonMeleeDamageLog(unitTarget, m_spellInfo->Id, new_damage, m_IsTriggeredSpell, true); |
---|
2464 | if(curHealth < new_damage) |
---|
2465 | new_damage = curHealth; |
---|
2466 | |
---|
2467 | if(m_caster->isAlive()) |
---|
2468 | { |
---|
2469 | new_damage = m_caster->SpellHealingBonus(m_spellInfo, new_damage, HEAL, m_caster); |
---|
2470 | |
---|
2471 | m_caster->ModifyHealth(new_damage); |
---|
2472 | |
---|
2473 | if(m_caster->GetTypeId() == TYPEID_PLAYER) |
---|
2474 | m_caster->SendHealSpellLog(m_caster, m_spellInfo->Id, uint32(new_damage)); |
---|
2475 | } |
---|
2476 | } |
---|
2477 | |
---|
2478 | void Spell::DoCreateItem(uint32 i, uint32 itemtype) |
---|
2479 | { |
---|
2480 | if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) |
---|
2481 | return; |
---|
2482 | |
---|
2483 | Player* player = (Player*)unitTarget; |
---|
2484 | |
---|
2485 | uint32 newitemid = itemtype; |
---|
2486 | ItemPrototype const *pProto = objmgr.GetItemPrototype( newitemid ); |
---|
2487 | if(!pProto) |
---|
2488 | { |
---|
2489 | player->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL ); |
---|
2490 | return; |
---|
2491 | } |
---|
2492 | |
---|
2493 | uint32 num_to_add; |
---|
2494 | |
---|
2495 | // TODO: maybe all this can be replaced by using correct calculated `damage` value |
---|
2496 | if(pProto->Class != ITEM_CLASS_CONSUMABLE || m_spellInfo->SpellFamilyName != SPELLFAMILY_MAGE) |
---|
2497 | { |
---|
2498 | int32 basePoints = m_currentBasePoints[i]; |
---|
2499 | int32 randomPoints = m_spellInfo->EffectDieSides[i]; |
---|
2500 | if (randomPoints) |
---|
2501 | num_to_add = basePoints + irand(1, randomPoints); |
---|
2502 | else |
---|
2503 | num_to_add = basePoints + 1; |
---|
2504 | } |
---|
2505 | else if (pProto->MaxCount == 1) |
---|
2506 | num_to_add = 1; |
---|
2507 | else if(player->getLevel() >= m_spellInfo->spellLevel) |
---|
2508 | { |
---|
2509 | int32 basePoints = m_currentBasePoints[i]; |
---|
2510 | float pointPerLevel = m_spellInfo->EffectRealPointsPerLevel[i]; |
---|
2511 | num_to_add = basePoints + 1 + uint32((player->getLevel() - m_spellInfo->spellLevel)*pointPerLevel); |
---|
2512 | } |
---|
2513 | else |
---|
2514 | num_to_add = 2; |
---|
2515 | |
---|
2516 | if (num_to_add < 1) |
---|
2517 | num_to_add = 1; |
---|
2518 | if (num_to_add > pProto->Stackable) |
---|
2519 | num_to_add = pProto->Stackable; |
---|
2520 | |
---|
2521 | // init items_count to 1, since 1 item will be created regardless of specialization |
---|
2522 | int items_count=1; |
---|
2523 | // the chance to create additional items |
---|
2524 | float additionalCreateChance=0.0f; |
---|
2525 | // the maximum number of created additional items |
---|
2526 | uint8 additionalMaxNum=0; |
---|
2527 | // get the chance and maximum number for creating extra items |
---|
2528 | if ( canCreateExtraItems(player, m_spellInfo->Id, additionalCreateChance, additionalMaxNum) ) |
---|
2529 | { |
---|
2530 | // roll with this chance till we roll not to create or we create the max num |
---|
2531 | while ( roll_chance_f(additionalCreateChance) && items_count<=additionalMaxNum ) |
---|
2532 | ++items_count; |
---|
2533 | } |
---|
2534 | |
---|
2535 | // really will be created more items |
---|
2536 | num_to_add *= items_count; |
---|
2537 | |
---|
2538 | // can the player store the new item? |
---|
2539 | ItemPosCountVec dest; |
---|
2540 | uint32 no_space = 0; |
---|
2541 | uint8 msg = player->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, newitemid, num_to_add, &no_space ); |
---|
2542 | if( msg != EQUIP_ERR_OK ) |
---|
2543 | { |
---|
2544 | // convert to possible store amount |
---|
2545 | if( msg == EQUIP_ERR_INVENTORY_FULL || msg == EQUIP_ERR_CANT_CARRY_MORE_OF_THIS ) |
---|
2546 | num_to_add -= no_space; |
---|
2547 | else |
---|
2548 | { |
---|
2549 | // if not created by another reason from full inventory or unique items amount limitation |
---|
2550 | player->SendEquipError( msg, NULL, NULL ); |
---|
2551 | return; |
---|
2552 | } |
---|
2553 | } |
---|
2554 | |
---|
2555 | if(num_to_add) |
---|
2556 | { |
---|
2557 | // create the new item and store it |
---|
2558 | Item* pItem = player->StoreNewItem( dest, newitemid, true, Item::GenerateItemRandomPropertyId(newitemid)); |
---|
2559 | |
---|
2560 | // was it successful? return error if not |
---|
2561 | if(!pItem) |
---|
2562 | { |
---|
2563 | player->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL ); |
---|
2564 | return; |
---|
2565 | } |
---|
2566 | |
---|
2567 | // set the "Crafted by ..." property of the item |
---|
2568 | if( pItem->GetProto()->Class != ITEM_CLASS_CONSUMABLE && pItem->GetProto()->Class != ITEM_CLASS_QUEST) |
---|
2569 | pItem->SetUInt32Value(ITEM_FIELD_CREATOR,player->GetGUIDLow()); |
---|
2570 | |
---|
2571 | // send info to the client |
---|
2572 | if(pItem) |
---|
2573 | player->SendNewItem(pItem, num_to_add, true, true); |
---|
2574 | |
---|
2575 | // we succeeded in creating at least one item, so a levelup is possible |
---|
2576 | player->UpdateCraftSkill(m_spellInfo->Id); |
---|
2577 | } |
---|
2578 | |
---|
2579 | // for battleground marks send by mail if not add all expected |
---|
2580 | if(no_space > 0 ) |
---|
2581 | { |
---|
2582 | BattleGroundTypeId bgType; |
---|
2583 | switch(m_spellInfo->Id) |
---|
2584 | { |
---|
2585 | case SPELL_AV_MARK_WINNER: |
---|
2586 | case SPELL_AV_MARK_LOSER: |
---|
2587 | bgType = BATTLEGROUND_AV; |
---|
2588 | break; |
---|
2589 | case SPELL_WS_MARK_WINNER: |
---|
2590 | case SPELL_WS_MARK_LOSER: |
---|
2591 | bgType = BATTLEGROUND_WS; |
---|
2592 | break; |
---|
2593 | case SPELL_AB_MARK_WINNER: |
---|
2594 | case SPELL_AB_MARK_LOSER: |
---|
2595 | bgType = BATTLEGROUND_AB; |
---|
2596 | break; |
---|
2597 | default: |
---|
2598 | return; |
---|
2599 | } |
---|
2600 | |
---|
2601 | if(BattleGround* bg = sBattleGroundMgr.GetBattleGroundTemplate(bgType)) |
---|
2602 | bg->SendRewardMarkByMail(player,newitemid,no_space); |
---|
2603 | } |
---|
2604 | } |
---|
2605 | |
---|
2606 | void Spell::EffectCreateItem(uint32 i) |
---|
2607 | { |
---|
2608 | DoCreateItem(i,m_spellInfo->EffectItemType[i]); |
---|
2609 | } |
---|
2610 | |
---|
2611 | void Spell::EffectPersistentAA(uint32 i) |
---|
2612 | { |
---|
2613 | float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i])); |
---|
2614 | |
---|
2615 | if(Player* modOwner = m_caster->GetSpellModOwner()) |
---|
2616 | modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RADIUS, radius); |
---|
2617 | |
---|
2618 | int32 duration = GetSpellDuration(m_spellInfo); |
---|
2619 | DynamicObject* dynObj = new DynamicObject; |
---|
2620 | if(!dynObj->Create(objmgr.GenerateLowGuid(HIGHGUID_DYNAMICOBJECT), m_caster, m_spellInfo->Id, i, m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ, duration, radius)) |
---|
2621 | { |
---|
2622 | delete dynObj; |
---|
2623 | return; |
---|
2624 | } |
---|
2625 | dynObj->SetUInt32Value(OBJECT_FIELD_TYPE, 65); |
---|
2626 | dynObj->SetUInt32Value(GAMEOBJECT_DISPLAYID, 368003); |
---|
2627 | dynObj->SetUInt32Value(DYNAMICOBJECT_BYTES, 0x01eeeeee); |
---|
2628 | m_caster->AddDynObject(dynObj); |
---|
2629 | MapManager::Instance().GetMap(dynObj->GetMapId(), dynObj)->Add(dynObj); |
---|
2630 | } |
---|
2631 | |
---|
2632 | void Spell::EffectEnergize(uint32 i) |
---|
2633 | { |
---|
2634 | if(!unitTarget) |
---|
2635 | return; |
---|
2636 | if(!unitTarget->isAlive()) |
---|
2637 | return; |
---|
2638 | |
---|
2639 | if(m_spellInfo->EffectMiscValue[i] < 0 || m_spellInfo->EffectMiscValue[i] >= MAX_POWERS) |
---|
2640 | return; |
---|
2641 | |
---|
2642 | // Some level depends spells |
---|
2643 | int multipler = 0; |
---|
2644 | int level_diff = 0; |
---|
2645 | switch (m_spellInfo->Id) |
---|
2646 | { |
---|
2647 | // Restore Energy |
---|
2648 | case 9512: |
---|
2649 | level_diff = m_caster->getLevel() - 40; |
---|
2650 | multipler = 2; |
---|
2651 | break; |
---|
2652 | // Blood Fury |
---|
2653 | case 24571: |
---|
2654 | level_diff = m_caster->getLevel() - 60; |
---|
2655 | multipler = 10; |
---|
2656 | break; |
---|
2657 | // Burst of Energy |
---|
2658 | case 24532: |
---|
2659 | level_diff = m_caster->getLevel() - 60; |
---|
2660 | multipler = 4; |
---|
2661 | break; |
---|
2662 | default: |
---|
2663 | break; |
---|
2664 | } |
---|
2665 | |
---|
2666 | if (level_diff > 0) |
---|
2667 | damage -= multipler * level_diff; |
---|
2668 | |
---|
2669 | if(damage < 0) |
---|
2670 | return; |
---|
2671 | |
---|
2672 | Powers power = Powers(m_spellInfo->EffectMiscValue[i]); |
---|
2673 | |
---|
2674 | if(unitTarget->GetMaxPower(power) == 0) |
---|
2675 | return; |
---|
2676 | |
---|
2677 | unitTarget->ModifyPower(power,damage); |
---|
2678 | m_caster->SendEnergizeSpellLog(unitTarget, m_spellInfo->Id, damage, power); |
---|
2679 | |
---|
2680 | // Mad Alchemist's Potion |
---|
2681 | if (m_spellInfo->Id == 45051) |
---|
2682 | { |
---|
2683 | // find elixirs on target |
---|
2684 | uint32 elixir_mask = 0; |
---|
2685 | Unit::AuraMap& Auras = unitTarget->GetAuras(); |
---|
2686 | for(Unit::AuraMap::iterator itr = Auras.begin(); itr != Auras.end(); ++itr) |
---|
2687 | { |
---|
2688 | uint32 spell_id = itr->second->GetId(); |
---|
2689 | if(uint32 mask = spellmgr.GetSpellElixirMask(spell_id)) |
---|
2690 | elixir_mask |= mask; |
---|
2691 | } |
---|
2692 | |
---|
2693 | // get available elixir mask any not active type from battle/guardian (and flask if no any) |
---|
2694 | elixir_mask = (elixir_mask & ELIXIR_FLASK_MASK) ^ ELIXIR_FLASK_MASK; |
---|
2695 | |
---|
2696 | // get all available elixirs by mask and spell level |
---|
2697 | std::vector<uint32> elixirs; |
---|
2698 | SpellElixirMap const& m_spellElixirs = spellmgr.GetSpellElixirMap(); |
---|
2699 | for(SpellElixirMap::const_iterator itr = m_spellElixirs.begin(); itr != m_spellElixirs.end(); ++itr) |
---|
2700 | { |
---|
2701 | if (itr->second & elixir_mask) |
---|
2702 | { |
---|
2703 | if (itr->second & (ELIXIR_UNSTABLE_MASK | ELIXIR_SHATTRATH_MASK)) |
---|
2704 | continue; |
---|
2705 | |
---|
2706 | SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first); |
---|
2707 | if (spellInfo && (spellInfo->spellLevel < m_spellInfo->spellLevel || spellInfo->spellLevel > unitTarget->getLevel())) |
---|
2708 | continue; |
---|
2709 | |
---|
2710 | elixirs.push_back(itr->first); |
---|
2711 | } |
---|
2712 | } |
---|
2713 | |
---|
2714 | if (!elixirs.empty()) |
---|
2715 | { |
---|
2716 | // cast random elixir on target |
---|
2717 | uint32 rand_spell = urand(0,elixirs.size()-1); |
---|
2718 | m_caster->CastSpell(unitTarget,elixirs[rand_spell],true,m_CastItem); |
---|
2719 | } |
---|
2720 | } |
---|
2721 | } |
---|
2722 | |
---|
2723 | void Spell::EffectEnergisePct(uint32 i) |
---|
2724 | { |
---|
2725 | if(!unitTarget) |
---|
2726 | return; |
---|
2727 | if(!unitTarget->isAlive()) |
---|
2728 | return; |
---|
2729 | |
---|
2730 | if(m_spellInfo->EffectMiscValue[i] < 0 || m_spellInfo->EffectMiscValue[i] >= MAX_POWERS) |
---|
2731 | return; |
---|
2732 | |
---|
2733 | Powers power = Powers(m_spellInfo->EffectMiscValue[i]); |
---|
2734 | |
---|
2735 | uint32 maxPower = unitTarget->GetMaxPower(power); |
---|
2736 | if(maxPower == 0) |
---|
2737 | return; |
---|
2738 | |
---|
2739 | uint32 gain = damage * maxPower / 100; |
---|
2740 | unitTarget->ModifyPower(power, gain); |
---|
2741 | m_caster->SendEnergizeSpellLog(unitTarget, m_spellInfo->Id, damage, power); |
---|
2742 | } |
---|
2743 | |
---|
2744 | void Spell::SendLoot(uint64 guid, LootType loottype) |
---|
2745 | { |
---|
2746 | Player* player = (Player*)m_caster; |
---|
2747 | if (!player) |
---|
2748 | return; |
---|
2749 | |
---|
2750 | if (gameObjTarget) |
---|
2751 | { |
---|
2752 | switch (gameObjTarget->GetGoType()) |
---|
2753 | { |
---|
2754 | case GAMEOBJECT_TYPE_DOOR: |
---|
2755 | case GAMEOBJECT_TYPE_BUTTON: |
---|
2756 | gameObjTarget->UseDoorOrButton(); |
---|
2757 | sWorld.ScriptsStart(sGameObjectScripts, gameObjTarget->GetDBTableGUIDLow(), player, gameObjTarget); |
---|
2758 | return; |
---|
2759 | |
---|
2760 | case GAMEOBJECT_TYPE_QUESTGIVER: |
---|
2761 | // start or end quest |
---|
2762 | player->PrepareQuestMenu(guid); |
---|
2763 | player->SendPreparedQuest(guid); |
---|
2764 | return; |
---|
2765 | |
---|
2766 | case GAMEOBJECT_TYPE_SPELL_FOCUS: |
---|
2767 | // triggering linked GO |
---|
2768 | if(uint32 trapEntry = gameObjTarget->GetGOInfo()->spellFocus.linkedTrapId) |
---|
2769 | gameObjTarget->TriggeringLinkedGameObject(trapEntry,m_caster); |
---|
2770 | return; |
---|
2771 | |
---|
2772 | case GAMEOBJECT_TYPE_GOOBER: |
---|
2773 | // goober_scripts can be triggered if the player don't have the quest |
---|
2774 | if (gameObjTarget->GetGOInfo()->goober.eventId) |
---|
2775 | { |
---|
2776 | sLog.outDebug("Goober ScriptStart id %u for GO %u", gameObjTarget->GetGOInfo()->goober.eventId,gameObjTarget->GetDBTableGUIDLow()); |
---|
2777 | sWorld.ScriptsStart(sEventScripts, gameObjTarget->GetGOInfo()->goober.eventId, player, gameObjTarget); |
---|
2778 | } |
---|
2779 | |
---|
2780 | // cast goober spell |
---|
2781 | if (gameObjTarget->GetGOInfo()->goober.questId) |
---|
2782 | ///Quest require to be active for GO using |
---|
2783 | if(player->GetQuestStatus(gameObjTarget->GetGOInfo()->goober.questId) != QUEST_STATUS_INCOMPLETE) |
---|
2784 | return; |
---|
2785 | |
---|
2786 | gameObjTarget->AddUniqueUse(player); |
---|
2787 | gameObjTarget->SetLootState(GO_JUST_DEACTIVATED); |
---|
2788 | |
---|
2789 | //TODO? Objective counting called without spell check but with quest objective check |
---|
2790 | // if send spell id then this line will duplicate to spell casting call (double counting) |
---|
2791 | // So we or have this line and not required in quest_template have reqSpellIdN |
---|
2792 | // or must remove this line and required in DB have data in quest_template have reqSpellIdN for all quest using cases. |
---|
2793 | player->CastedCreatureOrGO(gameObjTarget->GetEntry(), gameObjTarget->GetGUID(), 0); |
---|
2794 | |
---|
2795 | // triggering linked GO |
---|
2796 | if(uint32 trapEntry = gameObjTarget->GetGOInfo()->goober.linkedTrapId) |
---|
2797 | gameObjTarget->TriggeringLinkedGameObject(trapEntry,m_caster); |
---|
2798 | |
---|
2799 | return; |
---|
2800 | |
---|
2801 | case GAMEOBJECT_TYPE_CHEST: |
---|
2802 | // TODO: possible must be moved to loot release (in different from linked triggering) |
---|
2803 | if (gameObjTarget->GetGOInfo()->chest.eventId) |
---|
2804 | { |
---|
2805 | sLog.outDebug("Chest ScriptStart id %u for GO %u", gameObjTarget->GetGOInfo()->chest.eventId,gameObjTarget->GetDBTableGUIDLow()); |
---|
2806 | sWorld.ScriptsStart(sEventScripts, gameObjTarget->GetGOInfo()->chest.eventId, player, gameObjTarget); |
---|
2807 | } |
---|
2808 | |
---|
2809 | // triggering linked GO |
---|
2810 | if(uint32 trapEntry = gameObjTarget->GetGOInfo()->chest.linkedTrapId) |
---|
2811 | gameObjTarget->TriggeringLinkedGameObject(trapEntry,m_caster); |
---|
2812 | |
---|
2813 | // Don't return, let loots been taken |
---|
2814 | } |
---|
2815 | } |
---|
2816 | |
---|
2817 | // Send loot |
---|
2818 | player->SendLoot(guid, loottype); |
---|
2819 | } |
---|
2820 | |
---|
2821 | void Spell::EffectOpenLock(uint32 /*i*/) |
---|
2822 | { |
---|
2823 | if(!m_caster || m_caster->GetTypeId() != TYPEID_PLAYER) |
---|
2824 | { |
---|
2825 | sLog.outDebug( "WORLD: Open Lock - No Player Caster!"); |
---|
2826 | return; |
---|
2827 | } |
---|
2828 | |
---|
2829 | Player* player = (Player*)m_caster; |
---|
2830 | |
---|
2831 | LootType loottype = LOOT_CORPSE; |
---|
2832 | uint32 lockId = 0; |
---|
2833 | uint64 guid = 0; |
---|
2834 | |
---|
2835 | // Get lockId |
---|
2836 | if(gameObjTarget) |
---|
2837 | { |
---|
2838 | GameObjectInfo const* goInfo = gameObjTarget->GetGOInfo(); |
---|
2839 | // Arathi Basin banner opening ! |
---|
2840 | if( goInfo->type == GAMEOBJECT_TYPE_BUTTON && goInfo->button.noDamageImmune || |
---|
2841 | goInfo->type == GAMEOBJECT_TYPE_GOOBER && goInfo->goober.losOK ) |
---|
2842 | { |
---|
2843 | //isAllowUseBattleGroundObject() already called in CanCast() |
---|
2844 | // in battleground check |
---|
2845 | if(BattleGround *bg = player->GetBattleGround()) |
---|
2846 | { |
---|
2847 | // check if it's correct bg |
---|
2848 | if(bg && bg->GetTypeID() == BATTLEGROUND_AB) |
---|
2849 | bg->EventPlayerClickedOnFlag(player, gameObjTarget); |
---|
2850 | return; |
---|
2851 | } |
---|
2852 | } |
---|
2853 | else if (goInfo->type == GAMEOBJECT_TYPE_FLAGSTAND) |
---|
2854 | { |
---|
2855 | //isAllowUseBattleGroundObject() already called in CanCast() |
---|
2856 | // in battleground check |
---|
2857 | if(BattleGround *bg = player->GetBattleGround()) |
---|
2858 | { |
---|
2859 | if(bg->GetTypeID() == BATTLEGROUND_EY) |
---|
2860 | bg->EventPlayerClickedOnFlag(player, gameObjTarget); |
---|
2861 | return; |
---|
2862 | } |
---|
2863 | } |
---|
2864 | lockId = gameObjTarget->GetLockId(); |
---|
2865 | guid = gameObjTarget->GetGUID(); |
---|
2866 | } |
---|
2867 | else if(itemTarget) |
---|
2868 | { |
---|
2869 | lockId = itemTarget->GetProto()->LockID; |
---|
2870 | guid = itemTarget->GetGUID(); |
---|
2871 | } |
---|
2872 | else |
---|
2873 | { |
---|
2874 | sLog.outDebug( "WORLD: Open Lock - No GameObject/Item Target!"); |
---|
2875 | return; |
---|
2876 | } |
---|
2877 | |
---|
2878 | if(!lockId) // possible case for GO and maybe for items. |
---|
2879 | { |
---|
2880 | SendLoot(guid, loottype); |
---|
2881 | return; |
---|
2882 | } |
---|
2883 | |
---|
2884 | // Get LockInfo |
---|
2885 | LockEntry const *lockInfo = sLockStore.LookupEntry(lockId); |
---|
2886 | |
---|
2887 | if (!lockInfo) |
---|
2888 | { |
---|
2889 | sLog.outError( "Spell::EffectOpenLock: %s [guid = %u] has an unknown lockId: %u!", |
---|
2890 | (gameObjTarget ? "gameobject" : "item"), GUID_LOPART(guid), lockId); |
---|
2891 | SendCastResult(SPELL_FAILED_BAD_TARGETS); |
---|
2892 | return; |
---|
2893 | } |
---|
2894 | |
---|
2895 | // check key |
---|
2896 | for(int i = 0; i < 5; ++i) |
---|
2897 | { |
---|
2898 | // type==1 This means lockInfo->key[i] is an item |
---|
2899 | if(lockInfo->keytype[i]==LOCK_KEY_ITEM && lockInfo->key[i] && m_CastItem && m_CastItem->GetEntry()==lockInfo->key[i]) |
---|
2900 | { |
---|
2901 | SendLoot(guid, loottype); |
---|
2902 | return; |
---|
2903 | } |
---|
2904 | } |
---|
2905 | |
---|
2906 | uint32 SkillId = 0; |
---|
2907 | // Check and skill-up skill |
---|
2908 | if( m_spellInfo->Effect[1] == SPELL_EFFECT_SKILL ) |
---|
2909 | SkillId = m_spellInfo->EffectMiscValue[1]; |
---|
2910 | // pickpocketing spells |
---|
2911 | else if( m_spellInfo->EffectMiscValue[0] == LOCKTYPE_PICKLOCK ) |
---|
2912 | SkillId = SKILL_LOCKPICKING; |
---|
2913 | |
---|
2914 | // skill bonus provided by casting spell (mostly item spells) |
---|
2915 | uint32 spellSkillBonus = uint32(m_currentBasePoints[0]+1); |
---|
2916 | |
---|
2917 | uint32 reqSkillValue = lockInfo->requiredminingskill; |
---|
2918 | |
---|
2919 | if(lockInfo->requiredlockskill) // required pick lock skill applying |
---|
2920 | { |
---|
2921 | if(SkillId != SKILL_LOCKPICKING) // wrong skill (cheating?) |
---|
2922 | { |
---|
2923 | SendCastResult(SPELL_FAILED_FIZZLE); |
---|
2924 | return; |
---|
2925 | } |
---|
2926 | |
---|
2927 | reqSkillValue = lockInfo->requiredlockskill; |
---|
2928 | } |
---|
2929 | else if(SkillId == SKILL_LOCKPICKING) // apply picklock skill to wrong target |
---|
2930 | { |
---|
2931 | SendCastResult(SPELL_FAILED_BAD_TARGETS); |
---|
2932 | return; |
---|
2933 | } |
---|
2934 | |
---|
2935 | if ( SkillId ) |
---|
2936 | { |
---|
2937 | loottype = LOOT_SKINNING; |
---|
2938 | if ( player->GetSkillValue(SkillId) + spellSkillBonus < reqSkillValue ) |
---|
2939 | { |
---|
2940 | SendCastResult(SPELL_FAILED_LOW_CASTLEVEL); |
---|
2941 | return; |
---|
2942 | } |
---|
2943 | |
---|
2944 | // update skill if really known |
---|
2945 | uint32 SkillValue = player->GetPureSkillValue(SkillId); |
---|
2946 | if(SkillValue) // non only item base skill |
---|
2947 | { |
---|
2948 | if(gameObjTarget) |
---|
2949 | { |
---|
2950 | // Allow one skill-up until respawned |
---|
2951 | if ( !gameObjTarget->IsInSkillupList( player->GetGUIDLow() ) && |
---|
2952 | player->UpdateGatherSkill(SkillId, SkillValue, reqSkillValue) ) |
---|
2953 | gameObjTarget->AddToSkillupList( player->GetGUIDLow() ); |
---|
2954 | } |
---|
2955 | else if(itemTarget) |
---|
2956 | { |
---|
2957 | // Do one skill-up |
---|
2958 | uint32 SkillValue = player->GetPureSkillValue(SkillId); |
---|
2959 | player->UpdateGatherSkill(SkillId, SkillValue, reqSkillValue); |
---|
2960 | } |
---|
2961 | } |
---|
2962 | } |
---|
2963 | |
---|
2964 | SendLoot(guid, loottype); |
---|
2965 | } |
---|
2966 | |
---|
2967 | void Spell::EffectSummonChangeItem(uint32 i) |
---|
2968 | { |
---|
2969 | if(m_caster->GetTypeId() != TYPEID_PLAYER) |
---|
2970 | return; |
---|
2971 | |
---|
2972 | Player *player = (Player*)m_caster; |
---|
2973 | |
---|
2974 | // applied only to using item |
---|
2975 | if(!m_CastItem) |
---|
2976 | return; |
---|
2977 | |
---|
2978 | // ... only to item in own inventory/bank/equip_slot |
---|
2979 | if(m_CastItem->GetOwnerGUID()!=player->GetGUID()) |
---|
2980 | return; |
---|
2981 | |
---|
2982 | uint32 newitemid = m_spellInfo->EffectItemType[i]; |
---|
2983 | if(!newitemid) |
---|
2984 | return; |
---|
2985 | |
---|
2986 | uint16 pos = m_CastItem->GetPos(); |
---|
2987 | |
---|
2988 | Item *pNewItem = Item::CreateItem( newitemid, 1, player); |
---|
2989 | if( !pNewItem ) |
---|
2990 | return; |
---|
2991 | |
---|
2992 | for(uint8 i= PERM_ENCHANTMENT_SLOT; i<=TEMP_ENCHANTMENT_SLOT; ++i) |
---|
2993 | { |
---|
2994 | if(m_CastItem->GetEnchantmentId(EnchantmentSlot(i))) |
---|
2995 | pNewItem->SetEnchantment(EnchantmentSlot(i), m_CastItem->GetEnchantmentId(EnchantmentSlot(i)), m_CastItem->GetEnchantmentDuration(EnchantmentSlot(i)), m_CastItem->GetEnchantmentCharges(EnchantmentSlot(i))); |
---|
2996 | } |
---|
2997 | |
---|
2998 | if(m_CastItem->GetUInt32Value(ITEM_FIELD_DURABILITY) < m_CastItem->GetUInt32Value(ITEM_FIELD_MAXDURABILITY)) |
---|
2999 | { |
---|
3000 | double loosePercent = 1 - m_CastItem->GetUInt32Value(ITEM_FIELD_DURABILITY) / double(m_CastItem->GetUInt32Value(ITEM_FIELD_MAXDURABILITY)); |
---|
3001 | player->DurabilityLoss(pNewItem, loosePercent); |
---|
3002 | } |
---|
3003 | |
---|
3004 | if( player->IsInventoryPos( pos ) ) |
---|
3005 | { |
---|
3006 | ItemPosCountVec dest; |
---|
3007 | uint8 msg = player->CanStoreItem( m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), dest, pNewItem, true ); |
---|
3008 | if( msg == EQUIP_ERR_OK ) |
---|
3009 | { |
---|
3010 | player->DestroyItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(),true); |
---|
3011 | |
---|
3012 | // prevent crash at access and unexpected charges counting with item update queue corrupt |
---|
3013 | if(m_CastItem==m_targets.getItemTarget()) |
---|
3014 | m_targets.setItemTarget(NULL); |
---|
3015 | |
---|
3016 | m_CastItem = NULL; |
---|
3017 | |
---|
3018 | player->StoreItem( dest, pNewItem, true); |
---|
3019 | return; |
---|
3020 | } |
---|
3021 | } |
---|
3022 | else if( player->IsBankPos ( pos ) ) |
---|
3023 | { |
---|
3024 | ItemPosCountVec dest; |
---|
3025 | uint8 msg = player->CanBankItem( m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), dest, pNewItem, true ); |
---|
3026 | if( msg == EQUIP_ERR_OK ) |
---|
3027 | { |
---|
3028 | player->DestroyItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(),true); |
---|
3029 | |
---|
3030 | // prevent crash at access and unexpected charges counting with item update queue corrupt |
---|
3031 | if(m_CastItem==m_targets.getItemTarget()) |
---|
3032 | m_targets.setItemTarget(NULL); |
---|
3033 | |
---|
3034 | m_CastItem = NULL; |
---|
3035 | |
---|
3036 | player->BankItem( dest, pNewItem, true); |
---|
3037 | return; |
---|
3038 | } |
---|
3039 | } |
---|
3040 | else if( player->IsEquipmentPos ( pos ) ) |
---|
3041 | { |
---|
3042 | uint16 dest; |
---|
3043 | uint8 msg = player->CanEquipItem( m_CastItem->GetSlot(), dest, pNewItem, true ); |
---|
3044 | if( msg == EQUIP_ERR_OK ) |
---|
3045 | { |
---|
3046 | player->DestroyItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(),true); |
---|
3047 | |
---|
3048 | // prevent crash at access and unexpected charges counting with item update queue corrupt |
---|
3049 | if(m_CastItem==m_targets.getItemTarget()) |
---|
3050 | m_targets.setItemTarget(NULL); |
---|
3051 | |
---|
3052 | m_CastItem = NULL; |
---|
3053 | |
---|
3054 | player->EquipItem( dest, pNewItem, true); |
---|
3055 | player->AutoUnequipOffhandIfNeed(); |
---|
3056 | return; |
---|
3057 | } |
---|
3058 | } |
---|
3059 | |
---|
3060 | // fail |
---|
3061 | delete pNewItem; |
---|
3062 | } |
---|
3063 | |
---|
3064 | void Spell::EffectOpenSecretSafe(uint32 i) |
---|
3065 | { |
---|
3066 | EffectOpenLock(i); //no difference for now |
---|
3067 | } |
---|
3068 | |
---|
3069 | void Spell::EffectProficiency(uint32 /*i*/) |
---|
3070 | { |
---|
3071 | if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) |
---|
3072 | return; |
---|
3073 | Player *p_target = (Player*)unitTarget; |
---|
3074 | |
---|
3075 | uint32 subClassMask = m_spellInfo->EquippedItemSubClassMask; |
---|
3076 | if(m_spellInfo->EquippedItemClass == 2 && !(p_target->GetWeaponProficiency() & subClassMask)) |
---|
3077 | { |
---|
3078 | p_target->AddWeaponProficiency(subClassMask); |
---|
3079 | p_target->SendProficiency(uint8(0x02),p_target->GetWeaponProficiency()); |
---|
3080 | } |
---|
3081 | if(m_spellInfo->EquippedItemClass == 4 && !(p_target->GetArmorProficiency() & subClassMask)) |
---|
3082 | { |
---|
3083 | p_target->AddArmorProficiency(subClassMask); |
---|
3084 | p_target->SendProficiency(uint8(0x04),p_target->GetArmorProficiency()); |
---|
3085 | } |
---|
3086 | } |
---|
3087 | |
---|
3088 | void Spell::EffectApplyAreaAura(uint32 i) |
---|
3089 | { |
---|
3090 | if(!unitTarget) |
---|
3091 | return; |
---|
3092 | if(!unitTarget->isAlive()) |
---|
3093 | return; |
---|
3094 | |
---|
3095 | AreaAura* Aur = new AreaAura(m_spellInfo, i, &m_currentBasePoints[i], unitTarget, m_caster, m_CastItem); |
---|
3096 | unitTarget->AddAura(Aur); |
---|
3097 | } |
---|
3098 | |
---|
3099 | void Spell::EffectSummonType(uint32 i) |
---|
3100 | { |
---|
3101 | switch(m_spellInfo->EffectMiscValueB[i]) |
---|
3102 | { |
---|
3103 | case SUMMON_TYPE_GUARDIAN: |
---|
3104 | case SUMMON_TYPE_POSESSED: |
---|
3105 | case SUMMON_TYPE_POSESSED2: |
---|
3106 | EffectSummonGuardian(i); |
---|
3107 | break; |
---|
3108 | case SUMMON_TYPE_WILD: |
---|
3109 | EffectSummonWild(i); |
---|
3110 | break; |
---|
3111 | case SUMMON_TYPE_DEMON: |
---|
3112 | EffectSummonDemon(i); |
---|
3113 | break; |
---|
3114 | case SUMMON_TYPE_SUMMON: |
---|
3115 | EffectSummon(i); |
---|
3116 | break; |
---|
3117 | case SUMMON_TYPE_CRITTER: |
---|
3118 | case SUMMON_TYPE_CRITTER2: |
---|
3119 | EffectSummonCritter(i); |
---|
3120 | break; |
---|
3121 | case SUMMON_TYPE_TOTEM_SLOT1: |
---|
3122 | case SUMMON_TYPE_TOTEM_SLOT2: |
---|
3123 | case SUMMON_TYPE_TOTEM_SLOT3: |
---|
3124 | case SUMMON_TYPE_TOTEM_SLOT4: |
---|
3125 | case SUMMON_TYPE_TOTEM: |
---|
3126 | EffectSummonTotem(i); |
---|
3127 | break; |
---|
3128 | case SUMMON_TYPE_UNKNOWN1: |
---|
3129 | case SUMMON_TYPE_UNKNOWN2: |
---|
3130 | case SUMMON_TYPE_UNKNOWN3: |
---|
3131 | case SUMMON_TYPE_UNKNOWN4: |
---|
3132 | case SUMMON_TYPE_UNKNOWN5: |
---|
3133 | case SUMMON_TYPE_UNKNOWN6: |
---|
3134 | break; |
---|
3135 | default: |
---|
3136 | sLog.outError("EffectSummonType: Unhandled summon type %u", m_spellInfo->EffectMiscValueB[i]); |
---|
3137 | break; |
---|
3138 | } |
---|
3139 | } |
---|
3140 | |
---|
3141 | void Spell::EffectSummon(uint32 i) |
---|
3142 | { |
---|
3143 | if(m_caster->GetPetGUID()) |
---|
3144 | return; |
---|
3145 | |
---|
3146 | if(!unitTarget) |
---|
3147 | return; |
---|
3148 | uint32 pet_entry = m_spellInfo->EffectMiscValue[i]; |
---|
3149 | if(!pet_entry) |
---|
3150 | return; |
---|
3151 | uint32 level = m_caster->getLevel(); |
---|
3152 | Pet* spawnCreature = new Pet(SUMMON_PET); |
---|
3153 | |
---|
3154 | if(spawnCreature->LoadPetFromDB(m_caster,pet_entry)) |
---|
3155 | { |
---|
3156 | // set timer for unsummon |
---|
3157 | int32 duration = GetSpellDuration(m_spellInfo); |
---|
3158 | if(duration > 0) |
---|
3159 | spawnCreature->SetDuration(duration); |
---|
3160 | |
---|
3161 | return; |
---|
3162 | } |
---|
3163 | |
---|
3164 | Map *map = m_caster->GetMap(); |
---|
3165 | uint32 pet_number = objmgr.GeneratePetNumber(); |
---|
3166 | if(!spawnCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_PET),map,m_spellInfo->EffectMiscValue[i], pet_number)) |
---|
3167 | { |
---|
3168 | sLog.outErrorDb("Spell::EffectSummon: no such creature entry %u",m_spellInfo->EffectMiscValue[i]); |
---|
3169 | delete spawnCreature; |
---|
3170 | return; |
---|
3171 | } |
---|
3172 | |
---|
3173 | // Summon in dest location |
---|
3174 | float x,y,z; |
---|
3175 | if(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION) |
---|
3176 | { |
---|
3177 | x = m_targets.m_destX; |
---|
3178 | y = m_targets.m_destY; |
---|
3179 | z = m_targets.m_destZ; |
---|
3180 | } |
---|
3181 | else |
---|
3182 | m_caster->GetClosePoint(x,y,z,spawnCreature->GetObjectSize()); |
---|
3183 | |
---|
3184 | spawnCreature->Relocate(x,y,z,-m_caster->GetOrientation()); |
---|
3185 | |
---|
3186 | if(!spawnCreature->IsPositionValid()) |
---|
3187 | { |
---|
3188 | sLog.outError("ERROR: Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %d Y: ^%d)", spawnCreature->GetGUIDLow(), spawnCreature->GetEntry(), spawnCreature->GetPositionX(), spawnCreature->GetPositionY()); |
---|
3189 | delete spawnCreature; |
---|
3190 | return; |
---|
3191 | } |
---|
3192 | |
---|
3193 | // set timer for unsummon |
---|
3194 | int32 duration = GetSpellDuration(m_spellInfo); |
---|
3195 | if(duration > 0) |
---|
3196 | spawnCreature->SetDuration(duration); |
---|
3197 | |
---|
3198 | spawnCreature->SetUInt64Value(UNIT_FIELD_SUMMONEDBY,m_caster->GetGUID()); |
---|
3199 | spawnCreature->SetUInt32Value(UNIT_NPC_FLAGS , 0); |
---|
3200 | spawnCreature->setPowerType(POWER_MANA); |
---|
3201 | spawnCreature->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,m_caster->getFaction()); |
---|
3202 | spawnCreature->SetUInt32Value(UNIT_FIELD_FLAGS,0); |
---|
3203 | spawnCreature->SetUInt32Value(UNIT_FIELD_BYTES_0,2048); |
---|
3204 | spawnCreature->SetUInt32Value(UNIT_FIELD_BYTES_1,0); |
---|
3205 | spawnCreature->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP,0); |
---|
3206 | spawnCreature->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE,0); |
---|
3207 | spawnCreature->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP,1000); |
---|
3208 | spawnCreature->SetUInt64Value(UNIT_FIELD_CREATEDBY, m_caster->GetGUID()); |
---|
3209 | spawnCreature->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id); |
---|
3210 | |
---|
3211 | spawnCreature->InitStatsForLevel(level); |
---|
3212 | |
---|
3213 | spawnCreature->GetCharmInfo()->SetPetNumber(pet_number, false); |
---|
3214 | |
---|
3215 | spawnCreature->AIM_Initialize(); |
---|
3216 | spawnCreature->InitPetCreateSpells(); |
---|
3217 | spawnCreature->SetHealth(spawnCreature->GetMaxHealth()); |
---|
3218 | spawnCreature->SetPower(POWER_MANA, spawnCreature->GetMaxPower(POWER_MANA)); |
---|
3219 | |
---|
3220 | std::string name = m_caster->GetName(); |
---|
3221 | name.append(petTypeSuffix[spawnCreature->getPetType()]); |
---|
3222 | spawnCreature->SetName( name ); |
---|
3223 | |
---|
3224 | map->Add((Creature*)spawnCreature); |
---|
3225 | |
---|
3226 | if(m_caster->GetTypeId() == TYPEID_PLAYER) |
---|
3227 | { |
---|
3228 | m_caster->SetPet(spawnCreature); |
---|
3229 | spawnCreature->GetCharmInfo()->SetReactState( REACT_DEFENSIVE ); |
---|
3230 | spawnCreature->SavePetToDB(PET_SAVE_AS_CURRENT); |
---|
3231 | ((Player*)m_caster)->PetSpellInitialize(); |
---|
3232 | } |
---|
3233 | } |
---|
3234 | |
---|
3235 | void Spell::EffectLearnSpell(uint32 i) |
---|
3236 | { |
---|
3237 | if(!unitTarget) |
---|
3238 | return; |
---|
3239 | |
---|
3240 | if(unitTarget->GetTypeId() != TYPEID_PLAYER) |
---|
3241 | { |
---|
3242 | if(m_caster->GetTypeId() == TYPEID_PLAYER) |
---|
3243 | EffectLearnPetSpell(i); |
---|
3244 | |
---|
3245 | return; |
---|
3246 | } |
---|
3247 | |
---|
3248 | Player *player = (Player*)unitTarget; |
---|
3249 | |
---|
3250 | uint32 spellToLearn = (m_spellInfo->Id==SPELL_ID_GENERIC_LEARN) ? damage : m_spellInfo->EffectTriggerSpell[i]; |
---|
3251 | player->learnSpell(spellToLearn); |
---|
3252 | |
---|
3253 | sLog.outDebug( "Spell: Player %u have learned spell %u from NpcGUID=%u", player->GetGUIDLow(), spellToLearn, m_caster->GetGUIDLow() ); |
---|
3254 | } |
---|
3255 | |
---|
3256 | void Spell::EffectDispel(uint32 i) |
---|
3257 | { |
---|
3258 | if(!unitTarget) |
---|
3259 | return; |
---|
3260 | |
---|
3261 | // Fill possible dispell list |
---|
3262 | std::vector <Aura *> dispel_list; |
---|
3263 | |
---|
3264 | // Create dispel mask by dispel type |
---|
3265 | uint32 dispel_type = m_spellInfo->EffectMiscValue[i]; |
---|
3266 | uint32 dispelMask = GetDispellMask( DispelType(dispel_type) ); |
---|
3267 | Unit::AuraMap const& auras = unitTarget->GetAuras(); |
---|
3268 | for(Unit::AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr) |
---|
3269 | { |
---|
3270 | Aura *aur = (*itr).second; |
---|
3271 | if (aur && (1<<aur->GetSpellProto()->Dispel) & dispelMask) |
---|
3272 | { |
---|
3273 | if(aur->GetSpellProto()->Dispel == DISPEL_MAGIC) |
---|
3274 | { |
---|
3275 | bool positive = true; |
---|
3276 | if (!aur->IsPositive()) |
---|
3277 | positive = false; |
---|
3278 | else |
---|
3279 | positive = (aur->GetSpellProto()->AttributesEx & SPELL_ATTR_EX_NEGATIVE)==0; |
---|
3280 | |
---|
3281 | // do not remove positive auras if friendly target |
---|
3282 | // negative auras if non-friendly target |
---|
3283 | if(positive == unitTarget->IsFriendlyTo(m_caster)) |
---|
3284 | continue; |
---|
3285 | } |
---|
3286 | // Add aura to dispel list |
---|
3287 | dispel_list.push_back(aur); |
---|
3288 | } |
---|
3289 | } |
---|
3290 | // Ok if exist some buffs for dispel try dispel it |
---|
3291 | if (!dispel_list.empty()) |
---|
3292 | { |
---|
3293 | std::list < std::pair<uint32,uint64> > success_list;// (spell_id,casterGuid) |
---|
3294 | std::list < uint32 > fail_list; // spell_id |
---|
3295 | int32 list_size = dispel_list.size(); |
---|
3296 | // Dispell N = damage buffs (or while exist buffs for dispel) |
---|
3297 | for (int32 count=0; count < damage && list_size > 0; ++count) |
---|
3298 | { |
---|
3299 | // Random select buff for dispel |
---|
3300 | Aura *aur = dispel_list[urand(0, list_size-1)]; |
---|
3301 | |
---|
3302 | SpellEntry const* spellInfo = aur->GetSpellProto(); |
---|
3303 | // Base dispel chance |
---|
3304 | // TODO: possible chance depend from spell level?? |
---|
3305 | int32 miss_chance = 0; |
---|
3306 | // Apply dispel mod from aura caster |
---|
3307 | if (Unit *caster = aur->GetCaster()) |
---|
3308 | { |
---|
3309 | if ( Player* modOwner = caster->GetSpellModOwner() ) |
---|
3310 | modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_RESIST_DISPEL_CHANCE, miss_chance, this); |
---|
3311 | } |
---|
3312 | // Try dispel |
---|
3313 | if (roll_chance_i(miss_chance)) |
---|
3314 | fail_list.push_back(aur->GetId()); |
---|
3315 | else |
---|
3316 | success_list.push_back(std::pair<uint32,uint64>(aur->GetId(),aur->GetCasterGUID())); |
---|
3317 | // Remove buff from list for prevent doubles |
---|
3318 | for (std::vector<Aura *>::iterator j = dispel_list.begin(); j != dispel_list.end(); ) |
---|
3319 | { |
---|
3320 | Aura *dispeled = *j; |
---|
3321 | if (dispeled->GetId() == aur->GetId() && dispeled->GetCasterGUID() == aur->GetCasterGUID()) |
---|
3322 | { |
---|
3323 | j = dispel_list.erase(j); |
---|
3324 | --list_size; |
---|
3325 | } |
---|
3326 | else |
---|
3327 | ++j; |
---|
3328 | } |
---|
3329 | } |
---|
3330 | // Send success log and really remove auras |
---|
3331 | if (!success_list.empty()) |
---|
3332 | { |
---|
3333 | int32 count = success_list.size(); |
---|
3334 | WorldPacket data(SMSG_SPELLDISPELLOG, 8+8+4+1+4+count*5); |
---|
3335 | data.append(unitTarget->GetPackGUID()); // Victim GUID |
---|
3336 | data.append(m_caster->GetPackGUID()); // Caster GUID |
---|
3337 | data << uint32(m_spellInfo->Id); // Dispell spell id |
---|
3338 | data << uint8(0); // not used |
---|
3339 | data << uint32(count); // count |
---|
3340 | for (std::list<std::pair<uint32,uint64> >::iterator j = success_list.begin(); j != success_list.end(); ++j) |
---|
3341 | { |
---|
3342 | SpellEntry const* spellInfo = sSpellStore.LookupEntry(j->first); |
---|
3343 | data << uint32(spellInfo->Id); // Spell Id |
---|
3344 | data << uint8(0); // 0 - dispeled !=0 cleansed |
---|
3345 | unitTarget->RemoveAurasDueToSpellByDispel(spellInfo->Id, j->second, m_caster); |
---|
3346 | } |
---|
3347 | m_caster->SendMessageToSet(&data, true); |
---|
3348 | |
---|
3349 | // On succes dispel |
---|
3350 | // Devour Magic |
---|
3351 | if (m_spellInfo->SpellFamilyName == SPELLFAMILY_WARLOCK && m_spellInfo->Category == 12) |
---|
3352 | { |
---|
3353 | uint32 heal_spell = 0; |
---|
3354 | switch (m_spellInfo->Id) |
---|
3355 | { |
---|
3356 | case 19505: heal_spell = 19658; break; |
---|
3357 | case 19731: heal_spell = 19732; break; |
---|
3358 | case 19734: heal_spell = 19733; break; |
---|
3359 | case 19736: heal_spell = 19735; break; |
---|
3360 | case 27276: heal_spell = 27278; break; |
---|
3361 | case 27277: heal_spell = 27279; break; |
---|
3362 | default: |
---|
3363 | sLog.outDebug("Spell for Devour Magic %d not handled in Spell::EffectDispel", m_spellInfo->Id); |
---|
3364 | break; |
---|
3365 | } |
---|
3366 | if (heal_spell) |
---|
3367 | m_caster->CastSpell(m_caster, heal_spell, true); |
---|
3368 | } |
---|
3369 | } |
---|
3370 | // Send fail log to client |
---|
3371 | if (!fail_list.empty()) |
---|
3372 | { |
---|
3373 | // Failed to dispell |
---|
3374 | WorldPacket data(SMSG_DISPEL_FAILED, 8+8+4+4*fail_list.size()); |
---|
3375 | data << uint64(m_caster->GetGUID()); // Caster GUID |
---|
3376 | data << uint64(unitTarget->GetGUID()); // Victim GUID |
---|
3377 | data << uint32(m_spellInfo->Id); // Dispell spell id |
---|
3378 | for (std::list< uint32 >::iterator j = fail_list.begin(); j != fail_list.end(); ++j) |
---|
3379 | data << uint32(*j); // Spell Id |
---|
3380 | m_caster->SendMessageToSet(&data, true); |
---|
3381 | } |
---|
3382 | } |
---|
3383 | } |
---|
3384 | |
---|
3385 | void Spell::EffectDualWield(uint32 /*i*/) |
---|
3386 | { |
---|
3387 | if (unitTarget->GetTypeId() == TYPEID_PLAYER) |
---|
3388 | ((Player*)unitTarget)->SetCanDualWield(true); |
---|
3389 | } |
---|
3390 | |
---|
3391 | void Spell::EffectPull(uint32 /*i*/) |
---|
3392 | { |
---|
3393 | // TODO: create a proper pull towards distract spell center for distract |
---|
3394 | sLog.outDebug("WORLD: Spell Effect DUMMY"); |
---|
3395 | } |
---|
3396 | |
---|
3397 | void Spell::EffectDistract(uint32 /*i*/) |
---|
3398 | { |
---|
3399 | // Check for possible target |
---|
3400 | if (!unitTarget || unitTarget->isInCombat()) |
---|
3401 | return; |
---|
3402 | |
---|
3403 | // target must be OK to do this |
---|
3404 | if( unitTarget->hasUnitState(UNIT_STAT_CONFUSED | UNIT_STAT_STUNNED | UNIT_STAT_FLEEING ) ) |
---|
3405 | return; |
---|
3406 | |
---|
3407 | float angle = unitTarget->GetAngle(m_targets.m_destX, m_targets.m_destY); |
---|
3408 | |
---|
3409 | if ( unitTarget->GetTypeId() == TYPEID_PLAYER ) |
---|
3410 | { |
---|
3411 | // For players just turn them |
---|
3412 | WorldPacket data; |
---|
3413 | ((Player*)unitTarget)->BuildTeleportAckMsg(&data, unitTarget->GetPositionX(), unitTarget->GetPositionY(), unitTarget->GetPositionZ(), angle); |
---|
3414 | ((Player*)unitTarget)->GetSession()->SendPacket( &data ); |
---|
3415 | ((Player*)unitTarget)->SetPosition(unitTarget->GetPositionX(), unitTarget->GetPositionY(), unitTarget->GetPositionZ(), angle, false); |
---|
3416 | } |
---|
3417 | else |
---|
3418 | { |
---|
3419 | // Set creature Distracted, Stop it, And turn it |
---|
3420 | unitTarget->SetOrientation(angle); |
---|
3421 | unitTarget->StopMoving(); |
---|
3422 | unitTarget->GetMotionMaster()->MoveDistract(damage*1000); |
---|
3423 | } |
---|
3424 | } |
---|
3425 | |
---|
3426 | void Spell::EffectPickPocket(uint32 /*i*/) |
---|
3427 | { |
---|
3428 | if( m_caster->GetTypeId() != TYPEID_PLAYER ) |
---|
3429 | return; |
---|
3430 | |
---|
3431 | // victim must be creature and attackable |
---|
3432 | if( !unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT || m_caster->IsFriendlyTo(unitTarget) ) |
---|
3433 | return; |
---|
3434 | |
---|
3435 | // victim have to be alive and humanoid or undead |
---|
3436 | if( unitTarget->isAlive() && (unitTarget->GetCreatureTypeMask() &CREATURE_TYPEMASK_HUMANOID_OR_UNDEAD) != 0) |
---|
3437 | { |
---|
3438 | int32 chance = 10 + int32(m_caster->getLevel()) - int32(unitTarget->getLevel()); |
---|
3439 | |
---|
3440 | if (chance > irand(0, 19)) |
---|
3441 | { |
---|
3442 | // Stealing successful |
---|
3443 | //sLog.outDebug("Sending loot from pickpocket"); |
---|
3444 | ((Player*)m_caster)->SendLoot(unitTarget->GetGUID(),LOOT_PICKPOCKETING); |
---|
3445 | } |
---|
3446 | else |
---|
3447 | { |
---|
3448 | // Reveal action + get attack |
---|
3449 | m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); |
---|
3450 | if (((Creature*)unitTarget)->AI()) |
---|
3451 | ((Creature*)unitTarget)->AI()->AttackStart(m_caster); |
---|
3452 | } |
---|
3453 | } |
---|
3454 | } |
---|
3455 | |
---|
3456 | void Spell::EffectAddFarsight(uint32 i) |
---|
3457 | { |
---|
3458 | float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i])); |
---|
3459 | int32 duration = GetSpellDuration(m_spellInfo); |
---|
3460 | DynamicObject* dynObj = new DynamicObject; |
---|
3461 | if(!dynObj->Create(objmgr.GenerateLowGuid(HIGHGUID_DYNAMICOBJECT), m_caster, m_spellInfo->Id, i, m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ, duration, radius)) |
---|
3462 | { |
---|
3463 | delete dynObj; |
---|
3464 | return; |
---|
3465 | } |
---|
3466 | dynObj->SetUInt32Value(OBJECT_FIELD_TYPE, 65); |
---|
3467 | dynObj->SetUInt32Value(DYNAMICOBJECT_BYTES, 0x80000002); |
---|
3468 | m_caster->AddDynObject(dynObj); |
---|
3469 | MapManager::Instance().GetMap(dynObj->GetMapId(), dynObj)->Add(dynObj); |
---|
3470 | m_caster->SetUInt64Value(PLAYER_FARSIGHT, dynObj->GetGUID()); |
---|
3471 | } |
---|
3472 | |
---|
3473 | void Spell::EffectSummonWild(uint32 i) |
---|
3474 | { |
---|
3475 | uint32 creature_entry = m_spellInfo->EffectMiscValue[i]; |
---|
3476 | if(!creature_entry) |
---|
3477 | return; |
---|
3478 | |
---|
3479 | uint32 level = m_caster->getLevel(); |
---|
3480 | |
---|
3481 | // level of creature summoned using engineering item based at engineering skill level |
---|
3482 | if(m_caster->GetTypeId()==TYPEID_PLAYER && m_CastItem) |
---|
3483 | { |
---|
3484 | ItemPrototype const *proto = m_CastItem->GetProto(); |
---|
3485 | if(proto && proto->RequiredSkill == SKILL_ENGINERING) |
---|
3486 | { |
---|
3487 | uint16 skill202 = ((Player*)m_caster)->GetSkillValue(SKILL_ENGINERING); |
---|
3488 | if(skill202) |
---|
3489 | { |
---|
3490 | level = skill202/5; |
---|
3491 | } |
---|
3492 | } |
---|
3493 | } |
---|
3494 | |
---|
3495 | // select center of summon position |
---|
3496 | float center_x = m_targets.m_destX; |
---|
3497 | float center_y = m_targets.m_destY; |
---|
3498 | float center_z = m_targets.m_destZ; |
---|
3499 | |
---|
3500 | float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i])); |
---|
3501 | |
---|
3502 | int32 amount = damage > 0 ? damage : 1; |
---|
3503 | |
---|
3504 | for(int32 count = 0; count < amount; ++count) |
---|
3505 | { |
---|
3506 | float px, py, pz; |
---|
3507 | // If dest location if present |
---|
3508 | if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION) |
---|
3509 | { |
---|
3510 | // Summon 1 unit in dest location |
---|
3511 | if (count == 0) |
---|
3512 | { |
---|
3513 | px = m_targets.m_destX; |
---|
3514 | py = m_targets.m_destY; |
---|
3515 | pz = m_targets.m_destZ; |
---|
3516 | } |
---|
3517 | // Summon in random point all other units if location present |
---|
3518 | else |
---|
3519 | m_caster->GetRandomPoint(center_x,center_y,center_z,radius,px,py,pz); |
---|
3520 | } |
---|
3521 | // Summon if dest location not present near caster |
---|
3522 | else |
---|
3523 | m_caster->GetClosePoint(px,py,pz,3.0f); |
---|
3524 | |
---|
3525 | int32 duration = GetSpellDuration(m_spellInfo); |
---|
3526 | |
---|
3527 | TempSummonType summonType = (duration == 0) ? TEMPSUMMON_DEAD_DESPAWN : TEMPSUMMON_TIMED_OR_DEAD_DESPAWN; |
---|
3528 | |
---|
3529 | m_caster->SummonCreature(creature_entry,px,py,pz,m_caster->GetOrientation(),summonType,duration); |
---|
3530 | } |
---|
3531 | } |
---|
3532 | |
---|
3533 | void Spell::EffectSummonGuardian(uint32 i) |
---|
3534 | { |
---|
3535 | uint32 pet_entry = m_spellInfo->EffectMiscValue[i]; |
---|
3536 | if(!pet_entry) |
---|
3537 | return; |
---|
3538 | |
---|
3539 | // Jewelery statue case (totem like) |
---|
3540 | if(m_spellInfo->SpellIconID==2056) |
---|
3541 | { |
---|
3542 | EffectSummonTotem(i); |
---|
3543 | return; |
---|
3544 | } |
---|
3545 | |
---|
3546 | // set timer for unsummon |
---|
3547 | int32 duration = GetSpellDuration(m_spellInfo); |
---|
3548 | |
---|
3549 | // Search old Guardian only for players (if casted spell not have duration or cooldown) |
---|
3550 | // FIXME: some guardians have control spell applied and controlled by player and anyway player can't summon in this time |
---|
3551 | // so this code hack in fact |
---|
3552 | if( m_caster->GetTypeId() == TYPEID_PLAYER && (duration <= 0 || GetSpellRecoveryTime(m_spellInfo)==0) ) |
---|
3553 | if(((Player*)m_caster)->HasGuardianWithEntry(pet_entry)) |
---|
3554 | return; // find old guardian, ignore summon |
---|
3555 | |
---|
3556 | // in another case summon new |
---|
3557 | uint32 level = m_caster->getLevel(); |
---|
3558 | |
---|
3559 | // level of pet summoned using engineering item based at engineering skill level |
---|
3560 | if(m_caster->GetTypeId()==TYPEID_PLAYER && m_CastItem) |
---|
3561 | { |
---|
3562 | ItemPrototype const *proto = m_CastItem->GetProto(); |
---|
3563 | if(proto && proto->RequiredSkill == SKILL_ENGINERING) |
---|
3564 | { |
---|
3565 | uint16 skill202 = ((Player*)m_caster)->GetSkillValue(SKILL_ENGINERING); |
---|
3566 | if(skill202) |
---|
3567 | { |
---|
3568 | level = skill202/5; |
---|
3569 | } |
---|
3570 | } |
---|
3571 | } |
---|
3572 | |
---|
3573 | // select center of summon position |
---|
3574 | float center_x = m_targets.m_destX; |
---|
3575 | float center_y = m_targets.m_destY; |
---|
3576 | float center_z = m_targets.m_destZ; |
---|
3577 | |
---|
3578 | float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i])); |
---|
3579 | |
---|
3580 | int32 amount = damage > 0 ? damage : 1; |
---|
3581 | |
---|
3582 | for(int32 count = 0; count < amount; ++count) |
---|
3583 | { |
---|
3584 | Pet* spawnCreature = new Pet(GUARDIAN_PET); |
---|
3585 | |
---|
3586 | Map *map = m_caster->GetMap(); |
---|
3587 | uint32 pet_number = objmgr.GeneratePetNumber(); |
---|
3588 | if(!spawnCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_PET), map,m_spellInfo->EffectMiscValue[i], pet_number)) |
---|
3589 | { |
---|
3590 | sLog.outError("no such creature entry %u",m_spellInfo->EffectMiscValue[i]); |
---|
3591 | delete spawnCreature; |
---|
3592 | return; |
---|
3593 | } |
---|
3594 | |
---|
3595 | float px, py, pz; |
---|
3596 | // If dest location if present |
---|
3597 | if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION) |
---|
3598 | { |
---|
3599 | // Summon 1 unit in dest location |
---|
3600 | if (count == 0) |
---|
3601 | { |
---|
3602 | px = m_targets.m_destX; |
---|
3603 | py = m_targets.m_destY; |
---|
3604 | pz = m_targets.m_destZ; |
---|
3605 | } |
---|
3606 | // Summon in random point all other units if location present |
---|
3607 | else |
---|
3608 | m_caster->GetRandomPoint(center_x,center_y,center_z,radius,px,py,pz); |
---|
3609 | } |
---|
3610 | // Summon if dest location not present near caster |
---|
3611 | else |
---|
3612 | m_caster->GetClosePoint(px,py,pz,spawnCreature->GetObjectSize()); |
---|
3613 | |
---|
3614 | spawnCreature->Relocate(px,py,pz,m_caster->GetOrientation()); |
---|
3615 | |
---|
3616 | if(!spawnCreature->IsPositionValid()) |
---|
3617 | { |
---|
3618 | sLog.outError("ERROR: Pet (guidlow %d, entry %d) not created base at creature. Suggested coordinates isn't valid (X: %d Y: ^%d)", spawnCreature->GetGUIDLow(), spawnCreature->GetEntry(), spawnCreature->GetPositionX(), spawnCreature->GetPositionY()); |
---|
3619 | delete spawnCreature; |
---|
3620 | return; |
---|
3621 | } |
---|
3622 | |
---|
3623 | if(duration > 0) |
---|
3624 | spawnCreature->SetDuration(duration); |
---|
3625 | |
---|
3626 | spawnCreature->SetUInt64Value(UNIT_FIELD_SUMMONEDBY,m_caster->GetGUID()); |
---|
3627 | spawnCreature->setPowerType(POWER_MANA); |
---|
3628 | spawnCreature->SetUInt32Value(UNIT_NPC_FLAGS , 0); |
---|
3629 | spawnCreature->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,m_caster->getFaction()); |
---|
3630 | spawnCreature->SetUInt32Value(UNIT_FIELD_FLAGS,0); |
---|
3631 | spawnCreature->SetUInt32Value(UNIT_FIELD_BYTES_1,0); |
---|
3632 | spawnCreature->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP,0); |
---|
3633 | spawnCreature->SetUInt64Value(UNIT_FIELD_CREATEDBY, m_caster->GetGUID()); |
---|
3634 | spawnCreature->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id); |
---|
3635 | |
---|
3636 | spawnCreature->InitStatsForLevel(level); |
---|
3637 | spawnCreature->GetCharmInfo()->SetPetNumber(pet_number, false); |
---|
3638 | |
---|
3639 | spawnCreature->AIM_Initialize(); |
---|
3640 | |
---|
3641 | if(m_caster->GetTypeId()==TYPEID_PLAYER) |
---|
3642 | ((Player*)m_caster)->AddGuardian(spawnCreature); |
---|
3643 | |
---|
3644 | map->Add((Creature*)spawnCreature); |
---|
3645 | } |
---|
3646 | } |
---|
3647 | |
---|
3648 | void Spell::EffectTeleUnitsFaceCaster(uint32 i) |
---|
3649 | { |
---|
3650 | if(!unitTarget) |
---|
3651 | return; |
---|
3652 | |
---|
3653 | if(unitTarget->isInFlight()) |
---|
3654 | return; |
---|
3655 | |
---|
3656 | uint32 mapid = m_caster->GetMapId(); |
---|
3657 | float dis = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i])); |
---|
3658 | |
---|
3659 | float fx,fy,fz; |
---|
3660 | m_caster->GetClosePoint(fx,fy,fz,unitTarget->GetObjectSize(),dis); |
---|
3661 | |
---|
3662 | if(unitTarget->GetTypeId() == TYPEID_PLAYER) |
---|
3663 | ((Player*)unitTarget)->TeleportTo(mapid, fx, fy, fz, -m_caster->GetOrientation(), TELE_TO_NOT_LEAVE_COMBAT | TELE_TO_NOT_UNSUMMON_PET | (unitTarget==m_caster ? TELE_TO_SPELL : 0)); |
---|
3664 | else |
---|
3665 | MapManager::Instance().GetMap(mapid, m_caster)->CreatureRelocation((Creature*)m_caster, fx, fy, fz, -m_caster->GetOrientation()); |
---|
3666 | } |
---|
3667 | |
---|
3668 | void Spell::EffectLearnSkill(uint32 i) |
---|
3669 | { |
---|
3670 | if(unitTarget->GetTypeId() != TYPEID_PLAYER) |
---|
3671 | return; |
---|
3672 | |
---|
3673 | if(damage < 0) |
---|
3674 | return; |
---|
3675 | |
---|
3676 | uint32 skillid = m_spellInfo->EffectMiscValue[i]; |
---|
3677 | uint16 skillval = ((Player*)unitTarget)->GetPureSkillValue(skillid); |
---|
3678 | ((Player*)unitTarget)->SetSkill(skillid, skillval?skillval:1, damage*75); |
---|
3679 | } |
---|
3680 | |
---|
3681 | void Spell::EffectAddHonor(uint32 /*i*/) |
---|
3682 | { |
---|
3683 | if(unitTarget->GetTypeId() != TYPEID_PLAYER) |
---|
3684 | return; |
---|
3685 | |
---|
3686 | sLog.outDebug("SpellEffect::AddHonor called for spell_id %u , that rewards %d honor points to player: %u", m_spellInfo->Id, this->damage, ((Player*)unitTarget)->GetGUIDLow()); |
---|
3687 | |
---|
3688 | // TODO: find formula for honor reward based on player's level! |
---|
3689 | |
---|
3690 | // now fixed only for level 70 players: |
---|
3691 | if (((Player*)unitTarget)->getLevel() == 70) |
---|
3692 | ((Player*)unitTarget)->RewardHonor(NULL, 1, this->damage); |
---|
3693 | } |
---|
3694 | |
---|
3695 | void Spell::EffectTradeSkill(uint32 /*i*/) |
---|
3696 | { |
---|
3697 | if(unitTarget->GetTypeId() != TYPEID_PLAYER) |
---|
3698 | return; |
---|
3699 | // uint32 skillid = m_spellInfo->EffectMiscValue[i]; |
---|
3700 | // uint16 skillmax = ((Player*)unitTarget)->(skillid); |
---|
3701 | // ((Player*)unitTarget)->SetSkill(skillid,skillval?skillval:1,skillmax+75); |
---|
3702 | } |
---|
3703 | |
---|
3704 | void Spell::EffectEnchantItemPerm(uint32 i) |
---|
3705 | { |
---|
3706 | if(m_caster->GetTypeId() != TYPEID_PLAYER) |
---|
3707 | return; |
---|
3708 | if (!itemTarget) |
---|
3709 | return; |
---|
3710 | |
---|
3711 | Player* p_caster = (Player*)m_caster; |
---|
3712 | |
---|
3713 | p_caster->UpdateCraftSkill(m_spellInfo->Id); |
---|
3714 | |
---|
3715 | if (m_spellInfo->EffectMiscValue[i]) |
---|
3716 | { |
---|
3717 | uint32 enchant_id = m_spellInfo->EffectMiscValue[i]; |
---|
3718 | |
---|
3719 | SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id); |
---|
3720 | if(!pEnchant) |
---|
3721 | return; |
---|
3722 | |
---|
3723 | // item can be in trade slot and have owner diff. from caster |
---|
3724 | Player* item_owner = itemTarget->GetOwner(); |
---|
3725 | if(!item_owner) |
---|
3726 | return; |
---|
3727 | |
---|
3728 | if(item_owner!=p_caster && p_caster->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE) ) |
---|
3729 | sLog.outCommand("GM %s (Account: %u) enchanting(perm): %s (Entry: %d) for player: %s (Account: %u)", |
---|
3730 | p_caster->GetName(),p_caster->GetSession()->GetAccountId(), |
---|
3731 | itemTarget->GetProto()->Name1,itemTarget->GetEntry(), |
---|
3732 | item_owner->GetName(),item_owner->GetSession()->GetAccountId()); |
---|
3733 | |
---|
3734 | // remove old enchanting before applying new if equipped |
---|
3735 | item_owner->ApplyEnchantment(itemTarget,PERM_ENCHANTMENT_SLOT,false); |
---|
3736 | |
---|
3737 | itemTarget->SetEnchantment(PERM_ENCHANTMENT_SLOT, enchant_id, 0, 0); |
---|
3738 | |
---|
3739 | // add new enchanting if equipped |
---|
3740 | item_owner->ApplyEnchantment(itemTarget,PERM_ENCHANTMENT_SLOT,true); |
---|
3741 | } |
---|
3742 | } |
---|
3743 | |
---|
3744 | void Spell::EffectEnchantItemTmp(uint32 i) |
---|
3745 | { |
---|
3746 | if(m_caster->GetTypeId() != TYPEID_PLAYER) |
---|
3747 | return; |
---|
3748 | |
---|
3749 | Player* p_caster = (Player*)m_caster; |
---|
3750 | |
---|
3751 | if(!itemTarget) |
---|
3752 | return; |
---|
3753 | |
---|
3754 | uint32 enchant_id = m_spellInfo->EffectMiscValue[i]; |
---|
3755 | |
---|
3756 | // Shaman Rockbiter Weapon |
---|
3757 | if(i==0 && m_spellInfo->Effect[1]==SPELL_EFFECT_DUMMY) |
---|
3758 | { |
---|
3759 | int32 enchnting_damage = m_currentBasePoints[1]+1; |
---|
3760 | |
---|
3761 | // enchanting id selected by calculated damage-per-sec stored in Effect[1] base value |
---|
3762 | // with already applied percent bonus from Elemental Weapons talent |
---|
3763 | // Note: damage calculated (correctly) with rounding int32(float(v)) but |
---|
3764 | // RW enchantments applied damage int32(float(v)+0.5), this create 0..1 difference sometime |
---|
3765 | switch(enchnting_damage) |
---|
3766 | { |
---|
3767 | // Rank 1 |
---|
3768 | case 2: enchant_id = 29; break; // 0% [ 7% == 2, 14% == 2, 20% == 2] |
---|
3769 | // Rank 2 |
---|
3770 | case 4: enchant_id = 6; break; // 0% [ 7% == 4, 14% == 4] |
---|
3771 | case 5: enchant_id = 3025; break; // 20% |
---|
3772 | // Rank 3 |
---|
3773 | case 6: enchant_id = 1; break; // 0% [ 7% == 6, 14% == 6] |
---|
3774 | case 7: enchant_id = 3027; break; // 20% |
---|
3775 | // Rank 4 |
---|
3776 | case 9: enchant_id = 3032; break; // 0% [ 7% == 6] |
---|
3777 | case 10: enchant_id = 503; break; // 14% |
---|
3778 | case 11: enchant_id = 3031; break; // 20% |
---|
3779 | // Rank 5 |
---|
3780 | case 15: enchant_id = 3035; break; // 0% |
---|
3781 | case 16: enchant_id = 1663; break; // 7% |
---|
3782 | case 17: enchant_id = 3033; break; // 14% |
---|
3783 | case 18: enchant_id = 3034; break; // 20% |
---|
3784 | // Rank 6 |
---|
3785 | case 28: enchant_id = 3038; break; // 0% |
---|
3786 | case 29: enchant_id = 683; break; // 7% |
---|
3787 | case 31: enchant_id = 3036; break; // 14% |
---|
3788 | case 33: enchant_id = 3037; break; // 20% |
---|
3789 | // Rank 7 |
---|
3790 | case 40: enchant_id = 3041; break; // 0% |
---|
3791 | case 42: enchant_id = 1664; break; // 7% |
---|
3792 | case 45: enchant_id = 3039; break; // 14% |
---|
3793 | case 48: enchant_id = 3040; break; // 20% |
---|
3794 | // Rank 8 |
---|
3795 | case 49: enchant_id = 3044; break; // 0% |
---|
3796 | case 52: enchant_id = 2632; break; // 7% |
---|
3797 | case 55: enchant_id = 3042; break; // 14% |
---|
3798 | case 58: enchant_id = 3043; break; // 20% |
---|
3799 | // Rank 9 |
---|
3800 | case 62: enchant_id = 2633; break; // 0% |
---|
3801 | case 66: enchant_id = 3018; break; // 7% |
---|
3802 | case 70: enchant_id = 3019; break; // 14% |
---|
3803 | case 74: enchant_id = 3020; break; // 20% |
---|
3804 | default: |
---|
3805 | sLog.outError("Spell::EffectEnchantItemTmp: Damage %u not handled in S'RW",enchnting_damage); |
---|
3806 | return; |
---|
3807 | } |
---|
3808 | } |
---|
3809 | |
---|
3810 | if (!enchant_id) |
---|
3811 | { |
---|
3812 | sLog.outError("Spell %u Effect %u (SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY) have 0 as enchanting id",m_spellInfo->Id,i); |
---|
3813 | return; |
---|
3814 | } |
---|
3815 | |
---|
3816 | SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id); |
---|
3817 | if(!pEnchant) |
---|
3818 | { |
---|
3819 | sLog.outError("Spell %u Effect %u (SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY) have not existed enchanting id %u ",m_spellInfo->Id,i,enchant_id); |
---|
3820 | return; |
---|
3821 | } |
---|
3822 | |
---|
3823 | // select enchantment duration |
---|
3824 | uint32 duration; |
---|
3825 | |
---|
3826 | // rogue family enchantments exception by duration |
---|
3827 | if(m_spellInfo->Id==38615) |
---|
3828 | duration = 1800; // 30 mins |
---|
3829 | // other rogue family enchantments always 1 hour (some have spell damage=0, but some have wrong data in EffBasePoints) |
---|
3830 | else if(m_spellInfo->SpellFamilyName==SPELLFAMILY_ROGUE) |
---|
3831 | duration = 3600; // 1 hour |
---|
3832 | // shaman family enchantments |
---|
3833 | else if(m_spellInfo->SpellFamilyName==SPELLFAMILY_SHAMAN) |
---|
3834 | duration = 1800; // 30 mins |
---|
3835 | // other cases with this SpellVisual already selected |
---|
3836 | else if(m_spellInfo->SpellVisual==215) |
---|
3837 | duration = 1800; // 30 mins |
---|
3838 | // some fishing pole bonuses |
---|
3839 | else if(m_spellInfo->SpellVisual==563) |
---|
3840 | duration = 600; // 10 mins |
---|
3841 | // shaman rockbiter enchantments |
---|
3842 | else if(m_spellInfo->SpellVisual==0) |
---|
3843 | duration = 1800; // 30 mins |
---|
3844 | else if(m_spellInfo->Id==29702) |
---|
3845 | duration = 300; // 5 mins |
---|
3846 | else if(m_spellInfo->Id==37360) |
---|
3847 | duration = 300; // 5 mins |
---|
3848 | // default case |
---|
3849 | else |
---|
3850 | duration = 3600; // 1 hour |
---|
3851 | |
---|
3852 | // item can be in trade slot and have owner diff. from caster |
---|
3853 | Player* item_owner = itemTarget->GetOwner(); |
---|
3854 | if(!item_owner) |
---|
3855 | return; |
---|
3856 | |
---|
3857 | if(item_owner!=p_caster && p_caster->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE) ) |
---|
3858 | sLog.outCommand("GM %s (Account: %u) enchanting(temp): %s (Entry: %d) for player: %s (Account: %u)", |
---|
3859 | p_caster->GetName(),p_caster->GetSession()->GetAccountId(), |
---|
3860 | itemTarget->GetProto()->Name1,itemTarget->GetEntry(), |
---|
3861 | item_owner->GetName(),item_owner->GetSession()->GetAccountId()); |
---|
3862 | |
---|
3863 | // remove old enchanting before applying new if equipped |
---|
3864 | item_owner->ApplyEnchantment(itemTarget,TEMP_ENCHANTMENT_SLOT,false); |
---|
3865 | |
---|
3866 | itemTarget->SetEnchantment(TEMP_ENCHANTMENT_SLOT, enchant_id, duration*1000, 0); |
---|
3867 | |
---|
3868 | // add new enchanting if equipped |
---|
3869 | item_owner->ApplyEnchantment(itemTarget,TEMP_ENCHANTMENT_SLOT,true); |
---|
3870 | } |
---|
3871 | |
---|
3872 | void Spell::EffectTameCreature(uint32 /*i*/) |
---|
3873 | { |
---|
3874 | if(m_caster->GetPetGUID()) |
---|
3875 | return; |
---|
3876 | |
---|
3877 | if(!unitTarget) |
---|
3878 | return; |
---|
3879 | |
---|
3880 | if(unitTarget->GetTypeId() == TYPEID_PLAYER) |
---|
3881 | return; |
---|
3882 | |
---|
3883 | Creature* creatureTarget = (Creature*)unitTarget; |
---|
3884 | |
---|
3885 | if(creatureTarget->isPet()) |
---|
3886 | return; |
---|
3887 | |
---|
3888 | if(m_caster->getClass() == CLASS_HUNTER) |
---|
3889 | { |
---|
3890 | // cast finish successfully |
---|
3891 | //SendChannelUpdate(0); |
---|
3892 | finish(); |
---|
3893 | |
---|
3894 | Pet* pet = new Pet(HUNTER_PET); |
---|
3895 | |
---|
3896 | if(!pet->CreateBaseAtCreature(creatureTarget)) |
---|
3897 | { |
---|
3898 | delete pet; |
---|
3899 | return; |
---|
3900 | } |
---|
3901 | |
---|
3902 | creatureTarget->setDeathState(JUST_DIED); |
---|
3903 | creatureTarget->RemoveCorpse(); |
---|
3904 | creatureTarget->SetHealth(0); // just for nice GM-mode view |
---|
3905 | |
---|
3906 | pet->SetUInt64Value(UNIT_FIELD_SUMMONEDBY, m_caster->GetGUID()); |
---|
3907 | pet->SetUInt64Value(UNIT_FIELD_CREATEDBY, m_caster->GetGUID()); |
---|
3908 | pet->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,m_caster->getFaction()); |
---|
3909 | pet->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id); |
---|
3910 | |
---|
3911 | if(!pet->InitStatsForLevel(creatureTarget->getLevel())) |
---|
3912 | { |
---|
3913 | sLog.outError("ERROR: InitStatsForLevel() in EffectTameCreature failed! Pet deleted."); |
---|
3914 | delete pet; |
---|
3915 | return; |
---|
3916 | } |
---|
3917 | |
---|
3918 | // prepare visual effect for levelup |
---|
3919 | pet->SetUInt32Value(UNIT_FIELD_LEVEL,creatureTarget->getLevel()-1); |
---|
3920 | |
---|
3921 | pet->GetCharmInfo()->SetPetNumber(objmgr.GeneratePetNumber(), true); |
---|
3922 | // this enables pet details window (Shift+P) |
---|
3923 | pet->AIM_Initialize(); |
---|
3924 | pet->InitPetCreateSpells(); |
---|
3925 | pet->SetHealth(pet->GetMaxHealth()); |
---|
3926 | |
---|
3927 | MapManager::Instance().GetMap(pet->GetMapId(), pet)->Add((Creature*)pet); |
---|
3928 | |
---|
3929 | // visual effect for levelup |
---|
3930 | pet->SetUInt32Value(UNIT_FIELD_LEVEL,creatureTarget->getLevel()); |
---|
3931 | |
---|
3932 | if(m_caster->GetTypeId() == TYPEID_PLAYER) |
---|
3933 | { |
---|
3934 | m_caster->SetPet(pet); |
---|
3935 | pet->SavePetToDB(PET_SAVE_AS_CURRENT); |
---|
3936 | ((Player*)m_caster)->PetSpellInitialize(); |
---|
3937 | } |
---|
3938 | } |
---|
3939 | } |
---|
3940 | |
---|
3941 | void Spell::EffectSummonPet(uint32 i) |
---|
3942 | { |
---|
3943 | uint32 petentry = m_spellInfo->EffectMiscValue[i]; |
---|
3944 | |
---|
3945 | Pet *OldSummon = m_caster->GetPet(); |
---|
3946 | |
---|
3947 | // if pet requested type already exist |
---|
3948 | if( OldSummon ) |
---|
3949 | { |
---|
3950 | if(petentry == 0 || OldSummon->GetEntry() == petentry) |
---|
3951 | { |
---|
3952 | // pet in corpse state can't be summoned |
---|
3953 | if( OldSummon->isDead() ) |
---|
3954 | return; |
---|
3955 | |
---|
3956 | MapManager::Instance().GetMap(OldSummon->GetMapId(), OldSummon)->Remove((Creature*)OldSummon,false); |
---|
3957 | OldSummon->SetMapId(m_caster->GetMapId()); |
---|
3958 | |
---|
3959 | float px, py, pz; |
---|
3960 | m_caster->GetClosePoint(px, py, pz, OldSummon->GetObjectSize()); |
---|
3961 | |
---|
3962 | OldSummon->Relocate(px, py, pz, OldSummon->GetOrientation()); |
---|
3963 | MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster)->Add((Creature*)OldSummon); |
---|
3964 | |
---|
3965 | if(m_caster->GetTypeId() == TYPEID_PLAYER && OldSummon->isControlled() ) |
---|
3966 | { |
---|
3967 | ((Player*)m_caster)->PetSpellInitialize(); |
---|
3968 | } |
---|
3969 | return; |
---|
3970 | } |
---|
3971 | |
---|
3972 | if(m_caster->GetTypeId() == TYPEID_PLAYER) |
---|
3973 | ((Player*)m_caster)->RemovePet(OldSummon,(OldSummon->getPetType()==HUNTER_PET ? PET_SAVE_AS_DELETED : PET_SAVE_NOT_IN_SLOT),false); |
---|
3974 | else |
---|
3975 | return; |
---|
3976 | } |
---|
3977 | |
---|
3978 | Pet* NewSummon = new Pet; |
---|
3979 | |
---|
3980 | // petentry==0 for hunter "call pet" (current pet summoned if any) |
---|
3981 | if(NewSummon->LoadPetFromDB(m_caster,petentry)) |
---|
3982 | { |
---|
3983 | if(NewSummon->getPetType()==SUMMON_PET) |
---|
3984 | { |
---|
3985 | // Remove Demonic Sacrifice auras (known pet) |
---|
3986 | Unit::AuraList const& auraClassScripts = m_caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS); |
---|
3987 | for(Unit::AuraList::const_iterator itr = auraClassScripts.begin();itr!=auraClassScripts.end();) |
---|
3988 | { |
---|
3989 | if((*itr)->GetModifier()->m_miscvalue==2228) |
---|
3990 | { |
---|
3991 | m_caster->RemoveAurasDueToSpell((*itr)->GetId()); |
---|
3992 | itr = auraClassScripts.begin(); |
---|
3993 | } |
---|
3994 | else |
---|
3995 | ++itr; |
---|
3996 | } |
---|
3997 | } |
---|
3998 | |
---|
3999 | return; |
---|
4000 | } |
---|
4001 | |
---|
4002 | // not error in case fail hunter call pet |
---|
4003 | if(!petentry) |
---|
4004 | { |
---|
4005 | delete NewSummon; |
---|
4006 | return; |
---|
4007 | } |
---|
4008 | |
---|
4009 | CreatureInfo const* cInfo = sCreatureStorage.LookupEntry<CreatureInfo>(petentry); |
---|
4010 | |
---|
4011 | if(!cInfo) |
---|
4012 | { |
---|
4013 | sLog.outError("EffectSummonPet: creature entry %u not found.",petentry); |
---|
4014 | delete NewSummon; |
---|
4015 | return; |
---|
4016 | } |
---|
4017 | |
---|
4018 | Map *map = m_caster->GetMap(); |
---|
4019 | uint32 pet_number = objmgr.GeneratePetNumber(); |
---|
4020 | if(!NewSummon->Create(objmgr.GenerateLowGuid(HIGHGUID_PET), map, petentry, pet_number)) |
---|
4021 | { |
---|
4022 | delete NewSummon; |
---|
4023 | return; |
---|
4024 | } |
---|
4025 | |
---|
4026 | float px, py, pz; |
---|
4027 | m_caster->GetClosePoint(px, py, pz, NewSummon->GetObjectSize()); |
---|
4028 | |
---|
4029 | NewSummon->Relocate(px, py, pz, m_caster->GetOrientation()); |
---|
4030 | |
---|
4031 | if(!NewSummon->IsPositionValid()) |
---|
4032 | { |
---|
4033 | sLog.outError("ERROR: Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %d Y: ^%d)", NewSummon->GetGUIDLow(), NewSummon->GetEntry(), NewSummon->GetPositionX(), NewSummon->GetPositionY()); |
---|
4034 | delete NewSummon; |
---|
4035 | return; |
---|
4036 | } |
---|
4037 | |
---|
4038 | uint32 petlevel = m_caster->getLevel(); |
---|
4039 | NewSummon->setPetType(SUMMON_PET); |
---|
4040 | |
---|
4041 | uint32 faction = m_caster->getFaction(); |
---|
4042 | if(m_caster->GetTypeId() == TYPEID_UNIT && ((Creature*)m_caster)->isTotem()) |
---|
4043 | { |
---|
4044 | Unit* owner = ((Totem*)m_caster)->GetOwner(); |
---|
4045 | if(owner) |
---|
4046 | faction = owner->getFaction(); |
---|
4047 | NewSummon->GetCharmInfo()->SetReactState(REACT_AGGRESSIVE); |
---|
4048 | } |
---|
4049 | |
---|
4050 | NewSummon->SetUInt64Value(UNIT_FIELD_SUMMONEDBY, m_caster->GetGUID()); |
---|
4051 | NewSummon->SetUInt64Value(UNIT_FIELD_CREATEDBY, m_caster->GetGUID()); |
---|
4052 | NewSummon->SetUInt32Value(UNIT_NPC_FLAGS , 0); |
---|
4053 | NewSummon->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, faction); |
---|
4054 | NewSummon->SetUInt32Value(UNIT_FIELD_BYTES_0,2048); |
---|
4055 | NewSummon->SetUInt32Value(UNIT_FIELD_BYTES_1,0); |
---|
4056 | NewSummon->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP,time(NULL)); |
---|
4057 | NewSummon->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE,0); |
---|
4058 | NewSummon->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP,1000); |
---|
4059 | NewSummon->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id); |
---|
4060 | |
---|
4061 | NewSummon->GetCharmInfo()->SetPetNumber(pet_number, true); |
---|
4062 | // this enables pet details window (Shift+P) |
---|
4063 | |
---|
4064 | // this enables popup window (pet dismiss, cancel), hunter pet additional flags set later |
---|
4065 | NewSummon->SetUInt32Value(UNIT_FIELD_FLAGS,UNIT_FLAG_PVP_ATTACKABLE); |
---|
4066 | |
---|
4067 | NewSummon->InitStatsForLevel( petlevel); |
---|
4068 | NewSummon->InitPetCreateSpells(); |
---|
4069 | |
---|
4070 | if(NewSummon->getPetType()==SUMMON_PET) |
---|
4071 | { |
---|
4072 | // Remove Demonic Sacrifice auras (new pet) |
---|
4073 | Unit::AuraList const& auraClassScripts = m_caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS); |
---|
4074 | for(Unit::AuraList::const_iterator itr = auraClassScripts.begin();itr!=auraClassScripts.end();) |
---|
4075 | { |
---|
4076 | if((*itr)->GetModifier()->m_miscvalue==2228) |
---|
4077 | { |
---|
4078 | m_caster->RemoveAurasDueToSpell((*itr)->GetId()); |
---|
4079 | itr = auraClassScripts.begin(); |
---|
4080 | } |
---|
4081 | else |
---|
4082 | ++itr; |
---|
4083 | } |
---|
4084 | |
---|
4085 | // generate new name for summon pet |
---|
4086 | std::string new_name=objmgr.GeneratePetName(petentry); |
---|
4087 | if(!new_name.empty()) |
---|
4088 | NewSummon->SetName(new_name); |
---|
4089 | } |
---|
4090 | else if(NewSummon->getPetType()==HUNTER_PET) |
---|
4091 | NewSummon->SetByteValue(UNIT_FIELD_BYTES_2, 2, UNIT_RENAME_NOT_ALLOWED); |
---|
4092 | |
---|
4093 | NewSummon->AIM_Initialize(); |
---|
4094 | NewSummon->SetHealth(NewSummon->GetMaxHealth()); |
---|
4095 | NewSummon->SetPower(POWER_MANA, NewSummon->GetMaxPower(POWER_MANA)); |
---|
4096 | |
---|
4097 | map->Add((Creature*)NewSummon); |
---|
4098 | |
---|
4099 | m_caster->SetPet(NewSummon); |
---|
4100 | sLog.outDebug("New Pet has guid %u", NewSummon->GetGUIDLow()); |
---|
4101 | |
---|
4102 | if(m_caster->GetTypeId() == TYPEID_PLAYER) |
---|
4103 | { |
---|
4104 | NewSummon->SavePetToDB(PET_SAVE_AS_CURRENT); |
---|
4105 | ((Player*)m_caster)->PetSpellInitialize(); |
---|
4106 | } |
---|
4107 | } |
---|
4108 | |
---|
4109 | void Spell::EffectLearnPetSpell(uint32 i) |
---|
4110 | { |
---|
4111 | if(m_caster->GetTypeId() != TYPEID_PLAYER) |
---|
4112 | return; |
---|
4113 | |
---|
4114 | Player *_player = (Player*)m_caster; |
---|
4115 | |
---|
4116 | Pet *pet = _player->GetPet(); |
---|
4117 | if(!pet) |
---|
4118 | return; |
---|
4119 | if(!pet->isAlive()) |
---|
4120 | return; |
---|
4121 | |
---|
4122 | SpellEntry const *learn_spellproto = sSpellStore.LookupEntry(m_spellInfo->EffectTriggerSpell[i]); |
---|
4123 | if(!learn_spellproto) |
---|
4124 | return; |
---|
4125 | |
---|
4126 | pet->SetTP(pet->m_TrainingPoints - pet->GetTPForSpell(learn_spellproto->Id)); |
---|
4127 | pet->learnSpell(learn_spellproto->Id); |
---|
4128 | |
---|
4129 | pet->SavePetToDB(PET_SAVE_AS_CURRENT); |
---|
4130 | _player->PetSpellInitialize(); |
---|
4131 | } |
---|
4132 | |
---|
4133 | void Spell::EffectTaunt(uint32 /*i*/) |
---|
4134 | { |
---|
4135 | // this effect use before aura Taunt apply for prevent taunt already attacking target |
---|
4136 | // for spell as marked "non effective at already attacking target" |
---|
4137 | if(unitTarget && unitTarget->GetTypeId() != TYPEID_PLAYER) |
---|
4138 | { |
---|
4139 | if(unitTarget->getVictim()==m_caster) |
---|
4140 | { |
---|
4141 | SendCastResult(SPELL_FAILED_DONT_REPORT); |
---|
4142 | return; |
---|
4143 | } |
---|
4144 | } |
---|
4145 | |
---|
4146 | // Also use this effect to set the taunter's threat to the taunted creature's highest value |
---|
4147 | if(unitTarget->CanHaveThreatList() && unitTarget->getThreatManager().getCurrentVictim()) |
---|
4148 | unitTarget->getThreatManager().addThreat(m_caster,unitTarget->getThreatManager().getCurrentVictim()->getThreat()); |
---|
4149 | } |
---|
4150 | |
---|
4151 | void Spell::EffectWeaponDmg(uint32 i) |
---|
4152 | { |
---|
4153 | if(!unitTarget) |
---|
4154 | return; |
---|
4155 | if(!unitTarget->isAlive()) |
---|
4156 | return; |
---|
4157 | |
---|
4158 | // multiple weapon dmg effect workaround |
---|
4159 | // execute only the last weapon damage |
---|
4160 | // and handle all effects at once |
---|
4161 | for (int j = 0; j < 3; j++) |
---|
4162 | { |
---|
4163 | switch(m_spellInfo->Effect[j]) |
---|
4164 | { |
---|
4165 | case SPELL_EFFECT_WEAPON_DAMAGE: |
---|
4166 | case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL: |
---|
4167 | case SPELL_EFFECT_NORMALIZED_WEAPON_DMG: |
---|
4168 | case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE: |
---|
4169 | if (j < i) // we must calculate only at last weapon effect |
---|
4170 | return; |
---|
4171 | break; |
---|
4172 | } |
---|
4173 | } |
---|
4174 | |
---|
4175 | // some spell specific modifiers |
---|
4176 | bool customBonusDamagePercentMod = false; |
---|
4177 | float bonusDamagePercentMod = 1.0f; // applied to fixed effect damage bonus if set customBonusDamagePercentMod |
---|
4178 | float weaponDamagePercentMod = 1.0f; // applied to weapon damage (and to fixed effect damage bonus if customBonusDamagePercentMod not set |
---|
4179 | float totalDamagePercentMod = 1.0f; // applied to final bonus+weapon damage |
---|
4180 | bool normalized = false; |
---|
4181 | |
---|
4182 | int32 spell_bonus = 0; // bonus specific for spell |
---|
4183 | switch(m_spellInfo->SpellFamilyName) |
---|
4184 | { |
---|
4185 | case SPELLFAMILY_WARRIOR: |
---|
4186 | { |
---|
4187 | // Whirlwind, single only spell with 2 weapon white damage apply if have |
---|
4188 | if(m_caster->GetTypeId()==TYPEID_PLAYER && (m_spellInfo->SpellFamilyFlags & 0x00000400000000LL)) |
---|
4189 | { |
---|
4190 | if(((Player*)m_caster)->GetWeaponForAttack(OFF_ATTACK,true)) |
---|
4191 | spell_bonus += m_caster->CalculateDamage (OFF_ATTACK, normalized); |
---|
4192 | } |
---|
4193 | // Devastate bonus and sunder armor refresh |
---|
4194 | else if(m_spellInfo->SpellVisual == 671 && m_spellInfo->SpellIconID == 1508) |
---|
4195 | { |
---|
4196 | customBonusDamagePercentMod = true; |
---|
4197 | bonusDamagePercentMod = 0.0f; // only applied if auras found |
---|
4198 | |
---|
4199 | Unit::AuraList const& list = unitTarget->GetAurasByType(SPELL_AURA_MOD_RESISTANCE); |
---|
4200 | for(Unit::AuraList::const_iterator itr=list.begin();itr!=list.end();++itr) |
---|
4201 | { |
---|
4202 | SpellEntry const *proto = (*itr)->GetSpellProto(); |
---|
4203 | if(proto->SpellVisual == 406 && proto->SpellIconID == 565) |
---|
4204 | { |
---|
4205 | int32 duration = GetSpellDuration(proto); |
---|
4206 | (*itr)->SetAuraDuration(duration); |
---|
4207 | (*itr)->UpdateAuraDuration(); |
---|
4208 | bonusDamagePercentMod += 1.0f; // +100% |
---|
4209 | } |
---|
4210 | } |
---|
4211 | } |
---|
4212 | break; |
---|
4213 | } |
---|
4214 | case SPELLFAMILY_ROGUE: |
---|
4215 | { |
---|
4216 | // Ambush |
---|
4217 | if(m_spellInfo->SpellFamilyFlags & 0x00000200LL) |
---|
4218 | { |
---|
4219 | customBonusDamagePercentMod = true; |
---|
4220 | bonusDamagePercentMod = 2.5f; // 250% |
---|
4221 | } |
---|
4222 | // Mutilate (for each hand) |
---|
4223 | else if(m_spellInfo->SpellFamilyFlags & 0x600000000LL) |
---|
4224 | { |
---|
4225 | bool found = false; |
---|
4226 | // fast check |
---|
4227 | if(unitTarget->HasAuraState(AURA_STATE_DEADLY_POISON)) |
---|
4228 | found = true; |
---|
4229 | // full aura scan |
---|
4230 | else |
---|
4231 | { |
---|
4232 | Unit::AuraMap const& auras = unitTarget->GetAuras(); |
---|
4233 | for(Unit::AuraMap::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr) |
---|
4234 | { |
---|
4235 | if(itr->second->GetSpellProto()->Dispel == DISPEL_POISON) |
---|
4236 | { |
---|
4237 | found = true; |
---|
4238 | break; |
---|
4239 | } |
---|
4240 | } |
---|
4241 | } |
---|
4242 | |
---|
4243 | if(found) |
---|
4244 | totalDamagePercentMod *= 1.5f; // 150% if poisoned |
---|
4245 | } |
---|
4246 | break; |
---|
4247 | } |
---|
4248 | case SPELLFAMILY_PALADIN: |
---|
4249 | { |
---|
4250 | // Seal of Command - receive benefit from Spell Damage and Healing |
---|
4251 | if(m_spellInfo->SpellFamilyFlags & 0x00000002000000LL) |
---|
4252 | { |
---|
4253 | spell_bonus += int32(0.20f*m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo))); |
---|
4254 | spell_bonus += int32(0.29f*m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget)); |
---|
4255 | } |
---|
4256 | break; |
---|
4257 | } |
---|
4258 | case SPELLFAMILY_SHAMAN: |
---|
4259 | { |
---|
4260 | // Skyshatter Harness item set bonus |
---|
4261 | // Stormstrike |
---|
4262 | if(m_spellInfo->SpellFamilyFlags & 0x001000000000LL) |
---|
4263 | { |
---|
4264 | Unit::AuraList const& m_OverrideClassScript = m_caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS); |
---|
4265 | for(Unit::AuraList::const_iterator i = m_OverrideClassScript.begin(); i != m_OverrideClassScript.end(); ++i) |
---|
4266 | { |
---|
4267 | // Stormstrike AP Buff |
---|
4268 | if ( (*i)->GetModifier()->m_miscvalue == 5634 ) |
---|
4269 | { |
---|
4270 | m_caster->CastSpell(m_caster,38430,true,NULL,*i); |
---|
4271 | break; |
---|
4272 | } |
---|
4273 | } |
---|
4274 | } |
---|
4275 | } |
---|
4276 | } |
---|
4277 | |
---|
4278 | int32 fixed_bonus = 0; |
---|
4279 | for (int j = 0; j < 3; j++) |
---|
4280 | { |
---|
4281 | switch(m_spellInfo->Effect[j]) |
---|
4282 | { |
---|
4283 | case SPELL_EFFECT_WEAPON_DAMAGE: |
---|
4284 | case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL: |
---|
4285 | fixed_bonus += CalculateDamage(j,unitTarget); |
---|
4286 | break; |
---|
4287 | case SPELL_EFFECT_NORMALIZED_WEAPON_DMG: |
---|
4288 | fixed_bonus += CalculateDamage(j,unitTarget); |
---|
4289 | normalized = true; |
---|
4290 | break; |
---|
4291 | case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE: |
---|
4292 | weaponDamagePercentMod *= float(CalculateDamage(j,unitTarget)) / 100.0f; |
---|
4293 | |
---|
4294 | // applied only to prev.effects fixed damage |
---|
4295 | if(customBonusDamagePercentMod) |
---|
4296 | fixed_bonus = int32(fixed_bonus*bonusDamagePercentMod); |
---|
4297 | else |
---|
4298 | fixed_bonus = int32(fixed_bonus*weaponDamagePercentMod); |
---|
4299 | break; |
---|
4300 | default: |
---|
4301 | break; // not weapon damage effect, just skip |
---|
4302 | } |
---|
4303 | } |
---|
4304 | |
---|
4305 | // non-weapon damage |
---|
4306 | int32 bonus = spell_bonus + fixed_bonus; |
---|
4307 | |
---|
4308 | // apply to non-weapon bonus weapon total pct effect, weapon total flat effect included in weapon damage |
---|
4309 | if(bonus) |
---|
4310 | { |
---|
4311 | UnitMods unitMod; |
---|
4312 | switch(m_attackType) |
---|
4313 | { |
---|
4314 | default: |
---|
4315 | case BASE_ATTACK: unitMod = UNIT_MOD_DAMAGE_MAINHAND; break; |
---|
4316 | case OFF_ATTACK: unitMod = UNIT_MOD_DAMAGE_OFFHAND; break; |
---|
4317 | case RANGED_ATTACK: unitMod = UNIT_MOD_DAMAGE_RANGED; break; |
---|
4318 | } |
---|
4319 | |
---|
4320 | float weapon_total_pct = m_caster->GetModifierValue(unitMod, TOTAL_PCT); |
---|
4321 | bonus = int32(bonus*weapon_total_pct); |
---|
4322 | } |
---|
4323 | |
---|
4324 | // + weapon damage with applied weapon% dmg to base weapon damage in call |
---|
4325 | bonus += int32(m_caster->CalculateDamage(m_attackType, normalized)*weaponDamagePercentMod); |
---|
4326 | |
---|
4327 | // total damage |
---|
4328 | bonus = int32(bonus*totalDamagePercentMod); |
---|
4329 | |
---|
4330 | // prevent negative damage |
---|
4331 | uint32 eff_damage = uint32(bonus > 0 ? bonus : 0); |
---|
4332 | |
---|
4333 | const uint32 nohitMask = HITINFO_ABSORB | HITINFO_RESIST | HITINFO_MISS; |
---|
4334 | |
---|
4335 | uint32 hitInfo = 0; |
---|
4336 | VictimState victimState = VICTIMSTATE_NORMAL; |
---|
4337 | uint32 blocked_dmg = 0; |
---|
4338 | uint32 absorbed_dmg = 0; |
---|
4339 | uint32 resisted_dmg = 0; |
---|
4340 | CleanDamage cleanDamage = CleanDamage(0, BASE_ATTACK, MELEE_HIT_NORMAL ); |
---|
4341 | |
---|
4342 | m_caster->DoAttackDamage(unitTarget, &eff_damage, &cleanDamage, &blocked_dmg, m_spellSchoolMask, &hitInfo, &victimState, &absorbed_dmg, &resisted_dmg, m_attackType, m_spellInfo, m_IsTriggeredSpell); |
---|
4343 | |
---|
4344 | if ((hitInfo & nohitMask) && m_attackType != RANGED_ATTACK) // not send ranged miss/etc |
---|
4345 | m_caster->SendAttackStateUpdate(hitInfo & nohitMask, unitTarget, 1, m_spellSchoolMask, eff_damage, absorbed_dmg, resisted_dmg, VICTIMSTATE_NORMAL, blocked_dmg); |
---|
4346 | |
---|
4347 | bool criticalhit = (hitInfo & HITINFO_CRITICALHIT); |
---|
4348 | m_caster->SendSpellNonMeleeDamageLog(unitTarget, m_spellInfo->Id, eff_damage, m_spellSchoolMask, absorbed_dmg, resisted_dmg, false, blocked_dmg, criticalhit); |
---|
4349 | |
---|
4350 | if (eff_damage > (absorbed_dmg + resisted_dmg + blocked_dmg)) |
---|
4351 | { |
---|
4352 | eff_damage -= (absorbed_dmg + resisted_dmg + blocked_dmg); |
---|
4353 | } |
---|
4354 | else |
---|
4355 | { |
---|
4356 | cleanDamage.damage += eff_damage; |
---|
4357 | eff_damage = 0; |
---|
4358 | } |
---|
4359 | |
---|
4360 | // SPELL_SCHOOL_NORMAL use for weapon-like threat and rage calculation |
---|
4361 | m_caster->DealDamage(unitTarget, eff_damage, &cleanDamage, SPELL_DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, true); |
---|
4362 | |
---|
4363 | // Hemorrhage |
---|
4364 | if(m_spellInfo->SpellFamilyName==SPELLFAMILY_ROGUE && (m_spellInfo->SpellFamilyFlags & 0x2000000)) |
---|
4365 | { |
---|
4366 | if(m_caster->GetTypeId()==TYPEID_PLAYER) |
---|
4367 | ((Player*)m_caster)->AddComboPoints(unitTarget, 1); |
---|
4368 | } |
---|
4369 | // Mangle (Cat): CP |
---|
4370 | if(m_spellInfo->SpellFamilyName==SPELLFAMILY_DRUID && (m_spellInfo->SpellFamilyFlags==0x0000040000000000LL)) |
---|
4371 | { |
---|
4372 | if(m_caster->GetTypeId()==TYPEID_PLAYER) |
---|
4373 | ((Player*)m_caster)->AddComboPoints(unitTarget,1); |
---|
4374 | } |
---|
4375 | |
---|
4376 | |
---|
4377 | // take ammo |
---|
4378 | if(m_attackType == RANGED_ATTACK && m_caster->GetTypeId() == TYPEID_PLAYER) |
---|
4379 | { |
---|
4380 | Item *pItem = ((Player*)m_caster)->GetWeaponForAttack( RANGED_ATTACK ); |
---|
4381 | |
---|
4382 | // wands don't have ammo |
---|
4383 | if(!pItem || pItem->IsBroken() || pItem->GetProto()->SubClass==ITEM_SUBCLASS_WEAPON_WAND) |
---|
4384 | return; |
---|
4385 | |
---|
4386 | if( pItem->GetProto()->InventoryType == INVTYPE_THROWN ) |
---|
4387 | { |
---|
4388 | if(pItem->GetMaxStackCount()==1) |
---|
4389 | { |
---|
4390 | // decrease durability for non-stackable throw weapon |
---|
4391 | ((Player*)m_caster)->DurabilityPointLossForEquipSlot(EQUIPMENT_SLOT_RANGED); |
---|
4392 | } |
---|
4393 | else |
---|
4394 | { |
---|
4395 | // decrease items amount for stackable throw weapon |
---|
4396 | uint32 count = 1; |
---|
4397 | ((Player*)m_caster)->DestroyItemCount( pItem, count, true); |
---|
4398 | } |
---|
4399 | } |
---|
4400 | else if(uint32 ammo = ((Player*)m_caster)->GetUInt32Value(PLAYER_AMMO_ID)) |
---|
4401 | ((Player*)m_caster)->DestroyItemCount(ammo, 1, true); |
---|
4402 | } |
---|
4403 | } |
---|
4404 | |
---|
4405 | void Spell::EffectThreat(uint32 /*i*/) |
---|
4406 | { |
---|
4407 | if(!unitTarget || !unitTarget->isAlive() || !m_caster->isAlive()) |
---|
4408 | return; |
---|
4409 | |
---|
4410 | if(!unitTarget->CanHaveThreatList()) |
---|
4411 | return; |
---|
4412 | |
---|
4413 | unitTarget->AddThreat(m_caster, float(damage)); |
---|
4414 | } |
---|
4415 | |
---|
4416 | void Spell::EffectHealMaxHealth(uint32 /*i*/) |
---|
4417 | { |
---|
4418 | if(!unitTarget) |
---|
4419 | return; |
---|
4420 | if(!unitTarget->isAlive()) |
---|
4421 | return; |
---|
4422 | |
---|
4423 | uint32 heal = m_caster->GetMaxHealth(); |
---|
4424 | |
---|
4425 | int32 gain = unitTarget->ModifyHealth(heal); |
---|
4426 | unitTarget->getHostilRefManager().threatAssist(m_caster, float(gain) * 0.5f, m_spellInfo); |
---|
4427 | |
---|
4428 | m_caster->SendHealSpellLog(unitTarget, m_spellInfo->Id, heal); |
---|
4429 | } |
---|
4430 | |
---|
4431 | void Spell::EffectInterruptCast(uint32 /*i*/) |
---|
4432 | { |
---|
4433 | if(!unitTarget) |
---|
4434 | return; |
---|
4435 | if(!unitTarget->isAlive()) |
---|
4436 | return; |
---|
4437 | |
---|
4438 | // TODO: not all spells that used this effect apply cooldown at school spells |
---|
4439 | // also exist case: apply cooldown to interrupted cast only and to all spells |
---|
4440 | for (uint32 i = CURRENT_FIRST_NON_MELEE_SPELL; i < CURRENT_MAX_SPELL; i++) |
---|
4441 | { |
---|
4442 | if (unitTarget->m_currentSpells[i]) |
---|
4443 | { |
---|
4444 | // check if we can interrupt spell |
---|
4445 | if ( unitTarget->m_currentSpells[i]->m_spellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_INTERRUPT && unitTarget->m_currentSpells[i]->m_spellInfo->PreventionType == SPELL_PREVENTION_TYPE_SILENCE ) |
---|
4446 | { |
---|
4447 | unitTarget->ProhibitSpellScholl(GetSpellSchoolMask(unitTarget->m_currentSpells[i]->m_spellInfo), GetSpellDuration(m_spellInfo)); |
---|
4448 | unitTarget->InterruptSpell(i,false); |
---|
4449 | } |
---|
4450 | } |
---|
4451 | } |
---|
4452 | } |
---|
4453 | |
---|
4454 | void Spell::EffectSummonObjectWild(uint32 i) |
---|
4455 | { |
---|
4456 | uint32 gameobject_id = m_spellInfo->EffectMiscValue[i]; |
---|
4457 | |
---|
4458 | GameObject* pGameObj = new GameObject; |
---|
4459 | |
---|
4460 | WorldObject* target = focusObject; |
---|
4461 | if( !target ) |
---|
4462 | target = m_caster; |
---|
4463 | |
---|
4464 | float x,y,z; |
---|
4465 | if(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION) |
---|
4466 | { |
---|
4467 | x = m_targets.m_destX; |
---|
4468 | y = m_targets.m_destY; |
---|
4469 | z = m_targets.m_destZ; |
---|
4470 | } |
---|
4471 | else |
---|
4472 | m_caster->GetClosePoint(x,y,z,DEFAULT_WORLD_OBJECT_SIZE); |
---|
4473 | |
---|
4474 | Map *map = target->GetMap(); |
---|
4475 | |
---|
4476 | if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), gameobject_id, map, |
---|
4477 | x, y, z, target->GetOrientation(), 0, 0, 0, 0, 100, 1)) |
---|
4478 | { |
---|
4479 | delete pGameObj; |
---|
4480 | return; |
---|
4481 | } |
---|
4482 | |
---|
4483 | int32 duration = GetSpellDuration(m_spellInfo); |
---|
4484 | pGameObj->SetRespawnTime(duration > 0 ? duration/1000 : 0); |
---|
4485 | pGameObj->SetSpellId(m_spellInfo->Id); |
---|
4486 | |
---|
4487 | if(pGameObj->GetGoType() != GAMEOBJECT_TYPE_FLAGDROP) // make dropped flag clickable for other players (not set owner guid (created by) for this)... |
---|
4488 | m_caster->AddGameObject(pGameObj); |
---|
4489 | map->Add(pGameObj); |
---|
4490 | |
---|
4491 | if(pGameObj->GetMapId() == 489 && pGameObj->GetGoType() == GAMEOBJECT_TYPE_FLAGDROP) //WS |
---|
4492 | { |
---|
4493 | if(m_caster->GetTypeId() == TYPEID_PLAYER) |
---|
4494 | { |
---|
4495 | Player *pl = (Player*)m_caster; |
---|
4496 | BattleGround* bg = ((Player *)m_caster)->GetBattleGround(); |
---|
4497 | if(bg && bg->GetTypeID()==BATTLEGROUND_WS && bg->GetStatus() == STATUS_IN_PROGRESS) |
---|
4498 | { |
---|
4499 | uint32 team = ALLIANCE; |
---|
4500 | |
---|
4501 | if(pl->GetTeam() == team) |
---|
4502 | team = HORDE; |
---|
4503 | |
---|
4504 | ((BattleGroundWS*)bg)->SetDroppedFlagGUID(pGameObj->GetGUID(),team); |
---|
4505 | } |
---|
4506 | } |
---|
4507 | } |
---|
4508 | |
---|
4509 | if(pGameObj->GetMapId() == 566 && pGameObj->GetGoType() == GAMEOBJECT_TYPE_FLAGDROP) //EY |
---|
4510 | { |
---|
4511 | if(m_caster->GetTypeId() == TYPEID_PLAYER) |
---|
4512 | { |
---|
4513 | BattleGround* bg = ((Player *)m_caster)->GetBattleGround(); |
---|
4514 | if(bg && bg->GetTypeID()==BATTLEGROUND_EY && bg->GetStatus() == STATUS_IN_PROGRESS) |
---|
4515 | { |
---|
4516 | ((BattleGroundEY*)bg)->SetDroppedFlagGUID(pGameObj->GetGUID()); |
---|
4517 | } |
---|
4518 | } |
---|
4519 | } |
---|
4520 | |
---|
4521 | if(uint32 linkedEntry = pGameObj->GetLinkedGameObjectEntry()) |
---|
4522 | { |
---|
4523 | GameObject* linkedGO = new GameObject; |
---|
4524 | if(linkedGO->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), linkedEntry, map, |
---|
4525 | x, y, z, target->GetOrientation(), 0, 0, 0, 0, 100, 1)) |
---|
4526 | { |
---|
4527 | linkedGO->SetRespawnTime(duration > 0 ? duration/1000 : 0); |
---|
4528 | linkedGO->SetSpellId(m_spellInfo->Id); |
---|
4529 | |
---|
4530 | m_caster->AddGameObject(linkedGO); |
---|
4531 | map->Add(linkedGO); |
---|
4532 | } |
---|
4533 | else |
---|
4534 | { |
---|
4535 | delete linkedGO; |
---|
4536 | linkedGO = NULL; |
---|
4537 | return; |
---|
4538 | } |
---|
4539 | } |
---|
4540 | } |
---|
4541 | |
---|
4542 | void Spell::EffectScriptEffect(uint32 effIndex) |
---|
4543 | { |
---|
4544 | // TODO: we must implement hunter pet summon at login there (spell 6962) |
---|
4545 | |
---|
4546 | // by spell id |
---|
4547 | switch(m_spellInfo->Id) |
---|
4548 | { |
---|
4549 | // Bending Shinbone |
---|
4550 | case 8856: |
---|
4551 | { |
---|
4552 | if(!itemTarget && m_caster->GetTypeId()!=TYPEID_PLAYER) |
---|
4553 | return; |
---|
4554 | |
---|
4555 | uint32 spell_id = 0; |
---|
4556 | switch(urand(1,5)) |
---|
4557 | { |
---|
4558 | case 1: spell_id = 8854; break; |
---|
4559 | default: spell_id = 8855; break; |
---|
4560 | } |
---|
4561 | |
---|
4562 | m_caster->CastSpell(m_caster,spell_id,true,NULL); |
---|
4563 | return; |
---|
4564 | } |
---|
4565 | |
---|
4566 | // Healthstone creating spells |
---|
4567 | case 6201: |
---|
4568 | case 6202: |
---|
4569 | case 5699: |
---|
4570 | case 11729: |
---|
4571 | case 11730: |
---|
4572 | case 27230: |
---|
4573 | { |
---|
4574 | uint32 itemtype; |
---|
4575 | uint32 rank = 0; |
---|
4576 | Unit::AuraList const& mDummyAuras = unitTarget->GetAurasByType(SPELL_AURA_DUMMY); |
---|
4577 | for(Unit::AuraList::const_iterator i = mDummyAuras.begin();i != mDummyAuras.end(); ++i) |
---|
4578 | { |
---|
4579 | if((*i)->GetId() == 18692) |
---|
4580 | { |
---|
4581 | rank = 1; |
---|
4582 | break; |
---|
4583 | } |
---|
4584 | else if((*i)->GetId() == 18693) |
---|
4585 | { |
---|
4586 | rank = 2; |
---|
4587 | break; |
---|
4588 | } |
---|
4589 | } |
---|
4590 | |
---|
4591 | static uint32 const itypes[6][3] = { |
---|
4592 | { 5512,19004,19005}, // Minor Healthstone |
---|
4593 | { 5511,19006,19007}, // Lesser Healthstone |
---|
4594 | { 5509,19008,19009}, // Healthstone |
---|
4595 | { 5510,19010,19011}, // Greater Healthstone |
---|
4596 | { 9421,19012,19013}, // Major Healthstone |
---|
4597 | {22103,22104,22105} // Master Healthstone |
---|
4598 | }; |
---|
4599 | |
---|
4600 | switch(m_spellInfo->Id) |
---|
4601 | { |
---|
4602 | case 6201: itemtype=itypes[0][rank];break; // Minor Healthstone |
---|
4603 | case 6202: itemtype=itypes[1][rank];break; // Lesser Healthstone |
---|
4604 | case 5699: itemtype=itypes[2][rank];break; // Healthstone |
---|
4605 | case 11729: itemtype=itypes[3][rank];break; // Greater Healthstone |
---|
4606 | case 11730: itemtype=itypes[4][rank];break; // Major Healthstone |
---|
4607 | case 27230: itemtype=itypes[5][rank];break; // Master Healthstone |
---|
4608 | default: |
---|
4609 | return; |
---|
4610 | } |
---|
4611 | DoCreateItem( effIndex, itemtype ); |
---|
4612 | return; |
---|
4613 | } |
---|
4614 | // Brittle Armor - need remove one 24575 Brittle Armor aura |
---|
4615 | case 24590: |
---|
4616 | unitTarget->RemoveSingleAuraFromStack(24575, 0); |
---|
4617 | unitTarget->RemoveSingleAuraFromStack(24575, 1); |
---|
4618 | return; |
---|
4619 | // Mercurial Shield - need remove one 26464 Mercurial Shield aura |
---|
4620 | case 26465: |
---|
4621 | unitTarget->RemoveSingleAuraFromStack(26464, 0); |
---|
4622 | return; |
---|
4623 | // Orb teleport spells |
---|
4624 | case 25140: |
---|
4625 | case 25143: |
---|
4626 | case 25650: |
---|
4627 | case 25652: |
---|
4628 | case 29128: |
---|
4629 | case 29129: |
---|
4630 | case 35376: |
---|
4631 | case 35727: |
---|
4632 | { |
---|
4633 | if(!unitTarget) |
---|
4634 | return; |
---|
4635 | |
---|
4636 | uint32 spellid; |
---|
4637 | switch(m_spellInfo->Id) |
---|
4638 | { |
---|
4639 | case 25140: spellid = 32571; break; |
---|
4640 | case 25143: spellid = 32572; break; |
---|
4641 | case 25650: spellid = 30140; break; |
---|
4642 | case 25652: spellid = 30141; break; |
---|
4643 | case 29128: spellid = 32568; break; |
---|
4644 | case 29129: spellid = 32569; break; |
---|
4645 | case 35376: spellid = 25649; break; |
---|
4646 | case 35727: spellid = 35730; break; |
---|
4647 | default: |
---|
4648 | return; |
---|
4649 | } |
---|
4650 | |
---|
4651 | unitTarget->CastSpell(unitTarget,spellid,false); |
---|
4652 | return; |
---|
4653 | } |
---|
4654 | |
---|
4655 | // Shadow Flame (All script effects, not just end ones to prevent player from dodging the last triggered spell) |
---|
4656 | case 22539: |
---|
4657 | case 22972: |
---|
4658 | case 22975: |
---|
4659 | case 22976: |
---|
4660 | case 22977: |
---|
4661 | case 22978: |
---|
4662 | case 22979: |
---|
4663 | case 22980: |
---|
4664 | case 22981: |
---|
4665 | case 22982: |
---|
4666 | case 22983: |
---|
4667 | case 22984: |
---|
4668 | case 22985: |
---|
4669 | { |
---|
4670 | if(!unitTarget || !unitTarget->isAlive()) |
---|
4671 | return; |
---|
4672 | |
---|
4673 | // Onyxia Scale Cloak |
---|
4674 | if(unitTarget->GetDummyAura(22683)) |
---|
4675 | return; |
---|
4676 | |
---|
4677 | // Shadow Flame |
---|
4678 | m_caster->CastSpell(unitTarget, 22682, true); |
---|
4679 | return; |
---|
4680 | } |
---|
4681 | break; |
---|
4682 | |
---|
4683 | // Summon Black Qiraji Battle Tank |
---|
4684 | case 26656: |
---|
4685 | { |
---|
4686 | if(!unitTarget) |
---|
4687 | return; |
---|
4688 | |
---|
4689 | // Prevent stacking of mounts |
---|
4690 | unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED); |
---|
4691 | |
---|
4692 | // Two separate mounts depending on area id (allows use both in and out of specific instance) |
---|
4693 | if (unitTarget->GetAreaId() == 3428) |
---|
4694 | unitTarget->CastSpell(unitTarget, 25863, false); |
---|
4695 | else |
---|
4696 | unitTarget->CastSpell(unitTarget, 26655, false); |
---|
4697 | break; |
---|
4698 | } |
---|
4699 | // Piccolo of the Flaming Fire |
---|
4700 | case 17512: |
---|
4701 | { |
---|
4702 | if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) |
---|
4703 | return; |
---|
4704 | unitTarget->HandleEmoteCommand(EMOTE_STATE_DANCE); |
---|
4705 | break; |
---|
4706 | } |
---|
4707 | |
---|
4708 | // Dreaming Glory |
---|
4709 | case 28698: |
---|
4710 | { |
---|
4711 | if(!unitTarget) |
---|
4712 | return; |
---|
4713 | unitTarget->CastSpell(unitTarget, 28694, true); |
---|
4714 | break; |
---|
4715 | } |
---|
4716 | |
---|
4717 | // Netherbloom |
---|
4718 | case 28702: |
---|
4719 | { |
---|
4720 | if(!unitTarget) |
---|
4721 | return; |
---|
4722 | // 25% chance of casting a random buff |
---|
4723 | if(roll_chance_i(75)) |
---|
4724 | return; |
---|
4725 | |
---|
4726 | // triggered spells are 28703 to 28707 |
---|
4727 | // Note: some sources say, that there was the possibility of |
---|
4728 | // receiving a debuff. However, this seems to be removed by a patch. |
---|
4729 | const uint32 spellid = 28703; |
---|
4730 | |
---|
4731 | // don't overwrite an existing aura |
---|
4732 | for(uint8 i=0; i<5; i++) |
---|
4733 | if(unitTarget->HasAura(spellid+i, 0)) |
---|
4734 | return; |
---|
4735 | unitTarget->CastSpell(unitTarget, spellid+urand(0, 4), true); |
---|
4736 | break; |
---|
4737 | } |
---|
4738 | |
---|
4739 | // Nightmare Vine |
---|
4740 | case 28720: |
---|
4741 | { |
---|
4742 | if(!unitTarget) |
---|
4743 | return; |
---|
4744 | // 25% chance of casting Nightmare Pollen |
---|
4745 | if(roll_chance_i(75)) |
---|
4746 | return; |
---|
4747 | unitTarget->CastSpell(unitTarget, 28721, true); |
---|
4748 | break; |
---|
4749 | } |
---|
4750 | |
---|
4751 | // Mirren's Drinking Hat |
---|
4752 | case 29830: |
---|
4753 | { |
---|
4754 | uint32 item = 0; |
---|
4755 | switch ( urand(1,6) ) |
---|
4756 | { |
---|
4757 | case 1: case 2: case 3: item = 23584; break;// Loch Modan Lager |
---|
4758 | case 4: case 5: item = 23585; break;// Stouthammer Lite |
---|
4759 | case 6: item = 23586; break;// Aerie Peak Pale Ale |
---|
4760 | } |
---|
4761 | if (item) |
---|
4762 | DoCreateItem(effIndex,item); |
---|
4763 | break; |
---|
4764 | } |
---|
4765 | // Improved Sprint |
---|
4766 | case 30918: |
---|
4767 | { |
---|
4768 | // Removes snares and roots. |
---|
4769 | uint32 mechanic_mask = (1<<MECHANIC_ROOT) | (1<<MECHANIC_SNARE); |
---|
4770 | Unit::AuraMap& Auras = unitTarget->GetAuras(); |
---|
4771 | for(Unit::AuraMap::iterator iter = Auras.begin(), next; iter != Auras.end(); iter = next) |
---|
4772 | { |
---|
4773 | next = iter; |
---|
4774 | ++next; |
---|
4775 | Aura *aur = iter->second; |
---|
4776 | if (!aur->IsPositive()) //only remove negative spells |
---|
4777 | { |
---|
4778 | // check for mechanic mask |
---|
4779 | if(GetSpellMechanicMask(aur->GetSpellProto(), aur->GetEffIndex()) & mechanic_mask) |
---|
4780 | { |
---|
4781 | unitTarget->RemoveAurasDueToSpell(aur->GetId()); |
---|
4782 | if(Auras.empty()) |
---|
4783 | break; |
---|
4784 | else |
---|
4785 | next = Auras.begin(); |
---|
4786 | } |
---|
4787 | } |
---|
4788 | } |
---|
4789 | break; |
---|
4790 | } |
---|
4791 | case 41126: // Flame Crash |
---|
4792 | { |
---|
4793 | if(!unitTarget) |
---|
4794 | return; |
---|
4795 | |
---|
4796 | unitTarget->CastSpell(unitTarget, 41131, true); |
---|
4797 | break; |
---|
4798 | } |
---|
4799 | case 44876: // Force Cast - Portal Effect: Sunwell Isle |
---|
4800 | { |
---|
4801 | if(!unitTarget) |
---|
4802 | return; |
---|
4803 | |
---|
4804 | unitTarget->CastSpell(unitTarget, 44870, true); |
---|
4805 | break; |
---|
4806 | } |
---|
4807 | |
---|
4808 | // Goblin Weather Machine |
---|
4809 | case 46203: |
---|
4810 | { |
---|
4811 | if(!unitTarget) |
---|
4812 | return; |
---|
4813 | |
---|
4814 | uint32 spellId; |
---|
4815 | switch(rand()%4) |
---|
4816 | { |
---|
4817 | case 0: |
---|
4818 | spellId=46740; |
---|
4819 | break; |
---|
4820 | case 1: |
---|
4821 | spellId=46739; |
---|
4822 | break; |
---|
4823 | case 2: |
---|
4824 | spellId=46738; |
---|
4825 | break; |
---|
4826 | case 3: |
---|
4827 | spellId=46736; |
---|
4828 | break; |
---|
4829 | } |
---|
4830 | unitTarget->CastSpell(unitTarget, spellId, true); |
---|
4831 | break; |
---|
4832 | } |
---|
4833 | //5,000 Gold |
---|
4834 | case 46642: |
---|
4835 | { |
---|
4836 | if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) |
---|
4837 | return; |
---|
4838 | |
---|
4839 | ((Player*)unitTarget)->ModifyMoney(50000000); |
---|
4840 | |
---|
4841 | break; |
---|
4842 | } |
---|
4843 | } |
---|
4844 | |
---|
4845 | if( m_spellInfo->SpellFamilyName == SPELLFAMILY_PALADIN ) |
---|
4846 | { |
---|
4847 | switch(m_spellInfo->SpellFamilyFlags) |
---|
4848 | { |
---|
4849 | // Judgement |
---|
4850 | case 0x800000: |
---|
4851 | { |
---|
4852 | if(!unitTarget || !unitTarget->isAlive()) |
---|
4853 | return; |
---|
4854 | uint32 spellId2 = 0; |
---|
4855 | |
---|
4856 | // all seals have aura dummy |
---|
4857 | Unit::AuraList const& m_dummyAuras = m_caster->GetAurasByType(SPELL_AURA_DUMMY); |
---|
4858 | for(Unit::AuraList::const_iterator itr = m_dummyAuras.begin(); itr != m_dummyAuras.end(); ++itr) |
---|
4859 | { |
---|
4860 | SpellEntry const *spellInfo = (*itr)->GetSpellProto(); |
---|
4861 | |
---|
4862 | // search seal (all seals have judgement's aura dummy spell id in 2 effect |
---|
4863 | if ( !spellInfo || !IsSealSpell((*itr)->GetSpellProto()) || (*itr)->GetEffIndex() != 2 ) |
---|
4864 | continue; |
---|
4865 | |
---|
4866 | // must be calculated base at raw base points in spell proto, GetModifier()->m_value for S.Righteousness modified by SPELLMOD_DAMAGE |
---|
4867 | spellId2 = (*itr)->GetSpellProto()->EffectBasePoints[2]+1; |
---|
4868 | |
---|
4869 | if(spellId2 <= 1) |
---|
4870 | continue; |
---|
4871 | |
---|
4872 | // found, remove seal |
---|
4873 | m_caster->RemoveAurasDueToSpell((*itr)->GetId()); |
---|
4874 | |
---|
4875 | // Sanctified Judgement |
---|
4876 | Unit::AuraList const& m_auras = m_caster->GetAurasByType(SPELL_AURA_DUMMY); |
---|
4877 | for(Unit::AuraList::const_iterator i = m_auras.begin(); i != m_auras.end(); ++i) |
---|
4878 | { |
---|
4879 | if ((*i)->GetSpellProto()->SpellIconID == 205 && (*i)->GetSpellProto()->Attributes == 0x01D0LL) |
---|
4880 | { |
---|
4881 | int32 chance = (*i)->GetModifier()->m_amount; |
---|
4882 | if ( roll_chance_i(chance) ) |
---|
4883 | { |
---|
4884 | int32 mana = spellInfo->manaCost; |
---|
4885 | if ( Player* modOwner = m_caster->GetSpellModOwner() ) |
---|
4886 | modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_COST, mana); |
---|
4887 | mana = int32(mana* 0.8f); |
---|
4888 | m_caster->CastCustomSpell(m_caster,31930,&mana,NULL,NULL,true,NULL,*i); |
---|
4889 | } |
---|
4890 | break; |
---|
4891 | } |
---|
4892 | } |
---|
4893 | |
---|
4894 | break; |
---|
4895 | } |
---|
4896 | |
---|
4897 | m_caster->CastSpell(unitTarget,spellId2,true); |
---|
4898 | return; |
---|
4899 | } |
---|
4900 | } |
---|
4901 | } |
---|
4902 | |
---|
4903 | // normal DB scripted effect |
---|
4904 | if(!unitTarget) |
---|
4905 | return; |
---|
4906 | |
---|
4907 | sLog.outDebug("Spell ScriptStart spellid %u in EffectScriptEffect ", m_spellInfo->Id); |
---|
4908 | sWorld.ScriptsStart(sSpellScripts, m_spellInfo->Id, m_caster, unitTarget); |
---|
4909 | } |
---|
4910 | |
---|
4911 | void Spell::EffectSanctuary(uint32 /*i*/) |
---|
4912 | { |
---|
4913 | if(!unitTarget) |
---|
4914 | return; |
---|
4915 | //unitTarget->CombatStop(); |
---|
4916 | |
---|
4917 | unitTarget->CombatStop(); |
---|
4918 | unitTarget->getHostilRefManager().deleteReferences(); // stop all fighting |
---|
4919 | // Vanish allows to remove all threat and cast regular stealth so other spells can be used |
---|
4920 | if(m_spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && (m_spellInfo->SpellFamilyFlags & SPELLFAMILYFLAG_ROGUE_VANISH)) |
---|
4921 | { |
---|
4922 | ((Player *)m_caster)->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT); |
---|
4923 | } |
---|
4924 | } |
---|
4925 | |
---|
4926 | void Spell::EffectAddComboPoints(uint32 /*i*/) |
---|
4927 | { |
---|
4928 | if(!unitTarget) |
---|
4929 | return; |
---|
4930 | |
---|
4931 | if(m_caster->GetTypeId() != TYPEID_PLAYER) |
---|
4932 | return; |
---|
4933 | |
---|
4934 | if(damage <= 0) |
---|
4935 | return; |
---|
4936 | |
---|
4937 | ((Player*)m_caster)->AddComboPoints(unitTarget, damage); |
---|
4938 | } |
---|
4939 | |
---|
4940 | void Spell::EffectDuel(uint32 i) |
---|
4941 | { |
---|
4942 | if(!m_caster || !unitTarget || m_caster->GetTypeId() != TYPEID_PLAYER || unitTarget->GetTypeId() != TYPEID_PLAYER) |
---|
4943 | return; |
---|
4944 | |
---|
4945 | Player *caster = (Player*)m_caster; |
---|
4946 | Player *target = (Player*)unitTarget; |
---|
4947 | |
---|
4948 | // caster or target already have requested duel |
---|
4949 | if( caster->duel || target->duel || target->GetSocial()->HasIgnore(caster->GetGUIDLow()) ) |
---|
4950 | return; |
---|
4951 | |
---|
4952 | // Players can only fight a duel with each other outside (=not inside dungeons and not in capital cities) |
---|
4953 | // Don't have to check the target's map since you cannot challenge someone across maps |
---|
4954 | if( caster->GetMapId() != 0 && caster->GetMapId() != 1 && caster->GetMapId() != 530) |
---|
4955 | { |
---|
4956 | SendCastResult(SPELL_FAILED_NO_DUELING); // Dueling isn't allowed here |
---|
4957 | return; |
---|
4958 | } |
---|
4959 | |
---|
4960 | AreaTableEntry const* casterAreaEntry = GetAreaEntryByAreaID(caster->GetZoneId()); |
---|
4961 | if(casterAreaEntry && (casterAreaEntry->flags & AREA_FLAG_CAPITAL) ) |
---|
4962 | { |
---|
4963 | SendCastResult(SPELL_FAILED_NO_DUELING); // Dueling isn't allowed here |
---|
4964 | return; |
---|
4965 | } |
---|
4966 | |
---|
4967 | AreaTableEntry const* targetAreaEntry = GetAreaEntryByAreaID(target->GetZoneId()); |
---|
4968 | if(targetAreaEntry && (targetAreaEntry->flags & AREA_FLAG_CAPITAL) ) |
---|
4969 | { |
---|
4970 | SendCastResult(SPELL_FAILED_NO_DUELING); // Dueling isn't allowed here |
---|
4971 | return; |
---|
4972 | } |
---|
4973 | |
---|
4974 | //CREATE DUEL FLAG OBJECT |
---|
4975 | GameObject* pGameObj = new GameObject; |
---|
4976 | |
---|
4977 | uint32 gameobject_id = m_spellInfo->EffectMiscValue[i]; |
---|
4978 | |
---|
4979 | Map *map = m_caster->GetMap(); |
---|
4980 | if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), gameobject_id, map, |
---|
4981 | m_caster->GetPositionX()+(unitTarget->GetPositionX()-m_caster->GetPositionX())/2 , |
---|
4982 | m_caster->GetPositionY()+(unitTarget->GetPositionY()-m_caster->GetPositionY())/2 , |
---|
4983 | m_caster->GetPositionZ(), |
---|
4984 | m_caster->GetOrientation(), 0, 0, 0, 0, 0, 1)) |
---|
4985 | { |
---|
4986 | delete pGameObj; |
---|
4987 | return; |
---|
4988 | } |
---|
4989 | |
---|
4990 | pGameObj->SetUInt32Value(GAMEOBJECT_FACTION, m_caster->getFaction() ); |
---|
4991 | pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel()+1 ); |
---|
4992 | int32 duration = GetSpellDuration(m_spellInfo); |
---|
4993 | pGameObj->SetRespawnTime(duration > 0 ? duration/1000 : 0); |
---|
4994 | pGameObj->SetSpellId(m_spellInfo->Id); |
---|
4995 | |
---|
4996 | m_caster->AddGameObject(pGameObj); |
---|
4997 | map->Add(pGameObj); |
---|
4998 | //END |
---|
4999 | |
---|
5000 | // Send request |
---|
5001 | WorldPacket data(SMSG_DUEL_REQUESTED, 16); |
---|
5002 | data << pGameObj->GetGUID(); |
---|
5003 | data << caster->GetGUID(); |
---|
5004 | caster->GetSession()->SendPacket(&data); |
---|
5005 | target->GetSession()->SendPacket(&data); |
---|
5006 | |
---|
5007 | // create duel-info |
---|
5008 | DuelInfo *duel = new DuelInfo; |
---|
5009 | duel->initiator = caster; |
---|
5010 | duel->opponent = target; |
---|
5011 | duel->startTime = 0; |
---|
5012 | duel->startTimer = 0; |
---|
5013 | caster->duel = duel; |
---|
5014 | |
---|
5015 | DuelInfo *duel2 = new DuelInfo; |
---|
5016 | duel2->initiator = caster; |
---|
5017 | duel2->opponent = caster; |
---|
5018 | duel2->startTime = 0; |
---|
5019 | duel2->startTimer = 0; |
---|
5020 | target->duel = duel2; |
---|
5021 | |
---|
5022 | caster->SetUInt64Value(PLAYER_DUEL_ARBITER,pGameObj->GetGUID()); |
---|
5023 | target->SetUInt64Value(PLAYER_DUEL_ARBITER,pGameObj->GetGUID()); |
---|
5024 | } |
---|
5025 | |
---|
5026 | void Spell::EffectStuck(uint32 /*i*/) |
---|
5027 | { |
---|
5028 | if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) |
---|
5029 | return; |
---|
5030 | |
---|
5031 | if(!sWorld.getConfig(CONFIG_CAST_UNSTUCK)) |
---|
5032 | return; |
---|
5033 | |
---|
5034 | Player* pTarget = (Player*)unitTarget; |
---|
5035 | |
---|
5036 | sLog.outDebug("Spell Effect: Stuck"); |
---|
5037 | sLog.outDetail("Player %s (guid %u) used auto-unstuck future at map %u (%f, %f, %f)", pTarget->GetName(), pTarget->GetGUIDLow(), m_caster->GetMapId(), m_caster->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ()); |
---|
5038 | |
---|
5039 | if(pTarget->isInFlight()) |
---|
5040 | return; |
---|
5041 | |
---|
5042 | // homebind location is loaded always |
---|
5043 | pTarget->TeleportTo(pTarget->m_homebindMapId,pTarget->m_homebindX,pTarget->m_homebindY,pTarget->m_homebindZ,pTarget->GetOrientation(), (unitTarget==m_caster ? TELE_TO_SPELL : 0)); |
---|
5044 | |
---|
5045 | // Stuck spell trigger Hearthstone cooldown |
---|
5046 | SpellEntry const *spellInfo = sSpellStore.LookupEntry(8690); |
---|
5047 | if(!spellInfo) |
---|
5048 | return; |
---|
5049 | Spell spell(pTarget,spellInfo,true,0); |
---|
5050 | spell.SendSpellCooldown(); |
---|
5051 | } |
---|
5052 | |
---|
5053 | void Spell::EffectSummonPlayer(uint32 /*i*/) |
---|
5054 | { |
---|
5055 | if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) |
---|
5056 | return; |
---|
5057 | |
---|
5058 | // Evil Twin (ignore player summon, but hide this for summoner) |
---|
5059 | if(unitTarget->GetDummyAura(23445)) |
---|
5060 | return; |
---|
5061 | |
---|
5062 | float x,y,z; |
---|
5063 | m_caster->GetClosePoint(x,y,z,unitTarget->GetObjectSize()); |
---|
5064 | |
---|
5065 | ((Player*)unitTarget)->SetSummonPoint(m_caster->GetMapId(),x,y,z); |
---|
5066 | |
---|
5067 | WorldPacket data(SMSG_SUMMON_REQUEST, 8+4+4); |
---|
5068 | data << uint64(m_caster->GetGUID()); // summoner guid |
---|
5069 | data << uint32(m_caster->GetZoneId()); // summoner zone |
---|
5070 | data << uint32(MAX_PLAYER_SUMMON_DELAY*1000); // auto decline after msecs |
---|
5071 | ((Player*)unitTarget)->GetSession()->SendPacket(&data); |
---|
5072 | } |
---|
5073 | |
---|
5074 | static ScriptInfo generateActivateCommand() |
---|
5075 | { |
---|
5076 | ScriptInfo si; |
---|
5077 | si.command = SCRIPT_COMMAND_ACTIVATE_OBJECT; |
---|
5078 | return si; |
---|
5079 | } |
---|
5080 | |
---|
5081 | void Spell::EffectActivateObject(uint32 effect_idx) |
---|
5082 | { |
---|
5083 | if(!gameObjTarget) |
---|
5084 | return; |
---|
5085 | |
---|
5086 | static ScriptInfo activateCommand = generateActivateCommand(); |
---|
5087 | |
---|
5088 | int32 delay_secs = m_spellInfo->EffectMiscValue[effect_idx]; |
---|
5089 | |
---|
5090 | sWorld.ScriptCommandStart(activateCommand, delay_secs, m_caster, gameObjTarget); |
---|
5091 | } |
---|
5092 | |
---|
5093 | void Spell::EffectSummonTotem(uint32 i) |
---|
5094 | { |
---|
5095 | uint8 slot = 0; |
---|
5096 | switch(m_spellInfo->EffectMiscValueB[i]) |
---|
5097 | { |
---|
5098 | case SUMMON_TYPE_TOTEM_SLOT1: slot = 0; break; |
---|
5099 | case SUMMON_TYPE_TOTEM_SLOT2: slot = 1; break; |
---|
5100 | case SUMMON_TYPE_TOTEM_SLOT3: slot = 2; break; |
---|
5101 | case SUMMON_TYPE_TOTEM_SLOT4: slot = 3; break; |
---|
5102 | // Battle standard case |
---|
5103 | case SUMMON_TYPE_TOTEM: slot = 254; break; |
---|
5104 | // jewelery statue case, like totem without slot |
---|
5105 | case SUMMON_TYPE_GUARDIAN: slot = 255; break; |
---|
5106 | default: return; |
---|
5107 | } |
---|
5108 | |
---|
5109 | if(slot < MAX_TOTEM) |
---|
5110 | { |
---|
5111 | uint64 guid = m_caster->m_TotemSlot[slot]; |
---|
5112 | if(guid != 0) |
---|
5113 | { |
---|
5114 | Creature *OldTotem = ObjectAccessor::GetCreature(*m_caster, guid); |
---|
5115 | if(OldTotem && OldTotem->isTotem()) |
---|
5116 | ((Totem*)OldTotem)->UnSummon(); |
---|
5117 | } |
---|
5118 | } |
---|
5119 | |
---|
5120 | uint32 team = 0; |
---|
5121 | if (m_caster->GetTypeId()==TYPEID_PLAYER) |
---|
5122 | team = ((Player*)m_caster)->GetTeam(); |
---|
5123 | |
---|
5124 | Totem* pTotem = new Totem; |
---|
5125 | |
---|
5126 | if(!pTotem->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), m_caster->GetMap(), m_spellInfo->EffectMiscValue[i], team )) |
---|
5127 | { |
---|
5128 | delete pTotem; |
---|
5129 | return; |
---|
5130 | } |
---|
5131 | |
---|
5132 | float angle = slot < MAX_TOTEM ? M_PI/MAX_TOTEM - (slot*2*M_PI/MAX_TOTEM) : 0; |
---|
5133 | |
---|
5134 | float x,y,z; |
---|
5135 | m_caster->GetClosePoint(x,y,z,pTotem->GetObjectSize(),2.0f,angle); |
---|
5136 | |
---|
5137 | // totem must be at same Z in case swimming caster and etc. |
---|
5138 | if( fabs( z - m_caster->GetPositionZ() ) > 5 ) |
---|
5139 | z = m_caster->GetPositionZ(); |
---|
5140 | |
---|
5141 | pTotem->Relocate(x, y, z, m_caster->GetOrientation()); |
---|
5142 | |
---|
5143 | if(slot < MAX_TOTEM) |
---|
5144 | m_caster->m_TotemSlot[slot] = pTotem->GetGUID(); |
---|
5145 | |
---|
5146 | pTotem->SetOwner(m_caster->GetGUID()); |
---|
5147 | pTotem->SetTypeBySummonSpell(m_spellInfo); // must be after Create call where m_spells initilized |
---|
5148 | |
---|
5149 | int32 duration=GetSpellDuration(m_spellInfo); |
---|
5150 | if(Player* modOwner = m_caster->GetSpellModOwner()) |
---|
5151 | modOwner->ApplySpellMod(m_spellInfo->Id,SPELLMOD_DURATION, duration); |
---|
5152 | pTotem->SetDuration(duration); |
---|
5153 | |
---|
5154 | if (damage) // if not spell info, DB values used |
---|
5155 | { |
---|
5156 | pTotem->SetMaxHealth(damage); |
---|
5157 | pTotem->SetHealth(damage); |
---|
5158 | } |
---|
5159 | |
---|
5160 | pTotem->SetUInt32Value(UNIT_CREATED_BY_SPELL,m_spellInfo->Id); |
---|
5161 | pTotem->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_PVP_ATTACKABLE); |
---|
5162 | |
---|
5163 | pTotem->ApplySpellImmune(m_spellInfo->Id,IMMUNITY_STATE,SPELL_AURA_MOD_FEAR,true); |
---|
5164 | pTotem->ApplySpellImmune(m_spellInfo->Id,IMMUNITY_STATE,SPELL_AURA_TRANSFORM,true); |
---|
5165 | |
---|
5166 | pTotem->Summon(m_caster); |
---|
5167 | |
---|
5168 | if(slot < MAX_TOTEM && m_caster->GetTypeId() == TYPEID_PLAYER) |
---|
5169 | { |
---|
5170 | WorldPacket data(SMSG_TOTEM_CREATED, 1+8+4+4); |
---|
5171 | data << uint8(slot); |
---|
5172 | data << uint64(pTotem->GetGUID()); |
---|
5173 | data << uint32(duration); |
---|
5174 | data << uint32(m_spellInfo->Id); |
---|
5175 | ((Player*)m_caster)->SendDirectMessage(&data); |
---|
5176 | } |
---|
5177 | } |
---|
5178 | |
---|
5179 | void Spell::EffectEnchantHeldItem(uint32 i) |
---|
5180 | { |
---|
5181 | // this is only item spell effect applied to main-hand weapon of target player (players in area) |
---|
5182 | if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) |
---|
5183 | return; |
---|
5184 | |
---|
5185 | Player* item_owner = (Player*)unitTarget; |
---|
5186 | Item* item = item_owner->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND); |
---|
5187 | |
---|
5188 | if(!item ) |
---|
5189 | return; |
---|
5190 | |
---|
5191 | // must be equipped |
---|
5192 | if(!item ->IsEquipped()) |
---|
5193 | return; |
---|
5194 | |
---|
5195 | if (m_spellInfo->EffectMiscValue[i]) |
---|
5196 | { |
---|
5197 | uint32 enchant_id = m_spellInfo->EffectMiscValue[i]; |
---|
5198 | int32 duration = GetSpellDuration(m_spellInfo); //Try duration index first .. |
---|
5199 | if(!duration) |
---|
5200 | duration = m_currentBasePoints[i]+1; //Base points after .. |
---|
5201 | if(!duration) |
---|
5202 | duration = 10; //10 seconds for enchants which don't have listed duration |
---|
5203 | |
---|
5204 | SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id); |
---|
5205 | if(!pEnchant) |
---|
5206 | return; |
---|
5207 | |
---|
5208 | // Always go to temp enchantment slot |
---|
5209 | EnchantmentSlot slot = TEMP_ENCHANTMENT_SLOT; |
---|
5210 | |
---|
5211 | // Enchantment will not be applied if a different one already exists |
---|
5212 | if(item->GetEnchantmentId(slot) && item->GetEnchantmentId(slot) != enchant_id) |
---|
5213 | return; |
---|
5214 | |
---|
5215 | // Apply the temporary enchantment |
---|
5216 | item->SetEnchantment(slot, enchant_id, duration*1000, 0); |
---|
5217 | item_owner->ApplyEnchantment(item,slot,true); |
---|
5218 | } |
---|
5219 | } |
---|
5220 | |
---|
5221 | void Spell::EffectDisEnchant(uint32 /*i*/) |
---|
5222 | { |
---|
5223 | if(m_caster->GetTypeId() != TYPEID_PLAYER) |
---|
5224 | return; |
---|
5225 | |
---|
5226 | Player* p_caster = (Player*)m_caster; |
---|
5227 | if(!itemTarget || !itemTarget->GetProto()->DisenchantID) |
---|
5228 | return; |
---|
5229 | |
---|
5230 | p_caster->UpdateCraftSkill(m_spellInfo->Id); |
---|
5231 | |
---|
5232 | ((Player*)m_caster)->SendLoot(itemTarget->GetGUID(),LOOT_DISENCHANTING); |
---|
5233 | |
---|
5234 | // item will be removed at disenchanting end |
---|
5235 | } |
---|
5236 | |
---|
5237 | void Spell::EffectInebriate(uint32 /*i*/) |
---|
5238 | { |
---|
5239 | if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) |
---|
5240 | return; |
---|
5241 | |
---|
5242 | Player *player = (Player*)unitTarget; |
---|
5243 | uint16 currentDrunk = player->GetDrunkValue(); |
---|
5244 | uint16 drunkMod = damage * 256; |
---|
5245 | if (currentDrunk + drunkMod > 0xFFFF) |
---|
5246 | currentDrunk = 0xFFFF; |
---|
5247 | else |
---|
5248 | currentDrunk += drunkMod; |
---|
5249 | player->SetDrunkValue(currentDrunk, m_CastItem?m_CastItem->GetEntry():0); |
---|
5250 | } |
---|
5251 | |
---|
5252 | void Spell::EffectFeedPet(uint32 i) |
---|
5253 | { |
---|
5254 | if(m_caster->GetTypeId() != TYPEID_PLAYER) |
---|
5255 | return; |
---|
5256 | |
---|
5257 | Player *_player = (Player*)m_caster; |
---|
5258 | |
---|
5259 | if(!itemTarget) |
---|
5260 | return; |
---|
5261 | |
---|
5262 | Pet *pet = _player->GetPet(); |
---|
5263 | if(!pet) |
---|
5264 | return; |
---|
5265 | |
---|
5266 | if(!pet->isAlive()) |
---|
5267 | return; |
---|
5268 | |
---|
5269 | int32 benefit = pet->GetCurrentFoodBenefitLevel(itemTarget->GetProto()->ItemLevel); |
---|
5270 | if(benefit <= 0) |
---|
5271 | return; |
---|
5272 | |
---|
5273 | uint32 count = 1; |
---|
5274 | _player->DestroyItemCount(itemTarget,count,true); |
---|
5275 | // TODO: fix crash when a spell has two effects, both pointed at the same item target |
---|
5276 | |
---|
5277 | m_caster->CastCustomSpell(m_caster,m_spellInfo->EffectTriggerSpell[i],&benefit,NULL,NULL,true); |
---|
5278 | } |
---|
5279 | |
---|
5280 | void Spell::EffectDismissPet(uint32 /*i*/) |
---|
5281 | { |
---|
5282 | if(m_caster->GetTypeId() != TYPEID_PLAYER) |
---|
5283 | return; |
---|
5284 | |
---|
5285 | Pet* pet = m_caster->GetPet(); |
---|
5286 | |
---|
5287 | // not let dismiss dead pet |
---|
5288 | if(!pet||!pet->isAlive()) |
---|
5289 | return; |
---|
5290 | |
---|
5291 | ((Player*)m_caster)->RemovePet(pet,PET_SAVE_NOT_IN_SLOT); |
---|
5292 | } |
---|
5293 | |
---|
5294 | void Spell::EffectSummonObject(uint32 i) |
---|
5295 | { |
---|
5296 | uint32 go_id = m_spellInfo->EffectMiscValue[i]; |
---|
5297 | |
---|
5298 | uint8 slot = 0; |
---|
5299 | switch(m_spellInfo->Effect[i]) |
---|
5300 | { |
---|
5301 | case SPELL_EFFECT_SUMMON_OBJECT_SLOT1: slot = 0; break; |
---|
5302 | case SPELL_EFFECT_SUMMON_OBJECT_SLOT2: slot = 1; break; |
---|
5303 | case SPELL_EFFECT_SUMMON_OBJECT_SLOT3: slot = 2; break; |
---|
5304 | case SPELL_EFFECT_SUMMON_OBJECT_SLOT4: slot = 3; break; |
---|
5305 | default: return; |
---|
5306 | } |
---|
5307 | |
---|
5308 | uint64 guid = m_caster->m_ObjectSlot[slot]; |
---|
5309 | if(guid != 0) |
---|
5310 | { |
---|
5311 | GameObject* obj = NULL; |
---|
5312 | if( m_caster ) |
---|
5313 | obj = ObjectAccessor::GetGameObject(*m_caster, guid); |
---|
5314 | |
---|
5315 | if(obj) obj->Delete(); |
---|
5316 | m_caster->m_ObjectSlot[slot] = 0; |
---|
5317 | } |
---|
5318 | |
---|
5319 | GameObject* pGameObj = new GameObject; |
---|
5320 | |
---|
5321 | float rot2 = sin(m_caster->GetOrientation()/2); |
---|
5322 | float rot3 = cos(m_caster->GetOrientation()/2); |
---|
5323 | |
---|
5324 | float x,y,z; |
---|
5325 | // If dest location if present |
---|
5326 | if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION) |
---|
5327 | { |
---|
5328 | x = m_targets.m_destX; |
---|
5329 | y = m_targets.m_destY; |
---|
5330 | z = m_targets.m_destZ; |
---|
5331 | } |
---|
5332 | // Summon in random point all other units if location present |
---|
5333 | else |
---|
5334 | m_caster->GetClosePoint(x,y,z,DEFAULT_WORLD_OBJECT_SIZE); |
---|
5335 | |
---|
5336 | Map *map = m_caster->GetMap(); |
---|
5337 | if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), go_id, map, x, y, z, m_caster->GetOrientation(), 0, 0, rot2, rot3, 0, 1)) |
---|
5338 | { |
---|
5339 | delete pGameObj; |
---|
5340 | return; |
---|
5341 | } |
---|
5342 | |
---|
5343 | pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL,m_caster->getLevel()); |
---|
5344 | int32 duration = GetSpellDuration(m_spellInfo); |
---|
5345 | pGameObj->SetRespawnTime(duration > 0 ? duration/1000 : 0); |
---|
5346 | pGameObj->SetSpellId(m_spellInfo->Id); |
---|
5347 | m_caster->AddGameObject(pGameObj); |
---|
5348 | |
---|
5349 | map->Add(pGameObj); |
---|
5350 | WorldPacket data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE, 8); |
---|
5351 | data << pGameObj->GetGUID(); |
---|
5352 | m_caster->SendMessageToSet(&data,true); |
---|
5353 | |
---|
5354 | m_caster->m_ObjectSlot[slot] = pGameObj->GetGUID(); |
---|
5355 | } |
---|
5356 | |
---|
5357 | void Spell::EffectResurrect(uint32 i) |
---|
5358 | { |
---|
5359 | if(!unitTarget) |
---|
5360 | return; |
---|
5361 | if(unitTarget->GetTypeId() != TYPEID_PLAYER) |
---|
5362 | return; |
---|
5363 | |
---|
5364 | if(unitTarget->isAlive()) |
---|
5365 | return; |
---|
5366 | if(!unitTarget->IsInWorld()) |
---|
5367 | return; |
---|
5368 | |
---|
5369 | switch (m_spellInfo->Id) |
---|
5370 | { |
---|
5371 | // Defibrillate (Goblin Jumper Cables) have 33% chance on success |
---|
5372 | case 8342: |
---|
5373 | if (roll_chance_i(67)) |
---|
5374 | { |
---|
5375 | m_caster->CastSpell(m_caster, 8338, true, m_CastItem); |
---|
5376 | return; |
---|
5377 | } |
---|
5378 | break; |
---|
5379 | // Defibrillate (Goblin Jumper Cables XL) have 50% chance on success |
---|
5380 | case 22999: |
---|
5381 | if (roll_chance_i(50)) |
---|
5382 | { |
---|
5383 | m_caster->CastSpell(m_caster, 23055, true, m_CastItem); |
---|
5384 | return; |
---|
5385 | } |
---|
5386 | break; |
---|
5387 | default: |
---|
5388 | break; |
---|
5389 | } |
---|
5390 | |
---|
5391 | Player* pTarget = ((Player*)unitTarget); |
---|
5392 | |
---|
5393 | if(pTarget->isRessurectRequested()) // already have one active request |
---|
5394 | return; |
---|
5395 | |
---|
5396 | uint32 health = pTarget->GetMaxHealth() * damage / 100; |
---|
5397 | uint32 mana = pTarget->GetMaxPower(POWER_MANA) * damage / 100; |
---|
5398 | |
---|
5399 | pTarget->setResurrectRequestData(m_caster->GetGUID(), m_caster->GetMapId(), m_caster->GetPositionX(), m_caster->GetPositionY(), m_caster->GetPositionZ(), health, mana); |
---|
5400 | SendResurrectRequest(pTarget); |
---|
5401 | } |
---|
5402 | |
---|
5403 | void Spell::EffectAddExtraAttacks(uint32 /*i*/) |
---|
5404 | { |
---|
5405 | if(!unitTarget || !unitTarget->isAlive()) |
---|
5406 | return; |
---|
5407 | |
---|
5408 | if( unitTarget->m_extraAttacks ) |
---|
5409 | return; |
---|
5410 | |
---|
5411 | unitTarget->m_extraAttacks = damage; |
---|
5412 | } |
---|
5413 | |
---|
5414 | void Spell::EffectParry(uint32 /*i*/) |
---|
5415 | { |
---|
5416 | if (unitTarget->GetTypeId() == TYPEID_PLAYER) |
---|
5417 | { |
---|
5418 | ((Player*)unitTarget)->SetCanParry(true); |
---|
5419 | } |
---|
5420 | } |
---|
5421 | |
---|
5422 | void Spell::EffectBlock(uint32 /*i*/) |
---|
5423 | { |
---|
5424 | if (unitTarget->GetTypeId() != TYPEID_PLAYER) |
---|
5425 | return; |
---|
5426 | |
---|
5427 | ((Player*)unitTarget)->SetCanBlock(true); |
---|
5428 | } |
---|
5429 | |
---|
5430 | void Spell::EffectMomentMove(uint32 i) |
---|
5431 | { |
---|
5432 | if(unitTarget->isInFlight()) |
---|
5433 | return; |
---|
5434 | |
---|
5435 | if( m_spellInfo->rangeIndex== 1) //self range |
---|
5436 | { |
---|
5437 | uint32 mapid = m_caster->GetMapId(); |
---|
5438 | float dis = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i])); |
---|
5439 | |
---|
5440 | // before caster |
---|
5441 | float fx,fy,fz; |
---|
5442 | unitTarget->GetClosePoint(fx,fy,fz,unitTarget->GetObjectSize(),dis); |
---|
5443 | float ox,oy,oz; |
---|
5444 | unitTarget->GetPosition(ox,oy,oz); |
---|
5445 | |
---|
5446 | float fx2,fy2,fz2; // getObjectHitPos overwrite last args in any result case |
---|
5447 | if(VMAP::VMapFactory::createOrGetVMapManager()->getObjectHitPos(mapid, ox,oy,oz+0.5, fx,fy,oz+0.5,fx2,fy2,fz2, -0.5)) |
---|
5448 | { |
---|
5449 | fx = fx2; |
---|
5450 | fy = fy2; |
---|
5451 | fz = fz2; |
---|
5452 | unitTarget->UpdateGroundPositionZ(fx,fy,fz); |
---|
5453 | } |
---|
5454 | |
---|
5455 | if(unitTarget->GetTypeId() == TYPEID_PLAYER) |
---|
5456 | ((Player*)unitTarget)->TeleportTo(mapid, fx, fy, fz, unitTarget->GetOrientation(), TELE_TO_NOT_LEAVE_COMBAT | TELE_TO_NOT_UNSUMMON_PET | (unitTarget==m_caster ? TELE_TO_SPELL : 0)); |
---|
5457 | else |
---|
5458 | MapManager::Instance().GetMap(mapid, unitTarget)->CreatureRelocation((Creature*)unitTarget, fx, fy, fz, unitTarget->GetOrientation()); |
---|
5459 | } |
---|
5460 | } |
---|
5461 | |
---|
5462 | void Spell::EffectReputation(uint32 i) |
---|
5463 | { |
---|
5464 | if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) |
---|
5465 | return; |
---|
5466 | |
---|
5467 | Player *_player = (Player*)unitTarget; |
---|
5468 | |
---|
5469 | int32 rep_change = m_currentBasePoints[i]+1; // field store reputation change -1 |
---|
5470 | |
---|
5471 | uint32 faction_id = m_spellInfo->EffectMiscValue[i]; |
---|
5472 | |
---|
5473 | FactionEntry const* factionEntry = sFactionStore.LookupEntry(faction_id); |
---|
5474 | |
---|
5475 | if(!factionEntry) |
---|
5476 | return; |
---|
5477 | |
---|
5478 | _player->ModifyFactionReputation(factionEntry,rep_change); |
---|
5479 | } |
---|
5480 | |
---|
5481 | void Spell::EffectQuestComplete(uint32 i) |
---|
5482 | { |
---|
5483 | if(m_caster->GetTypeId() != TYPEID_PLAYER) |
---|
5484 | return; |
---|
5485 | |
---|
5486 | Player *_player = (Player*)m_caster; |
---|
5487 | |
---|
5488 | uint32 quest_id = m_spellInfo->EffectMiscValue[i]; |
---|
5489 | _player->AreaExploredOrEventHappens(quest_id); |
---|
5490 | } |
---|
5491 | |
---|
5492 | void Spell::EffectSelfResurrect(uint32 i) |
---|
5493 | { |
---|
5494 | if(!unitTarget || unitTarget->isAlive()) |
---|
5495 | return; |
---|
5496 | if(unitTarget->GetTypeId() != TYPEID_PLAYER) |
---|
5497 | return; |
---|
5498 | if(!unitTarget->IsInWorld()) |
---|
5499 | return; |
---|
5500 | |
---|
5501 | uint32 health = 0; |
---|
5502 | uint32 mana = 0; |
---|
5503 | |
---|
5504 | // flat case |
---|
5505 | if(damage < 0) |
---|
5506 | { |
---|
5507 | health = uint32(-damage); |
---|
5508 | mana = m_spellInfo->EffectMiscValue[i]; |
---|
5509 | } |
---|
5510 | // percent case |
---|
5511 | else |
---|
5512 | { |
---|
5513 | health = uint32(damage/100.0f*unitTarget->GetMaxHealth()); |
---|
5514 | if(unitTarget->GetMaxPower(POWER_MANA) > 0) |
---|
5515 | mana = uint32(damage/100.0f*unitTarget->GetMaxPower(POWER_MANA)); |
---|
5516 | } |
---|
5517 | |
---|
5518 | Player *plr = ((Player*)unitTarget); |
---|
5519 | plr->ResurrectPlayer(0.0f); |
---|
5520 | |
---|
5521 | plr->SetHealth( health ); |
---|
5522 | plr->SetPower(POWER_MANA, mana ); |
---|
5523 | plr->SetPower(POWER_RAGE, 0 ); |
---|
5524 | plr->SetPower(POWER_ENERGY, plr->GetMaxPower(POWER_ENERGY) ); |
---|
5525 | |
---|
5526 | plr->SpawnCorpseBones(); |
---|
5527 | |
---|
5528 | plr->SaveToDB(); |
---|
5529 | } |
---|
5530 | |
---|
5531 | void Spell::EffectSkinning(uint32 /*i*/) |
---|
5532 | { |
---|
5533 | if(unitTarget->GetTypeId() != TYPEID_UNIT ) |
---|
5534 | return; |
---|
5535 | if(!m_caster || m_caster->GetTypeId() != TYPEID_PLAYER) |
---|
5536 | return; |
---|
5537 | |
---|
5538 | Creature* creature = (Creature*) unitTarget; |
---|
5539 | int32 targetLevel = creature->getLevel(); |
---|
5540 | |
---|
5541 | uint32 skill; |
---|
5542 | if(creature->GetCreatureInfo()->flag1 & 256) |
---|
5543 | skill = SKILL_HERBALISM; // special case |
---|
5544 | else if(creature->GetCreatureInfo()->flag1 & 512) |
---|
5545 | skill = SKILL_MINING; // special case |
---|
5546 | else |
---|
5547 | skill = SKILL_SKINNING; // normal case |
---|
5548 | |
---|
5549 | ((Player*)m_caster)->SendLoot(creature->GetGUID(),LOOT_SKINNING); |
---|
5550 | creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE); |
---|
5551 | |
---|
5552 | int32 reqValue = targetLevel < 10 ? 0 : targetLevel < 20 ? (targetLevel-10)*10 : targetLevel*5; |
---|
5553 | |
---|
5554 | int32 skillValue = ((Player*)m_caster)->GetPureSkillValue(skill); |
---|
5555 | |
---|
5556 | // Double chances for elites |
---|
5557 | ((Player*)m_caster)->UpdateGatherSkill(skill, skillValue, reqValue, creature->isElite() ? 2 : 1 ); |
---|
5558 | } |
---|
5559 | |
---|
5560 | void Spell::EffectCharge(uint32 /*i*/) |
---|
5561 | { |
---|
5562 | if(!unitTarget || !m_caster) |
---|
5563 | return; |
---|
5564 | |
---|
5565 | float x, y, z; |
---|
5566 | unitTarget->GetContactPoint(m_caster, x, y, z); |
---|
5567 | if(unitTarget->GetTypeId() != TYPEID_PLAYER) |
---|
5568 | ((Creature *)unitTarget)->StopMoving(); |
---|
5569 | |
---|
5570 | // Only send MOVEMENTFLAG_WALK_MODE, client has strange issues with other move flags |
---|
5571 | m_caster->SendMonsterMove(x, y, z, 0, MOVEMENTFLAG_WALK_MODE, 1); |
---|
5572 | |
---|
5573 | if(m_caster->GetTypeId() != TYPEID_PLAYER) |
---|
5574 | MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster)->CreatureRelocation((Creature*)m_caster,x,y,z,m_caster->GetOrientation()); |
---|
5575 | |
---|
5576 | // not all charge effects used in negative spells |
---|
5577 | if ( !IsPositiveSpell(m_spellInfo->Id)) |
---|
5578 | m_caster->Attack(unitTarget,true); |
---|
5579 | } |
---|
5580 | |
---|
5581 | void Spell::EffectSummonCritter(uint32 i) |
---|
5582 | { |
---|
5583 | if(m_caster->GetTypeId() != TYPEID_PLAYER) |
---|
5584 | return; |
---|
5585 | Player* player = (Player*)m_caster; |
---|
5586 | |
---|
5587 | uint32 pet_entry = m_spellInfo->EffectMiscValue[i]; |
---|
5588 | if(!pet_entry) |
---|
5589 | return; |
---|
5590 | |
---|
5591 | Pet* old_critter = player->GetMiniPet(); |
---|
5592 | |
---|
5593 | // for same pet just despawn |
---|
5594 | if(old_critter && old_critter->GetEntry() == pet_entry) |
---|
5595 | { |
---|
5596 | player->RemoveMiniPet(); |
---|
5597 | return; |
---|
5598 | } |
---|
5599 | |
---|
5600 | // despawn old pet before summon new |
---|
5601 | if(old_critter) |
---|
5602 | player->RemoveMiniPet(); |
---|
5603 | |
---|
5604 | // summon new pet |
---|
5605 | Pet* critter = new Pet(MINI_PET); |
---|
5606 | |
---|
5607 | Map *map = m_caster->GetMap(); |
---|
5608 | uint32 pet_number = objmgr.GeneratePetNumber(); |
---|
5609 | if(!critter->Create(objmgr.GenerateLowGuid(HIGHGUID_PET), |
---|
5610 | map, pet_entry, pet_number)) |
---|
5611 | { |
---|
5612 | sLog.outError("Spell::EffectSummonCritter, spellid %u: no such creature entry %u", m_spellInfo->Id, pet_entry); |
---|
5613 | delete critter; |
---|
5614 | return; |
---|
5615 | } |
---|
5616 | |
---|
5617 | float x,y,z; |
---|
5618 | // If dest location if present |
---|
5619 | if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION) |
---|
5620 | { |
---|
5621 | x = m_targets.m_destX; |
---|
5622 | y = m_targets.m_destY; |
---|
5623 | z = m_targets.m_destZ; |
---|
5624 | } |
---|
5625 | // Summon if dest location not present near caster |
---|
5626 | else |
---|
5627 | m_caster->GetClosePoint(x,y,z,critter->GetObjectSize()); |
---|
5628 | |
---|
5629 | critter->Relocate(x,y,z,m_caster->GetOrientation()); |
---|
5630 | |
---|
5631 | if(!critter->IsPositionValid()) |
---|
5632 | { |
---|
5633 | sLog.outError("ERROR: Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %d Y: ^%d)", critter->GetGUIDLow(), critter->GetEntry(), critter->GetPositionX(), critter->GetPositionY()); |
---|
5634 | delete critter; |
---|
5635 | return; |
---|
5636 | } |
---|
5637 | |
---|
5638 | critter->SetUInt64Value(UNIT_FIELD_SUMMONEDBY,m_caster->GetGUID()); |
---|
5639 | critter->SetUInt64Value(UNIT_FIELD_CREATEDBY,m_caster->GetGUID()); |
---|
5640 | critter->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,m_caster->getFaction()); |
---|
5641 | critter->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id); |
---|
5642 | |
---|
5643 | critter->AIM_Initialize(); |
---|
5644 | critter->InitPetCreateSpells(); // e.g. disgusting oozeling has a create spell as critter... |
---|
5645 | critter->SetMaxHealth(1); |
---|
5646 | critter->SetHealth(1); |
---|
5647 | critter->SetLevel(1); |
---|
5648 | |
---|
5649 | // set timer for unsummon |
---|
5650 | int32 duration = GetSpellDuration(m_spellInfo); |
---|
5651 | if(duration > 0) |
---|
5652 | critter->SetDuration(duration); |
---|
5653 | |
---|
5654 | std::string name = player->GetName(); |
---|
5655 | name.append(petTypeSuffix[critter->getPetType()]); |
---|
5656 | critter->SetName( name ); |
---|
5657 | player->SetMiniPet(critter); |
---|
5658 | |
---|
5659 | map->Add((Creature*)critter); |
---|
5660 | } |
---|
5661 | |
---|
5662 | void Spell::EffectKnockBack(uint32 i) |
---|
5663 | { |
---|
5664 | if(!unitTarget || !m_caster) |
---|
5665 | return; |
---|
5666 | |
---|
5667 | // Effect only works on players |
---|
5668 | if(unitTarget->GetTypeId()!=TYPEID_PLAYER) |
---|
5669 | return; |
---|
5670 | |
---|
5671 | float vsin = sin(m_caster->GetAngle(unitTarget)); |
---|
5672 | float vcos = cos(m_caster->GetAngle(unitTarget)); |
---|
5673 | |
---|
5674 | WorldPacket data(SMSG_MOVE_KNOCK_BACK, (8+4+4+4+4+4)); |
---|
5675 | data.append(unitTarget->GetPackGUID()); |
---|
5676 | data << uint32(0); // Sequence |
---|
5677 | data << float(vcos); // x direction |
---|
5678 | data << float(vsin); // y direction |
---|
5679 | data << float(m_spellInfo->EffectMiscValue[i])/10; // Horizontal speed |
---|
5680 | data << float(damage/-10); // Z Movement speed (vertical) |
---|
5681 | |
---|
5682 | ((Player*)unitTarget)->GetSession()->SendPacket(&data); |
---|
5683 | } |
---|
5684 | |
---|
5685 | void Spell::EffectSendTaxi(uint32 i) |
---|
5686 | { |
---|
5687 | if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) |
---|
5688 | return; |
---|
5689 | |
---|
5690 | TaxiPathEntry const* entry = sTaxiPathStore.LookupEntry(m_spellInfo->EffectMiscValue[i]); |
---|
5691 | if(!entry) |
---|
5692 | return; |
---|
5693 | |
---|
5694 | std::vector<uint32> nodes; |
---|
5695 | |
---|
5696 | nodes.resize(2); |
---|
5697 | nodes[0] = entry->from; |
---|
5698 | nodes[1] = entry->to; |
---|
5699 | |
---|
5700 | uint32 mountid = 0; |
---|
5701 | switch(m_spellInfo->Id) |
---|
5702 | { |
---|
5703 | case 31606: //Stormcrow Amulet |
---|
5704 | mountid = 17447; |
---|
5705 | break; |
---|
5706 | case 45071: //Quest - Sunwell Daily - Dead Scar Bombing Run |
---|
5707 | case 45113: //Quest - Sunwell Daily - Ship Bombing Run |
---|
5708 | case 45353: //Quest - Sunwell Daily - Ship Bombing Run Return |
---|
5709 | mountid = 22840; |
---|
5710 | break; |
---|
5711 | case 34905: //Stealth Flight |
---|
5712 | mountid = 6851; |
---|
5713 | break; |
---|
5714 | } |
---|
5715 | |
---|
5716 | ((Player*)unitTarget)->ActivateTaxiPathTo(nodes,mountid); |
---|
5717 | |
---|
5718 | } |
---|
5719 | |
---|
5720 | void Spell::EffectPlayerPull(uint32 i) |
---|
5721 | { |
---|
5722 | if(!unitTarget || !m_caster) |
---|
5723 | return; |
---|
5724 | |
---|
5725 | // Effect only works on players |
---|
5726 | if(unitTarget->GetTypeId()!=TYPEID_PLAYER) |
---|
5727 | return; |
---|
5728 | |
---|
5729 | float vsin = sin(unitTarget->GetAngle(m_caster)); |
---|
5730 | float vcos = cos(unitTarget->GetAngle(m_caster)); |
---|
5731 | |
---|
5732 | WorldPacket data(SMSG_MOVE_KNOCK_BACK, (8+4+4+4+4+4)); |
---|
5733 | data.append(unitTarget->GetPackGUID()); |
---|
5734 | data << uint32(0); // Sequence |
---|
5735 | data << float(vcos); // x direction |
---|
5736 | data << float(vsin); // y direction |
---|
5737 | // Horizontal speed |
---|
5738 | data << float(damage ? damage : unitTarget->GetDistance2d(m_caster)); |
---|
5739 | data << float(m_spellInfo->EffectMiscValue[i])/-10; // Z Movement speed |
---|
5740 | |
---|
5741 | ((Player*)unitTarget)->GetSession()->SendPacket(&data); |
---|
5742 | } |
---|
5743 | |
---|
5744 | void Spell::EffectDispelMechanic(uint32 i) |
---|
5745 | { |
---|
5746 | if(!unitTarget) |
---|
5747 | return; |
---|
5748 | |
---|
5749 | uint32 mechanic = m_spellInfo->EffectMiscValue[i]; |
---|
5750 | |
---|
5751 | Unit::AuraMap& Auras = unitTarget->GetAuras(); |
---|
5752 | for(Unit::AuraMap::iterator iter = Auras.begin(), next; iter != Auras.end(); iter = next) |
---|
5753 | { |
---|
5754 | next = iter; |
---|
5755 | ++next; |
---|
5756 | SpellEntry const *spell = sSpellStore.LookupEntry(iter->second->GetSpellProto()->Id); |
---|
5757 | if(spell->Mechanic == mechanic || spell->EffectMechanic[iter->second->GetEffIndex()] == mechanic) |
---|
5758 | { |
---|
5759 | unitTarget->RemoveAurasDueToSpell(spell->Id); |
---|
5760 | if(Auras.empty()) |
---|
5761 | break; |
---|
5762 | else |
---|
5763 | next = Auras.begin(); |
---|
5764 | } |
---|
5765 | } |
---|
5766 | return; |
---|
5767 | } |
---|
5768 | |
---|
5769 | void Spell::EffectSummonDeadPet(uint32 /*i*/) |
---|
5770 | { |
---|
5771 | if(m_caster->GetTypeId() != TYPEID_PLAYER) |
---|
5772 | return; |
---|
5773 | Player *_player = (Player*)m_caster; |
---|
5774 | Pet *pet = _player->GetPet(); |
---|
5775 | if(!pet) |
---|
5776 | return; |
---|
5777 | if(pet->isAlive()) |
---|
5778 | return; |
---|
5779 | if(damage < 0) |
---|
5780 | return; |
---|
5781 | pet->SetUInt32Value(UNIT_DYNAMIC_FLAGS, 0); |
---|
5782 | pet->RemoveFlag (UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE); |
---|
5783 | pet->setDeathState( ALIVE ); |
---|
5784 | pet->clearUnitState(UNIT_STAT_ALL_STATE); |
---|
5785 | pet->SetHealth( uint32(pet->GetMaxHealth()*(float(damage)/100))); |
---|
5786 | |
---|
5787 | pet->AIM_Initialize(); |
---|
5788 | |
---|
5789 | _player->PetSpellInitialize(); |
---|
5790 | pet->SavePetToDB(PET_SAVE_AS_CURRENT); |
---|
5791 | } |
---|
5792 | |
---|
5793 | void Spell::EffectDestroyAllTotems(uint32 /*i*/) |
---|
5794 | { |
---|
5795 | float mana = 0; |
---|
5796 | for(int slot = 0; slot < MAX_TOTEM; ++slot) |
---|
5797 | { |
---|
5798 | if(!m_caster->m_TotemSlot[slot]) |
---|
5799 | continue; |
---|
5800 | |
---|
5801 | Creature* totem = ObjectAccessor::GetCreature(*m_caster,m_caster->m_TotemSlot[slot]); |
---|
5802 | if(totem && totem->isTotem()) |
---|
5803 | { |
---|
5804 | uint32 spell_id = totem->GetUInt32Value(UNIT_CREATED_BY_SPELL); |
---|
5805 | SpellEntry const* spellInfo = sSpellStore.LookupEntry(spell_id); |
---|
5806 | if(spellInfo) |
---|
5807 | mana += spellInfo->manaCost * damage / 100; |
---|
5808 | ((Totem*)totem)->UnSummon(); |
---|
5809 | } |
---|
5810 | } |
---|
5811 | |
---|
5812 | int32 gain = m_caster->ModifyPower(POWER_MANA,int32(mana)); |
---|
5813 | m_caster->SendEnergizeSpellLog(m_caster, m_spellInfo->Id, gain, POWER_MANA); |
---|
5814 | } |
---|
5815 | |
---|
5816 | void Spell::EffectDurabilityDamage(uint32 i) |
---|
5817 | { |
---|
5818 | if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) |
---|
5819 | return; |
---|
5820 | |
---|
5821 | int32 slot = m_spellInfo->EffectMiscValue[i]; |
---|
5822 | |
---|
5823 | // FIXME: some spells effects have value -1/-2 |
---|
5824 | // Possibly its mean -1 all player equipped items and -2 all items |
---|
5825 | if(slot < 0) |
---|
5826 | { |
---|
5827 | ((Player*)unitTarget)->DurabilityPointsLossAll(damage,(slot < -1)); |
---|
5828 | return; |
---|
5829 | } |
---|
5830 | |
---|
5831 | // invalid slot value |
---|
5832 | if(slot >= INVENTORY_SLOT_BAG_END) |
---|
5833 | return; |
---|
5834 | |
---|
5835 | if(Item* item = ((Player*)unitTarget)->GetItemByPos(INVENTORY_SLOT_BAG_0,slot)) |
---|
5836 | ((Player*)unitTarget)->DurabilityPointsLoss(item,damage); |
---|
5837 | } |
---|
5838 | |
---|
5839 | void Spell::EffectDurabilityDamagePCT(uint32 i) |
---|
5840 | { |
---|
5841 | if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) |
---|
5842 | return; |
---|
5843 | |
---|
5844 | int32 slot = m_spellInfo->EffectMiscValue[i]; |
---|
5845 | |
---|
5846 | // FIXME: some spells effects have value -1/-2 |
---|
5847 | // Possibly its mean -1 all player equipped items and -2 all items |
---|
5848 | if(slot < 0) |
---|
5849 | { |
---|
5850 | ((Player*)unitTarget)->DurabilityLossAll(double(damage)/100.0f,(slot < -1)); |
---|
5851 | return; |
---|
5852 | } |
---|
5853 | |
---|
5854 | // invalid slot value |
---|
5855 | if(slot >= INVENTORY_SLOT_BAG_END) |
---|
5856 | return; |
---|
5857 | |
---|
5858 | if(damage <= 0) |
---|
5859 | return; |
---|
5860 | |
---|
5861 | if(Item* item = ((Player*)unitTarget)->GetItemByPos(INVENTORY_SLOT_BAG_0,slot)) |
---|
5862 | ((Player*)unitTarget)->DurabilityLoss(item,double(damage)/100.0f); |
---|
5863 | } |
---|
5864 | |
---|
5865 | void Spell::EffectModifyThreatPercent(uint32 /*effIndex*/) |
---|
5866 | { |
---|
5867 | if(!unitTarget) |
---|
5868 | return; |
---|
5869 | |
---|
5870 | unitTarget->getThreatManager().modifyThreatPercent(m_caster, damage); |
---|
5871 | } |
---|
5872 | |
---|
5873 | void Spell::EffectTransmitted(uint32 effIndex) |
---|
5874 | { |
---|
5875 | uint32 name_id = m_spellInfo->EffectMiscValue[effIndex]; |
---|
5876 | |
---|
5877 | GameObjectInfo const* goinfo = objmgr.GetGameObjectInfo(name_id); |
---|
5878 | |
---|
5879 | if (!goinfo) |
---|
5880 | { |
---|
5881 | sLog.outErrorDb("Gameobject (Entry: %u) not exist and not created at spell (ID: %u) cast",name_id, m_spellInfo->Id); |
---|
5882 | return; |
---|
5883 | } |
---|
5884 | |
---|
5885 | float fx,fy,fz; |
---|
5886 | |
---|
5887 | if(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION) |
---|
5888 | { |
---|
5889 | fx = m_targets.m_destX; |
---|
5890 | fy = m_targets.m_destY; |
---|
5891 | fz = m_targets.m_destZ; |
---|
5892 | } |
---|
5893 | //FIXME: this can be better check for most objects but still hack |
---|
5894 | else if(m_spellInfo->EffectRadiusIndex[effIndex] && m_spellInfo->speed==0) |
---|
5895 | { |
---|
5896 | float dis = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[effIndex])); |
---|
5897 | m_caster->GetClosePoint(fx,fy,fz,DEFAULT_WORLD_OBJECT_SIZE, dis); |
---|
5898 | } |
---|
5899 | else |
---|
5900 | { |
---|
5901 | float min_dis = GetSpellMinRange(sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex)); |
---|
5902 | float max_dis = GetSpellMaxRange(sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex)); |
---|
5903 | float dis = rand_norm() * (max_dis - min_dis) + min_dis; |
---|
5904 | |
---|
5905 | m_caster->GetClosePoint(fx,fy,fz,DEFAULT_WORLD_OBJECT_SIZE, dis); |
---|
5906 | } |
---|
5907 | |
---|
5908 | Map *cMap = m_caster->GetMap(); |
---|
5909 | |
---|
5910 | if(goinfo->type==GAMEOBJECT_TYPE_FISHINGNODE) |
---|
5911 | { |
---|
5912 | if ( !cMap->IsInWater(fx,fy,fz-0.5f)) // Hack to prevent fishing bobber from failing to land on fishing hole |
---|
5913 | { // but this is not proper, we really need to ignore not materialized objects |
---|
5914 | SendCastResult(SPELL_FAILED_NOT_HERE); |
---|
5915 | SendChannelUpdate(0); |
---|
5916 | return; |
---|
5917 | } |
---|
5918 | |
---|
5919 | // replace by water level in this case |
---|
5920 | fz = cMap->GetWaterLevel(fx,fy); |
---|
5921 | } |
---|
5922 | // if gameobject is summoning object, it should be spawned right on caster's position |
---|
5923 | else if(goinfo->type==GAMEOBJECT_TYPE_SUMMONING_RITUAL) |
---|
5924 | { |
---|
5925 | m_caster->GetPosition(fx,fy,fz); |
---|
5926 | } |
---|
5927 | |
---|
5928 | GameObject* pGameObj = new GameObject; |
---|
5929 | |
---|
5930 | if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), name_id, cMap, |
---|
5931 | fx, fy, fz, m_caster->GetOrientation(), 0, 0, 0, 0, 100, 1)) |
---|
5932 | { |
---|
5933 | delete pGameObj; |
---|
5934 | return; |
---|
5935 | } |
---|
5936 | |
---|
5937 | int32 duration = GetSpellDuration(m_spellInfo); |
---|
5938 | |
---|
5939 | switch(goinfo->type) |
---|
5940 | { |
---|
5941 | case GAMEOBJECT_TYPE_FISHINGNODE: |
---|
5942 | { |
---|
5943 | m_caster->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT,pGameObj->GetGUID()); |
---|
5944 | // Orientation3 |
---|
5945 | pGameObj->SetFloatValue(GAMEOBJECT_ROTATION + 2, 0.88431775569915771 ); |
---|
5946 | // Orientation4 |
---|
5947 | pGameObj->SetFloatValue(GAMEOBJECT_ROTATION + 3, -0.4668855369091033 ); |
---|
5948 | m_caster->AddGameObject(pGameObj); // will removed at spell cancel |
---|
5949 | |
---|
5950 | // end time of range when possible catch fish (FISHING_BOBBER_READY_TIME..GetDuration(m_spellInfo)) |
---|
5951 | // start time == fish-FISHING_BOBBER_READY_TIME (0..GetDuration(m_spellInfo)-FISHING_BOBBER_READY_TIME) |
---|
5952 | int32 lastSec; |
---|
5953 | switch(urand(0, 3)) |
---|
5954 | { |
---|
5955 | case 0: lastSec = 3; break; |
---|
5956 | case 1: lastSec = 7; break; |
---|
5957 | case 2: lastSec = 13; break; |
---|
5958 | case 3: lastSec = 17; break; |
---|
5959 | } |
---|
5960 | |
---|
5961 | duration = duration - lastSec*1000 + FISHING_BOBBER_READY_TIME*1000; |
---|
5962 | break; |
---|
5963 | } |
---|
5964 | case GAMEOBJECT_TYPE_SUMMONING_RITUAL: |
---|
5965 | { |
---|
5966 | if(m_caster->GetTypeId()==TYPEID_PLAYER) |
---|
5967 | { |
---|
5968 | pGameObj->AddUniqueUse((Player*)m_caster); |
---|
5969 | m_caster->AddGameObject(pGameObj); // will removed at spell cancel |
---|
5970 | } |
---|
5971 | break; |
---|
5972 | } |
---|
5973 | case GAMEOBJECT_TYPE_FISHINGHOLE: |
---|
5974 | case GAMEOBJECT_TYPE_CHEST: |
---|
5975 | default: |
---|
5976 | { |
---|
5977 | break; |
---|
5978 | } |
---|
5979 | } |
---|
5980 | |
---|
5981 | pGameObj->SetRespawnTime(duration > 0 ? duration/1000 : 0); |
---|
5982 | |
---|
5983 | pGameObj->SetOwnerGUID(m_caster->GetGUID() ); |
---|
5984 | |
---|
5985 | pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel() ); |
---|
5986 | pGameObj->SetSpellId(m_spellInfo->Id); |
---|
5987 | |
---|
5988 | DEBUG_LOG("AddObject at SpellEfects.cpp EffectTransmitted\n"); |
---|
5989 | //m_caster->AddGameObject(pGameObj); |
---|
5990 | //m_ObjToDel.push_back(pGameObj); |
---|
5991 | |
---|
5992 | cMap->Add(pGameObj); |
---|
5993 | |
---|
5994 | WorldPacket data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE, 8); |
---|
5995 | data << uint64(pGameObj->GetGUID()); |
---|
5996 | m_caster->SendMessageToSet(&data,true); |
---|
5997 | |
---|
5998 | if(uint32 linkedEntry = pGameObj->GetLinkedGameObjectEntry()) |
---|
5999 | { |
---|
6000 | GameObject* linkedGO = new GameObject; |
---|
6001 | if(linkedGO->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), linkedEntry, cMap, |
---|
6002 | fx, fy, fz, m_caster->GetOrientation(), 0, 0, 0, 0, 100, 1)) |
---|
6003 | { |
---|
6004 | linkedGO->SetRespawnTime(duration > 0 ? duration/1000 : 0); |
---|
6005 | linkedGO->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel() ); |
---|
6006 | linkedGO->SetSpellId(m_spellInfo->Id); |
---|
6007 | linkedGO->SetOwnerGUID(m_caster->GetGUID() ); |
---|
6008 | |
---|
6009 | MapManager::Instance().GetMap(linkedGO->GetMapId(), linkedGO)->Add(linkedGO); |
---|
6010 | } |
---|
6011 | else |
---|
6012 | { |
---|
6013 | delete linkedGO; |
---|
6014 | linkedGO = NULL; |
---|
6015 | return; |
---|
6016 | } |
---|
6017 | } |
---|
6018 | } |
---|
6019 | |
---|
6020 | void Spell::EffectProspecting(uint32 /*i*/) |
---|
6021 | { |
---|
6022 | if(m_caster->GetTypeId() != TYPEID_PLAYER) |
---|
6023 | return; |
---|
6024 | |
---|
6025 | Player* p_caster = (Player*)m_caster; |
---|
6026 | if(!itemTarget || !(itemTarget->GetProto()->BagFamily & BAG_FAMILY_MASK_MINING_SUPP)) |
---|
6027 | return; |
---|
6028 | |
---|
6029 | if(itemTarget->GetCount() < 5) |
---|
6030 | return; |
---|
6031 | |
---|
6032 | if( sWorld.getConfig(CONFIG_SKILL_PROSPECTING)) |
---|
6033 | { |
---|
6034 | uint32 SkillValue = p_caster->GetPureSkillValue(SKILL_JEWELCRAFTING); |
---|
6035 | uint32 reqSkillValue = itemTarget->GetProto()->RequiredSkillRank; |
---|
6036 | p_caster->UpdateGatherSkill(SKILL_JEWELCRAFTING, SkillValue, reqSkillValue); |
---|
6037 | } |
---|
6038 | |
---|
6039 | ((Player*)m_caster)->SendLoot(itemTarget->GetGUID(), LOOT_PROSPECTING); |
---|
6040 | } |
---|
6041 | |
---|
6042 | void Spell::EffectSkill(uint32 /*i*/) |
---|
6043 | { |
---|
6044 | sLog.outDebug("WORLD: SkillEFFECT"); |
---|
6045 | } |
---|
6046 | |
---|
6047 | void Spell::EffectSummonDemon(uint32 i) |
---|
6048 | { |
---|
6049 | float px = m_targets.m_destX; |
---|
6050 | float py = m_targets.m_destY; |
---|
6051 | float pz = m_targets.m_destZ; |
---|
6052 | |
---|
6053 | Creature* Charmed = m_caster->SummonCreature(m_spellInfo->EffectMiscValue[i], px, py, pz, m_caster->GetOrientation(),TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,3600000); |
---|
6054 | if (!Charmed) |
---|
6055 | return; |
---|
6056 | |
---|
6057 | // might not always work correctly, maybe the creature that dies from CoD casts the effect on itself and is therefore the caster? |
---|
6058 | Charmed->SetLevel(m_caster->getLevel()); |
---|
6059 | |
---|
6060 | // TODO: Add damage/mana/hp according to level |
---|
6061 | |
---|
6062 | if (m_spellInfo->EffectMiscValue[i] == 89) // Inferno summon |
---|
6063 | { |
---|
6064 | // Enslave demon effect, without mana cost and cooldown |
---|
6065 | m_caster->CastSpell(Charmed, 20882, true); // FIXME: enslave does not scale with level, level 62+ minions cannot be enslaved |
---|
6066 | |
---|
6067 | // Inferno effect |
---|
6068 | Charmed->CastSpell(Charmed, 22703, true, 0); |
---|
6069 | } |
---|
6070 | } |
---|
6071 | |
---|
6072 | /* There is currently no need for this effect. We handle it in BattleGround.cpp |
---|
6073 | If we would handle the resurrection here, the spiritguide would instantly disappear as the |
---|
6074 | player revives, and so we wouldn't see the spirit heal visual effect on the npc. |
---|
6075 | This is why we use a half sec delay between the visual effect and the resurrection itself */ |
---|
6076 | void Spell::EffectSpiritHeal(uint32 /*i*/) |
---|
6077 | { |
---|
6078 | /* |
---|
6079 | if(!unitTarget || unitTarget->isAlive()) |
---|
6080 | return; |
---|
6081 | if(unitTarget->GetTypeId() != TYPEID_PLAYER) |
---|
6082 | return; |
---|
6083 | if(!unitTarget->IsInWorld()) |
---|
6084 | return; |
---|
6085 | |
---|
6086 | //m_spellInfo->EffectBasePoints[i]; == 99 (percent?) |
---|
6087 | //((Player*)unitTarget)->setResurrect(m_caster->GetGUID(), unitTarget->GetPositionX(), unitTarget->GetPositionY(), unitTarget->GetPositionZ(), unitTarget->GetMaxHealth(), unitTarget->GetMaxPower(POWER_MANA)); |
---|
6088 | ((Player*)unitTarget)->ResurrectPlayer(1.0f); |
---|
6089 | ((Player*)unitTarget)->SpawnCorpseBones(); |
---|
6090 | */ |
---|
6091 | } |
---|
6092 | |
---|
6093 | // remove insignia spell effect |
---|
6094 | void Spell::EffectSkinPlayerCorpse(uint32 /*i*/) |
---|
6095 | { |
---|
6096 | sLog.outDebug("Effect: SkinPlayerCorpse"); |
---|
6097 | if ( (m_caster->GetTypeId() != TYPEID_PLAYER) || (unitTarget->GetTypeId() != TYPEID_PLAYER) || (unitTarget->isAlive()) ) |
---|
6098 | return; |
---|
6099 | |
---|
6100 | ((Player*)unitTarget)->RemovedInsignia( (Player*)m_caster ); |
---|
6101 | } |
---|
6102 | |
---|
6103 | void Spell::EffectStealBeneficialBuff(uint32 i) |
---|
6104 | { |
---|
6105 | sLog.outDebug("Effect: StealBeneficialBuff"); |
---|
6106 | |
---|
6107 | if(!unitTarget || unitTarget==m_caster) // can't steal from self |
---|
6108 | return; |
---|
6109 | |
---|
6110 | std::vector <Aura *> steal_list; |
---|
6111 | // Create dispel mask by dispel type |
---|
6112 | uint32 dispelMask = GetDispellMask( DispelType(m_spellInfo->EffectMiscValue[i]) ); |
---|
6113 | Unit::AuraMap const& auras = unitTarget->GetAuras(); |
---|
6114 | for(Unit::AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr) |
---|
6115 | { |
---|
6116 | Aura *aur = (*itr).second; |
---|
6117 | if (aur && (1<<aur->GetSpellProto()->Dispel) & dispelMask) |
---|
6118 | { |
---|
6119 | // Need check for passive? this |
---|
6120 | if (aur->IsPositive() && !aur->IsPassive()) |
---|
6121 | steal_list.push_back(aur); |
---|
6122 | } |
---|
6123 | } |
---|
6124 | // Ok if exist some buffs for dispel try dispel it |
---|
6125 | if (!steal_list.empty()) |
---|
6126 | { |
---|
6127 | std::list < std::pair<uint32,uint64> > success_list; |
---|
6128 | int32 list_size = steal_list.size(); |
---|
6129 | // Dispell N = damage buffs (or while exist buffs for dispel) |
---|
6130 | for (int32 count=0; count < damage && list_size > 0; ++count) |
---|
6131 | { |
---|
6132 | // Random select buff for dispel |
---|
6133 | Aura *aur = steal_list[urand(0, list_size-1)]; |
---|
6134 | // Not use chance for steal |
---|
6135 | // TODO possible need do it |
---|
6136 | success_list.push_back( std::pair<uint32,uint64>(aur->GetId(),aur->GetCasterGUID())); |
---|
6137 | |
---|
6138 | // Remove buff from list for prevent doubles |
---|
6139 | for (std::vector<Aura *>::iterator j = steal_list.begin(); j != steal_list.end(); ) |
---|
6140 | { |
---|
6141 | Aura *stealed = *j; |
---|
6142 | if (stealed->GetId() == aur->GetId() && stealed->GetCasterGUID() == aur->GetCasterGUID()) |
---|
6143 | { |
---|
6144 | j = steal_list.erase(j); |
---|
6145 | --list_size; |
---|
6146 | } |
---|
6147 | else |
---|
6148 | ++j; |
---|
6149 | } |
---|
6150 | } |
---|
6151 | // Really try steal and send log |
---|
6152 | if (!success_list.empty()) |
---|
6153 | { |
---|
6154 | int32 count = success_list.size(); |
---|
6155 | WorldPacket data(SMSG_SPELLSTEALLOG, 8+8+4+1+4+count*5); |
---|
6156 | data.append(unitTarget->GetPackGUID()); // Victim GUID |
---|
6157 | data.append(m_caster->GetPackGUID()); // Caster GUID |
---|
6158 | data << uint32(m_spellInfo->Id); // Dispell spell id |
---|
6159 | data << uint8(0); // not used |
---|
6160 | data << uint32(count); // count |
---|
6161 | for (std::list<std::pair<uint32,uint64> >::iterator j = success_list.begin(); j != success_list.end(); ++j) |
---|
6162 | { |
---|
6163 | SpellEntry const* spellInfo = sSpellStore.LookupEntry(j->first); |
---|
6164 | data << uint32(spellInfo->Id); // Spell Id |
---|
6165 | data << uint8(0); // 0 - steals !=0 transfers |
---|
6166 | unitTarget->RemoveAurasDueToSpellBySteal(spellInfo->Id, j->second, m_caster); |
---|
6167 | } |
---|
6168 | m_caster->SendMessageToSet(&data, true); |
---|
6169 | } |
---|
6170 | } |
---|
6171 | } |
---|
6172 | |
---|
6173 | void Spell::EffectKillCredit(uint32 i) |
---|
6174 | { |
---|
6175 | if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) |
---|
6176 | return; |
---|
6177 | |
---|
6178 | ((Player*)unitTarget)->KilledMonster(m_spellInfo->EffectMiscValue[i], 0); |
---|
6179 | } |
---|
6180 | |
---|
6181 | void Spell::EffectQuestFail(uint32 i) |
---|
6182 | { |
---|
6183 | if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) |
---|
6184 | return; |
---|
6185 | |
---|
6186 | ((Player*)unitTarget)->FailQuest(m_spellInfo->EffectMiscValue[i]); |
---|
6187 | } |
---|