2 * Copyright (C) 2005-2008 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"
58 pEffect SpellEffects
[TOTAL_SPELL_EFFECTS
]=
60 &Spell::EffectNULL
, // 0
61 &Spell::EffectInstaKill
, // 1 SPELL_EFFECT_INSTAKILL
62 &Spell::EffectSchoolDMG
, // 2 SPELL_EFFECT_SCHOOL_DAMAGE
63 &Spell::EffectDummy
, // 3 SPELL_EFFECT_DUMMY
64 &Spell::EffectUnused
, // 4 SPELL_EFFECT_PORTAL_TELEPORT unused
65 &Spell::EffectTeleportUnits
, // 5 SPELL_EFFECT_TELEPORT_UNITS
66 &Spell::EffectApplyAura
, // 6 SPELL_EFFECT_APPLY_AURA
67 &Spell::EffectEnvirinmentalDMG
, // 7 SPELL_EFFECT_ENVIRONMENTAL_DAMAGE
68 &Spell::EffectPowerDrain
, // 8 SPELL_EFFECT_POWER_DRAIN
69 &Spell::EffectHealthLeech
, // 9 SPELL_EFFECT_HEALTH_LEECH
70 &Spell::EffectHeal
, // 10 SPELL_EFFECT_HEAL
71 &Spell::EffectUnused
, // 11 SPELL_EFFECT_BIND
72 &Spell::EffectNULL
, // 12 SPELL_EFFECT_PORTAL
73 &Spell::EffectUnused
, // 13 SPELL_EFFECT_RITUAL_BASE unused
74 &Spell::EffectUnused
, // 14 SPELL_EFFECT_RITUAL_SPECIALIZE unused
75 &Spell::EffectUnused
, // 15 SPELL_EFFECT_RITUAL_ACTIVATE_PORTAL unused
76 &Spell::EffectQuestComplete
, // 16 SPELL_EFFECT_QUEST_COMPLETE
77 &Spell::EffectWeaponDmg
, // 17 SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL
78 &Spell::EffectResurrect
, // 18 SPELL_EFFECT_RESURRECT
79 &Spell::EffectAddExtraAttacks
, // 19 SPELL_EFFECT_ADD_EXTRA_ATTACKS
80 &Spell::EffectUnused
, // 20 SPELL_EFFECT_DODGE one spell: Dodge
81 &Spell::EffectUnused
, // 21 SPELL_EFFECT_EVADE one spell: Evade (DND)
82 &Spell::EffectParry
, // 22 SPELL_EFFECT_PARRY
83 &Spell::EffectBlock
, // 23 SPELL_EFFECT_BLOCK one spell: Block
84 &Spell::EffectCreateItem
, // 24 SPELL_EFFECT_CREATE_ITEM
85 &Spell::EffectUnused
, // 25 SPELL_EFFECT_WEAPON
86 &Spell::EffectUnused
, // 26 SPELL_EFFECT_DEFENSE one spell: Defense
87 &Spell::EffectPersistentAA
, // 27 SPELL_EFFECT_PERSISTENT_AREA_AURA
88 &Spell::EffectSummonType
, // 28 SPELL_EFFECT_SUMMON
89 &Spell::EffectMomentMove
, // 29 SPELL_EFFECT_LEAP
90 &Spell::EffectEnergize
, // 30 SPELL_EFFECT_ENERGIZE
91 &Spell::EffectWeaponDmg
, // 31 SPELL_EFFECT_WEAPON_PERCENT_DAMAGE
92 &Spell::EffectTriggerMissileSpell
, // 32 SPELL_EFFECT_TRIGGER_MISSILE
93 &Spell::EffectOpenLock
, // 33 SPELL_EFFECT_OPEN_LOCK
94 &Spell::EffectSummonChangeItem
, // 34 SPELL_EFFECT_SUMMON_CHANGE_ITEM
95 &Spell::EffectApplyAreaAura
, // 35 SPELL_EFFECT_APPLY_AREA_AURA_PARTY
96 &Spell::EffectLearnSpell
, // 36 SPELL_EFFECT_LEARN_SPELL
97 &Spell::EffectUnused
, // 37 SPELL_EFFECT_SPELL_DEFENSE one spell: SPELLDEFENSE (DND)
98 &Spell::EffectDispel
, // 38 SPELL_EFFECT_DISPEL
99 &Spell::EffectUnused
, // 39 SPELL_EFFECT_LANGUAGE
100 &Spell::EffectDualWield
, // 40 SPELL_EFFECT_DUAL_WIELD
101 &Spell::EffectSummonWild
, // 41 SPELL_EFFECT_SUMMON_WILD
102 &Spell::EffectSummonGuardian
, // 42 SPELL_EFFECT_SUMMON_GUARDIAN
103 &Spell::EffectTeleUnitsFaceCaster
, // 43 SPELL_EFFECT_TELEPORT_UNITS_FACE_CASTER
104 &Spell::EffectLearnSkill
, // 44 SPELL_EFFECT_SKILL_STEP
105 &Spell::EffectAddHonor
, // 45 SPELL_EFFECT_ADD_HONOR honor/pvp related
106 &Spell::EffectNULL
, // 46 SPELL_EFFECT_SPAWN we must spawn pet there
107 &Spell::EffectTradeSkill
, // 47 SPELL_EFFECT_TRADE_SKILL
108 &Spell::EffectUnused
, // 48 SPELL_EFFECT_STEALTH one spell: Base Stealth
109 &Spell::EffectUnused
, // 49 SPELL_EFFECT_DETECT one spell: Detect
110 &Spell::EffectTransmitted
, // 50 SPELL_EFFECT_TRANS_DOOR
111 &Spell::EffectUnused
, // 51 SPELL_EFFECT_FORCE_CRITICAL_HIT unused
112 &Spell::EffectUnused
, // 52 SPELL_EFFECT_GUARANTEE_HIT one spell: zzOLDCritical Shot
113 &Spell::EffectEnchantItemPerm
, // 53 SPELL_EFFECT_ENCHANT_ITEM
114 &Spell::EffectEnchantItemTmp
, // 54 SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY
115 &Spell::EffectTameCreature
, // 55 SPELL_EFFECT_TAMECREATURE
116 &Spell::EffectSummonPet
, // 56 SPELL_EFFECT_SUMMON_PET
117 &Spell::EffectLearnPetSpell
, // 57 SPELL_EFFECT_LEARN_PET_SPELL
118 &Spell::EffectWeaponDmg
, // 58 SPELL_EFFECT_WEAPON_DAMAGE
119 &Spell::EffectOpenSecretSafe
, // 59 SPELL_EFFECT_OPEN_LOCK_ITEM
120 &Spell::EffectProficiency
, // 60 SPELL_EFFECT_PROFICIENCY
121 &Spell::EffectSendEvent
, // 61 SPELL_EFFECT_SEND_EVENT
122 &Spell::EffectPowerBurn
, // 62 SPELL_EFFECT_POWER_BURN
123 &Spell::EffectThreat
, // 63 SPELL_EFFECT_THREAT
124 &Spell::EffectTriggerSpell
, // 64 SPELL_EFFECT_TRIGGER_SPELL
125 &Spell::EffectApplyAreaAura
, // 65 SPELL_EFFECT_APPLY_AREA_AURA_RAID
126 &Spell::EffectUnused
, // 66 SPELL_EFFECT_POWER_FUNNEL unused
127 &Spell::EffectHealMaxHealth
, // 67 SPELL_EFFECT_HEAL_MAX_HEALTH
128 &Spell::EffectInterruptCast
, // 68 SPELL_EFFECT_INTERRUPT_CAST
129 &Spell::EffectDistract
, // 69 SPELL_EFFECT_DISTRACT
130 &Spell::EffectPull
, // 70 SPELL_EFFECT_PULL one spell: Distract Move
131 &Spell::EffectPickPocket
, // 71 SPELL_EFFECT_PICKPOCKET
132 &Spell::EffectAddFarsight
, // 72 SPELL_EFFECT_ADD_FARSIGHT
133 &Spell::EffectSummonGuardian
, // 73 SPELL_EFFECT_SUMMON_POSSESSED
134 &Spell::EffectApplyGlyph
, // 74 SPELL_EFFECT_APPLY_GLYPH
135 &Spell::EffectHealMechanical
, // 75 SPELL_EFFECT_HEAL_MECHANICAL one spell: Mechanical Patch Kit
136 &Spell::EffectSummonObjectWild
, // 76 SPELL_EFFECT_SUMMON_OBJECT_WILD
137 &Spell::EffectScriptEffect
, // 77 SPELL_EFFECT_SCRIPT_EFFECT
138 &Spell::EffectUnused
, // 78 SPELL_EFFECT_ATTACK
139 &Spell::EffectSanctuary
, // 79 SPELL_EFFECT_SANCTUARY
140 &Spell::EffectAddComboPoints
, // 80 SPELL_EFFECT_ADD_COMBO_POINTS
141 &Spell::EffectUnused
, // 81 SPELL_EFFECT_CREATE_HOUSE one spell: Create House (TEST)
142 &Spell::EffectNULL
, // 82 SPELL_EFFECT_BIND_SIGHT
143 &Spell::EffectDuel
, // 83 SPELL_EFFECT_DUEL
144 &Spell::EffectStuck
, // 84 SPELL_EFFECT_STUCK
145 &Spell::EffectSummonPlayer
, // 85 SPELL_EFFECT_SUMMON_PLAYER
146 &Spell::EffectActivateObject
, // 86 SPELL_EFFECT_ACTIVATE_OBJECT
147 &Spell::EffectSummonTotem
, // 87 SPELL_EFFECT_SUMMON_TOTEM_SLOT1
148 &Spell::EffectSummonTotem
, // 88 SPELL_EFFECT_SUMMON_TOTEM_SLOT2
149 &Spell::EffectSummonTotem
, // 89 SPELL_EFFECT_SUMMON_TOTEM_SLOT3
150 &Spell::EffectSummonTotem
, // 90 SPELL_EFFECT_SUMMON_TOTEM_SLOT4
151 &Spell::EffectUnused
, // 91 SPELL_EFFECT_THREAT_ALL one spell: zzOLDBrainwash
152 &Spell::EffectEnchantHeldItem
, // 92 SPELL_EFFECT_ENCHANT_HELD_ITEM
153 &Spell::EffectUnused
, // 93 SPELL_EFFECT_SUMMON_PHANTASM
154 &Spell::EffectSelfResurrect
, // 94 SPELL_EFFECT_SELF_RESURRECT
155 &Spell::EffectSkinning
, // 95 SPELL_EFFECT_SKINNING
156 &Spell::EffectCharge
, // 96 SPELL_EFFECT_CHARGE
157 &Spell::EffectSummonCritter
, // 97 SPELL_EFFECT_SUMMON_CRITTER
158 &Spell::EffectKnockBack
, // 98 SPELL_EFFECT_KNOCK_BACK
159 &Spell::EffectDisEnchant
, // 99 SPELL_EFFECT_DISENCHANT
160 &Spell::EffectInebriate
, //100 SPELL_EFFECT_INEBRIATE
161 &Spell::EffectFeedPet
, //101 SPELL_EFFECT_FEED_PET
162 &Spell::EffectDismissPet
, //102 SPELL_EFFECT_DISMISS_PET
163 &Spell::EffectReputation
, //103 SPELL_EFFECT_REPUTATION
164 &Spell::EffectSummonObject
, //104 SPELL_EFFECT_SUMMON_OBJECT_SLOT1
165 &Spell::EffectSummonObject
, //105 SPELL_EFFECT_SUMMON_OBJECT_SLOT2
166 &Spell::EffectSummonObject
, //106 SPELL_EFFECT_SUMMON_OBJECT_SLOT3
167 &Spell::EffectSummonObject
, //107 SPELL_EFFECT_SUMMON_OBJECT_SLOT4
168 &Spell::EffectDispelMechanic
, //108 SPELL_EFFECT_DISPEL_MECHANIC
169 &Spell::EffectSummonDeadPet
, //109 SPELL_EFFECT_SUMMON_DEAD_PET
170 &Spell::EffectDestroyAllTotems
, //110 SPELL_EFFECT_DESTROY_ALL_TOTEMS
171 &Spell::EffectDurabilityDamage
, //111 SPELL_EFFECT_DURABILITY_DAMAGE
172 &Spell::EffectSummonDemon
, //112 SPELL_EFFECT_SUMMON_DEMON
173 &Spell::EffectResurrectNew
, //113 SPELL_EFFECT_RESURRECT_NEW
174 &Spell::EffectTaunt
, //114 SPELL_EFFECT_ATTACK_ME
175 &Spell::EffectDurabilityDamagePCT
, //115 SPELL_EFFECT_DURABILITY_DAMAGE_PCT
176 &Spell::EffectSkinPlayerCorpse
, //116 SPELL_EFFECT_SKIN_PLAYER_CORPSE one spell: Remove Insignia, bg usage, required special corpse flags...
177 &Spell::EffectSpiritHeal
, //117 SPELL_EFFECT_SPIRIT_HEAL one spell: Spirit Heal
178 &Spell::EffectSkill
, //118 SPELL_EFFECT_SKILL professions and more
179 &Spell::EffectApplyAreaAura
, //119 SPELL_EFFECT_APPLY_AREA_AURA_PET
180 &Spell::EffectUnused
, //120 SPELL_EFFECT_TELEPORT_GRAVEYARD one spell: Graveyard Teleport Test
181 &Spell::EffectWeaponDmg
, //121 SPELL_EFFECT_NORMALIZED_WEAPON_DMG
182 &Spell::EffectUnused
, //122 SPELL_EFFECT_122 unused
183 &Spell::EffectSendTaxi
, //123 SPELL_EFFECT_SEND_TAXI taxi/flight related (misc value is taxi path id)
184 &Spell::EffectPlayerPull
, //124 SPELL_EFFECT_PLAYER_PULL opposite of knockback effect (pulls player twoard caster)
185 &Spell::EffectModifyThreatPercent
, //125 SPELL_EFFECT_MODIFY_THREAT_PERCENT
186 &Spell::EffectStealBeneficialBuff
, //126 SPELL_EFFECT_STEAL_BENEFICIAL_BUFF spell steal effect?
187 &Spell::EffectProspecting
, //127 SPELL_EFFECT_PROSPECTING Prospecting spell
188 &Spell::EffectApplyAreaAura
, //128 SPELL_EFFECT_APPLY_AREA_AURA_FRIEND
189 &Spell::EffectApplyAreaAura
, //129 SPELL_EFFECT_APPLY_AREA_AURA_ENEMY
190 &Spell::EffectNULL
, //130 SPELL_EFFECT_REDIRECT_THREAT
191 &Spell::EffectUnused
, //131 SPELL_EFFECT_131 used in some test spells
192 &Spell::EffectNULL
, //132 SPELL_EFFECT_PLAY_MUSIC sound id in misc value
193 &Spell::EffectUnlearnSpecialization
, //133 SPELL_EFFECT_UNLEARN_SPECIALIZATION unlearn profession specialization
194 &Spell::EffectKillCredit
, //134 SPELL_EFFECT_KILL_CREDIT misc value is creature entry
195 &Spell::EffectNULL
, //135 SPELL_EFFECT_CALL_PET
196 &Spell::EffectHealPct
, //136 SPELL_EFFECT_HEAL_PCT
197 &Spell::EffectEnergisePct
, //137 SPELL_EFFECT_ENERGIZE_PCT
198 &Spell::EffectNULL
, //138 SPELL_EFFECT_138 Leap
199 &Spell::EffectUnused
, //139 SPELL_EFFECT_139 unused
200 &Spell::EffectForceCast
, //140 SPELL_EFFECT_FORCE_CAST
201 &Spell::EffectNULL
, //141 SPELL_EFFECT_141 damage and reduce speed?
202 &Spell::EffectTriggerSpellWithValue
, //142 SPELL_EFFECT_TRIGGER_SPELL_WITH_VALUE
203 &Spell::EffectApplyAreaAura
, //143 SPELL_EFFECT_APPLY_AREA_AURA_OWNER
204 &Spell::EffectNULL
, //144 SPELL_EFFECT_144 Spectral Blast
205 &Spell::EffectNULL
, //145 SPELL_EFFECT_145 Black Hole Effect
206 &Spell::EffectActivateRune
, //146 SPELL_EFFECT_ACTIVATE_RUNE
207 &Spell::EffectQuestFail
, //147 SPELL_EFFECT_QUEST_FAIL quest fail
208 &Spell::EffectUnused
, //148 SPELL_EFFECT_148 unused
209 &Spell::EffectNULL
, //149 SPELL_EFFECT_149 swoop
210 &Spell::EffectUnused
, //150 SPELL_EFFECT_150 unused
211 &Spell::EffectTriggerRitualOfSummoning
, //151 SPELL_EFFECT_TRIGGER_SPELL_2
212 &Spell::EffectNULL
, //152 SPELL_EFFECT_152 summon Refer-a-Friend
213 &Spell::EffectNULL
, //153 SPELL_EFFECT_CREATE_PET misc value is creature entry
214 &Spell::EffectNULL
, //154 unused
215 &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.
216 &Spell::EffectNULL
, //156 Add Socket
217 &Spell::EffectNULL
, //157 create/learn random item/spell for profession
218 &Spell::EffectMilling
, //158 milling
219 &Spell::EffectNULL
//159 allow rename pet once again
222 void Spell::EffectNULL(uint32
/*i*/)
224 sLog
.outDebug("WORLD: Spell Effect DUMMY");
227 void Spell::EffectUnused(uint32
/*i*/)
229 // NOT USED BY ANY SPELL OR USELESS OR IMPLEMENTED IN DIFFERENT WAY IN MANGOS
232 void Spell::EffectResurrectNew(uint32 i
)
234 if(!unitTarget
|| unitTarget
->isAlive())
237 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
240 if(!unitTarget
->IsInWorld())
243 Player
* pTarget
= ((Player
*)unitTarget
);
245 if(pTarget
->isRessurectRequested()) // already have one active request
248 uint32 health
= damage
;
249 uint32 mana
= m_spellInfo
->EffectMiscValue
[i
];
250 pTarget
->setResurrectRequestData(m_caster
->GetGUID(), m_caster
->GetMapId(), m_caster
->GetPositionX(), m_caster
->GetPositionY(), m_caster
->GetPositionZ(), health
, mana
);
251 SendResurrectRequest(pTarget
);
254 void Spell::EffectInstaKill(uint32
/*i*/)
256 if( !unitTarget
|| !unitTarget
->isAlive() )
260 if(m_spellInfo
->Id
==18788 && unitTarget
->GetTypeId()==TYPEID_UNIT
)
262 uint32 entry
= unitTarget
->GetEntry();
266 case 416: spellID
=18789; break; //imp
267 case 417: spellID
=18792; break; //fellhunter
268 case 1860: spellID
=18790; break; //void
269 case 1863: spellID
=18791; break; //succubus
270 case 17252: spellID
=35701; break; //fellguard
272 sLog
.outError("EffectInstaKill: Unhandled creature entry (%u) case.",entry
);
276 m_caster
->CastSpell(m_caster
,spellID
,true);
279 if(m_caster
==unitTarget
) // prevent interrupt message
282 uint32 health
= unitTarget
->GetHealth();
283 m_caster
->DealDamage(unitTarget
, health
, NULL
, DIRECT_DAMAGE
, SPELL_SCHOOL_MASK_NORMAL
, NULL
, false);
286 void Spell::EffectEnvirinmentalDMG(uint32 i
)
291 // Note: this hack with damage replace required until GO casting not implemented
292 // environment damage spells already have around enemies targeting but this not help in case not existed GO casting support
293 // currently each enemy selected explicitly and self cast damage, we prevent apply self casted spell bonuses/etc
294 damage
= m_spellInfo
->EffectBasePoints
[i
]+m_spellInfo
->EffectBaseDice
[i
];
296 m_caster
->CalcAbsorbResist(m_caster
,GetSpellSchoolMask(m_spellInfo
), SPELL_DIRECT_DAMAGE
, damage
, &absorb
, &resist
);
298 m_caster
->SendSpellNonMeleeDamageLog(m_caster
, m_spellInfo
->Id
, damage
, GetSpellSchoolMask(m_spellInfo
), absorb
, resist
, false, 0, false);
299 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
300 ((Player
*)m_caster
)->EnvironmentalDamage(m_caster
->GetGUID(),DAMAGE_FIRE
,damage
);
303 void Spell::EffectSchoolDMG(uint32 effect_idx
)
305 if( unitTarget
&& unitTarget
->isAlive())
307 switch(m_spellInfo
->SpellFamilyName
)
309 case SPELLFAMILY_GENERIC
:
312 if(m_spellInfo
->SpellIconID
== 2269 )
314 damage
+= rand()%2 ? damage
: 0;
317 switch(m_spellInfo
->Id
) // better way to check unknown
319 // Meteor like spells (divided damage to targets)
320 case 24340: case 26558: case 28884: // Meteor
321 case 36837: case 38903: case 41276: // Meteor
322 case 26789: // Shard of the Fallen Star
323 case 31436: // Malevolent Cleave
324 case 35181: // Dive Bomb
325 case 40810: case 43267: case 43268: // Saber Lash
326 case 42384: // Brutal Swipe
327 case 45150: // Meteor Slash
330 for(std::list
<TargetInfo
>::iterator ihit
= m_UniqueTargetInfo
.begin();ihit
!= m_UniqueTargetInfo
.end();++ihit
)
331 if(ihit
->effectMask
& (1<<effect_idx
))
334 damage
/= count
; // divide to all targets
337 // percent from health with min
338 case 25599: // Thundercrash
340 damage
= unitTarget
->GetHealth() / 2;
349 case SPELLFAMILY_MAGE
:
352 if(m_spellInfo
->SpellFamilyFlags
& 0x20000000LL
)
354 m_caster
->CastSpell(m_caster
,36032,true);
358 case SPELLFAMILY_WARRIOR
:
361 if(m_spellInfo
->SpellFamilyFlags
& 0x40000000000LL
)
363 damage
= uint32(damage
* (m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
)) / 100);
366 else if(m_spellInfo
->SpellFamilyFlags
& 0x100000000LL
)
367 damage
+= int32(m_caster
->GetShieldBlockValue());
369 else if(m_spellInfo
->SpellFamilyFlags
& 0x10000000000LL
)
371 damage
= uint32(damage
* m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
) / 100);
372 m_caster
->ModifyAuraState(AURA_STATE_WARRIOR_VICTORY_RUSH
, false);
376 case SPELLFAMILY_WARLOCK
:
378 // Incinerate Rank 1 & 2
379 if((m_spellInfo
->SpellFamilyFlags
& 0x00004000000000LL
) && m_spellInfo
->SpellIconID
==2128)
381 // Incinerate does more dmg (dmg*0.25) if the target is Immolated.
382 if(unitTarget
->HasAuraState(AURA_STATE_IMMOLATE
))
383 damage
+= int32(damage
*0.25);
387 case SPELLFAMILY_DRUID
:
390 if((m_spellInfo
->SpellFamilyFlags
& 0x000800000) && m_spellInfo
->SpellVisual
[0]==6587)
392 // converts each extra point of energy into ($f1+$AP/630) additional damage
393 float multiple
= m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
) / 630 + m_spellInfo
->DmgMultiplier
[effect_idx
];
394 damage
+= int32(m_caster
->GetPower(POWER_ENERGY
) * multiple
);
395 m_caster
->SetPower(POWER_ENERGY
,0);
398 else if(m_spellInfo
->SpellFamilyFlags
& 0x0000000000001000LL
)
400 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
) / 100);
403 else if(m_spellInfo
->SpellFamilyFlags
& 0x0010000000000000LL
)
405 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
)*0.08f
);
408 else if ( m_spellInfo
->SpellFamilyFlags
& 0x0004LL
)
410 Unit::AuraList
const& m_OverrideClassScript
= m_caster
->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS
);
411 for(Unit::AuraList::const_iterator i
= m_OverrideClassScript
.begin(); i
!= m_OverrideClassScript
.end(); ++i
)
413 // Starfire Bonus (caster)
414 switch((*i
)->GetModifier()->m_miscvalue
)
416 case 5481: // Nordrassil Regalia - bonus
418 Unit::AuraList
const& m_periodicDamageAuras
= unitTarget
->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE
);
419 for(Unit::AuraList::const_iterator itr
= m_periodicDamageAuras
.begin(); itr
!= m_periodicDamageAuras
.end(); ++itr
)
421 // Moonfire or Insect Swarm (target debuff from any casters)
422 if ( (*itr
)->GetSpellProto()->SpellFamilyFlags
& 0x00200002LL
)
424 int32 mod
= (*i
)->GetModifier()->m_amount
;
425 damage
+= damage
*mod
/100;
431 case 5148: //Improved Starfire - Ivory Idol of the Moongoddes Aura
433 damage
+= (*i
)->GetModifier()->m_amount
;
439 //Mangle Bonus for the initial damage of Lacerate and Rake
440 if((m_spellInfo
->SpellFamilyFlags
==0x0000000000001000LL
&& m_spellInfo
->SpellIconID
==494) ||
441 (m_spellInfo
->SpellFamilyFlags
==0x0000010000000000LL
&& m_spellInfo
->SpellIconID
==2246))
443 Unit::AuraList
const& mDummyAuras
= unitTarget
->GetAurasByType(SPELL_AURA_DUMMY
);
444 for(Unit::AuraList::const_iterator i
= mDummyAuras
.begin(); i
!= mDummyAuras
.end(); ++i
)
445 if((*i
)->GetSpellProto()->SpellFamilyFlags
& 0x0000044000000000LL
&& (*i
)->GetSpellProto()->SpellFamilyName
==SPELLFAMILY_DRUID
)
447 damage
= int32(damage
*(100.0f
+(*i
)->GetModifier()->m_amount
)/100.0f
);
453 case SPELLFAMILY_ROGUE
:
456 if(m_caster
->GetTypeId()==TYPEID_PLAYER
&& (m_spellInfo
->SpellFamilyFlags
& 0x800000000LL
))
458 // consume from stack dozes not more that have combo-points
459 if(uint32 combo
= ((Player
*)m_caster
)->GetComboPoints())
461 // count consumed deadly poison doses at target
464 // remove consumed poison doses
465 Unit::AuraList
const& auras
= unitTarget
->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE
);
466 for(Unit::AuraList::const_iterator itr
= auras
.begin(); itr
!=auras
.end() && combo
;)
468 // Deadly poison (only attacker applied)
469 if( (*itr
)->GetSpellProto()->SpellFamilyName
==SPELLFAMILY_ROGUE
&& ((*itr
)->GetSpellProto()->SpellFamilyFlags
& 0x10000) &&
470 (*itr
)->GetSpellProto()->SpellVisual
[0]==5100 && (*itr
)->GetCasterGUID()==m_caster
->GetGUID() )
475 unitTarget
->RemoveSingleAuraFromStack((*itr
)->GetId(), (*itr
)->GetEffIndex());
484 damage
+= int32(((Player
*)m_caster
)->GetTotalAttackPowerValue(BASE_ATTACK
) * 0.03f
* doses
);
486 // Eviscerate and Envenom Bonus Damage (item set effect)
487 if(m_caster
->GetDummyAura(37169))
488 damage
+= ((Player
*)m_caster
)->GetComboPoints()*40;
492 else if((m_spellInfo
->SpellFamilyFlags
& 0x00020000LL
) && m_caster
->GetTypeId()==TYPEID_PLAYER
)
494 if(uint32 combo
= ((Player
*)m_caster
)->GetComboPoints())
496 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
) * combo
* 0.03f
);
498 // Eviscerate and Envenom Bonus Damage (item set effect)
499 if(m_caster
->GetDummyAura(37169))
505 case SPELLFAMILY_HUNTER
:
508 if((m_spellInfo
->SpellFamilyFlags
& 0x000000002) && m_spellInfo
->SpellVisual
[0]==342)
510 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
)*0.2);
513 else if((m_spellInfo
->SpellFamilyFlags
& 0x00000800) && m_spellInfo
->maxLevel
> 0)
515 damage
+= int32(m_caster
->GetTotalAttackPowerValue(RANGED_ATTACK
)*0.15);
518 else if(m_spellInfo
->SpellFamilyFlags
& 0x100000000LL
)
520 int32 base
= irand((int32
)m_caster
->GetWeaponDamageRange(RANGED_ATTACK
, MINDAMAGE
),(int32
)m_caster
->GetWeaponDamageRange(RANGED_ATTACK
, MAXDAMAGE
));
521 damage
+= int32(float(base
)/m_caster
->GetAttackTime(RANGED_ATTACK
)*2800 + m_caster
->GetTotalAttackPowerValue(RANGED_ATTACK
)*0.2f
);
523 //Explosive Trap Effect
524 else if(m_spellInfo
->SpellFamilyFlags
& 0x00000004)
526 damage
+= int32(m_caster
->GetTotalAttackPowerValue(RANGED_ATTACK
)*0.1);
530 case SPELLFAMILY_PALADIN
:
532 //Judgement of Vengeance
533 if((m_spellInfo
->SpellFamilyFlags
& 0x800000000LL
) && m_spellInfo
->SpellIconID
==2292)
536 Unit::AuraList
const& auras
= unitTarget
->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE
);
537 for(Unit::AuraList::const_iterator itr
= auras
.begin(); itr
!=auras
.end(); ++itr
)
538 if((*itr
)->GetId() == 31803 && (*itr
)->GetCasterGUID()==m_caster
->GetGUID())
541 //No damage if the target isn't affected by this
553 if(m_originalCaster
) // m_caster only passive source of cast
554 finalDamage
= m_originalCaster
->SpellNonMeleeDamageLog(unitTarget
, m_spellInfo
->Id
, damage
, m_IsTriggeredSpell
, true);
556 finalDamage
= m_caster
->SpellNonMeleeDamageLog(unitTarget
, m_spellInfo
->Id
, damage
, m_IsTriggeredSpell
, true);
559 switch(m_spellInfo
->SpellFamilyName
)
561 case SPELLFAMILY_WARRIOR
:
564 if(m_spellInfo
->SpellFamilyFlags
& 0x40000000000LL
)
567 switch(m_spellInfo
->Id
)
569 case 23881: BTAura
= 23885; break;
570 case 23892: BTAura
= 23886; break;
571 case 23893: BTAura
= 23887; break;
572 case 23894: BTAura
= 23888; break;
573 case 25251: BTAura
= 25252; break;
574 case 30335: BTAura
= 30339; break;
576 sLog
.outError("Spell::EffectSchoolDMG: Spell %u not handled in BTAura",m_spellInfo
->Id
);
581 m_caster
->CastSpell(m_caster
,BTAura
,true);
585 case SPELLFAMILY_PRIEST
:
587 // Shadow Word: Death
588 if(finalDamage
> 0 && (m_spellInfo
->SpellFamilyFlags
& 0x0000000200000000LL
) && unitTarget
->isAlive())
589 // deals damage equal to damage done to caster if victim is not killed
590 m_caster
->SpellNonMeleeDamageLog( m_caster
, m_spellInfo
->Id
, finalDamage
, m_IsTriggeredSpell
, false);
594 case SPELLFAMILY_PALADIN
:
596 // Judgement of Blood
597 if(finalDamage
> 0 && (m_spellInfo
->SpellFamilyFlags
& 0x0000000800000000LL
) && m_spellInfo
->SpellIconID
==153)
599 int32 damagePoint
= finalDamage
* 33 / 100;
600 m_caster
->CastCustomSpell(m_caster
, 32220, &damagePoint
, NULL
, NULL
, true);
609 void Spell::EffectDummy(uint32 i
)
611 if(!unitTarget
&& !gameObjTarget
&& !itemTarget
)
614 // selection by spell family
615 switch(m_spellInfo
->SpellFamilyName
)
617 case SPELLFAMILY_GENERIC
:
619 switch(m_spellInfo
->Id
)
621 case 8063: // Deviate Fish
623 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
629 case 1: spell_id
= 8064; break; // Sleepy
630 case 2: spell_id
= 8065; break; // Invigorate
631 case 3: spell_id
= 8066; break; // Shrink
632 case 4: spell_id
= 8067; break; // Party Time!
633 case 5: spell_id
= 8068; break; // Healthy Spirit
635 m_caster
->CastSpell(m_caster
,spell_id
,true,NULL
);
638 case 8213: // Savory Deviate Delight
640 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
647 case 1: spell_id
= (m_caster
->getGender() == GENDER_MALE
? 8219 : 8220); break;
649 case 2: spell_id
= (m_caster
->getGender() == GENDER_MALE
? 8221 : 8222); break;
651 m_caster
->CastSpell(m_caster
,spell_id
,true,NULL
);
654 case 8593: // Symbol of life (restore creature to life)
655 case 31225: // Shimmering Vessel (restore creature to life)
657 if(!unitTarget
|| unitTarget
->GetTypeId()!=TYPEID_UNIT
)
659 ((Creature
*)unitTarget
)->setDeathState(JUST_ALIVED
);
662 case 12162: // Deep wounds
663 case 12850: // (now good common check for this spells)
670 // DW should benefit of attack power, damage percent mods etc.
671 // TODO: check if using offhand damage is correct and if it should be divided by 2
672 if (m_caster
->haveOffhandWeapon() && m_caster
->getAttackTimer(BASE_ATTACK
) > m_caster
->getAttackTimer(OFF_ATTACK
))
673 damage
= (m_caster
->GetFloatValue(UNIT_FIELD_MINOFFHANDDAMAGE
) + m_caster
->GetFloatValue(UNIT_FIELD_MAXOFFHANDDAMAGE
))/2;
675 damage
= (m_caster
->GetFloatValue(UNIT_FIELD_MINDAMAGE
) + m_caster
->GetFloatValue(UNIT_FIELD_MAXDAMAGE
))/2;
677 switch (m_spellInfo
->Id
)
679 case 12850: damage
*= 0.2f
; break;
680 case 12162: damage
*= 0.4f
; break;
681 case 12868: damage
*= 0.6f
; break;
683 sLog
.outError("Spell::EffectDummy: Spell %u not handled in DW",m_spellInfo
->Id
);
687 int32 deepWoundsDotBasePoints0
= int32(damage
/ 4);
688 m_caster
->CastCustomSpell(unitTarget
, 12721, &deepWoundsDotBasePoints0
, NULL
, NULL
, true, NULL
);
691 case 12975: //Last Stand
693 int32 healthModSpellBasePoints0
= int32(m_caster
->GetMaxHealth()*0.3);
694 m_caster
->CastCustomSpell(m_caster
, 12976, &healthModSpellBasePoints0
, NULL
, NULL
, true, NULL
);
697 case 13120: // net-o-matic
704 uint32 roll
= urand(0, 99);
706 if(roll
< 2) // 2% for 30 sec self root (off-like chance unknown)
708 else if(roll
< 4) // 2% for 20 sec root, charge to target (off-like chance unknown)
713 m_caster
->CastSpell(unitTarget
,spell_id
,true,NULL
);
716 case 13567: // Dummy Trigger
718 // can be used for different aura triggering, so select by aura
719 if(!m_triggeredByAuraSpell
|| !unitTarget
)
722 switch(m_triggeredByAuraSpell
->Id
)
724 case 26467: // Persistent Shield
725 m_caster
->CastCustomSpell(unitTarget
, 26470, &damage
, NULL
, NULL
, true);
728 sLog
.outError("EffectDummy: Non-handled case for spell 13567 for triggered aura %u",m_triggeredByAuraSpell
->Id
);
733 case 14185: // Preparation Rogue
735 if(m_caster
->GetTypeId()!=TYPEID_PLAYER
)
738 //immediately finishes the cooldown on certain Rogue abilities
739 const PlayerSpellMap
& sp_list
= ((Player
*)m_caster
)->GetSpellMap();
740 for (PlayerSpellMap::const_iterator itr
= sp_list
.begin(); itr
!= sp_list
.end(); ++itr
)
742 uint32 classspell
= itr
->first
;
743 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(classspell
);
745 if (spellInfo
->SpellFamilyName
== SPELLFAMILY_ROGUE
&& (spellInfo
->SpellFamilyFlags
& 0x26000000860LL
))
747 ((Player
*)m_caster
)->RemoveSpellCooldown(classspell
);
749 WorldPacket
data(SMSG_CLEAR_COOLDOWN
, (4+8));
750 data
<< uint32(classspell
);
751 data
<< uint64(m_caster
->GetGUID());
752 ((Player
*)m_caster
)->GetSession()->SendPacket(&data
);
757 case 15998: // Capture Worg Pup
758 case 29435: // Capture Female Kaliri Hatchling
760 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_UNIT
)
763 Creature
* creatureTarget
= (Creature
*)unitTarget
;
764 creatureTarget
->setDeathState(JUST_DIED
);
765 creatureTarget
->RemoveCorpse();
766 creatureTarget
->SetHealth(0); // just for nice GM-mode view
769 case 16589: // Noggenfogger Elixir
771 if(m_caster
->GetTypeId()!=TYPEID_PLAYER
)
777 case 1: spell_id
= 16595; break;
778 case 2: spell_id
= 16593; break;
779 default:spell_id
= 16591; break;
782 m_caster
->CastSpell(m_caster
,spell_id
,true,NULL
);
785 case 17251: // Spirit Healer Res
787 if(!unitTarget
|| !m_originalCaster
)
790 if(m_originalCaster
->GetTypeId() == TYPEID_PLAYER
)
792 WorldPacket
data(SMSG_SPIRIT_HEALER_CONFIRM
, 8);
793 data
<< unitTarget
->GetGUID();
794 ((Player
*)m_originalCaster
)->GetSession()->SendPacket( &data
);
798 case 17271: // Test Fetid Skull
800 if(!itemTarget
&& m_caster
->GetTypeId()!=TYPEID_PLAYER
)
803 uint32 spell_id
= roll_chance_i(50) ? 17269 : 17270;
805 m_caster
->CastSpell(m_caster
,spell_id
,true,NULL
);
808 case 20577: // Cannibalize
810 m_caster
->CastSpell(m_caster
,20578,false,NULL
);
812 case 23019: // Crystal Prison Dummy DND
814 if(!unitTarget
|| !unitTarget
->isAlive() || unitTarget
->GetTypeId() != TYPEID_UNIT
|| ((Creature
*)unitTarget
)->isPet())
817 Creature
* creatureTarget
= (Creature
*)unitTarget
;
818 if(creatureTarget
->isPet())
821 creatureTarget
->setDeathState(JUST_DIED
);
822 creatureTarget
->RemoveCorpse();
823 creatureTarget
->SetHealth(0); // just for nice GM-mode view
825 GameObject
* pGameObj
= new GameObject
;
827 Map
*map
= creatureTarget
->GetMap();
829 if(!pGameObj
->Create(objmgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), 179644, map
,
830 creatureTarget
->GetPositionX(), creatureTarget
->GetPositionY(), creatureTarget
->GetPositionZ(),
831 creatureTarget
->GetOrientation(), 0, 0, 0, 0, 100, 1) )
837 pGameObj
->SetRespawnTime(creatureTarget
->GetRespawnTime()-time(NULL
));
838 pGameObj
->SetOwnerGUID(m_caster
->GetGUID() );
839 pGameObj
->SetUInt32Value(GAMEOBJECT_LEVEL
, m_caster
->getLevel() );
840 pGameObj
->SetSpellId(m_spellInfo
->Id
);
842 DEBUG_LOG("AddObject at SpellEfects.cpp EffectDummy\n");
845 WorldPacket
data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE
, 8);
846 data
<< uint64(pGameObj
->GetGUID());
847 m_caster
->SendMessageToSet(&data
,true);
851 case 23074: // Arc. Dragonling
852 if (!m_CastItem
) return;
853 m_caster
->CastSpell(m_caster
,19804,true,m_CastItem
);
855 case 23075: // Mithril Mechanical Dragonling
856 if (!m_CastItem
) return;
857 m_caster
->CastSpell(m_caster
,12749,true,m_CastItem
);
859 case 23076: // Mechanical Dragonling
860 if (!m_CastItem
) return;
861 m_caster
->CastSpell(m_caster
,4073,true,m_CastItem
);
863 case 23133: // Gnomish Battle Chicken
864 if (!m_CastItem
) return;
865 m_caster
->CastSpell(m_caster
,13166,true,m_CastItem
);
867 case 23448: // Ultrasafe Transporter: Gadgetzan - backfires
869 int32 r
= irand(0, 119);
870 if ( r
< 20 ) // 1/6 polymorph
871 m_caster
->CastSpell(m_caster
,23444,true);
872 else if ( r
< 100 ) // 4/6 evil twin
873 m_caster
->CastSpell(m_caster
,23445,true);
874 else // 1/6 miss the target
875 m_caster
->CastSpell(m_caster
,36902,true);
878 case 23453: // Ultrasafe Transporter: Gadgetzan
879 if ( roll_chance_i(50) ) // success
880 m_caster
->CastSpell(m_caster
,23441,true);
882 m_caster
->CastSpell(m_caster
,23446,true);
884 case 23645: // Hourglass Sand
885 m_caster
->RemoveAurasDueToSpell(23170);
887 case 23725: // Gift of Life (warrior bwl trinket)
888 m_caster
->CastSpell(m_caster
,23782,true);
889 m_caster
->CastSpell(m_caster
,23783,true);
891 case 25860: // Reindeer Transformation
893 if (!m_caster
->HasAuraType(SPELL_AURA_MOUNTED
))
896 float flyspeed
= m_caster
->GetSpeedRate(MOVE_FLIGHT
);
897 float speed
= m_caster
->GetSpeedRate(MOVE_RUN
);
899 m_caster
->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED
);
901 //5 different spells used depending on mounted speed and if mount can fly or not
902 if (flyspeed
>= 4.1f
)
903 m_caster
->CastSpell(m_caster
, 44827, true); //310% flying Reindeer
904 else if (flyspeed
>= 3.8f
)
905 m_caster
->CastSpell(m_caster
, 44825, true); //280% flying Reindeer
906 else if (flyspeed
>= 1.6f
)
907 m_caster
->CastSpell(m_caster
, 44824, true); //60% flying Reindeer
908 else if (speed
>= 2.0f
)
909 m_caster
->CastSpell(m_caster
, 25859, true); //100% ground Reindeer
911 m_caster
->CastSpell(m_caster
, 25858, true); //60% ground Reindeer
915 //case 26074: // Holiday Cheer
916 // return; -- implemented at client side
917 case 28006: // Arcane Cloaking
919 if( unitTarget
->GetTypeId() == TYPEID_PLAYER
)
920 m_caster
->CastSpell(unitTarget
,29294,true);
923 case 28730: // Arcane Torrent (Mana)
926 Unit::AuraList
const& m_dummyAuras
= m_caster
->GetAurasByType(SPELL_AURA_DUMMY
);
927 for(Unit::AuraList::const_iterator i
= m_dummyAuras
.begin(); i
!= m_dummyAuras
.end(); ++i
)
928 if ((*i
)->GetId() == 28734)
932 m_caster
->RemoveAurasDueToSpell(28734);
933 int32 bp
= damage
* count
;
934 m_caster
->CastCustomSpell(m_caster
, 28733, &bp
, NULL
, NULL
, true);
938 case 29200: // Purify Helboar Meat
940 if( m_caster
->GetTypeId() != TYPEID_PLAYER
)
943 uint32 spell_id
= roll_chance_i(50) ? 29277 : 29278;
945 m_caster
->CastSpell(m_caster
,spell_id
,true,NULL
);
948 case 29858: // Soulshatter
949 if (unitTarget
&& unitTarget
->GetTypeId() == TYPEID_UNIT
&& unitTarget
->IsHostileTo(m_caster
))
950 m_caster
->CastSpell(unitTarget
,32835,true);
952 case 30458: // Nigh Invulnerability
953 if (!m_CastItem
) return;
954 if(roll_chance_i(86)) // success
955 m_caster
->CastSpell(m_caster
, 30456, true, m_CastItem
);
956 else // backfire in 14% casts
957 m_caster
->CastSpell(m_caster
, 30457, true, m_CastItem
);
959 case 30507: // Poultryizer
960 if (!m_CastItem
) return;
961 if(roll_chance_i(80)) // success
962 m_caster
->CastSpell(unitTarget
, 30501, true, m_CastItem
);
964 m_caster
->CastSpell(unitTarget
, 30504, true, m_CastItem
);
966 case 33060: // Make a Wish
968 if(m_caster
->GetTypeId()!=TYPEID_PLAYER
)
975 case 1: spell_id
= 33053; break;
976 case 2: spell_id
= 33057; break;
977 case 3: spell_id
= 33059; break;
978 case 4: spell_id
= 33062; break;
979 case 5: spell_id
= 33064; break;
982 m_caster
->CastSpell(m_caster
,spell_id
,true,NULL
);
988 switch(m_caster
->GetAreaId())
990 case 3900: spell_id
= 35743; break;
991 case 3742: spell_id
= 35744; break;
995 m_caster
->CastSpell(m_caster
,spell_id
,true);
998 case 37674: // Chaos Blast
1003 int32 basepoints0
= 100;
1004 m_caster
->CastCustomSpell(unitTarget
,37675,&basepoints0
,NULL
,NULL
,true);
1007 case 40802: // Mingo's Fortune Generator (Mingo's Fortune Giblets)
1009 // selecting one from Bloodstained Fortune item
1013 case 1: newitemid
= 32688; break;
1014 case 2: newitemid
= 32689; break;
1015 case 3: newitemid
= 32690; break;
1016 case 4: newitemid
= 32691; break;
1017 case 5: newitemid
= 32692; break;
1018 case 6: newitemid
= 32693; break;
1019 case 7: newitemid
= 32700; break;
1020 case 8: newitemid
= 32701; break;
1021 case 9: newitemid
= 32702; break;
1022 case 10: newitemid
= 32703; break;
1023 case 11: newitemid
= 32704; break;
1024 case 12: newitemid
= 32705; break;
1025 case 13: newitemid
= 32706; break;
1026 case 14: newitemid
= 32707; break;
1027 case 15: newitemid
= 32708; break;
1028 case 16: newitemid
= 32709; break;
1029 case 17: newitemid
= 32710; break;
1030 case 18: newitemid
= 32711; break;
1031 case 19: newitemid
= 32712; break;
1032 case 20: newitemid
= 32713; break;
1037 DoCreateItem(i
,newitemid
);
1040 // Demon Broiled Surprise
1041 /* FIX ME: Required for correct work implementing implicit target 7 (in pair (22,7))
1044 if (m_caster->GetTypeId() != TYPEID_PLAYER)
1047 ((Player*)m_caster)->CastSpell(unitTarget, 43753, true);
1051 case 44875: // Complete Raptor Capture
1053 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_UNIT
)
1056 Creature
* creatureTarget
= (Creature
*)unitTarget
;
1058 creatureTarget
->setDeathState(JUST_DIED
);
1059 creatureTarget
->RemoveCorpse();
1060 creatureTarget
->SetHealth(0); // just for nice GM-mode view
1062 //cast spell Raptor Capture Credit
1063 m_caster
->CastSpell(m_caster
,42337,true,NULL
);
1066 case 37573: //Temporal Phase Modulator
1071 TemporarySummon
* tempSummon
= dynamic_cast<TemporarySummon
*>(unitTarget
);
1075 uint32 health
= tempSummon
->GetHealth();
1076 const uint32 entry_list
[6] = {21821, 21820, 21817};
1078 float x
= tempSummon
->GetPositionX();
1079 float y
= tempSummon
->GetPositionY();
1080 float z
= tempSummon
->GetPositionZ();
1081 float o
= tempSummon
->GetOrientation();
1083 tempSummon
->UnSummon();
1085 Creature
* pCreature
= m_caster
->SummonCreature(entry_list
[urand(0, 2)], x
, y
, z
, o
,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN
,180000);
1089 pCreature
->SetHealth(health
);
1092 pCreature
->AI()->AttackStart(m_caster
);
1096 case 34665: //Administer Antidote
1098 if(!unitTarget
|| m_caster
->GetTypeId() != TYPEID_PLAYER
)
1104 TemporarySummon
* tempSummon
= dynamic_cast<TemporarySummon
*>(unitTarget
);
1108 uint32 health
= tempSummon
->GetHealth();
1110 float x
= tempSummon
->GetPositionX();
1111 float y
= tempSummon
->GetPositionY();
1112 float z
= tempSummon
->GetPositionZ();
1113 float o
= tempSummon
->GetOrientation();
1114 tempSummon
->UnSummon();
1116 Creature
* pCreature
= m_caster
->SummonCreature(16992, x
, y
, z
, o
,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN
,180000);
1120 pCreature
->SetHealth(health
);
1121 ((Player
*)m_caster
)->KilledMonster(16992,pCreature
->GetGUID());
1123 if (pCreature
->AI())
1124 pCreature
->AI()->AttackStart(m_caster
);
1128 case 44997: // Converting Sentry
1130 //Converted Sentry Credit
1131 m_caster
->CastSpell(m_caster
, 45009, true);
1134 case 45030: // Impale Emissary
1136 // Emissary of Hate Credit
1137 m_caster
->CastSpell(m_caster
, 45088, true);
1140 case 50243: // Teach Language
1142 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
1145 // spell has a 1/3 chance to trigger one of the below
1146 if(roll_chance_i(66))
1148 if(((Player
*)m_caster
)->GetTeam() == ALLIANCE
)
1150 // 1000001 - gnomish binary
1151 m_caster
->CastSpell(m_caster
, 50242, true);
1155 // 01001000 - goblin binary
1156 m_caster
->CastSpell(m_caster
, 50246, true);
1161 case 51582: //Rocket Boots Engaged (Rocket Boots Xtreme and Rocket Boots Xtreme Lite)
1163 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
1166 if(BattleGround
* bg
= ((Player
*)m_caster
)->GetBattleGround())
1167 bg
->EventPlayerDroppedFlag((Player
*)m_caster
);
1169 m_caster
->CastSpell(m_caster
, 30452, true, NULL
);
1174 //All IconID Check in there
1175 switch(m_spellInfo
->SpellIconID
)
1177 // Berserking (troll racial traits)
1180 uint32 healthPerc
= uint32((float(m_caster
->GetHealth())/m_caster
->GetMaxHealth())*100);
1181 int32 melee_mod
= 10;
1182 if (healthPerc
<= 40)
1184 if (healthPerc
< 100 && healthPerc
> 40)
1185 melee_mod
= 10+(100-healthPerc
)/3;
1187 int32 hasteModBasePoints0
= melee_mod
; // (EffectBasePoints[0]+1)-1+(5-melee_mod) = (melee_mod-1+1)-1+5-melee_mod = 5-1
1188 int32 hasteModBasePoints1
= (5-melee_mod
);
1189 int32 hasteModBasePoints2
= 5;
1191 // FIXME: custom spell required this aura state by some unknown reason, we not need remove it anyway
1192 m_caster
->ModifyAuraState(AURA_STATE_BERSERKING
,true);
1193 m_caster
->CastCustomSpell(m_caster
,26635,&hasteModBasePoints0
,&hasteModBasePoints1
,&hasteModBasePoints2
,true,NULL
);
1199 case SPELLFAMILY_MAGE
:
1200 switch(m_spellInfo
->Id
)
1202 case 11958: // Cold Snap
1204 if(m_caster
->GetTypeId()!=TYPEID_PLAYER
)
1207 // immediately finishes the cooldown on Frost spells
1208 const PlayerSpellMap
& sp_list
= ((Player
*)m_caster
)->GetSpellMap();
1209 for (PlayerSpellMap::const_iterator itr
= sp_list
.begin(); itr
!= sp_list
.end(); ++itr
)
1211 if (itr
->second
->state
== PLAYERSPELL_REMOVED
)
1214 uint32 classspell
= itr
->first
;
1215 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(classspell
);
1217 if( spellInfo
->SpellFamilyName
== SPELLFAMILY_MAGE
&&
1218 (GetSpellSchoolMask(spellInfo
) & SPELL_SCHOOL_MASK_FROST
) &&
1219 spellInfo
->Id
!= 11958 && GetSpellRecoveryTime(spellInfo
) > 0 )
1221 ((Player
*)m_caster
)->RemoveSpellCooldown(classspell
);
1223 WorldPacket
data(SMSG_CLEAR_COOLDOWN
, (4+8));
1224 data
<< uint32(classspell
);
1225 data
<< uint64(m_caster
->GetGUID());
1226 ((Player
*)m_caster
)->GetSession()->SendPacket(&data
);
1233 if ( unitTarget
&& unitTarget
->GetTypeId() == TYPEID_UNIT
)
1235 //Polymorph Cast Visual Rank 1
1236 const uint32 spell_list
[6] = {32813, 32816, 32817, 32818, 32819, 32820};
1237 unitTarget
->CastSpell( unitTarget
, spell_list
[urand(0, 5)], true);
1243 case SPELLFAMILY_WARRIOR
:
1245 if(m_spellInfo
->SpellFamilyFlags
& 0x1 && m_spellInfo
->SpellVisual
[0] == 867)
1247 int32 chargeBasePoints0
= damage
;
1248 m_caster
->CastCustomSpell(m_caster
,34846,&chargeBasePoints0
,NULL
,NULL
,true);
1252 if(m_spellInfo
->SpellFamilyFlags
& 0x20000000)
1257 int32 basePoints0
= damage
+int32(m_caster
->GetPower(POWER_RAGE
) * m_spellInfo
->DmgMultiplier
[i
]);
1258 m_caster
->CastCustomSpell(unitTarget
, 20647, &basePoints0
, NULL
, NULL
, true, 0);
1259 m_caster
->SetPower(POWER_RAGE
,0);
1262 if(m_spellInfo
->Id
==21977) //Warrior's Wrath
1267 m_caster
->CastSpell(unitTarget
,21887,true); // spell mod
1271 case SPELLFAMILY_WARLOCK
:
1272 //Life Tap (only it have this with dummy effect)
1273 if (m_spellInfo
->SpellFamilyFlags
== 0x40000)
1275 float cost
= m_currentBasePoints
[0]+1;
1277 if(Player
* modOwner
= m_caster
->GetSpellModOwner())
1278 modOwner
->ApplySpellMod(m_spellInfo
->Id
, SPELLMOD_COST
, cost
,this);
1280 int32 dmg
= m_caster
->SpellDamageBonus(m_caster
, m_spellInfo
,uint32(cost
> 0 ? cost
: 0), SPELL_DIRECT_DAMAGE
);
1282 if(int32(m_caster
->GetHealth()) > dmg
)
1284 // Shouldn't Appear in Combat Log
1285 m_caster
->ModifyHealth(-dmg
);
1289 Unit::AuraList
const& auraDummy
= m_caster
->GetAurasByType(SPELL_AURA_DUMMY
);
1290 for(Unit::AuraList::const_iterator itr
= auraDummy
.begin(); itr
!= auraDummy
.end(); ++itr
)
1292 // only Imp. Life Tap have this in combination with dummy aura
1293 if((*itr
)->GetSpellProto()->SpellFamilyName
==SPELLFAMILY_WARLOCK
&& (*itr
)->GetSpellProto()->SpellIconID
== 208)
1294 mana
= ((*itr
)->GetModifier()->m_amount
+ 100)* mana
/ 100;
1297 m_caster
->CastCustomSpell(m_caster
,31818,&mana
,NULL
,NULL
,true,NULL
);
1300 int32 manaFeedVal
= m_caster
->CalculateSpellDamage(m_spellInfo
,1, m_spellInfo
->EffectBasePoints
[1],m_caster
);
1301 manaFeedVal
= manaFeedVal
* mana
/ 100;
1303 m_caster
->CastCustomSpell(m_caster
,32553,&manaFeedVal
,NULL
,NULL
,true,NULL
);
1306 SendCastResult(SPELL_FAILED_FIZZLE
);
1310 case SPELLFAMILY_PRIEST
:
1311 switch(m_spellInfo
->Id
)
1313 case 28598: // Touch of Weakness triggered spell
1315 if(!unitTarget
|| !m_triggeredByAuraSpell
)
1319 switch(m_triggeredByAuraSpell
->Id
)
1321 case 2652: spellid
= 2943; break; // Rank 1
1322 case 19261: spellid
= 19249; break; // Rank 2
1323 case 19262: spellid
= 19251; break; // Rank 3
1324 case 19264: spellid
= 19252; break; // Rank 4
1325 case 19265: spellid
= 19253; break; // Rank 5
1326 case 19266: spellid
= 19254; break; // Rank 6
1327 case 25461: spellid
= 25460; break; // Rank 7
1329 sLog
.outError("Spell::EffectDummy: Spell 28598 triggered by unhandeled spell %u",m_triggeredByAuraSpell
->Id
);
1332 m_caster
->CastSpell(unitTarget
, spellid
, true, NULL
);
1337 case SPELLFAMILY_DRUID
:
1338 switch(m_spellInfo
->Id
)
1340 case 5420: // Tree of Life passive
1342 // Tree of Life area effect
1343 int32 health_mod
= int32(m_caster
->GetStat(STAT_SPIRIT
)/4);
1344 m_caster
->CastCustomSpell(m_caster
,34123,&health_mod
,NULL
,NULL
,true,NULL
);
1349 case SPELLFAMILY_ROGUE
:
1350 switch(m_spellInfo
->Id
)
1352 case 31231: // Cheat Death
1354 m_caster
->CastSpell(m_caster
,45182,true);
1359 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
1362 Player
*pCaster
= ((Player
*)m_caster
);
1364 Item
*item
= pCaster
->GetWeaponForAttack(OFF_ATTACK
);
1368 // all poison enchantments is temporary
1369 uint32 enchant_id
= item
->GetEnchantmentId(TEMP_ENCHANTMENT_SLOT
);
1373 SpellItemEnchantmentEntry
const *pEnchant
= sSpellItemEnchantmentStore
.LookupEntry(enchant_id
);
1377 for (int s
=0;s
<3;s
++)
1379 if(pEnchant
->type
[s
]!=ITEM_ENCHANTMENT_TYPE_COMBAT_SPELL
)
1382 SpellEntry
const* combatEntry
= sSpellStore
.LookupEntry(pEnchant
->spellid
[s
]);
1383 if(!combatEntry
|| combatEntry
->Dispel
!= DISPEL_POISON
)
1386 m_caster
->CastSpell(unitTarget
, combatEntry
, true, item
);
1389 m_caster
->CastSpell(unitTarget
, 5940, true);
1394 case SPELLFAMILY_HUNTER
:
1396 if(m_spellInfo
->SpellFamilyFlags
& 0x100000000LL
)
1398 if( !unitTarget
|| !unitTarget
->isAlive())
1403 // check dazed affect
1404 Unit::AuraList
const& decSpeedList
= unitTarget
->GetAurasByType(SPELL_AURA_MOD_DECREASE_SPEED
);
1405 for(Unit::AuraList::const_iterator iter
= decSpeedList
.begin(); iter
!= decSpeedList
.end(); ++iter
)
1407 if((*iter
)->GetSpellProto()->SpellIconID
==15 && (*iter
)->GetSpellProto()->Dispel
==0)
1415 m_caster
->SpellNonMeleeDamageLog(unitTarget
, m_spellInfo
->Id
, damage
, m_IsTriggeredSpell
, true);
1419 if(m_spellInfo
->SpellFamilyFlags
& 0x00080000000000LL
)
1421 if(m_caster
->getClass()!=CLASS_HUNTER
)
1424 // clear hunter crit aura state
1425 m_caster
->ModifyAuraState(AURA_STATE_HUNTER_CRIT_STRIKE
,false);
1427 // additional damage from pet to pet target
1428 Pet
* pet
= m_caster
->GetPet();
1429 if(!pet
|| !pet
->getVictim())
1432 uint32 spell_id
= 0;
1433 switch (m_spellInfo
->Id
)
1435 case 34026: spell_id
= 34027; break; // rank 1
1437 sLog
.outError("Spell::EffectDummy: Spell %u not handled in KC",m_spellInfo
->Id
);
1441 pet
->CastSpell(pet
->getVictim(), spell_id
, true);
1445 switch(m_spellInfo
->Id
)
1447 case 23989: //Readiness talent
1449 if(m_caster
->GetTypeId()!=TYPEID_PLAYER
)
1452 //immediately finishes the cooldown for hunter abilities
1453 const PlayerSpellMap
& sp_list
= ((Player
*)m_caster
)->GetSpellMap();
1454 for (PlayerSpellMap::const_iterator itr
= sp_list
.begin(); itr
!= sp_list
.end(); ++itr
)
1456 uint32 classspell
= itr
->first
;
1457 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(classspell
);
1459 if (spellInfo
->SpellFamilyName
== SPELLFAMILY_HUNTER
&& spellInfo
->Id
!= 23989 && GetSpellRecoveryTime(spellInfo
) > 0 )
1461 ((Player
*)m_caster
)->RemoveSpellCooldown(classspell
);
1463 WorldPacket
data(SMSG_CLEAR_COOLDOWN
, (4+8));
1464 data
<< uint32(classspell
);
1465 data
<< uint64(m_caster
->GetGUID());
1466 ((Player
*)m_caster
)->GetSession()->SendPacket(&data
);
1471 case 37506: // Scatter Shot
1473 if (m_caster
->GetTypeId()!=TYPEID_PLAYER
)
1476 // break Auto Shot and autohit
1477 m_caster
->InterruptSpell(CURRENT_AUTOREPEAT_SPELL
);
1478 m_caster
->AttackStop();
1479 ((Player
*)m_caster
)->SendAttackSwingCancelAttack();
1484 case SPELLFAMILY_PALADIN
:
1485 switch(m_spellInfo
->SpellIconID
)
1487 case 156: // Holy Shock
1495 switch(m_spellInfo
->Id
)
1497 case 20473: hurt
= 25912; heal
= 25914; break;
1498 case 20929: hurt
= 25911; heal
= 25913; break;
1499 case 20930: hurt
= 25902; heal
= 25903; break;
1500 case 27174: hurt
= 27176; heal
= 27175; break;
1501 case 33072: hurt
= 33073; heal
= 33074; break;
1503 sLog
.outError("Spell::EffectDummy: Spell %u not handled in HS",m_spellInfo
->Id
);
1507 if(m_caster
->IsFriendlyTo(unitTarget
))
1508 m_caster
->CastSpell(unitTarget
, heal
, true, 0);
1510 m_caster
->CastSpell(unitTarget
, hurt
, true, 0);
1514 case 561: // Judgement of command
1519 uint32 spell_id
= m_currentBasePoints
[i
]+1;
1520 SpellEntry
const* spell_proto
= sSpellStore
.LookupEntry(spell_id
);
1524 if( !unitTarget
->hasUnitState(UNIT_STAT_STUNNED
) && m_caster
->GetTypeId()==TYPEID_PLAYER
)
1526 // decreased damage (/2) for non-stunned target.
1527 SpellModifier
*mod
= new SpellModifier
;
1528 mod
->op
= SPELLMOD_DAMAGE
;
1530 mod
->type
= SPELLMOD_PCT
;
1531 mod
->spellId
= m_spellInfo
->Id
;
1532 mod
->mask
= 0x0000020000000000LL
;
1535 ((Player
*)m_caster
)->AddSpellMod(mod
, true);
1536 m_caster
->CastSpell(unitTarget
,spell_proto
,true,NULL
);
1538 ((Player
*)m_caster
)->AddSpellMod(mod
, false);
1541 m_caster
->CastSpell(unitTarget
,spell_proto
,true,NULL
);
1547 switch(m_spellInfo
->Id
)
1549 case 31789: // Righteous Defense (step 1)
1551 // 31989 -> dummy effect (step 1) + dummy effect (step 2) -> 31709 (taunt like spell for each target)
1553 // non-standard cast requirement check
1554 if (!unitTarget
|| unitTarget
->getAttackers().empty())
1556 // clear cooldown at fail
1557 if(m_caster
->GetTypeId()==TYPEID_PLAYER
)
1559 ((Player
*)m_caster
)->RemoveSpellCooldown(m_spellInfo
->Id
);
1561 WorldPacket
data(SMSG_CLEAR_COOLDOWN
, (4+8));
1562 data
<< uint32(m_spellInfo
->Id
);
1563 data
<< uint64(m_caster
->GetGUID());
1564 ((Player
*)m_caster
)->GetSession()->SendPacket(&data
);
1567 SendCastResult(SPELL_FAILED_TARGET_AFFECTING_COMBAT
);
1571 // Righteous Defense (step 2) (in old version 31980 dummy effect)
1572 // Clear targets for eff 1
1573 for(std::list
<TargetInfo
>::iterator ihit
= m_UniqueTargetInfo
.begin();ihit
!= m_UniqueTargetInfo
.end();++ihit
)
1574 ihit
->effectMask
&= ~(1<<1);
1576 // not empty (checked)
1577 Unit::AttackerSet
const& attackers
= unitTarget
->getAttackers();
1579 // chance to be selected from list
1580 float chance
= 100.0f
/attackers
.size();
1582 for(Unit::AttackerSet::const_iterator aItr
= attackers
.begin(); aItr
!= attackers
.end() && count
< 3; ++aItr
)
1584 if(!roll_chance_f(chance
))
1587 AddUnitTarget((*aItr
), 1);
1590 // now let next effect cast spell at each target.
1593 case 37877: // Blessing of Faith
1598 uint32 spell_id
= 0;
1599 switch(unitTarget
->getClass())
1601 case CLASS_DRUID
: spell_id
= 37878; break;
1602 case CLASS_PALADIN
: spell_id
= 37879; break;
1603 case CLASS_PRIEST
: spell_id
= 37880; break;
1604 case CLASS_SHAMAN
: spell_id
= 37881; break;
1605 default: return; // ignore for not healing classes
1608 m_caster
->CastSpell(m_caster
,spell_id
,true);
1613 case SPELLFAMILY_SHAMAN
:
1614 //Shaman Rockbiter Weapon
1615 if (m_spellInfo
->SpellFamilyFlags
== 0x400000)
1617 uint32 spell_id
= 0;
1618 switch(m_spellInfo
->Id
)
1620 case 8017: spell_id
= 36494; break; // Rank 1
1621 case 8018: spell_id
= 36750; break; // Rank 2
1622 case 8019: spell_id
= 36755; break; // Rank 3
1623 case 10399: spell_id
= 36759; break; // Rank 4
1624 case 16314: spell_id
= 36763; break; // Rank 5
1625 case 16315: spell_id
= 36766; break; // Rank 6
1626 case 16316: spell_id
= 36771; break; // Rank 7
1627 case 25479: spell_id
= 36775; break; // Rank 8
1628 case 25485: spell_id
= 36499; break; // Rank 9
1630 sLog
.outError("Spell::EffectDummy: Spell %u not handled in RW",m_spellInfo
->Id
);
1634 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry( spell_id
);
1638 sLog
.outError("WORLD: unknown spell id %i\n", spell_id
);
1642 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
1645 for(int i
= BASE_ATTACK
; i
<= OFF_ATTACK
; ++i
)
1647 if(Item
* item
= ((Player
*)m_caster
)->GetWeaponForAttack(WeaponAttackType(i
)))
1649 if(item
->IsFitToSpellRequirements(m_spellInfo
))
1651 Spell
*spell
= new Spell(m_caster
, spellInfo
, true);
1653 // enchanting spell selected by calculated damage-per-sec in enchanting effect
1654 // at calculation applied affect from Elemental Weapons talent
1655 // real enchantment damage-1
1656 spell
->m_currentBasePoints
[1] = damage
-1;
1658 SpellCastTargets targets
;
1659 targets
.setItemTarget( item
);
1660 spell
->prepare(&targets
);
1667 if(m_spellInfo
->Id
== 39610) // Mana-Tide Totem effect
1669 if(!unitTarget
|| unitTarget
->getPowerType() != POWER_MANA
)
1672 // Regenerate 6% of Total Mana Every 3 secs
1673 int32 EffectBasePoints0
= unitTarget
->GetMaxPower(POWER_MANA
) * damage
/ 100;
1674 m_caster
->CastCustomSpell(unitTarget
,39609,&EffectBasePoints0
,NULL
,NULL
,true,NULL
,NULL
,m_originalCasterGUID
);
1682 if(PetAura
const* petSpell
= spellmgr
.GetPetAura(m_spellInfo
->Id
))
1684 m_caster
->AddPetAura(petSpell
);
1689 void Spell::EffectTriggerSpellWithValue(uint32 i
)
1691 uint32 triggered_spell_id
= m_spellInfo
->EffectTriggerSpell
[i
];
1694 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry( triggered_spell_id
);
1698 sLog
.outError("EffectTriggerSpellWithValue of spell %u: triggering unknown spell id %i\n", m_spellInfo
->Id
,triggered_spell_id
);
1703 m_caster
->CastCustomSpell(unitTarget
,triggered_spell_id
,&bp
,&bp
,&bp
,true,NULL
,NULL
,m_originalCasterGUID
);
1706 void Spell::EffectTriggerRitualOfSummoning(uint32 i
)
1708 uint32 triggered_spell_id
= m_spellInfo
->EffectTriggerSpell
[i
];
1709 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry( triggered_spell_id
);
1713 sLog
.outError("EffectTriggerRitualOfSummoning of spell %u: triggering unknown spell id %i", m_spellInfo
->Id
,triggered_spell_id
);
1718 Spell
*spell
= new Spell(m_caster
, spellInfo
, true);
1720 SpellCastTargets targets
;
1721 targets
.setUnitTarget( unitTarget
);
1722 spell
->prepare(&targets
);
1724 m_caster
->SetCurrentCastedSpell(spell
);
1725 spell
->m_selfContainer
= &(m_caster
->m_currentSpells
[spell
->GetCurrentContainer()]);
1729 void Spell::EffectForceCast(uint32 i
)
1734 uint32 triggered_spell_id
= m_spellInfo
->EffectTriggerSpell
[i
];
1737 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry( triggered_spell_id
);
1741 sLog
.outError("EffectForceCast of spell %u: triggering unknown spell id %i", m_spellInfo
->Id
,triggered_spell_id
);
1745 unitTarget
->CastSpell(unitTarget
,spellInfo
,true,NULL
,NULL
,m_originalCasterGUID
);
1748 void Spell::EffectTriggerSpell(uint32 i
)
1750 uint32 triggered_spell_id
= m_spellInfo
->EffectTriggerSpell
[i
];
1753 switch(triggered_spell_id
)
1758 m_caster
->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT
);
1759 m_caster
->RemoveSpellsCausingAura(SPELL_AURA_MOD_DECREASE_SPEED
);
1760 m_caster
->RemoveSpellsCausingAura(SPELL_AURA_MOD_STALKED
);
1762 // if this spell is given to NPC it must handle rest by it's own AI
1763 if ( m_caster
->GetTypeId() != TYPEID_PLAYER
)
1766 // get highest rank of the Stealth spell
1768 const PlayerSpellMap
& sp_list
= ((Player
*)m_caster
)->GetSpellMap();
1769 for (PlayerSpellMap::const_iterator itr
= sp_list
.begin(); itr
!= sp_list
.end(); ++itr
)
1771 // only highest rank is shown in spell book, so simply check if shown in spell book
1772 if(!itr
->second
->active
|| itr
->second
->disabled
|| itr
->second
->state
== PLAYERSPELL_REMOVED
)
1775 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(itr
->first
);
1779 if (spellInfo
->SpellFamilyName
== SPELLFAMILY_ROGUE
&& spellInfo
->SpellFamilyFlags
& SPELLFAMILYFLAG_ROGUE_STEALTH
)
1781 spellId
= spellInfo
->Id
;
1786 // no Stealth spell found
1790 // reset cooldown on it if needed
1791 if(((Player
*)m_caster
)->HasSpellCooldown(spellId
))
1792 ((Player
*)m_caster
)->RemoveSpellCooldown(spellId
);
1794 m_caster
->CastSpell(m_caster
, spellId
, true);
1798 case 23770: // Sayge's Dark Fortune of *
1799 // not exist, common cooldown can be implemented in scripts if need.
1801 // Brittle Armor - (need add max stack of 24575 Brittle Armor)
1804 const SpellEntry
*spell
= sSpellStore
.LookupEntry(24575);
1808 for (int i
=0; i
< spell
->StackAmount
; ++i
)
1809 m_caster
->CastSpell(unitTarget
,spell
->Id
, true, m_CastItem
, NULL
, m_originalCasterGUID
);
1812 // Mercurial Shield - (need add max stack of 26464 Mercurial Shield)
1815 const SpellEntry
*spell
= sSpellStore
.LookupEntry(26464);
1819 for (int i
=0; i
< spell
->StackAmount
; ++i
)
1820 m_caster
->CastSpell(unitTarget
,spell
->Id
, true, m_CastItem
, NULL
, m_originalCasterGUID
);
1823 // Righteous Defense
1826 m_caster
->CastSpell(unitTarget
, 31790, true,m_CastItem
,NULL
,m_originalCasterGUID
);
1832 Unit::AuraMap
& Auras
= m_caster
->GetAuras();
1833 for(Unit::AuraMap::iterator iter
= Auras
.begin(); iter
!= Auras
.end(); ++iter
)
1835 // remove all harmful spells on you...
1836 if( // ignore positive and passive auras
1837 !iter
->second
->IsPositive() && !iter
->second
->IsPassive() &&
1838 // ignore physical auras
1839 (GetSpellSchoolMask(iter
->second
->GetSpellProto()) & SPELL_SCHOOL_MASK_NORMAL
)==0 &&
1840 // ignore immunity persistent spells
1841 !( iter
->second
->GetSpellProto()->AttributesEx
& 0x10000 ) )
1843 m_caster
->RemoveAurasDueToSpell(iter
->second
->GetSpellProto()->Id
);
1844 iter
= Auras
.begin();
1849 // Priest Shadowfiend (34433) need apply mana gain trigger aura on pet
1852 if (Unit
*pet
= m_caster
->GetPet())
1853 pet
->CastSpell(pet
, 28305, true);
1859 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry( triggered_spell_id
);
1863 sLog
.outError("EffectTriggerSpell of spell %u: triggering unknown spell id %i", m_spellInfo
->Id
,triggered_spell_id
);
1867 // some triggered spells require specific equipment
1868 if(spellInfo
->EquippedItemClass
>=0 && m_caster
->GetTypeId()==TYPEID_PLAYER
)
1870 // main hand weapon required
1871 if(spellInfo
->AttributesEx3
& SPELL_ATTR_EX3_MAIN_HAND
)
1873 Item
* item
= ((Player
*)m_caster
)->GetWeaponForAttack(BASE_ATTACK
);
1875 // skip spell if no weapon in slot or broken
1876 if(!item
|| item
->IsBroken() )
1879 // skip spell if weapon not fit to triggered spell
1880 if(!item
->IsFitToSpellRequirements(spellInfo
))
1884 // offhand hand weapon required
1885 if(spellInfo
->AttributesEx3
& SPELL_ATTR_EX3_REQ_OFFHAND
)
1887 Item
* item
= ((Player
*)m_caster
)->GetWeaponForAttack(OFF_ATTACK
);
1889 // skip spell if no weapon in slot or broken
1890 if(!item
|| item
->IsBroken() )
1893 // skip spell if weapon not fit to triggered spell
1894 if(!item
->IsFitToSpellRequirements(spellInfo
))
1899 // some triggered spells must be casted instantly (for example, if next effect case instant kill caster)
1900 bool instant
= false;
1901 for(uint32 j
= i
+1; j
< 3; ++j
)
1903 if(m_spellInfo
->Effect
[j
]==SPELL_EFFECT_INSTAKILL
&& m_spellInfo
->EffectImplicitTargetA
[j
]==TARGET_SELF
)
1913 m_caster
->CastSpell(unitTarget
,spellInfo
,true,m_CastItem
,NULL
,m_originalCasterGUID
);
1916 m_TriggerSpells
.push_back(spellInfo
);
1919 void Spell::EffectTriggerMissileSpell(uint32 effect_idx
)
1921 uint32 triggered_spell_id
= m_spellInfo
->EffectTriggerSpell
[effect_idx
];
1924 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry( triggered_spell_id
);
1928 sLog
.outError("EffectTriggerMissileSpell of spell %u (eff: %u): triggering unknown spell id %u",
1929 m_spellInfo
->Id
,effect_idx
,triggered_spell_id
);
1934 DEBUG_LOG("WORLD: cast Item spellId - %i", spellInfo
->Id
);
1936 Spell
*spell
= new Spell(m_caster
, spellInfo
, true, m_originalCasterGUID
);
1938 SpellCastTargets targets
;
1939 targets
.setDestination(m_targets
.m_destX
,m_targets
.m_destY
,m_targets
.m_destZ
);
1940 spell
->m_CastItem
= m_CastItem
;
1941 spell
->prepare(&targets
, NULL
);
1944 void Spell::EffectTeleportUnits(uint32 i
)
1946 if(!unitTarget
|| unitTarget
->isInFlight())
1949 switch (m_spellInfo
->EffectImplicitTargetB
[i
])
1951 case TARGET_INNKEEPER_COORDINATES
:
1953 // Only players can teleport to innkeeper
1954 if (unitTarget
->GetTypeId() != TYPEID_PLAYER
)
1957 ((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);
1960 case TARGET_TABLE_X_Y_Z_COORDINATES
:
1962 // TODO: Only players can teleport?
1963 if (unitTarget
->GetTypeId() != TYPEID_PLAYER
)
1965 SpellTargetPosition
const* st
= spellmgr
.GetSpellTargetPosition(m_spellInfo
->Id
);
1968 sLog
.outError( "Spell::EffectTeleportUnits - unknown Teleport coordinates for spell ID %u\n", m_spellInfo
->Id
);
1971 ((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);
1974 case TARGET_BEHIND_VICTIM
:
1976 // Get selected target for player (or victim for units)
1977 Unit
*pTarget
= NULL
;
1978 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
1979 pTarget
= ObjectAccessor::GetUnit(*m_caster
, ((Player
*)m_caster
)->GetSelection());
1981 pTarget
= m_caster
->getVictim();
1982 // No target present - return
1985 // Init dest coordinates
1986 uint32 mapid
= m_caster
->GetMapId();
1987 float x
= m_targets
.m_destX
;
1988 float y
= m_targets
.m_destY
;
1989 float z
= m_targets
.m_destZ
;
1990 float orientation
= pTarget
->GetOrientation();
1992 if(unitTarget
->GetTypeId() == TYPEID_PLAYER
)
1993 ((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));
1996 m_caster
->GetMap()->CreatureRelocation((Creature
*)unitTarget
, x
, y
, z
, orientation
);
1998 unitTarget
->BuildTeleportAckMsg(&data
, x
, y
, z
, orientation
);
1999 unitTarget
->SendMessageToSet(&data
, false);
2005 // If not exist data for dest location - return
2006 if(!(m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
))
2008 sLog
.outError( "Spell::EffectTeleportUnits - unknown EffectImplicitTargetB[%u] = %u for spell ID %u\n", i
, m_spellInfo
->EffectImplicitTargetB
[i
], m_spellInfo
->Id
);
2011 // Init dest coordinates
2012 uint32 mapid
= m_caster
->GetMapId();
2013 float x
= m_targets
.m_destX
;
2014 float y
= m_targets
.m_destY
;
2015 float z
= m_targets
.m_destZ
;
2016 float orientation
= unitTarget
->GetOrientation();
2018 if(unitTarget
->GetTypeId() == TYPEID_PLAYER
)
2019 ((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));
2022 m_caster
->GetMap()->CreatureRelocation((Creature
*)unitTarget
, x
, y
, z
, orientation
);
2024 unitTarget
->BuildTeleportAckMsg(&data
, x
, y
, z
, orientation
);
2025 unitTarget
->SendMessageToSet(&data
, false);
2031 // post effects for TARGET_TABLE_X_Y_Z_COORDINATES
2032 switch ( m_spellInfo
->Id
)
2034 // Dimensional Ripper - Everlook
2037 int32 r
= irand(0, 119);
2038 if ( r
>= 70 ) // 7/12 success
2040 if ( r
< 100 ) // 4/12 evil twin
2041 m_caster
->CastSpell(m_caster
,23445,true);
2043 m_caster
->CastSpell(m_caster
,23449,true);
2047 // Ultrasafe Transporter: Toshley's Station
2050 if ( roll_chance_i(50) ) // 50% success
2052 int32 rand_eff
= urand(1,7);
2056 // soul split - evil
2057 m_caster
->CastSpell(m_caster
,36900,true);
2060 // soul split - good
2061 m_caster
->CastSpell(m_caster
,36901,true);
2064 // Increase the size
2065 m_caster
->CastSpell(m_caster
,36895,true);
2068 // Decrease the size
2069 m_caster
->CastSpell(m_caster
,36893,true);
2074 if (((Player
*)m_caster
)->GetTeam() == ALLIANCE
)
2075 m_caster
->CastSpell(m_caster
,36897,true);
2077 m_caster
->CastSpell(m_caster
,36899,true);
2082 m_caster
->CastSpell(m_caster
,36940,true);
2086 m_caster
->CastSpell(m_caster
,23445,true);
2092 // Dimensional Ripper - Area 52
2095 if ( roll_chance_i(50) ) // 50% success
2097 int32 rand_eff
= urand(1,4);
2101 // soul split - evil
2102 m_caster
->CastSpell(m_caster
,36900,true);
2105 // soul split - good
2106 m_caster
->CastSpell(m_caster
,36901,true);
2109 // Increase the size
2110 m_caster
->CastSpell(m_caster
,36895,true);
2115 if (((Player
*)m_caster
)->GetTeam() == ALLIANCE
)
2116 m_caster
->CastSpell(m_caster
,36897,true);
2118 m_caster
->CastSpell(m_caster
,36899,true);
2128 void Spell::EffectApplyAura(uint32 i
)
2133 SpellImmuneList
const& list
= unitTarget
->m_spellImmune
[IMMUNITY_STATE
];
2134 for(SpellImmuneList::const_iterator itr
= list
.begin(); itr
!= list
.end(); ++itr
)
2135 if(itr
->type
== m_spellInfo
->EffectApplyAuraName
[i
])
2138 // ghost spell check, allow apply any auras at player loading in ghost mode (will be cleanup after load)
2139 if( !unitTarget
->isAlive() && m_spellInfo
->Id
!= 20584 && m_spellInfo
->Id
!= 8326 &&
2140 (unitTarget
->GetTypeId()!=TYPEID_PLAYER
|| !((Player
*)unitTarget
)->GetSession()->PlayerLoading()) )
2143 Unit
* caster
= m_originalCasterGUID
? m_originalCaster
: m_caster
;
2147 sLog
.outDebug("Spell: Aura is: %u", m_spellInfo
->EffectApplyAuraName
[i
]);
2149 Aura
* Aur
= CreateAura(m_spellInfo
, i
, &m_currentBasePoints
[i
], unitTarget
, caster
, m_CastItem
);
2151 // Now Reduce spell duration using data received at spell hit
2152 int32 duration
= Aur
->GetAuraMaxDuration();
2153 unitTarget
->ApplyDiminishingToDuration(m_diminishGroup
,duration
,m_caster
,m_diminishLevel
);
2154 Aur
->setDiminishGroup(m_diminishGroup
);
2156 // if Aura removed and deleted, do not continue.
2157 if(duration
== 0 && !(Aur
->IsPermanent()))
2163 if(duration
!= Aur
->GetAuraMaxDuration())
2165 Aur
->SetAuraMaxDuration(duration
);
2166 Aur
->SetAuraDuration(duration
);
2169 bool added
= unitTarget
->AddAura(Aur
);
2171 // Aura not added and deleted in AddAura call;
2175 // found crash at character loading, broken pointer to Aur...
2176 // Aur was deleted in AddAura()...
2180 // TODO Make a way so it works for every related spell!
2181 if(unitTarget
->GetTypeId()==TYPEID_PLAYER
) // Negative buff should only be applied on players
2184 if(m_spellInfo
->CasterAuraStateNot
==AURA_STATE_WEAKENED_SOUL
|| m_spellInfo
->TargetAuraStateNot
==AURA_STATE_WEAKENED_SOUL
)
2185 spellId
= 6788; // Weakened Soul
2186 else if(m_spellInfo
->CasterAuraStateNot
==AURA_STATE_FORBEARANCE
|| m_spellInfo
->TargetAuraStateNot
==AURA_STATE_FORBEARANCE
)
2187 spellId
= 25771; // Forbearance
2188 else if(m_spellInfo
->CasterAuraStateNot
==AURA_STATE_HYPOTHERMIA
)
2189 spellId
= 41425; // Hypothermia
2190 else if (m_spellInfo
->Mechanic
== MECHANIC_BANDAGE
) // Bandages
2191 spellId
= 11196; // Recently Bandaged
2192 else if( (m_spellInfo
->AttributesEx
& 0x20) && (m_spellInfo
->AttributesEx2
& 0x20000) )
2193 spellId
= 23230; // Blood Fury - Healing Reduction
2195 SpellEntry
const *AdditionalSpellInfo
= sSpellStore
.LookupEntry(spellId
);
2196 if (AdditionalSpellInfo
)
2198 // applied at target by target
2199 Aura
* AdditionalAura
= CreateAura(AdditionalSpellInfo
, 0, &m_currentBasePoints
[0], unitTarget
,unitTarget
, 0);
2200 unitTarget
->AddAura(AdditionalAura
);
2201 sLog
.outDebug("Spell: Additional Aura is: %u", AdditionalSpellInfo
->EffectApplyAuraName
[0]);
2205 // Prayer of Mending (jump animation), we need formal caster instead original for correct animation
2206 if( m_spellInfo
->SpellFamilyName
== SPELLFAMILY_PRIEST
&& (m_spellInfo
->SpellFamilyFlags
& 0x00002000000000LL
))
2207 m_caster
->CastSpell(unitTarget
, 41637, true, NULL
, Aur
, m_originalCasterGUID
);
2210 void Spell::EffectUnlearnSpecialization( uint32 i
)
2212 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
2215 Player
*_player
= (Player
*)unitTarget
;
2216 uint32 spellToUnlearn
= m_spellInfo
->EffectTriggerSpell
[i
];
2218 _player
->removeSpell(spellToUnlearn
);
2220 sLog
.outDebug( "Spell: Player %u have unlearned spell %u from NpcGUID: %u", _player
->GetGUIDLow(), spellToUnlearn
, m_caster
->GetGUIDLow() );
2223 void Spell::EffectPowerDrain(uint32 i
)
2225 if(m_spellInfo
->EffectMiscValue
[i
] < 0 || m_spellInfo
->EffectMiscValue
[i
] >= MAX_POWERS
)
2228 Powers drain_power
= Powers(m_spellInfo
->EffectMiscValue
[i
]);
2232 if(!unitTarget
->isAlive())
2234 if(unitTarget
->getPowerType() != drain_power
)
2239 uint32 curPower
= unitTarget
->GetPower(drain_power
);
2241 //add spell damage bonus
2242 damage
=m_caster
->SpellDamageBonus(unitTarget
,m_spellInfo
,uint32(damage
),SPELL_DIRECT_DAMAGE
);
2244 // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
2245 uint32 power
= damage
;
2246 if ( drain_power
== POWER_MANA
&& unitTarget
->GetTypeId() == TYPEID_PLAYER
)
2247 power
-= ((Player
*)unitTarget
)->GetSpellCritDamageReduction(power
);
2250 if(curPower
< power
)
2251 new_damage
= curPower
;
2255 unitTarget
->ModifyPower(drain_power
,-new_damage
);
2257 if(drain_power
== POWER_MANA
)
2259 float manaMultiplier
= m_spellInfo
->EffectMultipleValue
[i
];
2260 if(manaMultiplier
==0)
2263 if(Player
*modOwner
= m_caster
->GetSpellModOwner())
2264 modOwner
->ApplySpellMod(m_spellInfo
->Id
, SPELLMOD_MULTIPLE_VALUE
, manaMultiplier
);
2266 int32 gain
= int32(new_damage
*manaMultiplier
);
2268 m_caster
->ModifyPower(POWER_MANA
,gain
);
2270 m_caster
->SendEnergizeSpellLog(m_caster
, m_spellInfo
->Id
,gain
,POWER_MANA
);
2274 void Spell::EffectSendEvent(uint32 EffectIndex
)
2276 if (m_caster
->GetTypeId() == TYPEID_PLAYER
&& ((Player
*)m_caster
)->InBattleGround())
2278 BattleGround
* bg
= ((Player
*)m_caster
)->GetBattleGround();
2279 if(bg
&& bg
->GetStatus() == STATUS_IN_PROGRESS
)
2281 switch(m_spellInfo
->Id
)
2283 case 23333: // Pickup Horde Flag
2284 /*do not uncomment .
2285 if(bg->GetTypeID()==BATTLEGROUND_WS)
2286 bg->EventPlayerClickedOnFlag((Player*)m_caster, gameObjTarget);
2287 sLog.outDebug("Send Event Horde Flag Picked Up");
2290 case 23334: // Drop Horde Flag
2291 if(bg->GetTypeID()==BATTLEGROUND_WS)
2292 bg->EventPlayerDroppedFlag((Player*)m_caster);
2293 sLog.outDebug("Drop Horde Flag");
2296 case 23335: // Pickup Alliance Flag
2297 /*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
2298 if(bg->GetTypeID()==BATTLEGROUND_WS)
2299 bg->EventPlayerClickedOnFlag((Player*)m_caster, gameObjTarget);
2300 sLog.outDebug("Send Event Alliance Flag Picked Up");
2303 case 23336: // Drop Alliance Flag
2304 if(bg->GetTypeID()==BATTLEGROUND_WS)
2305 bg->EventPlayerDroppedFlag((Player*)m_caster);
2306 sLog.outDebug("Drop Alliance Flag");
2308 case 23385: // Alliance Flag Returns
2309 if(bg->GetTypeID()==BATTLEGROUND_WS)
2310 bg->EventPlayerClickedOnFlag((Player*)m_caster, gameObjTarget);
2311 sLog.outDebug("Alliance Flag Returned");
2313 case 23386: // Horde Flag Returns
2314 if(bg->GetTypeID()==BATTLEGROUND_WS)
2315 bg->EventPlayerClickedOnFlag((Player*)m_caster, gameObjTarget);
2316 sLog.outDebug("Horde Flag Returned");
2320 if(bg->GetTypeID()==BATTLEGROUND_EY)
2321 bg->EventPlayerClickedOnFlag((Player*)m_caster, gameObjTarget);
2325 sLog
.outDebug("Unknown spellid %u in BG event", m_spellInfo
->Id
);
2330 sLog
.outDebug("Spell ScriptStart %u for spellid %u in EffectSendEvent ", m_spellInfo
->EffectMiscValue
[EffectIndex
], m_spellInfo
->Id
);
2331 sWorld
.ScriptsStart(sEventScripts
, m_spellInfo
->EffectMiscValue
[EffectIndex
], m_caster
, focusObject
);
2334 void Spell::EffectPowerBurn(uint32 i
)
2336 if(m_spellInfo
->EffectMiscValue
[i
] < 0 || m_spellInfo
->EffectMiscValue
[i
] >= MAX_POWERS
)
2339 Powers powertype
= Powers(m_spellInfo
->EffectMiscValue
[i
]);
2343 if(!unitTarget
->isAlive())
2345 if(unitTarget
->getPowerType()!=powertype
)
2350 int32 curPower
= int32(unitTarget
->GetPower(powertype
));
2352 // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
2353 uint32 power
= damage
;
2354 if ( powertype
== POWER_MANA
&& unitTarget
->GetTypeId() == TYPEID_PLAYER
)
2355 power
-= ((Player
*)unitTarget
)->GetSpellCritDamageReduction(power
);
2357 int32 new_damage
= (curPower
< power
) ? curPower
: power
;
2359 unitTarget
->ModifyPower(powertype
,-new_damage
);
2360 float multiplier
= m_spellInfo
->EffectMultipleValue
[i
];
2362 if(Player
*modOwner
= m_caster
->GetSpellModOwner())
2363 modOwner
->ApplySpellMod(m_spellInfo
->Id
, SPELLMOD_MULTIPLE_VALUE
, multiplier
);
2365 new_damage
= int32(new_damage
*multiplier
);
2366 m_caster
->SpellNonMeleeDamageLog(unitTarget
, m_spellInfo
->Id
, new_damage
, m_IsTriggeredSpell
, true);
2369 void Spell::EffectHeal( uint32
/*i*/ )
2371 if( unitTarget
&& unitTarget
->isAlive() && damage
>= 0)
2373 // Try to get original caster
2374 Unit
*caster
= m_originalCasterGUID
? m_originalCaster
: m_caster
;
2376 // Skip if m_originalCaster not available
2380 int32 addhealth
= damage
;
2382 // Vessel of the Naaru (Vial of the Sunwell trinket)
2383 if (m_spellInfo
->Id
== 45064)
2385 // Amount of heal - depends from stacked Holy Energy
2386 int damageAmount
= 0;
2387 Unit::AuraList
const& mDummyAuras
= m_caster
->GetAurasByType(SPELL_AURA_DUMMY
);
2388 for(Unit::AuraList::const_iterator i
= mDummyAuras
.begin();i
!= mDummyAuras
.end(); ++i
)
2389 if((*i
)->GetId() == 45062)
2390 damageAmount
+=(*i
)->GetModifier()->m_amount
;
2392 m_caster
->RemoveAurasDueToSpell(45062);
2394 addhealth
+= damageAmount
;
2396 // Swiftmend - consumes Regrowth or Rejuvenation
2397 else if (m_spellInfo
->TargetAuraState
== AURA_STATE_SWIFTMEND
&& unitTarget
->HasAuraState(AURA_STATE_SWIFTMEND
))
2399 Unit::AuraList
const& RejorRegr
= unitTarget
->GetAurasByType(SPELL_AURA_PERIODIC_HEAL
);
2400 // find most short by duration
2401 Aura
*targetAura
= NULL
;
2402 for(Unit::AuraList::const_iterator i
= RejorRegr
.begin(); i
!= RejorRegr
.end(); ++i
)
2404 if((*i
)->GetSpellProto()->SpellFamilyName
== SPELLFAMILY_DRUID
2405 && ((*i
)->GetSpellProto()->SpellFamilyFlags
== 0x40 || (*i
)->GetSpellProto()->SpellFamilyFlags
== 0x10) )
2407 if(!targetAura
|| (*i
)->GetAuraDuration() < targetAura
->GetAuraDuration())
2414 sLog
.outError("Target(GUID:" I64FMTD
") has aurastate AURA_STATE_SWIFTMEND but no matching aura.", unitTarget
->GetGUID());
2420 if(targetAura
->GetSpellProto()->EffectApplyAuraName
[idx
] == SPELL_AURA_PERIODIC_HEAL
)
2425 int32 tickheal
= caster
->SpellHealingBonus(targetAura
->GetSpellProto(), targetAura
->GetModifier()->m_amount
, DOT
, unitTarget
);
2426 int32 tickcount
= GetSpellDuration(targetAura
->GetSpellProto()) / targetAura
->GetSpellProto()->EffectAmplitude
[idx
];
2427 unitTarget
->RemoveAurasDueToSpell(targetAura
->GetId());
2429 addhealth
+= tickheal
* tickcount
;
2432 addhealth
= caster
->SpellHealingBonus(m_spellInfo
, addhealth
,HEAL
, unitTarget
);
2434 bool crit
= caster
->isSpellCrit(unitTarget
, m_spellInfo
, m_spellSchoolMask
, m_attackType
);
2436 addhealth
= caster
->SpellCriticalBonus(m_spellInfo
, addhealth
, unitTarget
);
2437 caster
->SendHealSpellLog(unitTarget
, m_spellInfo
->Id
, addhealth
, crit
);
2439 int32 gain
= unitTarget
->ModifyHealth( int32(addhealth
) );
2440 unitTarget
->getHostilRefManager().threatAssist(m_caster
, float(gain
) * 0.5f
, m_spellInfo
);
2442 if(caster
->GetTypeId()==TYPEID_PLAYER
)
2443 if(BattleGround
*bg
= ((Player
*)caster
)->GetBattleGround())
2444 bg
->UpdatePlayerScore(((Player
*)caster
), SCORE_HEALING_DONE
, gain
);
2446 // ignore item heals
2450 uint32 procHealer
= PROC_FLAG_HEAL
;
2452 procHealer
|= PROC_FLAG_CRIT_HEAL
;
2454 m_caster
->ProcDamageAndSpell(unitTarget
,procHealer
,PROC_FLAG_HEALED
,addhealth
,SPELL_SCHOOL_MASK_NONE
,m_spellInfo
,m_IsTriggeredSpell
);
2458 void Spell::EffectHealPct( uint32
/*i*/ )
2460 if( unitTarget
&& unitTarget
->isAlive() && damage
>= 0)
2462 // Try to get original caster
2463 Unit
*caster
= m_originalCasterGUID
? m_originalCaster
: m_caster
;
2465 // Skip if m_originalCaster not available
2469 uint32 addhealth
= unitTarget
->GetMaxHealth() * damage
/ 100;
2470 caster
->SendHealSpellLog(unitTarget
, m_spellInfo
->Id
, addhealth
, false);
2472 int32 gain
= unitTarget
->ModifyHealth( int32(addhealth
) );
2473 unitTarget
->getHostilRefManager().threatAssist(m_caster
, float(gain
) * 0.5f
, m_spellInfo
);
2475 if(caster
->GetTypeId()==TYPEID_PLAYER
)
2476 if(BattleGround
*bg
= ((Player
*)caster
)->GetBattleGround())
2477 bg
->UpdatePlayerScore(((Player
*)caster
), SCORE_HEALING_DONE
, gain
);
2481 void Spell::EffectHealMechanical( uint32
/*i*/ )
2483 // Mechanic creature type should be correctly checked by targetCreatureType field
2484 if( unitTarget
&& unitTarget
->isAlive() && damage
>= 0)
2486 // Try to get original caster
2487 Unit
*caster
= m_originalCasterGUID
? m_originalCaster
: m_caster
;
2489 // Skip if m_originalCaster not available
2493 uint32 addhealth
= caster
->SpellHealingBonus(m_spellInfo
, uint32(damage
), HEAL
, unitTarget
);
2494 caster
->SendHealSpellLog(unitTarget
, m_spellInfo
->Id
, addhealth
, false);
2495 unitTarget
->ModifyHealth( int32(damage
) );
2499 void Spell::EffectHealthLeech(uint32 i
)
2503 if(!unitTarget
->isAlive())
2509 sLog
.outDebug("HealthLeech :%i", damage
);
2511 float multiplier
= m_spellInfo
->EffectMultipleValue
[i
];
2513 if(Player
*modOwner
= m_caster
->GetSpellModOwner())
2514 modOwner
->ApplySpellMod(m_spellInfo
->Id
, SPELLMOD_MULTIPLE_VALUE
, multiplier
);
2516 int32 new_damage
= int32(damage
*multiplier
);
2517 uint32 curHealth
= unitTarget
->GetHealth();
2518 new_damage
= m_caster
->SpellNonMeleeDamageLog(unitTarget
, m_spellInfo
->Id
, new_damage
, m_IsTriggeredSpell
, true);
2519 if(curHealth
< new_damage
)
2520 new_damage
= curHealth
;
2522 if(m_caster
->isAlive())
2524 new_damage
= m_caster
->SpellHealingBonus(m_spellInfo
, new_damage
, HEAL
, m_caster
);
2526 m_caster
->ModifyHealth(new_damage
);
2528 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
2529 m_caster
->SendHealSpellLog(m_caster
, m_spellInfo
->Id
, uint32(new_damage
));
2533 void Spell::DoCreateItem(uint32 i
, uint32 itemtype
)
2535 if (!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
2538 Player
* player
= (Player
*)unitTarget
;
2540 uint32 newitemid
= itemtype
;
2541 ItemPrototype
const *pProto
= objmgr
.GetItemPrototype( newitemid
);
2544 player
->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND
, NULL
, NULL
);
2550 // TODO: maybe all this can be replaced by using correct calculated `damage` value
2551 if(pProto
->Class
!= ITEM_CLASS_CONSUMABLE
|| m_spellInfo
->SpellFamilyName
!= SPELLFAMILY_MAGE
)
2553 int32 basePoints
= m_currentBasePoints
[i
];
2554 int32 randomPoints
= m_spellInfo
->EffectDieSides
[i
];
2556 num_to_add
= basePoints
+ irand(1, randomPoints
);
2558 num_to_add
= basePoints
+ 1;
2560 else if (pProto
->MaxCount
== 1)
2562 else if(player
->getLevel() >= m_spellInfo
->spellLevel
)
2564 int32 basePoints
= m_currentBasePoints
[i
];
2565 float pointPerLevel
= m_spellInfo
->EffectRealPointsPerLevel
[i
];
2566 num_to_add
= basePoints
+ 1 + uint32((player
->getLevel() - m_spellInfo
->spellLevel
)*pointPerLevel
);
2573 if (num_to_add
> pProto
->Stackable
)
2574 num_to_add
= pProto
->Stackable
;
2576 // init items_count to 1, since 1 item will be created regardless of specialization
2578 // the chance to create additional items
2579 float additionalCreateChance
=0.0f
;
2580 // the maximum number of created additional items
2581 uint8 additionalMaxNum
=0;
2582 // get the chance and maximum number for creating extra items
2583 if ( canCreateExtraItems(player
, m_spellInfo
->Id
, additionalCreateChance
, additionalMaxNum
) )
2585 // roll with this chance till we roll not to create or we create the max num
2586 while ( roll_chance_f(additionalCreateChance
) && items_count
<=additionalMaxNum
)
2590 // really will be created more items
2591 num_to_add
*= items_count
;
2593 // can the player store the new item?
2594 ItemPosCountVec dest
;
2595 uint32 no_space
= 0;
2596 uint8 msg
= player
->CanStoreNewItem( NULL_BAG
, NULL_SLOT
, dest
, newitemid
, num_to_add
, &no_space
);
2597 if( msg
!= EQUIP_ERR_OK
)
2599 // convert to possible store amount
2600 if( msg
== EQUIP_ERR_INVENTORY_FULL
|| msg
== EQUIP_ERR_CANT_CARRY_MORE_OF_THIS
)
2601 num_to_add
-= no_space
;
2604 // if not created by another reason from full inventory or unique items amount limitation
2605 player
->SendEquipError( msg
, NULL
, NULL
);
2612 // create the new item and store it
2613 Item
* pItem
= player
->StoreNewItem( dest
, newitemid
, true, Item::GenerateItemRandomPropertyId(newitemid
));
2615 // was it successful? return error if not
2618 player
->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND
, NULL
, NULL
);
2622 // set the "Crafted by ..." property of the item
2623 if( pItem
->GetProto()->Class
!= ITEM_CLASS_CONSUMABLE
&& pItem
->GetProto()->Class
!= ITEM_CLASS_QUEST
)
2624 pItem
->SetUInt32Value(ITEM_FIELD_CREATOR
,player
->GetGUIDLow());
2626 // send info to the client
2628 player
->SendNewItem(pItem
, num_to_add
, true, true);
2630 // we succeeded in creating at least one item, so a levelup is possible
2631 player
->UpdateCraftSkill(m_spellInfo
->Id
);
2634 // for battleground marks send by mail if not add all expected
2637 BattleGroundTypeId bgType
;
2638 switch(m_spellInfo
->Id
)
2640 case SPELL_AV_MARK_WINNER
:
2641 case SPELL_AV_MARK_LOSER
:
2642 bgType
= BATTLEGROUND_AV
;
2644 case SPELL_WS_MARK_WINNER
:
2645 case SPELL_WS_MARK_LOSER
:
2646 bgType
= BATTLEGROUND_WS
;
2648 case SPELL_AB_MARK_WINNER
:
2649 case SPELL_AB_MARK_LOSER
:
2650 bgType
= BATTLEGROUND_AB
;
2656 if(BattleGround
* bg
= sBattleGroundMgr
.GetBattleGround(bgType
))
2657 bg
->SendRewardMarkByMail(player
,newitemid
,no_space
);
2661 void Spell::EffectCreateItem(uint32 i
)
2663 DoCreateItem(i
,m_spellInfo
->EffectItemType
[i
]);
2666 void Spell::EffectPersistentAA(uint32 i
)
2668 float radius
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[i
]));
2670 if(Player
* modOwner
= m_caster
->GetSpellModOwner())
2671 modOwner
->ApplySpellMod(m_spellInfo
->Id
, SPELLMOD_RADIUS
, radius
);
2673 int32 duration
= GetSpellDuration(m_spellInfo
);
2674 DynamicObject
* dynObj
= new DynamicObject
;
2675 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
))
2680 dynObj
->SetUInt32Value(OBJECT_FIELD_TYPE
, 65);
2681 dynObj
->SetUInt32Value(GAMEOBJECT_DISPLAYID
, 368003);
2682 dynObj
->SetUInt32Value(DYNAMICOBJECT_BYTES
, 0x01eeeeee);
2683 m_caster
->AddDynObject(dynObj
);
2684 dynObj
->GetMap()->Add(dynObj
);
2687 void Spell::EffectEnergize(uint32 i
)
2691 if(!unitTarget
->isAlive())
2694 if(m_spellInfo
->EffectMiscValue
[i
] < 0 || m_spellInfo
->EffectMiscValue
[i
] >= MAX_POWERS
)
2697 // Some level depends spells
2700 switch (m_spellInfo
->Id
)
2704 level_diff
= m_caster
->getLevel() - 40;
2709 level_diff
= m_caster
->getLevel() - 60;
2714 level_diff
= m_caster
->getLevel() - 60;
2722 damage
-= multiplier
* level_diff
;
2727 Powers power
= Powers(m_spellInfo
->EffectMiscValue
[i
]);
2729 if(unitTarget
->GetMaxPower(power
) == 0)
2732 unitTarget
->ModifyPower(power
,damage
);
2733 m_caster
->SendEnergizeSpellLog(unitTarget
, m_spellInfo
->Id
, damage
, power
);
2735 // Mad Alchemist's Potion
2736 if (m_spellInfo
->Id
== 45051)
2738 // find elixirs on target
2739 uint32 elixir_mask
= 0;
2740 Unit::AuraMap
& Auras
= unitTarget
->GetAuras();
2741 for(Unit::AuraMap::iterator itr
= Auras
.begin(); itr
!= Auras
.end(); ++itr
)
2743 uint32 spell_id
= itr
->second
->GetId();
2744 if(uint32 mask
= spellmgr
.GetSpellElixirMask(spell_id
))
2745 elixir_mask
|= mask
;
2748 // get available elixir mask any not active type from battle/guardian (and flask if no any)
2749 elixir_mask
= (elixir_mask
& ELIXIR_FLASK_MASK
) ^ ELIXIR_FLASK_MASK
;
2751 // get all available elixirs by mask and spell level
2752 std::vector
<uint32
> elixirs
;
2753 SpellElixirMap
const& m_spellElixirs
= spellmgr
.GetSpellElixirMap();
2754 for(SpellElixirMap::const_iterator itr
= m_spellElixirs
.begin(); itr
!= m_spellElixirs
.end(); ++itr
)
2756 if (itr
->second
& elixir_mask
)
2758 if (itr
->second
& (ELIXIR_UNSTABLE_MASK
| ELIXIR_SHATTRATH_MASK
))
2761 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(itr
->first
);
2762 if (spellInfo
&& (spellInfo
->spellLevel
< m_spellInfo
->spellLevel
|| spellInfo
->spellLevel
> unitTarget
->getLevel()))
2765 elixirs
.push_back(itr
->first
);
2769 if (!elixirs
.empty())
2771 // cast random elixir on target
2772 uint32 rand_spell
= urand(0,elixirs
.size()-1);
2773 m_caster
->CastSpell(unitTarget
,elixirs
[rand_spell
],true,m_CastItem
);
2778 void Spell::EffectEnergisePct(uint32 i
)
2782 if(!unitTarget
->isAlive())
2785 if(m_spellInfo
->EffectMiscValue
[i
] < 0 || m_spellInfo
->EffectMiscValue
[i
] >= MAX_POWERS
)
2788 Powers power
= Powers(m_spellInfo
->EffectMiscValue
[i
]);
2790 uint32 maxPower
= unitTarget
->GetMaxPower(power
);
2794 uint32 gain
= damage
* maxPower
/ 100;
2795 unitTarget
->ModifyPower(power
, gain
);
2796 m_caster
->SendEnergizeSpellLog(unitTarget
, m_spellInfo
->Id
, damage
, power
);
2799 void Spell::SendLoot(uint64 guid
, LootType loottype
)
2801 Player
* player
= (Player
*)m_caster
;
2807 if (Script
->GOHello(player
, gameObjTarget
))
2810 switch (gameObjTarget
->GetGoType())
2812 case GAMEOBJECT_TYPE_DOOR
:
2813 case GAMEOBJECT_TYPE_BUTTON
:
2814 gameObjTarget
->UseDoorOrButton();
2815 sWorld
.ScriptsStart(sGameObjectScripts
, gameObjTarget
->GetDBTableGUIDLow(), player
, gameObjTarget
);
2818 case GAMEOBJECT_TYPE_QUESTGIVER
:
2819 // start or end quest
2820 player
->PrepareQuestMenu(guid
);
2821 player
->SendPreparedQuest(guid
);
2824 case GAMEOBJECT_TYPE_SPELL_FOCUS
:
2825 // triggering linked GO
2826 if(uint32 trapEntry
= gameObjTarget
->GetGOInfo()->spellFocus
.linkedTrapId
)
2827 gameObjTarget
->TriggeringLinkedGameObject(trapEntry
,m_caster
);
2830 case GAMEOBJECT_TYPE_GOOBER
:
2831 // goober_scripts can be triggered if the player don't have the quest
2832 if (gameObjTarget
->GetGOInfo()->goober
.eventId
)
2834 sLog
.outDebug("Goober ScriptStart id %u for GO %u", gameObjTarget
->GetGOInfo()->goober
.eventId
,gameObjTarget
->GetDBTableGUIDLow());
2835 sWorld
.ScriptsStart(sEventScripts
, gameObjTarget
->GetGOInfo()->goober
.eventId
, player
, gameObjTarget
);
2838 // cast goober spell
2839 if (gameObjTarget
->GetGOInfo()->goober
.questId
)
2840 ///Quest require to be active for GO using
2841 if(player
->GetQuestStatus(gameObjTarget
->GetGOInfo()->goober
.questId
) != QUEST_STATUS_INCOMPLETE
)
2844 gameObjTarget
->AddUniqueUse(player
);
2845 gameObjTarget
->SetLootState(GO_JUST_DEACTIVATED
);
2847 //TODO? Objective counting called without spell check but with quest objective check
2848 // if send spell id then this line will duplicate to spell casting call (double counting)
2849 // So we or have this line and not required in quest_template have reqSpellIdN
2850 // or must remove this line and required in DB have data in quest_template have reqSpellIdN for all quest using cases.
2851 player
->CastedCreatureOrGO(gameObjTarget
->GetEntry(), gameObjTarget
->GetGUID(), 0);
2853 // triggering linked GO
2854 if(uint32 trapEntry
= gameObjTarget
->GetGOInfo()->goober
.linkedTrapId
)
2855 gameObjTarget
->TriggeringLinkedGameObject(trapEntry
,m_caster
);
2859 case GAMEOBJECT_TYPE_CHEST
:
2860 // TODO: possible must be moved to loot release (in different from linked triggering)
2861 if (gameObjTarget
->GetGOInfo()->chest
.eventId
)
2863 sLog
.outDebug("Chest ScriptStart id %u for GO %u", gameObjTarget
->GetGOInfo()->chest
.eventId
,gameObjTarget
->GetDBTableGUIDLow());
2864 sWorld
.ScriptsStart(sEventScripts
, gameObjTarget
->GetGOInfo()->chest
.eventId
, player
, gameObjTarget
);
2867 // triggering linked GO
2868 if(uint32 trapEntry
= gameObjTarget
->GetGOInfo()->chest
.linkedTrapId
)
2869 gameObjTarget
->TriggeringLinkedGameObject(trapEntry
,m_caster
);
2871 // Don't return, let loots been taken
2876 player
->SendLoot(guid
, loottype
);
2879 void Spell::EffectOpenLock(uint32
/*i*/)
2881 if(!m_caster
|| m_caster
->GetTypeId() != TYPEID_PLAYER
)
2883 sLog
.outDebug( "WORLD: Open Lock - No Player Caster!");
2887 Player
* player
= (Player
*)m_caster
;
2889 LootType loottype
= LOOT_CORPSE
;
2896 GameObjectInfo
const* goInfo
= gameObjTarget
->GetGOInfo();
2897 // Arathi Basin banner opening !
2898 if( goInfo
->type
== GAMEOBJECT_TYPE_BUTTON
&& goInfo
->button
.noDamageImmune
||
2899 goInfo
->type
== GAMEOBJECT_TYPE_GOOBER
&& goInfo
->goober
.losOK
)
2901 //isAllowUseBattleGroundObject() already called in CanCast()
2902 // in battleground check
2903 if(BattleGround
*bg
= player
->GetBattleGround())
2905 // check if it's correct bg
2906 if(bg
&& bg
->GetTypeID() == BATTLEGROUND_AB
)
2907 bg
->EventPlayerClickedOnFlag(player
, gameObjTarget
);
2911 else if (goInfo
->type
== GAMEOBJECT_TYPE_FLAGSTAND
)
2913 //isAllowUseBattleGroundObject() already called in CanCast()
2914 // in battleground check
2915 if(BattleGround
*bg
= player
->GetBattleGround())
2917 if(bg
->GetTypeID() == BATTLEGROUND_EY
)
2918 bg
->EventPlayerClickedOnFlag(player
, gameObjTarget
);
2922 lockId
= gameObjTarget
->GetLockId();
2923 guid
= gameObjTarget
->GetGUID();
2927 lockId
= itemTarget
->GetProto()->LockID
;
2928 guid
= itemTarget
->GetGUID();
2932 sLog
.outDebug( "WORLD: Open Lock - No GameObject/Item Target!");
2936 if(!lockId
) // possible case for GO and maybe for items.
2938 SendLoot(guid
, loottype
);
2943 LockEntry
const *lockInfo
= sLockStore
.LookupEntry(lockId
);
2947 sLog
.outError( "Spell::EffectOpenLock: %s [guid = %u] has an unknown lockId: %u!",
2948 (gameObjTarget
? "gameobject" : "item"), GUID_LOPART(guid
), lockId
);
2949 SendCastResult(SPELL_FAILED_BAD_TARGETS
);
2954 for(int i
= 0; i
< 8; ++i
)
2956 // Type==1 This means lockInfo->Index[i] is an item
2957 if(lockInfo
->Type
[i
]==LOCK_KEY_ITEM
&& lockInfo
->Index
[i
] && m_CastItem
&& m_CastItem
->GetEntry()==lockInfo
->Index
[i
])
2959 SendLoot(guid
, loottype
);
2965 // Check and skill-up skill
2966 if( m_spellInfo
->Effect
[1] == SPELL_EFFECT_SKILL
)
2967 SkillId
= m_spellInfo
->EffectMiscValue
[1];
2968 // pickpocketing spells
2969 else if( m_spellInfo
->EffectMiscValue
[0] == LOCKTYPE_PICKLOCK
)
2970 SkillId
= SKILL_LOCKPICKING
;
2972 // skill bonus provided by casting spell (mostly item spells)
2973 uint32 spellSkillBonus
= uint32(m_currentBasePoints
[0]+1);
2975 uint32 reqSkillValue
= lockInfo
->Skill
[0];
2977 if(lockInfo
->Skill
[1]) // required pick lock skill applying
2979 if(SkillId
!= SKILL_LOCKPICKING
) // wrong skill (cheating?)
2981 SendCastResult(SPELL_FAILED_FIZZLE
);
2985 reqSkillValue
= lockInfo
->Skill
[1];
2987 else if(SkillId
== SKILL_LOCKPICKING
) // apply picklock skill to wrong target
2989 SendCastResult(SPELL_FAILED_BAD_TARGETS
);
2995 loottype
= LOOT_SKINNING
;
2996 if ( player
->GetSkillValue(SkillId
) + spellSkillBonus
< reqSkillValue
)
2998 SendCastResult(SPELL_FAILED_LOW_CASTLEVEL
);
3002 // update skill if really known
3003 uint32 SkillValue
= player
->GetPureSkillValue(SkillId
);
3004 if(SkillValue
) // non only item base skill
3008 // Allow one skill-up until respawned
3009 if ( !gameObjTarget
->IsInSkillupList( player
->GetGUIDLow() ) &&
3010 player
->UpdateGatherSkill(SkillId
, SkillValue
, reqSkillValue
) )
3011 gameObjTarget
->AddToSkillupList( player
->GetGUIDLow() );
3016 uint32 SkillValue
= player
->GetPureSkillValue(SkillId
);
3017 player
->UpdateGatherSkill(SkillId
, SkillValue
, reqSkillValue
);
3022 SendLoot(guid
, loottype
);
3025 void Spell::EffectSummonChangeItem(uint32 i
)
3027 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
3030 Player
*player
= (Player
*)m_caster
;
3032 // applied only to using item
3036 // ... only to item in own inventory/bank/equip_slot
3037 if(m_CastItem
->GetOwnerGUID()!=player
->GetGUID())
3040 uint32 newitemid
= m_spellInfo
->EffectItemType
[i
];
3044 uint16 pos
= m_CastItem
->GetPos();
3046 Item
*pNewItem
= Item::CreateItem( newitemid
, 1, player
);
3050 for(uint8 i
= PERM_ENCHANTMENT_SLOT
; i
<=TEMP_ENCHANTMENT_SLOT
; ++i
)
3052 if(m_CastItem
->GetEnchantmentId(EnchantmentSlot(i
)))
3053 pNewItem
->SetEnchantment(EnchantmentSlot(i
), m_CastItem
->GetEnchantmentId(EnchantmentSlot(i
)), m_CastItem
->GetEnchantmentDuration(EnchantmentSlot(i
)), m_CastItem
->GetEnchantmentCharges(EnchantmentSlot(i
)));
3056 if(m_CastItem
->GetUInt32Value(ITEM_FIELD_DURABILITY
) < m_CastItem
->GetUInt32Value(ITEM_FIELD_MAXDURABILITY
))
3058 double loosePercent
= 1 - m_CastItem
->GetUInt32Value(ITEM_FIELD_DURABILITY
) / double(m_CastItem
->GetUInt32Value(ITEM_FIELD_MAXDURABILITY
));
3059 player
->DurabilityLoss(pNewItem
, loosePercent
);
3062 if( player
->IsInventoryPos( pos
) )
3064 ItemPosCountVec dest
;
3065 uint8 msg
= player
->CanStoreItem( m_CastItem
->GetBagSlot(), m_CastItem
->GetSlot(), dest
, pNewItem
, true );
3066 if( msg
== EQUIP_ERR_OK
)
3068 player
->DestroyItem(m_CastItem
->GetBagSlot(), m_CastItem
->GetSlot(),true);
3070 // prevent crash at access and unexpected charges counting with item update queue corrupt
3071 if(m_CastItem
==m_targets
.getItemTarget())
3072 m_targets
.setItemTarget(NULL
);
3076 player
->StoreItem( dest
, pNewItem
, true);
3080 else if( player
->IsBankPos ( pos
) )
3082 ItemPosCountVec dest
;
3083 uint8 msg
= player
->CanBankItem( m_CastItem
->GetBagSlot(), m_CastItem
->GetSlot(), dest
, pNewItem
, true );
3084 if( msg
== EQUIP_ERR_OK
)
3086 player
->DestroyItem(m_CastItem
->GetBagSlot(), m_CastItem
->GetSlot(),true);
3088 // prevent crash at access and unexpected charges counting with item update queue corrupt
3089 if(m_CastItem
==m_targets
.getItemTarget())
3090 m_targets
.setItemTarget(NULL
);
3094 player
->BankItem( dest
, pNewItem
, true);
3098 else if( player
->IsEquipmentPos ( pos
) )
3101 uint8 msg
= player
->CanEquipItem( m_CastItem
->GetSlot(), dest
, pNewItem
, true );
3102 if( msg
== EQUIP_ERR_OK
)
3104 player
->DestroyItem(m_CastItem
->GetBagSlot(), m_CastItem
->GetSlot(),true);
3106 // prevent crash at access and unexpected charges counting with item update queue corrupt
3107 if(m_CastItem
==m_targets
.getItemTarget())
3108 m_targets
.setItemTarget(NULL
);
3112 player
->EquipItem( dest
, pNewItem
, true);
3113 player
->AutoUnequipOffhandIfNeed();
3122 void Spell::EffectOpenSecretSafe(uint32 i
)
3124 EffectOpenLock(i
); //no difference for now
3127 void Spell::EffectProficiency(uint32
/*i*/)
3129 if (!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
3131 Player
*p_target
= (Player
*)unitTarget
;
3133 uint32 subClassMask
= m_spellInfo
->EquippedItemSubClassMask
;
3134 if(m_spellInfo
->EquippedItemClass
== 2 && !(p_target
->GetWeaponProficiency() & subClassMask
))
3136 p_target
->AddWeaponProficiency(subClassMask
);
3137 p_target
->SendProficiency(uint8(0x02),p_target
->GetWeaponProficiency());
3139 if(m_spellInfo
->EquippedItemClass
== 4 && !(p_target
->GetArmorProficiency() & subClassMask
))
3141 p_target
->AddArmorProficiency(subClassMask
);
3142 p_target
->SendProficiency(uint8(0x04),p_target
->GetArmorProficiency());
3146 void Spell::EffectApplyAreaAura(uint32 i
)
3150 if(!unitTarget
->isAlive())
3153 AreaAura
* Aur
= new AreaAura(m_spellInfo
, i
, &m_currentBasePoints
[i
], unitTarget
, m_caster
, m_CastItem
);
3154 unitTarget
->AddAura(Aur
);
3157 void Spell::EffectSummonType(uint32 i
)
3159 switch(m_spellInfo
->EffectMiscValueB
[i
])
3161 case SUMMON_TYPE_GUARDIAN
:
3162 case SUMMON_TYPE_POSESSED
:
3163 case SUMMON_TYPE_POSESSED2
:
3164 EffectSummonGuardian(i
);
3166 case SUMMON_TYPE_WILD
:
3167 EffectSummonWild(i
);
3169 case SUMMON_TYPE_DEMON
:
3170 EffectSummonDemon(i
);
3172 case SUMMON_TYPE_SUMMON
:
3175 case SUMMON_TYPE_CRITTER
:
3176 case SUMMON_TYPE_CRITTER2
:
3177 case SUMMON_TYPE_CRITTER3
:
3178 EffectSummonCritter(i
);
3180 case SUMMON_TYPE_TOTEM_SLOT1
:
3181 case SUMMON_TYPE_TOTEM_SLOT2
:
3182 case SUMMON_TYPE_TOTEM_SLOT3
:
3183 case SUMMON_TYPE_TOTEM_SLOT4
:
3184 case SUMMON_TYPE_TOTEM
:
3185 EffectSummonTotem(i
);
3187 case SUMMON_TYPE_UNKNOWN1
:
3188 case SUMMON_TYPE_UNKNOWN2
:
3189 case SUMMON_TYPE_UNKNOWN3
:
3190 case SUMMON_TYPE_UNKNOWN4
:
3191 case SUMMON_TYPE_UNKNOWN5
:
3194 sLog
.outError("EffectSummonType: Unhandled summon type %u", m_spellInfo
->EffectMiscValueB
[i
]);
3199 void Spell::EffectSummon(uint32 i
)
3201 if(m_caster
->GetPetGUID())
3206 uint32 pet_entry
= m_spellInfo
->EffectMiscValue
[i
];
3209 uint32 level
= m_caster
->getLevel();
3210 Pet
* spawnCreature
= new Pet(SUMMON_PET
);
3212 if(spawnCreature
->LoadPetFromDB(m_caster
,pet_entry
))
3214 // set timer for unsummon
3215 int32 duration
= GetSpellDuration(m_spellInfo
);
3217 spawnCreature
->SetDuration(duration
);
3222 Map
*map
= m_caster
->GetMap();
3223 uint32 pet_number
= objmgr
.GeneratePetNumber();
3224 if(!spawnCreature
->Create(objmgr
.GenerateLowGuid(HIGHGUID_PET
),map
,m_spellInfo
->EffectMiscValue
[i
], pet_number
))
3226 sLog
.outErrorDb("Spell::EffectSummon: no such creature entry %u",m_spellInfo
->EffectMiscValue
[i
]);
3227 delete spawnCreature
;
3231 // Summon in dest location
3233 if(m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
3235 x
= m_targets
.m_destX
;
3236 y
= m_targets
.m_destY
;
3237 z
= m_targets
.m_destZ
;
3240 m_caster
->GetClosePoint(x
,y
,z
,spawnCreature
->GetObjectSize());
3242 spawnCreature
->Relocate(x
,y
,z
,-m_caster
->GetOrientation());
3244 if(!spawnCreature
->IsPositionValid())
3246 sLog
.outError("ERROR: Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)",
3247 spawnCreature
->GetGUIDLow(), spawnCreature
->GetEntry(), spawnCreature
->GetPositionX(), spawnCreature
->GetPositionY());
3248 delete spawnCreature
;
3252 // set timer for unsummon
3253 int32 duration
= GetSpellDuration(m_spellInfo
);
3255 spawnCreature
->SetDuration(duration
);
3257 spawnCreature
->SetOwnerGUID(m_caster
->GetGUID());
3258 spawnCreature
->SetUInt32Value(UNIT_NPC_FLAGS
, 0);
3259 spawnCreature
->setPowerType(POWER_MANA
);
3260 spawnCreature
->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE
, m_caster
->getFaction());
3261 spawnCreature
->SetUInt32Value(UNIT_FIELD_FLAGS
, 0);
3262 spawnCreature
->SetUInt32Value(UNIT_FIELD_BYTES_0
, 2048);
3263 spawnCreature
->SetUInt32Value(UNIT_FIELD_BYTES_1
, 0);
3264 spawnCreature
->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP
, 0);
3265 spawnCreature
->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE
, 0);
3266 spawnCreature
->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP
, 1000);
3267 spawnCreature
->SetCreatorGUID(m_caster
->GetGUID());
3268 spawnCreature
->SetUInt32Value(UNIT_CREATED_BY_SPELL
, m_spellInfo
->Id
);
3270 spawnCreature
->InitStatsForLevel(level
);
3272 spawnCreature
->GetCharmInfo()->SetPetNumber(pet_number
, false);
3274 spawnCreature
->AIM_Initialize();
3275 spawnCreature
->InitPetCreateSpells();
3276 spawnCreature
->SetHealth(spawnCreature
->GetMaxHealth());
3277 spawnCreature
->SetPower(POWER_MANA
, spawnCreature
->GetMaxPower(POWER_MANA
));
3279 std::string name
= m_caster
->GetName();
3280 name
.append(petTypeSuffix
[spawnCreature
->getPetType()]);
3281 spawnCreature
->SetName( name
);
3283 map
->Add((Creature
*)spawnCreature
);
3285 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
3287 m_caster
->SetPet(spawnCreature
);
3288 spawnCreature
->GetCharmInfo()->SetReactState( REACT_DEFENSIVE
);
3289 spawnCreature
->SavePetToDB(PET_SAVE_AS_CURRENT
);
3290 ((Player
*)m_caster
)->PetSpellInitialize();
3294 void Spell::EffectLearnSpell(uint32 i
)
3299 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
3301 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
3302 EffectLearnPetSpell(i
);
3307 Player
*player
= (Player
*)unitTarget
;
3309 uint32 spellToLearn
= ((m_spellInfo
->Id
==SPELL_ID_GENERIC_LEARN
) || (m_spellInfo
->Id
==SPELL_ID_GENERIC_LEARN_PET
)) ? damage
: m_spellInfo
->EffectTriggerSpell
[i
];
3310 player
->learnSpell(spellToLearn
);
3312 sLog
.outDebug( "Spell: Player %u have learned spell %u from NpcGUID=%u", player
->GetGUIDLow(), spellToLearn
, m_caster
->GetGUIDLow() );
3315 void Spell::EffectDispel(uint32 i
)
3320 // Fill possible dispell list
3321 std::vector
<Aura
*> dispel_list
;
3323 // Create dispel mask by dispel type
3324 uint32 dispel_type
= m_spellInfo
->EffectMiscValue
[i
];
3325 uint32 dispelMask
= GetDispellMask( DispelType(dispel_type
) );
3326 Unit::AuraMap
const& auras
= unitTarget
->GetAuras();
3327 for(Unit::AuraMap::const_iterator itr
= auras
.begin(); itr
!= auras
.end(); ++itr
)
3329 Aura
*aur
= (*itr
).second
;
3330 if (aur
&& (1<<aur
->GetSpellProto()->Dispel
) & dispelMask
)
3332 if(aur
->GetSpellProto()->Dispel
== DISPEL_MAGIC
)
3334 bool positive
= true;
3335 if (!aur
->IsPositive())
3338 positive
= (aur
->GetSpellProto()->AttributesEx
& SPELL_ATTR_EX_NEGATIVE
)==0;
3340 // do not remove positive auras if friendly target
3341 // negative auras if non-friendly target
3342 if(positive
== unitTarget
->IsFriendlyTo(m_caster
))
3345 // Add aura to dispel list
3346 dispel_list
.push_back(aur
);
3349 // Ok if exist some buffs for dispel try dispel it
3350 if (!dispel_list
.empty())
3352 std::list
< std::pair
<uint32
,uint64
> > success_list
;// (spell_id,casterGuid)
3353 std::list
< uint32
> fail_list
; // spell_id
3354 int32 list_size
= dispel_list
.size();
3355 // Dispell N = damage buffs (or while exist buffs for dispel)
3356 for (int32 count
=0; count
< damage
&& list_size
> 0; ++count
)
3358 // Random select buff for dispel
3359 Aura
*aur
= dispel_list
[urand(0, list_size
-1)];
3361 SpellEntry
const* spellInfo
= aur
->GetSpellProto();
3362 // Base dispel chance
3363 // TODO: possible chance depend from spell level??
3364 int32 miss_chance
= 0;
3365 // Apply dispel mod from aura caster
3366 if (Unit
*caster
= aur
->GetCaster())
3368 if ( Player
* modOwner
= caster
->GetSpellModOwner() )
3369 modOwner
->ApplySpellMod(spellInfo
->Id
, SPELLMOD_RESIST_DISPEL_CHANCE
, miss_chance
, this);
3372 if (roll_chance_i(miss_chance
))
3373 fail_list
.push_back(aur
->GetId());
3375 success_list
.push_back(std::pair
<uint32
,uint64
>(aur
->GetId(),aur
->GetCasterGUID()));
3376 // Remove buff from list for prevent doubles
3377 for (std::vector
<Aura
*>::iterator j
= dispel_list
.begin(); j
!= dispel_list
.end(); )
3379 Aura
*dispeled
= *j
;
3380 if (dispeled
->GetId() == aur
->GetId() && dispeled
->GetCasterGUID() == aur
->GetCasterGUID())
3382 j
= dispel_list
.erase(j
);
3389 // Send success log and really remove auras
3390 if (!success_list
.empty())
3392 int32 count
= success_list
.size();
3393 WorldPacket
data(SMSG_SPELLDISPELLOG
, 8+8+4+1+4+count
*5);
3394 data
.append(unitTarget
->GetPackGUID()); // Victim GUID
3395 data
.append(m_caster
->GetPackGUID()); // Caster GUID
3396 data
<< uint32(m_spellInfo
->Id
); // Dispell spell id
3397 data
<< uint8(0); // not used
3398 data
<< uint32(count
); // count
3399 for (std::list
<std::pair
<uint32
,uint64
> >::iterator j
= success_list
.begin(); j
!= success_list
.end(); ++j
)
3401 SpellEntry
const* spellInfo
= sSpellStore
.LookupEntry(j
->first
);
3402 data
<< uint32(spellInfo
->Id
); // Spell Id
3403 data
<< uint8(0); // 0 - dispeled !=0 cleansed
3404 unitTarget
->RemoveAurasDueToSpellByDispel(spellInfo
->Id
, j
->second
, m_caster
);
3406 m_caster
->SendMessageToSet(&data
, true);
3410 if (m_spellInfo
->SpellFamilyName
== SPELLFAMILY_WARLOCK
&& m_spellInfo
->Category
== 12)
3412 uint32 heal_spell
= 0;
3413 switch (m_spellInfo
->Id
)
3415 case 19505: heal_spell
= 19658; break;
3416 case 19731: heal_spell
= 19732; break;
3417 case 19734: heal_spell
= 19733; break;
3418 case 19736: heal_spell
= 19735; break;
3419 case 27276: heal_spell
= 27278; break;
3420 case 27277: heal_spell
= 27279; break;
3422 sLog
.outDebug("Spell for Devour Magic %d not handled in Spell::EffectDispel", m_spellInfo
->Id
);
3426 m_caster
->CastSpell(m_caster
, heal_spell
, true);
3429 // Send fail log to client
3430 if (!fail_list
.empty())
3432 // Failed to dispell
3433 WorldPacket
data(SMSG_DISPEL_FAILED
, 8+8+4+4*fail_list
.size());
3434 data
<< uint64(m_caster
->GetGUID()); // Caster GUID
3435 data
<< uint64(unitTarget
->GetGUID()); // Victim GUID
3436 data
<< uint32(m_spellInfo
->Id
); // Dispell spell id
3437 for (std::list
< uint32
>::iterator j
= fail_list
.begin(); j
!= fail_list
.end(); ++j
)
3438 data
<< uint32(*j
); // Spell Id
3439 m_caster
->SendMessageToSet(&data
, true);
3444 void Spell::EffectDualWield(uint32
/*i*/)
3446 if (unitTarget
&& unitTarget
->GetTypeId() == TYPEID_PLAYER
)
3447 ((Player
*)unitTarget
)->SetCanDualWield(true);
3450 void Spell::EffectPull(uint32
/*i*/)
3452 // TODO: create a proper pull towards distract spell center for distract
3453 sLog
.outDebug("WORLD: Spell Effect DUMMY");
3456 void Spell::EffectDistract(uint32
/*i*/)
3458 // Check for possible target
3459 if (!unitTarget
|| unitTarget
->isInCombat())
3462 // target must be OK to do this
3463 if( unitTarget
->hasUnitState(UNIT_STAT_CONFUSED
| UNIT_STAT_STUNNED
| UNIT_STAT_FLEEING
) )
3466 float angle
= unitTarget
->GetAngle(m_targets
.m_destX
, m_targets
.m_destY
);
3468 if ( unitTarget
->GetTypeId() == TYPEID_PLAYER
)
3470 // For players just turn them
3472 ((Player
*)unitTarget
)->BuildTeleportAckMsg(&data
, unitTarget
->GetPositionX(), unitTarget
->GetPositionY(), unitTarget
->GetPositionZ(), angle
);
3473 ((Player
*)unitTarget
)->GetSession()->SendPacket( &data
);
3474 ((Player
*)unitTarget
)->SetPosition(unitTarget
->GetPositionX(), unitTarget
->GetPositionY(), unitTarget
->GetPositionZ(), angle
, false);
3478 // Set creature Distracted, Stop it, And turn it
3479 unitTarget
->SetOrientation(angle
);
3480 unitTarget
->StopMoving();
3481 unitTarget
->GetMotionMaster()->MoveDistract(damage
*1000);
3485 void Spell::EffectPickPocket(uint32
/*i*/)
3487 if( m_caster
->GetTypeId() != TYPEID_PLAYER
)
3490 // victim must be creature and attackable
3491 if( !unitTarget
|| unitTarget
->GetTypeId() != TYPEID_UNIT
|| m_caster
->IsFriendlyTo(unitTarget
) )
3494 // victim have to be alive and humanoid or undead
3495 if( unitTarget
->isAlive() && (unitTarget
->GetCreatureTypeMask() &CREATURE_TYPEMASK_HUMANOID_OR_UNDEAD
) != 0)
3497 int32 chance
= 10 + int32(m_caster
->getLevel()) - int32(unitTarget
->getLevel());
3499 if (chance
> irand(0, 19))
3501 // Stealing successful
3502 //sLog.outDebug("Sending loot from pickpocket");
3503 ((Player
*)m_caster
)->SendLoot(unitTarget
->GetGUID(),LOOT_PICKPOCKETING
);
3507 // Reveal action + get attack
3508 m_caster
->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH
);
3509 if (((Creature
*)unitTarget
)->AI())
3510 ((Creature
*)unitTarget
)->AI()->AttackStart(m_caster
);
3515 void Spell::EffectAddFarsight(uint32 i
)
3517 float radius
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[i
]));
3518 int32 duration
= GetSpellDuration(m_spellInfo
);
3519 DynamicObject
* dynObj
= new DynamicObject
;
3520 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
))
3525 dynObj
->SetUInt32Value(OBJECT_FIELD_TYPE
, 65);
3526 dynObj
->SetUInt32Value(DYNAMICOBJECT_BYTES
, 0x80000002);
3527 m_caster
->AddDynObject(dynObj
);
3528 dynObj
->GetMap()->Add(dynObj
);
3529 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
3530 ((Player
*)m_caster
)->SetFarSight(dynObj
->GetGUID());
3533 void Spell::EffectSummonWild(uint32 i
)
3535 uint32 creature_entry
= m_spellInfo
->EffectMiscValue
[i
];
3539 uint32 level
= m_caster
->getLevel();
3541 // level of creature summoned using engineering item based at engineering skill level
3542 if(m_caster
->GetTypeId()==TYPEID_PLAYER
&& m_CastItem
)
3544 ItemPrototype
const *proto
= m_CastItem
->GetProto();
3545 if(proto
&& proto
->RequiredSkill
== SKILL_ENGINERING
)
3547 uint16 skill202
= ((Player
*)m_caster
)->GetSkillValue(SKILL_ENGINERING
);
3555 // select center of summon position
3556 float center_x
= m_targets
.m_destX
;
3557 float center_y
= m_targets
.m_destY
;
3558 float center_z
= m_targets
.m_destZ
;
3560 float radius
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[i
]));
3562 int32 amount
= damage
> 0 ? damage
: 1;
3564 for(int32 count
= 0; count
< amount
; ++count
)
3567 // If dest location if present
3568 if (m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
3570 // Summon 1 unit in dest location
3573 px
= m_targets
.m_destX
;
3574 py
= m_targets
.m_destY
;
3575 pz
= m_targets
.m_destZ
;
3577 // Summon in random point all other units if location present
3579 m_caster
->GetRandomPoint(center_x
,center_y
,center_z
,radius
,px
,py
,pz
);
3581 // Summon if dest location not present near caster
3583 m_caster
->GetClosePoint(px
,py
,pz
,3.0f
);
3585 int32 duration
= GetSpellDuration(m_spellInfo
);
3587 TempSummonType summonType
= (duration
== 0) ? TEMPSUMMON_DEAD_DESPAWN
: TEMPSUMMON_TIMED_OR_DEAD_DESPAWN
;
3589 m_caster
->SummonCreature(creature_entry
,px
,py
,pz
,m_caster
->GetOrientation(),summonType
,duration
);
3593 void Spell::EffectSummonGuardian(uint32 i
)
3595 uint32 pet_entry
= m_spellInfo
->EffectMiscValue
[i
];
3599 // Jewelery statue case (totem like)
3600 if(m_spellInfo
->SpellIconID
==2056)
3602 EffectSummonTotem(i
);
3606 // set timer for unsummon
3607 int32 duration
= GetSpellDuration(m_spellInfo
);
3609 // Search old Guardian only for players (if casted spell not have duration or cooldown)
3610 // FIXME: some guardians have control spell applied and controlled by player and anyway player can't summon in this time
3611 // so this code hack in fact
3612 if( m_caster
->GetTypeId() == TYPEID_PLAYER
&& (duration
<= 0 || GetSpellRecoveryTime(m_spellInfo
)==0) )
3613 if(((Player
*)m_caster
)->HasGuardianWithEntry(pet_entry
))
3614 return; // find old guardian, ignore summon
3616 // in another case summon new
3617 uint32 level
= m_caster
->getLevel();
3619 // level of pet summoned using engineering item based at engineering skill level
3620 if(m_caster
->GetTypeId()==TYPEID_PLAYER
&& m_CastItem
)
3622 ItemPrototype
const *proto
= m_CastItem
->GetProto();
3623 if(proto
&& proto
->RequiredSkill
== SKILL_ENGINERING
)
3625 uint16 skill202
= ((Player
*)m_caster
)->GetSkillValue(SKILL_ENGINERING
);
3633 // select center of summon position
3634 float center_x
= m_targets
.m_destX
;
3635 float center_y
= m_targets
.m_destY
;
3636 float center_z
= m_targets
.m_destZ
;
3638 float radius
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[i
]));
3640 int32 amount
= damage
> 0 ? damage
: 1;
3642 for(int32 count
= 0; count
< amount
; ++count
)
3644 Pet
* spawnCreature
= new Pet(GUARDIAN_PET
);
3646 Map
*map
= m_caster
->GetMap();
3647 uint32 pet_number
= objmgr
.GeneratePetNumber();
3648 if(!spawnCreature
->Create(objmgr
.GenerateLowGuid(HIGHGUID_PET
), map
,m_spellInfo
->EffectMiscValue
[i
], pet_number
))
3650 sLog
.outError("no such creature entry %u",m_spellInfo
->EffectMiscValue
[i
]);
3651 delete spawnCreature
;
3656 // If dest location if present
3657 if (m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
3659 // Summon 1 unit in dest location
3662 px
= m_targets
.m_destX
;
3663 py
= m_targets
.m_destY
;
3664 pz
= m_targets
.m_destZ
;
3666 // Summon in random point all other units if location present
3668 m_caster
->GetRandomPoint(center_x
,center_y
,center_z
,radius
,px
,py
,pz
);
3670 // Summon if dest location not present near caster
3672 m_caster
->GetClosePoint(px
,py
,pz
,spawnCreature
->GetObjectSize());
3674 spawnCreature
->Relocate(px
,py
,pz
,m_caster
->GetOrientation());
3676 if(!spawnCreature
->IsPositionValid())
3678 sLog
.outError("ERROR: Pet (guidlow %d, entry %d) not created base at creature. Suggested coordinates isn't valid (X: %f Y: %f)",
3679 spawnCreature
->GetGUIDLow(), spawnCreature
->GetEntry(), spawnCreature
->GetPositionX(), spawnCreature
->GetPositionY());
3680 delete spawnCreature
;
3685 spawnCreature
->SetDuration(duration
);
3687 spawnCreature
->SetOwnerGUID(m_caster
->GetGUID());
3688 spawnCreature
->setPowerType(POWER_MANA
);
3689 spawnCreature
->SetUInt32Value(UNIT_NPC_FLAGS
, 0);
3690 spawnCreature
->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE
,m_caster
->getFaction());
3691 spawnCreature
->SetUInt32Value(UNIT_FIELD_FLAGS
,0);
3692 spawnCreature
->SetUInt32Value(UNIT_FIELD_BYTES_1
,0);
3693 spawnCreature
->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP
,0);
3694 spawnCreature
->SetCreatorGUID(m_caster
->GetGUID());
3695 spawnCreature
->SetUInt32Value(UNIT_CREATED_BY_SPELL
, m_spellInfo
->Id
);
3697 spawnCreature
->InitStatsForLevel(level
);
3698 spawnCreature
->GetCharmInfo()->SetPetNumber(pet_number
, false);
3700 spawnCreature
->AIM_Initialize();
3702 if(m_caster
->GetTypeId()==TYPEID_PLAYER
)
3703 ((Player
*)m_caster
)->AddGuardian(spawnCreature
);
3705 map
->Add((Creature
*)spawnCreature
);
3709 void Spell::EffectTeleUnitsFaceCaster(uint32 i
)
3714 if(unitTarget
->isInFlight())
3717 uint32 mapid
= m_caster
->GetMapId();
3718 float dis
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[i
]));
3721 m_caster
->GetClosePoint(fx
,fy
,fz
,unitTarget
->GetObjectSize(),dis
);
3723 if(unitTarget
->GetTypeId() == TYPEID_PLAYER
)
3724 ((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));
3726 m_caster
->GetMap()->CreatureRelocation((Creature
*)m_caster
, fx
, fy
, fz
, -m_caster
->GetOrientation());
3729 void Spell::EffectLearnSkill(uint32 i
)
3731 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
3737 uint32 skillid
= m_spellInfo
->EffectMiscValue
[i
];
3738 uint16 skillval
= ((Player
*)unitTarget
)->GetPureSkillValue(skillid
);
3739 ((Player
*)unitTarget
)->SetSkill(skillid
, skillval
?skillval
:1, damage
*75);
3742 void Spell::EffectAddHonor(uint32
/*i*/)
3744 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
3747 sLog
.outDebug("SpellEffect::AddHonor called for spell_id %u , that rewards %d honor points to player: %u", m_spellInfo
->Id
, damage
, ((Player
*)unitTarget
)->GetGUIDLow());
3749 // TODO: find formula for honor reward based on player's level!
3751 // now fixed only for level 70 players:
3752 if (((Player
*)unitTarget
)->getLevel() == 70)
3753 ((Player
*)unitTarget
)->RewardHonor(NULL
, 1, damage
);
3756 void Spell::EffectTradeSkill(uint32
/*i*/)
3758 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
3760 // uint32 skillid = m_spellInfo->EffectMiscValue[i];
3761 // uint16 skillmax = ((Player*)unitTarget)->(skillid);
3762 // ((Player*)unitTarget)->SetSkill(skillid,skillval?skillval:1,skillmax+75);
3765 void Spell::EffectEnchantItemPerm(uint32 i
)
3767 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
3772 Player
* p_caster
= (Player
*)m_caster
;
3774 p_caster
->UpdateCraftSkill(m_spellInfo
->Id
);
3776 if (m_spellInfo
->EffectMiscValue
[i
])
3778 uint32 enchant_id
= m_spellInfo
->EffectMiscValue
[i
];
3780 SpellItemEnchantmentEntry
const *pEnchant
= sSpellItemEnchantmentStore
.LookupEntry(enchant_id
);
3784 // item can be in trade slot and have owner diff. from caster
3785 Player
* item_owner
= itemTarget
->GetOwner();
3789 if(item_owner
!=p_caster
&& p_caster
->GetSession()->GetSecurity() > SEC_PLAYER
&& sWorld
.getConfig(CONFIG_GM_LOG_TRADE
) )
3791 sLog
.outCommand(p_caster
->GetSession()->GetAccountId(),"GM %s (Account: %u) enchanting(perm): %s (Entry: %d) for player: %s (Account: %u)",
3792 p_caster
->GetName(),p_caster
->GetSession()->GetAccountId(),
3793 itemTarget
->GetProto()->Name1
,itemTarget
->GetEntry(),
3794 item_owner
->GetName(),item_owner
->GetSession()->GetAccountId());
3797 // remove old enchanting before applying new if equipped
3798 item_owner
->ApplyEnchantment(itemTarget
,PERM_ENCHANTMENT_SLOT
,false);
3800 itemTarget
->SetEnchantment(PERM_ENCHANTMENT_SLOT
, enchant_id
, 0, 0);
3802 // add new enchanting if equipped
3803 item_owner
->ApplyEnchantment(itemTarget
,PERM_ENCHANTMENT_SLOT
,true);
3807 void Spell::EffectEnchantItemTmp(uint32 i
)
3809 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
3812 Player
* p_caster
= (Player
*)m_caster
;
3817 uint32 enchant_id
= m_spellInfo
->EffectMiscValue
[i
];
3819 // Shaman Rockbiter Weapon
3820 if(i
==0 && m_spellInfo
->Effect
[1]==SPELL_EFFECT_DUMMY
)
3822 int32 enchnting_damage
= m_currentBasePoints
[1]+1;
3824 // enchanting id selected by calculated damage-per-sec stored in Effect[1] base value
3825 // with already applied percent bonus from Elemental Weapons talent
3826 // Note: damage calculated (correctly) with rounding int32(float(v)) but
3827 // RW enchantments applied damage int32(float(v)+0.5), this create 0..1 difference sometime
3828 switch(enchnting_damage
)
3831 case 2: enchant_id
= 29; break; // 0% [ 7% == 2, 14% == 2, 20% == 2]
3833 case 4: enchant_id
= 6; break; // 0% [ 7% == 4, 14% == 4]
3834 case 5: enchant_id
= 3025; break; // 20%
3836 case 6: enchant_id
= 1; break; // 0% [ 7% == 6, 14% == 6]
3837 case 7: enchant_id
= 3027; break; // 20%
3839 case 9: enchant_id
= 3032; break; // 0% [ 7% == 6]
3840 case 10: enchant_id
= 503; break; // 14%
3841 case 11: enchant_id
= 3031; break; // 20%
3843 case 15: enchant_id
= 3035; break; // 0%
3844 case 16: enchant_id
= 1663; break; // 7%
3845 case 17: enchant_id
= 3033; break; // 14%
3846 case 18: enchant_id
= 3034; break; // 20%
3848 case 28: enchant_id
= 3038; break; // 0%
3849 case 29: enchant_id
= 683; break; // 7%
3850 case 31: enchant_id
= 3036; break; // 14%
3851 case 33: enchant_id
= 3037; break; // 20%
3853 case 40: enchant_id
= 3041; break; // 0%
3854 case 42: enchant_id
= 1664; break; // 7%
3855 case 45: enchant_id
= 3039; break; // 14%
3856 case 48: enchant_id
= 3040; break; // 20%
3858 case 49: enchant_id
= 3044; break; // 0%
3859 case 52: enchant_id
= 2632; break; // 7%
3860 case 55: enchant_id
= 3042; break; // 14%
3861 case 58: enchant_id
= 3043; break; // 20%
3863 case 62: enchant_id
= 2633; break; // 0%
3864 case 66: enchant_id
= 3018; break; // 7%
3865 case 70: enchant_id
= 3019; break; // 14%
3866 case 74: enchant_id
= 3020; break; // 20%
3868 sLog
.outError("Spell::EffectEnchantItemTmp: Damage %u not handled in S'RW",enchnting_damage
);
3875 sLog
.outError("Spell %u Effect %u (SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY) have 0 as enchanting id",m_spellInfo
->Id
,i
);
3879 SpellItemEnchantmentEntry
const *pEnchant
= sSpellItemEnchantmentStore
.LookupEntry(enchant_id
);
3882 sLog
.outError("Spell %u Effect %u (SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY) have not existed enchanting id %u ",m_spellInfo
->Id
,i
,enchant_id
);
3886 // select enchantment duration
3889 // rogue family enchantments exception by duration
3890 if(m_spellInfo
->Id
==38615)
3891 duration
= 1800; // 30 mins
3892 // other rogue family enchantments always 1 hour (some have spell damage=0, but some have wrong data in EffBasePoints)
3893 else if(m_spellInfo
->SpellFamilyName
==SPELLFAMILY_ROGUE
)
3894 duration
= 3600; // 1 hour
3895 // shaman family enchantments
3896 else if(m_spellInfo
->SpellFamilyName
==SPELLFAMILY_SHAMAN
)
3897 duration
= 1800; // 30 mins
3898 // other cases with this SpellVisual already selected
3899 else if(m_spellInfo
->SpellVisual
[0]==215)
3900 duration
= 1800; // 30 mins
3901 // some fishing pole bonuses
3902 else if(m_spellInfo
->SpellVisual
[0]==563)
3903 duration
= 600; // 10 mins
3904 // shaman rockbiter enchantments
3905 else if(m_spellInfo
->SpellVisual
[0]==0)
3906 duration
= 1800; // 30 mins
3907 else if(m_spellInfo
->Id
==29702)
3908 duration
= 300; // 5 mins
3909 else if(m_spellInfo
->Id
==37360)
3910 duration
= 300; // 5 mins
3913 duration
= 3600; // 1 hour
3915 // item can be in trade slot and have owner diff. from caster
3916 Player
* item_owner
= itemTarget
->GetOwner();
3920 if(item_owner
!=p_caster
&& p_caster
->GetSession()->GetSecurity() > SEC_PLAYER
&& sWorld
.getConfig(CONFIG_GM_LOG_TRADE
) )
3922 sLog
.outCommand(p_caster
->GetSession()->GetAccountId(),"GM %s (Account: %u) enchanting(temp): %s (Entry: %d) for player: %s (Account: %u)",
3923 p_caster
->GetName(),p_caster
->GetSession()->GetAccountId(),
3924 itemTarget
->GetProto()->Name1
,itemTarget
->GetEntry(),
3925 item_owner
->GetName(),item_owner
->GetSession()->GetAccountId());
3928 // remove old enchanting before applying new if equipped
3929 item_owner
->ApplyEnchantment(itemTarget
,TEMP_ENCHANTMENT_SLOT
,false);
3931 itemTarget
->SetEnchantment(TEMP_ENCHANTMENT_SLOT
, enchant_id
, duration
*1000, 0);
3933 // add new enchanting if equipped
3934 item_owner
->ApplyEnchantment(itemTarget
,TEMP_ENCHANTMENT_SLOT
,true);
3937 void Spell::EffectTameCreature(uint32
/*i*/)
3939 if(m_caster
->GetPetGUID())
3945 if(unitTarget
->GetTypeId() == TYPEID_PLAYER
)
3948 Creature
* creatureTarget
= (Creature
*)unitTarget
;
3950 if(creatureTarget
->isPet())
3953 if(m_caster
->getClass() != CLASS_HUNTER
)
3956 // cast finish successfully
3957 //SendChannelUpdate(0);
3960 Pet
* pet
= m_caster
->CreateTamedPetFrom(creatureTarget
,m_spellInfo
->Id
);
3962 // kill original creature
3963 creatureTarget
->setDeathState(JUST_DIED
);
3964 creatureTarget
->RemoveCorpse();
3965 creatureTarget
->SetHealth(0); // just for nice GM-mode view
3967 uint32 level
= (creatureTarget
->getLevel() < (m_caster
->getLevel() - 5)) ? (m_caster
->getLevel() - 5) : creatureTarget
->getLevel();
3969 // prepare visual effect for levelup
3970 pet
->SetUInt32Value(UNIT_FIELD_LEVEL
, level
- 1);
3973 pet
->GetMap()->Add((Creature
*)pet
);
3975 // visual effect for levelup
3976 pet
->SetUInt32Value(UNIT_FIELD_LEVEL
, level
);
3978 // caster have pet now
3979 m_caster
->SetPet(pet
);
3981 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
3983 pet
->SavePetToDB(PET_SAVE_AS_CURRENT
);
3984 ((Player
*)m_caster
)->PetSpellInitialize();
3988 void Spell::EffectSummonPet(uint32 i
)
3990 uint32 petentry
= m_spellInfo
->EffectMiscValue
[i
];
3992 Pet
*OldSummon
= m_caster
->GetPet();
3994 // if pet requested type already exist
3997 if(petentry
== 0 || OldSummon
->GetEntry() == petentry
)
3999 // pet in corpse state can't be summoned
4000 if( OldSummon
->isDead() )
4003 OldSummon
->GetMap()->Remove((Creature
*)OldSummon
,false);
4004 OldSummon
->SetMapId(m_caster
->GetMapId());
4007 m_caster
->GetClosePoint(px
, py
, pz
, OldSummon
->GetObjectSize());
4009 OldSummon
->Relocate(px
, py
, pz
, OldSummon
->GetOrientation());
4010 m_caster
->GetMap()->Add((Creature
*)OldSummon
);
4012 if(m_caster
->GetTypeId() == TYPEID_PLAYER
&& OldSummon
->isControlled() )
4014 ((Player
*)m_caster
)->PetSpellInitialize();
4019 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
4020 ((Player
*)m_caster
)->RemovePet(OldSummon
,(OldSummon
->getPetType()==HUNTER_PET
? PET_SAVE_AS_DELETED
: PET_SAVE_NOT_IN_SLOT
),false);
4025 Pet
* NewSummon
= new Pet
;
4027 // petentry==0 for hunter "call pet" (current pet summoned if any)
4028 if(NewSummon
->LoadPetFromDB(m_caster
,petentry
))
4030 if(NewSummon
->getPetType()==SUMMON_PET
)
4032 // Remove Demonic Sacrifice auras (known pet)
4033 Unit::AuraList
const& auraClassScripts
= m_caster
->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS
);
4034 for(Unit::AuraList::const_iterator itr
= auraClassScripts
.begin();itr
!=auraClassScripts
.end();)
4036 if((*itr
)->GetModifier()->m_miscvalue
==2228)
4038 m_caster
->RemoveAurasDueToSpell((*itr
)->GetId());
4039 itr
= auraClassScripts
.begin();
4049 // not error in case fail hunter call pet
4056 CreatureInfo
const* cInfo
= sCreatureStorage
.LookupEntry
<CreatureInfo
>(petentry
);
4060 sLog
.outError("EffectSummonPet: creature entry %u not found.",petentry
);
4065 Map
*map
= m_caster
->GetMap();
4066 uint32 pet_number
= objmgr
.GeneratePetNumber();
4067 if(!NewSummon
->Create(objmgr
.GenerateLowGuid(HIGHGUID_PET
), map
, petentry
, pet_number
))
4074 m_caster
->GetClosePoint(px
, py
, pz
, NewSummon
->GetObjectSize());
4076 NewSummon
->Relocate(px
, py
, pz
, m_caster
->GetOrientation());
4078 if(!NewSummon
->IsPositionValid())
4080 sLog
.outError("ERROR: Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)",
4081 NewSummon
->GetGUIDLow(), NewSummon
->GetEntry(), NewSummon
->GetPositionX(), NewSummon
->GetPositionY());
4086 uint32 petlevel
= m_caster
->getLevel();
4087 NewSummon
->setPetType(SUMMON_PET
);
4089 uint32 faction
= m_caster
->getFaction();
4090 if(m_caster
->GetTypeId() == TYPEID_UNIT
)
4092 if ( ((Creature
*)m_caster
)->isTotem() )
4093 NewSummon
->GetCharmInfo()->SetReactState(REACT_AGGRESSIVE
);
4095 NewSummon
->GetCharmInfo()->SetReactState(REACT_DEFENSIVE
);
4098 NewSummon
->SetOwnerGUID(m_caster
->GetGUID());
4099 NewSummon
->SetCreatorGUID(m_caster
->GetGUID());
4100 NewSummon
->SetUInt32Value(UNIT_NPC_FLAGS
, 0);
4101 NewSummon
->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE
, faction
);
4102 NewSummon
->SetUInt32Value(UNIT_FIELD_BYTES_0
, 2048);
4103 NewSummon
->SetUInt32Value(UNIT_FIELD_BYTES_1
, 0);
4104 NewSummon
->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP
, time(NULL
));
4105 NewSummon
->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE
, 0);
4106 NewSummon
->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP
, 1000);
4107 NewSummon
->SetUInt32Value(UNIT_CREATED_BY_SPELL
, m_spellInfo
->Id
);
4109 NewSummon
->GetCharmInfo()->SetPetNumber(pet_number
, true);
4110 // this enables pet details window (Shift+P)
4112 // this enables popup window (pet dismiss, cancel), hunter pet additional flags set later
4113 NewSummon
->SetUInt32Value(UNIT_FIELD_FLAGS
,UNIT_FLAG_PVP_ATTACKABLE
);
4115 NewSummon
->InitStatsForLevel(petlevel
);
4116 NewSummon
->InitPetCreateSpells();
4118 if(NewSummon
->getPetType()==SUMMON_PET
)
4120 // Remove Demonic Sacrifice auras (new pet)
4121 Unit::AuraList
const& auraClassScripts
= m_caster
->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS
);
4122 for(Unit::AuraList::const_iterator itr
= auraClassScripts
.begin();itr
!=auraClassScripts
.end();)
4124 if((*itr
)->GetModifier()->m_miscvalue
==2228)
4126 m_caster
->RemoveAurasDueToSpell((*itr
)->GetId());
4127 itr
= auraClassScripts
.begin();
4133 // generate new name for summon pet
4134 std::string new_name
=objmgr
.GeneratePetName(petentry
);
4135 if(!new_name
.empty())
4136 NewSummon
->SetName(new_name
);
4138 else if(NewSummon
->getPetType()==HUNTER_PET
)
4139 NewSummon
->SetByteValue(UNIT_FIELD_BYTES_2
, 2, UNIT_RENAME_NOT_ALLOWED
);
4141 NewSummon
->AIM_Initialize();
4142 NewSummon
->SetHealth(NewSummon
->GetMaxHealth());
4143 NewSummon
->SetPower(POWER_MANA
, NewSummon
->GetMaxPower(POWER_MANA
));
4145 map
->Add((Creature
*)NewSummon
);
4147 m_caster
->SetPet(NewSummon
);
4148 sLog
.outDebug("New Pet has guid %u", NewSummon
->GetGUIDLow());
4150 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
4152 NewSummon
->SavePetToDB(PET_SAVE_AS_CURRENT
);
4153 ((Player
*)m_caster
)->PetSpellInitialize();
4157 void Spell::EffectLearnPetSpell(uint32 i
)
4159 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
4162 Player
*_player
= (Player
*)m_caster
;
4164 Pet
*pet
= _player
->GetPet();
4170 SpellEntry
const *learn_spellproto
= sSpellStore
.LookupEntry(m_spellInfo
->EffectTriggerSpell
[i
]);
4171 if(!learn_spellproto
)
4174 pet
->learnSpell(learn_spellproto
->Id
);
4176 pet
->SavePetToDB(PET_SAVE_AS_CURRENT
);
4177 _player
->PetSpellInitialize();
4180 void Spell::EffectTaunt(uint32
/*i*/)
4182 // this effect use before aura Taunt apply for prevent taunt already attacking target
4183 // for spell as marked "non effective at already attacking target"
4184 if(unitTarget
&& unitTarget
->GetTypeId() != TYPEID_PLAYER
)
4186 if(unitTarget
->getVictim()==m_caster
)
4188 SendCastResult(SPELL_FAILED_DONT_REPORT
);
4193 // Also use this effect to set the taunter's threat to the taunted creature's highest value
4194 if(unitTarget
->CanHaveThreatList() && unitTarget
->getThreatManager().getCurrentVictim())
4195 unitTarget
->getThreatManager().addThreat(m_caster
,unitTarget
->getThreatManager().getCurrentVictim()->getThreat());
4198 void Spell::EffectWeaponDmg(uint32 i
)
4202 if(!unitTarget
->isAlive())
4205 // multiple weapon dmg effect workaround
4206 // execute only the last weapon damage
4207 // and handle all effects at once
4208 for (int j
= 0; j
< 3; j
++)
4210 switch(m_spellInfo
->Effect
[j
])
4212 case SPELL_EFFECT_WEAPON_DAMAGE
:
4213 case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL
:
4214 case SPELL_EFFECT_NORMALIZED_WEAPON_DMG
:
4215 case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE
:
4216 if (j
< i
) // we must calculate only at last weapon effect
4222 // some spell specific modifiers
4223 bool customBonusDamagePercentMod
= false;
4224 float bonusDamagePercentMod
= 1.0f
; // applied to fixed effect damage bonus if set customBonusDamagePercentMod
4225 float weaponDamagePercentMod
= 1.0f
; // applied to weapon damage (and to fixed effect damage bonus if customBonusDamagePercentMod not set
4226 float totalDamagePercentMod
= 1.0f
; // applied to final bonus+weapon damage
4227 bool normalized
= false;
4229 int32 spell_bonus
= 0; // bonus specific for spell
4230 switch(m_spellInfo
->SpellFamilyName
)
4232 case SPELLFAMILY_WARRIOR
:
4234 // Whirlwind, single only spell with 2 weapon white damage apply if have
4235 if(m_caster
->GetTypeId()==TYPEID_PLAYER
&& (m_spellInfo
->SpellFamilyFlags
& 0x00000400000000LL
))
4237 if(((Player
*)m_caster
)->GetWeaponForAttack(OFF_ATTACK
,true))
4238 spell_bonus
+= m_caster
->CalculateDamage (OFF_ATTACK
, normalized
);
4240 // Devastate bonus and sunder armor refresh
4241 else if(m_spellInfo
->SpellVisual
[0] == 671 && m_spellInfo
->SpellIconID
== 1508)
4243 customBonusDamagePercentMod
= true;
4244 bonusDamagePercentMod
= 0.0f
; // only applied if auras found
4246 Unit::AuraList
const& list
= unitTarget
->GetAurasByType(SPELL_AURA_MOD_RESISTANCE
);
4247 for(Unit::AuraList::const_iterator itr
=list
.begin();itr
!=list
.end();++itr
)
4249 SpellEntry
const *proto
= (*itr
)->GetSpellProto();
4250 if(proto
->SpellVisual
[0] == 406 && proto
->SpellIconID
== 565)
4252 int32 duration
= GetSpellDuration(proto
);
4253 (*itr
)->SetAuraDuration(duration
);
4254 (*itr
)->SendAuraUpdate(false);
4255 bonusDamagePercentMod
+= 1.0f
; // +100%
4261 case SPELLFAMILY_ROGUE
:
4264 if(m_spellInfo
->SpellFamilyFlags
& 0x00000200LL
)
4266 customBonusDamagePercentMod
= true;
4267 bonusDamagePercentMod
= 2.5f
; // 250%
4269 // Mutilate (for each hand)
4270 else if(m_spellInfo
->SpellFamilyFlags
& 0x600000000LL
)
4274 if(unitTarget
->HasAuraState(AURA_STATE_DEADLY_POISON
))
4279 Unit::AuraMap
const& auras
= unitTarget
->GetAuras();
4280 for(Unit::AuraMap::const_iterator itr
= auras
.begin(); itr
!=auras
.end(); ++itr
)
4282 if(itr
->second
->GetSpellProto()->Dispel
== DISPEL_POISON
)
4291 totalDamagePercentMod
*= 1.5f
; // 150% if poisoned
4295 case SPELLFAMILY_PALADIN
:
4297 // Seal of Command - receive benefit from Spell Damage and Healing
4298 if(m_spellInfo
->SpellFamilyFlags
& 0x00000002000000LL
)
4300 spell_bonus
+= int32(0.20f
*m_caster
->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo
)));
4301 spell_bonus
+= int32(0.29f
*m_caster
->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo
), unitTarget
));
4305 case SPELLFAMILY_SHAMAN
:
4307 // Skyshatter Harness item set bonus
4309 if(m_spellInfo
->SpellFamilyFlags
& 0x001000000000LL
)
4311 Unit::AuraList
const& m_OverrideClassScript
= m_caster
->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS
);
4312 for(Unit::AuraList::const_iterator i
= m_OverrideClassScript
.begin(); i
!= m_OverrideClassScript
.end(); ++i
)
4314 // Stormstrike AP Buff
4315 if ( (*i
)->GetModifier()->m_miscvalue
== 5634 )
4317 m_caster
->CastSpell(m_caster
,38430,true,NULL
,*i
);
4325 int32 fixed_bonus
= 0;
4326 for (int j
= 0; j
< 3; j
++)
4328 switch(m_spellInfo
->Effect
[j
])
4330 case SPELL_EFFECT_WEAPON_DAMAGE
:
4331 case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL
:
4332 fixed_bonus
+= CalculateDamage(j
,unitTarget
);
4334 case SPELL_EFFECT_NORMALIZED_WEAPON_DMG
:
4335 fixed_bonus
+= CalculateDamage(j
,unitTarget
);
4338 case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE
:
4339 weaponDamagePercentMod
*= float(CalculateDamage(j
,unitTarget
)) / 100.0f
;
4341 // applied only to prev.effects fixed damage
4342 if(customBonusDamagePercentMod
)
4343 fixed_bonus
= int32(fixed_bonus
*bonusDamagePercentMod
);
4345 fixed_bonus
= int32(fixed_bonus
*weaponDamagePercentMod
);
4348 break; // not weapon damage effect, just skip
4352 // non-weapon damage
4353 int32 bonus
= spell_bonus
+ fixed_bonus
;
4355 // apply to non-weapon bonus weapon total pct effect, weapon total flat effect included in weapon damage
4359 switch(m_attackType
)
4362 case BASE_ATTACK
: unitMod
= UNIT_MOD_DAMAGE_MAINHAND
; break;
4363 case OFF_ATTACK
: unitMod
= UNIT_MOD_DAMAGE_OFFHAND
; break;
4364 case RANGED_ATTACK
: unitMod
= UNIT_MOD_DAMAGE_RANGED
; break;
4367 float weapon_total_pct
= m_caster
->GetModifierValue(unitMod
, TOTAL_PCT
);
4368 bonus
= int32(bonus
*weapon_total_pct
);
4371 // + weapon damage with applied weapon% dmg to base weapon damage in call
4372 bonus
+= int32(m_caster
->CalculateDamage(m_attackType
, normalized
)*weaponDamagePercentMod
);
4375 bonus
= int32(bonus
*totalDamagePercentMod
);
4377 // prevent negative damage
4378 uint32 eff_damage
= uint32(bonus
> 0 ? bonus
: 0);
4380 const uint32 nohitMask
= HITINFO_ABSORB
| HITINFO_RESIST
| HITINFO_MISS
;
4383 VictimState victimState
= VICTIMSTATE_NORMAL
;
4384 uint32 blocked_dmg
= 0;
4385 uint32 absorbed_dmg
= 0;
4386 uint32 resisted_dmg
= 0;
4387 CleanDamage cleanDamage
= CleanDamage(0, BASE_ATTACK
, MELEE_HIT_NORMAL
);
4389 m_caster
->DoAttackDamage(unitTarget
, &eff_damage
, &cleanDamage
, &blocked_dmg
, m_spellSchoolMask
, &hitInfo
, &victimState
, &absorbed_dmg
, &resisted_dmg
, m_attackType
, m_spellInfo
, m_IsTriggeredSpell
);
4391 if ((hitInfo
& nohitMask
) && m_attackType
!= RANGED_ATTACK
) // not send ranged miss/etc
4392 m_caster
->SendAttackStateUpdate(hitInfo
& nohitMask
, unitTarget
, 1, m_spellSchoolMask
, eff_damage
, absorbed_dmg
, resisted_dmg
, VICTIMSTATE_NORMAL
, blocked_dmg
);
4394 bool criticalhit
= (hitInfo
& HITINFO_CRITICALHIT
);
4395 m_caster
->SendSpellNonMeleeDamageLog(unitTarget
, m_spellInfo
->Id
, eff_damage
, m_spellSchoolMask
, absorbed_dmg
, resisted_dmg
, false, blocked_dmg
, criticalhit
);
4397 if (eff_damage
> (absorbed_dmg
+ resisted_dmg
+ blocked_dmg
))
4399 eff_damage
-= (absorbed_dmg
+ resisted_dmg
+ blocked_dmg
);
4403 cleanDamage
.damage
+= eff_damage
;
4407 // SPELL_SCHOOL_NORMAL use for weapon-like threat and rage calculation
4408 m_caster
->DealDamage(unitTarget
, eff_damage
, &cleanDamage
, SPELL_DIRECT_DAMAGE
, SPELL_SCHOOL_MASK_NORMAL
, NULL
, true);
4411 if(m_spellInfo
->SpellFamilyName
==SPELLFAMILY_ROGUE
&& (m_spellInfo
->SpellFamilyFlags
& 0x2000000))
4413 if(m_caster
->GetTypeId()==TYPEID_PLAYER
)
4414 ((Player
*)m_caster
)->AddComboPoints(unitTarget
, 1);
4418 if(m_spellInfo
->SpellFamilyName
==SPELLFAMILY_DRUID
&& (m_spellInfo
->SpellFamilyFlags
==0x0000040000000000LL
))
4420 if(m_caster
->GetTypeId()==TYPEID_PLAYER
)
4421 ((Player
*)m_caster
)->AddComboPoints(unitTarget
,1);
4425 if(m_attackType
== RANGED_ATTACK
&& m_caster
->GetTypeId() == TYPEID_PLAYER
)
4427 Item
*pItem
= ((Player
*)m_caster
)->GetWeaponForAttack( RANGED_ATTACK
);
4429 // wands don't have ammo
4430 if(!pItem
|| pItem
->IsBroken() || pItem
->GetProto()->SubClass
==ITEM_SUBCLASS_WEAPON_WAND
)
4433 if( pItem
->GetProto()->InventoryType
== INVTYPE_THROWN
)
4435 if(pItem
->GetMaxStackCount()==1)
4437 // decrease durability for non-stackable throw weapon
4438 ((Player
*)m_caster
)->DurabilityPointLossForEquipSlot(EQUIPMENT_SLOT_RANGED
);
4442 // decrease items amount for stackable throw weapon
4444 ((Player
*)m_caster
)->DestroyItemCount( pItem
, count
, true);
4447 else if(uint32 ammo
= ((Player
*)m_caster
)->GetUInt32Value(PLAYER_AMMO_ID
))
4448 ((Player
*)m_caster
)->DestroyItemCount(ammo
, 1, true);
4452 void Spell::EffectThreat(uint32
/*i*/)
4454 if(!unitTarget
|| !unitTarget
->isAlive() || !m_caster
->isAlive())
4457 if(!unitTarget
->CanHaveThreatList())
4460 unitTarget
->AddThreat(m_caster
, float(damage
));
4463 void Spell::EffectHealMaxHealth(uint32
/*i*/)
4467 if(!unitTarget
->isAlive())
4470 uint32 heal
= m_caster
->GetMaxHealth();
4472 int32 gain
= unitTarget
->ModifyHealth(heal
);
4473 unitTarget
->getHostilRefManager().threatAssist(m_caster
, float(gain
) * 0.5f
, m_spellInfo
);
4475 m_caster
->SendHealSpellLog(unitTarget
, m_spellInfo
->Id
, heal
);
4478 void Spell::EffectInterruptCast(uint32
/*i*/)
4482 if(!unitTarget
->isAlive())
4485 // TODO: not all spells that used this effect apply cooldown at school spells
4486 // also exist case: apply cooldown to interrupted cast only and to all spells
4487 for (uint32 i
= CURRENT_FIRST_NON_MELEE_SPELL
; i
< CURRENT_MAX_SPELL
; i
++)
4489 if (unitTarget
->m_currentSpells
[i
])
4491 // check if we can interrupt spell
4492 if ( unitTarget
->m_currentSpells
[i
]->m_spellInfo
->InterruptFlags
& SPELL_INTERRUPT_FLAG_INTERRUPT
&& unitTarget
->m_currentSpells
[i
]->m_spellInfo
->PreventionType
== SPELL_PREVENTION_TYPE_SILENCE
)
4494 unitTarget
->ProhibitSpellScholl(GetSpellSchoolMask(unitTarget
->m_currentSpells
[i
]->m_spellInfo
), GetSpellDuration(m_spellInfo
));
4495 unitTarget
->InterruptSpell(i
,false);
4501 void Spell::EffectSummonObjectWild(uint32 i
)
4503 uint32 gameobject_id
= m_spellInfo
->EffectMiscValue
[i
];
4505 GameObject
* pGameObj
= new GameObject
;
4507 WorldObject
* target
= focusObject
;
4512 if(m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
4514 x
= m_targets
.m_destX
;
4515 y
= m_targets
.m_destY
;
4516 z
= m_targets
.m_destZ
;
4519 m_caster
->GetClosePoint(x
,y
,z
,DEFAULT_WORLD_OBJECT_SIZE
);
4521 Map
*map
= target
->GetMap();
4523 if(!pGameObj
->Create(objmgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), gameobject_id
, map
,
4524 x
, y
, z
, target
->GetOrientation(), 0, 0, 0, 0, 100, 1))
4530 int32 duration
= GetSpellDuration(m_spellInfo
);
4531 pGameObj
->SetRespawnTime(duration
> 0 ? duration
/1000 : 0);
4532 pGameObj
->SetSpellId(m_spellInfo
->Id
);
4534 if(pGameObj
->GetGoType() != GAMEOBJECT_TYPE_FLAGDROP
) // make dropped flag clickable for other players (not set owner guid (created by) for this)...
4535 m_caster
->AddGameObject(pGameObj
);
4538 if(pGameObj
->GetMapId() == 489 && pGameObj
->GetGoType() == GAMEOBJECT_TYPE_FLAGDROP
) //WS
4540 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
4542 Player
*pl
= (Player
*)m_caster
;
4543 BattleGround
* bg
= ((Player
*)m_caster
)->GetBattleGround();
4544 if(bg
&& bg
->GetTypeID()==BATTLEGROUND_WS
&& bg
->GetStatus() == STATUS_IN_PROGRESS
)
4546 uint32 team
= ALLIANCE
;
4548 if(pl
->GetTeam() == team
)
4551 ((BattleGroundWS
*)bg
)->SetDroppedFlagGUID(pGameObj
->GetGUID(),team
);
4556 if(pGameObj
->GetMapId() == 566 && pGameObj
->GetGoType() == GAMEOBJECT_TYPE_FLAGDROP
) //EY
4558 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
4560 BattleGround
* bg
= ((Player
*)m_caster
)->GetBattleGround();
4561 if(bg
&& bg
->GetTypeID()==BATTLEGROUND_EY
&& bg
->GetStatus() == STATUS_IN_PROGRESS
)
4563 ((BattleGroundEY
*)bg
)->SetDroppedFlagGUID(pGameObj
->GetGUID());
4568 if(uint32 linkedEntry
= pGameObj
->GetLinkedGameObjectEntry())
4570 GameObject
* linkedGO
= new GameObject
;
4571 if(linkedGO
->Create(objmgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), linkedEntry
, map
,
4572 x
, y
, z
, target
->GetOrientation(), 0, 0, 0, 0, 100, 1))
4574 linkedGO
->SetRespawnTime(duration
> 0 ? duration
/1000 : 0);
4575 linkedGO
->SetSpellId(m_spellInfo
->Id
);
4577 m_caster
->AddGameObject(linkedGO
);
4589 void Spell::EffectScriptEffect(uint32 effIndex
)
4591 // TODO: we must implement hunter pet summon at login there (spell 6962)
4594 switch(m_spellInfo
->Id
)
4596 // PX-238 Winter Wondervolt TRAP
4599 if( unitTarget
->HasAura(26272,0)
4600 || unitTarget
->HasAura(26157,0)
4601 || unitTarget
->HasAura(26273,0)
4602 || unitTarget
->HasAura(26274,0))
4610 iTmpSpellId
= 26272;
4613 iTmpSpellId
= 26157;
4616 iTmpSpellId
= 26273;
4619 iTmpSpellId
= 26274;
4623 unitTarget
->CastSpell(unitTarget
, iTmpSpellId
, true);
4631 if(!itemTarget
&& m_caster
->GetTypeId()!=TYPEID_PLAYER
)
4634 uint32 spell_id
= 0;
4637 case 1: spell_id
= 8854; break;
4638 default: spell_id
= 8855; break;
4641 m_caster
->CastSpell(m_caster
,spell_id
,true,NULL
);
4645 // Healthstone creating spells
4655 Unit::AuraList
const& mDummyAuras
= unitTarget
->GetAurasByType(SPELL_AURA_DUMMY
);
4656 for(Unit::AuraList::const_iterator i
= mDummyAuras
.begin();i
!= mDummyAuras
.end(); ++i
)
4658 if((*i
)->GetId() == 18692)
4663 else if((*i
)->GetId() == 18693)
4670 static uint32
const itypes
[6][3] = {
4671 { 5512,19004,19005}, // Minor Healthstone
4672 { 5511,19006,19007}, // Lesser Healthstone
4673 { 5509,19008,19009}, // Healthstone
4674 { 5510,19010,19011}, // Greater Healthstone
4675 { 9421,19012,19013}, // Major Healthstone
4676 {22103,22104,22105} // Master Healthstone
4679 switch(m_spellInfo
->Id
)
4681 case 6201: itemtype
=itypes
[0][rank
];break; // Minor Healthstone
4682 case 6202: itemtype
=itypes
[1][rank
];break; // Lesser Healthstone
4683 case 5699: itemtype
=itypes
[2][rank
];break; // Healthstone
4684 case 11729: itemtype
=itypes
[3][rank
];break; // Greater Healthstone
4685 case 11730: itemtype
=itypes
[4][rank
];break; // Major Healthstone
4686 case 27230: itemtype
=itypes
[5][rank
];break; // Master Healthstone
4690 DoCreateItem( effIndex
, itemtype
);
4693 // Brittle Armor - need remove one 24575 Brittle Armor aura
4695 unitTarget
->RemoveSingleAuraFromStack(24575, 0);
4696 unitTarget
->RemoveSingleAuraFromStack(24575, 1);
4698 // Mercurial Shield - need remove one 26464 Mercurial Shield aura
4700 unitTarget
->RemoveSingleAuraFromStack(26464, 0);
4702 // Orb teleport spells
4716 switch(m_spellInfo
->Id
)
4718 case 25140: spellid
= 32571; break;
4719 case 25143: spellid
= 32572; break;
4720 case 25650: spellid
= 30140; break;
4721 case 25652: spellid
= 30141; break;
4722 case 29128: spellid
= 32568; break;
4723 case 29129: spellid
= 32569; break;
4724 case 35376: spellid
= 25649; break;
4725 case 35727: spellid
= 35730; break;
4730 unitTarget
->CastSpell(unitTarget
,spellid
,false);
4734 // Shadow Flame (All script effects, not just end ones to prevent player from dodging the last triggered spell)
4749 if(!unitTarget
|| !unitTarget
->isAlive())
4752 // Onyxia Scale Cloak
4753 if(unitTarget
->GetDummyAura(22683))
4757 m_caster
->CastSpell(unitTarget
, 22682, true);
4762 // Summon Black Qiraji Battle Tank
4768 // Prevent stacking of mounts
4769 unitTarget
->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED
);
4771 // Two separate mounts depending on area id (allows use both in and out of specific instance)
4772 if (unitTarget
->GetAreaId() == 3428)
4773 unitTarget
->CastSpell(unitTarget
, 25863, false);
4775 unitTarget
->CastSpell(unitTarget
, 26655, false);
4778 // Piccolo of the Flaming Fire
4781 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
4783 unitTarget
->HandleEmoteCommand(EMOTE_STATE_DANCE
);
4792 unitTarget
->CastSpell(unitTarget
, 28694, true);
4801 // 25% chance of casting a random buff
4802 if(roll_chance_i(75))
4805 // triggered spells are 28703 to 28707
4806 // Note: some sources say, that there was the possibility of
4807 // receiving a debuff. However, this seems to be removed by a patch.
4808 const uint32 spellid
= 28703;
4810 // don't overwrite an existing aura
4811 for(uint8 i
=0; i
<5; i
++)
4812 if(unitTarget
->HasAura(spellid
+i
, 0))
4814 unitTarget
->CastSpell(unitTarget
, spellid
+urand(0, 4), true);
4823 // 25% chance of casting Nightmare Pollen
4824 if(roll_chance_i(75))
4826 unitTarget
->CastSpell(unitTarget
, 28721, true);
4830 // Mirren's Drinking Hat
4834 switch ( urand(1,6) )
4836 case 1: case 2: case 3: item
= 23584; break;// Loch Modan Lager
4837 case 4: case 5: item
= 23585; break;// Stouthammer Lite
4838 case 6: item
= 23586; break;// Aerie Peak Pale Ale
4841 DoCreateItem(effIndex
,item
);
4847 // Removes snares and roots.
4848 uint32 mechanic_mask
= (1<<MECHANIC_ROOT
) | (1<<MECHANIC_SNARE
);
4849 Unit::AuraMap
& Auras
= unitTarget
->GetAuras();
4850 for(Unit::AuraMap::iterator iter
= Auras
.begin(), next
; iter
!= Auras
.end(); iter
= next
)
4854 Aura
*aur
= iter
->second
;
4855 if (!aur
->IsPositive()) //only remove negative spells
4857 // check for mechanic mask
4858 if(GetSpellMechanicMask(aur
->GetSpellProto(), aur
->GetEffIndex()) & mechanic_mask
)
4860 unitTarget
->RemoveAurasDueToSpell(aur
->GetId());
4864 next
= Auras
.begin();
4870 case 41126: // Flame Crash
4875 unitTarget
->CastSpell(unitTarget
, 41131, true);
4878 case 44876: // Force Cast - Portal Effect: Sunwell Isle
4883 unitTarget
->CastSpell(unitTarget
, 44870, true);
4887 // Goblin Weather Machine
4909 unitTarget
->CastSpell(unitTarget
, spellId
, true);
4915 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
4918 ((Player
*)unitTarget
)->ModifyMoney(50000000);
4924 if( m_spellInfo
->SpellFamilyName
== SPELLFAMILY_PALADIN
)
4926 switch(m_spellInfo
->SpellFamilyFlags
)
4931 if(!unitTarget
|| !unitTarget
->isAlive())
4933 uint32 spellId2
= 0;
4935 // all seals have aura dummy
4936 Unit::AuraList
const& m_dummyAuras
= m_caster
->GetAurasByType(SPELL_AURA_DUMMY
);
4937 for(Unit::AuraList::const_iterator itr
= m_dummyAuras
.begin(); itr
!= m_dummyAuras
.end(); ++itr
)
4939 SpellEntry
const *spellInfo
= (*itr
)->GetSpellProto();
4941 // search seal (all seals have judgement's aura dummy spell id in 2 effect
4942 if ( !spellInfo
|| !IsSealSpell((*itr
)->GetSpellProto()) || (*itr
)->GetEffIndex() != 2 )
4945 // must be calculated base at raw base points in spell proto, GetModifier()->m_value for S.Righteousness modified by SPELLMOD_DAMAGE
4946 spellId2
= (*itr
)->GetSpellProto()->EffectBasePoints
[2]+1;
4951 // found, remove seal
4952 m_caster
->RemoveAurasDueToSpell((*itr
)->GetId());
4954 // Sanctified Judgement
4955 Unit::AuraList
const& m_auras
= m_caster
->GetAurasByType(SPELL_AURA_DUMMY
);
4956 for(Unit::AuraList::const_iterator i
= m_auras
.begin(); i
!= m_auras
.end(); ++i
)
4958 if ((*i
)->GetSpellProto()->SpellIconID
== 205 && (*i
)->GetSpellProto()->Attributes
== 0x01D0LL
)
4960 int32 chance
= (*i
)->GetModifier()->m_amount
;
4961 if ( roll_chance_i(chance
) )
4963 int32 mana
= spellInfo
->manaCost
;
4964 if ( Player
* modOwner
= m_caster
->GetSpellModOwner() )
4965 modOwner
->ApplySpellMod(spellInfo
->Id
, SPELLMOD_COST
, mana
);
4966 mana
= int32(mana
* 0.8f
);
4967 m_caster
->CastCustomSpell(m_caster
,31930,&mana
,NULL
,NULL
,true,NULL
,*i
);
4976 m_caster
->CastSpell(unitTarget
,spellId2
,true);
4982 // normal DB scripted effect
4986 sLog
.outDebug("Spell ScriptStart spellid %u in EffectScriptEffect ", m_spellInfo
->Id
);
4987 sWorld
.ScriptsStart(sSpellScripts
, m_spellInfo
->Id
, m_caster
, unitTarget
);
4990 void Spell::EffectSanctuary(uint32
/*i*/)
4994 //unitTarget->CombatStop();
4996 unitTarget
->CombatStop();
4997 unitTarget
->getHostilRefManager().deleteReferences(); // stop all fighting
4998 // Vanish allows to remove all threat and cast regular stealth so other spells can be used
4999 if(m_spellInfo
->SpellFamilyName
== SPELLFAMILY_ROGUE
&& (m_spellInfo
->SpellFamilyFlags
& SPELLFAMILYFLAG_ROGUE_VANISH
))
5001 ((Player
*)m_caster
)->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT
);
5005 void Spell::EffectAddComboPoints(uint32
/*i*/)
5010 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5016 ((Player
*)m_caster
)->AddComboPoints(unitTarget
, damage
);
5019 void Spell::EffectDuel(uint32 i
)
5021 if(!m_caster
|| !unitTarget
|| m_caster
->GetTypeId() != TYPEID_PLAYER
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5024 Player
*caster
= (Player
*)m_caster
;
5025 Player
*target
= (Player
*)unitTarget
;
5027 // caster or target already have requested duel
5028 if( caster
->duel
|| target
->duel
|| !target
->GetSocial() || target
->GetSocial()->HasIgnore(caster
->GetGUIDLow()) )
5031 // Players can only fight a duel with each other outside (=not inside dungeons and not in capital cities)
5032 // Don't have to check the target's map since you cannot challenge someone across maps
5033 uint32 mapid
= caster
->GetMapId();
5034 if( mapid
!= 0 && mapid
!= 1 && mapid
!= 530 && mapid
!= 571 && mapid
!= 609)
5036 SendCastResult(SPELL_FAILED_NO_DUELING
); // Dueling isn't allowed here
5040 AreaTableEntry
const* casterAreaEntry
= GetAreaEntryByAreaID(caster
->GetZoneId());
5041 if(casterAreaEntry
&& (casterAreaEntry
->flags
& AREA_FLAG_CAPITAL
) )
5043 SendCastResult(SPELL_FAILED_NO_DUELING
); // Dueling isn't allowed here
5047 AreaTableEntry
const* targetAreaEntry
= GetAreaEntryByAreaID(target
->GetZoneId());
5048 if(targetAreaEntry
&& (targetAreaEntry
->flags
& AREA_FLAG_CAPITAL
) )
5050 SendCastResult(SPELL_FAILED_NO_DUELING
); // Dueling isn't allowed here
5054 //CREATE DUEL FLAG OBJECT
5055 GameObject
* pGameObj
= new GameObject
;
5057 uint32 gameobject_id
= m_spellInfo
->EffectMiscValue
[i
];
5059 Map
*map
= m_caster
->GetMap();
5060 if(!pGameObj
->Create(objmgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), gameobject_id
, map
,
5061 m_caster
->GetPositionX()+(unitTarget
->GetPositionX()-m_caster
->GetPositionX())/2 ,
5062 m_caster
->GetPositionY()+(unitTarget
->GetPositionY()-m_caster
->GetPositionY())/2 ,
5063 m_caster
->GetPositionZ(),
5064 m_caster
->GetOrientation(), 0, 0, 0, 0, 0, 1))
5070 pGameObj
->SetUInt32Value(GAMEOBJECT_FACTION
, m_caster
->getFaction() );
5071 pGameObj
->SetUInt32Value(GAMEOBJECT_LEVEL
, m_caster
->getLevel()+1 );
5072 int32 duration
= GetSpellDuration(m_spellInfo
);
5073 pGameObj
->SetRespawnTime(duration
> 0 ? duration
/1000 : 0);
5074 pGameObj
->SetSpellId(m_spellInfo
->Id
);
5076 m_caster
->AddGameObject(pGameObj
);
5081 WorldPacket
data(SMSG_DUEL_REQUESTED
, 16);
5082 data
<< pGameObj
->GetGUID();
5083 data
<< caster
->GetGUID();
5084 caster
->GetSession()->SendPacket(&data
);
5085 target
->GetSession()->SendPacket(&data
);
5088 DuelInfo
*duel
= new DuelInfo
;
5089 duel
->initiator
= caster
;
5090 duel
->opponent
= target
;
5091 duel
->startTime
= 0;
5092 duel
->startTimer
= 0;
5093 caster
->duel
= duel
;
5095 DuelInfo
*duel2
= new DuelInfo
;
5096 duel2
->initiator
= caster
;
5097 duel2
->opponent
= caster
;
5098 duel2
->startTime
= 0;
5099 duel2
->startTimer
= 0;
5100 target
->duel
= duel2
;
5102 caster
->SetUInt64Value(PLAYER_DUEL_ARBITER
,pGameObj
->GetGUID());
5103 target
->SetUInt64Value(PLAYER_DUEL_ARBITER
,pGameObj
->GetGUID());
5106 void Spell::EffectStuck(uint32
/*i*/)
5108 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5111 if(!sWorld
.getConfig(CONFIG_CAST_UNSTUCK
))
5114 Player
* pTarget
= (Player
*)unitTarget
;
5116 sLog
.outDebug("Spell Effect: Stuck");
5117 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());
5119 if(pTarget
->isInFlight())
5122 // homebind location is loaded always
5123 pTarget
->TeleportTo(pTarget
->m_homebindMapId
,pTarget
->m_homebindX
,pTarget
->m_homebindY
,pTarget
->m_homebindZ
,pTarget
->GetOrientation(), (unitTarget
==m_caster
? TELE_TO_SPELL
: 0));
5125 // Stuck spell trigger Hearthstone cooldown
5126 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(8690);
5129 Spell
spell(pTarget
,spellInfo
,true,0);
5130 spell
.SendSpellCooldown();
5133 void Spell::EffectSummonPlayer(uint32
/*i*/)
5135 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5138 // Evil Twin (ignore player summon, but hide this for summoner)
5139 if(unitTarget
->GetDummyAura(23445))
5143 m_caster
->GetClosePoint(x
,y
,z
,unitTarget
->GetObjectSize());
5145 ((Player
*)unitTarget
)->SetSummonPoint(m_caster
->GetMapId(),x
,y
,z
);
5147 WorldPacket
data(SMSG_SUMMON_REQUEST
, 8+4+4);
5148 data
<< uint64(m_caster
->GetGUID()); // summoner guid
5149 data
<< uint32(m_caster
->GetZoneId()); // summoner zone
5150 data
<< uint32(MAX_PLAYER_SUMMON_DELAY
*1000); // auto decline after msecs
5151 ((Player
*)unitTarget
)->GetSession()->SendPacket(&data
);
5154 static ScriptInfo
generateActivateCommand()
5157 si
.command
= SCRIPT_COMMAND_ACTIVATE_OBJECT
;
5161 void Spell::EffectActivateObject(uint32 effect_idx
)
5166 static ScriptInfo activateCommand
= generateActivateCommand();
5168 int32 delay_secs
= m_spellInfo
->EffectMiscValue
[effect_idx
];
5170 sWorld
.ScriptCommandStart(activateCommand
, delay_secs
, m_caster
, gameObjTarget
);
5173 void Spell::EffectApplyGlyph(uint32 i
)
5175 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5178 Player
*player
= (Player
*)m_caster
;
5181 if(uint32 oldglyph
= player
->GetGlyph(m_glyphIndex
))
5183 if(GlyphPropertiesEntry
const *old_gp
= sGlyphPropertiesStore
.LookupEntry(oldglyph
))
5185 player
->RemoveAurasDueToSpell(old_gp
->SpellId
);
5186 player
->SetGlyph(m_glyphIndex
, 0);
5191 if(uint32 glyph
= m_spellInfo
->EffectMiscValue
[i
])
5193 if(GlyphPropertiesEntry
const *gp
= sGlyphPropertiesStore
.LookupEntry(glyph
))
5195 if(GlyphSlotEntry
const *gs
= sGlyphSlotStore
.LookupEntry(player
->GetGlyphSlot(m_glyphIndex
)))
5197 if(gp
->TypeFlags
!= gs
->TypeFlags
)
5199 SendCastResult(SPELL_FAILED_INVALID_GLYPH
);
5200 return; // glyph slot missmatch
5204 player
->CastSpell(m_caster
, gp
->SpellId
, true);
5205 player
->SetGlyph(m_glyphIndex
, glyph
);
5207 player
->DestroyItemCount(m_CastItem
->GetEntry(), 1, true);
5212 void Spell::EffectSummonTotem(uint32 i
)
5215 switch(m_spellInfo
->EffectMiscValueB
[i
])
5217 case SUMMON_TYPE_TOTEM_SLOT1
: slot
= 0; break;
5218 case SUMMON_TYPE_TOTEM_SLOT2
: slot
= 1; break;
5219 case SUMMON_TYPE_TOTEM_SLOT3
: slot
= 2; break;
5220 case SUMMON_TYPE_TOTEM_SLOT4
: slot
= 3; break;
5221 // Battle standard case
5222 case SUMMON_TYPE_TOTEM
: slot
= 254; break;
5223 // jewelery statue case, like totem without slot
5224 case SUMMON_TYPE_GUARDIAN
: slot
= 255; break;
5228 if(slot
< MAX_TOTEM
)
5230 uint64 guid
= m_caster
->m_TotemSlot
[slot
];
5233 Creature
*OldTotem
= ObjectAccessor::GetCreature(*m_caster
, guid
);
5234 if(OldTotem
&& OldTotem
->isTotem())
5235 ((Totem
*)OldTotem
)->UnSummon();
5240 if (m_caster
->GetTypeId()==TYPEID_PLAYER
)
5241 team
= ((Player
*)m_caster
)->GetTeam();
5243 Totem
* pTotem
= new Totem
;
5245 if(!pTotem
->Create(objmgr
.GenerateLowGuid(HIGHGUID_UNIT
), m_caster
->GetMap(), m_spellInfo
->EffectMiscValue
[i
], team
))
5251 float angle
= slot
< MAX_TOTEM
? M_PI
/MAX_TOTEM
- (slot
*2*M_PI
/MAX_TOTEM
) : 0;
5254 m_caster
->GetClosePoint(x
,y
,z
,pTotem
->GetObjectSize(),2.0f
,angle
);
5256 // totem must be at same Z in case swimming caster and etc.
5257 if( fabs( z
- m_caster
->GetPositionZ() ) > 5 )
5258 z
= m_caster
->GetPositionZ();
5260 pTotem
->Relocate(x
, y
, z
, m_caster
->GetOrientation());
5262 if(slot
< MAX_TOTEM
)
5263 m_caster
->m_TotemSlot
[slot
] = pTotem
->GetGUID();
5265 pTotem
->SetOwner(m_caster
->GetGUID());
5266 pTotem
->SetTypeBySummonSpell(m_spellInfo
); // must be after Create call where m_spells initilized
5268 int32 duration
=GetSpellDuration(m_spellInfo
);
5269 if(Player
* modOwner
= m_caster
->GetSpellModOwner())
5270 modOwner
->ApplySpellMod(m_spellInfo
->Id
,SPELLMOD_DURATION
, duration
);
5271 pTotem
->SetDuration(duration
);
5273 if (damage
) // if not spell info, DB values used
5275 pTotem
->SetMaxHealth(damage
);
5276 pTotem
->SetHealth(damage
);
5279 pTotem
->SetUInt32Value(UNIT_CREATED_BY_SPELL
,m_spellInfo
->Id
);
5280 pTotem
->SetFlag(UNIT_FIELD_FLAGS
,UNIT_FLAG_PVP_ATTACKABLE
);
5282 pTotem
->ApplySpellImmune(m_spellInfo
->Id
,IMMUNITY_STATE
,SPELL_AURA_MOD_FEAR
,true);
5283 pTotem
->ApplySpellImmune(m_spellInfo
->Id
,IMMUNITY_STATE
,SPELL_AURA_TRANSFORM
,true);
5285 pTotem
->Summon(m_caster
);
5287 if(slot
< MAX_TOTEM
&& m_caster
->GetTypeId() == TYPEID_PLAYER
)
5289 WorldPacket
data(SMSG_TOTEM_CREATED
, 1+8+4+4);
5290 data
<< uint8(slot
);
5291 data
<< uint64(pTotem
->GetGUID());
5292 data
<< uint32(duration
);
5293 data
<< uint32(m_spellInfo
->Id
);
5294 ((Player
*)m_caster
)->SendDirectMessage(&data
);
5298 void Spell::EffectEnchantHeldItem(uint32 i
)
5300 // this is only item spell effect applied to main-hand weapon of target player (players in area)
5301 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5304 Player
* item_owner
= (Player
*)unitTarget
;
5305 Item
* item
= item_owner
->GetItemByPos(INVENTORY_SLOT_BAG_0
, EQUIPMENT_SLOT_MAINHAND
);
5311 if(!item
->IsEquipped())
5314 if (m_spellInfo
->EffectMiscValue
[i
])
5316 uint32 enchant_id
= m_spellInfo
->EffectMiscValue
[i
];
5317 int32 duration
= GetSpellDuration(m_spellInfo
); //Try duration index first ..
5319 duration
= m_currentBasePoints
[i
]+1; //Base points after ..
5321 duration
= 10; //10 seconds for enchants which don't have listed duration
5323 SpellItemEnchantmentEntry
const *pEnchant
= sSpellItemEnchantmentStore
.LookupEntry(enchant_id
);
5327 // Always go to temp enchantment slot
5328 EnchantmentSlot slot
= TEMP_ENCHANTMENT_SLOT
;
5330 // Enchantment will not be applied if a different one already exists
5331 if(item
->GetEnchantmentId(slot
) && item
->GetEnchantmentId(slot
) != enchant_id
)
5334 // Apply the temporary enchantment
5335 item
->SetEnchantment(slot
, enchant_id
, duration
*1000, 0);
5336 item_owner
->ApplyEnchantment(item
,slot
,true);
5340 void Spell::EffectDisEnchant(uint32
/*i*/)
5342 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5345 Player
* p_caster
= (Player
*)m_caster
;
5346 if(!itemTarget
|| !itemTarget
->GetProto()->DisenchantID
)
5349 p_caster
->UpdateCraftSkill(m_spellInfo
->Id
);
5351 ((Player
*)m_caster
)->SendLoot(itemTarget
->GetGUID(),LOOT_DISENCHANTING
);
5353 // item will be removed at disenchanting end
5356 void Spell::EffectInebriate(uint32
/*i*/)
5358 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5361 Player
*player
= (Player
*)unitTarget
;
5362 uint16 currentDrunk
= player
->GetDrunkValue();
5363 uint16 drunkMod
= damage
* 256;
5364 if (currentDrunk
+ drunkMod
> 0xFFFF)
5365 currentDrunk
= 0xFFFF;
5367 currentDrunk
+= drunkMod
;
5368 player
->SetDrunkValue(currentDrunk
, m_CastItem
?m_CastItem
->GetEntry():0);
5371 void Spell::EffectFeedPet(uint32 i
)
5373 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5376 Player
*_player
= (Player
*)m_caster
;
5381 Pet
*pet
= _player
->GetPet();
5388 int32 benefit
= pet
->GetCurrentFoodBenefitLevel(itemTarget
->GetProto()->ItemLevel
);
5393 _player
->DestroyItemCount(itemTarget
,count
,true);
5394 // TODO: fix crash when a spell has two effects, both pointed at the same item target
5396 m_caster
->CastCustomSpell(m_caster
,m_spellInfo
->EffectTriggerSpell
[i
],&benefit
,NULL
,NULL
,true);
5399 void Spell::EffectDismissPet(uint32
/*i*/)
5401 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5404 Pet
* pet
= m_caster
->GetPet();
5406 // not let dismiss dead pet
5407 if(!pet
||!pet
->isAlive())
5410 ((Player
*)m_caster
)->RemovePet(pet
,PET_SAVE_NOT_IN_SLOT
);
5413 void Spell::EffectSummonObject(uint32 i
)
5415 uint32 go_id
= m_spellInfo
->EffectMiscValue
[i
];
5418 switch(m_spellInfo
->Effect
[i
])
5420 case SPELL_EFFECT_SUMMON_OBJECT_SLOT1
: slot
= 0; break;
5421 case SPELL_EFFECT_SUMMON_OBJECT_SLOT2
: slot
= 1; break;
5422 case SPELL_EFFECT_SUMMON_OBJECT_SLOT3
: slot
= 2; break;
5423 case SPELL_EFFECT_SUMMON_OBJECT_SLOT4
: slot
= 3; break;
5427 uint64 guid
= m_caster
->m_ObjectSlot
[slot
];
5430 GameObject
* obj
= NULL
;
5432 obj
= ObjectAccessor::GetGameObject(*m_caster
, guid
);
5434 if(obj
) obj
->Delete();
5435 m_caster
->m_ObjectSlot
[slot
] = 0;
5438 GameObject
* pGameObj
= new GameObject
;
5440 float rot2
= sin(m_caster
->GetOrientation()/2);
5441 float rot3
= cos(m_caster
->GetOrientation()/2);
5444 // If dest location if present
5445 if (m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
5447 x
= m_targets
.m_destX
;
5448 y
= m_targets
.m_destY
;
5449 z
= m_targets
.m_destZ
;
5451 // Summon in random point all other units if location present
5453 m_caster
->GetClosePoint(x
,y
,z
,DEFAULT_WORLD_OBJECT_SIZE
);
5455 Map
*map
= m_caster
->GetMap();
5456 if(!pGameObj
->Create(objmgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), go_id
, map
, x
, y
, z
, m_caster
->GetOrientation(), 0, 0, rot2
, rot3
, 0, 1))
5462 pGameObj
->SetUInt32Value(GAMEOBJECT_LEVEL
,m_caster
->getLevel());
5463 int32 duration
= GetSpellDuration(m_spellInfo
);
5464 pGameObj
->SetRespawnTime(duration
> 0 ? duration
/1000 : 0);
5465 pGameObj
->SetSpellId(m_spellInfo
->Id
);
5466 m_caster
->AddGameObject(pGameObj
);
5469 WorldPacket
data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE
, 8);
5470 data
<< pGameObj
->GetGUID();
5471 m_caster
->SendMessageToSet(&data
,true);
5473 m_caster
->m_ObjectSlot
[slot
] = pGameObj
->GetGUID();
5476 void Spell::EffectResurrect(uint32
/*effIndex*/)
5480 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5483 if(unitTarget
->isAlive())
5485 if(!unitTarget
->IsInWorld())
5488 switch (m_spellInfo
->Id
)
5490 // Defibrillate (Goblin Jumper Cables) have 33% chance on success
5492 if (roll_chance_i(67))
5494 m_caster
->CastSpell(m_caster
, 8338, true, m_CastItem
);
5498 // Defibrillate (Goblin Jumper Cables XL) have 50% chance on success
5500 if (roll_chance_i(50))
5502 m_caster
->CastSpell(m_caster
, 23055, true, m_CastItem
);
5510 Player
* pTarget
= ((Player
*)unitTarget
);
5512 if(pTarget
->isRessurectRequested()) // already have one active request
5515 uint32 health
= pTarget
->GetMaxHealth() * damage
/ 100;
5516 uint32 mana
= pTarget
->GetMaxPower(POWER_MANA
) * damage
/ 100;
5518 pTarget
->setResurrectRequestData(m_caster
->GetGUID(), m_caster
->GetMapId(), m_caster
->GetPositionX(), m_caster
->GetPositionY(), m_caster
->GetPositionZ(), health
, mana
);
5519 SendResurrectRequest(pTarget
);
5522 void Spell::EffectAddExtraAttacks(uint32
/*i*/)
5524 if(!unitTarget
|| !unitTarget
->isAlive())
5527 if( unitTarget
->m_extraAttacks
)
5530 unitTarget
->m_extraAttacks
= damage
;
5533 void Spell::EffectParry(uint32
/*i*/)
5535 if (unitTarget
&& unitTarget
->GetTypeId() == TYPEID_PLAYER
)
5536 ((Player
*)unitTarget
)->SetCanParry(true);
5539 void Spell::EffectBlock(uint32
/*i*/)
5541 if (unitTarget
&& unitTarget
->GetTypeId() == TYPEID_PLAYER
)
5542 ((Player
*)unitTarget
)->SetCanBlock(true);
5545 void Spell::EffectMomentMove(uint32 i
)
5547 if(unitTarget
->isInFlight())
5550 if( m_spellInfo
->rangeIndex
== 1) //self range
5552 uint32 mapid
= m_caster
->GetMapId();
5553 float dis
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[i
]));
5557 unitTarget
->GetClosePoint(fx
,fy
,fz
,unitTarget
->GetObjectSize(),dis
);
5559 unitTarget
->GetPosition(ox
,oy
,oz
);
5561 float fx2
,fy2
,fz2
; // getObjectHitPos overwrite last args in any result case
5562 if(VMAP::VMapFactory::createOrGetVMapManager()->getObjectHitPos(mapid
, ox
,oy
,oz
+0.5, fx
,fy
,oz
+0.5,fx2
,fy2
,fz2
, -0.5))
5567 unitTarget
->UpdateGroundPositionZ(fx
,fy
,fz
);
5570 if(unitTarget
->GetTypeId() == TYPEID_PLAYER
)
5571 ((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));
5573 m_caster
->GetMap()->CreatureRelocation((Creature
*)unitTarget
, fx
, fy
, fz
, unitTarget
->GetOrientation());
5577 void Spell::EffectReputation(uint32 i
)
5579 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5582 Player
*_player
= (Player
*)unitTarget
;
5584 int32 rep_change
= m_currentBasePoints
[i
]+1; // field store reputation change -1
5586 uint32 faction_id
= m_spellInfo
->EffectMiscValue
[i
];
5588 FactionEntry
const* factionEntry
= sFactionStore
.LookupEntry(faction_id
);
5593 _player
->ModifyFactionReputation(factionEntry
,rep_change
);
5596 void Spell::EffectQuestComplete(uint32 i
)
5598 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5601 Player
*_player
= (Player
*)m_caster
;
5603 uint32 quest_id
= m_spellInfo
->EffectMiscValue
[i
];
5604 _player
->AreaExploredOrEventHappens(quest_id
);
5607 void Spell::EffectSelfResurrect(uint32 i
)
5609 if(!unitTarget
|| unitTarget
->isAlive())
5611 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5613 if(!unitTarget
->IsInWorld())
5622 health
= uint32(-damage
);
5623 mana
= m_spellInfo
->EffectMiscValue
[i
];
5628 health
= uint32(damage
/100.0f
*unitTarget
->GetMaxHealth());
5629 if(unitTarget
->GetMaxPower(POWER_MANA
) > 0)
5630 mana
= uint32(damage
/100.0f
*unitTarget
->GetMaxPower(POWER_MANA
));
5633 Player
*plr
= ((Player
*)unitTarget
);
5634 plr
->ResurrectPlayer(0.0f
);
5636 plr
->SetHealth( health
);
5637 plr
->SetPower(POWER_MANA
, mana
);
5638 plr
->SetPower(POWER_RAGE
, 0 );
5639 plr
->SetPower(POWER_ENERGY
, plr
->GetMaxPower(POWER_ENERGY
) );
5641 plr
->SpawnCorpseBones();
5646 void Spell::EffectSkinning(uint32
/*i*/)
5648 if(unitTarget
->GetTypeId() != TYPEID_UNIT
)
5650 if(!m_caster
|| m_caster
->GetTypeId() != TYPEID_PLAYER
)
5653 Creature
* creature
= (Creature
*) unitTarget
;
5654 int32 targetLevel
= creature
->getLevel();
5656 uint32 skill
= creature
->GetCreatureInfo()->GetRequiredLootSkill();
5658 ((Player
*)m_caster
)->SendLoot(creature
->GetGUID(),LOOT_SKINNING
);
5659 creature
->RemoveFlag(UNIT_FIELD_FLAGS
, UNIT_FLAG_SKINNABLE
);
5661 int32 reqValue
= targetLevel
< 10 ? 0 : targetLevel
< 20 ? (targetLevel
-10)*10 : targetLevel
*5;
5663 int32 skillValue
= ((Player
*)m_caster
)->GetPureSkillValue(skill
);
5665 // Double chances for elites
5666 ((Player
*)m_caster
)->UpdateGatherSkill(skill
, skillValue
, reqValue
, creature
->isElite() ? 2 : 1 );
5669 void Spell::EffectCharge(uint32
/*i*/)
5671 if(!unitTarget
|| !m_caster
)
5675 unitTarget
->GetContactPoint(m_caster
, x
, y
, z
);
5676 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5677 ((Creature
*)unitTarget
)->StopMoving();
5679 // Only send MOVEMENTFLAG_WALK_MODE, client has strange issues with other move flags
5680 m_caster
->SendMonsterMove(x
, y
, z
, 0, MOVEMENTFLAG_WALK_MODE
, 1);
5682 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5683 m_caster
->GetMap()->CreatureRelocation((Creature
*)m_caster
,x
,y
,z
,m_caster
->GetOrientation());
5685 // not all charge effects used in negative spells
5686 if ( !IsPositiveSpell(m_spellInfo
->Id
))
5687 m_caster
->Attack(unitTarget
,true);
5690 void Spell::EffectSummonCritter(uint32 i
)
5692 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5694 Player
* player
= (Player
*)m_caster
;
5696 uint32 pet_entry
= m_spellInfo
->EffectMiscValue
[i
];
5700 Pet
* old_critter
= player
->GetMiniPet();
5702 // for same pet just despawn
5703 if(old_critter
&& old_critter
->GetEntry() == pet_entry
)
5705 player
->RemoveMiniPet();
5709 // despawn old pet before summon new
5711 player
->RemoveMiniPet();
5714 Pet
* critter
= new Pet(MINI_PET
);
5716 Map
*map
= m_caster
->GetMap();
5717 uint32 pet_number
= objmgr
.GeneratePetNumber();
5718 if(!critter
->Create(objmgr
.GenerateLowGuid(HIGHGUID_PET
),
5719 map
, pet_entry
, pet_number
))
5721 sLog
.outError("Spell::EffectSummonCritter, spellid %u: no such creature entry %u", m_spellInfo
->Id
, pet_entry
);
5727 // If dest location if present
5728 if (m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
5730 x
= m_targets
.m_destX
;
5731 y
= m_targets
.m_destY
;
5732 z
= m_targets
.m_destZ
;
5734 // Summon if dest location not present near caster
5736 m_caster
->GetClosePoint(x
,y
,z
,critter
->GetObjectSize());
5738 critter
->Relocate(x
,y
,z
,m_caster
->GetOrientation());
5740 if(!critter
->IsPositionValid())
5742 sLog
.outError("ERROR: Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)",
5743 critter
->GetGUIDLow(), critter
->GetEntry(), critter
->GetPositionX(), critter
->GetPositionY());
5748 critter
->SetOwnerGUID(m_caster
->GetGUID());
5749 critter
->SetCreatorGUID(m_caster
->GetGUID());
5750 critter
->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE
,m_caster
->getFaction());
5751 critter
->SetUInt32Value(UNIT_CREATED_BY_SPELL
, m_spellInfo
->Id
);
5753 critter
->AIM_Initialize();
5754 critter
->InitPetCreateSpells(); // e.g. disgusting oozeling has a create spell as critter...
5755 critter
->SetMaxHealth(1);
5756 critter
->SetHealth(1);
5757 critter
->SetLevel(1);
5759 // set timer for unsummon
5760 int32 duration
= GetSpellDuration(m_spellInfo
);
5762 critter
->SetDuration(duration
);
5764 std::string name
= player
->GetName();
5765 name
.append(petTypeSuffix
[critter
->getPetType()]);
5766 critter
->SetName( name
);
5767 player
->SetMiniPet(critter
);
5769 map
->Add((Creature
*)critter
);
5772 void Spell::EffectKnockBack(uint32 i
)
5774 if(!unitTarget
|| !m_caster
)
5777 // Effect only works on players
5778 if(unitTarget
->GetTypeId()!=TYPEID_PLAYER
)
5781 float vsin
= sin(m_caster
->GetAngle(unitTarget
));
5782 float vcos
= cos(m_caster
->GetAngle(unitTarget
));
5784 WorldPacket
data(SMSG_MOVE_KNOCK_BACK
, (8+4+4+4+4+4));
5785 data
.append(unitTarget
->GetPackGUID());
5786 data
<< uint32(0); // Sequence
5787 data
<< float(vcos
); // x direction
5788 data
<< float(vsin
); // y direction
5789 data
<< float(m_spellInfo
->EffectMiscValue
[i
])/10; // Horizontal speed
5790 data
<< float(damage
/-10); // Z Movement speed (vertical)
5792 ((Player
*)unitTarget
)->GetSession()->SendPacket(&data
);
5795 void Spell::EffectSendTaxi(uint32 i
)
5797 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5800 TaxiPathEntry
const* entry
= sTaxiPathStore
.LookupEntry(m_spellInfo
->EffectMiscValue
[i
]);
5804 std::vector
<uint32
> nodes
;
5807 nodes
[0] = entry
->from
;
5808 nodes
[1] = entry
->to
;
5811 switch(m_spellInfo
->Id
)
5813 case 31606: //Stormcrow Amulet
5816 case 45071: //Quest - Sunwell Daily - Dead Scar Bombing Run
5817 case 45113: //Quest - Sunwell Daily - Ship Bombing Run
5818 case 45353: //Quest - Sunwell Daily - Ship Bombing Run Return
5821 case 34905: //Stealth Flight
5826 ((Player
*)unitTarget
)->ActivateTaxiPathTo(nodes
,mountid
);
5830 void Spell::EffectPlayerPull(uint32 i
)
5832 if(!unitTarget
|| !m_caster
)
5835 // Effect only works on players
5836 if(unitTarget
->GetTypeId()!=TYPEID_PLAYER
)
5839 float vsin
= sin(unitTarget
->GetAngle(m_caster
));
5840 float vcos
= cos(unitTarget
->GetAngle(m_caster
));
5842 WorldPacket
data(SMSG_MOVE_KNOCK_BACK
, (8+4+4+4+4+4));
5843 data
.append(unitTarget
->GetPackGUID());
5844 data
<< uint32(0); // Sequence
5845 data
<< float(vcos
); // x direction
5846 data
<< float(vsin
); // y direction
5848 data
<< float(damage
? damage
: unitTarget
->GetDistance2d(m_caster
));
5849 data
<< float(m_spellInfo
->EffectMiscValue
[i
])/-10; // Z Movement speed
5851 ((Player
*)unitTarget
)->GetSession()->SendPacket(&data
);
5854 void Spell::EffectDispelMechanic(uint32 i
)
5859 uint32 mechanic
= m_spellInfo
->EffectMiscValue
[i
];
5861 Unit::AuraMap
& Auras
= unitTarget
->GetAuras();
5862 for(Unit::AuraMap::iterator iter
= Auras
.begin(), next
; iter
!= Auras
.end(); iter
= next
)
5866 SpellEntry
const *spell
= sSpellStore
.LookupEntry(iter
->second
->GetSpellProto()->Id
);
5867 if(spell
->Mechanic
== mechanic
|| spell
->EffectMechanic
[iter
->second
->GetEffIndex()] == mechanic
)
5869 unitTarget
->RemoveAurasDueToSpell(spell
->Id
);
5873 next
= Auras
.begin();
5879 void Spell::EffectSummonDeadPet(uint32
/*i*/)
5881 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5883 Player
*_player
= (Player
*)m_caster
;
5884 Pet
*pet
= _player
->GetPet();
5891 pet
->SetUInt32Value(UNIT_DYNAMIC_FLAGS
, 0);
5892 pet
->RemoveFlag (UNIT_FIELD_FLAGS
, UNIT_FLAG_SKINNABLE
);
5893 pet
->setDeathState( ALIVE
);
5894 pet
->clearUnitState(UNIT_STAT_ALL_STATE
);
5895 pet
->SetHealth( uint32(pet
->GetMaxHealth()*(float(damage
)/100)));
5897 pet
->AIM_Initialize();
5899 _player
->PetSpellInitialize();
5900 pet
->SavePetToDB(PET_SAVE_AS_CURRENT
);
5903 void Spell::EffectDestroyAllTotems(uint32
/*i*/)
5906 for(int slot
= 0; slot
< MAX_TOTEM
; ++slot
)
5908 if(!m_caster
->m_TotemSlot
[slot
])
5911 Creature
* totem
= ObjectAccessor::GetCreature(*m_caster
,m_caster
->m_TotemSlot
[slot
]);
5912 if(totem
&& totem
->isTotem())
5914 uint32 spell_id
= totem
->GetUInt32Value(UNIT_CREATED_BY_SPELL
);
5915 SpellEntry
const* spellInfo
= sSpellStore
.LookupEntry(spell_id
);
5917 mana
+= spellInfo
->manaCost
* damage
/ 100;
5918 ((Totem
*)totem
)->UnSummon();
5922 int32 gain
= m_caster
->ModifyPower(POWER_MANA
,int32(mana
));
5923 m_caster
->SendEnergizeSpellLog(m_caster
, m_spellInfo
->Id
, gain
, POWER_MANA
);
5926 void Spell::EffectDurabilityDamage(uint32 i
)
5928 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5931 int32 slot
= m_spellInfo
->EffectMiscValue
[i
];
5933 // FIXME: some spells effects have value -1/-2
5934 // Possibly its mean -1 all player equipped items and -2 all items
5937 ((Player
*)unitTarget
)->DurabilityPointsLossAll(damage
,(slot
< -1));
5941 // invalid slot value
5942 if(slot
>= INVENTORY_SLOT_BAG_END
)
5945 if(Item
* item
= ((Player
*)unitTarget
)->GetItemByPos(INVENTORY_SLOT_BAG_0
,slot
))
5946 ((Player
*)unitTarget
)->DurabilityPointsLoss(item
,damage
);
5949 void Spell::EffectDurabilityDamagePCT(uint32 i
)
5951 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5954 int32 slot
= m_spellInfo
->EffectMiscValue
[i
];
5956 // FIXME: some spells effects have value -1/-2
5957 // Possibly its mean -1 all player equipped items and -2 all items
5960 ((Player
*)unitTarget
)->DurabilityLossAll(double(damage
)/100.0f
,(slot
< -1));
5964 // invalid slot value
5965 if(slot
>= INVENTORY_SLOT_BAG_END
)
5971 if(Item
* item
= ((Player
*)unitTarget
)->GetItemByPos(INVENTORY_SLOT_BAG_0
,slot
))
5972 ((Player
*)unitTarget
)->DurabilityLoss(item
,double(damage
)/100.0f
);
5975 void Spell::EffectModifyThreatPercent(uint32
/*effIndex*/)
5980 unitTarget
->getThreatManager().modifyThreatPercent(m_caster
, damage
);
5983 void Spell::EffectTransmitted(uint32 effIndex
)
5985 uint32 name_id
= m_spellInfo
->EffectMiscValue
[effIndex
];
5987 GameObjectInfo
const* goinfo
= objmgr
.GetGameObjectInfo(name_id
);
5991 sLog
.outErrorDb("Gameobject (Entry: %u) not exist and not created at spell (ID: %u) cast",name_id
, m_spellInfo
->Id
);
5997 if(m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
5999 fx
= m_targets
.m_destX
;
6000 fy
= m_targets
.m_destY
;
6001 fz
= m_targets
.m_destZ
;
6003 //FIXME: this can be better check for most objects but still hack
6004 else if(m_spellInfo
->EffectRadiusIndex
[effIndex
] && m_spellInfo
->speed
==0)
6006 float dis
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[effIndex
]));
6007 m_caster
->GetClosePoint(fx
,fy
,fz
,DEFAULT_WORLD_OBJECT_SIZE
, dis
);
6011 float min_dis
= GetSpellMinRange(sSpellRangeStore
.LookupEntry(m_spellInfo
->rangeIndex
));
6012 float max_dis
= GetSpellMaxRange(sSpellRangeStore
.LookupEntry(m_spellInfo
->rangeIndex
));
6013 float dis
= rand_norm() * (max_dis
- min_dis
) + min_dis
;
6015 m_caster
->GetClosePoint(fx
,fy
,fz
,DEFAULT_WORLD_OBJECT_SIZE
, dis
);
6018 Map
*cMap
= m_caster
->GetMap();
6020 if(goinfo
->type
==GAMEOBJECT_TYPE_FISHINGNODE
)
6022 if ( !cMap
->IsInWater(fx
,fy
,fz
-0.5f
)) // Hack to prevent fishing bobber from failing to land on fishing hole
6023 { // but this is not proper, we really need to ignore not materialized objects
6024 SendCastResult(SPELL_FAILED_NOT_HERE
);
6025 SendChannelUpdate(0);
6029 // replace by water level in this case
6030 fz
= cMap
->GetWaterLevel(fx
,fy
);
6032 // if gameobject is summoning object, it should be spawned right on caster's position
6033 else if(goinfo
->type
==GAMEOBJECT_TYPE_SUMMONING_RITUAL
)
6035 m_caster
->GetPosition(fx
,fy
,fz
);
6038 GameObject
* pGameObj
= new GameObject
;
6040 if(!pGameObj
->Create(objmgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), name_id
, cMap
,
6041 fx
, fy
, fz
, m_caster
->GetOrientation(), 0, 0, 0, 0, 100, 1))
6047 int32 duration
= GetSpellDuration(m_spellInfo
);
6049 switch(goinfo
->type
)
6051 case GAMEOBJECT_TYPE_FISHINGNODE
:
6053 m_caster
->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT
,pGameObj
->GetGUID());
6055 pGameObj
->SetFloatValue(GAMEOBJECT_PARENTROTATION
+ 2, 0.88431775569915771 );
6057 pGameObj
->SetFloatValue(GAMEOBJECT_PARENTROTATION
+ 3, -0.4668855369091033 );
6058 m_caster
->AddGameObject(pGameObj
); // will removed at spell cancel
6060 // end time of range when possible catch fish (FISHING_BOBBER_READY_TIME..GetDuration(m_spellInfo))
6061 // start time == fish-FISHING_BOBBER_READY_TIME (0..GetDuration(m_spellInfo)-FISHING_BOBBER_READY_TIME)
6065 case 0: lastSec
= 3; break;
6066 case 1: lastSec
= 7; break;
6067 case 2: lastSec
= 13; break;
6068 case 3: lastSec
= 17; break;
6071 duration
= duration
- lastSec
*1000 + FISHING_BOBBER_READY_TIME
*1000;
6074 case GAMEOBJECT_TYPE_SUMMONING_RITUAL
:
6076 if(m_caster
->GetTypeId()==TYPEID_PLAYER
)
6078 pGameObj
->AddUniqueUse((Player
*)m_caster
);
6079 m_caster
->AddGameObject(pGameObj
); // will removed at spell cancel
6083 case GAMEOBJECT_TYPE_FISHINGHOLE
:
6084 case GAMEOBJECT_TYPE_CHEST
:
6091 pGameObj
->SetRespawnTime(duration
> 0 ? duration
/1000 : 0);
6093 pGameObj
->SetOwnerGUID(m_caster
->GetGUID() );
6095 pGameObj
->SetUInt32Value(GAMEOBJECT_LEVEL
, m_caster
->getLevel() );
6096 pGameObj
->SetSpellId(m_spellInfo
->Id
);
6098 DEBUG_LOG("AddObject at SpellEfects.cpp EffectTransmitted\n");
6099 //m_caster->AddGameObject(pGameObj);
6100 //m_ObjToDel.push_back(pGameObj);
6102 cMap
->Add(pGameObj
);
6104 WorldPacket
data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE
, 8);
6105 data
<< uint64(pGameObj
->GetGUID());
6106 m_caster
->SendMessageToSet(&data
,true);
6108 if(uint32 linkedEntry
= pGameObj
->GetLinkedGameObjectEntry())
6110 GameObject
* linkedGO
= new GameObject
;
6111 if(linkedGO
->Create(objmgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), linkedEntry
, cMap
,
6112 fx
, fy
, fz
, m_caster
->GetOrientation(), 0, 0, 0, 0, 100, 1))
6114 linkedGO
->SetRespawnTime(duration
> 0 ? duration
/1000 : 0);
6115 linkedGO
->SetUInt32Value(GAMEOBJECT_LEVEL
, m_caster
->getLevel() );
6116 linkedGO
->SetSpellId(m_spellInfo
->Id
);
6117 linkedGO
->SetOwnerGUID(m_caster
->GetGUID() );
6119 linkedGO
->GetMap()->Add(linkedGO
);
6130 void Spell::EffectProspecting(uint32
/*i*/)
6132 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
6135 Player
* p_caster
= (Player
*)m_caster
;
6136 if(!itemTarget
|| !(itemTarget
->GetProto()->BagFamily
& BAG_FAMILY_MASK_MINING_SUPP
))
6139 if(itemTarget
->GetCount() < 5)
6142 if( sWorld
.getConfig(CONFIG_SKILL_PROSPECTING
))
6144 uint32 SkillValue
= p_caster
->GetPureSkillValue(SKILL_JEWELCRAFTING
);
6145 uint32 reqSkillValue
= itemTarget
->GetProto()->RequiredSkillRank
;
6146 p_caster
->UpdateGatherSkill(SKILL_JEWELCRAFTING
, SkillValue
, reqSkillValue
);
6149 ((Player
*)m_caster
)->SendLoot(itemTarget
->GetGUID(), LOOT_PROSPECTING
);
6152 void Spell::EffectMilling(uint32
/*i*/)
6154 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
6157 Player
* p_caster
= (Player
*)m_caster
;
6158 if(!itemTarget
|| !(itemTarget
->GetProto()->BagFamily
& BAG_FAMILY_MASK_HERBS
))
6161 if(itemTarget
->GetCount() < 5)
6164 if( sWorld
.getConfig(CONFIG_SKILL_MILLING
))
6166 uint32 SkillValue
= p_caster
->GetPureSkillValue(SKILL_INSCRIPTION
);
6167 uint32 reqSkillValue
= itemTarget
->GetProto()->RequiredSkillRank
;
6168 p_caster
->UpdateGatherSkill(SKILL_INSCRIPTION
, SkillValue
, reqSkillValue
);
6171 ((Player
*)m_caster
)->SendLoot(itemTarget
->GetGUID(), LOOT_MILLING
);
6174 void Spell::EffectSkill(uint32
/*i*/)
6176 sLog
.outDebug("WORLD: SkillEFFECT");
6179 void Spell::EffectSummonDemon(uint32 i
)
6181 float px
= m_targets
.m_destX
;
6182 float py
= m_targets
.m_destY
;
6183 float pz
= m_targets
.m_destZ
;
6185 Creature
* Charmed
= m_caster
->SummonCreature(m_spellInfo
->EffectMiscValue
[i
], px
, py
, pz
, m_caster
->GetOrientation(),TEMPSUMMON_TIMED_OR_DEAD_DESPAWN
,3600000);
6189 // might not always work correctly, maybe the creature that dies from CoD casts the effect on itself and is therefore the caster?
6190 Charmed
->SetLevel(m_caster
->getLevel());
6192 // TODO: Add damage/mana/hp according to level
6194 if (m_spellInfo
->EffectMiscValue
[i
] == 89) // Inferno summon
6196 // Enslave demon effect, without mana cost and cooldown
6197 m_caster
->CastSpell(Charmed
, 20882, true); // FIXME: enslave does not scale with level, level 62+ minions cannot be enslaved
6200 Charmed
->CastSpell(Charmed
, 22703, true, 0);
6204 /* There is currently no need for this effect. We handle it in BattleGround.cpp
6205 If we would handle the resurrection here, the spiritguide would instantly disappear as the
6206 player revives, and so we wouldn't see the spirit heal visual effect on the npc.
6207 This is why we use a half sec delay between the visual effect and the resurrection itself */
6208 void Spell::EffectSpiritHeal(uint32
/*i*/)
6211 if(!unitTarget || unitTarget->isAlive())
6213 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
6215 if(!unitTarget->IsInWorld())
6218 //m_spellInfo->EffectBasePoints[i]; == 99 (percent?)
6219 //((Player*)unitTarget)->setResurrect(m_caster->GetGUID(), unitTarget->GetPositionX(), unitTarget->GetPositionY(), unitTarget->GetPositionZ(), unitTarget->GetMaxHealth(), unitTarget->GetMaxPower(POWER_MANA));
6220 ((Player*)unitTarget)->ResurrectPlayer(1.0f);
6221 ((Player*)unitTarget)->SpawnCorpseBones();
6225 // remove insignia spell effect
6226 void Spell::EffectSkinPlayerCorpse(uint32
/*i*/)
6228 sLog
.outDebug("Effect: SkinPlayerCorpse");
6229 if ( (m_caster
->GetTypeId() != TYPEID_PLAYER
) || (unitTarget
->GetTypeId() != TYPEID_PLAYER
) || (unitTarget
->isAlive()) )
6232 ((Player
*)unitTarget
)->RemovedInsignia( (Player
*)m_caster
);
6235 void Spell::EffectStealBeneficialBuff(uint32 i
)
6237 sLog
.outDebug("Effect: StealBeneficialBuff");
6239 if(!unitTarget
|| unitTarget
==m_caster
) // can't steal from self
6242 std::vector
<Aura
*> steal_list
;
6243 // Create dispel mask by dispel type
6244 uint32 dispelMask
= GetDispellMask( DispelType(m_spellInfo
->EffectMiscValue
[i
]) );
6245 Unit::AuraMap
const& auras
= unitTarget
->GetAuras();
6246 for(Unit::AuraMap::const_iterator itr
= auras
.begin(); itr
!= auras
.end(); ++itr
)
6248 Aura
*aur
= (*itr
).second
;
6249 if (aur
&& (1<<aur
->GetSpellProto()->Dispel
) & dispelMask
)
6251 // Need check for passive? this
6252 if (aur
->IsPositive() && !aur
->IsPassive())
6253 steal_list
.push_back(aur
);
6256 // Ok if exist some buffs for dispel try dispel it
6257 if (!steal_list
.empty())
6259 std::list
< std::pair
<uint32
,uint64
> > success_list
;
6260 int32 list_size
= steal_list
.size();
6261 // Dispell N = damage buffs (or while exist buffs for dispel)
6262 for (int32 count
=0; count
< damage
&& list_size
> 0; ++count
)
6264 // Random select buff for dispel
6265 Aura
*aur
= steal_list
[urand(0, list_size
-1)];
6266 // Not use chance for steal
6267 // TODO possible need do it
6268 success_list
.push_back( std::pair
<uint32
,uint64
>(aur
->GetId(),aur
->GetCasterGUID()));
6270 // Remove buff from list for prevent doubles
6271 for (std::vector
<Aura
*>::iterator j
= steal_list
.begin(); j
!= steal_list
.end(); )
6274 if (stealed
->GetId() == aur
->GetId() && stealed
->GetCasterGUID() == aur
->GetCasterGUID())
6276 j
= steal_list
.erase(j
);
6283 // Really try steal and send log
6284 if (!success_list
.empty())
6286 int32 count
= success_list
.size();
6287 WorldPacket
data(SMSG_SPELLSTEALLOG
, 8+8+4+1+4+count
*5);
6288 data
.append(unitTarget
->GetPackGUID()); // Victim GUID
6289 data
.append(m_caster
->GetPackGUID()); // Caster GUID
6290 data
<< uint32(m_spellInfo
->Id
); // Dispell spell id
6291 data
<< uint8(0); // not used
6292 data
<< uint32(count
); // count
6293 for (std::list
<std::pair
<uint32
,uint64
> >::iterator j
= success_list
.begin(); j
!= success_list
.end(); ++j
)
6295 SpellEntry
const* spellInfo
= sSpellStore
.LookupEntry(j
->first
);
6296 data
<< uint32(spellInfo
->Id
); // Spell Id
6297 data
<< uint8(0); // 0 - steals !=0 transfers
6298 unitTarget
->RemoveAurasDueToSpellBySteal(spellInfo
->Id
, j
->second
, m_caster
);
6300 m_caster
->SendMessageToSet(&data
, true);
6305 void Spell::EffectKillCredit(uint32 i
)
6307 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
6310 ((Player
*)unitTarget
)->KilledMonster(m_spellInfo
->EffectMiscValue
[i
], 0);
6313 void Spell::EffectQuestFail(uint32 i
)
6315 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
6318 ((Player
*)unitTarget
)->FailQuest(m_spellInfo
->EffectMiscValue
[i
]);
6321 void Spell::EffectActivateRune(uint32 i
)
6323 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
6326 Player
*plr
= (Player
*)m_caster
;
6328 if(plr
->getClass() != CLASS_DEATH_KNIGHT
)
6331 for(uint32 j
= 0; j
< MAX_RUNES
; ++j
)
6333 if(plr
->GetRuneCooldown(j
) && plr
->GetCurrentRune(j
) == m_spellInfo
->EffectMiscValue
[i
])
6335 plr
->SetRuneCooldown(j
, 0);
6340 void Spell::EffectTitanGrip(uint32 i
)
6342 if (unitTarget
&& unitTarget
->GetTypeId() == TYPEID_PLAYER
)
6343 ((Player
*)unitTarget
)->SetCanTitanGrip(true);