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