2 * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 #include "SharedDefines.h"
21 #include "Database/DatabaseEnv.h"
22 #include "WorldPacket.h"
23 #include "WorldSession.h"
26 #include "UpdateMask.h"
28 #include "ObjectMgr.h"
31 #include "SkillExtraItems.h"
33 #include "CreatureAI.h"
35 #include "DynamicObject.h"
36 #include "SpellAuras.h"
38 #include "UpdateData.h"
39 #include "MapManager.h"
40 #include "ObjectAccessor.h"
41 #include "SharedDefines.h"
43 #include "GameObject.h"
44 #include "GossipDef.h"
47 #include "CreatureAI.h"
48 #include "BattleGround.h"
49 #include "BattleGroundEY.h"
50 #include "BattleGroundWS.h"
51 #include "VMapFactory.h"
53 #include "SocialMgr.h"
55 #include "TemporarySummon.h"
56 #include "ScriptCalls.h"
57 #include "SkillDiscovery.h"
59 pEffect SpellEffects
[TOTAL_SPELL_EFFECTS
]=
61 &Spell::EffectNULL
, // 0
62 &Spell::EffectInstaKill
, // 1 SPELL_EFFECT_INSTAKILL
63 &Spell::EffectSchoolDMG
, // 2 SPELL_EFFECT_SCHOOL_DAMAGE
64 &Spell::EffectDummy
, // 3 SPELL_EFFECT_DUMMY
65 &Spell::EffectUnused
, // 4 SPELL_EFFECT_PORTAL_TELEPORT unused
66 &Spell::EffectTeleportUnits
, // 5 SPELL_EFFECT_TELEPORT_UNITS
67 &Spell::EffectApplyAura
, // 6 SPELL_EFFECT_APPLY_AURA
68 &Spell::EffectEnvirinmentalDMG
, // 7 SPELL_EFFECT_ENVIRONMENTAL_DAMAGE
69 &Spell::EffectPowerDrain
, // 8 SPELL_EFFECT_POWER_DRAIN
70 &Spell::EffectHealthLeech
, // 9 SPELL_EFFECT_HEALTH_LEECH
71 &Spell::EffectHeal
, // 10 SPELL_EFFECT_HEAL
72 &Spell::EffectUnused
, // 11 SPELL_EFFECT_BIND
73 &Spell::EffectNULL
, // 12 SPELL_EFFECT_PORTAL
74 &Spell::EffectUnused
, // 13 SPELL_EFFECT_RITUAL_BASE unused
75 &Spell::EffectUnused
, // 14 SPELL_EFFECT_RITUAL_SPECIALIZE unused
76 &Spell::EffectUnused
, // 15 SPELL_EFFECT_RITUAL_ACTIVATE_PORTAL unused
77 &Spell::EffectQuestComplete
, // 16 SPELL_EFFECT_QUEST_COMPLETE
78 &Spell::EffectWeaponDmg
, // 17 SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL
79 &Spell::EffectResurrect
, // 18 SPELL_EFFECT_RESURRECT
80 &Spell::EffectAddExtraAttacks
, // 19 SPELL_EFFECT_ADD_EXTRA_ATTACKS
81 &Spell::EffectUnused
, // 20 SPELL_EFFECT_DODGE one spell: Dodge
82 &Spell::EffectUnused
, // 21 SPELL_EFFECT_EVADE one spell: Evade (DND)
83 &Spell::EffectParry
, // 22 SPELL_EFFECT_PARRY
84 &Spell::EffectBlock
, // 23 SPELL_EFFECT_BLOCK one spell: Block
85 &Spell::EffectCreateItem
, // 24 SPELL_EFFECT_CREATE_ITEM
86 &Spell::EffectUnused
, // 25 SPELL_EFFECT_WEAPON
87 &Spell::EffectUnused
, // 26 SPELL_EFFECT_DEFENSE one spell: Defense
88 &Spell::EffectPersistentAA
, // 27 SPELL_EFFECT_PERSISTENT_AREA_AURA
89 &Spell::EffectSummonType
, // 28 SPELL_EFFECT_SUMMON
90 &Spell::EffectMomentMove
, // 29 SPELL_EFFECT_LEAP
91 &Spell::EffectEnergize
, // 30 SPELL_EFFECT_ENERGIZE
92 &Spell::EffectWeaponDmg
, // 31 SPELL_EFFECT_WEAPON_PERCENT_DAMAGE
93 &Spell::EffectTriggerMissileSpell
, // 32 SPELL_EFFECT_TRIGGER_MISSILE
94 &Spell::EffectOpenLock
, // 33 SPELL_EFFECT_OPEN_LOCK
95 &Spell::EffectSummonChangeItem
, // 34 SPELL_EFFECT_SUMMON_CHANGE_ITEM
96 &Spell::EffectApplyAreaAura
, // 35 SPELL_EFFECT_APPLY_AREA_AURA_PARTY
97 &Spell::EffectLearnSpell
, // 36 SPELL_EFFECT_LEARN_SPELL
98 &Spell::EffectUnused
, // 37 SPELL_EFFECT_SPELL_DEFENSE one spell: SPELLDEFENSE (DND)
99 &Spell::EffectDispel
, // 38 SPELL_EFFECT_DISPEL
100 &Spell::EffectUnused
, // 39 SPELL_EFFECT_LANGUAGE
101 &Spell::EffectDualWield
, // 40 SPELL_EFFECT_DUAL_WIELD
102 &Spell::EffectUnused
, // 41 SPELL_EFFECT_JUMP
103 &Spell::EffectUnused
, // 42 SPELL_EFFECT_JUMP2
104 &Spell::EffectTeleUnitsFaceCaster
, // 43 SPELL_EFFECT_TELEPORT_UNITS_FACE_CASTER
105 &Spell::EffectLearnSkill
, // 44 SPELL_EFFECT_SKILL_STEP
106 &Spell::EffectAddHonor
, // 45 SPELL_EFFECT_ADD_HONOR honor/pvp related
107 &Spell::EffectNULL
, // 46 SPELL_EFFECT_SPAWN we must spawn pet there
108 &Spell::EffectTradeSkill
, // 47 SPELL_EFFECT_TRADE_SKILL
109 &Spell::EffectUnused
, // 48 SPELL_EFFECT_STEALTH one spell: Base Stealth
110 &Spell::EffectUnused
, // 49 SPELL_EFFECT_DETECT one spell: Detect
111 &Spell::EffectTransmitted
, // 50 SPELL_EFFECT_TRANS_DOOR
112 &Spell::EffectUnused
, // 51 SPELL_EFFECT_FORCE_CRITICAL_HIT unused
113 &Spell::EffectUnused
, // 52 SPELL_EFFECT_GUARANTEE_HIT one spell: zzOLDCritical Shot
114 &Spell::EffectEnchantItemPerm
, // 53 SPELL_EFFECT_ENCHANT_ITEM
115 &Spell::EffectEnchantItemTmp
, // 54 SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY
116 &Spell::EffectTameCreature
, // 55 SPELL_EFFECT_TAMECREATURE
117 &Spell::EffectSummonPet
, // 56 SPELL_EFFECT_SUMMON_PET
118 &Spell::EffectLearnPetSpell
, // 57 SPELL_EFFECT_LEARN_PET_SPELL
119 &Spell::EffectWeaponDmg
, // 58 SPELL_EFFECT_WEAPON_DAMAGE
120 &Spell::EffectOpenSecretSafe
, // 59 SPELL_EFFECT_OPEN_LOCK_ITEM
121 &Spell::EffectProficiency
, // 60 SPELL_EFFECT_PROFICIENCY
122 &Spell::EffectSendEvent
, // 61 SPELL_EFFECT_SEND_EVENT
123 &Spell::EffectPowerBurn
, // 62 SPELL_EFFECT_POWER_BURN
124 &Spell::EffectThreat
, // 63 SPELL_EFFECT_THREAT
125 &Spell::EffectTriggerSpell
, // 64 SPELL_EFFECT_TRIGGER_SPELL
126 &Spell::EffectApplyAreaAura
, // 65 SPELL_EFFECT_APPLY_AREA_AURA_RAID
127 &Spell::EffectUnused
, // 66 SPELL_EFFECT_CREATE_MANA_GEM (possibly recharge it, misc - is item ID)
128 &Spell::EffectHealMaxHealth
, // 67 SPELL_EFFECT_HEAL_MAX_HEALTH
129 &Spell::EffectInterruptCast
, // 68 SPELL_EFFECT_INTERRUPT_CAST
130 &Spell::EffectDistract
, // 69 SPELL_EFFECT_DISTRACT
131 &Spell::EffectPull
, // 70 SPELL_EFFECT_PULL one spell: Distract Move
132 &Spell::EffectPickPocket
, // 71 SPELL_EFFECT_PICKPOCKET
133 &Spell::EffectAddFarsight
, // 72 SPELL_EFFECT_ADD_FARSIGHT
134 &Spell::EffectUnused
, // 73 SPELL_EFFECT_UNTRAIN_TALENTS
135 &Spell::EffectApplyGlyph
, // 74 SPELL_EFFECT_APPLY_GLYPH
136 &Spell::EffectHealMechanical
, // 75 SPELL_EFFECT_HEAL_MECHANICAL one spell: Mechanical Patch Kit
137 &Spell::EffectSummonObjectWild
, // 76 SPELL_EFFECT_SUMMON_OBJECT_WILD
138 &Spell::EffectScriptEffect
, // 77 SPELL_EFFECT_SCRIPT_EFFECT
139 &Spell::EffectUnused
, // 78 SPELL_EFFECT_ATTACK
140 &Spell::EffectSanctuary
, // 79 SPELL_EFFECT_SANCTUARY
141 &Spell::EffectAddComboPoints
, // 80 SPELL_EFFECT_ADD_COMBO_POINTS
142 &Spell::EffectUnused
, // 81 SPELL_EFFECT_CREATE_HOUSE one spell: Create House (TEST)
143 &Spell::EffectNULL
, // 82 SPELL_EFFECT_BIND_SIGHT
144 &Spell::EffectDuel
, // 83 SPELL_EFFECT_DUEL
145 &Spell::EffectStuck
, // 84 SPELL_EFFECT_STUCK
146 &Spell::EffectSummonPlayer
, // 85 SPELL_EFFECT_SUMMON_PLAYER
147 &Spell::EffectActivateObject
, // 86 SPELL_EFFECT_ACTIVATE_OBJECT
148 &Spell::EffectUnused
, // 87 SPELL_EFFECT_WMO_DAMAGE
149 &Spell::EffectUnused
, // 88 SPELL_EFFECT_WMO_REPAIR
150 &Spell::EffectUnused
, // 89 SPELL_EFFECT_WMO_CHANGE
151 &Spell::EffectUnused
, // 90 SPELL_EFFECT_KILL_CREDIT
152 &Spell::EffectUnused
, // 91 SPELL_EFFECT_THREAT_ALL one spell: zzOLDBrainwash
153 &Spell::EffectEnchantHeldItem
, // 92 SPELL_EFFECT_ENCHANT_HELD_ITEM
154 &Spell::EffectUnused
, // 93 SPELL_EFFECT_SUMMON_PHANTASM
155 &Spell::EffectSelfResurrect
, // 94 SPELL_EFFECT_SELF_RESURRECT
156 &Spell::EffectSkinning
, // 95 SPELL_EFFECT_SKINNING
157 &Spell::EffectCharge
, // 96 SPELL_EFFECT_CHARGE
158 &Spell::EffectUnused
, // 97 SPELL_EFFECT_97
159 &Spell::EffectKnockBack
, // 98 SPELL_EFFECT_KNOCK_BACK
160 &Spell::EffectDisEnchant
, // 99 SPELL_EFFECT_DISENCHANT
161 &Spell::EffectInebriate
, //100 SPELL_EFFECT_INEBRIATE
162 &Spell::EffectFeedPet
, //101 SPELL_EFFECT_FEED_PET
163 &Spell::EffectDismissPet
, //102 SPELL_EFFECT_DISMISS_PET
164 &Spell::EffectReputation
, //103 SPELL_EFFECT_REPUTATION
165 &Spell::EffectSummonObject
, //104 SPELL_EFFECT_SUMMON_OBJECT_SLOT1
166 &Spell::EffectSummonObject
, //105 SPELL_EFFECT_SUMMON_OBJECT_SLOT2
167 &Spell::EffectSummonObject
, //106 SPELL_EFFECT_SUMMON_OBJECT_SLOT3
168 &Spell::EffectSummonObject
, //107 SPELL_EFFECT_SUMMON_OBJECT_SLOT4
169 &Spell::EffectDispelMechanic
, //108 SPELL_EFFECT_DISPEL_MECHANIC
170 &Spell::EffectSummonDeadPet
, //109 SPELL_EFFECT_SUMMON_DEAD_PET
171 &Spell::EffectDestroyAllTotems
, //110 SPELL_EFFECT_DESTROY_ALL_TOTEMS
172 &Spell::EffectDurabilityDamage
, //111 SPELL_EFFECT_DURABILITY_DAMAGE
173 &Spell::EffectUnused
, //112 SPELL_EFFECT_112
174 &Spell::EffectResurrectNew
, //113 SPELL_EFFECT_RESURRECT_NEW
175 &Spell::EffectTaunt
, //114 SPELL_EFFECT_ATTACK_ME
176 &Spell::EffectDurabilityDamagePCT
, //115 SPELL_EFFECT_DURABILITY_DAMAGE_PCT
177 &Spell::EffectSkinPlayerCorpse
, //116 SPELL_EFFECT_SKIN_PLAYER_CORPSE one spell: Remove Insignia, bg usage, required special corpse flags...
178 &Spell::EffectSpiritHeal
, //117 SPELL_EFFECT_SPIRIT_HEAL one spell: Spirit Heal
179 &Spell::EffectSkill
, //118 SPELL_EFFECT_SKILL professions and more
180 &Spell::EffectApplyAreaAura
, //119 SPELL_EFFECT_APPLY_AREA_AURA_PET
181 &Spell::EffectUnused
, //120 SPELL_EFFECT_TELEPORT_GRAVEYARD one spell: Graveyard Teleport Test
182 &Spell::EffectWeaponDmg
, //121 SPELL_EFFECT_NORMALIZED_WEAPON_DMG
183 &Spell::EffectUnused
, //122 SPELL_EFFECT_122 unused
184 &Spell::EffectSendTaxi
, //123 SPELL_EFFECT_SEND_TAXI taxi/flight related (misc value is taxi path id)
185 &Spell::EffectPlayerPull
, //124 SPELL_EFFECT_PLAYER_PULL opposite of knockback effect (pulls player twoard caster)
186 &Spell::EffectModifyThreatPercent
, //125 SPELL_EFFECT_MODIFY_THREAT_PERCENT
187 &Spell::EffectStealBeneficialBuff
, //126 SPELL_EFFECT_STEAL_BENEFICIAL_BUFF spell steal effect?
188 &Spell::EffectProspecting
, //127 SPELL_EFFECT_PROSPECTING Prospecting spell
189 &Spell::EffectApplyAreaAura
, //128 SPELL_EFFECT_APPLY_AREA_AURA_FRIEND
190 &Spell::EffectApplyAreaAura
, //129 SPELL_EFFECT_APPLY_AREA_AURA_ENEMY
191 &Spell::EffectNULL
, //130 SPELL_EFFECT_REDIRECT_THREAT
192 &Spell::EffectUnused
, //131 SPELL_EFFECT_131 used in some test spells
193 &Spell::EffectNULL
, //132 SPELL_EFFECT_PLAY_MUSIC sound id in misc value (SoundEntries.dbc)
194 &Spell::EffectUnlearnSpecialization
, //133 SPELL_EFFECT_UNLEARN_SPECIALIZATION unlearn profession specialization
195 &Spell::EffectKillCredit
, //134 SPELL_EFFECT_KILL_CREDIT misc value is creature entry
196 &Spell::EffectNULL
, //135 SPELL_EFFECT_CALL_PET
197 &Spell::EffectHealPct
, //136 SPELL_EFFECT_HEAL_PCT
198 &Spell::EffectEnergisePct
, //137 SPELL_EFFECT_ENERGIZE_PCT
199 &Spell::EffectNULL
, //138 SPELL_EFFECT_138 Leap
200 &Spell::EffectUnused
, //139 SPELL_EFFECT_CLEAR_QUEST (misc - is quest ID)
201 &Spell::EffectForceCast
, //140 SPELL_EFFECT_FORCE_CAST
202 &Spell::EffectNULL
, //141 SPELL_EFFECT_141 damage and reduce speed?
203 &Spell::EffectTriggerSpellWithValue
, //142 SPELL_EFFECT_TRIGGER_SPELL_WITH_VALUE
204 &Spell::EffectApplyAreaAura
, //143 SPELL_EFFECT_APPLY_AREA_AURA_OWNER
205 &Spell::EffectNULL
, //144 SPELL_EFFECT_144 Spectral Blast
206 &Spell::EffectNULL
, //145 SPELL_EFFECT_145 Black Hole Effect
207 &Spell::EffectActivateRune
, //146 SPELL_EFFECT_ACTIVATE_RUNE
208 &Spell::EffectQuestFail
, //147 SPELL_EFFECT_QUEST_FAIL quest fail
209 &Spell::EffectUnused
, //148 SPELL_EFFECT_148 unused
210 &Spell::EffectNULL
, //149 SPELL_EFFECT_149 swoop
211 &Spell::EffectUnused
, //150 SPELL_EFFECT_150 unused
212 &Spell::EffectTriggerRitualOfSummoning
, //151 SPELL_EFFECT_TRIGGER_SPELL_2
213 &Spell::EffectNULL
, //152 SPELL_EFFECT_152 summon Refer-a-Friend
214 &Spell::EffectNULL
, //153 SPELL_EFFECT_CREATE_PET misc value is creature entry
215 &Spell::EffectNULL
, //154 unused
216 &Spell::EffectTitanGrip
, //155 SPELL_EFFECT_TITAN_GRIP Allows you to equip two-handed axes, maces and swords in one hand, but you attack $49152s1% slower than normal.
217 &Spell::EffectEnchantItemPrismatic
, //156 SPELL_EFFECT_ENCHANT_ITEM_PRISMATIC
218 &Spell::EffectCreateItem2
, //157 SPELL_EFFECT_CREATE_ITEM_2 create/learn item/spell for profession
219 &Spell::EffectMilling
, //158 SPELL_EFFECT_MILLING milling
220 &Spell::EffectRenamePet
//159 SPELL_EFFECT_ALLOW_RENAME_PET allow rename pet once again
223 void Spell::EffectNULL(uint32
/*i*/)
225 sLog
.outDebug("WORLD: Spell Effect DUMMY");
228 void Spell::EffectUnused(uint32
/*i*/)
230 // NOT USED BY ANY SPELL OR USELESS OR IMPLEMENTED IN DIFFERENT WAY IN MANGOS
233 void Spell::EffectResurrectNew(uint32 i
)
235 if(!unitTarget
|| unitTarget
->isAlive())
238 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
241 if(!unitTarget
->IsInWorld())
244 Player
* pTarget
= ((Player
*)unitTarget
);
246 if(pTarget
->isRessurectRequested()) // already have one active request
249 uint32 health
= damage
;
250 uint32 mana
= m_spellInfo
->EffectMiscValue
[i
];
251 pTarget
->setResurrectRequestData(m_caster
->GetGUID(), m_caster
->GetMapId(), m_caster
->GetPositionX(), m_caster
->GetPositionY(), m_caster
->GetPositionZ(), health
, mana
);
252 SendResurrectRequest(pTarget
);
255 void Spell::EffectInstaKill(uint32
/*i*/)
257 if( !unitTarget
|| !unitTarget
->isAlive() )
261 if(m_spellInfo
->Id
==18788 && unitTarget
->GetTypeId()==TYPEID_UNIT
)
263 uint32 entry
= unitTarget
->GetEntry();
267 case 416: spellID
=18789; break; //imp
268 case 417: spellID
=18792; break; //fellhunter
269 case 1860: spellID
=18790; break; //void
270 case 1863: spellID
=18791; break; //succubus
271 case 17252: spellID
=35701; break; //fellguard
273 sLog
.outError("EffectInstaKill: Unhandled creature entry (%u) case.",entry
);
277 m_caster
->CastSpell(m_caster
,spellID
,true);
280 if(m_caster
==unitTarget
) // prevent interrupt message
283 uint32 health
= unitTarget
->GetHealth();
284 m_caster
->DealDamage(unitTarget
, health
, NULL
, DIRECT_DAMAGE
, SPELL_SCHOOL_MASK_NORMAL
, NULL
, false);
287 void Spell::EffectEnvirinmentalDMG(uint32 i
)
292 // Note: this hack with damage replace required until GO casting not implemented
293 // environment damage spells already have around enemies targeting but this not help in case not existed GO casting support
294 // currently each enemy selected explicitly and self cast damage, we prevent apply self casted spell bonuses/etc
295 damage
= m_spellInfo
->EffectBasePoints
[i
]+m_spellInfo
->EffectBaseDice
[i
];
297 m_caster
->CalcAbsorbResist(m_caster
,GetSpellSchoolMask(m_spellInfo
), SPELL_DIRECT_DAMAGE
, damage
, &absorb
, &resist
);
299 m_caster
->SendSpellNonMeleeDamageLog(m_caster
, m_spellInfo
->Id
, damage
, GetSpellSchoolMask(m_spellInfo
), absorb
, resist
, false, 0, false);
300 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
301 ((Player
*)m_caster
)->EnvironmentalDamage(m_caster
->GetGUID(),DAMAGE_FIRE
,damage
);
304 void Spell::EffectSchoolDMG(uint32 effect_idx
)
306 if( unitTarget
&& unitTarget
->isAlive())
308 switch(m_spellInfo
->SpellFamilyName
)
310 case SPELLFAMILY_GENERIC
:
313 if(m_spellInfo
->SpellIconID
== 2269 )
315 damage
+= rand()%2 ? damage
: 0;
318 switch(m_spellInfo
->Id
) // better way to check unknown
320 // Meteor like spells (divided damage to targets)
321 case 24340: case 26558: case 28884: // Meteor
322 case 36837: case 38903: case 41276: // Meteor
323 case 26789: // Shard of the Fallen Star
324 case 31436: // Malevolent Cleave
325 case 35181: // Dive Bomb
326 case 40810: case 43267: case 43268: // Saber Lash
327 case 42384: // Brutal Swipe
328 case 45150: // Meteor Slash
331 for(std::list
<TargetInfo
>::iterator ihit
= m_UniqueTargetInfo
.begin();ihit
!= m_UniqueTargetInfo
.end();++ihit
)
332 if(ihit
->effectMask
& (1<<effect_idx
))
335 damage
/= count
; // divide to all targets
338 // percent from health with min
339 case 25599: // Thundercrash
341 damage
= unitTarget
->GetHealth() / 2;
346 // Intercept (warrior spell trigger)
350 damage
+= uint32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
) * 0.12f
);
357 case SPELLFAMILY_MAGE
:
360 if(m_spellInfo
->SpellFamilyFlags
& 0x20000000LL
)
362 m_caster
->CastSpell(m_caster
,36032,true);
366 case SPELLFAMILY_WARRIOR
:
369 if(m_spellInfo
->SpellFamilyFlags
& 0x40000000000LL
)
371 damage
= uint32(damage
* (m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
)) / 100);
374 else if(m_spellInfo
->SpellFamilyFlags
& 0x100000000LL
)
375 damage
+= int32(m_caster
->GetShieldBlockValue());
377 else if(m_spellInfo
->SpellFamilyFlags
& 0x10000000000LL
)
379 damage
= uint32(damage
* m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
) / 100);
380 m_caster
->ModifyAuraState(AURA_STATE_WARRIOR_VICTORY_RUSH
, false);
382 // Revenge ${$m1+$AP*0.207} to ${$M1+$AP*0.207}
383 else if(m_spellInfo
->SpellFamilyFlags
& 0x0000000000000400LL
)
384 damage
+= uint32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
) * 0.207f
);
385 // Heroic Throw ${$m1+$AP*.50}
386 else if(m_spellInfo
->SpellFamilyFlags
& 0x0000000100000000LL
)
387 damage
+= uint32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
) * 0.5f
);
388 // Shockwave ${$m3/100*$AP}
389 else if(m_spellInfo
->SpellFamilyFlags
& 0x0000800000000000LL
)
391 int32 pct
= m_caster
->CalculateSpellDamage(m_spellInfo
, 2, m_spellInfo
->EffectBasePoints
[2], unitTarget
);
393 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
) * pct
/ 100);
398 case SPELLFAMILY_WARLOCK
:
400 // Incinerate Rank 1 & 2
401 if((m_spellInfo
->SpellFamilyFlags
& 0x00004000000000LL
) && m_spellInfo
->SpellIconID
==2128)
403 // Incinerate does more dmg (dmg*0.25) if the target is Immolated.
404 if(unitTarget
->HasAuraState(AURA_STATE_IMMOLATE
))
405 damage
+= int32(damage
*0.25f
);
409 case SPELLFAMILY_PRIEST
:
411 // Shadow Word: Death - deals damage equal to damage done to caster
412 if (m_spellInfo
->SpellFamilyFlags
& 0x0000000200000000LL
)
413 m_caster
->CastCustomSpell(m_caster
, 32409, &damage
, 0, 0, true);
416 case SPELLFAMILY_DRUID
:
419 if(m_caster
->GetTypeId()==TYPEID_PLAYER
&& (m_spellInfo
->SpellFamilyFlags
& 0x000800000) && m_spellInfo
->SpellVisual
[0]==6587)
421 // converts each extra point of energy into ($f1+$AP/410) additional damage
422 float ap
= m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
);
423 float multiple
= ap
/ 410 + m_spellInfo
->DmgMultiplier
[effect_idx
];
424 damage
+= int32(m_caster
->GetPower(POWER_ENERGY
) * multiple
);
425 damage
+= int32(((Player
*)m_caster
)->GetComboPoints() * ap
* 7 / 100);
426 m_caster
->SetPower(POWER_ENERGY
,0);
429 else if(m_spellInfo
->SpellFamilyFlags
& 0x0000000000001000LL
)
431 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
) / 100);
434 else if(m_spellInfo
->SpellFamilyFlags
& 0x0010000000000000LL
)
436 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
)*0.08f
);
438 //Mangle Bonus for the initial damage of Lacerate and Rake
439 if((m_spellInfo
->SpellFamilyFlags
==0x0000000000001000LL
&& m_spellInfo
->SpellIconID
==494) ||
440 (m_spellInfo
->SpellFamilyFlags
==0x0000010000000000LL
&& m_spellInfo
->SpellIconID
==2246))
442 Unit::AuraList
const& mDummyAuras
= unitTarget
->GetAurasByType(SPELL_AURA_DUMMY
);
443 for(Unit::AuraList::const_iterator i
= mDummyAuras
.begin(); i
!= mDummyAuras
.end(); ++i
)
444 if((*i
)->GetSpellProto()->SpellFamilyFlags
& 0x0000044000000000LL
&& (*i
)->GetSpellProto()->SpellFamilyName
==SPELLFAMILY_DRUID
)
446 damage
= int32(damage
*(100.0f
+(*i
)->GetModifier()->m_amount
)/100.0f
);
452 case SPELLFAMILY_ROGUE
:
455 if(m_caster
->GetTypeId()==TYPEID_PLAYER
&& (m_spellInfo
->SpellFamilyFlags
& 0x800000000LL
))
457 // consume from stack dozes not more that have combo-points
458 if(uint32 combo
= ((Player
*)m_caster
)->GetComboPoints())
461 // Lookup for Deadly poison (only attacker applied)
462 Unit::AuraList
const& auras
= unitTarget
->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE
);
463 for(Unit::AuraList::const_iterator itr
= auras
.begin(); itr
!=auras
.end(); ++itr
)
464 if( (*itr
)->GetSpellProto()->SpellFamilyName
==SPELLFAMILY_ROGUE
&&
465 (*itr
)->GetSpellProto()->SpellFamilyFlags
& 0x10000 &&
466 (*itr
)->GetCasterGUID()==m_caster
->GetGUID() )
471 // count consumed deadly poison doses at target
474 uint32 spellId
= poison
->GetId();
475 uint32 doses
= poison
->GetStackAmount();
478 for (int i
=0; i
< doses
; i
++)
479 unitTarget
->RemoveSingleSpellAurasFromStack(spellId
);
481 damage
+= int32(((Player
*)m_caster
)->GetTotalAttackPowerValue(BASE_ATTACK
) * 0.03f
* doses
);
483 // Eviscerate and Envenom Bonus Damage (item set effect)
484 if(m_caster
->GetDummyAura(37169))
485 damage
+= ((Player
*)m_caster
)->GetComboPoints()*40;
489 else if((m_spellInfo
->SpellFamilyFlags
& 0x00020000LL
) && m_caster
->GetTypeId()==TYPEID_PLAYER
)
491 if(uint32 combo
= ((Player
*)m_caster
)->GetComboPoints())
493 float ap
= m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
);
494 damage
+= irand(int32(ap
* combo
* 0.03f
), int32(ap
* combo
* 0.07f
));
496 // Eviscerate and Envenom Bonus Damage (item set effect)
497 if(m_caster
->GetDummyAura(37169))
502 else if(m_spellInfo
->SpellFamilyFlags
& 0x0000000000000008LL
)
504 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
)*0.02f
);
507 else if(m_spellInfo
->SpellFamilyFlags
& 0x0000000000002000LL
)
509 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
)*0.10f
);
512 else if(m_spellInfo
->SpellFamilyFlags
& 0x0000000010000000LL
)
514 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
)*0.04f
);
518 case SPELLFAMILY_HUNTER
:
521 if((m_spellInfo
->SpellFamilyFlags
& 0x000000002) && m_spellInfo
->SpellVisual
[0]==342)
523 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
)*0.2f
);
526 else if(m_spellInfo
->SpellFamilyFlags
& 0x0008000000000000LL
)
528 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
)*0.2f
);
531 else if((m_spellInfo
->SpellFamilyFlags
& 0x00000800) && m_spellInfo
->maxLevel
> 0)
533 damage
+= int32(m_caster
->GetTotalAttackPowerValue(RANGED_ATTACK
)*0.15f
);
536 else if(m_spellInfo
->SpellFamilyFlags
& 0x100000000LL
)
538 int32 base
= irand((int32
)m_caster
->GetWeaponDamageRange(RANGED_ATTACK
, MINDAMAGE
),(int32
)m_caster
->GetWeaponDamageRange(RANGED_ATTACK
, MAXDAMAGE
));
539 damage
+= int32(float(base
)/m_caster
->GetAttackTime(RANGED_ATTACK
)*2800 + m_caster
->GetTotalAttackPowerValue(RANGED_ATTACK
)*0.2f
);
541 // Explosive Trap Effect
542 else if(m_spellInfo
->SpellFamilyFlags
& 0x00000004)
544 damage
+= int32(m_caster
->GetTotalAttackPowerValue(RANGED_ATTACK
)*0.1f
);
548 case SPELLFAMILY_PALADIN
:
550 // Judgement of Vengeance ${1+0.22*$SPH+0.14*$AP} + 10% for each application of Holy Vengeance on the target
551 if((m_spellInfo
->SpellFamilyFlags
& 0x800000000LL
) && m_spellInfo
->SpellIconID
==2292)
553 float ap
= m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
);
554 int32 holy
= m_caster
->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo
)) +
555 m_caster
->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo
), unitTarget
);
556 damage
+=int32(ap
* 0.14f
) + int32(holy
* 22 / 100);
557 // Get stack of Holy Vengeance on the target added by caster
559 Unit::AuraList
const& auras
= unitTarget
->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE
);
560 for(Unit::AuraList::const_iterator itr
= auras
.begin(); itr
!=auras
.end(); ++itr
)
561 if((*itr
)->GetId() == 31803 && (*itr
)->GetCasterGUID()==m_caster
->GetGUID())
563 stacks
= (*itr
)->GetStackAmount();
566 // + 10% for each application of Holy Vengeance on the target
568 damage
+= damage
* stacks
* 10 /100;
570 // Avenger's Shield ($m1+0.07*$SPH+0.07*$AP) - ranged sdb for future
571 else if(m_spellInfo
->SpellFamilyFlags
& 0x0000000000004000LL
)
573 float ap
= m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
);
574 int32 holy
= m_caster
->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo
)) +
575 m_caster
->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo
), unitTarget
);
576 damage
+= int32(ap
* 0.07f
) + int32(holy
* 7 / 100);
578 // Hammer of Wrath ($m1+0.15*$SPH+0.15*$AP) - ranged type sdb future fix
579 else if(m_spellInfo
->SpellFamilyFlags
& 0x0000008000000000LL
)
581 float ap
= m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
);
582 int32 holy
= m_caster
->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo
)) +
583 m_caster
->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo
), unitTarget
);
584 damage
+= int32(ap
* 0.15f
) + int32(holy
* 15 / 100);
586 // Hammer of the Righteous
587 else if(m_spellInfo
->SpellFamilyFlags
&0x0004000000000000LL
)
589 // Add main hand dps * effect[2] amount
590 float averange
= (m_caster
->GetFloatValue(UNIT_FIELD_MINDAMAGE
) + m_caster
->GetFloatValue(UNIT_FIELD_MAXDAMAGE
)) / 2;
591 int32 count
= m_caster
->CalculateSpellDamage(m_spellInfo
, 2, m_spellInfo
->EffectBasePoints
[2], unitTarget
);
592 damage
+= count
* int32(averange
* 1000) / m_caster
->GetAttackTime(BASE_ATTACK
);
603 void Spell::EffectDummy(uint32 i
)
605 if(!unitTarget
&& !gameObjTarget
&& !itemTarget
)
608 // selection by spell family
609 switch(m_spellInfo
->SpellFamilyName
)
611 case SPELLFAMILY_GENERIC
:
613 switch(m_spellInfo
->Id
)
615 case 8063: // Deviate Fish
617 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
623 case 1: spell_id
= 8064; break; // Sleepy
624 case 2: spell_id
= 8065; break; // Invigorate
625 case 3: spell_id
= 8066; break; // Shrink
626 case 4: spell_id
= 8067; break; // Party Time!
627 case 5: spell_id
= 8068; break; // Healthy Spirit
629 m_caster
->CastSpell(m_caster
,spell_id
,true,NULL
);
632 case 8213: // Savory Deviate Delight
634 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
641 case 1: spell_id
= (m_caster
->getGender() == GENDER_MALE
? 8219 : 8220); break;
643 case 2: spell_id
= (m_caster
->getGender() == GENDER_MALE
? 8221 : 8222); break;
645 m_caster
->CastSpell(m_caster
,spell_id
,true,NULL
);
648 case 8593: // Symbol of life (restore creature to life)
649 case 31225: // Shimmering Vessel (restore creature to life)
651 if(!unitTarget
|| unitTarget
->GetTypeId()!=TYPEID_UNIT
)
653 ((Creature
*)unitTarget
)->setDeathState(JUST_ALIVED
);
656 case 12162: // Deep wounds
657 case 12850: // (now good common check for this spells)
664 // DW should benefit of attack power, damage percent mods etc.
665 // TODO: check if using offhand damage is correct and if it should be divided by 2
666 if (m_caster
->haveOffhandWeapon() && m_caster
->getAttackTimer(BASE_ATTACK
) > m_caster
->getAttackTimer(OFF_ATTACK
))
667 damage
= (m_caster
->GetFloatValue(UNIT_FIELD_MINOFFHANDDAMAGE
) + m_caster
->GetFloatValue(UNIT_FIELD_MAXOFFHANDDAMAGE
))/2;
669 damage
= (m_caster
->GetFloatValue(UNIT_FIELD_MINDAMAGE
) + m_caster
->GetFloatValue(UNIT_FIELD_MAXDAMAGE
))/2;
671 switch (m_spellInfo
->Id
)
673 case 12850: damage
*= 0.2f
; break;
674 case 12162: damage
*= 0.4f
; break;
675 case 12868: damage
*= 0.6f
; break;
677 sLog
.outError("Spell::EffectDummy: Spell %u not handled in DW",m_spellInfo
->Id
);
681 int32 deepWoundsDotBasePoints0
= int32(damage
/ 4);
682 m_caster
->CastCustomSpell(unitTarget
, 12721, &deepWoundsDotBasePoints0
, NULL
, NULL
, true, NULL
);
685 case 13120: // net-o-matic
692 uint32 roll
= urand(0, 99);
694 if(roll
< 2) // 2% for 30 sec self root (off-like chance unknown)
696 else if(roll
< 4) // 2% for 20 sec root, charge to target (off-like chance unknown)
701 m_caster
->CastSpell(unitTarget
,spell_id
,true,NULL
);
704 case 13567: // Dummy Trigger
706 // can be used for different aura triggering, so select by aura
707 if(!m_triggeredByAuraSpell
|| !unitTarget
)
710 switch(m_triggeredByAuraSpell
->Id
)
712 case 26467: // Persistent Shield
713 m_caster
->CastCustomSpell(unitTarget
, 26470, &damage
, NULL
, NULL
, true);
716 sLog
.outError("EffectDummy: Non-handled case for spell 13567 for triggered aura %u",m_triggeredByAuraSpell
->Id
);
721 case 15998: // Capture Worg Pup
722 case 29435: // Capture Female Kaliri Hatchling
724 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_UNIT
)
727 Creature
* creatureTarget
= (Creature
*)unitTarget
;
728 creatureTarget
->setDeathState(JUST_DIED
);
729 creatureTarget
->RemoveCorpse();
730 creatureTarget
->SetHealth(0); // just for nice GM-mode view
733 case 16589: // Noggenfogger Elixir
735 if(m_caster
->GetTypeId()!=TYPEID_PLAYER
)
741 case 1: spell_id
= 16595; break;
742 case 2: spell_id
= 16593; break;
743 default:spell_id
= 16591; break;
746 m_caster
->CastSpell(m_caster
,spell_id
,true,NULL
);
749 case 17251: // Spirit Healer Res
751 if(!unitTarget
|| !m_originalCaster
)
754 if(m_originalCaster
->GetTypeId() == TYPEID_PLAYER
)
756 WorldPacket
data(SMSG_SPIRIT_HEALER_CONFIRM
, 8);
757 data
<< unitTarget
->GetGUID();
758 ((Player
*)m_originalCaster
)->GetSession()->SendPacket( &data
);
762 case 17271: // Test Fetid Skull
764 if(!itemTarget
&& m_caster
->GetTypeId()!=TYPEID_PLAYER
)
767 uint32 spell_id
= roll_chance_i(50) ? 17269 : 17270;
769 m_caster
->CastSpell(m_caster
,spell_id
,true,NULL
);
772 case 20577: // Cannibalize
774 m_caster
->CastSpell(m_caster
,20578,false,NULL
);
776 case 23019: // Crystal Prison Dummy DND
778 if(!unitTarget
|| !unitTarget
->isAlive() || unitTarget
->GetTypeId() != TYPEID_UNIT
|| ((Creature
*)unitTarget
)->isPet())
781 Creature
* creatureTarget
= (Creature
*)unitTarget
;
782 if(creatureTarget
->isPet())
785 GameObject
* pGameObj
= new GameObject
;
787 Map
*map
= creatureTarget
->GetMap();
789 // create before death for get proper coordinates
790 if(!pGameObj
->Create(objmgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), 179644, map
, m_caster
->GetPhaseMask(),
791 creatureTarget
->GetPositionX(), creatureTarget
->GetPositionY(), creatureTarget
->GetPositionZ(),
792 creatureTarget
->GetOrientation(), 0, 0, 0, 0, 100, 1) )
798 pGameObj
->SetRespawnTime(creatureTarget
->GetRespawnTime()-time(NULL
));
799 pGameObj
->SetOwnerGUID(m_caster
->GetGUID() );
800 pGameObj
->SetUInt32Value(GAMEOBJECT_LEVEL
, m_caster
->getLevel() );
801 pGameObj
->SetSpellId(m_spellInfo
->Id
);
803 creatureTarget
->setDeathState(JUST_DIED
);
804 creatureTarget
->RemoveCorpse();
805 creatureTarget
->SetHealth(0); // just for nice GM-mode view
807 DEBUG_LOG("AddObject at SpellEfects.cpp EffectDummy\n");
810 WorldPacket
data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE
, 8);
811 data
<< uint64(pGameObj
->GetGUID());
812 m_caster
->SendMessageToSet(&data
,true);
816 case 23074: // Arcanite Dragonling
817 if (!m_CastItem
) return;
818 m_caster
->CastSpell(m_caster
,19804,true,m_CastItem
);
820 case 23075: // Mithril Mechanical Dragonling
821 if (!m_CastItem
) return;
822 m_caster
->CastSpell(m_caster
,12749,true,m_CastItem
);
824 case 23076: // Mechanical Dragonling
825 if (!m_CastItem
) return;
826 m_caster
->CastSpell(m_caster
,4073,true,m_CastItem
);
828 case 23133: // Gnomish Battle Chicken
829 if (!m_CastItem
) return;
830 m_caster
->CastSpell(m_caster
,13166,true,m_CastItem
);
832 case 23448: // Ultrasafe Transporter: Gadgetzan - backfires
834 int32 r
= irand(0, 119);
835 if ( r
< 20 ) // 1/6 polymorph
836 m_caster
->CastSpell(m_caster
,23444,true);
837 else if ( r
< 100 ) // 4/6 evil twin
838 m_caster
->CastSpell(m_caster
,23445,true);
839 else // 1/6 miss the target
840 m_caster
->CastSpell(m_caster
,36902,true);
843 case 23453: // Ultrasafe Transporter: Gadgetzan
844 if ( roll_chance_i(50) ) // success
845 m_caster
->CastSpell(m_caster
,23441,true);
847 m_caster
->CastSpell(m_caster
,23446,true);
849 case 23645: // Hourglass Sand
850 m_caster
->RemoveAurasDueToSpell(23170);
852 case 23725: // Gift of Life (warrior bwl trinket)
853 m_caster
->CastSpell(m_caster
,23782,true);
854 m_caster
->CastSpell(m_caster
,23783,true);
856 case 25860: // Reindeer Transformation
858 if (!m_caster
->HasAuraType(SPELL_AURA_MOUNTED
))
861 float flyspeed
= m_caster
->GetSpeedRate(MOVE_FLIGHT
);
862 float speed
= m_caster
->GetSpeedRate(MOVE_RUN
);
864 m_caster
->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED
);
866 //5 different spells used depending on mounted speed and if mount can fly or not
867 if (flyspeed
>= 4.1f
)
868 m_caster
->CastSpell(m_caster
, 44827, true); //310% flying Reindeer
869 else if (flyspeed
>= 3.8f
)
870 m_caster
->CastSpell(m_caster
, 44825, true); //280% flying Reindeer
871 else if (flyspeed
>= 1.6f
)
872 m_caster
->CastSpell(m_caster
, 44824, true); //60% flying Reindeer
873 else if (speed
>= 2.0f
)
874 m_caster
->CastSpell(m_caster
, 25859, true); //100% ground Reindeer
876 m_caster
->CastSpell(m_caster
, 25858, true); //60% ground Reindeer
880 //case 26074: // Holiday Cheer
881 // return; -- implemented at client side
882 case 28006: // Arcane Cloaking
884 if( unitTarget
->GetTypeId() == TYPEID_PLAYER
)
885 m_caster
->CastSpell(unitTarget
,29294,true);
888 case 28730: // Arcane Torrent (Mana)
890 Aura
* dummy
= m_caster
->GetDummyAura(28734);
893 int32 bp
= damage
* dummy
->GetStackAmount();
894 m_caster
->CastCustomSpell(m_caster
, 28733, &bp
, NULL
, NULL
, true);
895 m_caster
->RemoveAurasDueToSpell(28734);
899 case 29200: // Purify Helboar Meat
901 if( m_caster
->GetTypeId() != TYPEID_PLAYER
)
904 uint32 spell_id
= roll_chance_i(50) ? 29277 : 29278;
906 m_caster
->CastSpell(m_caster
,spell_id
,true,NULL
);
909 case 29858: // Soulshatter
910 if (unitTarget
&& unitTarget
->GetTypeId() == TYPEID_UNIT
&& unitTarget
->IsHostileTo(m_caster
))
911 m_caster
->CastSpell(unitTarget
,32835,true);
913 case 30458: // Nigh Invulnerability
914 if (!m_CastItem
) return;
915 if(roll_chance_i(86)) // success
916 m_caster
->CastSpell(m_caster
, 30456, true, m_CastItem
);
917 else // backfire in 14% casts
918 m_caster
->CastSpell(m_caster
, 30457, true, m_CastItem
);
920 case 30507: // Poultryizer
921 if (!m_CastItem
) return;
922 if(roll_chance_i(80)) // success
923 m_caster
->CastSpell(unitTarget
, 30501, true, m_CastItem
);
925 m_caster
->CastSpell(unitTarget
, 30504, true, m_CastItem
);
927 case 33060: // Make a Wish
929 if(m_caster
->GetTypeId()!=TYPEID_PLAYER
)
936 case 1: spell_id
= 33053; break;
937 case 2: spell_id
= 33057; break;
938 case 3: spell_id
= 33059; break;
939 case 4: spell_id
= 33062; break;
940 case 5: spell_id
= 33064; break;
943 m_caster
->CastSpell(m_caster
,spell_id
,true,NULL
);
949 switch(m_caster
->GetAreaId())
951 case 3900: spell_id
= 35743; break;
952 case 3742: spell_id
= 35744; break;
956 m_caster
->CastSpell(m_caster
,spell_id
,true);
959 case 37674: // Chaos Blast
964 int32 basepoints0
= 100;
965 m_caster
->CastCustomSpell(unitTarget
,37675,&basepoints0
,NULL
,NULL
,true);
968 case 40802: // Mingo's Fortune Generator (Mingo's Fortune Giblets)
970 // selecting one from Bloodstained Fortune item
974 case 1: newitemid
= 32688; break;
975 case 2: newitemid
= 32689; break;
976 case 3: newitemid
= 32690; break;
977 case 4: newitemid
= 32691; break;
978 case 5: newitemid
= 32692; break;
979 case 6: newitemid
= 32693; break;
980 case 7: newitemid
= 32700; break;
981 case 8: newitemid
= 32701; break;
982 case 9: newitemid
= 32702; break;
983 case 10: newitemid
= 32703; break;
984 case 11: newitemid
= 32704; break;
985 case 12: newitemid
= 32705; break;
986 case 13: newitemid
= 32706; break;
987 case 14: newitemid
= 32707; break;
988 case 15: newitemid
= 32708; break;
989 case 16: newitemid
= 32709; break;
990 case 17: newitemid
= 32710; break;
991 case 18: newitemid
= 32711; break;
992 case 19: newitemid
= 32712; break;
993 case 20: newitemid
= 32713; break;
998 DoCreateItem(i
,newitemid
);
1001 // Demon Broiled Surprise
1002 /* FIX ME: Required for correct work implementing implicit target 7 (in pair (22,7))
1005 if (m_caster->GetTypeId() != TYPEID_PLAYER)
1008 ((Player*)m_caster)->CastSpell(unitTarget, 43753, true);
1012 case 44875: // Complete Raptor Capture
1014 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_UNIT
)
1017 Creature
* creatureTarget
= (Creature
*)unitTarget
;
1019 creatureTarget
->setDeathState(JUST_DIED
);
1020 creatureTarget
->RemoveCorpse();
1021 creatureTarget
->SetHealth(0); // just for nice GM-mode view
1023 //cast spell Raptor Capture Credit
1024 m_caster
->CastSpell(m_caster
,42337,true,NULL
);
1027 case 37573: //Temporal Phase Modulator
1032 TemporarySummon
* tempSummon
= dynamic_cast<TemporarySummon
*>(unitTarget
);
1036 uint32 health
= tempSummon
->GetHealth();
1037 const uint32 entry_list
[6] = {21821, 21820, 21817};
1039 float x
= tempSummon
->GetPositionX();
1040 float y
= tempSummon
->GetPositionY();
1041 float z
= tempSummon
->GetPositionZ();
1042 float o
= tempSummon
->GetOrientation();
1044 tempSummon
->UnSummon();
1046 Creature
* pCreature
= m_caster
->SummonCreature(entry_list
[urand(0, 2)], x
, y
, z
, o
,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN
,180000);
1050 pCreature
->SetHealth(health
);
1053 pCreature
->AI()->AttackStart(m_caster
);
1057 case 34665: //Administer Antidote
1059 if(!unitTarget
|| m_caster
->GetTypeId() != TYPEID_PLAYER
)
1065 TemporarySummon
* tempSummon
= dynamic_cast<TemporarySummon
*>(unitTarget
);
1069 uint32 health
= tempSummon
->GetHealth();
1071 float x
= tempSummon
->GetPositionX();
1072 float y
= tempSummon
->GetPositionY();
1073 float z
= tempSummon
->GetPositionZ();
1074 float o
= tempSummon
->GetOrientation();
1075 tempSummon
->UnSummon();
1077 Creature
* pCreature
= m_caster
->SummonCreature(16992, x
, y
, z
, o
,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN
,180000);
1081 pCreature
->SetHealth(health
);
1082 ((Player
*)m_caster
)->KilledMonster(16992,pCreature
->GetGUID());
1084 if (pCreature
->AI())
1085 pCreature
->AI()->AttackStart(m_caster
);
1089 case 44997: // Converting Sentry
1091 //Converted Sentry Credit
1092 m_caster
->CastSpell(m_caster
, 45009, true);
1095 case 45030: // Impale Emissary
1097 // Emissary of Hate Credit
1098 m_caster
->CastSpell(m_caster
, 45088, true);
1101 case 50243: // Teach Language
1103 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
1106 // spell has a 1/3 chance to trigger one of the below
1107 if(roll_chance_i(66))
1109 if(((Player
*)m_caster
)->GetTeam() == ALLIANCE
)
1111 // 1000001 - gnomish binary
1112 m_caster
->CastSpell(m_caster
, 50242, true);
1116 // 01001000 - goblin binary
1117 m_caster
->CastSpell(m_caster
, 50246, true);
1122 case 51582: //Rocket Boots Engaged (Rocket Boots Xtreme and Rocket Boots Xtreme Lite)
1124 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
1127 if(BattleGround
* bg
= ((Player
*)m_caster
)->GetBattleGround())
1128 bg
->EventPlayerDroppedFlag((Player
*)m_caster
);
1130 m_caster
->CastSpell(m_caster
, 30452, true, NULL
);
1136 m_caster
->CastSpell(m_caster
,54586,true);
1141 //All IconID Check in there
1142 switch(m_spellInfo
->SpellIconID
)
1144 // Berserking (troll racial traits)
1147 uint32 healthPerc
= uint32((float(m_caster
->GetHealth())/m_caster
->GetMaxHealth())*100);
1148 int32 melee_mod
= 10;
1149 if (healthPerc
<= 40)
1151 if (healthPerc
< 100 && healthPerc
> 40)
1152 melee_mod
= 10+(100-healthPerc
)/3;
1154 int32 hasteModBasePoints0
= melee_mod
; // (EffectBasePoints[0]+1)-1+(5-melee_mod) = (melee_mod-1+1)-1+5-melee_mod = 5-1
1155 int32 hasteModBasePoints1
= (5-melee_mod
);
1156 int32 hasteModBasePoints2
= 5;
1158 // FIXME: custom spell required this aura state by some unknown reason, we not need remove it anyway
1159 m_caster
->ModifyAuraState(AURA_STATE_BERSERKING
,true);
1160 m_caster
->CastCustomSpell(m_caster
,26635,&hasteModBasePoints0
,&hasteModBasePoints1
,&hasteModBasePoints2
,true,NULL
);
1166 case SPELLFAMILY_MAGE
:
1167 switch(m_spellInfo
->Id
)
1169 case 11958: // Cold Snap
1171 if(m_caster
->GetTypeId()!=TYPEID_PLAYER
)
1174 // immediately finishes the cooldown on Frost spells
1175 const PlayerSpellMap
& sp_list
= ((Player
*)m_caster
)->GetSpellMap();
1176 for (PlayerSpellMap::const_iterator itr
= sp_list
.begin(); itr
!= sp_list
.end(); ++itr
)
1178 if (itr
->second
->state
== PLAYERSPELL_REMOVED
)
1181 uint32 classspell
= itr
->first
;
1182 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(classspell
);
1184 if( spellInfo
->SpellFamilyName
== SPELLFAMILY_MAGE
&&
1185 (GetSpellSchoolMask(spellInfo
) & SPELL_SCHOOL_MASK_FROST
) &&
1186 spellInfo
->Id
!= 11958 && GetSpellRecoveryTime(spellInfo
) > 0 )
1188 ((Player
*)m_caster
)->RemoveSpellCooldown(classspell
);
1190 WorldPacket
data(SMSG_CLEAR_COOLDOWN
, (4+8));
1191 data
<< uint32(classspell
);
1192 data
<< uint64(m_caster
->GetGUID());
1193 ((Player
*)m_caster
)->GetSession()->SendPacket(&data
);
1200 if ( unitTarget
&& unitTarget
->GetTypeId() == TYPEID_UNIT
)
1202 //Polymorph Cast Visual Rank 1
1203 const uint32 spell_list
[6] = {32813, 32816, 32817, 32818, 32819, 32820};
1204 unitTarget
->CastSpell( unitTarget
, spell_list
[urand(0, 5)], true);
1210 case SPELLFAMILY_WARRIOR
:
1212 if(m_spellInfo
->SpellFamilyFlags
& 0x1 && m_spellInfo
->SpellVisual
[0] == 867)
1214 int32 chargeBasePoints0
= damage
;
1215 m_caster
->CastCustomSpell(m_caster
,34846,&chargeBasePoints0
,NULL
,NULL
,true);
1219 if(m_spellInfo
->SpellFamilyFlags
& 0x20000000)
1224 uint32 rage
= m_caster
->GetPower(POWER_RAGE
);
1225 // Glyph of Execution bonus
1226 if (Aura
*aura
= m_caster
->GetDummyAura(58367))
1227 rage
+=aura
->GetModifier()->m_amount
;
1229 int32 basePoints0
= damage
+int32(rage
* m_spellInfo
->DmgMultiplier
[i
] +
1230 m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
)*0.2f
);
1231 m_caster
->CastCustomSpell(unitTarget
, 20647, &basePoints0
, NULL
, NULL
, true, 0);
1232 m_caster
->SetPower(POWER_RAGE
,0);
1236 if(m_spellInfo
->SpellFamilyFlags
& 0x0000000000200000LL
)
1240 m_damage
+=m_caster
->CalculateDamage(m_attackType
, false);
1244 switch(m_spellInfo
->Id
)
1251 m_caster
->CastSpell(unitTarget
,21887,true); // spell mod
1257 int32 healthModSpellBasePoints0
= int32(m_caster
->GetMaxHealth()*0.3);
1258 m_caster
->CastCustomSpell(m_caster
, 12976, &healthModSpellBasePoints0
, NULL
, NULL
, true, NULL
);
1264 m_caster
->CastCustomSpell(unitTarget
, 23885, &damage
, NULL
, NULL
, true, NULL
);
1269 case SPELLFAMILY_WARLOCK
:
1271 if (m_spellInfo
->SpellFamilyFlags
& 0x0000000000040000LL
)
1273 // In 303 exist spirit depend
1274 uint32 spirit
= m_caster
->GetStat(STAT_SPIRIT
);
1275 switch (m_spellInfo
->Id
)
1277 case 1454: damage
+=spirit
; break;
1278 case 1455: damage
+=spirit
*15/10; break;
1279 case 1456: damage
+=spirit
*2; break;
1280 case 11687: damage
+=spirit
*25/10; break;
1284 case 57946: damage
+=spirit
*3; break;
1286 sLog
.outError("Spell::EffectDummy: %u Life Tap need set spirit multipler", m_spellInfo
->Id
);
1289 // Think its not need (also need remove Life Tap from SpellDamageBonus or add new value)
1290 // damage = m_caster->SpellDamageBonus(m_caster, m_spellInfo,uint32(damage > 0 ? damage : 0), SPELL_DIRECT_DAMAGE);
1291 if(int32(unitTarget
->GetHealth()) > damage
)
1293 // Shouldn't Appear in Combat Log
1294 unitTarget
->ModifyHealth(-damage
);
1296 int32 mana
= damage
;
1297 // Improved Life Tap mod
1298 Unit::AuraList
const& auraDummy
= m_caster
->GetAurasByType(SPELL_AURA_DUMMY
);
1299 for(Unit::AuraList::const_iterator itr
= auraDummy
.begin(); itr
!= auraDummy
.end(); ++itr
)
1301 if((*itr
)->GetSpellProto()->SpellFamilyName
==SPELLFAMILY_WARLOCK
&& (*itr
)->GetSpellProto()->SpellIconID
== 208)
1302 mana
= ((*itr
)->GetModifier()->m_amount
+ 100)* mana
/ 100;
1304 m_caster
->CastCustomSpell(unitTarget
, 31818, &mana
, NULL
, NULL
, true);
1307 int32 manaFeedVal
= 0;
1308 Unit::AuraList
const& mod
= m_caster
->GetAurasByType(SPELL_AURA_ADD_FLAT_MODIFIER
);
1309 for(Unit::AuraList::const_iterator itr
= mod
.begin(); itr
!= mod
.end(); ++itr
)
1311 if((*itr
)->GetSpellProto()->SpellFamilyName
==SPELLFAMILY_WARLOCK
&& (*itr
)->GetSpellProto()->SpellIconID
== 1982)
1312 manaFeedVal
+= (*itr
)->GetModifier()->m_amount
;
1316 manaFeedVal
= manaFeedVal
* mana
/ 100;
1317 m_caster
->CastCustomSpell(m_caster
, 32553, &manaFeedVal
, NULL
, NULL
, true, NULL
);
1321 SendCastResult(SPELL_FAILED_FIZZLE
);
1325 case SPELLFAMILY_PRIEST
:
1327 if (m_spellInfo
->SpellFamilyFlags
& 0x0080000000000000LL
)
1334 switch(m_spellInfo
->Id
)
1336 case 47540: hurt
= 47758; heal
= 47757; break;
1337 case 53005: hurt
= 53001; heal
= 52986; break;
1338 case 53006: hurt
= 53002; heal
= 52987; break;
1339 case 53007: hurt
= 53003; heal
= 52988; break;
1341 sLog
.outError("Spell::EffectDummy: Spell %u Penance need set correct heal/damage spell", m_spellInfo
->Id
);
1344 if (m_caster
->IsFriendlyTo(unitTarget
))
1345 m_caster
->CastSpell(unitTarget
, heal
, true, 0);
1347 m_caster
->CastSpell(unitTarget
, hurt
, true, 0);
1350 switch(m_spellInfo
->Id
)
1352 case 28598: // Touch of Weakness triggered spell
1354 if(!unitTarget
|| !m_triggeredByAuraSpell
)
1358 switch(m_triggeredByAuraSpell
->Id
)
1360 case 2652: spellid
= 2943; break; // Rank 1
1361 case 19261: spellid
= 19249; break; // Rank 2
1362 case 19262: spellid
= 19251; break; // Rank 3
1363 case 19264: spellid
= 19252; break; // Rank 4
1364 case 19265: spellid
= 19253; break; // Rank 5
1365 case 19266: spellid
= 19254; break; // Rank 6
1366 case 25461: spellid
= 25460; break; // Rank 7
1368 sLog
.outError("Spell::EffectDummy: Spell 28598 triggered by unhandeled spell %u",m_triggeredByAuraSpell
->Id
);
1371 m_caster
->CastSpell(unitTarget
, spellid
, true, NULL
);
1376 case SPELLFAMILY_DRUID
:
1378 case SPELLFAMILY_ROGUE
:
1379 switch(m_spellInfo
->Id
)
1383 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
1386 Player
*pCaster
= ((Player
*)m_caster
);
1388 Item
*item
= pCaster
->GetWeaponForAttack(OFF_ATTACK
);
1392 // all poison enchantments is temporary
1393 uint32 enchant_id
= item
->GetEnchantmentId(TEMP_ENCHANTMENT_SLOT
);
1397 SpellItemEnchantmentEntry
const *pEnchant
= sSpellItemEnchantmentStore
.LookupEntry(enchant_id
);
1401 for (int s
=0;s
<3;s
++)
1403 if(pEnchant
->type
[s
]!=ITEM_ENCHANTMENT_TYPE_COMBAT_SPELL
)
1406 SpellEntry
const* combatEntry
= sSpellStore
.LookupEntry(pEnchant
->spellid
[s
]);
1407 if(!combatEntry
|| combatEntry
->Dispel
!= DISPEL_POISON
)
1410 m_caster
->CastSpell(unitTarget
, combatEntry
, true, item
);
1413 m_caster
->CastSpell(unitTarget
, 5940, true);
1416 case 14185: // Preparation Rogue
1418 if(m_caster
->GetTypeId()!=TYPEID_PLAYER
)
1421 //immediately finishes the cooldown on certain Rogue abilities
1422 const PlayerSpellMap
& sp_list
= ((Player
*)m_caster
)->GetSpellMap();
1423 for (PlayerSpellMap::const_iterator itr
= sp_list
.begin(); itr
!= sp_list
.end(); ++itr
)
1425 uint32 classspell
= itr
->first
;
1426 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(classspell
);
1428 if (spellInfo
->SpellFamilyName
== SPELLFAMILY_ROGUE
&& (spellInfo
->SpellFamilyFlags
& 0x0000024000000860LL
))
1430 ((Player
*)m_caster
)->RemoveSpellCooldown(classspell
);
1432 WorldPacket
data(SMSG_CLEAR_COOLDOWN
, (4+8));
1433 data
<< uint32(classspell
);
1434 data
<< uint64(m_caster
->GetGUID());
1435 ((Player
*)m_caster
)->GetSession()->SendPacket(&data
);
1440 case 31231: // Cheat Death
1442 m_caster
->CastSpell(m_caster
,45182,true);
1447 case SPELLFAMILY_HUNTER
:
1449 if(m_spellInfo
->SpellFamilyFlags
& 0x100000000LL
)
1451 if( !unitTarget
|| !unitTarget
->isAlive())
1456 // check dazed affect
1457 Unit::AuraList
const& decSpeedList
= unitTarget
->GetAurasByType(SPELL_AURA_MOD_DECREASE_SPEED
);
1458 for(Unit::AuraList::const_iterator iter
= decSpeedList
.begin(); iter
!= decSpeedList
.end(); ++iter
)
1460 if((*iter
)->GetSpellProto()->SpellIconID
==15 && (*iter
)->GetSpellProto()->Dispel
==0)
1472 switch(m_spellInfo
->Id
)
1474 case 23989: //Readiness talent
1476 if(m_caster
->GetTypeId()!=TYPEID_PLAYER
)
1479 //immediately finishes the cooldown for hunter abilities
1480 const PlayerSpellMap
& sp_list
= ((Player
*)m_caster
)->GetSpellMap();
1481 for (PlayerSpellMap::const_iterator itr
= sp_list
.begin(); itr
!= sp_list
.end(); ++itr
)
1483 uint32 classspell
= itr
->first
;
1484 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(classspell
);
1486 if (spellInfo
->SpellFamilyName
== SPELLFAMILY_HUNTER
&& spellInfo
->Id
!= 23989 && GetSpellRecoveryTime(spellInfo
) > 0 )
1488 ((Player
*)m_caster
)->RemoveSpellCooldown(classspell
);
1490 WorldPacket
data(SMSG_CLEAR_COOLDOWN
, (4+8));
1491 data
<< uint32(classspell
);
1492 data
<< uint64(m_caster
->GetGUID());
1493 ((Player
*)m_caster
)->GetSession()->SendPacket(&data
);
1498 case 37506: // Scatter Shot
1500 if (m_caster
->GetTypeId()!=TYPEID_PLAYER
)
1503 // break Auto Shot and autohit
1504 m_caster
->InterruptSpell(CURRENT_AUTOREPEAT_SPELL
);
1505 m_caster
->AttackStop();
1506 ((Player
*)m_caster
)->SendAttackSwingCancelAttack();
1511 case SPELLFAMILY_PALADIN
:
1512 switch(m_spellInfo
->SpellIconID
)
1514 case 156: // Holy Shock
1522 switch(m_spellInfo
->Id
)
1524 case 20473: hurt
= 25912; heal
= 25914; break;
1525 case 20929: hurt
= 25911; heal
= 25913; break;
1526 case 20930: hurt
= 25902; heal
= 25903; break;
1527 case 27174: hurt
= 27176; heal
= 27175; break;
1528 case 33072: hurt
= 33073; heal
= 33074; break;
1529 case 48824: hurt
= 48822; heal
= 48820; break;
1530 case 48825: hurt
= 48823; heal
= 48821; break;
1532 sLog
.outError("Spell::EffectDummy: Spell %u not handled in HS",m_spellInfo
->Id
);
1536 if(m_caster
->IsFriendlyTo(unitTarget
))
1537 m_caster
->CastSpell(unitTarget
, heal
, true, 0);
1539 m_caster
->CastSpell(unitTarget
, hurt
, true, 0);
1543 case 561: // Judgement of command
1548 uint32 spell_id
= m_currentBasePoints
[i
]+1;
1549 SpellEntry
const* spell_proto
= sSpellStore
.LookupEntry(spell_id
);
1553 if( !unitTarget
->hasUnitState(UNIT_STAT_STUNNED
) && m_caster
->GetTypeId()==TYPEID_PLAYER
)
1555 // decreased damage (/2) for non-stunned target.
1556 SpellModifier
*mod
= new SpellModifier
;
1557 mod
->op
= SPELLMOD_DAMAGE
;
1559 mod
->type
= SPELLMOD_PCT
;
1560 mod
->spellId
= m_spellInfo
->Id
;
1561 mod
->mask
= 0x0000020000000000LL
;
1564 ((Player
*)m_caster
)->AddSpellMod(mod
, true);
1565 m_caster
->CastSpell(unitTarget
,spell_proto
,true,NULL
);
1567 ((Player
*)m_caster
)->AddSpellMod(mod
, false);
1570 m_caster
->CastSpell(unitTarget
,spell_proto
,true,NULL
);
1576 switch(m_spellInfo
->Id
)
1578 // Judgement of Righteousness (0.2*$AP+0.32*$SPH) holy added in spellDamagBonus
1583 m_damage
+=int32(0.2f
*m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
));
1586 case 31789: // Righteous Defense (step 1)
1588 // 31989 -> dummy effect (step 1) + dummy effect (step 2) -> 31709 (taunt like spell for each target)
1590 // non-standard cast requirement check
1591 if (!unitTarget
|| unitTarget
->getAttackers().empty())
1593 // clear cooldown at fail
1594 if(m_caster
->GetTypeId()==TYPEID_PLAYER
)
1596 ((Player
*)m_caster
)->RemoveSpellCooldown(m_spellInfo
->Id
);
1598 WorldPacket
data(SMSG_CLEAR_COOLDOWN
, (4+8));
1599 data
<< uint32(m_spellInfo
->Id
);
1600 data
<< uint64(m_caster
->GetGUID());
1601 ((Player
*)m_caster
)->GetSession()->SendPacket(&data
);
1604 SendCastResult(SPELL_FAILED_TARGET_AFFECTING_COMBAT
);
1608 // Righteous Defense (step 2) (in old version 31980 dummy effect)
1609 // Clear targets for eff 1
1610 for(std::list
<TargetInfo
>::iterator ihit
= m_UniqueTargetInfo
.begin();ihit
!= m_UniqueTargetInfo
.end();++ihit
)
1611 ihit
->effectMask
&= ~(1<<1);
1613 // not empty (checked)
1614 Unit::AttackerSet
const& attackers
= unitTarget
->getAttackers();
1616 // chance to be selected from list
1617 float chance
= 100.0f
/attackers
.size();
1619 for(Unit::AttackerSet::const_iterator aItr
= attackers
.begin(); aItr
!= attackers
.end() && count
< 3; ++aItr
)
1621 if(!roll_chance_f(chance
))
1624 AddUnitTarget((*aItr
), 1);
1627 // now let next effect cast spell at each target.
1630 case 37877: // Blessing of Faith
1635 uint32 spell_id
= 0;
1636 switch(unitTarget
->getClass())
1638 case CLASS_DRUID
: spell_id
= 37878; break;
1639 case CLASS_PALADIN
: spell_id
= 37879; break;
1640 case CLASS_PRIEST
: spell_id
= 37880; break;
1641 case CLASS_SHAMAN
: spell_id
= 37881; break;
1642 default: return; // ignore for not healing classes
1645 m_caster
->CastSpell(m_caster
,spell_id
,true);
1650 case SPELLFAMILY_SHAMAN
:
1651 //Shaman Rockbiter Weapon
1652 if (m_spellInfo
->SpellFamilyFlags
== 0x400000)
1654 // TODO: use expect spell for enchant (if exist talent)
1655 // In 3.0.3 no mods present for rockbiter
1656 uint32 spell_id
= 0;
1657 switch(m_spellInfo
->Id
)
1659 case 8017: spell_id
= 36494; break; // Rank 1
1660 case 8018: spell_id
= 36750; break; // Rank 2
1661 case 8019: spell_id
= 36755; break; // Rank 3
1662 case 10399: spell_id
= 36759; break; // Rank 4
1664 sLog
.outError("Spell::EffectDummy: Spell %u not handled in RW",m_spellInfo
->Id
);
1668 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry( spell_id
);
1672 sLog
.outError("WORLD: unknown spell id %i\n", spell_id
);
1676 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
1679 for(int i
= BASE_ATTACK
; i
<= OFF_ATTACK
; ++i
)
1681 if(Item
* item
= ((Player
*)m_caster
)->GetWeaponForAttack(WeaponAttackType(i
)))
1683 if(item
->IsFitToSpellRequirements(m_spellInfo
))
1685 Spell
*spell
= new Spell(m_caster
, spellInfo
, true);
1687 // enchanting spell selected by calculated damage-per-sec in enchanting effect
1688 // at calculation applied affect from Elemental Weapons talent
1689 // real enchantment damage-1
1690 spell
->m_currentBasePoints
[1] = damage
-1;
1692 SpellCastTargets targets
;
1693 targets
.setItemTarget( item
);
1694 spell
->prepare(&targets
);
1700 // Healing Stream Totem
1701 if(m_spellInfo
->SpellFamilyFlags
& 0x0000000000002000LL
)
1703 m_caster
->CastCustomSpell(unitTarget
, 52042, &damage
, 0, 0, true, 0, 0, m_originalCasterGUID
);
1706 // Mana Spring Totem
1707 if(m_spellInfo
->SpellFamilyFlags
& 0x0000000000004000LL
)
1709 if(unitTarget
->getPowerType()!=POWER_MANA
)
1711 m_caster
->CastCustomSpell(unitTarget
, 52032, &damage
, 0, 0, true, 0, 0, m_originalCasterGUID
);
1714 if(m_spellInfo
->Id
== 39610) // Mana Tide Totem effect
1716 if(!unitTarget
|| unitTarget
->getPowerType() != POWER_MANA
)
1718 // Glyph of Mana Tide
1719 Unit
*owner
= m_caster
->GetOwner();
1721 if (Aura
*dummy
= owner
->GetDummyAura(55441))
1722 damage
+=dummy
->GetModifier()->m_amount
;
1723 // Regenerate 6% of Total Mana Every 3 secs
1724 int32 EffectBasePoints0
= unitTarget
->GetMaxPower(POWER_MANA
) * damage
/ 100;
1725 m_caster
->CastCustomSpell(unitTarget
,39609,&EffectBasePoints0
,NULL
,NULL
,true,NULL
,NULL
,m_originalCasterGUID
);
1729 if (m_spellInfo
->SpellFamilyFlags2
& 0x00000004)
1731 if (m_caster
->GetTypeId()!=TYPEID_PLAYER
)
1733 Item
*item
= ((Player
*)m_caster
)->GetItemByPos(INVENTORY_SLOT_BAG_0
, EQUIPMENT_SLOT_OFFHAND
);
1736 // Damage is increased if your off-hand weapon is enchanted with Flametongue.
1737 Unit::AuraList
const& auraDummy
= m_caster
->GetAurasByType(SPELL_AURA_DUMMY
);
1738 for(Unit::AuraList::const_iterator itr
= auraDummy
.begin(); itr
!= auraDummy
.end(); ++itr
)
1740 if( (*itr
)->GetSpellProto()->SpellFamilyName
==SPELLFAMILY_SHAMAN
&&
1741 (*itr
)->GetSpellProto()->SpellFamilyFlags
& 0x0000000000200000LL
&&
1742 (*itr
)->GetCastItemGUID() == item
->GetGUID())
1744 m_damage
+= m_damage
* damage
/ 100;
1755 if(PetAura
const* petSpell
= spellmgr
.GetPetAura(m_spellInfo
->Id
))
1757 m_caster
->AddPetAura(petSpell
);
1762 void Spell::EffectTriggerSpellWithValue(uint32 i
)
1764 uint32 triggered_spell_id
= m_spellInfo
->EffectTriggerSpell
[i
];
1767 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry( triggered_spell_id
);
1771 sLog
.outError("EffectTriggerSpellWithValue of spell %u: triggering unknown spell id %i\n", m_spellInfo
->Id
,triggered_spell_id
);
1776 m_caster
->CastCustomSpell(unitTarget
,triggered_spell_id
,&bp
,&bp
,&bp
,true,NULL
,NULL
,m_originalCasterGUID
);
1779 void Spell::EffectTriggerRitualOfSummoning(uint32 i
)
1781 uint32 triggered_spell_id
= m_spellInfo
->EffectTriggerSpell
[i
];
1782 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry( triggered_spell_id
);
1786 sLog
.outError("EffectTriggerRitualOfSummoning of spell %u: triggering unknown spell id %i", m_spellInfo
->Id
,triggered_spell_id
);
1791 Spell
*spell
= new Spell(m_caster
, spellInfo
, true);
1793 SpellCastTargets targets
;
1794 targets
.setUnitTarget( unitTarget
);
1795 spell
->prepare(&targets
);
1797 m_caster
->SetCurrentCastedSpell(spell
);
1798 spell
->m_selfContainer
= &(m_caster
->m_currentSpells
[spell
->GetCurrentContainer()]);
1802 void Spell::EffectForceCast(uint32 i
)
1807 uint32 triggered_spell_id
= m_spellInfo
->EffectTriggerSpell
[i
];
1810 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry( triggered_spell_id
);
1814 sLog
.outError("EffectForceCast of spell %u: triggering unknown spell id %i", m_spellInfo
->Id
,triggered_spell_id
);
1818 unitTarget
->CastSpell(unitTarget
,spellInfo
,true,NULL
,NULL
,m_originalCasterGUID
);
1821 void Spell::EffectTriggerSpell(uint32 i
)
1823 uint32 triggered_spell_id
= m_spellInfo
->EffectTriggerSpell
[i
];
1826 switch(triggered_spell_id
)
1831 m_caster
->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT
);
1832 m_caster
->RemoveSpellsCausingAura(SPELL_AURA_MOD_DECREASE_SPEED
);
1833 m_caster
->RemoveSpellsCausingAura(SPELL_AURA_MOD_STALKED
);
1835 // if this spell is given to NPC it must handle rest by it's own AI
1836 if ( m_caster
->GetTypeId() != TYPEID_PLAYER
)
1839 // get highest rank of the Stealth spell
1841 const PlayerSpellMap
& sp_list
= ((Player
*)m_caster
)->GetSpellMap();
1842 for (PlayerSpellMap::const_iterator itr
= sp_list
.begin(); itr
!= sp_list
.end(); ++itr
)
1844 // only highest rank is shown in spell book, so simply check if shown in spell book
1845 if(!itr
->second
->active
|| itr
->second
->disabled
|| itr
->second
->state
== PLAYERSPELL_REMOVED
)
1848 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(itr
->first
);
1852 if (spellInfo
->SpellFamilyName
== SPELLFAMILY_ROGUE
&& spellInfo
->SpellFamilyFlags
& SPELLFAMILYFLAG_ROGUE_STEALTH
)
1854 spellId
= spellInfo
->Id
;
1859 // no Stealth spell found
1863 // reset cooldown on it if needed
1864 if(((Player
*)m_caster
)->HasSpellCooldown(spellId
))
1865 ((Player
*)m_caster
)->RemoveSpellCooldown(spellId
);
1867 m_caster
->CastSpell(m_caster
, spellId
, true);
1871 case 23770: // Sayge's Dark Fortune of *
1872 // not exist, common cooldown can be implemented in scripts if need.
1874 // Brittle Armor - (need add max stack of 24575 Brittle Armor)
1877 const SpellEntry
*spell
= sSpellStore
.LookupEntry(24575);
1881 for (int i
=0; i
< spell
->StackAmount
; ++i
)
1882 m_caster
->CastSpell(unitTarget
,spell
->Id
, true, m_CastItem
, NULL
, m_originalCasterGUID
);
1885 // Mercurial Shield - (need add max stack of 26464 Mercurial Shield)
1888 const SpellEntry
*spell
= sSpellStore
.LookupEntry(26464);
1892 for (int i
=0; i
< spell
->StackAmount
; ++i
)
1893 m_caster
->CastSpell(unitTarget
,spell
->Id
, true, m_CastItem
, NULL
, m_originalCasterGUID
);
1896 // Righteous Defense
1899 m_caster
->CastSpell(unitTarget
, 31790, true,m_CastItem
,NULL
,m_originalCasterGUID
);
1905 Unit::AuraMap
& Auras
= m_caster
->GetAuras();
1906 for(Unit::AuraMap::iterator iter
= Auras
.begin(); iter
!= Auras
.end(); ++iter
)
1908 // remove all harmful spells on you...
1909 if( // ignore positive and passive auras
1910 !iter
->second
->IsPositive() && !iter
->second
->IsPassive() &&
1911 // ignore physical auras
1912 (GetSpellSchoolMask(iter
->second
->GetSpellProto()) & SPELL_SCHOOL_MASK_NORMAL
)==0 )
1914 m_caster
->RemoveAurasDueToSpell(iter
->second
->GetSpellProto()->Id
);
1915 iter
= Auras
.begin();
1920 // Priest Shadowfiend (34433) need apply mana gain trigger aura on pet
1923 if (Unit
*pet
= m_caster
->GetPet())
1924 pet
->CastSpell(pet
, 28305, true);
1930 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry( triggered_spell_id
);
1934 sLog
.outError("EffectTriggerSpell of spell %u: triggering unknown spell id %i", m_spellInfo
->Id
,triggered_spell_id
);
1938 // some triggered spells require specific equipment
1939 if(spellInfo
->EquippedItemClass
>=0 && m_caster
->GetTypeId()==TYPEID_PLAYER
)
1941 // main hand weapon required
1942 if(spellInfo
->AttributesEx3
& SPELL_ATTR_EX3_MAIN_HAND
)
1944 Item
* item
= ((Player
*)m_caster
)->GetWeaponForAttack(BASE_ATTACK
);
1946 // skip spell if no weapon in slot or broken
1947 if(!item
|| item
->IsBroken() )
1950 // skip spell if weapon not fit to triggered spell
1951 if(!item
->IsFitToSpellRequirements(spellInfo
))
1955 // offhand hand weapon required
1956 if(spellInfo
->AttributesEx3
& SPELL_ATTR_EX3_REQ_OFFHAND
)
1958 Item
* item
= ((Player
*)m_caster
)->GetWeaponForAttack(OFF_ATTACK
);
1960 // skip spell if no weapon in slot or broken
1961 if(!item
|| item
->IsBroken() )
1964 // skip spell if weapon not fit to triggered spell
1965 if(!item
->IsFitToSpellRequirements(spellInfo
))
1970 // some triggered spells must be casted instantly (for example, if next effect case instant kill caster)
1971 bool instant
= false;
1972 for(uint32 j
= i
+1; j
< 3; ++j
)
1974 if(m_spellInfo
->Effect
[j
]==SPELL_EFFECT_INSTAKILL
&& m_spellInfo
->EffectImplicitTargetA
[j
]==TARGET_SELF
)
1984 m_caster
->CastSpell(unitTarget
,spellInfo
,true,m_CastItem
,NULL
,m_originalCasterGUID
);
1987 m_TriggerSpells
.push_back(spellInfo
);
1990 void Spell::EffectTriggerMissileSpell(uint32 effect_idx
)
1992 uint32 triggered_spell_id
= m_spellInfo
->EffectTriggerSpell
[effect_idx
];
1995 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry( triggered_spell_id
);
1999 sLog
.outError("EffectTriggerMissileSpell of spell %u (eff: %u): triggering unknown spell id %u",
2000 m_spellInfo
->Id
,effect_idx
,triggered_spell_id
);
2005 DEBUG_LOG("WORLD: cast Item spellId - %i", spellInfo
->Id
);
2007 m_caster
->CastSpell(m_targets
.m_destX
, m_targets
.m_destY
, m_targets
.m_destZ
, spellInfo
, true, m_CastItem
, 0, m_originalCasterGUID
);
2010 void Spell::EffectTeleportUnits(uint32 i
)
2012 if(!unitTarget
|| unitTarget
->isInFlight())
2015 switch (m_spellInfo
->EffectImplicitTargetB
[i
])
2017 case TARGET_INNKEEPER_COORDINATES
:
2019 // Only players can teleport to innkeeper
2020 if (unitTarget
->GetTypeId() != TYPEID_PLAYER
)
2023 ((Player
*)unitTarget
)->TeleportTo(((Player
*)unitTarget
)->m_homebindMapId
,((Player
*)unitTarget
)->m_homebindX
,((Player
*)unitTarget
)->m_homebindY
,((Player
*)unitTarget
)->m_homebindZ
,unitTarget
->GetOrientation(),unitTarget
==m_caster
? TELE_TO_SPELL
: 0);
2026 case TARGET_TABLE_X_Y_Z_COORDINATES
:
2028 // TODO: Only players can teleport?
2029 if (unitTarget
->GetTypeId() != TYPEID_PLAYER
)
2031 SpellTargetPosition
const* st
= spellmgr
.GetSpellTargetPosition(m_spellInfo
->Id
);
2034 sLog
.outError( "Spell::EffectTeleportUnits - unknown Teleport coordinates for spell ID %u\n", m_spellInfo
->Id
);
2037 ((Player
*)unitTarget
)->TeleportTo(st
->target_mapId
,st
->target_X
,st
->target_Y
,st
->target_Z
,st
->target_Orientation
,unitTarget
==m_caster
? TELE_TO_SPELL
: 0);
2040 case TARGET_BEHIND_VICTIM
:
2042 // Get selected target for player (or victim for units)
2043 Unit
*pTarget
= NULL
;
2044 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
2045 pTarget
= ObjectAccessor::GetUnit(*m_caster
, ((Player
*)m_caster
)->GetSelection());
2047 pTarget
= m_caster
->getVictim();
2048 // No target present - return
2051 // Init dest coordinates
2052 uint32 mapid
= m_caster
->GetMapId();
2053 float x
= m_targets
.m_destX
;
2054 float y
= m_targets
.m_destY
;
2055 float z
= m_targets
.m_destZ
;
2056 float orientation
= pTarget
->GetOrientation();
2058 if(unitTarget
->GetTypeId() == TYPEID_PLAYER
)
2059 ((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));
2062 m_caster
->GetMap()->CreatureRelocation((Creature
*)unitTarget
, x
, y
, z
, orientation
);
2064 unitTarget
->BuildTeleportAckMsg(&data
, x
, y
, z
, orientation
);
2065 unitTarget
->SendMessageToSet(&data
, false);
2071 // If not exist data for dest location - return
2072 if(!(m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
))
2074 sLog
.outError( "Spell::EffectTeleportUnits - unknown EffectImplicitTargetB[%u] = %u for spell ID %u\n", i
, m_spellInfo
->EffectImplicitTargetB
[i
], m_spellInfo
->Id
);
2077 // Init dest coordinates
2078 uint32 mapid
= m_caster
->GetMapId();
2079 float x
= m_targets
.m_destX
;
2080 float y
= m_targets
.m_destY
;
2081 float z
= m_targets
.m_destZ
;
2082 float orientation
= unitTarget
->GetOrientation();
2084 if(unitTarget
->GetTypeId() == TYPEID_PLAYER
)
2085 ((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));
2088 m_caster
->GetMap()->CreatureRelocation((Creature
*)unitTarget
, x
, y
, z
, orientation
);
2090 unitTarget
->BuildTeleportAckMsg(&data
, x
, y
, z
, orientation
);
2091 unitTarget
->SendMessageToSet(&data
, false);
2097 // post effects for TARGET_TABLE_X_Y_Z_COORDINATES
2098 switch ( m_spellInfo
->Id
)
2100 // Dimensional Ripper - Everlook
2103 int32 r
= irand(0, 119);
2104 if ( r
>= 70 ) // 7/12 success
2106 if ( r
< 100 ) // 4/12 evil twin
2107 m_caster
->CastSpell(m_caster
,23445,true);
2109 m_caster
->CastSpell(m_caster
,23449,true);
2113 // Ultrasafe Transporter: Toshley's Station
2116 if ( roll_chance_i(50) ) // 50% success
2118 int32 rand_eff
= urand(1,7);
2122 // soul split - evil
2123 m_caster
->CastSpell(m_caster
,36900,true);
2126 // soul split - good
2127 m_caster
->CastSpell(m_caster
,36901,true);
2130 // Increase the size
2131 m_caster
->CastSpell(m_caster
,36895,true);
2134 // Decrease the size
2135 m_caster
->CastSpell(m_caster
,36893,true);
2140 if (((Player
*)m_caster
)->GetTeam() == ALLIANCE
)
2141 m_caster
->CastSpell(m_caster
,36897,true);
2143 m_caster
->CastSpell(m_caster
,36899,true);
2148 m_caster
->CastSpell(m_caster
,36940,true);
2152 m_caster
->CastSpell(m_caster
,23445,true);
2158 // Dimensional Ripper - Area 52
2161 if ( roll_chance_i(50) ) // 50% success
2163 int32 rand_eff
= urand(1,4);
2167 // soul split - evil
2168 m_caster
->CastSpell(m_caster
,36900,true);
2171 // soul split - good
2172 m_caster
->CastSpell(m_caster
,36901,true);
2175 // Increase the size
2176 m_caster
->CastSpell(m_caster
,36895,true);
2181 if (((Player
*)m_caster
)->GetTeam() == ALLIANCE
)
2182 m_caster
->CastSpell(m_caster
,36897,true);
2184 m_caster
->CastSpell(m_caster
,36899,true);
2194 void Spell::EffectApplyAura(uint32 i
)
2199 // ghost spell check, allow apply any auras at player loading in ghost mode (will be cleanup after load)
2200 if( !unitTarget
->isAlive() && m_spellInfo
->Id
!= 20584 && m_spellInfo
->Id
!= 8326 &&
2201 (unitTarget
->GetTypeId()!=TYPEID_PLAYER
|| !((Player
*)unitTarget
)->GetSession()->PlayerLoading()) )
2204 Unit
* caster
= m_originalCaster
? m_originalCaster
: m_caster
;
2208 sLog
.outDebug("Spell: Aura is: %u", m_spellInfo
->EffectApplyAuraName
[i
]);
2210 Aura
* Aur
= CreateAura(m_spellInfo
, i
, &m_currentBasePoints
[i
], unitTarget
, caster
, m_CastItem
);
2212 // Now Reduce spell duration using data received at spell hit
2213 int32 duration
= Aur
->GetAuraMaxDuration();
2214 unitTarget
->ApplyDiminishingToDuration(m_diminishGroup
,duration
,m_caster
,m_diminishLevel
);
2215 Aur
->setDiminishGroup(m_diminishGroup
);
2217 // if Aura removed and deleted, do not continue.
2218 if(duration
== 0 && !(Aur
->IsPermanent()))
2224 if(duration
!= Aur
->GetAuraMaxDuration())
2226 Aur
->SetAuraMaxDuration(duration
);
2227 Aur
->SetAuraDuration(duration
);
2230 bool added
= unitTarget
->AddAura(Aur
);
2232 // Aura not added and deleted in AddAura call;
2236 // found crash at character loading, broken pointer to Aur...
2237 // Aur was deleted in AddAura()...
2241 // Prayer of Mending (jump animation), we need formal caster instead original for correct animation
2242 if( m_spellInfo
->SpellFamilyName
== SPELLFAMILY_PRIEST
&& (m_spellInfo
->SpellFamilyFlags
& 0x00002000000000LL
))
2243 m_caster
->CastSpell(unitTarget
, 41637, true, NULL
, Aur
, m_originalCasterGUID
);
2246 void Spell::EffectUnlearnSpecialization( uint32 i
)
2248 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
2251 Player
*_player
= (Player
*)unitTarget
;
2252 uint32 spellToUnlearn
= m_spellInfo
->EffectTriggerSpell
[i
];
2254 _player
->removeSpell(spellToUnlearn
);
2256 sLog
.outDebug( "Spell: Player %u have unlearned spell %u from NpcGUID: %u", _player
->GetGUIDLow(), spellToUnlearn
, m_caster
->GetGUIDLow() );
2259 void Spell::EffectPowerDrain(uint32 i
)
2261 if(m_spellInfo
->EffectMiscValue
[i
] < 0 || m_spellInfo
->EffectMiscValue
[i
] >= MAX_POWERS
)
2264 Powers drain_power
= Powers(m_spellInfo
->EffectMiscValue
[i
]);
2268 if(!unitTarget
->isAlive())
2270 if(unitTarget
->getPowerType() != drain_power
)
2275 uint32 curPower
= unitTarget
->GetPower(drain_power
);
2277 //add spell damage bonus
2278 damage
=m_caster
->SpellDamageBonus(unitTarget
,m_spellInfo
,uint32(damage
),SPELL_DIRECT_DAMAGE
);
2280 // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
2281 uint32 power
= damage
;
2282 if ( drain_power
== POWER_MANA
&& unitTarget
->GetTypeId() == TYPEID_PLAYER
)
2283 power
-= ((Player
*)unitTarget
)->GetSpellCritDamageReduction(power
);
2286 if(curPower
< power
)
2287 new_damage
= curPower
;
2291 unitTarget
->ModifyPower(drain_power
,-new_damage
);
2293 // Don`t restore from self drain
2294 if(drain_power
== POWER_MANA
&& m_caster
!= unitTarget
)
2296 float manaMultiplier
= m_spellInfo
->EffectMultipleValue
[i
];
2297 if(manaMultiplier
==0)
2300 if(Player
*modOwner
= m_caster
->GetSpellModOwner())
2301 modOwner
->ApplySpellMod(m_spellInfo
->Id
, SPELLMOD_MULTIPLE_VALUE
, manaMultiplier
);
2303 int32 gain
= int32(new_damage
*manaMultiplier
);
2305 m_caster
->ModifyPower(POWER_MANA
,gain
);
2307 m_caster
->SendEnergizeSpellLog(m_caster
, m_spellInfo
->Id
,gain
,POWER_MANA
);
2311 void Spell::EffectSendEvent(uint32 EffectIndex
)
2313 if (m_caster
->GetTypeId() == TYPEID_PLAYER
&& ((Player
*)m_caster
)->InBattleGround())
2315 BattleGround
* bg
= ((Player
*)m_caster
)->GetBattleGround();
2316 if(bg
&& bg
->GetStatus() == STATUS_IN_PROGRESS
)
2318 switch(m_spellInfo
->Id
)
2320 case 23333: // Pickup Horde Flag
2321 /*do not uncomment .
2322 if(bg->GetTypeID()==BATTLEGROUND_WS)
2323 bg->EventPlayerClickedOnFlag((Player*)m_caster, gameObjTarget);
2324 sLog.outDebug("Send Event Horde Flag Picked Up");
2327 case 23334: // Drop Horde Flag
2328 if(bg->GetTypeID()==BATTLEGROUND_WS)
2329 bg->EventPlayerDroppedFlag((Player*)m_caster);
2330 sLog.outDebug("Drop Horde Flag");
2333 case 23335: // Pickup Alliance Flag
2334 /*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
2335 if(bg->GetTypeID()==BATTLEGROUND_WS)
2336 bg->EventPlayerClickedOnFlag((Player*)m_caster, gameObjTarget);
2337 sLog.outDebug("Send Event Alliance Flag Picked Up");
2340 case 23336: // Drop Alliance Flag
2341 if(bg->GetTypeID()==BATTLEGROUND_WS)
2342 bg->EventPlayerDroppedFlag((Player*)m_caster);
2343 sLog.outDebug("Drop Alliance Flag");
2345 case 23385: // Alliance Flag Returns
2346 if(bg->GetTypeID()==BATTLEGROUND_WS)
2347 bg->EventPlayerClickedOnFlag((Player*)m_caster, gameObjTarget);
2348 sLog.outDebug("Alliance Flag Returned");
2350 case 23386: // Horde Flag Returns
2351 if(bg->GetTypeID()==BATTLEGROUND_WS)
2352 bg->EventPlayerClickedOnFlag((Player*)m_caster, gameObjTarget);
2353 sLog.outDebug("Horde Flag Returned");
2357 if(bg->GetTypeID()==BATTLEGROUND_EY)
2358 bg->EventPlayerClickedOnFlag((Player*)m_caster, gameObjTarget);
2362 sLog
.outDebug("Unknown spellid %u in BG event", m_spellInfo
->Id
);
2367 sLog
.outDebug("Spell ScriptStart %u for spellid %u in EffectSendEvent ", m_spellInfo
->EffectMiscValue
[EffectIndex
], m_spellInfo
->Id
);
2368 sWorld
.ScriptsStart(sEventScripts
, m_spellInfo
->EffectMiscValue
[EffectIndex
], m_caster
, focusObject
);
2371 void Spell::EffectPowerBurn(uint32 i
)
2373 if(m_spellInfo
->EffectMiscValue
[i
] < 0 || m_spellInfo
->EffectMiscValue
[i
] >= MAX_POWERS
)
2376 Powers powertype
= Powers(m_spellInfo
->EffectMiscValue
[i
]);
2380 if(!unitTarget
->isAlive())
2382 if(unitTarget
->getPowerType()!=powertype
)
2387 int32 curPower
= int32(unitTarget
->GetPower(powertype
));
2389 // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
2390 uint32 power
= damage
;
2391 if ( powertype
== POWER_MANA
&& unitTarget
->GetTypeId() == TYPEID_PLAYER
)
2392 power
-= ((Player
*)unitTarget
)->GetSpellCritDamageReduction(power
);
2394 int32 new_damage
= (curPower
< power
) ? curPower
: power
;
2396 unitTarget
->ModifyPower(powertype
,-new_damage
);
2397 float multiplier
= m_spellInfo
->EffectMultipleValue
[i
];
2399 if(Player
*modOwner
= m_caster
->GetSpellModOwner())
2400 modOwner
->ApplySpellMod(m_spellInfo
->Id
, SPELLMOD_MULTIPLE_VALUE
, multiplier
);
2402 new_damage
= int32(new_damage
*multiplier
);
2403 m_damage
+=new_damage
;
2406 void Spell::EffectHeal( uint32
/*i*/ )
2408 if( unitTarget
&& unitTarget
->isAlive() && damage
>= 0)
2410 // Try to get original caster
2411 Unit
*caster
= m_originalCasterGUID
? m_originalCaster
: m_caster
;
2413 // Skip if m_originalCaster not available
2417 int32 addhealth
= damage
;
2419 // Vessel of the Naaru (Vial of the Sunwell trinket)
2420 if (m_spellInfo
->Id
== 45064)
2422 // Amount of heal - depends from stacked Holy Energy
2423 int damageAmount
= 0;
2424 Unit::AuraList
const& mDummyAuras
= m_caster
->GetAurasByType(SPELL_AURA_DUMMY
);
2425 for(Unit::AuraList::const_iterator i
= mDummyAuras
.begin();i
!= mDummyAuras
.end(); ++i
)
2426 if((*i
)->GetId() == 45062)
2427 damageAmount
+=(*i
)->GetModifier()->m_amount
;
2429 m_caster
->RemoveAurasDueToSpell(45062);
2431 addhealth
+= damageAmount
;
2433 // Swiftmend - consumes Regrowth or Rejuvenation
2434 else if (m_spellInfo
->TargetAuraState
== AURA_STATE_SWIFTMEND
&& unitTarget
->HasAuraState(AURA_STATE_SWIFTMEND
))
2436 Unit::AuraList
const& RejorRegr
= unitTarget
->GetAurasByType(SPELL_AURA_PERIODIC_HEAL
);
2437 // find most short by duration
2438 Aura
*targetAura
= NULL
;
2439 for(Unit::AuraList::const_iterator i
= RejorRegr
.begin(); i
!= RejorRegr
.end(); ++i
)
2441 if((*i
)->GetSpellProto()->SpellFamilyName
== SPELLFAMILY_DRUID
2442 && ((*i
)->GetSpellProto()->SpellFamilyFlags
== 0x40 || (*i
)->GetSpellProto()->SpellFamilyFlags
== 0x10) )
2444 if(!targetAura
|| (*i
)->GetAuraDuration() < targetAura
->GetAuraDuration())
2451 sLog
.outError("Target(GUID:" I64FMTD
") has aurastate AURA_STATE_SWIFTMEND but no matching aura.", unitTarget
->GetGUID());
2457 if(targetAura
->GetSpellProto()->EffectApplyAuraName
[idx
] == SPELL_AURA_PERIODIC_HEAL
)
2462 int32 tickheal
= caster
->SpellHealingBonus(unitTarget
, targetAura
->GetSpellProto(), targetAura
->GetModifier()->m_amount
, DOT
);
2463 int32 tickcount
= GetSpellDuration(targetAura
->GetSpellProto()) / targetAura
->GetSpellProto()->EffectAmplitude
[idx
];
2464 unitTarget
->RemoveAurasDueToSpell(targetAura
->GetId());
2466 addhealth
+= tickheal
* tickcount
;
2469 addhealth
= caster
->SpellHealingBonus(unitTarget
, m_spellInfo
, addhealth
, HEAL
);
2471 m_healing
+=addhealth
;
2475 void Spell::EffectHealPct( uint32
/*i*/ )
2477 if( unitTarget
&& unitTarget
->isAlive() && damage
>= 0)
2479 // Try to get original caster
2480 Unit
*caster
= m_originalCasterGUID
? m_originalCaster
: m_caster
;
2482 // Skip if m_originalCaster not available
2486 uint32 addhealth
= unitTarget
->GetMaxHealth() * damage
/ 100;
2487 caster
->SendHealSpellLog(unitTarget
, m_spellInfo
->Id
, addhealth
, false);
2489 int32 gain
= unitTarget
->ModifyHealth( int32(addhealth
) );
2490 unitTarget
->getHostilRefManager().threatAssist(m_caster
, float(gain
) * 0.5f
, m_spellInfo
);
2492 if(caster
->GetTypeId()==TYPEID_PLAYER
)
2493 if(BattleGround
*bg
= ((Player
*)caster
)->GetBattleGround())
2494 bg
->UpdatePlayerScore(((Player
*)caster
), SCORE_HEALING_DONE
, gain
);
2498 void Spell::EffectHealMechanical( uint32
/*i*/ )
2500 // Mechanic creature type should be correctly checked by targetCreatureType field
2501 if( unitTarget
&& unitTarget
->isAlive() && damage
>= 0)
2503 // Try to get original caster
2504 Unit
*caster
= m_originalCasterGUID
? m_originalCaster
: m_caster
;
2506 // Skip if m_originalCaster not available
2510 uint32 addhealth
= caster
->SpellHealingBonus(unitTarget
, m_spellInfo
, uint32(damage
), HEAL
);
2511 caster
->SendHealSpellLog(unitTarget
, m_spellInfo
->Id
, addhealth
, false);
2512 unitTarget
->ModifyHealth( int32(damage
) );
2516 void Spell::EffectHealthLeech(uint32 i
)
2520 if(!unitTarget
->isAlive())
2526 sLog
.outDebug("HealthLeech :%i", damage
);
2528 float multiplier
= m_spellInfo
->EffectMultipleValue
[i
];
2530 if(Player
*modOwner
= m_caster
->GetSpellModOwner())
2531 modOwner
->ApplySpellMod(m_spellInfo
->Id
, SPELLMOD_MULTIPLE_VALUE
, multiplier
);
2533 int32 new_damage
= int32(damage
*multiplier
);
2534 uint32 curHealth
= unitTarget
->GetHealth();
2535 new_damage
= m_caster
->SpellNonMeleeDamageLog(unitTarget
, m_spellInfo
->Id
, new_damage
, m_IsTriggeredSpell
, true);
2536 if(curHealth
< new_damage
)
2537 new_damage
= curHealth
;
2539 if(m_caster
->isAlive())
2541 new_damage
= m_caster
->SpellHealingBonus(m_caster
, m_spellInfo
, new_damage
, HEAL
);
2543 m_caster
->ModifyHealth(new_damage
);
2545 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
2546 m_caster
->SendHealSpellLog(m_caster
, m_spellInfo
->Id
, uint32(new_damage
));
2548 // m_healthLeech+=tmpvalue;
2549 // m_damage+=new_damage;
2552 void Spell::DoCreateItem(uint32 i
, uint32 itemtype
)
2554 if (!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
2557 Player
* player
= (Player
*)unitTarget
;
2559 uint32 newitemid
= itemtype
;
2560 ItemPrototype
const *pProto
= objmgr
.GetItemPrototype( newitemid
);
2563 player
->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND
, NULL
, NULL
);
2569 // TODO: maybe all this can be replaced by using correct calculated `damage` value
2570 if(pProto
->Class
!= ITEM_CLASS_CONSUMABLE
|| m_spellInfo
->SpellFamilyName
!= SPELLFAMILY_MAGE
)
2572 int32 basePoints
= m_currentBasePoints
[i
];
2573 int32 randomPoints
= m_spellInfo
->EffectDieSides
[i
];
2575 num_to_add
= basePoints
+ irand(1, randomPoints
);
2577 num_to_add
= basePoints
+ 1;
2579 else if (pProto
->MaxCount
== 1)
2581 else if(player
->getLevel() >= m_spellInfo
->spellLevel
)
2583 int32 basePoints
= m_currentBasePoints
[i
];
2584 float pointPerLevel
= m_spellInfo
->EffectRealPointsPerLevel
[i
];
2585 num_to_add
= basePoints
+ 1 + uint32((player
->getLevel() - m_spellInfo
->spellLevel
)*pointPerLevel
);
2592 if (num_to_add
> pProto
->GetMaxStackSize())
2593 num_to_add
= pProto
->GetMaxStackSize();
2595 // init items_count to 1, since 1 item will be created regardless of specialization
2597 // the chance to create additional items
2598 float additionalCreateChance
=0.0f
;
2599 // the maximum number of created additional items
2600 uint8 additionalMaxNum
=0;
2601 // get the chance and maximum number for creating extra items
2602 if ( canCreateExtraItems(player
, m_spellInfo
->Id
, additionalCreateChance
, additionalMaxNum
) )
2604 // roll with this chance till we roll not to create or we create the max num
2605 while ( roll_chance_f(additionalCreateChance
) && items_count
<=additionalMaxNum
)
2609 // really will be created more items
2610 num_to_add
*= items_count
;
2612 // can the player store the new item?
2613 ItemPosCountVec dest
;
2614 uint32 no_space
= 0;
2615 uint8 msg
= player
->CanStoreNewItem( NULL_BAG
, NULL_SLOT
, dest
, newitemid
, num_to_add
, &no_space
);
2616 if( msg
!= EQUIP_ERR_OK
)
2618 // convert to possible store amount
2619 if( msg
== EQUIP_ERR_INVENTORY_FULL
|| msg
== EQUIP_ERR_CANT_CARRY_MORE_OF_THIS
)
2620 num_to_add
-= no_space
;
2623 // if not created by another reason from full inventory or unique items amount limitation
2624 player
->SendEquipError( msg
, NULL
, NULL
);
2631 // create the new item and store it
2632 Item
* pItem
= player
->StoreNewItem( dest
, newitemid
, true, Item::GenerateItemRandomPropertyId(newitemid
));
2634 // was it successful? return error if not
2637 player
->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND
, NULL
, NULL
);
2641 // set the "Crafted by ..." property of the item
2642 if( pItem
->GetProto()->Class
!= ITEM_CLASS_CONSUMABLE
&& pItem
->GetProto()->Class
!= ITEM_CLASS_QUEST
)
2643 pItem
->SetUInt32Value(ITEM_FIELD_CREATOR
,player
->GetGUIDLow());
2645 // send info to the client
2647 player
->SendNewItem(pItem
, num_to_add
, true, true);
2649 // we succeeded in creating at least one item, so a levelup is possible
2650 player
->UpdateCraftSkill(m_spellInfo
->Id
);
2653 // for battleground marks send by mail if not add all expected
2656 BattleGroundTypeId bgType
;
2657 switch(m_spellInfo
->Id
)
2659 case SPELL_AV_MARK_WINNER
:
2660 case SPELL_AV_MARK_LOSER
:
2661 bgType
= BATTLEGROUND_AV
;
2663 case SPELL_WS_MARK_WINNER
:
2664 case SPELL_WS_MARK_LOSER
:
2665 bgType
= BATTLEGROUND_WS
;
2667 case SPELL_AB_MARK_WINNER
:
2668 case SPELL_AB_MARK_LOSER
:
2669 bgType
= BATTLEGROUND_AB
;
2675 if(BattleGround
* bg
= sBattleGroundMgr
.GetBattleGroundTemplate(bgType
))
2676 bg
->SendRewardMarkByMail(player
,newitemid
,no_space
);
2680 void Spell::EffectCreateItem(uint32 i
)
2682 DoCreateItem(i
,m_spellInfo
->EffectItemType
[i
]);
2685 void Spell::EffectCreateItem2(uint32 i
)
2687 // special case: generate using spell_loot_template
2688 if(!m_spellInfo
->EffectItemType
[i
])
2690 if(m_caster
->GetTypeId()!=TYPEID_PLAYER
)
2693 // create some random items
2694 ((Player
*)m_caster
)->AutoStoreLootItem(m_spellInfo
->Id
,LootTemplates_Spell
);
2697 DoCreateItem(i
,m_spellInfo
->EffectItemType
[i
]);
2700 void Spell::EffectPersistentAA(uint32 i
)
2702 float radius
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[i
]));
2704 if(Player
* modOwner
= m_caster
->GetSpellModOwner())
2705 modOwner
->ApplySpellMod(m_spellInfo
->Id
, SPELLMOD_RADIUS
, radius
);
2707 int32 duration
= GetSpellDuration(m_spellInfo
);
2708 DynamicObject
* dynObj
= new DynamicObject
;
2709 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
))
2714 dynObj
->SetUInt32Value(OBJECT_FIELD_TYPE
, 65);
2715 dynObj
->SetUInt32Value(GAMEOBJECT_DISPLAYID
, 368003);
2716 dynObj
->SetUInt32Value(DYNAMICOBJECT_BYTES
, 0x01eeeeee);
2717 m_caster
->AddDynObject(dynObj
);
2718 dynObj
->GetMap()->Add(dynObj
);
2721 void Spell::EffectEnergize(uint32 i
)
2725 if(!unitTarget
->isAlive())
2728 if(m_spellInfo
->EffectMiscValue
[i
] < 0 || m_spellInfo
->EffectMiscValue
[i
] >= MAX_POWERS
)
2731 Powers power
= Powers(m_spellInfo
->EffectMiscValue
[i
]);
2733 // Some level depends spells
2736 switch (m_spellInfo
->Id
)
2740 level_diff
= m_caster
->getLevel() - 40;
2745 level_diff
= m_caster
->getLevel() - 60;
2750 level_diff
= m_caster
->getLevel() - 60;
2758 damage
-= multiplier
* level_diff
;
2763 if(unitTarget
->GetMaxPower(power
) == 0)
2766 unitTarget
->ModifyPower(power
,damage
);
2767 m_caster
->SendEnergizeSpellLog(unitTarget
, m_spellInfo
->Id
, damage
, power
);
2769 // Mad Alchemist's Potion
2770 if (m_spellInfo
->Id
== 45051)
2772 // find elixirs on target
2773 uint32 elixir_mask
= 0;
2774 Unit::AuraMap
& Auras
= unitTarget
->GetAuras();
2775 for(Unit::AuraMap::iterator itr
= Auras
.begin(); itr
!= Auras
.end(); ++itr
)
2777 uint32 spell_id
= itr
->second
->GetId();
2778 if(uint32 mask
= spellmgr
.GetSpellElixirMask(spell_id
))
2779 elixir_mask
|= mask
;
2782 // get available elixir mask any not active type from battle/guardian (and flask if no any)
2783 elixir_mask
= (elixir_mask
& ELIXIR_FLASK_MASK
) ^ ELIXIR_FLASK_MASK
;
2785 // get all available elixirs by mask and spell level
2786 std::vector
<uint32
> elixirs
;
2787 SpellElixirMap
const& m_spellElixirs
= spellmgr
.GetSpellElixirMap();
2788 for(SpellElixirMap::const_iterator itr
= m_spellElixirs
.begin(); itr
!= m_spellElixirs
.end(); ++itr
)
2790 if (itr
->second
& elixir_mask
)
2792 if (itr
->second
& (ELIXIR_UNSTABLE_MASK
| ELIXIR_SHATTRATH_MASK
))
2795 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(itr
->first
);
2796 if (spellInfo
&& (spellInfo
->spellLevel
< m_spellInfo
->spellLevel
|| spellInfo
->spellLevel
> unitTarget
->getLevel()))
2799 elixirs
.push_back(itr
->first
);
2803 if (!elixirs
.empty())
2805 // cast random elixir on target
2806 uint32 rand_spell
= urand(0,elixirs
.size()-1);
2807 m_caster
->CastSpell(unitTarget
,elixirs
[rand_spell
],true,m_CastItem
);
2812 void Spell::EffectEnergisePct(uint32 i
)
2816 if(!unitTarget
->isAlive())
2819 if(m_spellInfo
->EffectMiscValue
[i
] < 0 || m_spellInfo
->EffectMiscValue
[i
] >= MAX_POWERS
)
2822 Powers power
= Powers(m_spellInfo
->EffectMiscValue
[i
]);
2824 uint32 maxPower
= unitTarget
->GetMaxPower(power
);
2828 uint32 gain
= damage
* maxPower
/ 100;
2829 unitTarget
->ModifyPower(power
, gain
);
2830 m_caster
->SendEnergizeSpellLog(unitTarget
, m_spellInfo
->Id
, gain
, power
);
2833 void Spell::SendLoot(uint64 guid
, LootType loottype
)
2835 Player
* player
= (Player
*)m_caster
;
2841 if (Script
->GOHello(player
, gameObjTarget
))
2844 switch (gameObjTarget
->GetGoType())
2846 case GAMEOBJECT_TYPE_DOOR
:
2847 case GAMEOBJECT_TYPE_BUTTON
:
2848 gameObjTarget
->UseDoorOrButton();
2849 sWorld
.ScriptsStart(sGameObjectScripts
, gameObjTarget
->GetDBTableGUIDLow(), player
, gameObjTarget
);
2852 case GAMEOBJECT_TYPE_QUESTGIVER
:
2853 // start or end quest
2854 player
->PrepareQuestMenu(guid
);
2855 player
->SendPreparedQuest(guid
);
2858 case GAMEOBJECT_TYPE_SPELL_FOCUS
:
2859 // triggering linked GO
2860 if(uint32 trapEntry
= gameObjTarget
->GetGOInfo()->spellFocus
.linkedTrapId
)
2861 gameObjTarget
->TriggeringLinkedGameObject(trapEntry
,m_caster
);
2864 case GAMEOBJECT_TYPE_GOOBER
:
2865 // goober_scripts can be triggered if the player don't have the quest
2866 if (gameObjTarget
->GetGOInfo()->goober
.eventId
)
2868 sLog
.outDebug("Goober ScriptStart id %u for GO %u", gameObjTarget
->GetGOInfo()->goober
.eventId
,gameObjTarget
->GetDBTableGUIDLow());
2869 sWorld
.ScriptsStart(sEventScripts
, gameObjTarget
->GetGOInfo()->goober
.eventId
, player
, gameObjTarget
);
2872 // cast goober spell
2873 if (gameObjTarget
->GetGOInfo()->goober
.questId
)
2874 ///Quest require to be active for GO using
2875 if(player
->GetQuestStatus(gameObjTarget
->GetGOInfo()->goober
.questId
) != QUEST_STATUS_INCOMPLETE
)
2878 gameObjTarget
->AddUniqueUse(player
);
2879 gameObjTarget
->SetLootState(GO_JUST_DEACTIVATED
);
2881 //TODO? Objective counting called without spell check but with quest objective check
2882 // if send spell id then this line will duplicate to spell casting call (double counting)
2883 // So we or have this line and not required in quest_template have reqSpellIdN
2884 // or must remove this line and required in DB have data in quest_template have reqSpellIdN for all quest using cases.
2885 player
->CastedCreatureOrGO(gameObjTarget
->GetEntry(), gameObjTarget
->GetGUID(), 0);
2887 // triggering linked GO
2888 if(uint32 trapEntry
= gameObjTarget
->GetGOInfo()->goober
.linkedTrapId
)
2889 gameObjTarget
->TriggeringLinkedGameObject(trapEntry
,m_caster
);
2893 case GAMEOBJECT_TYPE_CHEST
:
2894 // TODO: possible must be moved to loot release (in different from linked triggering)
2895 if (gameObjTarget
->GetGOInfo()->chest
.eventId
)
2897 sLog
.outDebug("Chest ScriptStart id %u for GO %u", gameObjTarget
->GetGOInfo()->chest
.eventId
,gameObjTarget
->GetDBTableGUIDLow());
2898 sWorld
.ScriptsStart(sEventScripts
, gameObjTarget
->GetGOInfo()->chest
.eventId
, player
, gameObjTarget
);
2901 // triggering linked GO
2902 if(uint32 trapEntry
= gameObjTarget
->GetGOInfo()->chest
.linkedTrapId
)
2903 gameObjTarget
->TriggeringLinkedGameObject(trapEntry
,m_caster
);
2905 // Don't return, let loots been taken
2910 player
->SendLoot(guid
, loottype
);
2913 void Spell::EffectOpenLock(uint32
/*i*/)
2915 if(!m_caster
|| m_caster
->GetTypeId() != TYPEID_PLAYER
)
2917 sLog
.outDebug( "WORLD: Open Lock - No Player Caster!");
2921 Player
* player
= (Player
*)m_caster
;
2923 LootType loottype
= LOOT_CORPSE
;
2930 GameObjectInfo
const* goInfo
= gameObjTarget
->GetGOInfo();
2931 // Arathi Basin banner opening !
2932 if( goInfo
->type
== GAMEOBJECT_TYPE_BUTTON
&& goInfo
->button
.noDamageImmune
||
2933 goInfo
->type
== GAMEOBJECT_TYPE_GOOBER
&& goInfo
->goober
.losOK
)
2935 //isAllowUseBattleGroundObject() already called in CanCast()
2936 // in battleground check
2937 if(BattleGround
*bg
= player
->GetBattleGround())
2939 // check if it's correct bg
2940 if(bg
&& bg
->GetTypeID() == BATTLEGROUND_AB
)
2941 bg
->EventPlayerClickedOnFlag(player
, gameObjTarget
);
2945 else if (goInfo
->type
== GAMEOBJECT_TYPE_FLAGSTAND
)
2947 //isAllowUseBattleGroundObject() already called in CanCast()
2948 // in battleground check
2949 if(BattleGround
*bg
= player
->GetBattleGround())
2951 if(bg
->GetTypeID() == BATTLEGROUND_EY
)
2952 bg
->EventPlayerClickedOnFlag(player
, gameObjTarget
);
2956 lockId
= gameObjTarget
->GetLockId();
2957 guid
= gameObjTarget
->GetGUID();
2961 lockId
= itemTarget
->GetProto()->LockID
;
2962 guid
= itemTarget
->GetGUID();
2966 sLog
.outDebug( "WORLD: Open Lock - No GameObject/Item Target!");
2970 if(!lockId
) // possible case for GO and maybe for items.
2972 SendLoot(guid
, loottype
);
2977 LockEntry
const *lockInfo
= sLockStore
.LookupEntry(lockId
);
2981 sLog
.outError( "Spell::EffectOpenLock: %s [guid = %u] has an unknown lockId: %u!",
2982 (gameObjTarget
? "gameobject" : "item"), GUID_LOPART(guid
), lockId
);
2983 SendCastResult(SPELL_FAILED_BAD_TARGETS
);
2988 for(int i
= 0; i
< 8; ++i
)
2990 // Type==1 This means lockInfo->Index[i] is an item
2991 if(lockInfo
->Type
[i
]==LOCK_KEY_ITEM
&& lockInfo
->Index
[i
] && m_CastItem
&& m_CastItem
->GetEntry()==lockInfo
->Index
[i
])
2993 SendLoot(guid
, loottype
);
2999 // Check and skill-up skill
3000 if( m_spellInfo
->Effect
[1] == SPELL_EFFECT_SKILL
)
3001 SkillId
= m_spellInfo
->EffectMiscValue
[1];
3002 // pickpocketing spells
3003 else if( m_spellInfo
->EffectMiscValue
[0] == LOCKTYPE_PICKLOCK
)
3004 SkillId
= SKILL_LOCKPICKING
;
3006 // skill bonus provided by casting spell (mostly item spells)
3007 uint32 spellSkillBonus
= uint32(m_currentBasePoints
[0]+1);
3009 uint32 reqSkillValue
= lockInfo
->Skill
[0];
3011 if(lockInfo
->Skill
[1]) // required pick lock skill applying
3013 if(SkillId
!= SKILL_LOCKPICKING
) // wrong skill (cheating?)
3015 SendCastResult(SPELL_FAILED_FIZZLE
);
3019 reqSkillValue
= lockInfo
->Skill
[1];
3021 else if(SkillId
== SKILL_LOCKPICKING
) // apply picklock skill to wrong target
3023 SendCastResult(SPELL_FAILED_BAD_TARGETS
);
3029 loottype
= LOOT_SKINNING
;
3030 if ( player
->GetSkillValue(SkillId
) + spellSkillBonus
< reqSkillValue
)
3032 SendCastResult(SPELL_FAILED_LOW_CASTLEVEL
);
3036 // update skill if really known
3037 uint32 SkillValue
= player
->GetPureSkillValue(SkillId
);
3038 if(SkillValue
) // non only item base skill
3042 // Allow one skill-up until respawned
3043 if ( !gameObjTarget
->IsInSkillupList( player
->GetGUIDLow() ) &&
3044 player
->UpdateGatherSkill(SkillId
, SkillValue
, reqSkillValue
) )
3045 gameObjTarget
->AddToSkillupList( player
->GetGUIDLow() );
3050 uint32 SkillValue
= player
->GetPureSkillValue(SkillId
);
3051 player
->UpdateGatherSkill(SkillId
, SkillValue
, reqSkillValue
);
3056 SendLoot(guid
, loottype
);
3059 void Spell::EffectSummonChangeItem(uint32 i
)
3061 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
3064 Player
*player
= (Player
*)m_caster
;
3066 // applied only to using item
3070 // ... only to item in own inventory/bank/equip_slot
3071 if(m_CastItem
->GetOwnerGUID()!=player
->GetGUID())
3074 uint32 newitemid
= m_spellInfo
->EffectItemType
[i
];
3078 uint16 pos
= m_CastItem
->GetPos();
3080 Item
*pNewItem
= Item::CreateItem( newitemid
, 1, player
);
3084 for(uint8 i
= PERM_ENCHANTMENT_SLOT
; i
<=TEMP_ENCHANTMENT_SLOT
; ++i
)
3086 if(m_CastItem
->GetEnchantmentId(EnchantmentSlot(i
)))
3087 pNewItem
->SetEnchantment(EnchantmentSlot(i
), m_CastItem
->GetEnchantmentId(EnchantmentSlot(i
)), m_CastItem
->GetEnchantmentDuration(EnchantmentSlot(i
)), m_CastItem
->GetEnchantmentCharges(EnchantmentSlot(i
)));
3090 if(m_CastItem
->GetUInt32Value(ITEM_FIELD_DURABILITY
) < m_CastItem
->GetUInt32Value(ITEM_FIELD_MAXDURABILITY
))
3092 double loosePercent
= 1 - m_CastItem
->GetUInt32Value(ITEM_FIELD_DURABILITY
) / double(m_CastItem
->GetUInt32Value(ITEM_FIELD_MAXDURABILITY
));
3093 player
->DurabilityLoss(pNewItem
, loosePercent
);
3096 if( player
->IsInventoryPos( pos
) )
3098 ItemPosCountVec dest
;
3099 uint8 msg
= player
->CanStoreItem( m_CastItem
->GetBagSlot(), m_CastItem
->GetSlot(), dest
, pNewItem
, true );
3100 if( msg
== EQUIP_ERR_OK
)
3102 player
->DestroyItem(m_CastItem
->GetBagSlot(), m_CastItem
->GetSlot(),true);
3104 // prevent crash at access and unexpected charges counting with item update queue corrupt
3105 if(m_CastItem
==m_targets
.getItemTarget())
3106 m_targets
.setItemTarget(NULL
);
3110 player
->StoreItem( dest
, pNewItem
, true);
3114 else if( player
->IsBankPos ( pos
) )
3116 ItemPosCountVec dest
;
3117 uint8 msg
= player
->CanBankItem( m_CastItem
->GetBagSlot(), m_CastItem
->GetSlot(), dest
, pNewItem
, true );
3118 if( msg
== EQUIP_ERR_OK
)
3120 player
->DestroyItem(m_CastItem
->GetBagSlot(), m_CastItem
->GetSlot(),true);
3122 // prevent crash at access and unexpected charges counting with item update queue corrupt
3123 if(m_CastItem
==m_targets
.getItemTarget())
3124 m_targets
.setItemTarget(NULL
);
3128 player
->BankItem( dest
, pNewItem
, true);
3132 else if( player
->IsEquipmentPos ( pos
) )
3135 uint8 msg
= player
->CanEquipItem( m_CastItem
->GetSlot(), dest
, pNewItem
, true );
3136 if( msg
== EQUIP_ERR_OK
)
3138 player
->DestroyItem(m_CastItem
->GetBagSlot(), m_CastItem
->GetSlot(),true);
3140 // prevent crash at access and unexpected charges counting with item update queue corrupt
3141 if(m_CastItem
==m_targets
.getItemTarget())
3142 m_targets
.setItemTarget(NULL
);
3146 player
->EquipItem( dest
, pNewItem
, true);
3147 player
->AutoUnequipOffhandIfNeed();
3156 void Spell::EffectOpenSecretSafe(uint32 i
)
3158 EffectOpenLock(i
); //no difference for now
3161 void Spell::EffectProficiency(uint32
/*i*/)
3163 if (!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
3165 Player
*p_target
= (Player
*)unitTarget
;
3167 uint32 subClassMask
= m_spellInfo
->EquippedItemSubClassMask
;
3168 if(m_spellInfo
->EquippedItemClass
== 2 && !(p_target
->GetWeaponProficiency() & subClassMask
))
3170 p_target
->AddWeaponProficiency(subClassMask
);
3171 p_target
->SendProficiency(uint8(0x02),p_target
->GetWeaponProficiency());
3173 if(m_spellInfo
->EquippedItemClass
== 4 && !(p_target
->GetArmorProficiency() & subClassMask
))
3175 p_target
->AddArmorProficiency(subClassMask
);
3176 p_target
->SendProficiency(uint8(0x04),p_target
->GetArmorProficiency());
3180 void Spell::EffectApplyAreaAura(uint32 i
)
3184 if(!unitTarget
->isAlive())
3187 AreaAura
* Aur
= new AreaAura(m_spellInfo
, i
, &m_currentBasePoints
[i
], unitTarget
, m_caster
, m_CastItem
);
3188 unitTarget
->AddAura(Aur
);
3191 void Spell::EffectSummonType(uint32 i
)
3193 switch(m_spellInfo
->EffectMiscValueB
[i
])
3195 case SUMMON_TYPE_GUARDIAN
:
3196 case SUMMON_TYPE_POSESSED
:
3197 case SUMMON_TYPE_POSESSED2
:
3198 case SUMMON_TYPE_FORCE_OF_NATURE
:
3199 case SUMMON_TYPE_GUARDIAN2
:
3200 EffectSummonGuardian(i
);
3202 case SUMMON_TYPE_WILD
:
3203 EffectSummonWild(i
);
3205 case SUMMON_TYPE_DEMON
:
3206 EffectSummonDemon(i
);
3208 case SUMMON_TYPE_SUMMON
:
3211 case SUMMON_TYPE_CRITTER
:
3212 case SUMMON_TYPE_CRITTER2
:
3213 case SUMMON_TYPE_CRITTER3
:
3214 EffectSummonCritter(i
);
3216 case SUMMON_TYPE_TOTEM_SLOT1
:
3217 case SUMMON_TYPE_TOTEM_SLOT2
:
3218 case SUMMON_TYPE_TOTEM_SLOT3
:
3219 case SUMMON_TYPE_TOTEM_SLOT4
:
3220 case SUMMON_TYPE_TOTEM
:
3221 EffectSummonTotem(i
);
3223 case SUMMON_TYPE_UNKNOWN1
:
3224 case SUMMON_TYPE_UNKNOWN2
:
3225 case SUMMON_TYPE_UNKNOWN3
:
3226 case SUMMON_TYPE_UNKNOWN4
:
3227 case SUMMON_TYPE_UNKNOWN5
:
3230 sLog
.outError("EffectSummonType: Unhandled summon type %u", m_spellInfo
->EffectMiscValueB
[i
]);
3235 void Spell::EffectSummon(uint32 i
)
3237 if(m_caster
->GetPetGUID())
3242 uint32 pet_entry
= m_spellInfo
->EffectMiscValue
[i
];
3245 uint32 level
= m_caster
->getLevel();
3246 Pet
* spawnCreature
= new Pet(SUMMON_PET
);
3248 if(m_caster
->GetTypeId()==TYPEID_PLAYER
&& spawnCreature
->LoadPetFromDB((Player
*)m_caster
,pet_entry
))
3250 // set timer for unsummon
3251 int32 duration
= GetSpellDuration(m_spellInfo
);
3253 spawnCreature
->SetDuration(duration
);
3258 Map
*map
= m_caster
->GetMap();
3259 uint32 pet_number
= objmgr
.GeneratePetNumber();
3260 if(!spawnCreature
->Create(objmgr
.GenerateLowGuid(HIGHGUID_PET
),map
,m_caster
->GetPhaseMask(),
3261 m_spellInfo
->EffectMiscValue
[i
], pet_number
))
3263 sLog
.outErrorDb("Spell::EffectSummon: no such creature entry %u",m_spellInfo
->EffectMiscValue
[i
]);
3264 delete spawnCreature
;
3268 // Summon in dest location
3270 if(m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
3272 x
= m_targets
.m_destX
;
3273 y
= m_targets
.m_destY
;
3274 z
= m_targets
.m_destZ
;
3277 m_caster
->GetClosePoint(x
,y
,z
,spawnCreature
->GetObjectSize());
3279 spawnCreature
->Relocate(x
,y
,z
,-m_caster
->GetOrientation());
3281 if(!spawnCreature
->IsPositionValid())
3283 sLog
.outError("ERROR: Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)",
3284 spawnCreature
->GetGUIDLow(), spawnCreature
->GetEntry(), spawnCreature
->GetPositionX(), spawnCreature
->GetPositionY());
3285 delete spawnCreature
;
3289 // set timer for unsummon
3290 int32 duration
= GetSpellDuration(m_spellInfo
);
3292 spawnCreature
->SetDuration(duration
);
3294 spawnCreature
->SetOwnerGUID(m_caster
->GetGUID());
3295 spawnCreature
->SetUInt32Value(UNIT_NPC_FLAGS
, 0);
3296 spawnCreature
->setPowerType(POWER_MANA
);
3297 spawnCreature
->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE
, m_caster
->getFaction());
3298 spawnCreature
->SetUInt32Value(UNIT_FIELD_FLAGS
, 0);
3299 spawnCreature
->SetUInt32Value(UNIT_FIELD_BYTES_0
, 2048);
3300 spawnCreature
->SetUInt32Value(UNIT_FIELD_BYTES_1
, 0);
3301 spawnCreature
->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP
, 0);
3302 spawnCreature
->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE
, 0);
3303 spawnCreature
->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP
, 1000);
3304 spawnCreature
->SetCreatorGUID(m_caster
->GetGUID());
3305 spawnCreature
->SetUInt32Value(UNIT_CREATED_BY_SPELL
, m_spellInfo
->Id
);
3307 spawnCreature
->InitStatsForLevel(level
);
3309 spawnCreature
->GetCharmInfo()->SetPetNumber(pet_number
, false);
3311 spawnCreature
->AIM_Initialize();
3312 spawnCreature
->InitPetCreateSpells();
3313 spawnCreature
->SetHealth(spawnCreature
->GetMaxHealth());
3314 spawnCreature
->SetPower(POWER_MANA
, spawnCreature
->GetMaxPower(POWER_MANA
));
3316 std::string name
= m_caster
->GetName();
3317 name
.append(petTypeSuffix
[spawnCreature
->getPetType()]);
3318 spawnCreature
->SetName( name
);
3320 map
->Add((Creature
*)spawnCreature
);
3322 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
3324 m_caster
->SetPet(spawnCreature
);
3325 spawnCreature
->GetCharmInfo()->SetReactState( REACT_DEFENSIVE
);
3326 spawnCreature
->SavePetToDB(PET_SAVE_AS_CURRENT
);
3327 ((Player
*)m_caster
)->PetSpellInitialize();
3331 void Spell::EffectLearnSpell(uint32 i
)
3336 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
3338 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
3339 EffectLearnPetSpell(i
);
3344 Player
*player
= (Player
*)unitTarget
;
3346 uint32 spellToLearn
= ((m_spellInfo
->Id
==SPELL_ID_GENERIC_LEARN
) || (m_spellInfo
->Id
==SPELL_ID_GENERIC_LEARN_PET
)) ? damage
: m_spellInfo
->EffectTriggerSpell
[i
];
3347 player
->learnSpell(spellToLearn
,false);
3349 sLog
.outDebug( "Spell: Player %u have learned spell %u from NpcGUID=%u", player
->GetGUIDLow(), spellToLearn
, m_caster
->GetGUIDLow() );
3352 void Spell::EffectDispel(uint32 i
)
3357 // Fill possible dispell list
3358 std::vector
<Aura
*> dispel_list
;
3360 // Create dispel mask by dispel type
3361 uint32 dispel_type
= m_spellInfo
->EffectMiscValue
[i
];
3362 uint32 dispelMask
= GetDispellMask( DispelType(dispel_type
) );
3363 Unit::AuraMap
const& auras
= unitTarget
->GetAuras();
3364 for(Unit::AuraMap::const_iterator itr
= auras
.begin(); itr
!= auras
.end(); ++itr
)
3366 Aura
*aur
= (*itr
).second
;
3367 if (aur
&& (1<<aur
->GetSpellProto()->Dispel
) & dispelMask
)
3369 if(aur
->GetSpellProto()->Dispel
== DISPEL_MAGIC
)
3371 bool positive
= true;
3372 if (!aur
->IsPositive())
3375 positive
= (aur
->GetSpellProto()->AttributesEx
& SPELL_ATTR_EX_NEGATIVE
)==0;
3377 // do not remove positive auras if friendly target
3378 // negative auras if non-friendly target
3379 if(positive
== unitTarget
->IsFriendlyTo(m_caster
))
3382 // Add aura to dispel list
3383 dispel_list
.push_back(aur
);
3386 // Ok if exist some buffs for dispel try dispel it
3387 if (!dispel_list
.empty())
3389 std::list
< std::pair
<uint32
,uint64
> > success_list
;// (spell_id,casterGuid)
3390 std::list
< uint32
> fail_list
; // spell_id
3391 int32 list_size
= dispel_list
.size();
3392 // Dispell N = damage buffs (or while exist buffs for dispel)
3393 for (int32 count
=0; count
< damage
&& list_size
> 0; ++count
)
3395 // Random select buff for dispel
3396 Aura
*aur
= dispel_list
[urand(0, list_size
-1)];
3398 SpellEntry
const* spellInfo
= aur
->GetSpellProto();
3399 // Base dispel chance
3400 // TODO: possible chance depend from spell level??
3401 int32 miss_chance
= 0;
3402 // Apply dispel mod from aura caster
3403 if (Unit
*caster
= aur
->GetCaster())
3405 if ( Player
* modOwner
= caster
->GetSpellModOwner() )
3406 modOwner
->ApplySpellMod(spellInfo
->Id
, SPELLMOD_RESIST_DISPEL_CHANCE
, miss_chance
, this);
3409 if (roll_chance_i(miss_chance
))
3410 fail_list
.push_back(aur
->GetId());
3412 success_list
.push_back(std::pair
<uint32
,uint64
>(aur
->GetId(),aur
->GetCasterGUID()));
3413 // Remove buff from list for prevent doubles
3414 for (std::vector
<Aura
*>::iterator j
= dispel_list
.begin(); j
!= dispel_list
.end(); )
3416 Aura
*dispeled
= *j
;
3417 if (dispeled
->GetId() == aur
->GetId() && dispeled
->GetCasterGUID() == aur
->GetCasterGUID())
3419 j
= dispel_list
.erase(j
);
3426 // Send success log and really remove auras
3427 if (!success_list
.empty())
3429 int32 count
= success_list
.size();
3430 WorldPacket
data(SMSG_SPELLDISPELLOG
, 8+8+4+1+4+count
*5);
3431 data
.append(unitTarget
->GetPackGUID()); // Victim GUID
3432 data
.append(m_caster
->GetPackGUID()); // Caster GUID
3433 data
<< uint32(m_spellInfo
->Id
); // Dispell spell id
3434 data
<< uint8(0); // not used
3435 data
<< uint32(count
); // count
3436 for (std::list
<std::pair
<uint32
,uint64
> >::iterator j
= success_list
.begin(); j
!= success_list
.end(); ++j
)
3438 SpellEntry
const* spellInfo
= sSpellStore
.LookupEntry(j
->first
);
3439 data
<< uint32(spellInfo
->Id
); // Spell Id
3440 data
<< uint8(0); // 0 - dispeled !=0 cleansed
3441 unitTarget
->RemoveAurasDueToSpellByDispel(spellInfo
->Id
, j
->second
, m_caster
);
3443 m_caster
->SendMessageToSet(&data
, true);
3447 if (m_spellInfo
->SpellFamilyName
== SPELLFAMILY_WARLOCK
&& m_spellInfo
->Category
== 12)
3449 uint32 heal_spell
= 0;
3450 switch (m_spellInfo
->Id
)
3452 case 19505: heal_spell
= 19658; break;
3453 case 19731: heal_spell
= 19732; break;
3454 case 19734: heal_spell
= 19733; break;
3455 case 19736: heal_spell
= 19735; break;
3456 case 27276: heal_spell
= 27278; break;
3457 case 27277: heal_spell
= 27279; break;
3459 sLog
.outDebug("Spell for Devour Magic %d not handled in Spell::EffectDispel", m_spellInfo
->Id
);
3463 m_caster
->CastSpell(m_caster
, heal_spell
, true);
3466 // Send fail log to client
3467 if (!fail_list
.empty())
3469 // Failed to dispell
3470 WorldPacket
data(SMSG_DISPEL_FAILED
, 8+8+4+4*fail_list
.size());
3471 data
<< uint64(m_caster
->GetGUID()); // Caster GUID
3472 data
<< uint64(unitTarget
->GetGUID()); // Victim GUID
3473 data
<< uint32(m_spellInfo
->Id
); // Dispell spell id
3474 for (std::list
< uint32
>::iterator j
= fail_list
.begin(); j
!= fail_list
.end(); ++j
)
3475 data
<< uint32(*j
); // Spell Id
3476 m_caster
->SendMessageToSet(&data
, true);
3481 void Spell::EffectDualWield(uint32
/*i*/)
3483 if (unitTarget
&& unitTarget
->GetTypeId() == TYPEID_PLAYER
)
3484 ((Player
*)unitTarget
)->SetCanDualWield(true);
3487 void Spell::EffectPull(uint32
/*i*/)
3489 // TODO: create a proper pull towards distract spell center for distract
3490 sLog
.outDebug("WORLD: Spell Effect DUMMY");
3493 void Spell::EffectDistract(uint32
/*i*/)
3495 // Check for possible target
3496 if (!unitTarget
|| unitTarget
->isInCombat())
3499 // target must be OK to do this
3500 if( unitTarget
->hasUnitState(UNIT_STAT_CONFUSED
| UNIT_STAT_STUNNED
| UNIT_STAT_FLEEING
) )
3503 float angle
= unitTarget
->GetAngle(m_targets
.m_destX
, m_targets
.m_destY
);
3505 if ( unitTarget
->GetTypeId() == TYPEID_PLAYER
)
3507 // For players just turn them
3509 ((Player
*)unitTarget
)->BuildTeleportAckMsg(&data
, unitTarget
->GetPositionX(), unitTarget
->GetPositionY(), unitTarget
->GetPositionZ(), angle
);
3510 ((Player
*)unitTarget
)->GetSession()->SendPacket( &data
);
3511 ((Player
*)unitTarget
)->SetPosition(unitTarget
->GetPositionX(), unitTarget
->GetPositionY(), unitTarget
->GetPositionZ(), angle
, false);
3515 // Set creature Distracted, Stop it, And turn it
3516 unitTarget
->SetOrientation(angle
);
3517 unitTarget
->StopMoving();
3518 unitTarget
->GetMotionMaster()->MoveDistract(damage
*1000);
3522 void Spell::EffectPickPocket(uint32
/*i*/)
3524 if( m_caster
->GetTypeId() != TYPEID_PLAYER
)
3527 // victim must be creature and attackable
3528 if( !unitTarget
|| unitTarget
->GetTypeId() != TYPEID_UNIT
|| m_caster
->IsFriendlyTo(unitTarget
) )
3531 // victim have to be alive and humanoid or undead
3532 if( unitTarget
->isAlive() && (unitTarget
->GetCreatureTypeMask() &CREATURE_TYPEMASK_HUMANOID_OR_UNDEAD
) != 0)
3534 int32 chance
= 10 + int32(m_caster
->getLevel()) - int32(unitTarget
->getLevel());
3536 if (chance
> irand(0, 19))
3538 // Stealing successful
3539 //sLog.outDebug("Sending loot from pickpocket");
3540 ((Player
*)m_caster
)->SendLoot(unitTarget
->GetGUID(),LOOT_PICKPOCKETING
);
3544 // Reveal action + get attack
3545 m_caster
->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH
);
3546 if (((Creature
*)unitTarget
)->AI())
3547 ((Creature
*)unitTarget
)->AI()->AttackStart(m_caster
);
3552 void Spell::EffectAddFarsight(uint32 i
)
3554 float radius
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[i
]));
3555 int32 duration
= GetSpellDuration(m_spellInfo
);
3556 DynamicObject
* dynObj
= new DynamicObject
;
3557 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
))
3562 dynObj
->SetUInt32Value(OBJECT_FIELD_TYPE
, 65);
3563 dynObj
->SetUInt32Value(DYNAMICOBJECT_BYTES
, 0x80000002);
3564 m_caster
->AddDynObject(dynObj
);
3565 dynObj
->GetMap()->Add(dynObj
);
3566 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
3567 ((Player
*)m_caster
)->SetFarSightGUID(dynObj
->GetGUID());
3570 void Spell::EffectSummonWild(uint32 i
)
3572 uint32 creature_entry
= m_spellInfo
->EffectMiscValue
[i
];
3576 uint32 level
= m_caster
->getLevel();
3578 // level of creature summoned using engineering item based at engineering skill level
3579 if(m_caster
->GetTypeId()==TYPEID_PLAYER
&& m_CastItem
)
3581 ItemPrototype
const *proto
= m_CastItem
->GetProto();
3582 if(proto
&& proto
->RequiredSkill
== SKILL_ENGINERING
)
3584 uint16 skill202
= ((Player
*)m_caster
)->GetSkillValue(SKILL_ENGINERING
);
3592 // select center of summon position
3593 float center_x
= m_targets
.m_destX
;
3594 float center_y
= m_targets
.m_destY
;
3595 float center_z
= m_targets
.m_destZ
;
3597 float radius
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[i
]));
3599 int32 amount
= damage
> 0 ? damage
: 1;
3601 for(int32 count
= 0; count
< amount
; ++count
)
3604 // If dest location if present
3605 if (m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
3607 // Summon 1 unit in dest location
3610 px
= m_targets
.m_destX
;
3611 py
= m_targets
.m_destY
;
3612 pz
= m_targets
.m_destZ
;
3614 // Summon in random point all other units if location present
3616 m_caster
->GetRandomPoint(center_x
,center_y
,center_z
,radius
,px
,py
,pz
);
3618 // Summon if dest location not present near caster
3620 m_caster
->GetClosePoint(px
,py
,pz
,3.0f
);
3622 int32 duration
= GetSpellDuration(m_spellInfo
);
3624 TempSummonType summonType
= (duration
== 0) ? TEMPSUMMON_DEAD_DESPAWN
: TEMPSUMMON_TIMED_OR_DEAD_DESPAWN
;
3626 m_caster
->SummonCreature(creature_entry
,px
,py
,pz
,m_caster
->GetOrientation(),summonType
,duration
);
3630 void Spell::EffectSummonGuardian(uint32 i
)
3632 uint32 pet_entry
= m_spellInfo
->EffectMiscValue
[i
];
3636 // Jewelery statue case (totem like)
3637 if(m_spellInfo
->SpellIconID
==2056)
3639 EffectSummonTotem(i
);
3643 // set timer for unsummon
3644 int32 duration
= GetSpellDuration(m_spellInfo
);
3646 // Search old Guardian only for players (if casted spell not have duration or cooldown)
3647 // FIXME: some guardians have control spell applied and controlled by player and anyway player can't summon in this time
3648 // so this code hack in fact
3649 if( m_caster
->GetTypeId() == TYPEID_PLAYER
&& (duration
<= 0 || GetSpellRecoveryTime(m_spellInfo
)==0) )
3650 if(((Player
*)m_caster
)->HasGuardianWithEntry(pet_entry
))
3651 return; // find old guardian, ignore summon
3653 // in another case summon new
3654 uint32 level
= m_caster
->getLevel();
3656 // level of pet summoned using engineering item based at engineering skill level
3657 if(m_caster
->GetTypeId()==TYPEID_PLAYER
&& m_CastItem
)
3659 ItemPrototype
const *proto
= m_CastItem
->GetProto();
3660 if(proto
&& proto
->RequiredSkill
== SKILL_ENGINERING
)
3662 uint16 skill202
= ((Player
*)m_caster
)->GetSkillValue(SKILL_ENGINERING
);
3670 // select center of summon position
3671 float center_x
= m_targets
.m_destX
;
3672 float center_y
= m_targets
.m_destY
;
3673 float center_z
= m_targets
.m_destZ
;
3675 float radius
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[i
]));
3677 int32 amount
= damage
> 0 ? damage
: 1;
3679 for(int32 count
= 0; count
< amount
; ++count
)
3681 Pet
* spawnCreature
= new Pet(GUARDIAN_PET
);
3683 Map
*map
= m_caster
->GetMap();
3684 uint32 pet_number
= objmgr
.GeneratePetNumber();
3685 if(!spawnCreature
->Create(objmgr
.GenerateLowGuid(HIGHGUID_PET
), map
,m_caster
->GetPhaseMask(),
3686 m_spellInfo
->EffectMiscValue
[i
], pet_number
))
3688 sLog
.outError("no such creature entry %u",m_spellInfo
->EffectMiscValue
[i
]);
3689 delete spawnCreature
;
3694 // If dest location if present
3695 if (m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
3697 // Summon 1 unit in dest location
3700 px
= m_targets
.m_destX
;
3701 py
= m_targets
.m_destY
;
3702 pz
= m_targets
.m_destZ
;
3704 // Summon in random point all other units if location present
3706 m_caster
->GetRandomPoint(center_x
,center_y
,center_z
,radius
,px
,py
,pz
);
3708 // Summon if dest location not present near caster
3710 m_caster
->GetClosePoint(px
,py
,pz
,spawnCreature
->GetObjectSize());
3712 spawnCreature
->Relocate(px
,py
,pz
,m_caster
->GetOrientation());
3714 if(!spawnCreature
->IsPositionValid())
3716 sLog
.outError("ERROR: Pet (guidlow %d, entry %d) not created base at creature. Suggested coordinates isn't valid (X: %f Y: %f)",
3717 spawnCreature
->GetGUIDLow(), spawnCreature
->GetEntry(), spawnCreature
->GetPositionX(), spawnCreature
->GetPositionY());
3718 delete spawnCreature
;
3723 spawnCreature
->SetDuration(duration
);
3725 spawnCreature
->SetOwnerGUID(m_caster
->GetGUID());
3726 spawnCreature
->setPowerType(POWER_MANA
);
3727 spawnCreature
->SetUInt32Value(UNIT_NPC_FLAGS
, 0);
3728 spawnCreature
->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE
,m_caster
->getFaction());
3729 spawnCreature
->SetUInt32Value(UNIT_FIELD_FLAGS
,0);
3730 spawnCreature
->SetUInt32Value(UNIT_FIELD_BYTES_1
,0);
3731 spawnCreature
->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP
,0);
3732 spawnCreature
->SetCreatorGUID(m_caster
->GetGUID());
3733 spawnCreature
->SetUInt32Value(UNIT_CREATED_BY_SPELL
, m_spellInfo
->Id
);
3735 spawnCreature
->InitStatsForLevel(level
);
3736 spawnCreature
->GetCharmInfo()->SetPetNumber(pet_number
, false);
3738 spawnCreature
->AIM_Initialize();
3740 if(m_caster
->GetTypeId()==TYPEID_PLAYER
)
3741 ((Player
*)m_caster
)->AddGuardian(spawnCreature
);
3743 map
->Add((Creature
*)spawnCreature
);
3747 void Spell::EffectTeleUnitsFaceCaster(uint32 i
)
3752 if(unitTarget
->isInFlight())
3755 uint32 mapid
= m_caster
->GetMapId();
3756 float dis
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[i
]));
3759 m_caster
->GetClosePoint(fx
,fy
,fz
,unitTarget
->GetObjectSize(),dis
);
3761 if(unitTarget
->GetTypeId() == TYPEID_PLAYER
)
3762 ((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));
3764 m_caster
->GetMap()->CreatureRelocation((Creature
*)m_caster
, fx
, fy
, fz
, -m_caster
->GetOrientation());
3767 void Spell::EffectLearnSkill(uint32 i
)
3769 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
3775 uint32 skillid
= m_spellInfo
->EffectMiscValue
[i
];
3776 uint16 skillval
= ((Player
*)unitTarget
)->GetPureSkillValue(skillid
);
3777 ((Player
*)unitTarget
)->SetSkill(skillid
, skillval
?skillval
:1, damage
*75);
3780 void Spell::EffectAddHonor(uint32
/*i*/)
3782 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
3785 sLog
.outDebug("SpellEffect::AddHonor called for spell_id %u , that rewards %d honor points to player: %u", m_spellInfo
->Id
, damage
, ((Player
*)unitTarget
)->GetGUIDLow());
3787 // TODO: find formula for honor reward based on player's level!
3789 // now fixed only for level 70 players:
3790 if (((Player
*)unitTarget
)->getLevel() == 70)
3791 ((Player
*)unitTarget
)->RewardHonor(NULL
, 1, damage
);
3794 void Spell::EffectTradeSkill(uint32
/*i*/)
3796 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
3798 // uint32 skillid = m_spellInfo->EffectMiscValue[i];
3799 // uint16 skillmax = ((Player*)unitTarget)->(skillid);
3800 // ((Player*)unitTarget)->SetSkill(skillid,skillval?skillval:1,skillmax+75);
3803 void Spell::EffectEnchantItemPerm(uint32 effect_idx
)
3805 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
3810 Player
* p_caster
= (Player
*)m_caster
;
3812 // not grow at item use at item case
3813 p_caster
->UpdateCraftSkill(m_spellInfo
->Id
);
3815 uint32 enchant_id
= m_spellInfo
->EffectMiscValue
[effect_idx
];
3819 SpellItemEnchantmentEntry
const *pEnchant
= sSpellItemEnchantmentStore
.LookupEntry(enchant_id
);
3823 // item can be in trade slot and have owner diff. from caster
3824 Player
* item_owner
= itemTarget
->GetOwner();
3828 if(item_owner
!=p_caster
&& p_caster
->GetSession()->GetSecurity() > SEC_PLAYER
&& sWorld
.getConfig(CONFIG_GM_LOG_TRADE
) )
3830 sLog
.outCommand(p_caster
->GetSession()->GetAccountId(),"GM %s (Account: %u) enchanting(perm): %s (Entry: %d) for player: %s (Account: %u)",
3831 p_caster
->GetName(),p_caster
->GetSession()->GetAccountId(),
3832 itemTarget
->GetProto()->Name1
,itemTarget
->GetEntry(),
3833 item_owner
->GetName(),item_owner
->GetSession()->GetAccountId());
3836 // remove old enchanting before applying new if equipped
3837 item_owner
->ApplyEnchantment(itemTarget
,PERM_ENCHANTMENT_SLOT
,false);
3839 itemTarget
->SetEnchantment(PERM_ENCHANTMENT_SLOT
, enchant_id
, 0, 0);
3841 // add new enchanting if equipped
3842 item_owner
->ApplyEnchantment(itemTarget
,PERM_ENCHANTMENT_SLOT
,true);
3845 void Spell::EffectEnchantItemPrismatic(uint32 effect_idx
)
3847 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
3852 Player
* p_caster
= (Player
*)m_caster
;
3854 uint32 enchant_id
= m_spellInfo
->EffectMiscValue
[effect_idx
];
3858 SpellItemEnchantmentEntry
const *pEnchant
= sSpellItemEnchantmentStore
.LookupEntry(enchant_id
);
3862 // support only enchantings with add socket in this slot
3864 bool add_socket
= false;
3865 for(int i
= 0; i
< 3; ++i
)
3867 if(pEnchant
->type
[i
]==ITEM_ENCHANTMENT_TYPE_PRISMATIC_SOCKET
)
3875 sLog
.outError("Spell::EffectEnchantItemPrismatic: attempt apply enchant spell %u with SPELL_EFFECT_ENCHANT_ITEM_PRISMATIC (%u) but without ITEM_ENCHANTMENT_TYPE_PRISMATIC_SOCKET (u), not suppoted yet.",
3876 m_spellInfo
->Id
,SPELL_EFFECT_ENCHANT_ITEM_PRISMATIC
,ITEM_ENCHANTMENT_TYPE_PRISMATIC_SOCKET
);
3881 // item can be in trade slot and have owner diff. from caster
3882 Player
* item_owner
= itemTarget
->GetOwner();
3886 if(item_owner
!=p_caster
&& p_caster
->GetSession()->GetSecurity() > SEC_PLAYER
&& sWorld
.getConfig(CONFIG_GM_LOG_TRADE
) )
3888 sLog
.outCommand(p_caster
->GetSession()->GetAccountId(),"GM %s (Account: %u) enchanting(perm): %s (Entry: %d) for player: %s (Account: %u)",
3889 p_caster
->GetName(),p_caster
->GetSession()->GetAccountId(),
3890 itemTarget
->GetProto()->Name1
,itemTarget
->GetEntry(),
3891 item_owner
->GetName(),item_owner
->GetSession()->GetAccountId());
3894 // remove old enchanting before applying new if equipped
3895 item_owner
->ApplyEnchantment(itemTarget
,PRISMATIC_ENCHANTMENT_SLOT
,false);
3897 itemTarget
->SetEnchantment(PRISMATIC_ENCHANTMENT_SLOT
, enchant_id
, 0, 0);
3899 // add new enchanting if equipped
3900 item_owner
->ApplyEnchantment(itemTarget
,PRISMATIC_ENCHANTMENT_SLOT
,true);
3903 void Spell::EffectEnchantItemTmp(uint32 i
)
3905 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
3908 Player
* p_caster
= (Player
*)m_caster
;
3913 uint32 enchant_id
= m_spellInfo
->EffectMiscValue
[i
];
3915 // Shaman Rockbiter Weapon
3916 if(i
==0 && m_spellInfo
->Effect
[1]==SPELL_EFFECT_DUMMY
)
3918 int32 enchnting_damage
= m_currentBasePoints
[1]+1;
3920 // enchanting id selected by calculated damage-per-sec stored in Effect[1] base value
3921 // with already applied percent bonus from Elemental Weapons talent
3922 // Note: damage calculated (correctly) with rounding int32(float(v)) but
3923 // RW enchantments applied damage int32(float(v)+0.5), this create 0..1 difference sometime
3924 switch(enchnting_damage
)
3927 case 2: enchant_id
= 29; break; // 0% [ 7% == 2, 14% == 2, 20% == 2]
3929 case 4: enchant_id
= 6; break; // 0% [ 7% == 4, 14% == 4]
3930 case 5: enchant_id
= 3025; break; // 20%
3932 case 6: enchant_id
= 1; break; // 0% [ 7% == 6, 14% == 6]
3933 case 7: enchant_id
= 3027; break; // 20%
3935 case 9: enchant_id
= 3032; break; // 0% [ 7% == 6]
3936 case 10: enchant_id
= 503; break; // 14%
3937 case 11: enchant_id
= 3031; break; // 20%
3939 case 15: enchant_id
= 3035; break; // 0%
3940 case 16: enchant_id
= 1663; break; // 7%
3941 case 17: enchant_id
= 3033; break; // 14%
3942 case 18: enchant_id
= 3034; break; // 20%
3944 case 28: enchant_id
= 3038; break; // 0%
3945 case 29: enchant_id
= 683; break; // 7%
3946 case 31: enchant_id
= 3036; break; // 14%
3947 case 33: enchant_id
= 3037; break; // 20%
3949 case 40: enchant_id
= 3041; break; // 0%
3950 case 42: enchant_id
= 1664; break; // 7%
3951 case 45: enchant_id
= 3039; break; // 14%
3952 case 48: enchant_id
= 3040; break; // 20%
3954 case 49: enchant_id
= 3044; break; // 0%
3955 case 52: enchant_id
= 2632; break; // 7%
3956 case 55: enchant_id
= 3042; break; // 14%
3957 case 58: enchant_id
= 3043; break; // 20%
3959 case 62: enchant_id
= 2633; break; // 0%
3960 case 66: enchant_id
= 3018; break; // 7%
3961 case 70: enchant_id
= 3019; break; // 14%
3962 case 74: enchant_id
= 3020; break; // 20%
3964 sLog
.outError("Spell::EffectEnchantItemTmp: Damage %u not handled in S'RW",enchnting_damage
);
3971 sLog
.outError("Spell %u Effect %u (SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY) have 0 as enchanting id",m_spellInfo
->Id
,i
);
3975 SpellItemEnchantmentEntry
const *pEnchant
= sSpellItemEnchantmentStore
.LookupEntry(enchant_id
);
3978 sLog
.outError("Spell %u Effect %u (SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY) have not existed enchanting id %u ",m_spellInfo
->Id
,i
,enchant_id
);
3982 // select enchantment duration
3985 // rogue family enchantments exception by duration
3986 if(m_spellInfo
->Id
==38615)
3987 duration
= 1800; // 30 mins
3988 // other rogue family enchantments always 1 hour (some have spell damage=0, but some have wrong data in EffBasePoints)
3989 else if(m_spellInfo
->SpellFamilyName
==SPELLFAMILY_ROGUE
)
3990 duration
= 3600; // 1 hour
3991 // shaman family enchantments
3992 else if(m_spellInfo
->SpellFamilyName
==SPELLFAMILY_SHAMAN
)
3993 duration
= 1800; // 30 mins
3994 // other cases with this SpellVisual already selected
3995 else if(m_spellInfo
->SpellVisual
[0]==215)
3996 duration
= 1800; // 30 mins
3997 // some fishing pole bonuses
3998 else if(m_spellInfo
->SpellVisual
[0]==563)
3999 duration
= 600; // 10 mins
4000 // shaman rockbiter enchantments
4001 else if(m_spellInfo
->SpellVisual
[0]==0)
4002 duration
= 1800; // 30 mins
4003 else if(m_spellInfo
->Id
==29702)
4004 duration
= 300; // 5 mins
4005 else if(m_spellInfo
->Id
==37360)
4006 duration
= 300; // 5 mins
4009 duration
= 3600; // 1 hour
4011 // item can be in trade slot and have owner diff. from caster
4012 Player
* item_owner
= itemTarget
->GetOwner();
4016 if(item_owner
!=p_caster
&& p_caster
->GetSession()->GetSecurity() > SEC_PLAYER
&& sWorld
.getConfig(CONFIG_GM_LOG_TRADE
) )
4018 sLog
.outCommand(p_caster
->GetSession()->GetAccountId(),"GM %s (Account: %u) enchanting(temp): %s (Entry: %d) for player: %s (Account: %u)",
4019 p_caster
->GetName(),p_caster
->GetSession()->GetAccountId(),
4020 itemTarget
->GetProto()->Name1
,itemTarget
->GetEntry(),
4021 item_owner
->GetName(),item_owner
->GetSession()->GetAccountId());
4024 // remove old enchanting before applying new if equipped
4025 item_owner
->ApplyEnchantment(itemTarget
,TEMP_ENCHANTMENT_SLOT
,false);
4027 itemTarget
->SetEnchantment(TEMP_ENCHANTMENT_SLOT
, enchant_id
, duration
*1000, 0);
4029 // add new enchanting if equipped
4030 item_owner
->ApplyEnchantment(itemTarget
,TEMP_ENCHANTMENT_SLOT
,true);
4033 void Spell::EffectTameCreature(uint32
/*i*/)
4035 if(m_caster
->GetPetGUID())
4041 if(unitTarget
->GetTypeId() == TYPEID_PLAYER
)
4044 Creature
* creatureTarget
= (Creature
*)unitTarget
;
4046 if(creatureTarget
->isPet())
4049 if(m_caster
->getClass() != CLASS_HUNTER
)
4052 // cast finish successfully
4053 //SendChannelUpdate(0);
4056 Pet
* pet
= m_caster
->CreateTamedPetFrom(creatureTarget
,m_spellInfo
->Id
);
4058 // kill original creature
4059 creatureTarget
->setDeathState(JUST_DIED
);
4060 creatureTarget
->RemoveCorpse();
4061 creatureTarget
->SetHealth(0); // just for nice GM-mode view
4063 uint32 level
= (creatureTarget
->getLevel() < (m_caster
->getLevel() - 5)) ? (m_caster
->getLevel() - 5) : creatureTarget
->getLevel();
4065 // prepare visual effect for levelup
4066 pet
->SetUInt32Value(UNIT_FIELD_LEVEL
, level
- 1);
4069 pet
->GetMap()->Add((Creature
*)pet
);
4071 // visual effect for levelup
4072 pet
->SetUInt32Value(UNIT_FIELD_LEVEL
, level
);
4074 // caster have pet now
4075 m_caster
->SetPet(pet
);
4077 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
4079 pet
->SavePetToDB(PET_SAVE_AS_CURRENT
);
4080 ((Player
*)m_caster
)->PetSpellInitialize();
4084 void Spell::EffectSummonPet(uint32 i
)
4086 uint32 petentry
= m_spellInfo
->EffectMiscValue
[i
];
4088 Pet
*OldSummon
= m_caster
->GetPet();
4090 // if pet requested type already exist
4093 if(petentry
== 0 || OldSummon
->GetEntry() == petentry
)
4095 // pet in corpse state can't be summoned
4096 if( OldSummon
->isDead() )
4099 OldSummon
->GetMap()->Remove((Creature
*)OldSummon
,false);
4100 OldSummon
->SetMapId(m_caster
->GetMapId());
4103 m_caster
->GetClosePoint(px
, py
, pz
, OldSummon
->GetObjectSize());
4105 OldSummon
->Relocate(px
, py
, pz
, OldSummon
->GetOrientation());
4106 m_caster
->GetMap()->Add((Creature
*)OldSummon
);
4108 if(m_caster
->GetTypeId() == TYPEID_PLAYER
&& OldSummon
->isControlled() )
4110 ((Player
*)m_caster
)->PetSpellInitialize();
4115 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
4116 ((Player
*)m_caster
)->RemovePet(OldSummon
,(OldSummon
->getPetType()==HUNTER_PET
? PET_SAVE_AS_DELETED
: PET_SAVE_NOT_IN_SLOT
),false);
4121 Pet
* NewSummon
= new Pet
;
4123 // petentry==0 for hunter "call pet" (current pet summoned if any)
4124 if(m_caster
->GetTypeId() == TYPEID_PLAYER
&& NewSummon
->LoadPetFromDB((Player
*)m_caster
,petentry
))
4126 if(NewSummon
->getPetType()==SUMMON_PET
)
4128 // Remove Demonic Sacrifice auras (known pet)
4129 Unit::AuraList
const& auraClassScripts
= m_caster
->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS
);
4130 for(Unit::AuraList::const_iterator itr
= auraClassScripts
.begin();itr
!=auraClassScripts
.end();)
4132 if((*itr
)->GetModifier()->m_miscvalue
==2228)
4134 m_caster
->RemoveAurasDueToSpell((*itr
)->GetId());
4135 itr
= auraClassScripts
.begin();
4145 // not error in case fail hunter call pet
4152 CreatureInfo
const* cInfo
= sCreatureStorage
.LookupEntry
<CreatureInfo
>(petentry
);
4156 sLog
.outError("EffectSummonPet: creature entry %u not found.",petentry
);
4161 Map
*map
= m_caster
->GetMap();
4162 uint32 pet_number
= objmgr
.GeneratePetNumber();
4163 if(!NewSummon
->Create(objmgr
.GenerateLowGuid(HIGHGUID_PET
), map
, m_caster
->GetPhaseMask(),
4164 petentry
, pet_number
))
4171 m_caster
->GetClosePoint(px
, py
, pz
, NewSummon
->GetObjectSize());
4173 NewSummon
->Relocate(px
, py
, pz
, m_caster
->GetOrientation());
4175 if(!NewSummon
->IsPositionValid())
4177 sLog
.outError("ERROR: Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)",
4178 NewSummon
->GetGUIDLow(), NewSummon
->GetEntry(), NewSummon
->GetPositionX(), NewSummon
->GetPositionY());
4183 uint32 petlevel
= m_caster
->getLevel();
4184 NewSummon
->setPetType(SUMMON_PET
);
4186 uint32 faction
= m_caster
->getFaction();
4187 if(m_caster
->GetTypeId() == TYPEID_UNIT
)
4189 if ( ((Creature
*)m_caster
)->isTotem() )
4190 NewSummon
->GetCharmInfo()->SetReactState(REACT_AGGRESSIVE
);
4192 NewSummon
->GetCharmInfo()->SetReactState(REACT_DEFENSIVE
);
4195 NewSummon
->SetOwnerGUID(m_caster
->GetGUID());
4196 NewSummon
->SetCreatorGUID(m_caster
->GetGUID());
4197 NewSummon
->SetUInt32Value(UNIT_NPC_FLAGS
, 0);
4198 NewSummon
->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE
, faction
);
4199 NewSummon
->SetUInt32Value(UNIT_FIELD_BYTES_0
, 2048);
4200 NewSummon
->SetUInt32Value(UNIT_FIELD_BYTES_1
, 0);
4201 NewSummon
->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP
, time(NULL
));
4202 NewSummon
->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE
, 0);
4203 NewSummon
->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP
, 1000);
4204 NewSummon
->SetUInt32Value(UNIT_CREATED_BY_SPELL
, m_spellInfo
->Id
);
4206 NewSummon
->GetCharmInfo()->SetPetNumber(pet_number
, true);
4207 // this enables pet details window (Shift+P)
4209 // this enables popup window (pet dismiss, cancel), hunter pet additional flags set later
4210 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
4211 NewSummon
->SetUInt32Value(UNIT_FIELD_FLAGS
,UNIT_FLAG_PVP_ATTACKABLE
);
4213 NewSummon
->InitStatsForLevel(petlevel
);
4214 NewSummon
->InitPetCreateSpells();
4215 NewSummon
->InitTalentForLevel();
4217 if(NewSummon
->getPetType()==SUMMON_PET
)
4219 // Remove Demonic Sacrifice auras (new pet)
4220 Unit::AuraList
const& auraClassScripts
= m_caster
->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS
);
4221 for(Unit::AuraList::const_iterator itr
= auraClassScripts
.begin();itr
!=auraClassScripts
.end();)
4223 if((*itr
)->GetModifier()->m_miscvalue
==2228)
4225 m_caster
->RemoveAurasDueToSpell((*itr
)->GetId());
4226 itr
= auraClassScripts
.begin();
4232 // generate new name for summon pet
4233 std::string new_name
=objmgr
.GeneratePetName(petentry
);
4234 if(!new_name
.empty())
4235 NewSummon
->SetName(new_name
);
4237 else if(NewSummon
->getPetType()==HUNTER_PET
)
4238 NewSummon
->SetByteValue(UNIT_FIELD_BYTES_2
, 2, UNIT_RENAME_NOT_ALLOWED
);
4240 NewSummon
->AIM_Initialize();
4241 NewSummon
->SetHealth(NewSummon
->GetMaxHealth());
4242 NewSummon
->SetPower(POWER_MANA
, NewSummon
->GetMaxPower(POWER_MANA
));
4244 map
->Add((Creature
*)NewSummon
);
4246 m_caster
->SetPet(NewSummon
);
4247 sLog
.outDebug("New Pet has guid %u", NewSummon
->GetGUIDLow());
4249 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
4251 NewSummon
->SavePetToDB(PET_SAVE_AS_CURRENT
);
4252 ((Player
*)m_caster
)->PetSpellInitialize();
4256 void Spell::EffectLearnPetSpell(uint32 i
)
4258 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
4261 Player
*_player
= (Player
*)m_caster
;
4263 Pet
*pet
= _player
->GetPet();
4269 SpellEntry
const *learn_spellproto
= sSpellStore
.LookupEntry(m_spellInfo
->EffectTriggerSpell
[i
]);
4270 if(!learn_spellproto
)
4273 pet
->learnSpell(learn_spellproto
->Id
);
4275 pet
->SavePetToDB(PET_SAVE_AS_CURRENT
);
4276 _player
->PetSpellInitialize();
4279 void Spell::EffectTaunt(uint32
/*i*/)
4281 // this effect use before aura Taunt apply for prevent taunt already attacking target
4282 // for spell as marked "non effective at already attacking target"
4283 if(unitTarget
&& unitTarget
->GetTypeId() != TYPEID_PLAYER
)
4285 if(unitTarget
->getVictim()==m_caster
)
4287 SendCastResult(SPELL_FAILED_DONT_REPORT
);
4292 // Also use this effect to set the taunter's threat to the taunted creature's highest value
4293 if(unitTarget
->CanHaveThreatList() && unitTarget
->getThreatManager().getCurrentVictim())
4294 unitTarget
->getThreatManager().addThreat(m_caster
,unitTarget
->getThreatManager().getCurrentVictim()->getThreat());
4297 void Spell::EffectWeaponDmg(uint32 i
)
4301 if(!unitTarget
->isAlive())
4304 // multiple weapon dmg effect workaround
4305 // execute only the last weapon damage
4306 // and handle all effects at once
4307 for (int j
= 0; j
< 3; j
++)
4309 switch(m_spellInfo
->Effect
[j
])
4311 case SPELL_EFFECT_WEAPON_DAMAGE
:
4312 case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL
:
4313 case SPELL_EFFECT_NORMALIZED_WEAPON_DMG
:
4314 case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE
:
4315 if (j
< i
) // we must calculate only at last weapon effect
4321 // some spell specific modifiers
4322 bool customBonusDamagePercentMod
= false;
4323 float bonusDamagePercentMod
= 1.0f
; // applied to fixed effect damage bonus if set customBonusDamagePercentMod
4324 float weaponDamagePercentMod
= 1.0f
; // applied to weapon damage (and to fixed effect damage bonus if customBonusDamagePercentMod not set
4325 float totalDamagePercentMod
= 1.0f
; // applied to final bonus+weapon damage
4326 bool normalized
= false;
4328 int32 spell_bonus
= 0; // bonus specific for spell
4329 switch(m_spellInfo
->SpellFamilyName
)
4331 case SPELLFAMILY_WARRIOR
:
4333 // Whirlwind, single only spell with 2 weapon white damage apply if have
4334 if(m_caster
->GetTypeId()==TYPEID_PLAYER
&& (m_spellInfo
->SpellFamilyFlags
& 0x00000400000000LL
))
4336 if(((Player
*)m_caster
)->GetWeaponForAttack(OFF_ATTACK
,true))
4337 spell_bonus
+= m_caster
->CalculateDamage (OFF_ATTACK
, normalized
);
4339 // Devastate bonus and sunder armor refresh
4340 else if(m_spellInfo
->SpellVisual
[0] == 671 && m_spellInfo
->SpellIconID
== 1508)
4343 // Need refresh all Sunder Armor auras from this caster
4344 Unit::AuraMap
& suAuras
= unitTarget
->GetAuras();
4345 for(Unit::AuraMap::iterator itr
= suAuras
.begin(); itr
!= suAuras
.end(); ++itr
)
4347 SpellEntry
const *spellInfo
= (*itr
).second
->GetSpellProto();
4348 if( spellInfo
->SpellFamilyName
== SPELLFAMILY_WARRIOR
&&
4349 spellInfo
->SpellFamilyFlags
& 0x0000000000004000LL
&&
4350 (*itr
).second
->GetCasterGUID() == m_caster
->GetGUID())
4352 (*itr
).second
->RefreshAura();
4353 stack
= (*itr
).second
->GetStackAmount();
4357 spell_bonus
+= stack
* CalculateDamage(2, unitTarget
);
4361 case SPELLFAMILY_ROGUE
:
4364 if(m_spellInfo
->SpellFamilyFlags
& 0x00000200LL
)
4366 customBonusDamagePercentMod
= true;
4367 bonusDamagePercentMod
= 2.5f
; // 250%
4369 // Mutilate (for each hand)
4370 else if(m_spellInfo
->SpellFamilyFlags
& 0x600000000LL
)
4374 if(unitTarget
->HasAuraState(AURA_STATE_DEADLY_POISON
))
4379 Unit::AuraMap
const& auras
= unitTarget
->GetAuras();
4380 for(Unit::AuraMap::const_iterator itr
= auras
.begin(); itr
!=auras
.end(); ++itr
)
4382 if(itr
->second
->GetSpellProto()->Dispel
== DISPEL_POISON
)
4391 totalDamagePercentMod
*= 1.5f
; // 150% if poisoned
4395 case SPELLFAMILY_PALADIN
:
4397 // Seal of Command - receive benefit from Spell Damage and Healing
4398 if(m_spellInfo
->SpellFamilyFlags
& 0x00000002000000LL
)
4400 spell_bonus
+= int32(0.20f
*m_caster
->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo
)));
4401 spell_bonus
+= int32(0.29f
*m_caster
->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo
), unitTarget
));
4405 case SPELLFAMILY_SHAMAN
:
4407 // Skyshatter Harness item set bonus
4409 if(m_spellInfo
->SpellFamilyFlags
& 0x001000000000LL
)
4411 Unit::AuraList
const& m_OverrideClassScript
= m_caster
->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS
);
4412 for(Unit::AuraList::const_iterator i
= m_OverrideClassScript
.begin(); i
!= m_OverrideClassScript
.end(); ++i
)
4414 // Stormstrike AP Buff
4415 if ( (*i
)->GetModifier()->m_miscvalue
== 5634 )
4417 m_caster
->CastSpell(m_caster
,38430,true,NULL
,*i
);
4425 int32 fixed_bonus
= 0;
4426 for (int j
= 0; j
< 3; j
++)
4428 switch(m_spellInfo
->Effect
[j
])
4430 case SPELL_EFFECT_WEAPON_DAMAGE
:
4431 case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL
:
4432 fixed_bonus
+= CalculateDamage(j
,unitTarget
);
4434 case SPELL_EFFECT_NORMALIZED_WEAPON_DMG
:
4435 fixed_bonus
+= CalculateDamage(j
,unitTarget
);
4438 case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE
:
4439 weaponDamagePercentMod
*= float(CalculateDamage(j
,unitTarget
)) / 100.0f
;
4441 // applied only to prev.effects fixed damage
4442 if(customBonusDamagePercentMod
)
4443 fixed_bonus
= int32(fixed_bonus
*bonusDamagePercentMod
);
4445 fixed_bonus
= int32(fixed_bonus
*weaponDamagePercentMod
);
4448 break; // not weapon damage effect, just skip
4452 // non-weapon damage
4453 int32 bonus
= spell_bonus
+ fixed_bonus
;
4455 // apply to non-weapon bonus weapon total pct effect, weapon total flat effect included in weapon damage
4459 switch(m_attackType
)
4462 case BASE_ATTACK
: unitMod
= UNIT_MOD_DAMAGE_MAINHAND
; break;
4463 case OFF_ATTACK
: unitMod
= UNIT_MOD_DAMAGE_OFFHAND
; break;
4464 case RANGED_ATTACK
: unitMod
= UNIT_MOD_DAMAGE_RANGED
; break;
4467 float weapon_total_pct
= m_caster
->GetModifierValue(unitMod
, TOTAL_PCT
);
4468 bonus
= int32(bonus
*weapon_total_pct
);
4471 // + weapon damage with applied weapon% dmg to base weapon damage in call
4472 bonus
+= int32(m_caster
->CalculateDamage(m_attackType
, normalized
)*weaponDamagePercentMod
);
4475 bonus
= int32(bonus
*totalDamagePercentMod
);
4477 // prevent negative damage
4478 uint32 eff_damage
= uint32(bonus
> 0 ? bonus
: 0);
4480 // Add melee damage bonuses (also check for negative)
4481 m_caster
->MeleeDamageBonus(unitTarget
, &eff_damage
, m_attackType
, m_spellInfo
);
4482 m_damage
+= eff_damage
;
4485 if(m_spellInfo
->SpellFamilyName
==SPELLFAMILY_ROGUE
&& (m_spellInfo
->SpellFamilyFlags
& 0x2000000))
4487 if(m_caster
->GetTypeId()==TYPEID_PLAYER
)
4488 ((Player
*)m_caster
)->AddComboPoints(unitTarget
, 1);
4492 if(m_spellInfo
->SpellFamilyName
==SPELLFAMILY_DRUID
&& (m_spellInfo
->SpellFamilyFlags
==0x0000040000000000LL
))
4494 if(m_caster
->GetTypeId()==TYPEID_PLAYER
)
4495 ((Player
*)m_caster
)->AddComboPoints(unitTarget
,1);
4499 if(m_attackType
== RANGED_ATTACK
&& m_caster
->GetTypeId() == TYPEID_PLAYER
)
4501 Item
*pItem
= ((Player
*)m_caster
)->GetWeaponForAttack( RANGED_ATTACK
);
4503 // wands don't have ammo
4504 if(!pItem
|| pItem
->IsBroken() || pItem
->GetProto()->SubClass
==ITEM_SUBCLASS_WEAPON_WAND
)
4507 if( pItem
->GetProto()->InventoryType
== INVTYPE_THROWN
)
4509 if(pItem
->GetMaxStackCount()==1)
4511 // decrease durability for non-stackable throw weapon
4512 ((Player
*)m_caster
)->DurabilityPointLossForEquipSlot(EQUIPMENT_SLOT_RANGED
);
4516 // decrease items amount for stackable throw weapon
4518 ((Player
*)m_caster
)->DestroyItemCount( pItem
, count
, true);
4521 else if(uint32 ammo
= ((Player
*)m_caster
)->GetUInt32Value(PLAYER_AMMO_ID
))
4522 ((Player
*)m_caster
)->DestroyItemCount(ammo
, 1, true);
4526 void Spell::EffectThreat(uint32
/*i*/)
4528 if(!unitTarget
|| !unitTarget
->isAlive() || !m_caster
->isAlive())
4531 if(!unitTarget
->CanHaveThreatList())
4534 unitTarget
->AddThreat(m_caster
, float(damage
));
4537 void Spell::EffectHealMaxHealth(uint32
/*i*/)
4541 if(!unitTarget
->isAlive())
4544 uint32 heal
= m_caster
->GetMaxHealth();
4549 void Spell::EffectInterruptCast(uint32
/*i*/)
4553 if(!unitTarget
->isAlive())
4556 // TODO: not all spells that used this effect apply cooldown at school spells
4557 // also exist case: apply cooldown to interrupted cast only and to all spells
4558 for (uint32 i
= CURRENT_FIRST_NON_MELEE_SPELL
; i
< CURRENT_MAX_SPELL
; i
++)
4560 if (unitTarget
->m_currentSpells
[i
])
4562 // check if we can interrupt spell
4563 if ( unitTarget
->m_currentSpells
[i
]->m_spellInfo
->InterruptFlags
& SPELL_INTERRUPT_FLAG_INTERRUPT
&& unitTarget
->m_currentSpells
[i
]->m_spellInfo
->PreventionType
== SPELL_PREVENTION_TYPE_SILENCE
)
4565 unitTarget
->ProhibitSpellScholl(GetSpellSchoolMask(unitTarget
->m_currentSpells
[i
]->m_spellInfo
), GetSpellDuration(m_spellInfo
));
4566 unitTarget
->InterruptSpell(i
,false);
4572 void Spell::EffectSummonObjectWild(uint32 i
)
4574 uint32 gameobject_id
= m_spellInfo
->EffectMiscValue
[i
];
4576 GameObject
* pGameObj
= new GameObject
;
4578 WorldObject
* target
= focusObject
;
4583 if(m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
4585 x
= m_targets
.m_destX
;
4586 y
= m_targets
.m_destY
;
4587 z
= m_targets
.m_destZ
;
4590 m_caster
->GetClosePoint(x
,y
,z
,DEFAULT_WORLD_OBJECT_SIZE
);
4592 Map
*map
= target
->GetMap();
4594 if(!pGameObj
->Create(objmgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), gameobject_id
, map
,
4595 m_caster
->GetPhaseMask(), x
, y
, z
, target
->GetOrientation(), 0, 0, 0, 0, 100, 1))
4601 int32 duration
= GetSpellDuration(m_spellInfo
);
4602 pGameObj
->SetRespawnTime(duration
> 0 ? duration
/1000 : 0);
4603 pGameObj
->SetSpellId(m_spellInfo
->Id
);
4605 if(pGameObj
->GetGoType() != GAMEOBJECT_TYPE_FLAGDROP
) // make dropped flag clickable for other players (not set owner guid (created by) for this)...
4606 m_caster
->AddGameObject(pGameObj
);
4609 if(pGameObj
->GetMapId() == 489 && pGameObj
->GetGoType() == GAMEOBJECT_TYPE_FLAGDROP
) //WS
4611 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
4613 Player
*pl
= (Player
*)m_caster
;
4614 BattleGround
* bg
= ((Player
*)m_caster
)->GetBattleGround();
4615 if(bg
&& bg
->GetTypeID()==BATTLEGROUND_WS
&& bg
->GetStatus() == STATUS_IN_PROGRESS
)
4617 uint32 team
= ALLIANCE
;
4619 if(pl
->GetTeam() == team
)
4622 ((BattleGroundWS
*)bg
)->SetDroppedFlagGUID(pGameObj
->GetGUID(),team
);
4627 if(pGameObj
->GetMapId() == 566 && pGameObj
->GetGoType() == GAMEOBJECT_TYPE_FLAGDROP
) //EY
4629 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
4631 BattleGround
* bg
= ((Player
*)m_caster
)->GetBattleGround();
4632 if(bg
&& bg
->GetTypeID()==BATTLEGROUND_EY
&& bg
->GetStatus() == STATUS_IN_PROGRESS
)
4634 ((BattleGroundEY
*)bg
)->SetDroppedFlagGUID(pGameObj
->GetGUID());
4639 if(uint32 linkedEntry
= pGameObj
->GetLinkedGameObjectEntry())
4641 GameObject
* linkedGO
= new GameObject
;
4642 if(linkedGO
->Create(objmgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), linkedEntry
, map
,
4643 m_caster
->GetPhaseMask(), x
, y
, z
, target
->GetOrientation(), 0, 0, 0, 0, 100, 1))
4645 linkedGO
->SetRespawnTime(duration
> 0 ? duration
/1000 : 0);
4646 linkedGO
->SetSpellId(m_spellInfo
->Id
);
4648 m_caster
->AddGameObject(linkedGO
);
4660 void Spell::EffectScriptEffect(uint32 effIndex
)
4662 // TODO: we must implement hunter pet summon at login there (spell 6962)
4664 switch(m_spellInfo
->SpellFamilyName
)
4666 case SPELLFAMILY_GENERIC
:
4668 switch(m_spellInfo
->Id
)
4670 // PX-238 Winter Wondervolt TRAP
4673 uint32 spells
[4] = { 26272, 26157, 26273, 26274 };
4676 for(int j
= 0; j
< 4; ++j
)
4677 if(unitTarget
->HasAura(spells
[j
],0))
4681 uint32 iTmpSpellId
= spells
[urand(0,3)];
4684 unitTarget
->CastSpell(unitTarget
, iTmpSpellId
, true);
4690 if(!itemTarget
&& m_caster
->GetTypeId()!=TYPEID_PLAYER
)
4693 uint32 spell_id
= 0;
4696 case 1: spell_id
= 8854; break;
4697 default: spell_id
= 8855; break;
4700 m_caster
->CastSpell(m_caster
,spell_id
,true,NULL
);
4703 // Brittle Armor - need remove one 24575 Brittle Armor aura
4705 unitTarget
->RemoveSingleSpellAurasFromStack(24575);
4707 // Mercurial Shield - need remove one 26464 Mercurial Shield aura
4709 unitTarget
->RemoveSingleSpellAurasFromStack(26464);
4711 // Orb teleport spells
4725 switch(m_spellInfo
->Id
)
4727 case 25140: spellid
= 32571; break;
4728 case 25143: spellid
= 32572; break;
4729 case 25650: spellid
= 30140; break;
4730 case 25652: spellid
= 30141; break;
4731 case 29128: spellid
= 32568; break;
4732 case 29129: spellid
= 32569; break;
4733 case 35376: spellid
= 25649; break;
4734 case 35727: spellid
= 35730; break;
4739 unitTarget
->CastSpell(unitTarget
,spellid
,false);
4742 // Shadow Flame (All script effects, not just end ones to prevent player from dodging the last triggered spell)
4757 if(!unitTarget
|| !unitTarget
->isAlive())
4760 // Onyxia Scale Cloak
4761 if(unitTarget
->GetDummyAura(22683))
4765 m_caster
->CastSpell(unitTarget
, 22682, true);
4768 // Summon Black Qiraji Battle Tank
4774 // Prevent stacking of mounts
4775 unitTarget
->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED
);
4777 // Two separate mounts depending on area id (allows use both in and out of specific instance)
4778 if (unitTarget
->GetAreaId() == 3428)
4779 unitTarget
->CastSpell(unitTarget
, 25863, false);
4781 unitTarget
->CastSpell(unitTarget
, 26655, false);
4784 // Piccolo of the Flaming Fire
4787 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
4789 unitTarget
->HandleEmoteCommand(EMOTE_STATE_DANCE
);
4792 // Mirren's Drinking Hat
4796 switch ( urand(1,6) )
4798 case 1:case 2:case 3:
4799 item
= 23584;break; // Loch Modan Lager
4801 item
= 23585;break; // Stouthammer Lite
4803 item
= 23586;break; // Aerie Peak Pale Ale
4806 DoCreateItem(effIndex
,item
);
4812 // Removes snares and roots.
4813 uint32 mechanic_mask
= (1<<MECHANIC_ROOT
) | (1<<MECHANIC_SNARE
);
4814 Unit::AuraMap
& Auras
= unitTarget
->GetAuras();
4815 for(Unit::AuraMap::iterator iter
= Auras
.begin(), next
; iter
!= Auras
.end(); iter
= next
)
4819 Aura
*aur
= iter
->second
;
4820 if (!aur
->IsPositive()) //only remove negative spells
4822 // check for mechanic mask
4823 if(GetSpellMechanicMask(aur
->GetSpellProto(), aur
->GetEffIndex()) & mechanic_mask
)
4825 unitTarget
->RemoveAurasDueToSpell(aur
->GetId());
4829 next
= Auras
.begin();
4841 unitTarget
->CastSpell(unitTarget
, 41131, true);
4844 // Force Cast - Portal Effect: Sunwell Isle
4850 unitTarget
->CastSpell(unitTarget
, 44870, true);
4853 // Goblin Weather Machine
4862 case 0: spellId
= 46740; break;
4863 case 1: spellId
= 46739; break;
4864 case 2: spellId
= 46738; break;
4865 case 3: spellId
= 46736; break;
4867 unitTarget
->CastSpell(unitTarget
, spellId
, true);
4873 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
4876 ((Player
*)unitTarget
)->ModifyMoney(50000000);
4880 // Emblazon Runeblade
4886 unitTarget
->CastSpell(unitTarget
,51771,false);
4892 if(!unitTarget
|| unitTarget
->getClass() != CLASS_DEATH_KNIGHT
)
4894 // triggered spell is stored in m_spellInfo->EffectBasePoints[0]
4895 unitTarget
->CastSpell(unitTarget
, damage
, false);
4898 // random spell learn instead placeholder
4899 case 60893: // Northrend Alchemy Research
4900 case 61177: // Northrend Inscription Research
4901 case 61288: // Minor Inscription Research
4902 case 61756: // Northrend Inscription Research (FAST QA VERSION)
4904 if(!IsExplicitDiscoverySpell(m_spellInfo
))
4906 sLog
.outError("Wrong explicit discovery spell %u structure, or outdated...",m_spellInfo
->Id
);
4910 if(m_caster
->GetTypeId()!=TYPEID_PLAYER
)
4912 Player
* player
= (Player
*)m_caster
;
4914 // need replace effect 0 item by loot
4915 uint32 reagent_id
= m_spellInfo
->EffectItemType
[0];
4917 if(!player
->HasItemCount(reagent_id
,1))
4922 player
->DestroyItemCount (reagent_id
,count
,true);
4924 // create some random items
4925 player
->AutoStoreLootItem(m_spellInfo
->Id
,LootTemplates_Spell
);
4927 // learn random explicit discovery recipe (if any)
4928 if(uint32 discoveredSpell
= GetExplicitDiscoverySpell(m_spellInfo
->Id
, player
))
4929 player
->learnSpell(discoveredSpell
,false);
4935 case SPELLFAMILY_WARLOCK
:
4937 switch(m_spellInfo
->Id
)
4939 // Healthstone creating spells
4951 Unit::AuraList
const& mDummyAuras
= unitTarget
->GetAurasByType(SPELL_AURA_DUMMY
);
4952 for(Unit::AuraList::const_iterator i
= mDummyAuras
.begin();i
!= mDummyAuras
.end(); ++i
)
4954 if((*i
)->GetId() == 18692)
4959 else if((*i
)->GetId() == 18693)
4966 static uint32
const itypes
[8][3] = {
4967 { 5512,19004,19005}, // Minor Healthstone
4968 { 5511,19006,19007}, // Lesser Healthstone
4969 { 5509,19008,19009}, // Healthstone
4970 { 5510,19010,19011}, // Greater Healthstone
4971 { 9421,19012,19013}, // Major Healthstone
4972 {22103,22104,22105}, // Master Healthstone
4973 {36889,36890,36891}, // Demonic Healthstone
4974 {36892,36893,36894} // Fel Healthstone
4977 switch(m_spellInfo
->Id
)
4980 itemtype
=itypes
[0][rank
];break; // Minor Healthstone
4982 itemtype
=itypes
[1][rank
];break; // Lesser Healthstone
4984 itemtype
=itypes
[2][rank
];break; // Healthstone
4986 itemtype
=itypes
[3][rank
];break; // Greater Healthstone
4988 itemtype
=itypes
[4][rank
];break; // Major Healthstone
4990 itemtype
=itypes
[5][rank
];break; // Master Healthstone
4992 itemtype
=itypes
[6][rank
];break; // Demonic Healthstone
4994 itemtype
=itypes
[7][rank
];break; // Fel Healthstone
4998 DoCreateItem( effIndex
, itemtype
);
5004 case SPELLFAMILY_PRIEST
:
5006 switch(m_spellInfo
->Id
)
5008 // Pain and Suffering
5013 // Refresh Shadow Word: Pain on target
5014 Unit::AuraMap
& auras
= unitTarget
->GetAuras();
5015 for(Unit::AuraMap::iterator itr
= auras
.begin(); itr
!= auras
.end(); ++itr
)
5017 SpellEntry
const *spellInfo
= (*itr
).second
->GetSpellProto();
5018 if( spellInfo
->SpellFamilyName
== SPELLFAMILY_PRIEST
&&
5019 spellInfo
->SpellFamilyFlags
& 0x0000000000008000LL
&&
5020 (*itr
).second
->GetCasterGUID() == m_caster
->GetGUID())
5022 (*itr
).second
->RefreshAura();
5033 case SPELLFAMILY_HUNTER
:
5035 switch(m_spellInfo
->Id
)
5041 int32 basePoint
= 0;
5042 Unit::AuraMap
& Auras
= unitTarget
->GetAuras();
5043 for(Unit::AuraMap::iterator i
= Auras
.begin(); i
!= Auras
.end(); ++i
)
5045 Aura
*aura
= (*i
).second
;
5046 if (aura
->GetCasterGUID() != m_caster
->GetGUID())
5048 // Search only Serpent Sting, Viper Sting, Scorpid Sting auras
5049 uint64 familyFlag
= aura
->GetSpellProto()->SpellFamilyFlags
;
5050 if (!(familyFlag
& 0x000000800000C000LL
))
5052 // Refresh aura duration
5053 aura
->RefreshAura();
5055 // Serpent Sting - Instantly deals 40% of the damage done by your Serpent Sting.
5056 if (familyFlag
& 0x0000000000004000LL
&& aura
->GetEffIndex() == 0)
5058 spellId
= 53353; // 53353 Chimera Shot - Serpent
5059 basePoint
= aura
->GetModifier()->m_amount
* 5 * 40 / 100;
5061 // Viper Sting - Instantly restores mana to you equal to 60% of the total amount drained by your Viper Sting.
5062 if (familyFlag
& 0x0000008000000000LL
&& aura
->GetEffIndex() == 0)
5064 spellId
= 53358; // 53358 Chimera Shot - Viper
5065 basePoint
= aura
->GetModifier()->m_amount
* 4 * 60 / 100;
5067 // Scorpid Sting - Attempts to Disarm the target for 10 sec. This effect cannot occur more than once per 1 minute.
5068 if (familyFlag
& 0x0000000000008000LL
)
5069 spellId
= 53359; // 53359 Chimera Shot - Scorpid
5070 // ?? nothing say in spell desc (possibly need addition check)
5071 //if (familyFlag & 0x0000010000000000LL || // dot
5072 // familyFlag & 0x0000100000000000LL) // stun
5074 // spellId = 53366; // 53366 Chimera Shot - Wyvern
5078 m_caster
->CastCustomSpell(unitTarget
, spellId
, &basePoint
, 0, 0, false);
5086 case SPELLFAMILY_PALADIN
:
5089 if (m_spellInfo
->SpellFamilyFlags
& 0x0000000000800000LL
)
5091 if(!unitTarget
|| !unitTarget
->isAlive())
5093 uint32 spellId1
= 0;
5094 uint32 spellId2
= 0;
5096 // Judgement self add switch
5097 switch (m_spellInfo
->Id
)
5099 case 41467: break; // Judgement
5100 case 53407: spellId1
= 20184; break; // Judgement of Justice
5101 case 20271: // Judgement of Light
5102 case 57774: spellId1
= 20185; break; // Judgement of Light
5103 case 53408: spellId1
= 20186; break; // Judgement of Wisdom
5107 // all seals have aura dummy in 2 effect
5108 Unit::AuraList
const& m_dummyAuras
= m_caster
->GetAurasByType(SPELL_AURA_DUMMY
);
5109 for(Unit::AuraList::const_iterator itr
= m_dummyAuras
.begin(); itr
!= m_dummyAuras
.end(); ++itr
)
5111 SpellEntry
const *spellInfo
= (*itr
)->GetSpellProto();
5112 // search seal (all seals have judgement's aura dummy spell id in 2 effect
5113 if ((*itr
)->GetEffIndex() != 2 || !spellInfo
|| !IsSealSpell(spellInfo
))
5115 spellId2
= (*itr
)->GetModifier()->m_amount
;
5116 SpellEntry
const *judge
= sSpellStore
.LookupEntry(spellId2
);
5122 m_caster
->CastSpell(unitTarget
, spellId1
, true);
5124 m_caster
->CastSpell(unitTarget
, spellId2
, true);
5128 case SPELLFAMILY_POTION
:
5130 switch(m_spellInfo
->Id
)
5137 unitTarget
->CastSpell(unitTarget
, 28694, true);
5145 // 25% chance of casting a random buff
5146 if(roll_chance_i(75))
5149 // triggered spells are 28703 to 28707
5150 // Note: some sources say, that there was the possibility of
5151 // receiving a debuff. However, this seems to be removed by a patch.
5152 const uint32 spellid
= 28703;
5154 // don't overwrite an existing aura
5155 for(uint8 i
=0; i
<5; i
++)
5156 if(unitTarget
->HasAura(spellid
+i
, 0))
5158 unitTarget
->CastSpell(unitTarget
, spellid
+urand(0, 4), true);
5167 // 25% chance of casting Nightmare Pollen
5168 if(roll_chance_i(75))
5170 unitTarget
->CastSpell(unitTarget
, 28721, true);
5178 // normal DB scripted effect
5182 sLog
.outDebug("Spell ScriptStart spellid %u in EffectScriptEffect ", m_spellInfo
->Id
);
5183 sWorld
.ScriptsStart(sSpellScripts
, m_spellInfo
->Id
, m_caster
, unitTarget
);
5186 void Spell::EffectSanctuary(uint32
/*i*/)
5190 //unitTarget->CombatStop();
5192 unitTarget
->CombatStop();
5193 unitTarget
->getHostilRefManager().deleteReferences(); // stop all fighting
5194 // Vanish allows to remove all threat and cast regular stealth so other spells can be used
5195 if(m_spellInfo
->SpellFamilyName
== SPELLFAMILY_ROGUE
&& (m_spellInfo
->SpellFamilyFlags
& SPELLFAMILYFLAG_ROGUE_VANISH
))
5197 ((Player
*)m_caster
)->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT
);
5201 void Spell::EffectAddComboPoints(uint32
/*i*/)
5206 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5212 ((Player
*)m_caster
)->AddComboPoints(unitTarget
, damage
);
5215 void Spell::EffectDuel(uint32 i
)
5217 if(!m_caster
|| !unitTarget
|| m_caster
->GetTypeId() != TYPEID_PLAYER
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5220 Player
*caster
= (Player
*)m_caster
;
5221 Player
*target
= (Player
*)unitTarget
;
5223 // caster or target already have requested duel
5224 if( caster
->duel
|| target
->duel
|| !target
->GetSocial() || target
->GetSocial()->HasIgnore(caster
->GetGUIDLow()) )
5227 // Players can only fight a duel with each other outside (=not inside dungeons and not in capital cities)
5228 // Don't have to check the target's map since you cannot challenge someone across maps
5229 uint32 mapid
= caster
->GetMapId();
5230 if( mapid
!= 0 && mapid
!= 1 && mapid
!= 530 && mapid
!= 571 && mapid
!= 609)
5232 SendCastResult(SPELL_FAILED_NO_DUELING
); // Dueling isn't allowed here
5236 AreaTableEntry
const* casterAreaEntry
= GetAreaEntryByAreaID(caster
->GetZoneId());
5237 if(casterAreaEntry
&& (casterAreaEntry
->flags
& AREA_FLAG_CAPITAL
) )
5239 SendCastResult(SPELL_FAILED_NO_DUELING
); // Dueling isn't allowed here
5243 AreaTableEntry
const* targetAreaEntry
= GetAreaEntryByAreaID(target
->GetZoneId());
5244 if(targetAreaEntry
&& (targetAreaEntry
->flags
& AREA_FLAG_CAPITAL
) )
5246 SendCastResult(SPELL_FAILED_NO_DUELING
); // Dueling isn't allowed here
5250 //CREATE DUEL FLAG OBJECT
5251 GameObject
* pGameObj
= new GameObject
;
5253 uint32 gameobject_id
= m_spellInfo
->EffectMiscValue
[i
];
5255 Map
*map
= m_caster
->GetMap();
5256 if(!pGameObj
->Create(objmgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), gameobject_id
,
5257 map
, m_caster
->GetPhaseMask(),
5258 m_caster
->GetPositionX()+(unitTarget
->GetPositionX()-m_caster
->GetPositionX())/2 ,
5259 m_caster
->GetPositionY()+(unitTarget
->GetPositionY()-m_caster
->GetPositionY())/2 ,
5260 m_caster
->GetPositionZ(),
5261 m_caster
->GetOrientation(), 0, 0, 0, 0, 0, 1))
5267 pGameObj
->SetUInt32Value(GAMEOBJECT_FACTION
, m_caster
->getFaction() );
5268 pGameObj
->SetUInt32Value(GAMEOBJECT_LEVEL
, m_caster
->getLevel()+1 );
5269 int32 duration
= GetSpellDuration(m_spellInfo
);
5270 pGameObj
->SetRespawnTime(duration
> 0 ? duration
/1000 : 0);
5271 pGameObj
->SetSpellId(m_spellInfo
->Id
);
5273 m_caster
->AddGameObject(pGameObj
);
5278 WorldPacket
data(SMSG_DUEL_REQUESTED
, 16);
5279 data
<< pGameObj
->GetGUID();
5280 data
<< caster
->GetGUID();
5281 caster
->GetSession()->SendPacket(&data
);
5282 target
->GetSession()->SendPacket(&data
);
5285 DuelInfo
*duel
= new DuelInfo
;
5286 duel
->initiator
= caster
;
5287 duel
->opponent
= target
;
5288 duel
->startTime
= 0;
5289 duel
->startTimer
= 0;
5290 caster
->duel
= duel
;
5292 DuelInfo
*duel2
= new DuelInfo
;
5293 duel2
->initiator
= caster
;
5294 duel2
->opponent
= caster
;
5295 duel2
->startTime
= 0;
5296 duel2
->startTimer
= 0;
5297 target
->duel
= duel2
;
5299 caster
->SetUInt64Value(PLAYER_DUEL_ARBITER
,pGameObj
->GetGUID());
5300 target
->SetUInt64Value(PLAYER_DUEL_ARBITER
,pGameObj
->GetGUID());
5303 void Spell::EffectStuck(uint32
/*i*/)
5305 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5308 if(!sWorld
.getConfig(CONFIG_CAST_UNSTUCK
))
5311 Player
* pTarget
= (Player
*)unitTarget
;
5313 sLog
.outDebug("Spell Effect: Stuck");
5314 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());
5316 if(pTarget
->isInFlight())
5319 // homebind location is loaded always
5320 pTarget
->TeleportTo(pTarget
->m_homebindMapId
,pTarget
->m_homebindX
,pTarget
->m_homebindY
,pTarget
->m_homebindZ
,pTarget
->GetOrientation(), (unitTarget
==m_caster
? TELE_TO_SPELL
: 0));
5322 // Stuck spell trigger Hearthstone cooldown
5323 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(8690);
5326 Spell
spell(pTarget
,spellInfo
,true,0);
5327 spell
.SendSpellCooldown();
5330 void Spell::EffectSummonPlayer(uint32
/*i*/)
5332 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5335 // Evil Twin (ignore player summon, but hide this for summoner)
5336 if(unitTarget
->GetDummyAura(23445))
5340 m_caster
->GetClosePoint(x
,y
,z
,unitTarget
->GetObjectSize());
5342 ((Player
*)unitTarget
)->SetSummonPoint(m_caster
->GetMapId(),x
,y
,z
);
5344 WorldPacket
data(SMSG_SUMMON_REQUEST
, 8+4+4);
5345 data
<< uint64(m_caster
->GetGUID()); // summoner guid
5346 data
<< uint32(m_caster
->GetZoneId()); // summoner zone
5347 data
<< uint32(MAX_PLAYER_SUMMON_DELAY
*1000); // auto decline after msecs
5348 ((Player
*)unitTarget
)->GetSession()->SendPacket(&data
);
5351 static ScriptInfo
generateActivateCommand()
5354 si
.command
= SCRIPT_COMMAND_ACTIVATE_OBJECT
;
5358 void Spell::EffectActivateObject(uint32 effect_idx
)
5363 static ScriptInfo activateCommand
= generateActivateCommand();
5365 int32 delay_secs
= m_spellInfo
->EffectMiscValue
[effect_idx
];
5367 sWorld
.ScriptCommandStart(activateCommand
, delay_secs
, m_caster
, gameObjTarget
);
5370 void Spell::EffectApplyGlyph(uint32 i
)
5372 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5375 Player
*player
= (Player
*)m_caster
;
5378 if(uint32 oldglyph
= player
->GetGlyph(m_glyphIndex
))
5380 if(GlyphPropertiesEntry
const *old_gp
= sGlyphPropertiesStore
.LookupEntry(oldglyph
))
5382 player
->RemoveAurasDueToSpell(old_gp
->SpellId
);
5383 player
->SetGlyph(m_glyphIndex
, 0);
5388 if(uint32 glyph
= m_spellInfo
->EffectMiscValue
[i
])
5390 if(GlyphPropertiesEntry
const *gp
= sGlyphPropertiesStore
.LookupEntry(glyph
))
5392 if(GlyphSlotEntry
const *gs
= sGlyphSlotStore
.LookupEntry(player
->GetGlyphSlot(m_glyphIndex
)))
5394 if(gp
->TypeFlags
!= gs
->TypeFlags
)
5396 SendCastResult(SPELL_FAILED_INVALID_GLYPH
);
5397 return; // glyph slot missmatch
5401 player
->CastSpell(m_caster
, gp
->SpellId
, true);
5402 player
->SetGlyph(m_glyphIndex
, glyph
);
5407 void Spell::EffectSummonTotem(uint32 i
)
5410 switch(m_spellInfo
->EffectMiscValueB
[i
])
5412 case SUMMON_TYPE_TOTEM_SLOT1
: slot
= 0; break;
5413 case SUMMON_TYPE_TOTEM_SLOT2
: slot
= 1; break;
5414 case SUMMON_TYPE_TOTEM_SLOT3
: slot
= 2; break;
5415 case SUMMON_TYPE_TOTEM_SLOT4
: slot
= 3; break;
5416 // Battle standard case
5417 case SUMMON_TYPE_TOTEM
: slot
= 254; break;
5418 // jewelery statue case, like totem without slot
5419 case SUMMON_TYPE_GUARDIAN
: slot
= 255; break;
5423 if(slot
< MAX_TOTEM
)
5425 uint64 guid
= m_caster
->m_TotemSlot
[slot
];
5428 Creature
*OldTotem
= ObjectAccessor::GetCreature(*m_caster
, guid
);
5429 if(OldTotem
&& OldTotem
->isTotem())
5430 ((Totem
*)OldTotem
)->UnSummon();
5435 if (m_caster
->GetTypeId()==TYPEID_PLAYER
)
5436 team
= ((Player
*)m_caster
)->GetTeam();
5438 Totem
* pTotem
= new Totem
;
5440 if(!pTotem
->Create(objmgr
.GenerateLowGuid(HIGHGUID_UNIT
), m_caster
->GetMap(), m_caster
->GetPhaseMask(),
5441 m_spellInfo
->EffectMiscValue
[i
], team
))
5447 float angle
= slot
< MAX_TOTEM
? M_PI
/MAX_TOTEM
- (slot
*2*M_PI
/MAX_TOTEM
) : 0;
5450 m_caster
->GetClosePoint(x
,y
,z
,pTotem
->GetObjectSize(),2.0f
,angle
);
5452 // totem must be at same Z in case swimming caster and etc.
5453 if( fabs( z
- m_caster
->GetPositionZ() ) > 5 )
5454 z
= m_caster
->GetPositionZ();
5456 pTotem
->Relocate(x
, y
, z
, m_caster
->GetOrientation());
5458 if(slot
< MAX_TOTEM
)
5459 m_caster
->m_TotemSlot
[slot
] = pTotem
->GetGUID();
5461 pTotem
->SetOwner(m_caster
->GetGUID());
5462 pTotem
->SetTypeBySummonSpell(m_spellInfo
); // must be after Create call where m_spells initilized
5464 int32 duration
=GetSpellDuration(m_spellInfo
);
5465 if(Player
* modOwner
= m_caster
->GetSpellModOwner())
5466 modOwner
->ApplySpellMod(m_spellInfo
->Id
,SPELLMOD_DURATION
, duration
);
5467 pTotem
->SetDuration(duration
);
5469 if (damage
) // if not spell info, DB values used
5471 pTotem
->SetMaxHealth(damage
);
5472 pTotem
->SetHealth(damage
);
5475 pTotem
->SetUInt32Value(UNIT_CREATED_BY_SPELL
,m_spellInfo
->Id
);
5477 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
5478 pTotem
->SetFlag(UNIT_FIELD_FLAGS
,UNIT_FLAG_PVP_ATTACKABLE
);
5480 pTotem
->Summon(m_caster
);
5482 if(slot
< MAX_TOTEM
&& m_caster
->GetTypeId() == TYPEID_PLAYER
)
5484 WorldPacket
data(SMSG_TOTEM_CREATED
, 1+8+4+4);
5485 data
<< uint8(slot
);
5486 data
<< uint64(pTotem
->GetGUID());
5487 data
<< uint32(duration
);
5488 data
<< uint32(m_spellInfo
->Id
);
5489 ((Player
*)m_caster
)->SendDirectMessage(&data
);
5493 void Spell::EffectEnchantHeldItem(uint32 i
)
5495 // this is only item spell effect applied to main-hand weapon of target player (players in area)
5496 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5499 Player
* item_owner
= (Player
*)unitTarget
;
5500 Item
* item
= item_owner
->GetItemByPos(INVENTORY_SLOT_BAG_0
, EQUIPMENT_SLOT_MAINHAND
);
5506 if(!item
->IsEquipped())
5509 if (m_spellInfo
->EffectMiscValue
[i
])
5511 uint32 enchant_id
= m_spellInfo
->EffectMiscValue
[i
];
5512 int32 duration
= GetSpellDuration(m_spellInfo
); //Try duration index first ..
5514 duration
= m_currentBasePoints
[i
]+1; //Base points after ..
5516 duration
= 10; //10 seconds for enchants which don't have listed duration
5518 SpellItemEnchantmentEntry
const *pEnchant
= sSpellItemEnchantmentStore
.LookupEntry(enchant_id
);
5522 // Always go to temp enchantment slot
5523 EnchantmentSlot slot
= TEMP_ENCHANTMENT_SLOT
;
5525 // Enchantment will not be applied if a different one already exists
5526 if(item
->GetEnchantmentId(slot
) && item
->GetEnchantmentId(slot
) != enchant_id
)
5529 // Apply the temporary enchantment
5530 item
->SetEnchantment(slot
, enchant_id
, duration
*1000, 0);
5531 item_owner
->ApplyEnchantment(item
,slot
,true);
5535 void Spell::EffectDisEnchant(uint32
/*i*/)
5537 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5540 Player
* p_caster
= (Player
*)m_caster
;
5541 if(!itemTarget
|| !itemTarget
->GetProto()->DisenchantID
)
5544 p_caster
->UpdateCraftSkill(m_spellInfo
->Id
);
5546 ((Player
*)m_caster
)->SendLoot(itemTarget
->GetGUID(),LOOT_DISENCHANTING
);
5548 // item will be removed at disenchanting end
5551 void Spell::EffectInebriate(uint32
/*i*/)
5553 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5556 Player
*player
= (Player
*)unitTarget
;
5557 uint16 currentDrunk
= player
->GetDrunkValue();
5558 uint16 drunkMod
= damage
* 256;
5559 if (currentDrunk
+ drunkMod
> 0xFFFF)
5560 currentDrunk
= 0xFFFF;
5562 currentDrunk
+= drunkMod
;
5563 player
->SetDrunkValue(currentDrunk
, m_CastItem
?m_CastItem
->GetEntry():0);
5566 void Spell::EffectFeedPet(uint32 i
)
5568 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5571 Player
*_player
= (Player
*)m_caster
;
5573 Item
* foodItem
= m_targets
.getItemTarget();
5577 Pet
*pet
= _player
->GetPet();
5584 int32 benefit
= pet
->GetCurrentFoodBenefitLevel(foodItem
->GetProto()->ItemLevel
);
5589 _player
->DestroyItemCount(foodItem
,count
,true);
5590 // TODO: fix crash when a spell has two effects, both pointed at the same item target
5592 m_caster
->CastCustomSpell(pet
,m_spellInfo
->EffectTriggerSpell
[i
],&benefit
,NULL
,NULL
,true);
5595 void Spell::EffectDismissPet(uint32
/*i*/)
5597 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5600 Pet
* pet
= m_caster
->GetPet();
5602 // not let dismiss dead pet
5603 if(!pet
||!pet
->isAlive())
5606 ((Player
*)m_caster
)->RemovePet(pet
,PET_SAVE_NOT_IN_SLOT
);
5609 void Spell::EffectSummonObject(uint32 i
)
5611 uint32 go_id
= m_spellInfo
->EffectMiscValue
[i
];
5614 switch(m_spellInfo
->Effect
[i
])
5616 case SPELL_EFFECT_SUMMON_OBJECT_SLOT1
: slot
= 0; break;
5617 case SPELL_EFFECT_SUMMON_OBJECT_SLOT2
: slot
= 1; break;
5618 case SPELL_EFFECT_SUMMON_OBJECT_SLOT3
: slot
= 2; break;
5619 case SPELL_EFFECT_SUMMON_OBJECT_SLOT4
: slot
= 3; break;
5623 uint64 guid
= m_caster
->m_ObjectSlot
[slot
];
5626 GameObject
* obj
= NULL
;
5628 obj
= ObjectAccessor::GetGameObject(*m_caster
, guid
);
5630 if(obj
) obj
->Delete();
5631 m_caster
->m_ObjectSlot
[slot
] = 0;
5634 GameObject
* pGameObj
= new GameObject
;
5636 float rot2
= sin(m_caster
->GetOrientation()/2);
5637 float rot3
= cos(m_caster
->GetOrientation()/2);
5640 // If dest location if present
5641 if (m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
5643 x
= m_targets
.m_destX
;
5644 y
= m_targets
.m_destY
;
5645 z
= m_targets
.m_destZ
;
5647 // Summon in random point all other units if location present
5649 m_caster
->GetClosePoint(x
,y
,z
,DEFAULT_WORLD_OBJECT_SIZE
);
5651 Map
*map
= m_caster
->GetMap();
5652 if(!pGameObj
->Create(objmgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), go_id
, map
,
5653 m_caster
->GetPhaseMask(), x
, y
, z
, m_caster
->GetOrientation(), 0, 0, rot2
, rot3
, 0, 1))
5659 pGameObj
->SetUInt32Value(GAMEOBJECT_LEVEL
,m_caster
->getLevel());
5660 int32 duration
= GetSpellDuration(m_spellInfo
);
5661 pGameObj
->SetRespawnTime(duration
> 0 ? duration
/1000 : 0);
5662 pGameObj
->SetSpellId(m_spellInfo
->Id
);
5663 m_caster
->AddGameObject(pGameObj
);
5666 WorldPacket
data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE
, 8);
5667 data
<< pGameObj
->GetGUID();
5668 m_caster
->SendMessageToSet(&data
,true);
5670 m_caster
->m_ObjectSlot
[slot
] = pGameObj
->GetGUID();
5673 void Spell::EffectResurrect(uint32
/*effIndex*/)
5677 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5680 if(unitTarget
->isAlive())
5682 if(!unitTarget
->IsInWorld())
5685 switch (m_spellInfo
->Id
)
5687 // Defibrillate (Goblin Jumper Cables) have 33% chance on success
5689 if (roll_chance_i(67))
5691 m_caster
->CastSpell(m_caster
, 8338, true, m_CastItem
);
5695 // Defibrillate (Goblin Jumper Cables XL) have 50% chance on success
5697 if (roll_chance_i(50))
5699 m_caster
->CastSpell(m_caster
, 23055, true, m_CastItem
);
5707 Player
* pTarget
= ((Player
*)unitTarget
);
5709 if(pTarget
->isRessurectRequested()) // already have one active request
5712 uint32 health
= pTarget
->GetMaxHealth() * damage
/ 100;
5713 uint32 mana
= pTarget
->GetMaxPower(POWER_MANA
) * damage
/ 100;
5715 pTarget
->setResurrectRequestData(m_caster
->GetGUID(), m_caster
->GetMapId(), m_caster
->GetPositionX(), m_caster
->GetPositionY(), m_caster
->GetPositionZ(), health
, mana
);
5716 SendResurrectRequest(pTarget
);
5719 void Spell::EffectAddExtraAttacks(uint32
/*i*/)
5721 if(!unitTarget
|| !unitTarget
->isAlive())
5724 if( unitTarget
->m_extraAttacks
)
5727 unitTarget
->m_extraAttacks
= damage
;
5730 void Spell::EffectParry(uint32
/*i*/)
5732 if (unitTarget
&& unitTarget
->GetTypeId() == TYPEID_PLAYER
)
5733 ((Player
*)unitTarget
)->SetCanParry(true);
5736 void Spell::EffectBlock(uint32
/*i*/)
5738 if (unitTarget
&& unitTarget
->GetTypeId() == TYPEID_PLAYER
)
5739 ((Player
*)unitTarget
)->SetCanBlock(true);
5742 void Spell::EffectMomentMove(uint32 i
)
5744 if(unitTarget
->isInFlight())
5747 if( m_spellInfo
->rangeIndex
== 1) //self range
5749 uint32 mapid
= m_caster
->GetMapId();
5750 float dis
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[i
]));
5754 unitTarget
->GetClosePoint(fx
,fy
,fz
,unitTarget
->GetObjectSize(),dis
);
5756 unitTarget
->GetPosition(ox
,oy
,oz
);
5758 float fx2
,fy2
,fz2
; // getObjectHitPos overwrite last args in any result case
5759 if(VMAP::VMapFactory::createOrGetVMapManager()->getObjectHitPos(mapid
, ox
,oy
,oz
+0.5, fx
,fy
,oz
+0.5,fx2
,fy2
,fz2
, -0.5))
5764 unitTarget
->UpdateGroundPositionZ(fx
,fy
,fz
);
5767 if(unitTarget
->GetTypeId() == TYPEID_PLAYER
)
5768 ((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));
5770 m_caster
->GetMap()->CreatureRelocation((Creature
*)unitTarget
, fx
, fy
, fz
, unitTarget
->GetOrientation());
5774 void Spell::EffectReputation(uint32 i
)
5776 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5779 Player
*_player
= (Player
*)unitTarget
;
5781 int32 rep_change
= m_currentBasePoints
[i
]+1; // field store reputation change -1
5783 uint32 faction_id
= m_spellInfo
->EffectMiscValue
[i
];
5785 FactionEntry
const* factionEntry
= sFactionStore
.LookupEntry(faction_id
);
5790 _player
->ModifyFactionReputation(factionEntry
,rep_change
);
5793 void Spell::EffectQuestComplete(uint32 i
)
5795 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5798 Player
*_player
= (Player
*)m_caster
;
5800 uint32 quest_id
= m_spellInfo
->EffectMiscValue
[i
];
5801 _player
->AreaExploredOrEventHappens(quest_id
);
5804 void Spell::EffectSelfResurrect(uint32 i
)
5806 if(!unitTarget
|| unitTarget
->isAlive())
5808 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5810 if(!unitTarget
->IsInWorld())
5819 health
= uint32(-damage
);
5820 mana
= m_spellInfo
->EffectMiscValue
[i
];
5825 health
= uint32(damage
/100.0f
*unitTarget
->GetMaxHealth());
5826 if(unitTarget
->GetMaxPower(POWER_MANA
) > 0)
5827 mana
= uint32(damage
/100.0f
*unitTarget
->GetMaxPower(POWER_MANA
));
5830 Player
*plr
= ((Player
*)unitTarget
);
5831 plr
->ResurrectPlayer(0.0f
);
5833 plr
->SetHealth( health
);
5834 plr
->SetPower(POWER_MANA
, mana
);
5835 plr
->SetPower(POWER_RAGE
, 0 );
5836 plr
->SetPower(POWER_ENERGY
, plr
->GetMaxPower(POWER_ENERGY
) );
5838 plr
->SpawnCorpseBones();
5843 void Spell::EffectSkinning(uint32
/*i*/)
5845 if(unitTarget
->GetTypeId() != TYPEID_UNIT
)
5847 if(!m_caster
|| m_caster
->GetTypeId() != TYPEID_PLAYER
)
5850 Creature
* creature
= (Creature
*) unitTarget
;
5851 int32 targetLevel
= creature
->getLevel();
5853 uint32 skill
= creature
->GetCreatureInfo()->GetRequiredLootSkill();
5855 ((Player
*)m_caster
)->SendLoot(creature
->GetGUID(),LOOT_SKINNING
);
5856 creature
->RemoveFlag(UNIT_FIELD_FLAGS
, UNIT_FLAG_SKINNABLE
);
5858 int32 reqValue
= targetLevel
< 10 ? 0 : targetLevel
< 20 ? (targetLevel
-10)*10 : targetLevel
*5;
5860 int32 skillValue
= ((Player
*)m_caster
)->GetPureSkillValue(skill
);
5862 // Double chances for elites
5863 ((Player
*)m_caster
)->UpdateGatherSkill(skill
, skillValue
, reqValue
, creature
->isElite() ? 2 : 1 );
5866 void Spell::EffectCharge(uint32
/*i*/)
5868 if(!unitTarget
|| !m_caster
)
5872 unitTarget
->GetContactPoint(m_caster
, x
, y
, z
);
5873 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5874 ((Creature
*)unitTarget
)->StopMoving();
5876 // Only send MOVEMENTFLAG_WALK_MODE, client has strange issues with other move flags
5877 m_caster
->SendMonsterMove(x
, y
, z
, 0, MOVEMENTFLAG_WALK_MODE
, 1);
5879 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5880 m_caster
->GetMap()->CreatureRelocation((Creature
*)m_caster
,x
,y
,z
,m_caster
->GetOrientation());
5882 // not all charge effects used in negative spells
5883 if ( !IsPositiveSpell(m_spellInfo
->Id
))
5884 m_caster
->Attack(unitTarget
,true);
5887 void Spell::EffectSummonCritter(uint32 i
)
5889 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5891 Player
* player
= (Player
*)m_caster
;
5893 uint32 pet_entry
= m_spellInfo
->EffectMiscValue
[i
];
5897 Pet
* old_critter
= player
->GetMiniPet();
5899 // for same pet just despawn
5900 if(old_critter
&& old_critter
->GetEntry() == pet_entry
)
5902 player
->RemoveMiniPet();
5906 // despawn old pet before summon new
5908 player
->RemoveMiniPet();
5911 Pet
* critter
= new Pet(MINI_PET
);
5913 Map
*map
= m_caster
->GetMap();
5914 uint32 pet_number
= objmgr
.GeneratePetNumber();
5915 if(!critter
->Create(objmgr
.GenerateLowGuid(HIGHGUID_PET
), map
, m_caster
->GetPhaseMask(),
5916 pet_entry
, pet_number
))
5918 sLog
.outError("Spell::EffectSummonCritter, spellid %u: no such creature entry %u", m_spellInfo
->Id
, pet_entry
);
5924 // If dest location if present
5925 if (m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
5927 x
= m_targets
.m_destX
;
5928 y
= m_targets
.m_destY
;
5929 z
= m_targets
.m_destZ
;
5931 // Summon if dest location not present near caster
5933 m_caster
->GetClosePoint(x
,y
,z
,critter
->GetObjectSize());
5935 critter
->Relocate(x
,y
,z
,m_caster
->GetOrientation());
5937 if(!critter
->IsPositionValid())
5939 sLog
.outError("ERROR: Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)",
5940 critter
->GetGUIDLow(), critter
->GetEntry(), critter
->GetPositionX(), critter
->GetPositionY());
5945 critter
->SetOwnerGUID(m_caster
->GetGUID());
5946 critter
->SetCreatorGUID(m_caster
->GetGUID());
5947 critter
->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE
,m_caster
->getFaction());
5948 critter
->SetUInt32Value(UNIT_CREATED_BY_SPELL
, m_spellInfo
->Id
);
5950 critter
->AIM_Initialize();
5951 critter
->InitPetCreateSpells(); // e.g. disgusting oozeling has a create spell as critter...
5952 critter
->SetMaxHealth(1);
5953 critter
->SetHealth(1);
5954 critter
->SetLevel(1);
5956 // set timer for unsummon
5957 int32 duration
= GetSpellDuration(m_spellInfo
);
5959 critter
->SetDuration(duration
);
5961 std::string name
= player
->GetName();
5962 name
.append(petTypeSuffix
[critter
->getPetType()]);
5963 critter
->SetName( name
);
5964 player
->SetMiniPet(critter
);
5966 map
->Add((Creature
*)critter
);
5969 void Spell::EffectKnockBack(uint32 i
)
5971 if(!unitTarget
|| !m_caster
)
5974 // Effect only works on players
5975 if(unitTarget
->GetTypeId()!=TYPEID_PLAYER
)
5978 float vsin
= sin(m_caster
->GetAngle(unitTarget
));
5979 float vcos
= cos(m_caster
->GetAngle(unitTarget
));
5981 WorldPacket
data(SMSG_MOVE_KNOCK_BACK
, (8+4+4+4+4+4));
5982 data
.append(unitTarget
->GetPackGUID());
5983 data
<< uint32(0); // Sequence
5984 data
<< float(vcos
); // x direction
5985 data
<< float(vsin
); // y direction
5986 data
<< float(m_spellInfo
->EffectMiscValue
[i
])/10; // Horizontal speed
5987 data
<< float(damage
/-10); // Z Movement speed (vertical)
5989 ((Player
*)unitTarget
)->GetSession()->SendPacket(&data
);
5992 void Spell::EffectSendTaxi(uint32 i
)
5994 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5997 TaxiPathEntry
const* entry
= sTaxiPathStore
.LookupEntry(m_spellInfo
->EffectMiscValue
[i
]);
6001 std::vector
<uint32
> nodes
;
6004 nodes
[0] = entry
->from
;
6005 nodes
[1] = entry
->to
;
6008 switch(m_spellInfo
->Id
)
6010 case 31606: //Stormcrow Amulet
6013 case 45071: //Quest - Sunwell Daily - Dead Scar Bombing Run
6014 case 45113: //Quest - Sunwell Daily - Ship Bombing Run
6015 case 45353: //Quest - Sunwell Daily - Ship Bombing Run Return
6018 case 34905: //Stealth Flight
6021 case 45883: //Amber Ledge to Beryl Point
6024 case 46064: //Amber Ledge to Coldarra
6027 case 53335: //Stormwind Harbor Flight - Peaceful
6032 ((Player
*)unitTarget
)->ActivateTaxiPathTo(nodes
,mountid
);
6036 void Spell::EffectPlayerPull(uint32 i
)
6038 if(!unitTarget
|| !m_caster
)
6041 // Effect only works on players
6042 if(unitTarget
->GetTypeId()!=TYPEID_PLAYER
)
6045 float vsin
= sin(unitTarget
->GetAngle(m_caster
));
6046 float vcos
= cos(unitTarget
->GetAngle(m_caster
));
6048 WorldPacket
data(SMSG_MOVE_KNOCK_BACK
, (8+4+4+4+4+4));
6049 data
.append(unitTarget
->GetPackGUID());
6050 data
<< uint32(0); // Sequence
6051 data
<< float(vcos
); // x direction
6052 data
<< float(vsin
); // y direction
6054 data
<< float(damage
? damage
: unitTarget
->GetDistance2d(m_caster
));
6055 data
<< float(m_spellInfo
->EffectMiscValue
[i
])/-10; // Z Movement speed
6057 ((Player
*)unitTarget
)->GetSession()->SendPacket(&data
);
6060 void Spell::EffectDispelMechanic(uint32 i
)
6065 uint32 mechanic
= m_spellInfo
->EffectMiscValue
[i
];
6067 Unit::AuraMap
& Auras
= unitTarget
->GetAuras();
6068 for(Unit::AuraMap::iterator iter
= Auras
.begin(), next
; iter
!= Auras
.end(); iter
= next
)
6072 SpellEntry
const *spell
= sSpellStore
.LookupEntry(iter
->second
->GetSpellProto()->Id
);
6073 if(spell
->Mechanic
== mechanic
|| spell
->EffectMechanic
[iter
->second
->GetEffIndex()] == mechanic
)
6075 unitTarget
->RemoveAurasDueToSpell(spell
->Id
);
6079 next
= Auras
.begin();
6085 void Spell::EffectSummonDeadPet(uint32
/*i*/)
6087 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
6089 Player
*_player
= (Player
*)m_caster
;
6090 Pet
*pet
= _player
->GetPet();
6097 pet
->SetUInt32Value(UNIT_DYNAMIC_FLAGS
, 0);
6098 pet
->RemoveFlag (UNIT_FIELD_FLAGS
, UNIT_FLAG_SKINNABLE
);
6099 pet
->setDeathState( ALIVE
);
6100 pet
->clearUnitState(UNIT_STAT_ALL_STATE
);
6101 pet
->SetHealth( uint32(pet
->GetMaxHealth()*(float(damage
)/100)));
6103 pet
->AIM_Initialize();
6105 _player
->PetSpellInitialize();
6106 pet
->SavePetToDB(PET_SAVE_AS_CURRENT
);
6109 void Spell::EffectDestroyAllTotems(uint32
/*i*/)
6112 for(int slot
= 0; slot
< MAX_TOTEM
; ++slot
)
6114 if(!m_caster
->m_TotemSlot
[slot
])
6117 Creature
* totem
= ObjectAccessor::GetCreature(*m_caster
,m_caster
->m_TotemSlot
[slot
]);
6118 if(totem
&& totem
->isTotem())
6120 uint32 spell_id
= totem
->GetUInt32Value(UNIT_CREATED_BY_SPELL
);
6121 SpellEntry
const* spellInfo
= sSpellStore
.LookupEntry(spell_id
);
6123 mana
+= spellInfo
->manaCost
* damage
/ 100;
6124 ((Totem
*)totem
)->UnSummon();
6128 int32 gain
= m_caster
->ModifyPower(POWER_MANA
,int32(mana
));
6129 m_caster
->SendEnergizeSpellLog(m_caster
, m_spellInfo
->Id
, gain
, POWER_MANA
);
6132 void Spell::EffectDurabilityDamage(uint32 i
)
6134 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
6137 int32 slot
= m_spellInfo
->EffectMiscValue
[i
];
6139 // FIXME: some spells effects have value -1/-2
6140 // Possibly its mean -1 all player equipped items and -2 all items
6143 ((Player
*)unitTarget
)->DurabilityPointsLossAll(damage
,(slot
< -1));
6147 // invalid slot value
6148 if(slot
>= INVENTORY_SLOT_BAG_END
)
6151 if(Item
* item
= ((Player
*)unitTarget
)->GetItemByPos(INVENTORY_SLOT_BAG_0
,slot
))
6152 ((Player
*)unitTarget
)->DurabilityPointsLoss(item
,damage
);
6155 void Spell::EffectDurabilityDamagePCT(uint32 i
)
6157 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
6160 int32 slot
= m_spellInfo
->EffectMiscValue
[i
];
6162 // FIXME: some spells effects have value -1/-2
6163 // Possibly its mean -1 all player equipped items and -2 all items
6166 ((Player
*)unitTarget
)->DurabilityLossAll(double(damage
)/100.0f
,(slot
< -1));
6170 // invalid slot value
6171 if(slot
>= INVENTORY_SLOT_BAG_END
)
6177 if(Item
* item
= ((Player
*)unitTarget
)->GetItemByPos(INVENTORY_SLOT_BAG_0
,slot
))
6178 ((Player
*)unitTarget
)->DurabilityLoss(item
,double(damage
)/100.0f
);
6181 void Spell::EffectModifyThreatPercent(uint32
/*effIndex*/)
6186 unitTarget
->getThreatManager().modifyThreatPercent(m_caster
, damage
);
6189 void Spell::EffectTransmitted(uint32 effIndex
)
6191 uint32 name_id
= m_spellInfo
->EffectMiscValue
[effIndex
];
6193 GameObjectInfo
const* goinfo
= objmgr
.GetGameObjectInfo(name_id
);
6197 sLog
.outErrorDb("Gameobject (Entry: %u) not exist and not created at spell (ID: %u) cast",name_id
, m_spellInfo
->Id
);
6203 if(m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
6205 fx
= m_targets
.m_destX
;
6206 fy
= m_targets
.m_destY
;
6207 fz
= m_targets
.m_destZ
;
6209 //FIXME: this can be better check for most objects but still hack
6210 else if(m_spellInfo
->EffectRadiusIndex
[effIndex
] && m_spellInfo
->speed
==0)
6212 float dis
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[effIndex
]));
6213 m_caster
->GetClosePoint(fx
,fy
,fz
,DEFAULT_WORLD_OBJECT_SIZE
, dis
);
6217 float min_dis
= GetSpellMinRange(sSpellRangeStore
.LookupEntry(m_spellInfo
->rangeIndex
));
6218 float max_dis
= GetSpellMaxRange(sSpellRangeStore
.LookupEntry(m_spellInfo
->rangeIndex
));
6219 float dis
= rand_norm() * (max_dis
- min_dis
) + min_dis
;
6221 m_caster
->GetClosePoint(fx
,fy
,fz
,DEFAULT_WORLD_OBJECT_SIZE
, dis
);
6224 Map
*cMap
= m_caster
->GetMap();
6226 if(goinfo
->type
==GAMEOBJECT_TYPE_FISHINGNODE
)
6228 if ( !cMap
->IsInWater(fx
,fy
,fz
-0.5f
)) // Hack to prevent fishing bobber from failing to land on fishing hole
6229 { // but this is not proper, we really need to ignore not materialized objects
6230 SendCastResult(SPELL_FAILED_NOT_HERE
);
6231 SendChannelUpdate(0);
6235 // replace by water level in this case
6236 fz
= cMap
->GetWaterLevel(fx
,fy
);
6238 // if gameobject is summoning object, it should be spawned right on caster's position
6239 else if(goinfo
->type
==GAMEOBJECT_TYPE_SUMMONING_RITUAL
)
6241 m_caster
->GetPosition(fx
,fy
,fz
);
6244 GameObject
* pGameObj
= new GameObject
;
6246 if(!pGameObj
->Create(objmgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), name_id
, cMap
,
6247 m_caster
->GetPhaseMask(), fx
, fy
, fz
, m_caster
->GetOrientation(), 0, 0, 0, 0, 100, 1))
6253 int32 duration
= GetSpellDuration(m_spellInfo
);
6255 switch(goinfo
->type
)
6257 case GAMEOBJECT_TYPE_FISHINGNODE
:
6259 m_caster
->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT
,pGameObj
->GetGUID());
6261 pGameObj
->SetFloatValue(GAMEOBJECT_PARENTROTATION
+ 2, 0.88431775569915771 );
6263 pGameObj
->SetFloatValue(GAMEOBJECT_PARENTROTATION
+ 3, -0.4668855369091033 );
6264 m_caster
->AddGameObject(pGameObj
); // will removed at spell cancel
6266 // end time of range when possible catch fish (FISHING_BOBBER_READY_TIME..GetDuration(m_spellInfo))
6267 // start time == fish-FISHING_BOBBER_READY_TIME (0..GetDuration(m_spellInfo)-FISHING_BOBBER_READY_TIME)
6271 case 0: lastSec
= 3; break;
6272 case 1: lastSec
= 7; break;
6273 case 2: lastSec
= 13; break;
6274 case 3: lastSec
= 17; break;
6277 duration
= duration
- lastSec
*1000 + FISHING_BOBBER_READY_TIME
*1000;
6280 case GAMEOBJECT_TYPE_SUMMONING_RITUAL
:
6282 if(m_caster
->GetTypeId()==TYPEID_PLAYER
)
6284 pGameObj
->AddUniqueUse((Player
*)m_caster
);
6285 m_caster
->AddGameObject(pGameObj
); // will removed at spell cancel
6289 case GAMEOBJECT_TYPE_FISHINGHOLE
:
6290 case GAMEOBJECT_TYPE_CHEST
:
6297 pGameObj
->SetRespawnTime(duration
> 0 ? duration
/1000 : 0);
6299 pGameObj
->SetOwnerGUID(m_caster
->GetGUID() );
6301 pGameObj
->SetUInt32Value(GAMEOBJECT_LEVEL
, m_caster
->getLevel() );
6302 pGameObj
->SetSpellId(m_spellInfo
->Id
);
6304 DEBUG_LOG("AddObject at SpellEfects.cpp EffectTransmitted\n");
6305 //m_caster->AddGameObject(pGameObj);
6306 //m_ObjToDel.push_back(pGameObj);
6308 cMap
->Add(pGameObj
);
6310 WorldPacket
data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE
, 8);
6311 data
<< uint64(pGameObj
->GetGUID());
6312 m_caster
->SendMessageToSet(&data
,true);
6314 if(uint32 linkedEntry
= pGameObj
->GetLinkedGameObjectEntry())
6316 GameObject
* linkedGO
= new GameObject
;
6317 if(linkedGO
->Create(objmgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), linkedEntry
, cMap
,
6318 m_caster
->GetPhaseMask(), fx
, fy
, fz
, m_caster
->GetOrientation(), 0, 0, 0, 0, 100, 1))
6320 linkedGO
->SetRespawnTime(duration
> 0 ? duration
/1000 : 0);
6321 linkedGO
->SetUInt32Value(GAMEOBJECT_LEVEL
, m_caster
->getLevel() );
6322 linkedGO
->SetSpellId(m_spellInfo
->Id
);
6323 linkedGO
->SetOwnerGUID(m_caster
->GetGUID() );
6325 linkedGO
->GetMap()->Add(linkedGO
);
6336 void Spell::EffectProspecting(uint32
/*i*/)
6338 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
6341 Player
* p_caster
= (Player
*)m_caster
;
6342 if(!itemTarget
|| !(itemTarget
->GetProto()->BagFamily
& BAG_FAMILY_MASK_MINING_SUPP
))
6345 if(itemTarget
->GetCount() < 5)
6348 if( sWorld
.getConfig(CONFIG_SKILL_PROSPECTING
))
6350 uint32 SkillValue
= p_caster
->GetPureSkillValue(SKILL_JEWELCRAFTING
);
6351 uint32 reqSkillValue
= itemTarget
->GetProto()->RequiredSkillRank
;
6352 p_caster
->UpdateGatherSkill(SKILL_JEWELCRAFTING
, SkillValue
, reqSkillValue
);
6355 ((Player
*)m_caster
)->SendLoot(itemTarget
->GetGUID(), LOOT_PROSPECTING
);
6358 void Spell::EffectMilling(uint32
/*i*/)
6360 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
6363 Player
* p_caster
= (Player
*)m_caster
;
6364 if(!itemTarget
|| !(itemTarget
->GetProto()->BagFamily
& BAG_FAMILY_MASK_HERBS
))
6367 if(itemTarget
->GetCount() < 5)
6370 if( sWorld
.getConfig(CONFIG_SKILL_MILLING
))
6372 uint32 SkillValue
= p_caster
->GetPureSkillValue(SKILL_INSCRIPTION
);
6373 uint32 reqSkillValue
= itemTarget
->GetProto()->RequiredSkillRank
;
6374 p_caster
->UpdateGatherSkill(SKILL_INSCRIPTION
, SkillValue
, reqSkillValue
);
6377 ((Player
*)m_caster
)->SendLoot(itemTarget
->GetGUID(), LOOT_MILLING
);
6380 void Spell::EffectSkill(uint32
/*i*/)
6382 sLog
.outDebug("WORLD: SkillEFFECT");
6385 void Spell::EffectSummonDemon(uint32 i
)
6387 float px
= m_targets
.m_destX
;
6388 float py
= m_targets
.m_destY
;
6389 float pz
= m_targets
.m_destZ
;
6391 Creature
* Charmed
= m_caster
->SummonCreature(m_spellInfo
->EffectMiscValue
[i
], px
, py
, pz
, m_caster
->GetOrientation(),TEMPSUMMON_TIMED_OR_DEAD_DESPAWN
,3600000);
6395 // might not always work correctly, maybe the creature that dies from CoD casts the effect on itself and is therefore the caster?
6396 Charmed
->SetLevel(m_caster
->getLevel());
6398 // TODO: Add damage/mana/hp according to level
6400 if (m_spellInfo
->EffectMiscValue
[i
] == 89) // Inferno summon
6402 // Enslave demon effect, without mana cost and cooldown
6403 m_caster
->CastSpell(Charmed
, 20882, true); // FIXME: enslave does not scale with level, level 62+ minions cannot be enslaved
6406 Charmed
->CastSpell(Charmed
, 22703, true, 0);
6410 /* There is currently no need for this effect. We handle it in BattleGround.cpp
6411 If we would handle the resurrection here, the spiritguide would instantly disappear as the
6412 player revives, and so we wouldn't see the spirit heal visual effect on the npc.
6413 This is why we use a half sec delay between the visual effect and the resurrection itself */
6414 void Spell::EffectSpiritHeal(uint32
/*i*/)
6417 if(!unitTarget || unitTarget->isAlive())
6419 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
6421 if(!unitTarget->IsInWorld())
6424 //m_spellInfo->EffectBasePoints[i]; == 99 (percent?)
6425 //((Player*)unitTarget)->setResurrect(m_caster->GetGUID(), unitTarget->GetPositionX(), unitTarget->GetPositionY(), unitTarget->GetPositionZ(), unitTarget->GetMaxHealth(), unitTarget->GetMaxPower(POWER_MANA));
6426 ((Player*)unitTarget)->ResurrectPlayer(1.0f);
6427 ((Player*)unitTarget)->SpawnCorpseBones();
6431 // remove insignia spell effect
6432 void Spell::EffectSkinPlayerCorpse(uint32
/*i*/)
6434 sLog
.outDebug("Effect: SkinPlayerCorpse");
6435 if ( (m_caster
->GetTypeId() != TYPEID_PLAYER
) || (unitTarget
->GetTypeId() != TYPEID_PLAYER
) || (unitTarget
->isAlive()) )
6438 ((Player
*)unitTarget
)->RemovedInsignia( (Player
*)m_caster
);
6441 void Spell::EffectStealBeneficialBuff(uint32 i
)
6443 sLog
.outDebug("Effect: StealBeneficialBuff");
6445 if(!unitTarget
|| unitTarget
==m_caster
) // can't steal from self
6448 std::vector
<Aura
*> steal_list
;
6449 // Create dispel mask by dispel type
6450 uint32 dispelMask
= GetDispellMask( DispelType(m_spellInfo
->EffectMiscValue
[i
]) );
6451 Unit::AuraMap
const& auras
= unitTarget
->GetAuras();
6452 for(Unit::AuraMap::const_iterator itr
= auras
.begin(); itr
!= auras
.end(); ++itr
)
6454 Aura
*aur
= (*itr
).second
;
6455 if (aur
&& (1<<aur
->GetSpellProto()->Dispel
) & dispelMask
)
6457 // Need check for passive? this
6458 if (aur
->IsPositive() && !aur
->IsPassive())
6459 steal_list
.push_back(aur
);
6462 // Ok if exist some buffs for dispel try dispel it
6463 if (!steal_list
.empty())
6465 std::list
< std::pair
<uint32
,uint64
> > success_list
;
6466 int32 list_size
= steal_list
.size();
6467 // Dispell N = damage buffs (or while exist buffs for dispel)
6468 for (int32 count
=0; count
< damage
&& list_size
> 0; ++count
)
6470 // Random select buff for dispel
6471 Aura
*aur
= steal_list
[urand(0, list_size
-1)];
6472 // Not use chance for steal
6473 // TODO possible need do it
6474 success_list
.push_back( std::pair
<uint32
,uint64
>(aur
->GetId(),aur
->GetCasterGUID()));
6476 // Remove buff from list for prevent doubles
6477 for (std::vector
<Aura
*>::iterator j
= steal_list
.begin(); j
!= steal_list
.end(); )
6480 if (stealed
->GetId() == aur
->GetId() && stealed
->GetCasterGUID() == aur
->GetCasterGUID())
6482 j
= steal_list
.erase(j
);
6489 // Really try steal and send log
6490 if (!success_list
.empty())
6492 int32 count
= success_list
.size();
6493 WorldPacket
data(SMSG_SPELLSTEALLOG
, 8+8+4+1+4+count
*5);
6494 data
.append(unitTarget
->GetPackGUID()); // Victim GUID
6495 data
.append(m_caster
->GetPackGUID()); // Caster GUID
6496 data
<< uint32(m_spellInfo
->Id
); // Dispell spell id
6497 data
<< uint8(0); // not used
6498 data
<< uint32(count
); // count
6499 for (std::list
<std::pair
<uint32
,uint64
> >::iterator j
= success_list
.begin(); j
!= success_list
.end(); ++j
)
6501 SpellEntry
const* spellInfo
= sSpellStore
.LookupEntry(j
->first
);
6502 data
<< uint32(spellInfo
->Id
); // Spell Id
6503 data
<< uint8(0); // 0 - steals !=0 transfers
6504 unitTarget
->RemoveAurasDueToSpellBySteal(spellInfo
->Id
, j
->second
, m_caster
);
6506 m_caster
->SendMessageToSet(&data
, true);
6511 void Spell::EffectKillCredit(uint32 i
)
6513 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
6516 ((Player
*)unitTarget
)->KilledMonster(m_spellInfo
->EffectMiscValue
[i
], 0);
6519 void Spell::EffectQuestFail(uint32 i
)
6521 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
6524 ((Player
*)unitTarget
)->FailQuest(m_spellInfo
->EffectMiscValue
[i
]);
6527 void Spell::EffectActivateRune(uint32 eff_idx
)
6529 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
6532 Player
*plr
= (Player
*)m_caster
;
6534 if(plr
->getClass() != CLASS_DEATH_KNIGHT
)
6537 for(uint32 j
= 0; j
< MAX_RUNES
; ++j
)
6539 if(plr
->GetRuneCooldown(j
) && plr
->GetCurrentRune(j
) == m_spellInfo
->EffectMiscValue
[eff_idx
])
6541 plr
->SetRuneCooldown(j
, 0);
6546 void Spell::EffectTitanGrip(uint32
/*eff_idx*/)
6548 if (unitTarget
&& unitTarget
->GetTypeId() == TYPEID_PLAYER
)
6549 ((Player
*)unitTarget
)->SetCanTitanGrip(true);
6552 void Spell::EffectRenamePet(uint32
/*eff_idx*/)
6554 if (!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_UNIT
||
6555 !((Creature
*)unitTarget
)->isPet() || ((Pet
*)unitTarget
)->getPetType() != HUNTER_PET
)
6558 unitTarget
->SetByteValue(UNIT_FIELD_BYTES_2
, 2, UNIT_RENAME_ALLOWED
);