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"
57 pEffect SpellEffects
[TOTAL_SPELL_EFFECTS
]=
59 &Spell::EffectNULL
, // 0
60 &Spell::EffectInstaKill
, // 1 SPELL_EFFECT_INSTAKILL
61 &Spell::EffectSchoolDMG
, // 2 SPELL_EFFECT_SCHOOL_DAMAGE
62 &Spell::EffectDummy
, // 3 SPELL_EFFECT_DUMMY
63 &Spell::EffectUnused
, // 4 SPELL_EFFECT_PORTAL_TELEPORT unused
64 &Spell::EffectTeleportUnits
, // 5 SPELL_EFFECT_TELEPORT_UNITS
65 &Spell::EffectApplyAura
, // 6 SPELL_EFFECT_APPLY_AURA
66 &Spell::EffectEnvirinmentalDMG
, // 7 SPELL_EFFECT_ENVIRONMENTAL_DAMAGE
67 &Spell::EffectPowerDrain
, // 8 SPELL_EFFECT_POWER_DRAIN
68 &Spell::EffectHealthLeech
, // 9 SPELL_EFFECT_HEALTH_LEECH
69 &Spell::EffectHeal
, // 10 SPELL_EFFECT_HEAL
70 &Spell::EffectUnused
, // 11 SPELL_EFFECT_BIND
71 &Spell::EffectNULL
, // 12 SPELL_EFFECT_PORTAL
72 &Spell::EffectUnused
, // 13 SPELL_EFFECT_RITUAL_BASE unused
73 &Spell::EffectUnused
, // 14 SPELL_EFFECT_RITUAL_SPECIALIZE unused
74 &Spell::EffectUnused
, // 15 SPELL_EFFECT_RITUAL_ACTIVATE_PORTAL unused
75 &Spell::EffectQuestComplete
, // 16 SPELL_EFFECT_QUEST_COMPLETE
76 &Spell::EffectWeaponDmg
, // 17 SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL
77 &Spell::EffectResurrect
, // 18 SPELL_EFFECT_RESURRECT
78 &Spell::EffectAddExtraAttacks
, // 19 SPELL_EFFECT_ADD_EXTRA_ATTACKS
79 &Spell::EffectUnused
, // 20 SPELL_EFFECT_DODGE one spell: Dodge
80 &Spell::EffectUnused
, // 21 SPELL_EFFECT_EVADE one spell: Evade (DND)
81 &Spell::EffectParry
, // 22 SPELL_EFFECT_PARRY
82 &Spell::EffectBlock
, // 23 SPELL_EFFECT_BLOCK one spell: Block
83 &Spell::EffectCreateItem
, // 24 SPELL_EFFECT_CREATE_ITEM
84 &Spell::EffectUnused
, // 25 SPELL_EFFECT_WEAPON
85 &Spell::EffectUnused
, // 26 SPELL_EFFECT_DEFENSE one spell: Defense
86 &Spell::EffectPersistentAA
, // 27 SPELL_EFFECT_PERSISTENT_AREA_AURA
87 &Spell::EffectSummonType
, // 28 SPELL_EFFECT_SUMMON
88 &Spell::EffectMomentMove
, // 29 SPELL_EFFECT_LEAP
89 &Spell::EffectEnergize
, // 30 SPELL_EFFECT_ENERGIZE
90 &Spell::EffectWeaponDmg
, // 31 SPELL_EFFECT_WEAPON_PERCENT_DAMAGE
91 &Spell::EffectTriggerMissileSpell
, // 32 SPELL_EFFECT_TRIGGER_MISSILE
92 &Spell::EffectOpenLock
, // 33 SPELL_EFFECT_OPEN_LOCK
93 &Spell::EffectSummonChangeItem
, // 34 SPELL_EFFECT_SUMMON_CHANGE_ITEM
94 &Spell::EffectApplyAreaAura
, // 35 SPELL_EFFECT_APPLY_AREA_AURA_PARTY
95 &Spell::EffectLearnSpell
, // 36 SPELL_EFFECT_LEARN_SPELL
96 &Spell::EffectUnused
, // 37 SPELL_EFFECT_SPELL_DEFENSE one spell: SPELLDEFENSE (DND)
97 &Spell::EffectDispel
, // 38 SPELL_EFFECT_DISPEL
98 &Spell::EffectUnused
, // 39 SPELL_EFFECT_LANGUAGE
99 &Spell::EffectDualWield
, // 40 SPELL_EFFECT_DUAL_WIELD
100 &Spell::EffectSummonWild
, // 41 SPELL_EFFECT_SUMMON_WILD
101 &Spell::EffectSummonGuardian
, // 42 SPELL_EFFECT_SUMMON_GUARDIAN
102 &Spell::EffectTeleUnitsFaceCaster
, // 43 SPELL_EFFECT_TELEPORT_UNITS_FACE_CASTER
103 &Spell::EffectLearnSkill
, // 44 SPELL_EFFECT_SKILL_STEP
104 &Spell::EffectAddHonor
, // 45 SPELL_EFFECT_ADD_HONOR honor/pvp related
105 &Spell::EffectNULL
, // 46 SPELL_EFFECT_SPAWN we must spawn pet there
106 &Spell::EffectTradeSkill
, // 47 SPELL_EFFECT_TRADE_SKILL
107 &Spell::EffectUnused
, // 48 SPELL_EFFECT_STEALTH one spell: Base Stealth
108 &Spell::EffectUnused
, // 49 SPELL_EFFECT_DETECT one spell: Detect
109 &Spell::EffectTransmitted
, // 50 SPELL_EFFECT_TRANS_DOOR
110 &Spell::EffectUnused
, // 51 SPELL_EFFECT_FORCE_CRITICAL_HIT unused
111 &Spell::EffectUnused
, // 52 SPELL_EFFECT_GUARANTEE_HIT one spell: zzOLDCritical Shot
112 &Spell::EffectEnchantItemPerm
, // 53 SPELL_EFFECT_ENCHANT_ITEM
113 &Spell::EffectEnchantItemTmp
, // 54 SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY
114 &Spell::EffectTameCreature
, // 55 SPELL_EFFECT_TAMECREATURE
115 &Spell::EffectSummonPet
, // 56 SPELL_EFFECT_SUMMON_PET
116 &Spell::EffectLearnPetSpell
, // 57 SPELL_EFFECT_LEARN_PET_SPELL
117 &Spell::EffectWeaponDmg
, // 58 SPELL_EFFECT_WEAPON_DAMAGE
118 &Spell::EffectOpenSecretSafe
, // 59 SPELL_EFFECT_OPEN_LOCK_ITEM
119 &Spell::EffectProficiency
, // 60 SPELL_EFFECT_PROFICIENCY
120 &Spell::EffectSendEvent
, // 61 SPELL_EFFECT_SEND_EVENT
121 &Spell::EffectPowerBurn
, // 62 SPELL_EFFECT_POWER_BURN
122 &Spell::EffectThreat
, // 63 SPELL_EFFECT_THREAT
123 &Spell::EffectTriggerSpell
, // 64 SPELL_EFFECT_TRIGGER_SPELL
124 &Spell::EffectUnused
, // 65 SPELL_EFFECT_HEALTH_FUNNEL unused
125 &Spell::EffectUnused
, // 66 SPELL_EFFECT_POWER_FUNNEL unused
126 &Spell::EffectHealMaxHealth
, // 67 SPELL_EFFECT_HEAL_MAX_HEALTH
127 &Spell::EffectInterruptCast
, // 68 SPELL_EFFECT_INTERRUPT_CAST
128 &Spell::EffectDistract
, // 69 SPELL_EFFECT_DISTRACT
129 &Spell::EffectPull
, // 70 SPELL_EFFECT_PULL one spell: Distract Move
130 &Spell::EffectPickPocket
, // 71 SPELL_EFFECT_PICKPOCKET
131 &Spell::EffectAddFarsight
, // 72 SPELL_EFFECT_ADD_FARSIGHT
132 &Spell::EffectSummonGuardian
, // 73 SPELL_EFFECT_SUMMON_POSSESSED
133 &Spell::EffectSummonTotem
, // 74 SPELL_EFFECT_SUMMON_TOTEM
134 &Spell::EffectHealMechanical
, // 75 SPELL_EFFECT_HEAL_MECHANICAL one spell: Mechanical Patch Kit
135 &Spell::EffectSummonObjectWild
, // 76 SPELL_EFFECT_SUMMON_OBJECT_WILD
136 &Spell::EffectScriptEffect
, // 77 SPELL_EFFECT_SCRIPT_EFFECT
137 &Spell::EffectUnused
, // 78 SPELL_EFFECT_ATTACK
138 &Spell::EffectSanctuary
, // 79 SPELL_EFFECT_SANCTUARY
139 &Spell::EffectAddComboPoints
, // 80 SPELL_EFFECT_ADD_COMBO_POINTS
140 &Spell::EffectUnused
, // 81 SPELL_EFFECT_CREATE_HOUSE one spell: Create House (TEST)
141 &Spell::EffectNULL
, // 82 SPELL_EFFECT_BIND_SIGHT
142 &Spell::EffectDuel
, // 83 SPELL_EFFECT_DUEL
143 &Spell::EffectStuck
, // 84 SPELL_EFFECT_STUCK
144 &Spell::EffectSummonPlayer
, // 85 SPELL_EFFECT_SUMMON_PLAYER
145 &Spell::EffectActivateObject
, // 86 SPELL_EFFECT_ACTIVATE_OBJECT
146 &Spell::EffectSummonTotem
, // 87 SPELL_EFFECT_SUMMON_TOTEM_SLOT1
147 &Spell::EffectSummonTotem
, // 88 SPELL_EFFECT_SUMMON_TOTEM_SLOT2
148 &Spell::EffectSummonTotem
, // 89 SPELL_EFFECT_SUMMON_TOTEM_SLOT3
149 &Spell::EffectSummonTotem
, // 90 SPELL_EFFECT_SUMMON_TOTEM_SLOT4
150 &Spell::EffectUnused
, // 91 SPELL_EFFECT_THREAT_ALL one spell: zzOLDBrainwash
151 &Spell::EffectEnchantHeldItem
, // 92 SPELL_EFFECT_ENCHANT_HELD_ITEM
152 &Spell::EffectUnused
, // 93 SPELL_EFFECT_SUMMON_PHANTASM
153 &Spell::EffectSelfResurrect
, // 94 SPELL_EFFECT_SELF_RESURRECT
154 &Spell::EffectSkinning
, // 95 SPELL_EFFECT_SKINNING
155 &Spell::EffectCharge
, // 96 SPELL_EFFECT_CHARGE
156 &Spell::EffectSummonCritter
, // 97 SPELL_EFFECT_SUMMON_CRITTER
157 &Spell::EffectKnockBack
, // 98 SPELL_EFFECT_KNOCK_BACK
158 &Spell::EffectDisEnchant
, // 99 SPELL_EFFECT_DISENCHANT
159 &Spell::EffectInebriate
, //100 SPELL_EFFECT_INEBRIATE
160 &Spell::EffectFeedPet
, //101 SPELL_EFFECT_FEED_PET
161 &Spell::EffectDismissPet
, //102 SPELL_EFFECT_DISMISS_PET
162 &Spell::EffectReputation
, //103 SPELL_EFFECT_REPUTATION
163 &Spell::EffectSummonObject
, //104 SPELL_EFFECT_SUMMON_OBJECT_SLOT1
164 &Spell::EffectSummonObject
, //105 SPELL_EFFECT_SUMMON_OBJECT_SLOT2
165 &Spell::EffectSummonObject
, //106 SPELL_EFFECT_SUMMON_OBJECT_SLOT3
166 &Spell::EffectSummonObject
, //107 SPELL_EFFECT_SUMMON_OBJECT_SLOT4
167 &Spell::EffectDispelMechanic
, //108 SPELL_EFFECT_DISPEL_MECHANIC
168 &Spell::EffectSummonDeadPet
, //109 SPELL_EFFECT_SUMMON_DEAD_PET
169 &Spell::EffectDestroyAllTotems
, //110 SPELL_EFFECT_DESTROY_ALL_TOTEMS
170 &Spell::EffectDurabilityDamage
, //111 SPELL_EFFECT_DURABILITY_DAMAGE
171 &Spell::EffectSummonDemon
, //112 SPELL_EFFECT_SUMMON_DEMON
172 &Spell::EffectResurrectNew
, //113 SPELL_EFFECT_RESURRECT_NEW
173 &Spell::EffectTaunt
, //114 SPELL_EFFECT_ATTACK_ME
174 &Spell::EffectDurabilityDamagePCT
, //115 SPELL_EFFECT_DURABILITY_DAMAGE_PCT
175 &Spell::EffectSkinPlayerCorpse
, //116 SPELL_EFFECT_SKIN_PLAYER_CORPSE one spell: Remove Insignia, bg usage, required special corpse flags...
176 &Spell::EffectSpiritHeal
, //117 SPELL_EFFECT_SPIRIT_HEAL one spell: Spirit Heal
177 &Spell::EffectSkill
, //118 SPELL_EFFECT_SKILL professions and more
178 &Spell::EffectApplyAreaAura
, //119 SPELL_EFFECT_APPLY_AREA_AURA_PET
179 &Spell::EffectUnused
, //120 SPELL_EFFECT_TELEPORT_GRAVEYARD one spell: Graveyard Teleport Test
180 &Spell::EffectWeaponDmg
, //121 SPELL_EFFECT_NORMALIZED_WEAPON_DMG
181 &Spell::EffectUnused
, //122 SPELL_EFFECT_122 unused
182 &Spell::EffectSendTaxi
, //123 SPELL_EFFECT_SEND_TAXI taxi/flight related (misc value is taxi path id)
183 &Spell::EffectPlayerPull
, //124 SPELL_EFFECT_PLAYER_PULL opposite of knockback effect (pulls player twoard caster)
184 &Spell::EffectModifyThreatPercent
, //125 SPELL_EFFECT_MODIFY_THREAT_PERCENT
185 &Spell::EffectStealBeneficialBuff
, //126 SPELL_EFFECT_STEAL_BENEFICIAL_BUFF spell steal effect?
186 &Spell::EffectProspecting
, //127 SPELL_EFFECT_PROSPECTING Prospecting spell
187 &Spell::EffectApplyAreaAura
, //128 SPELL_EFFECT_APPLY_AREA_AURA_FRIEND
188 &Spell::EffectApplyAreaAura
, //129 SPELL_EFFECT_APPLY_AREA_AURA_ENEMY
189 &Spell::EffectNULL
, //130 SPELL_EFFECT_REDIRECT_THREAT
190 &Spell::EffectUnused
, //131 SPELL_EFFECT_131 used in some test spells
191 &Spell::EffectNULL
, //132 SPELL_EFFECT_PLAY_MUSIC sound id in misc value
192 &Spell::EffectUnlearnSpecialization
, //133 SPELL_EFFECT_UNLEARN_SPECIALIZATION unlearn profession specialization
193 &Spell::EffectKillCredit
, //134 SPELL_EFFECT_KILL_CREDIT misc value is creature entry
194 &Spell::EffectNULL
, //135 SPELL_EFFECT_CALL_PET
195 &Spell::EffectHealPct
, //136 SPELL_EFFECT_HEAL_PCT
196 &Spell::EffectEnergisePct
, //137 SPELL_EFFECT_ENERGIZE_PCT
197 &Spell::EffectNULL
, //138 SPELL_EFFECT_138 Leap
198 &Spell::EffectUnused
, //139 SPELL_EFFECT_139 unused
199 &Spell::EffectForceCast
, //140 SPELL_EFFECT_FORCE_CAST
200 &Spell::EffectNULL
, //141 SPELL_EFFECT_141 damage and reduce speed?
201 &Spell::EffectTriggerSpellWithValue
, //142 SPELL_EFFECT_TRIGGER_SPELL_WITH_VALUE
202 &Spell::EffectApplyAreaAura
, //143 SPELL_EFFECT_APPLY_AREA_AURA_OWNER
203 &Spell::EffectNULL
, //144 SPELL_EFFECT_144 Spectral Blast
204 &Spell::EffectNULL
, //145 SPELL_EFFECT_145 Black Hole Effect
205 &Spell::EffectUnused
, //146 SPELL_EFFECT_146 unused
206 &Spell::EffectQuestFail
, //147 SPELL_EFFECT_QUEST_FAIL quest fail
207 &Spell::EffectUnused
, //148 SPELL_EFFECT_148 unused
208 &Spell::EffectNULL
, //149 SPELL_EFFECT_149 swoop
209 &Spell::EffectUnused
, //150 SPELL_EFFECT_150 unused
210 &Spell::EffectTriggerRitualOfSummoning
, //151 SPELL_EFFECT_TRIGGER_SPELL_2
211 &Spell::EffectNULL
, //152 SPELL_EFFECT_152 summon Refer-a-Friend
212 &Spell::EffectNULL
, //153 SPELL_EFFECT_CREATE_PET misc value is creature entry
215 void Spell::EffectNULL(uint32
/*i*/)
217 sLog
.outDebug("WORLD: Spell Effect DUMMY");
220 void Spell::EffectUnused(uint32
/*i*/)
222 // NOT USED BY ANY SPELL OR USELESS OR IMPLEMENTED IN DIFFERENT WAY IN MANGOS
225 void Spell::EffectResurrectNew(uint32 i
)
227 if(!unitTarget
|| unitTarget
->isAlive())
230 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
233 if(!unitTarget
->IsInWorld())
236 Player
* pTarget
= ((Player
*)unitTarget
);
238 if(pTarget
->isRessurectRequested()) // already have one active request
241 uint32 health
= damage
;
242 uint32 mana
= m_spellInfo
->EffectMiscValue
[i
];
243 pTarget
->setResurrectRequestData(m_caster
->GetGUID(), m_caster
->GetMapId(), m_caster
->GetPositionX(), m_caster
->GetPositionY(), m_caster
->GetPositionZ(), health
, mana
);
244 SendResurrectRequest(pTarget
);
247 void Spell::EffectInstaKill(uint32
/*i*/)
249 if( !unitTarget
|| !unitTarget
->isAlive() )
253 if(m_spellInfo
->Id
==18788 && unitTarget
->GetTypeId()==TYPEID_UNIT
)
255 uint32 entry
= unitTarget
->GetEntry();
259 case 416: spellID
=18789; break; //imp
260 case 417: spellID
=18792; break; //fellhunter
261 case 1860: spellID
=18790; break; //void
262 case 1863: spellID
=18791; break; //succubus
263 case 17252: spellID
=35701; break; //fellguard
265 sLog
.outError("EffectInstaKill: Unhandled creature entry (%u) case.",entry
);
269 m_caster
->CastSpell(m_caster
,spellID
,true);
272 if(m_caster
==unitTarget
) // prevent interrupt message
275 uint32 health
= unitTarget
->GetHealth();
276 m_caster
->DealDamage(unitTarget
, health
, NULL
, DIRECT_DAMAGE
, SPELL_SCHOOL_MASK_NORMAL
, NULL
, false);
279 void Spell::EffectEnvirinmentalDMG(uint32 i
)
284 // Note: this hack with damage replace required until GO casting not implemented
285 // environment damage spells already have around enemies targeting but this not help in case not existed GO casting support
286 // currently each enemy selected explicitly and self cast damage, we prevent apply self casted spell bonuses/etc
287 damage
= m_spellInfo
->EffectBasePoints
[i
]+m_spellInfo
->EffectBaseDice
[i
];
289 m_caster
->CalcAbsorbResist(m_caster
,GetSpellSchoolMask(m_spellInfo
), SPELL_DIRECT_DAMAGE
, damage
, &absorb
, &resist
);
291 m_caster
->SendSpellNonMeleeDamageLog(m_caster
, m_spellInfo
->Id
, damage
, GetSpellSchoolMask(m_spellInfo
), absorb
, resist
, false, 0, false);
292 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
293 ((Player
*)m_caster
)->EnvironmentalDamage(m_caster
->GetGUID(),DAMAGE_FIRE
,damage
);
296 void Spell::EffectSchoolDMG(uint32 effect_idx
)
298 if( unitTarget
&& unitTarget
->isAlive())
300 switch(m_spellInfo
->SpellFamilyName
)
302 case SPELLFAMILY_GENERIC
:
305 if(m_spellInfo
->SpellIconID
== 2269 )
307 damage
+= rand()%2 ? damage
: 0;
310 switch(m_spellInfo
->Id
) // better way to check unknown
312 // Meteor like spells (divided damage to targets)
313 case 24340: case 26558: case 28884: // Meteor
314 case 36837: case 38903: case 41276: // Meteor
315 case 26789: // Shard of the Fallen Star
316 case 31436: // Malevolent Cleave
317 case 35181: // Dive Bomb
318 case 40810: case 43267: case 43268: // Saber Lash
319 case 42384: // Brutal Swipe
320 case 45150: // Meteor Slash
323 for(std::list
<TargetInfo
>::iterator ihit
= m_UniqueTargetInfo
.begin();ihit
!= m_UniqueTargetInfo
.end();++ihit
)
324 if(ihit
->effectMask
& (1<<effect_idx
))
327 damage
/= count
; // divide to all targets
330 // percent from health with min
331 case 25599: // Thundercrash
333 damage
= unitTarget
->GetHealth() / 2;
342 case SPELLFAMILY_MAGE
:
345 if(m_spellInfo
->SpellFamilyFlags
& 0x20000000LL
)
347 m_caster
->CastSpell(m_caster
,36032,true);
351 case SPELLFAMILY_WARRIOR
:
354 if(m_spellInfo
->SpellFamilyFlags
& 0x40000000000LL
)
356 damage
= uint32(damage
* (m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
)) / 100);
359 else if(m_spellInfo
->SpellFamilyFlags
& 0x100000000LL
)
360 damage
+= int32(m_caster
->GetShieldBlockValue());
362 else if(m_spellInfo
->SpellFamilyFlags
& 0x10000000000LL
)
364 damage
= uint32(damage
* m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
) / 100);
365 m_caster
->ModifyAuraState(AURA_STATE_WARRIOR_VICTORY_RUSH
, false);
369 case SPELLFAMILY_WARLOCK
:
371 // Incinerate Rank 1 & 2
372 if((m_spellInfo
->SpellFamilyFlags
& 0x00004000000000LL
) && m_spellInfo
->SpellIconID
==2128)
374 // Incinerate does more dmg (dmg*0.25) if the target is Immolated.
375 if(unitTarget
->HasAuraState(AURA_STATE_IMMOLATE
))
376 damage
+= int32(damage
*0.25);
380 case SPELLFAMILY_DRUID
:
383 if((m_spellInfo
->SpellFamilyFlags
& 0x000800000) && m_spellInfo
->SpellVisual
==6587)
385 // converts each extra point of energy into ($f1+$AP/630) additional damage
386 float multiple
= m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
) / 630 + m_spellInfo
->DmgMultiplier
[effect_idx
];
387 damage
+= int32(m_caster
->GetPower(POWER_ENERGY
) * multiple
);
388 m_caster
->SetPower(POWER_ENERGY
,0);
391 else if(m_spellInfo
->SpellFamilyFlags
& 0x0000000000001000LL
)
393 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
) / 100);
396 else if(m_spellInfo
->SpellFamilyFlags
& 0x0010000000000000LL
)
398 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
)*0.08f
);
401 else if ( m_spellInfo
->SpellFamilyFlags
& 0x0004LL
)
403 Unit::AuraList
const& m_OverrideClassScript
= m_caster
->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS
);
404 for(Unit::AuraList::const_iterator i
= m_OverrideClassScript
.begin(); i
!= m_OverrideClassScript
.end(); ++i
)
406 // Starfire Bonus (caster)
407 switch((*i
)->GetModifier()->m_miscvalue
)
409 case 5481: // Nordrassil Regalia - bonus
411 Unit::AuraList
const& m_periodicDamageAuras
= unitTarget
->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE
);
412 for(Unit::AuraList::const_iterator itr
= m_periodicDamageAuras
.begin(); itr
!= m_periodicDamageAuras
.end(); ++itr
)
414 // Moonfire or Insect Swarm (target debuff from any casters)
415 if ( (*itr
)->GetSpellProto()->SpellFamilyFlags
& 0x00200002LL
)
417 int32 mod
= (*i
)->GetModifier()->m_amount
;
418 damage
+= damage
*mod
/100;
424 case 5148: //Improved Starfire - Ivory Idol of the Moongoddes Aura
426 damage
+= (*i
)->GetModifier()->m_amount
;
432 //Mangle Bonus for the initial damage of Lacerate and Rake
433 if((m_spellInfo
->SpellFamilyFlags
==0x0000000000001000LL
&& m_spellInfo
->SpellIconID
==494) ||
434 (m_spellInfo
->SpellFamilyFlags
==0x0000010000000000LL
&& m_spellInfo
->SpellIconID
==2246))
436 Unit::AuraList
const& mDummyAuras
= unitTarget
->GetAurasByType(SPELL_AURA_DUMMY
);
437 for(Unit::AuraList::const_iterator i
= mDummyAuras
.begin(); i
!= mDummyAuras
.end(); ++i
)
438 if((*i
)->GetSpellProto()->SpellFamilyFlags
& 0x0000044000000000LL
&& (*i
)->GetSpellProto()->SpellFamilyName
==SPELLFAMILY_DRUID
)
440 damage
= int32(damage
*(100.0f
+(*i
)->GetModifier()->m_amount
)/100.0f
);
446 case SPELLFAMILY_ROGUE
:
449 if(m_caster
->GetTypeId()==TYPEID_PLAYER
&& (m_spellInfo
->SpellFamilyFlags
& 0x800000000LL
))
451 // consume from stack dozes not more that have combo-points
452 if(uint32 combo
= ((Player
*)m_caster
)->GetComboPoints())
454 // count consumed deadly poison doses at target
457 // remove consumed poison doses
458 Unit::AuraList
const& auras
= unitTarget
->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE
);
459 for(Unit::AuraList::const_iterator itr
= auras
.begin(); itr
!=auras
.end() && combo
;)
461 // Deadly poison (only attacker applied)
462 if( (*itr
)->GetSpellProto()->SpellFamilyName
==SPELLFAMILY_ROGUE
&& ((*itr
)->GetSpellProto()->SpellFamilyFlags
& 0x10000) &&
463 (*itr
)->GetSpellProto()->SpellVisual
==5100 && (*itr
)->GetCasterGUID()==m_caster
->GetGUID() )
468 unitTarget
->RemoveSingleAuraFromStack((*itr
)->GetId(), (*itr
)->GetEffIndex());
477 damage
+= int32(((Player
*)m_caster
)->GetTotalAttackPowerValue(BASE_ATTACK
) * 0.03f
* doses
);
479 // Eviscerate and Envenom Bonus Damage (item set effect)
480 if(m_caster
->GetDummyAura(37169))
481 damage
+= ((Player
*)m_caster
)->GetComboPoints()*40;
485 else if((m_spellInfo
->SpellFamilyFlags
& 0x00020000LL
) && m_caster
->GetTypeId()==TYPEID_PLAYER
)
487 if(uint32 combo
= ((Player
*)m_caster
)->GetComboPoints())
489 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
) * combo
* 0.03f
);
491 // Eviscerate and Envenom Bonus Damage (item set effect)
492 if(m_caster
->GetDummyAura(37169))
498 case SPELLFAMILY_HUNTER
:
501 if((m_spellInfo
->SpellFamilyFlags
& 0x000000002) && m_spellInfo
->SpellVisual
==342)
503 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
)*0.2);
506 else if((m_spellInfo
->SpellFamilyFlags
& 0x00000800) && m_spellInfo
->maxLevel
> 0)
508 damage
+= int32(m_caster
->GetTotalAttackPowerValue(RANGED_ATTACK
)*0.15);
511 else if(m_spellInfo
->SpellFamilyFlags
& 0x100000000LL
)
513 int32 base
= irand((int32
)m_caster
->GetWeaponDamageRange(RANGED_ATTACK
, MINDAMAGE
),(int32
)m_caster
->GetWeaponDamageRange(RANGED_ATTACK
, MAXDAMAGE
));
514 damage
+= int32(float(base
)/m_caster
->GetAttackTime(RANGED_ATTACK
)*2800 + m_caster
->GetTotalAttackPowerValue(RANGED_ATTACK
)*0.2f
);
516 //Explosive Trap Effect
517 else if(m_spellInfo
->SpellFamilyFlags
& 0x00000004)
519 damage
+= int32(m_caster
->GetTotalAttackPowerValue(RANGED_ATTACK
)*0.1);
523 case SPELLFAMILY_PALADIN
:
525 //Judgement of Vengeance
526 if((m_spellInfo
->SpellFamilyFlags
& 0x800000000LL
) && m_spellInfo
->SpellIconID
==2292)
529 Unit::AuraList
const& auras
= unitTarget
->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE
);
530 for(Unit::AuraList::const_iterator itr
= auras
.begin(); itr
!=auras
.end(); ++itr
)
531 if((*itr
)->GetId() == 31803 && (*itr
)->GetCasterGUID()==m_caster
->GetGUID())
534 //No damage if the target isn't affected by this
546 if(m_originalCaster
) // m_caster only passive source of cast
547 finalDamage
= m_originalCaster
->SpellNonMeleeDamageLog(unitTarget
, m_spellInfo
->Id
, damage
, m_IsTriggeredSpell
, true);
549 finalDamage
= m_caster
->SpellNonMeleeDamageLog(unitTarget
, m_spellInfo
->Id
, damage
, m_IsTriggeredSpell
, true);
552 switch(m_spellInfo
->SpellFamilyName
)
554 case SPELLFAMILY_WARRIOR
:
557 if(m_spellInfo
->SpellFamilyFlags
& 0x40000000000LL
)
560 switch(m_spellInfo
->Id
)
562 case 23881: BTAura
= 23885; break;
563 case 23892: BTAura
= 23886; break;
564 case 23893: BTAura
= 23887; break;
565 case 23894: BTAura
= 23888; break;
566 case 25251: BTAura
= 25252; break;
567 case 30335: BTAura
= 30339; break;
569 sLog
.outError("Spell::EffectSchoolDMG: Spell %u not handled in BTAura",m_spellInfo
->Id
);
574 m_caster
->CastSpell(m_caster
,BTAura
,true);
578 case SPELLFAMILY_PRIEST
:
580 // Shadow Word: Death
581 if(finalDamage
> 0 && (m_spellInfo
->SpellFamilyFlags
& 0x0000000200000000LL
) && unitTarget
->isAlive())
582 // deals damage equal to damage done to caster if victim is not killed
583 m_caster
->SpellNonMeleeDamageLog( m_caster
, m_spellInfo
->Id
, finalDamage
, m_IsTriggeredSpell
, false);
587 case SPELLFAMILY_PALADIN
:
589 // Judgement of Blood
590 if(finalDamage
> 0 && (m_spellInfo
->SpellFamilyFlags
& 0x0000000800000000LL
) && m_spellInfo
->SpellIconID
==153)
592 int32 damagePoint
= finalDamage
* 33 / 100;
593 m_caster
->CastCustomSpell(m_caster
, 32220, &damagePoint
, NULL
, NULL
, true);
602 void Spell::EffectDummy(uint32 i
)
604 if(!unitTarget
&& !gameObjTarget
&& !itemTarget
)
607 // selection by spell family
608 switch(m_spellInfo
->SpellFamilyName
)
610 case SPELLFAMILY_GENERIC
:
611 // Gnomish Poultryizer trinket
612 switch(m_spellInfo
->Id
)
614 case 8063: // Deviate Fish
616 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
622 case 1: spell_id
= 8064; break; // Sleepy
623 case 2: spell_id
= 8065; break; // Invigorate
624 case 3: spell_id
= 8066; break; // Shrink
625 case 4: spell_id
= 8067; break; // Party Time!
626 case 5: spell_id
= 8068; break; // Healthy Spirit
628 m_caster
->CastSpell(m_caster
,spell_id
,true,NULL
);
631 case 8213: // Savory Deviate Delight
633 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
640 case 1: spell_id
= (m_caster
->getGender() == GENDER_MALE
? 8219 : 8220); break;
642 case 2: spell_id
= (m_caster
->getGender() == GENDER_MALE
? 8221 : 8222); break;
644 m_caster
->CastSpell(m_caster
,spell_id
,true,NULL
);
647 case 8593: // Symbol of life (restore creature to life)
648 case 31225: // Shimmering Vessel (restore creature to life)
650 if(!unitTarget
|| unitTarget
->GetTypeId()!=TYPEID_UNIT
)
652 ((Creature
*)unitTarget
)->setDeathState(JUST_ALIVED
);
655 case 12162: // Deep wounds
656 case 12850: // (now good common check for this spells)
663 // DW should benefit of attack power, damage percent mods etc.
664 // TODO: check if using offhand damage is correct and if it should be divided by 2
665 if (m_caster
->haveOffhandWeapon() && m_caster
->getAttackTimer(BASE_ATTACK
) > m_caster
->getAttackTimer(OFF_ATTACK
))
666 damage
= (m_caster
->GetFloatValue(UNIT_FIELD_MINOFFHANDDAMAGE
) + m_caster
->GetFloatValue(UNIT_FIELD_MAXOFFHANDDAMAGE
))/2;
668 damage
= (m_caster
->GetFloatValue(UNIT_FIELD_MINDAMAGE
) + m_caster
->GetFloatValue(UNIT_FIELD_MAXDAMAGE
))/2;
670 switch (m_spellInfo
->Id
)
672 case 12850: damage
*= 0.2f
; break;
673 case 12162: damage
*= 0.4f
; break;
674 case 12868: damage
*= 0.6f
; break;
676 sLog
.outError("Spell::EffectDummy: Spell %u not handled in DW",m_spellInfo
->Id
);
680 int32 deepWoundsDotBasePoints0
= int32(damage
/ 4);
681 m_caster
->CastCustomSpell(unitTarget
, 12721, &deepWoundsDotBasePoints0
, NULL
, NULL
, true, NULL
);
684 case 12975: //Last Stand
686 int32 healthModSpellBasePoints0
= int32(m_caster
->GetMaxHealth()*0.3);
687 m_caster
->CastCustomSpell(m_caster
, 12976, &healthModSpellBasePoints0
, NULL
, NULL
, true, NULL
);
690 case 13120: // net-o-matic
697 uint32 roll
= urand(0, 99);
699 if(roll
< 2) // 2% for 30 sec self root (off-like chance unknown)
701 else if(roll
< 4) // 2% for 20 sec root, charge to target (off-like chance unknown)
706 m_caster
->CastSpell(unitTarget
,spell_id
,true,NULL
);
709 case 13567: // Dummy Trigger
711 // can be used for different aura triggreing, so select by aura
712 if(!m_triggeredByAuraSpell
|| !unitTarget
)
715 switch(m_triggeredByAuraSpell
->Id
)
717 case 26467: // Persistent Shield
718 m_caster
->CastCustomSpell(unitTarget
, 26470, &damage
, NULL
, NULL
, true);
721 sLog
.outError("EffectDummy: Non-handled case for spell 13567 for triggered aura %u",m_triggeredByAuraSpell
->Id
);
726 case 14185: // Preparation Rogue
728 if(m_caster
->GetTypeId()!=TYPEID_PLAYER
)
731 //immediately finishes the cooldown on certain Rogue abilities
732 const PlayerSpellMap
& sp_list
= ((Player
*)m_caster
)->GetSpellMap();
733 for (PlayerSpellMap::const_iterator itr
= sp_list
.begin(); itr
!= sp_list
.end(); ++itr
)
735 uint32 classspell
= itr
->first
;
736 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(classspell
);
738 if (spellInfo
->SpellFamilyName
== SPELLFAMILY_ROGUE
&& (spellInfo
->SpellFamilyFlags
& 0x26000000860LL
))
740 ((Player
*)m_caster
)->RemoveSpellCooldown(classspell
);
742 WorldPacket
data(SMSG_CLEAR_COOLDOWN
, (4+8));
743 data
<< uint32(classspell
);
744 data
<< uint64(m_caster
->GetGUID());
745 ((Player
*)m_caster
)->GetSession()->SendPacket(&data
);
750 case 15998: // Capture Worg Pup
751 case 29435: // Capture Female Kaliri Hatchling
753 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_UNIT
)
756 Creature
* creatureTarget
= (Creature
*)unitTarget
;
757 creatureTarget
->setDeathState(JUST_DIED
);
758 creatureTarget
->RemoveCorpse();
759 creatureTarget
->SetHealth(0); // just for nice GM-mode view
762 case 16589: // Noggenfogger Elixir
764 if(m_caster
->GetTypeId()!=TYPEID_PLAYER
)
770 case 1: spell_id
= 16595; break;
771 case 2: spell_id
= 16593; break;
772 default:spell_id
= 16591; break;
775 m_caster
->CastSpell(m_caster
,spell_id
,true,NULL
);
778 case 17251: // Spirit Healer Res
780 if(!unitTarget
|| !m_originalCaster
)
783 if(m_originalCaster
->GetTypeId() == TYPEID_PLAYER
)
785 WorldPacket
data(SMSG_SPIRIT_HEALER_CONFIRM
, 8);
786 data
<< unitTarget
->GetGUID();
787 ((Player
*)m_originalCaster
)->GetSession()->SendPacket( &data
);
791 case 17271: // Test Fetid Skull
793 if(!itemTarget
&& m_caster
->GetTypeId()!=TYPEID_PLAYER
)
796 uint32 spell_id
= roll_chance_i(50) ? 17269 : 17270;
798 m_caster
->CastSpell(m_caster
,spell_id
,true,NULL
);
801 case 20577: // Cannibalize
803 m_caster
->CastSpell(m_caster
,20578,false,NULL
);
805 case 23019: // Crystal Prison Dummy DND
807 if(!unitTarget
|| !unitTarget
->isAlive() || unitTarget
->GetTypeId() != TYPEID_UNIT
|| ((Creature
*)unitTarget
)->isPet())
810 Creature
* creatureTarget
= (Creature
*)unitTarget
;
811 if(creatureTarget
->isPet())
814 creatureTarget
->setDeathState(JUST_DIED
);
815 creatureTarget
->RemoveCorpse();
816 creatureTarget
->SetHealth(0); // just for nice GM-mode view
818 GameObject
* pGameObj
= new GameObject
;
820 Map
*map
= creatureTarget
->GetMap();
822 if(!pGameObj
->Create(objmgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), 179644, map
,
823 creatureTarget
->GetPositionX(), creatureTarget
->GetPositionY(), creatureTarget
->GetPositionZ(),
824 creatureTarget
->GetOrientation(), 0, 0, 0, 0, 100, 1) )
830 pGameObj
->SetRespawnTime(creatureTarget
->GetRespawnTime()-time(NULL
));
831 pGameObj
->SetOwnerGUID(m_caster
->GetGUID() );
832 pGameObj
->SetUInt32Value(GAMEOBJECT_LEVEL
, m_caster
->getLevel() );
833 pGameObj
->SetSpellId(m_spellInfo
->Id
);
835 DEBUG_LOG("AddObject at SpellEfects.cpp EffectDummy\n");
838 WorldPacket
data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE
, 8);
839 data
<< uint64(pGameObj
->GetGUID());
840 m_caster
->SendMessageToSet(&data
,true);
844 case 23074: // Arc. Dragonling
845 if (!m_CastItem
) return;
846 m_caster
->CastSpell(m_caster
,19804,true,m_CastItem
);
848 case 23075: // Mithril Mechanical Dragonling
849 if (!m_CastItem
) return;
850 m_caster
->CastSpell(m_caster
,12749,true,m_CastItem
);
852 case 23076: // Mechanical Dragonling
853 if (!m_CastItem
) return;
854 m_caster
->CastSpell(m_caster
,4073,true,m_CastItem
);
856 case 23133: // Gnomish Battle Chicken
857 if (!m_CastItem
) return;
858 m_caster
->CastSpell(m_caster
,13166,true,m_CastItem
);
860 case 23448: // Ultrasafe Transporter: Gadgetzan - backfires
862 int32 r
= irand(0, 119);
863 if ( r
< 20 ) // 1/6 polymorph
864 m_caster
->CastSpell(m_caster
,23444,true);
865 else if ( r
< 100 ) // 4/6 evil twin
866 m_caster
->CastSpell(m_caster
,23445,true);
867 else // 1/6 miss the target
868 m_caster
->CastSpell(m_caster
,36902,true);
871 case 23453: // Ultrasafe Transporter: Gadgetzan
872 if ( roll_chance_i(50) ) // success
873 m_caster
->CastSpell(m_caster
,23441,true);
875 m_caster
->CastSpell(m_caster
,23446,true);
877 case 23645: // Hourglass Sand
878 m_caster
->RemoveAurasDueToSpell(23170);
880 case 23725: // Gift of Life (warrior bwl trinket)
881 m_caster
->CastSpell(m_caster
,23782,true);
882 m_caster
->CastSpell(m_caster
,23783,true);
884 case 25860: // Reindeer Transformation
886 if (!m_caster
->HasAuraType(SPELL_AURA_MOUNTED
))
889 float flyspeed
= m_caster
->GetSpeedRate(MOVE_FLY
);
890 float speed
= m_caster
->GetSpeedRate(MOVE_RUN
);
892 m_caster
->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED
);
894 //5 different spells used depending on mounted speed and if mount can fly or not
895 if (flyspeed
>= 4.1f
)
896 m_caster
->CastSpell(m_caster
, 44827, true); //310% flying Reindeer
897 else if (flyspeed
>= 3.8f
)
898 m_caster
->CastSpell(m_caster
, 44825, true); //280% flying Reindeer
899 else if (flyspeed
>= 1.6f
)
900 m_caster
->CastSpell(m_caster
, 44824, true); //60% flying Reindeer
901 else if (speed
>= 2.0f
)
902 m_caster
->CastSpell(m_caster
, 25859, true); //100% ground Reindeer
904 m_caster
->CastSpell(m_caster
, 25858, true); //60% ground Reindeer
908 //case 26074: // Holiday Cheer
909 // return; -- implemented at client side
910 case 28006: // Arcane Cloaking
912 if( unitTarget
->GetTypeId() == TYPEID_PLAYER
)
913 m_caster
->CastSpell(unitTarget
,29294,true);
916 case 28730: // Arcane Torrent (Mana)
919 Unit::AuraList
const& m_dummyAuras
= m_caster
->GetAurasByType(SPELL_AURA_DUMMY
);
920 for(Unit::AuraList::const_iterator i
= m_dummyAuras
.begin(); i
!= m_dummyAuras
.end(); ++i
)
921 if ((*i
)->GetId() == 28734)
925 m_caster
->RemoveAurasDueToSpell(28734);
926 int32 bp
= damage
* count
;
927 m_caster
->CastCustomSpell(m_caster
, 28733, &bp
, NULL
, NULL
, true);
931 case 29200: // Purify Helboar Meat
933 if( m_caster
->GetTypeId() != TYPEID_PLAYER
)
936 uint32 spell_id
= roll_chance_i(50) ? 29277 : 29278;
938 m_caster
->CastSpell(m_caster
,spell_id
,true,NULL
);
941 case 29858: // Soulshatter
942 if (unitTarget
&& unitTarget
->GetTypeId() == TYPEID_UNIT
&& unitTarget
->IsHostileTo(m_caster
))
943 m_caster
->CastSpell(unitTarget
,32835,true);
945 case 30458: // Nigh Invulnerability
946 if (!m_CastItem
) return;
947 if(roll_chance_i(86)) // success
948 m_caster
->CastSpell(m_caster
, 30456, true, m_CastItem
);
949 else // backfire in 14% casts
950 m_caster
->CastSpell(m_caster
, 30457, true, m_CastItem
);
952 case 30507: // Poultryizer
953 if (!m_CastItem
) return;
954 if(roll_chance_i(80)) // success
955 m_caster
->CastSpell(unitTarget
, 30501, true, m_CastItem
);
957 m_caster
->CastSpell(unitTarget
, 30504, true, m_CastItem
);
959 case 33060: // Make a Wish
961 if(m_caster
->GetTypeId()!=TYPEID_PLAYER
)
968 case 1: spell_id
= 33053; break;
969 case 2: spell_id
= 33057; break;
970 case 3: spell_id
= 33059; break;
971 case 4: spell_id
= 33062; break;
972 case 5: spell_id
= 33064; break;
975 m_caster
->CastSpell(m_caster
,spell_id
,true,NULL
);
981 switch(m_caster
->GetAreaId())
983 case 3900: spell_id
= 35743; break;
984 case 3742: spell_id
= 35744; break;
988 m_caster
->CastSpell(m_caster
,spell_id
,true);
991 case 37674: // Chaos Blast
993 m_caster
->CastSpell(unitTarget
,37675,true);
995 case 44875: // Complete Raptor Capture
997 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_UNIT
)
1000 Creature
* creatureTarget
= (Creature
*)unitTarget
;
1002 creatureTarget
->setDeathState(JUST_DIED
);
1003 creatureTarget
->RemoveCorpse();
1004 creatureTarget
->SetHealth(0); // just for nice GM-mode view
1006 //cast spell Raptor Capture Credit
1007 m_caster
->CastSpell(m_caster
,42337,true,NULL
);
1010 case 37573: //Temporal Phase Modulator
1015 TemporarySummon
* tempSummon
= dynamic_cast<TemporarySummon
*>(unitTarget
);
1019 uint32 health
= tempSummon
->GetHealth();
1020 const uint32 entry_list
[6] = {21821, 21820, 21817};
1022 float x
= tempSummon
->GetPositionX();
1023 float y
= tempSummon
->GetPositionY();
1024 float z
= tempSummon
->GetPositionZ();
1025 float o
= tempSummon
->GetOrientation();
1027 tempSummon
->UnSummon();
1029 Creature
* pCreature
= m_caster
->SummonCreature(entry_list
[urand(0, 2)], x
, y
, z
, o
,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN
,180000);
1033 pCreature
->SetHealth(health
);
1036 pCreature
->AI()->AttackStart(m_caster
);
1040 case 34665: //Administer Antidote
1042 if(!unitTarget
|| m_caster
->GetTypeId() != TYPEID_PLAYER
)
1048 TemporarySummon
* tempSummon
= dynamic_cast<TemporarySummon
*>(unitTarget
);
1052 uint32 health
= tempSummon
->GetHealth();
1054 float x
= tempSummon
->GetPositionX();
1055 float y
= tempSummon
->GetPositionY();
1056 float z
= tempSummon
->GetPositionZ();
1057 float o
= tempSummon
->GetOrientation();
1058 tempSummon
->UnSummon();
1060 Creature
* pCreature
= m_caster
->SummonCreature(16992, x
, y
, z
, o
,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN
,180000);
1064 pCreature
->SetHealth(health
);
1065 ((Player
*)m_caster
)->KilledMonster(16992,pCreature
->GetGUID());
1067 if (pCreature
->AI())
1068 pCreature
->AI()->AttackStart(m_caster
);
1072 case 44997: // Converting Sentry
1074 //Converted Sentry Credit
1075 m_caster
->CastSpell(m_caster
, 45009, true);
1078 case 45030: // Impale Emissary
1080 // Emissary of Hate Credit
1081 m_caster
->CastSpell(m_caster
, 45088, true);
1084 case 50243: // Teach Language
1086 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
1089 // spell has a 1/3 chance to trigger one of the below
1090 if(roll_chance_i(66))
1092 if(((Player
*)m_caster
)->GetTeam() == ALLIANCE
)
1094 // 1000001 - gnomish binary
1095 m_caster
->CastSpell(m_caster
, 50242, true);
1099 // 01001000 - goblin binary
1100 m_caster
->CastSpell(m_caster
, 50246, true);
1105 case 51582: //Rocket Boots Engaged (Rocket Boots Xtreme and Rocket Boots Xtreme Lite)
1107 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
1110 if(BattleGround
* bg
= ((Player
*)m_caster
)->GetBattleGround())
1111 bg
->EventPlayerDroppedFlag((Player
*)m_caster
);
1113 m_caster
->CastSpell(m_caster
, 30452, true, NULL
);
1118 //All IconID Check in there
1119 switch(m_spellInfo
->SpellIconID
)
1121 // Berserking (troll racial traits)
1124 uint32 healthPerc
= uint32((float(m_caster
->GetHealth())/m_caster
->GetMaxHealth())*100);
1125 int32 melee_mod
= 10;
1126 if (healthPerc
<= 40)
1128 if (healthPerc
< 100 && healthPerc
> 40)
1129 melee_mod
= 10+(100-healthPerc
)/3;
1131 int32 hasteModBasePoints0
= melee_mod
; // (EffectBasePoints[0]+1)-1+(5-melee_mod) = (melee_mod-1+1)-1+5-melee_mod = 5-1
1132 int32 hasteModBasePoints1
= (5-melee_mod
);
1133 int32 hasteModBasePoints2
= 5;
1135 // FIXME: custom spell required this aura state by some unknown reason, we not need remove it anyway
1136 m_caster
->ModifyAuraState(AURA_STATE_BERSERKING
,true);
1137 m_caster
->CastCustomSpell(m_caster
,26635,&hasteModBasePoints0
,&hasteModBasePoints1
,&hasteModBasePoints2
,true,NULL
);
1142 case SPELLFAMILY_MAGE
:
1143 switch(m_spellInfo
->Id
)
1145 case 11958: // Cold Snap
1147 if(m_caster
->GetTypeId()!=TYPEID_PLAYER
)
1150 // immediately finishes the cooldown on Frost spells
1151 const PlayerSpellMap
& sp_list
= ((Player
*)m_caster
)->GetSpellMap();
1152 for (PlayerSpellMap::const_iterator itr
= sp_list
.begin(); itr
!= sp_list
.end(); ++itr
)
1154 if (itr
->second
->state
== PLAYERSPELL_REMOVED
)
1157 uint32 classspell
= itr
->first
;
1158 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(classspell
);
1160 if( spellInfo
->SpellFamilyName
== SPELLFAMILY_MAGE
&&
1161 (GetSpellSchoolMask(spellInfo
) & SPELL_SCHOOL_MASK_FROST
) &&
1162 spellInfo
->Id
!= 11958 && GetSpellRecoveryTime(spellInfo
) > 0 )
1164 ((Player
*)m_caster
)->RemoveSpellCooldown(classspell
);
1166 WorldPacket
data(SMSG_CLEAR_COOLDOWN
, (4+8));
1167 data
<< uint32(classspell
);
1168 data
<< uint64(m_caster
->GetGUID());
1169 ((Player
*)m_caster
)->GetSession()->SendPacket(&data
);
1176 if ( unitTarget
&& unitTarget
->GetTypeId() == TYPEID_UNIT
)
1178 //Polymorph Cast Visual Rank 1
1179 const uint32 spell_list
[6] = {32813, 32816, 32817, 32818, 32819, 32820};
1180 unitTarget
->CastSpell( unitTarget
, spell_list
[urand(0, 5)], true);
1186 case SPELLFAMILY_WARRIOR
:
1188 if(m_spellInfo
->SpellFamilyFlags
& 0x1 && m_spellInfo
->SpellVisual
== 867)
1190 int32 chargeBasePoints0
= damage
;
1191 m_caster
->CastCustomSpell(m_caster
,34846,&chargeBasePoints0
,NULL
,NULL
,true);
1195 if(m_spellInfo
->SpellFamilyFlags
& 0x20000000)
1200 int32 basePoints0
= damage
+int32(m_caster
->GetPower(POWER_RAGE
) * m_spellInfo
->DmgMultiplier
[i
]);
1201 m_caster
->CastCustomSpell(unitTarget
, 20647, &basePoints0
, NULL
, NULL
, true, 0);
1202 m_caster
->SetPower(POWER_RAGE
,0);
1205 if(m_spellInfo
->Id
==21977) //Warrior's Wrath
1210 m_caster
->CastSpell(unitTarget
,21887,true); // spell mod
1214 case SPELLFAMILY_WARLOCK
:
1215 //Life Tap (only it have this with dummy effect)
1216 if (m_spellInfo
->SpellFamilyFlags
== 0x40000)
1218 float cost
= m_currentBasePoints
[0]+1;
1220 if(Player
* modOwner
= m_caster
->GetSpellModOwner())
1221 modOwner
->ApplySpellMod(m_spellInfo
->Id
, SPELLMOD_COST
, cost
,this);
1223 int32 dmg
= m_caster
->SpellDamageBonus(m_caster
, m_spellInfo
,uint32(cost
> 0 ? cost
: 0), SPELL_DIRECT_DAMAGE
);
1225 if(int32(m_caster
->GetHealth()) > dmg
)
1227 // Shouldn't Appear in Combat Log
1228 m_caster
->ModifyHealth(-dmg
);
1232 Unit::AuraList
const& auraDummy
= m_caster
->GetAurasByType(SPELL_AURA_DUMMY
);
1233 for(Unit::AuraList::const_iterator itr
= auraDummy
.begin(); itr
!= auraDummy
.end(); ++itr
)
1235 // only Imp. Life Tap have this in combination with dummy aura
1236 if((*itr
)->GetSpellProto()->SpellFamilyName
==SPELLFAMILY_WARLOCK
&& (*itr
)->GetSpellProto()->SpellIconID
== 208)
1237 mana
= ((*itr
)->GetModifier()->m_amount
+ 100)* mana
/ 100;
1240 m_caster
->CastCustomSpell(m_caster
,31818,&mana
,NULL
,NULL
,true,NULL
);
1243 int32 manaFeedVal
= m_caster
->CalculateSpellDamage(m_spellInfo
,1, m_spellInfo
->EffectBasePoints
[1],m_caster
);
1244 manaFeedVal
= manaFeedVal
* mana
/ 100;
1246 m_caster
->CastCustomSpell(m_caster
,32553,&manaFeedVal
,NULL
,NULL
,true,NULL
);
1249 SendCastResult(SPELL_FAILED_FIZZLE
);
1253 case SPELLFAMILY_PRIEST
:
1254 switch(m_spellInfo
->Id
)
1256 case 28598: // Touch of Weakness triggered spell
1258 if(!unitTarget
|| !m_triggeredByAuraSpell
)
1262 switch(m_triggeredByAuraSpell
->Id
)
1264 case 2652: spellid
= 2943; break; // Rank 1
1265 case 19261: spellid
= 19249; break; // Rank 2
1266 case 19262: spellid
= 19251; break; // Rank 3
1267 case 19264: spellid
= 19252; break; // Rank 4
1268 case 19265: spellid
= 19253; break; // Rank 5
1269 case 19266: spellid
= 19254; break; // Rank 6
1270 case 25461: spellid
= 25460; break; // Rank 7
1272 sLog
.outError("Spell::EffectDummy: Spell 28598 triggered by unhandeled spell %u",m_triggeredByAuraSpell
->Id
);
1275 m_caster
->CastSpell(unitTarget
, spellid
, true, NULL
);
1280 case SPELLFAMILY_DRUID
:
1281 switch(m_spellInfo
->Id
)
1283 case 5420: // Tree of Life passive
1285 // Tree of Life area effect
1286 int32 health_mod
= int32(m_caster
->GetStat(STAT_SPIRIT
)/4);
1287 m_caster
->CastCustomSpell(m_caster
,34123,&health_mod
,NULL
,NULL
,true,NULL
);
1292 case SPELLFAMILY_ROGUE
:
1293 switch(m_spellInfo
->Id
)
1295 case 31231: // Cheat Death
1297 m_caster
->CastSpell(m_caster
,45182,true);
1302 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
1305 Player
*pCaster
= ((Player
*)m_caster
);
1307 Item
*item
= pCaster
->GetWeaponForAttack(OFF_ATTACK
);
1311 // all poison enchantments is temporary
1312 uint32 enchant_id
= item
->GetEnchantmentId(TEMP_ENCHANTMENT_SLOT
);
1316 SpellItemEnchantmentEntry
const *pEnchant
= sSpellItemEnchantmentStore
.LookupEntry(enchant_id
);
1320 for (int s
=0;s
<3;s
++)
1322 if(pEnchant
->type
[s
]!=ITEM_ENCHANTMENT_TYPE_COMBAT_SPELL
)
1325 SpellEntry
const* combatEntry
= sSpellStore
.LookupEntry(pEnchant
->spellid
[s
]);
1326 if(!combatEntry
|| combatEntry
->Dispel
!= DISPEL_POISON
)
1329 m_caster
->CastSpell(unitTarget
, combatEntry
, true, item
);
1332 m_caster
->CastSpell(unitTarget
, 5940, true);
1337 case SPELLFAMILY_HUNTER
:
1339 if(m_spellInfo
->SpellFamilyFlags
& 0x100000000LL
)
1341 if( !unitTarget
|| !unitTarget
->isAlive())
1346 // check dazed affect
1347 Unit::AuraList
const& decSpeedList
= unitTarget
->GetAurasByType(SPELL_AURA_MOD_DECREASE_SPEED
);
1348 for(Unit::AuraList::const_iterator iter
= decSpeedList
.begin(); iter
!= decSpeedList
.end(); ++iter
)
1350 if((*iter
)->GetSpellProto()->SpellIconID
==15 && (*iter
)->GetSpellProto()->Dispel
==0)
1358 m_caster
->SpellNonMeleeDamageLog(unitTarget
, m_spellInfo
->Id
, damage
, m_IsTriggeredSpell
, true);
1362 if(m_spellInfo
->SpellFamilyFlags
& 0x00080000000000LL
)
1364 if(m_caster
->getClass()!=CLASS_HUNTER
)
1367 // clear hunter crit aura state
1368 m_caster
->ModifyAuraState(AURA_STATE_HUNTER_CRIT_STRIKE
,false);
1370 // additional damage from pet to pet target
1371 Pet
* pet
= m_caster
->GetPet();
1372 if(!pet
|| !pet
->getVictim())
1375 uint32 spell_id
= 0;
1376 switch (m_spellInfo
->Id
)
1378 case 34026: spell_id
= 34027; break; // rank 1
1380 sLog
.outError("Spell::EffectDummy: Spell %u not handled in KC",m_spellInfo
->Id
);
1384 pet
->CastSpell(pet
->getVictim(), spell_id
, true);
1388 switch(m_spellInfo
->Id
)
1390 case 23989: //Readiness talent
1392 if(m_caster
->GetTypeId()!=TYPEID_PLAYER
)
1395 //immediately finishes the cooldown for hunter abilities
1396 const PlayerSpellMap
& sp_list
= ((Player
*)m_caster
)->GetSpellMap();
1397 for (PlayerSpellMap::const_iterator itr
= sp_list
.begin(); itr
!= sp_list
.end(); ++itr
)
1399 uint32 classspell
= itr
->first
;
1400 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(classspell
);
1402 if (spellInfo
->SpellFamilyName
== SPELLFAMILY_HUNTER
&& spellInfo
->Id
!= 23989 && GetSpellRecoveryTime(spellInfo
) > 0 )
1404 ((Player
*)m_caster
)->RemoveSpellCooldown(classspell
);
1406 WorldPacket
data(SMSG_CLEAR_COOLDOWN
, (4+8));
1407 data
<< uint32(classspell
);
1408 data
<< uint64(m_caster
->GetGUID());
1409 ((Player
*)m_caster
)->GetSession()->SendPacket(&data
);
1414 case 37506: // Scatter Shot
1416 if (m_caster
->GetTypeId()!=TYPEID_PLAYER
)
1419 // break Auto Shot and autohit
1420 m_caster
->InterruptSpell(CURRENT_AUTOREPEAT_SPELL
);
1421 m_caster
->AttackStop();
1422 ((Player
*)m_caster
)->SendAttackSwingCancelAttack();
1427 case SPELLFAMILY_PALADIN
:
1428 switch(m_spellInfo
->SpellIconID
)
1430 case 156: // Holy Shock
1438 switch(m_spellInfo
->Id
)
1440 case 20473: hurt
= 25912; heal
= 25914; break;
1441 case 20929: hurt
= 25911; heal
= 25913; break;
1442 case 20930: hurt
= 25902; heal
= 25903; break;
1443 case 27174: hurt
= 27176; heal
= 27175; break;
1444 case 33072: hurt
= 33073; heal
= 33074; break;
1446 sLog
.outError("Spell::EffectDummy: Spell %u not handled in HS",m_spellInfo
->Id
);
1450 if(m_caster
->IsFriendlyTo(unitTarget
))
1451 m_caster
->CastSpell(unitTarget
, heal
, true, 0);
1453 m_caster
->CastSpell(unitTarget
, hurt
, true, 0);
1457 case 561: // Judgement of command
1462 uint32 spell_id
= m_currentBasePoints
[i
]+1;
1463 SpellEntry
const* spell_proto
= sSpellStore
.LookupEntry(spell_id
);
1467 if( !unitTarget
->hasUnitState(UNIT_STAT_STUNNED
) && m_caster
->GetTypeId()==TYPEID_PLAYER
)
1469 // decreased damage (/2) for non-stunned target.
1470 SpellModifier
*mod
= new SpellModifier
;
1471 mod
->op
= SPELLMOD_DAMAGE
;
1473 mod
->type
= SPELLMOD_PCT
;
1474 mod
->spellId
= m_spellInfo
->Id
;
1476 mod
->lastAffected
= NULL
;
1477 mod
->mask
= 0x0000020000000000LL
;
1480 ((Player
*)m_caster
)->AddSpellMod(mod
, true);
1481 m_caster
->CastSpell(unitTarget
,spell_proto
,true,NULL
);
1483 ((Player
*)m_caster
)->AddSpellMod(mod
, false);
1486 m_caster
->CastSpell(unitTarget
,spell_proto
,true,NULL
);
1492 switch(m_spellInfo
->Id
)
1494 case 31789: // Righteous Defense (step 1)
1496 // 31989 -> dummy effect (step 1) + dummy effect (step 2) -> 31709 (taunt like spell for each target)
1498 // non-standard cast requirement check
1499 if (!unitTarget
|| unitTarget
->getAttackers().empty())
1501 // clear cooldown at fail
1502 if(m_caster
->GetTypeId()==TYPEID_PLAYER
)
1504 ((Player
*)m_caster
)->RemoveSpellCooldown(m_spellInfo
->Id
);
1506 WorldPacket
data(SMSG_CLEAR_COOLDOWN
, (4+8));
1507 data
<< uint32(m_spellInfo
->Id
);
1508 data
<< uint64(m_caster
->GetGUID());
1509 ((Player
*)m_caster
)->GetSession()->SendPacket(&data
);
1512 SendCastResult(SPELL_FAILED_TARGET_AFFECTING_COMBAT
);
1516 // Righteous Defense (step 2) (in old version 31980 dummy effect)
1517 // Clear targets for eff 1
1518 for(std::list
<TargetInfo
>::iterator ihit
= m_UniqueTargetInfo
.begin();ihit
!= m_UniqueTargetInfo
.end();++ihit
)
1519 ihit
->effectMask
&= ~(1<<1);
1521 // not empty (checked)
1522 Unit::AttackerSet
const& attackers
= unitTarget
->getAttackers();
1524 // chance to be selected from list
1525 float chance
= 100.0f
/attackers
.size();
1527 for(Unit::AttackerSet::const_iterator aItr
= attackers
.begin(); aItr
!= attackers
.end() && count
< 3; ++aItr
)
1529 if(!roll_chance_f(chance
))
1532 AddUnitTarget((*aItr
), 1);
1535 // now let next effect cast spell at each target.
1538 case 37877: // Blessing of Faith
1543 uint32 spell_id
= 0;
1544 switch(unitTarget
->getClass())
1546 case CLASS_DRUID
: spell_id
= 37878; break;
1547 case CLASS_PALADIN
: spell_id
= 37879; break;
1548 case CLASS_PRIEST
: spell_id
= 37880; break;
1549 case CLASS_SHAMAN
: spell_id
= 37881; break;
1550 default: return; // ignore for not healing classes
1553 m_caster
->CastSpell(m_caster
,spell_id
,true);
1558 case SPELLFAMILY_SHAMAN
:
1559 //Shaman Rockbiter Weapon
1560 if (m_spellInfo
->SpellFamilyFlags
== 0x400000)
1562 uint32 spell_id
= 0;
1563 switch(m_spellInfo
->Id
)
1565 case 8017: spell_id
= 36494; break; // Rank 1
1566 case 8018: spell_id
= 36750; break; // Rank 2
1567 case 8019: spell_id
= 36755; break; // Rank 3
1568 case 10399: spell_id
= 36759; break; // Rank 4
1569 case 16314: spell_id
= 36763; break; // Rank 5
1570 case 16315: spell_id
= 36766; break; // Rank 6
1571 case 16316: spell_id
= 36771; break; // Rank 7
1572 case 25479: spell_id
= 36775; break; // Rank 8
1573 case 25485: spell_id
= 36499; break; // Rank 9
1575 sLog
.outError("Spell::EffectDummy: Spell %u not handled in RW",m_spellInfo
->Id
);
1579 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry( spell_id
);
1583 sLog
.outError("WORLD: unknown spell id %i\n", spell_id
);
1587 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
1590 for(int i
= BASE_ATTACK
; i
<= OFF_ATTACK
; ++i
)
1592 if(Item
* item
= ((Player
*)m_caster
)->GetWeaponForAttack(WeaponAttackType(i
)))
1594 if(item
->IsFitToSpellRequirements(m_spellInfo
))
1596 Spell
*spell
= new Spell(m_caster
, spellInfo
, true);
1598 // enchanting spell selected by calculated damage-per-sec in enchanting effect
1599 // at calculation applied affect from Elemental Weapons talent
1600 // real enchantment damage-1
1601 spell
->m_currentBasePoints
[1] = damage
-1;
1603 SpellCastTargets targets
;
1604 targets
.setItemTarget( item
);
1605 spell
->prepare(&targets
);
1612 if(m_spellInfo
->Id
== 39610) // Mana-Tide Totem effect
1614 if(!unitTarget
|| unitTarget
->getPowerType() != POWER_MANA
)
1617 // Regenerate 6% of Total Mana Every 3 secs
1618 int32 EffectBasePoints0
= unitTarget
->GetMaxPower(POWER_MANA
) * damage
/ 100;
1619 m_caster
->CastCustomSpell(unitTarget
,39609,&EffectBasePoints0
,NULL
,NULL
,true,NULL
,NULL
,m_originalCasterGUID
);
1627 if(PetAura
const* petSpell
= spellmgr
.GetPetAura(m_spellInfo
->Id
))
1629 m_caster
->AddPetAura(petSpell
);
1634 void Spell::EffectTriggerSpellWithValue(uint32 i
)
1636 uint32 triggered_spell_id
= m_spellInfo
->EffectTriggerSpell
[i
];
1639 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry( triggered_spell_id
);
1643 sLog
.outError("EffectTriggerSpellWithValue of spell %u: triggering unknown spell id %i\n", m_spellInfo
->Id
,triggered_spell_id
);
1648 m_caster
->CastCustomSpell(unitTarget
,triggered_spell_id
,&bp
,&bp
,&bp
,true,NULL
,NULL
,m_originalCasterGUID
);
1651 void Spell::EffectTriggerRitualOfSummoning(uint32 i
)
1653 uint32 triggered_spell_id
= m_spellInfo
->EffectTriggerSpell
[i
];
1654 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry( triggered_spell_id
);
1658 sLog
.outError("EffectTriggerRitualOfSummoning of spell %u: triggering unknown spell id %i", m_spellInfo
->Id
,triggered_spell_id
);
1663 Spell
*spell
= new Spell(m_caster
, spellInfo
, true);
1665 SpellCastTargets targets
;
1666 targets
.setUnitTarget( unitTarget
);
1667 spell
->prepare(&targets
);
1669 m_caster
->SetCurrentCastedSpell(spell
);
1670 spell
->m_selfContainer
= &(m_caster
->m_currentSpells
[spell
->GetCurrentContainer()]);
1674 void Spell::EffectForceCast(uint32 i
)
1679 uint32 triggered_spell_id
= m_spellInfo
->EffectTriggerSpell
[i
];
1682 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry( triggered_spell_id
);
1686 sLog
.outError("EffectForceCast of spell %u: triggering unknown spell id %i", m_spellInfo
->Id
,triggered_spell_id
);
1690 unitTarget
->CastSpell(unitTarget
,spellInfo
,true,NULL
,NULL
,m_originalCasterGUID
);
1693 void Spell::EffectTriggerSpell(uint32 i
)
1695 uint32 triggered_spell_id
= m_spellInfo
->EffectTriggerSpell
[i
];
1698 switch(triggered_spell_id
)
1703 m_caster
->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT
);
1704 m_caster
->RemoveSpellsCausingAura(SPELL_AURA_MOD_DECREASE_SPEED
);
1705 m_caster
->RemoveSpellsCausingAura(SPELL_AURA_MOD_STALKED
);
1707 // if this spell is given to NPC it must handle rest by it's own AI
1708 if ( m_caster
->GetTypeId() != TYPEID_PLAYER
)
1711 // get highest rank of the Stealth spell
1713 const PlayerSpellMap
& sp_list
= ((Player
*)m_caster
)->GetSpellMap();
1714 for (PlayerSpellMap::const_iterator itr
= sp_list
.begin(); itr
!= sp_list
.end(); ++itr
)
1716 // only highest rank is shown in spell book, so simply check if shown in spell book
1717 if(!itr
->second
->active
|| itr
->second
->disabled
|| itr
->second
->state
== PLAYERSPELL_REMOVED
)
1720 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(itr
->first
);
1724 if (spellInfo
->SpellFamilyName
== SPELLFAMILY_ROGUE
&& spellInfo
->SpellFamilyFlags
& SPELLFAMILYFLAG_ROGUE_STEALTH
)
1726 spellId
= spellInfo
->Id
;
1731 // no Stealth spell found
1735 // reset cooldown on it if needed
1736 if(((Player
*)m_caster
)->HasSpellCooldown(spellId
))
1737 ((Player
*)m_caster
)->RemoveSpellCooldown(spellId
);
1739 m_caster
->CastSpell(m_caster
, spellId
, true);
1743 case 23770: // Sayge's Dark Fortune of *
1744 // not exist, common cooldown can be implemented in scripts if need.
1746 // Brittle Armor - (need add max stack of 24575 Brittle Armor)
1749 const SpellEntry
*spell
= sSpellStore
.LookupEntry(24575);
1753 for (int i
=0; i
< spell
->StackAmount
; ++i
)
1754 m_caster
->CastSpell(unitTarget
,spell
->Id
, true, m_CastItem
, NULL
, m_originalCasterGUID
);
1757 // Mercurial Shield - (need add max stack of 26464 Mercurial Shield)
1760 const SpellEntry
*spell
= sSpellStore
.LookupEntry(26464);
1764 for (int i
=0; i
< spell
->StackAmount
; ++i
)
1765 m_caster
->CastSpell(unitTarget
,spell
->Id
, true, m_CastItem
, NULL
, m_originalCasterGUID
);
1768 // Righteous Defense
1771 m_caster
->CastSpell(unitTarget
, 31790, true,m_CastItem
,NULL
,m_originalCasterGUID
);
1777 Unit::AuraMap
& Auras
= m_caster
->GetAuras();
1778 for(Unit::AuraMap::iterator iter
= Auras
.begin(); iter
!= Auras
.end(); ++iter
)
1780 // remove all harmful spells on you...
1781 if( // ignore positive and passive auras
1782 !iter
->second
->IsPositive() && !iter
->second
->IsPassive() &&
1783 // ignore physical auras
1784 (GetSpellSchoolMask(iter
->second
->GetSpellProto()) & SPELL_SCHOOL_MASK_NORMAL
)==0 &&
1785 // ignore immunity persistent spells
1786 !( iter
->second
->GetSpellProto()->AttributesEx
& 0x10000 ) )
1788 m_caster
->RemoveAurasDueToSpell(iter
->second
->GetSpellProto()->Id
);
1789 iter
= Auras
.begin();
1794 // Priest Shadowfiend (34433) need apply mana gain trigger aura on pet
1797 if (Unit
*pet
= m_caster
->GetPet())
1798 pet
->CastSpell(pet
, 28305, true);
1804 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry( triggered_spell_id
);
1808 sLog
.outError("EffectTriggerSpell of spell %u: triggering unknown spell id %i", m_spellInfo
->Id
,triggered_spell_id
);
1812 // some triggered spells require specific equipment
1813 if(spellInfo
->EquippedItemClass
>=0 && m_caster
->GetTypeId()==TYPEID_PLAYER
)
1815 // main hand weapon required
1816 if(spellInfo
->AttributesEx3
& SPELL_ATTR_EX3_MAIN_HAND
)
1818 Item
* item
= ((Player
*)m_caster
)->GetWeaponForAttack(BASE_ATTACK
);
1820 // skip spell if no weapon in slot or broken
1821 if(!item
|| item
->IsBroken() )
1824 // skip spell if weapon not fit to triggered spell
1825 if(!item
->IsFitToSpellRequirements(spellInfo
))
1829 // offhand hand weapon required
1830 if(spellInfo
->AttributesEx3
& SPELL_ATTR_EX3_REQ_OFFHAND
)
1832 Item
* item
= ((Player
*)m_caster
)->GetWeaponForAttack(OFF_ATTACK
);
1834 // skip spell if no weapon in slot or broken
1835 if(!item
|| item
->IsBroken() )
1838 // skip spell if weapon not fit to triggered spell
1839 if(!item
->IsFitToSpellRequirements(spellInfo
))
1844 // some triggered spells must be casted instantly (for example, if next effect case instant kill caster)
1845 bool instant
= false;
1846 for(uint32 j
= i
+1; j
< 3; ++j
)
1848 if(m_spellInfo
->Effect
[j
]==SPELL_EFFECT_INSTAKILL
&& m_spellInfo
->EffectImplicitTargetA
[j
]==TARGET_SELF
)
1858 m_caster
->CastSpell(unitTarget
,spellInfo
,true,m_CastItem
,NULL
,m_originalCasterGUID
);
1861 m_TriggerSpells
.push_back(spellInfo
);
1864 void Spell::EffectTriggerMissileSpell(uint32 effect_idx
)
1866 uint32 triggered_spell_id
= m_spellInfo
->EffectTriggerSpell
[effect_idx
];
1869 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry( triggered_spell_id
);
1873 sLog
.outError("EffectTriggerMissileSpell of spell %u: triggering unknown spell id %effect_idx", m_spellInfo
->Id
,triggered_spell_id
);
1878 DEBUG_LOG("WORLD: cast Item spellId - %i", spellInfo
->Id
);
1880 Spell
*spell
= new Spell(m_caster
, spellInfo
, true, m_originalCasterGUID
);
1882 SpellCastTargets targets
;
1883 targets
.setDestination(m_targets
.m_destX
,m_targets
.m_destY
,m_targets
.m_destZ
);
1884 spell
->m_CastItem
= m_CastItem
;
1885 spell
->prepare(&targets
, NULL
);
1888 void Spell::EffectTeleportUnits(uint32 i
)
1890 if(!unitTarget
|| unitTarget
->isInFlight())
1893 switch (m_spellInfo
->EffectImplicitTargetB
[i
])
1895 case TARGET_INNKEEPER_COORDINATES
:
1897 // Only players can teleport to innkeeper
1898 if (unitTarget
->GetTypeId() != TYPEID_PLAYER
)
1901 ((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);
1904 case TARGET_TABLE_X_Y_Z_COORDINATES
:
1906 // TODO: Only players can teleport?
1907 if (unitTarget
->GetTypeId() != TYPEID_PLAYER
)
1909 SpellTargetPosition
const* st
= spellmgr
.GetSpellTargetPosition(m_spellInfo
->Id
);
1912 sLog
.outError( "Spell::EffectTeleportUnits - unknown Teleport coordinates for spell ID %u\n", m_spellInfo
->Id
);
1915 ((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);
1918 case TARGET_BEHIND_VICTIM
:
1920 // Get selected target for player (or victim for units)
1921 Unit
*pTarget
= NULL
;
1922 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
1923 pTarget
= ObjectAccessor::GetUnit(*m_caster
, ((Player
*)m_caster
)->GetSelection());
1925 pTarget
= m_caster
->getVictim();
1926 // No target present - return
1929 // Init dest coordinates
1930 uint32 mapid
= m_caster
->GetMapId();
1931 float x
= m_targets
.m_destX
;
1932 float y
= m_targets
.m_destY
;
1933 float z
= m_targets
.m_destZ
;
1934 float orientation
= pTarget
->GetOrientation();
1936 if(unitTarget
->GetTypeId() == TYPEID_PLAYER
)
1937 ((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));
1940 MapManager::Instance().GetMap(mapid
, m_caster
)->CreatureRelocation((Creature
*)unitTarget
, x
, y
, z
, orientation
);
1942 unitTarget
->BuildTeleportAckMsg(&data
, x
, y
, z
, orientation
);
1943 unitTarget
->SendMessageToSet(&data
, false);
1949 // If not exist data for dest location - return
1950 if(!(m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
))
1952 sLog
.outError( "Spell::EffectTeleportUnits - unknown EffectImplicitTargetB[%u] = %u for spell ID %u\n", i
, m_spellInfo
->EffectImplicitTargetB
[i
], m_spellInfo
->Id
);
1955 // Init dest coordinates
1956 uint32 mapid
= m_caster
->GetMapId();
1957 float x
= m_targets
.m_destX
;
1958 float y
= m_targets
.m_destY
;
1959 float z
= m_targets
.m_destZ
;
1960 float orientation
= unitTarget
->GetOrientation();
1962 if(unitTarget
->GetTypeId() == TYPEID_PLAYER
)
1963 ((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));
1966 MapManager::Instance().GetMap(mapid
, m_caster
)->CreatureRelocation((Creature
*)unitTarget
, x
, y
, z
, orientation
);
1968 unitTarget
->BuildTeleportAckMsg(&data
, x
, y
, z
, orientation
);
1969 unitTarget
->SendMessageToSet(&data
, false);
1975 // post effects for TARGET_TABLE_X_Y_Z_COORDINATES
1976 switch ( m_spellInfo
->Id
)
1978 // Dimensional Ripper - Everlook
1981 int32 r
= irand(0, 119);
1982 if ( r
>= 70 ) // 7/12 success
1984 if ( r
< 100 ) // 4/12 evil twin
1985 m_caster
->CastSpell(m_caster
,23445,true);
1987 m_caster
->CastSpell(m_caster
,23449,true);
1991 // Ultrasafe Transporter: Toshley's Station
1994 if ( roll_chance_i(50) ) // 50% success
1996 int32 rand_eff
= urand(1,7);
2000 // soul split - evil
2001 m_caster
->CastSpell(m_caster
,36900,true);
2004 // soul split - good
2005 m_caster
->CastSpell(m_caster
,36901,true);
2008 // Increase the size
2009 m_caster
->CastSpell(m_caster
,36895,true);
2012 // Decrease the size
2013 m_caster
->CastSpell(m_caster
,36893,true);
2018 if (((Player
*)m_caster
)->GetTeam() == ALLIANCE
)
2019 m_caster
->CastSpell(m_caster
,36897,true);
2021 m_caster
->CastSpell(m_caster
,36899,true);
2026 m_caster
->CastSpell(m_caster
,36940,true);
2030 m_caster
->CastSpell(m_caster
,23445,true);
2036 // Dimensional Ripper - Area 52
2039 if ( roll_chance_i(50) ) // 50% success
2041 int32 rand_eff
= urand(1,4);
2045 // soul split - evil
2046 m_caster
->CastSpell(m_caster
,36900,true);
2049 // soul split - good
2050 m_caster
->CastSpell(m_caster
,36901,true);
2053 // Increase the size
2054 m_caster
->CastSpell(m_caster
,36895,true);
2059 if (((Player
*)m_caster
)->GetTeam() == ALLIANCE
)
2060 m_caster
->CastSpell(m_caster
,36897,true);
2062 m_caster
->CastSpell(m_caster
,36899,true);
2072 void Spell::EffectApplyAura(uint32 i
)
2077 SpellImmuneList
const& list
= unitTarget
->m_spellImmune
[IMMUNITY_STATE
];
2078 for(SpellImmuneList::const_iterator itr
= list
.begin(); itr
!= list
.end(); ++itr
)
2079 if(itr
->type
== m_spellInfo
->EffectApplyAuraName
[i
])
2082 // ghost spell check, allow apply any auras at player loading in ghost mode (will be cleanup after load)
2083 if( !unitTarget
->isAlive() && m_spellInfo
->Id
!= 20584 && m_spellInfo
->Id
!= 8326 &&
2084 (unitTarget
->GetTypeId()!=TYPEID_PLAYER
|| !((Player
*)unitTarget
)->GetSession()->PlayerLoading()) )
2087 Unit
* caster
= m_originalCasterGUID
? m_originalCaster
: m_caster
;
2091 sLog
.outDebug("Spell: Aura is: %u", m_spellInfo
->EffectApplyAuraName
[i
]);
2093 Aura
* Aur
= CreateAura(m_spellInfo
, i
, &m_currentBasePoints
[i
], unitTarget
, caster
, m_CastItem
);
2095 // Now Reduce spell duration using data received at spell hit
2096 int32 duration
= Aur
->GetAuraMaxDuration();
2097 unitTarget
->ApplyDiminishingToDuration(m_diminishGroup
,duration
,m_caster
,m_diminishLevel
);
2098 Aur
->setDiminishGroup(m_diminishGroup
);
2100 // if Aura removed and deleted, do not continue.
2101 if(duration
== 0 && !(Aur
->IsPermanent()))
2107 if(duration
!= Aur
->GetAuraMaxDuration())
2109 Aur
->SetAuraMaxDuration(duration
);
2110 Aur
->SetAuraDuration(duration
);
2113 bool added
= unitTarget
->AddAura(Aur
);
2115 // Aura not added and deleted in AddAura call;
2119 // found crash at character loading, broken pointer to Aur...
2120 // Aur was deleted in AddAura()...
2124 // TODO Make a way so it works for every related spell!
2125 if(unitTarget
->GetTypeId()==TYPEID_PLAYER
) // Negative buff should only be applied on players
2128 if(m_spellInfo
->CasterAuraStateNot
==AURA_STATE_WEAKENED_SOUL
|| m_spellInfo
->TargetAuraStateNot
==AURA_STATE_WEAKENED_SOUL
)
2129 spellId
= 6788; // Weakened Soul
2130 else if(m_spellInfo
->CasterAuraStateNot
==AURA_STATE_FORBEARANCE
|| m_spellInfo
->TargetAuraStateNot
==AURA_STATE_FORBEARANCE
)
2131 spellId
= 25771; // Forbearance
2132 else if(m_spellInfo
->CasterAuraStateNot
==AURA_STATE_HYPOTHERMIA
)
2133 spellId
= 41425; // Hypothermia
2134 else if (m_spellInfo
->Mechanic
== MECHANIC_BANDAGE
) // Bandages
2135 spellId
= 11196; // Recently Bandaged
2136 else if( (m_spellInfo
->AttributesEx
& 0x20) && (m_spellInfo
->AttributesEx2
& 0x20000) )
2137 spellId
= 23230; // Blood Fury - Healing Reduction
2139 SpellEntry
const *AdditionalSpellInfo
= sSpellStore
.LookupEntry(spellId
);
2140 if (AdditionalSpellInfo
)
2142 // applied at target by target
2143 Aura
* AdditionalAura
= CreateAura(AdditionalSpellInfo
, 0, &m_currentBasePoints
[0], unitTarget
,unitTarget
, 0);
2144 unitTarget
->AddAura(AdditionalAura
);
2145 sLog
.outDebug("Spell: Additional Aura is: %u", AdditionalSpellInfo
->EffectApplyAuraName
[0]);
2149 // Prayer of Mending (jump animation), we need formal caster instead original for correct animation
2150 if( m_spellInfo
->SpellFamilyName
== SPELLFAMILY_PRIEST
&& (m_spellInfo
->SpellFamilyFlags
& 0x00002000000000LL
))
2151 m_caster
->CastSpell(unitTarget
,41637,true,NULL
,Aur
);
2154 void Spell::EffectUnlearnSpecialization( uint32 i
)
2156 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
2159 Player
*_player
= (Player
*)unitTarget
;
2160 uint32 spellToUnlearn
= m_spellInfo
->EffectTriggerSpell
[i
];
2162 _player
->removeSpell(spellToUnlearn
);
2164 sLog
.outDebug( "Spell: Player %u have unlearned spell %u from NpcGUID: %u", _player
->GetGUIDLow(), spellToUnlearn
, m_caster
->GetGUIDLow() );
2167 void Spell::EffectPowerDrain(uint32 i
)
2169 if(m_spellInfo
->EffectMiscValue
[i
] < 0 || m_spellInfo
->EffectMiscValue
[i
] >= MAX_POWERS
)
2172 Powers drain_power
= Powers(m_spellInfo
->EffectMiscValue
[i
]);
2176 if(!unitTarget
->isAlive())
2178 if(unitTarget
->getPowerType() != drain_power
)
2183 uint32 curPower
= unitTarget
->GetPower(drain_power
);
2185 //add spell damage bonus
2186 damage
=m_caster
->SpellDamageBonus(unitTarget
,m_spellInfo
,uint32(damage
),SPELL_DIRECT_DAMAGE
);
2188 // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
2189 uint32 power
= damage
;
2190 if ( drain_power
== POWER_MANA
&& unitTarget
->GetTypeId() == TYPEID_PLAYER
)
2191 power
-= ((Player
*)unitTarget
)->GetSpellCritDamageReduction(power
);
2194 if(curPower
< power
)
2195 new_damage
= curPower
;
2199 unitTarget
->ModifyPower(drain_power
,-new_damage
);
2201 if(drain_power
== POWER_MANA
)
2203 float manaMultiplier
= m_spellInfo
->EffectMultipleValue
[i
];
2204 if(manaMultiplier
==0)
2207 if(Player
*modOwner
= m_caster
->GetSpellModOwner())
2208 modOwner
->ApplySpellMod(m_spellInfo
->Id
, SPELLMOD_MULTIPLE_VALUE
, manaMultiplier
);
2210 int32 gain
= int32(new_damage
*manaMultiplier
);
2212 m_caster
->ModifyPower(POWER_MANA
,gain
);
2214 m_caster
->SendEnergizeSpellLog(m_caster
, m_spellInfo
->Id
,gain
,POWER_MANA
,false);
2218 void Spell::EffectSendEvent(uint32 EffectIndex
)
2220 if (m_caster
->GetTypeId() == TYPEID_PLAYER
&& ((Player
*)m_caster
)->InBattleGround())
2222 BattleGround
* bg
= ((Player
*)m_caster
)->GetBattleGround();
2223 if(bg
&& bg
->GetStatus() == STATUS_IN_PROGRESS
)
2225 switch(m_spellInfo
->Id
)
2227 case 23333: // Pickup Horde Flag
2228 /*do not uncomment .
2229 if(bg->GetTypeID()==BATTLEGROUND_WS)
2230 bg->EventPlayerClickedOnFlag((Player*)m_caster, this->gameObjTarget);
2231 sLog.outDebug("Send Event Horde Flag Picked Up");
2234 case 23334: // Drop Horde Flag
2235 if(bg->GetTypeID()==BATTLEGROUND_WS)
2236 bg->EventPlayerDroppedFlag((Player*)m_caster);
2237 sLog.outDebug("Drop Horde Flag");
2240 case 23335: // Pickup Alliance Flag
2241 /*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
2242 if(bg->GetTypeID()==BATTLEGROUND_WS)
2243 bg->EventPlayerClickedOnFlag((Player*)m_caster, this->gameObjTarget);
2244 sLog.outDebug("Send Event Alliance Flag Picked Up");
2247 case 23336: // Drop Alliance Flag
2248 if(bg->GetTypeID()==BATTLEGROUND_WS)
2249 bg->EventPlayerDroppedFlag((Player*)m_caster);
2250 sLog.outDebug("Drop Alliance Flag");
2252 case 23385: // Alliance Flag Returns
2253 if(bg->GetTypeID()==BATTLEGROUND_WS)
2254 bg->EventPlayerClickedOnFlag((Player*)m_caster, this->gameObjTarget);
2255 sLog.outDebug("Alliance Flag Returned");
2257 case 23386: // Horde Flag Returns
2258 if(bg->GetTypeID()==BATTLEGROUND_WS)
2259 bg->EventPlayerClickedOnFlag((Player*)m_caster, this->gameObjTarget);
2260 sLog.outDebug("Horde Flag Returned");
2264 if(bg->GetTypeID()==BATTLEGROUND_EY)
2265 bg->EventPlayerClickedOnFlag((Player*)m_caster, this->gameObjTarget);
2269 sLog
.outDebug("Unknown spellid %u in BG event", m_spellInfo
->Id
);
2274 sLog
.outDebug("Spell ScriptStart %u for spellid %u in EffectSendEvent ", m_spellInfo
->EffectMiscValue
[EffectIndex
], m_spellInfo
->Id
);
2275 sWorld
.ScriptsStart(sEventScripts
, m_spellInfo
->EffectMiscValue
[EffectIndex
], m_caster
, focusObject
);
2278 void Spell::EffectPowerBurn(uint32 i
)
2280 if(m_spellInfo
->EffectMiscValue
[i
] < 0 || m_spellInfo
->EffectMiscValue
[i
] >= MAX_POWERS
)
2283 Powers powertype
= Powers(m_spellInfo
->EffectMiscValue
[i
]);
2287 if(!unitTarget
->isAlive())
2289 if(unitTarget
->getPowerType()!=powertype
)
2294 int32 curPower
= int32(unitTarget
->GetPower(powertype
));
2296 // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
2297 uint32 power
= damage
;
2298 if ( powertype
== POWER_MANA
&& unitTarget
->GetTypeId() == TYPEID_PLAYER
)
2299 power
-= ((Player
*)unitTarget
)->GetSpellCritDamageReduction(power
);
2301 int32 new_damage
= (curPower
< power
) ? curPower
: power
;
2303 unitTarget
->ModifyPower(powertype
,-new_damage
);
2304 float multiplier
= m_spellInfo
->EffectMultipleValue
[i
];
2306 if(Player
*modOwner
= m_caster
->GetSpellModOwner())
2307 modOwner
->ApplySpellMod(m_spellInfo
->Id
, SPELLMOD_MULTIPLE_VALUE
, multiplier
);
2309 new_damage
= int32(new_damage
*multiplier
);
2310 m_caster
->SpellNonMeleeDamageLog(unitTarget
, m_spellInfo
->Id
, new_damage
, m_IsTriggeredSpell
, true);
2313 void Spell::EffectHeal( uint32
/*i*/ )
2315 if( unitTarget
&& unitTarget
->isAlive() && damage
>= 0)
2317 // Try to get original caster
2318 Unit
*caster
= m_originalCasterGUID
? m_originalCaster
: m_caster
;
2320 // Skip if m_originalCaster not available
2324 int32 addhealth
= damage
;
2326 // Vessel of the Naaru (Vial of the Sunwell trinket)
2327 if (m_spellInfo
->Id
== 45064)
2329 // Amount of heal - depends from stacked Holy Energy
2330 int damageAmount
= 0;
2331 Unit::AuraList
const& mDummyAuras
= m_caster
->GetAurasByType(SPELL_AURA_DUMMY
);
2332 for(Unit::AuraList::const_iterator i
= mDummyAuras
.begin();i
!= mDummyAuras
.end(); ++i
)
2333 if((*i
)->GetId() == 45062)
2334 damageAmount
+=(*i
)->GetModifier()->m_amount
;
2336 m_caster
->RemoveAurasDueToSpell(45062);
2338 addhealth
+= damageAmount
;
2340 // Swiftmend - consumes Regrowth or Rejuvenation
2341 else if (m_spellInfo
->TargetAuraState
== AURA_STATE_SWIFTMEND
&& unitTarget
->HasAuraState(AURA_STATE_SWIFTMEND
))
2343 Unit::AuraList
const& RejorRegr
= unitTarget
->GetAurasByType(SPELL_AURA_PERIODIC_HEAL
);
2344 // find most short by duration
2345 Aura
*targetAura
= NULL
;
2346 for(Unit::AuraList::const_iterator i
= RejorRegr
.begin(); i
!= RejorRegr
.end(); ++i
)
2348 if((*i
)->GetSpellProto()->SpellFamilyName
== SPELLFAMILY_DRUID
2349 && ((*i
)->GetSpellProto()->SpellFamilyFlags
== 0x40 || (*i
)->GetSpellProto()->SpellFamilyFlags
== 0x10) )
2351 if(!targetAura
|| (*i
)->GetAuraDuration() < targetAura
->GetAuraDuration())
2358 sLog
.outError("Target(GUID:" I64FMTD
") has aurastate AURA_STATE_SWIFTMEND but no matching aura.", unitTarget
->GetGUID());
2364 if(targetAura
->GetSpellProto()->EffectApplyAuraName
[idx
] == SPELL_AURA_PERIODIC_HEAL
)
2369 int32 tickheal
= caster
->SpellHealingBonus(targetAura
->GetSpellProto(), targetAura
->GetModifier()->m_amount
, DOT
, unitTarget
);
2370 int32 tickcount
= GetSpellDuration(targetAura
->GetSpellProto()) / targetAura
->GetSpellProto()->EffectAmplitude
[idx
];
2371 unitTarget
->RemoveAurasDueToSpell(targetAura
->GetId());
2373 addhealth
+= tickheal
* tickcount
;
2376 addhealth
= caster
->SpellHealingBonus(m_spellInfo
, addhealth
,HEAL
, unitTarget
);
2378 bool crit
= caster
->isSpellCrit(unitTarget
, m_spellInfo
, m_spellSchoolMask
, m_attackType
);
2380 addhealth
= caster
->SpellCriticalBonus(m_spellInfo
, addhealth
, unitTarget
);
2381 caster
->SendHealSpellLog(unitTarget
, m_spellInfo
->Id
, addhealth
, crit
);
2383 int32 gain
= unitTarget
->ModifyHealth( int32(addhealth
) );
2384 unitTarget
->getHostilRefManager().threatAssist(m_caster
, float(gain
) * 0.5f
, m_spellInfo
);
2386 if(caster
->GetTypeId()==TYPEID_PLAYER
)
2387 if(BattleGround
*bg
= ((Player
*)caster
)->GetBattleGround())
2388 bg
->UpdatePlayerScore(((Player
*)caster
), SCORE_HEALING_DONE
, gain
);
2390 // ignore item heals
2394 uint32 procHealer
= PROC_FLAG_HEAL
;
2396 procHealer
|= PROC_FLAG_CRIT_HEAL
;
2398 m_caster
->ProcDamageAndSpell(unitTarget
,procHealer
,PROC_FLAG_HEALED
,addhealth
,SPELL_SCHOOL_MASK_NONE
,m_spellInfo
,m_IsTriggeredSpell
);
2402 void Spell::EffectHealPct( uint32
/*i*/ )
2404 if( unitTarget
&& unitTarget
->isAlive() && damage
>= 0)
2406 // Try to get original caster
2407 Unit
*caster
= m_originalCasterGUID
? m_originalCaster
: m_caster
;
2409 // Skip if m_originalCaster not available
2413 uint32 addhealth
= unitTarget
->GetMaxHealth() * damage
/ 100;
2414 caster
->SendHealSpellLog(unitTarget
, m_spellInfo
->Id
, addhealth
, false);
2416 int32 gain
= unitTarget
->ModifyHealth( int32(addhealth
) );
2417 unitTarget
->getHostilRefManager().threatAssist(m_caster
, float(gain
) * 0.5f
, m_spellInfo
);
2419 if(caster
->GetTypeId()==TYPEID_PLAYER
)
2420 if(BattleGround
*bg
= ((Player
*)caster
)->GetBattleGround())
2421 bg
->UpdatePlayerScore(((Player
*)caster
), SCORE_HEALING_DONE
, gain
);
2425 void Spell::EffectHealMechanical( uint32
/*i*/ )
2427 // Mechanic creature type should be correctly checked by targetCreatureType field
2428 if( unitTarget
&& unitTarget
->isAlive() && damage
>= 0)
2430 // Try to get original caster
2431 Unit
*caster
= m_originalCasterGUID
? m_originalCaster
: m_caster
;
2433 // Skip if m_originalCaster not available
2437 uint32 addhealth
= caster
->SpellHealingBonus(m_spellInfo
, uint32(damage
), HEAL
, unitTarget
);
2438 caster
->SendHealSpellLog(unitTarget
, m_spellInfo
->Id
, addhealth
, false);
2439 unitTarget
->ModifyHealth( int32(damage
) );
2443 void Spell::EffectHealthLeech(uint32 i
)
2447 if(!unitTarget
->isAlive())
2453 sLog
.outDebug("HealthLeech :%i", damage
);
2455 float multiplier
= m_spellInfo
->EffectMultipleValue
[i
];
2457 if(Player
*modOwner
= m_caster
->GetSpellModOwner())
2458 modOwner
->ApplySpellMod(m_spellInfo
->Id
, SPELLMOD_MULTIPLE_VALUE
, multiplier
);
2460 int32 new_damage
= int32(damage
*multiplier
);
2461 uint32 curHealth
= unitTarget
->GetHealth();
2462 new_damage
= m_caster
->SpellNonMeleeDamageLog(unitTarget
, m_spellInfo
->Id
, new_damage
, m_IsTriggeredSpell
, true);
2463 if(curHealth
< new_damage
)
2464 new_damage
= curHealth
;
2466 if(m_caster
->isAlive())
2468 new_damage
= m_caster
->SpellHealingBonus(m_spellInfo
, new_damage
, HEAL
, m_caster
);
2470 m_caster
->ModifyHealth(new_damage
);
2472 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
2473 m_caster
->SendHealSpellLog(m_caster
, m_spellInfo
->Id
, uint32(new_damage
));
2477 void Spell::DoCreateItem(uint32 i
, uint32 itemtype
)
2479 if (!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
2482 Player
* player
= (Player
*)unitTarget
;
2484 uint32 newitemid
= itemtype
;
2485 ItemPrototype
const *pProto
= objmgr
.GetItemPrototype( newitemid
);
2488 player
->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND
, NULL
, NULL
);
2494 // TODO: maybe all this can be replaced by using correct calculated `damage` value
2495 if(pProto
->Class
!= ITEM_CLASS_CONSUMABLE
|| m_spellInfo
->SpellFamilyName
!= SPELLFAMILY_MAGE
)
2497 int32 basePoints
= m_currentBasePoints
[i
];
2498 int32 randomPoints
= m_spellInfo
->EffectDieSides
[i
];
2500 num_to_add
= basePoints
+ irand(1, randomPoints
);
2502 num_to_add
= basePoints
+ 1;
2504 else if (pProto
->MaxCount
== 1)
2506 else if(player
->getLevel() >= m_spellInfo
->spellLevel
)
2508 int32 basePoints
= m_currentBasePoints
[i
];
2509 float pointPerLevel
= m_spellInfo
->EffectRealPointsPerLevel
[i
];
2510 num_to_add
= basePoints
+ 1 + uint32((player
->getLevel() - m_spellInfo
->spellLevel
)*pointPerLevel
);
2517 if (num_to_add
> pProto
->Stackable
)
2518 num_to_add
= pProto
->Stackable
;
2520 // init items_count to 1, since 1 item will be created regardless of specialization
2522 // the chance to create additional items
2523 float additionalCreateChance
=0.0f
;
2524 // the maximum number of created additional items
2525 uint8 additionalMaxNum
=0;
2526 // get the chance and maximum number for creating extra items
2527 if ( canCreateExtraItems(player
, m_spellInfo
->Id
, additionalCreateChance
, additionalMaxNum
) )
2529 // roll with this chance till we roll not to create or we create the max num
2530 while ( roll_chance_f(additionalCreateChance
) && items_count
<=additionalMaxNum
)
2534 // really will be created more items
2535 num_to_add
*= items_count
;
2537 // can the player store the new item?
2538 ItemPosCountVec dest
;
2539 uint32 no_space
= 0;
2540 uint8 msg
= player
->CanStoreNewItem( NULL_BAG
, NULL_SLOT
, dest
, newitemid
, num_to_add
, &no_space
);
2541 if( msg
!= EQUIP_ERR_OK
)
2543 // convert to possible store amount
2544 if( msg
== EQUIP_ERR_INVENTORY_FULL
|| msg
== EQUIP_ERR_CANT_CARRY_MORE_OF_THIS
)
2545 num_to_add
-= no_space
;
2548 // if not created by another reason from full inventory or unique items amount limitation
2549 player
->SendEquipError( msg
, NULL
, NULL
);
2556 // create the new item and store it
2557 Item
* pItem
= player
->StoreNewItem( dest
, newitemid
, true, Item::GenerateItemRandomPropertyId(newitemid
));
2559 // was it successful? return error if not
2562 player
->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND
, NULL
, NULL
);
2566 // set the "Crafted by ..." property of the item
2567 if( pItem
->GetProto()->Class
!= ITEM_CLASS_CONSUMABLE
&& pItem
->GetProto()->Class
!= ITEM_CLASS_QUEST
)
2568 pItem
->SetUInt32Value(ITEM_FIELD_CREATOR
,player
->GetGUIDLow());
2570 // send info to the client
2572 player
->SendNewItem(pItem
, num_to_add
, true, true);
2574 // we succeeded in creating at least one item, so a levelup is possible
2575 player
->UpdateCraftSkill(m_spellInfo
->Id
);
2578 // for battleground marks send by mail if not add all expected
2581 BattleGroundTypeId bgType
;
2582 switch(m_spellInfo
->Id
)
2584 case SPELL_AV_MARK_WINNER
:
2585 case SPELL_AV_MARK_LOSER
:
2586 bgType
= BATTLEGROUND_AV
;
2588 case SPELL_WS_MARK_WINNER
:
2589 case SPELL_WS_MARK_LOSER
:
2590 bgType
= BATTLEGROUND_WS
;
2592 case SPELL_AB_MARK_WINNER
:
2593 case SPELL_AB_MARK_LOSER
:
2594 bgType
= BATTLEGROUND_AB
;
2600 if(BattleGround
* bg
= sBattleGroundMgr
.GetBattleGround(bgType
))
2601 bg
->SendRewardMarkByMail(player
,newitemid
,no_space
);
2605 void Spell::EffectCreateItem(uint32 i
)
2607 DoCreateItem(i
,m_spellInfo
->EffectItemType
[i
]);
2610 void Spell::EffectPersistentAA(uint32 i
)
2612 float radius
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[i
]));
2614 if(Player
* modOwner
= m_caster
->GetSpellModOwner())
2615 modOwner
->ApplySpellMod(m_spellInfo
->Id
, SPELLMOD_RADIUS
, radius
);
2617 int32 duration
= GetSpellDuration(m_spellInfo
);
2618 DynamicObject
* dynObj
= new DynamicObject
;
2619 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
))
2624 dynObj
->SetUInt32Value(OBJECT_FIELD_TYPE
, 65);
2625 dynObj
->SetUInt32Value(GAMEOBJECT_DISPLAYID
, 368003);
2626 dynObj
->SetUInt32Value(DYNAMICOBJECT_BYTES
, 0x01eeeeee);
2627 m_caster
->AddDynObject(dynObj
);
2628 MapManager::Instance().GetMap(dynObj
->GetMapId(), dynObj
)->Add(dynObj
);
2631 void Spell::EffectEnergize(uint32 i
)
2635 if(!unitTarget
->isAlive())
2638 if(m_spellInfo
->EffectMiscValue
[i
] < 0 || m_spellInfo
->EffectMiscValue
[i
] >= MAX_POWERS
)
2641 // Some level depends spells
2644 switch (m_spellInfo
->Id
)
2648 level_diff
= m_caster
->getLevel() - 40;
2653 level_diff
= m_caster
->getLevel() - 60;
2658 level_diff
= m_caster
->getLevel() - 60;
2666 damage
-= multipler
* level_diff
;
2671 Powers power
= Powers(m_spellInfo
->EffectMiscValue
[i
]);
2673 if(unitTarget
->GetMaxPower(power
) == 0)
2676 unitTarget
->ModifyPower(power
,damage
);
2677 m_caster
->SendEnergizeSpellLog(unitTarget
, m_spellInfo
->Id
, damage
, power
);
2679 // Mad Alchemist's Potion
2680 if (m_spellInfo
->Id
== 45051)
2682 // find elixirs on target
2683 uint32 elixir_mask
= 0;
2684 Unit::AuraMap
& Auras
= unitTarget
->GetAuras();
2685 for(Unit::AuraMap::iterator itr
= Auras
.begin(); itr
!= Auras
.end(); ++itr
)
2687 uint32 spell_id
= itr
->second
->GetId();
2688 if(uint32 mask
= spellmgr
.GetSpellElixirMask(spell_id
))
2689 elixir_mask
|= mask
;
2692 // get available elixir mask any not active type from battle/guardian (and flask if no any)
2693 elixir_mask
= (elixir_mask
& ELIXIR_FLASK_MASK
) ^ ELIXIR_FLASK_MASK
;
2695 // get all available elixirs by mask and spell level
2696 std::vector
<uint32
> elixirs
;
2697 SpellElixirMap
const& m_spellElixirs
= spellmgr
.GetSpellElixirMap();
2698 for(SpellElixirMap::const_iterator itr
= m_spellElixirs
.begin(); itr
!= m_spellElixirs
.end(); ++itr
)
2700 if (itr
->second
& elixir_mask
)
2702 if (itr
->second
& (ELIXIR_UNSTABLE_MASK
| ELIXIR_SHATTRATH_MASK
))
2705 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(itr
->first
);
2706 if (spellInfo
&& (spellInfo
->spellLevel
< m_spellInfo
->spellLevel
|| spellInfo
->spellLevel
> unitTarget
->getLevel()))
2709 elixirs
.push_back(itr
->first
);
2713 if (!elixirs
.empty())
2715 // cast random elixir on target
2716 uint32 rand_spell
= urand(0,elixirs
.size()-1);
2717 m_caster
->CastSpell(unitTarget
,elixirs
[rand_spell
],true,m_CastItem
);
2722 void Spell::EffectEnergisePct(uint32 i
)
2726 if(!unitTarget
->isAlive())
2729 if(m_spellInfo
->EffectMiscValue
[i
] < 0 || m_spellInfo
->EffectMiscValue
[i
] >= MAX_POWERS
)
2732 Powers power
= Powers(m_spellInfo
->EffectMiscValue
[i
]);
2734 uint32 maxPower
= unitTarget
->GetMaxPower(power
);
2738 uint32 gain
= damage
* maxPower
/ 100;
2739 unitTarget
->ModifyPower(power
, gain
);
2740 m_caster
->SendEnergizeSpellLog(unitTarget
, m_spellInfo
->Id
, damage
, power
);
2743 void Spell::SendLoot(uint64 guid
, LootType loottype
)
2745 Player
* player
= (Player
*)m_caster
;
2751 switch (gameObjTarget
->GetGoType())
2753 case GAMEOBJECT_TYPE_DOOR
:
2754 case GAMEOBJECT_TYPE_BUTTON
:
2755 gameObjTarget
->UseDoorOrButton();
2756 sWorld
.ScriptsStart(sGameObjectScripts
, gameObjTarget
->GetDBTableGUIDLow(), player
, gameObjTarget
);
2759 case GAMEOBJECT_TYPE_QUESTGIVER
:
2760 // start or end quest
2761 player
->PrepareQuestMenu(guid
);
2762 player
->SendPreparedQuest(guid
);
2765 case GAMEOBJECT_TYPE_SPELL_FOCUS
:
2766 // triggering linked GO
2767 if(uint32 trapEntry
= gameObjTarget
->GetGOInfo()->spellFocus
.linkedTrapId
)
2768 gameObjTarget
->TriggeringLinkedGameObject(trapEntry
,m_caster
);
2771 case GAMEOBJECT_TYPE_GOOBER
:
2772 // goober_scripts can be triggered if the player don't have the quest
2773 if (gameObjTarget
->GetGOInfo()->goober
.eventId
)
2775 sLog
.outDebug("Goober ScriptStart id %u for GO %u", gameObjTarget
->GetGOInfo()->goober
.eventId
,gameObjTarget
->GetDBTableGUIDLow());
2776 sWorld
.ScriptsStart(sEventScripts
, gameObjTarget
->GetGOInfo()->goober
.eventId
, player
, gameObjTarget
);
2779 // cast goober spell
2780 if (gameObjTarget
->GetGOInfo()->goober
.questId
)
2781 ///Quest require to be active for GO using
2782 if(player
->GetQuestStatus(gameObjTarget
->GetGOInfo()->goober
.questId
) != QUEST_STATUS_INCOMPLETE
)
2785 gameObjTarget
->AddUniqueUse(player
);
2786 gameObjTarget
->SetLootState(GO_JUST_DEACTIVATED
);
2788 //TODO? Objective counting called without spell check but with quest objective check
2789 // if send spell id then this line will duplicate to spell casting call (double counting)
2790 // So we or have this line and not required in quest_template have reqSpellIdN
2791 // or must remove this line and required in DB have data in quest_template have reqSpellIdN for all quest using cases.
2792 player
->CastedCreatureOrGO(gameObjTarget
->GetEntry(), gameObjTarget
->GetGUID(), 0);
2794 // triggering linked GO
2795 if(uint32 trapEntry
= gameObjTarget
->GetGOInfo()->goober
.linkedTrapId
)
2796 gameObjTarget
->TriggeringLinkedGameObject(trapEntry
,m_caster
);
2800 case GAMEOBJECT_TYPE_CHEST
:
2801 // TODO: possible must be moved to loot release (in different from linked triggering)
2802 if (gameObjTarget
->GetGOInfo()->chest
.eventId
)
2804 sLog
.outDebug("Chest ScriptStart id %u for GO %u", gameObjTarget
->GetGOInfo()->chest
.eventId
,gameObjTarget
->GetDBTableGUIDLow());
2805 sWorld
.ScriptsStart(sEventScripts
, gameObjTarget
->GetGOInfo()->chest
.eventId
, player
, gameObjTarget
);
2808 // triggering linked GO
2809 if(uint32 trapEntry
= gameObjTarget
->GetGOInfo()->chest
.linkedTrapId
)
2810 gameObjTarget
->TriggeringLinkedGameObject(trapEntry
,m_caster
);
2812 // Don't return, let loots been taken
2817 player
->SendLoot(guid
, loottype
);
2820 void Spell::EffectOpenLock(uint32
/*i*/)
2822 if(!m_caster
|| m_caster
->GetTypeId() != TYPEID_PLAYER
)
2824 sLog
.outDebug( "WORLD: Open Lock - No Player Caster!");
2828 Player
* player
= (Player
*)m_caster
;
2830 LootType loottype
= LOOT_CORPSE
;
2837 GameObjectInfo
const* goInfo
= gameObjTarget
->GetGOInfo();
2838 // Arathi Basin banner opening !
2839 if( goInfo
->type
== GAMEOBJECT_TYPE_BUTTON
&& goInfo
->button
.noDamageImmune
||
2840 goInfo
->type
== GAMEOBJECT_TYPE_GOOBER
&& goInfo
->goober
.losOK
)
2842 //isAllowUseBattleGroundObject() already called in CanCast()
2843 // in battleground check
2844 if(BattleGround
*bg
= player
->GetBattleGround())
2846 // check if it's correct bg
2847 if(bg
&& bg
->GetTypeID() == BATTLEGROUND_AB
)
2848 bg
->EventPlayerClickedOnFlag(player
, gameObjTarget
);
2852 else if (goInfo
->type
== GAMEOBJECT_TYPE_FLAGSTAND
)
2854 //isAllowUseBattleGroundObject() already called in CanCast()
2855 // in battleground check
2856 if(BattleGround
*bg
= player
->GetBattleGround())
2858 if(bg
->GetTypeID() == BATTLEGROUND_EY
)
2859 bg
->EventPlayerClickedOnFlag(player
, gameObjTarget
);
2863 lockId
= gameObjTarget
->GetLockId();
2864 guid
= gameObjTarget
->GetGUID();
2868 lockId
= itemTarget
->GetProto()->LockID
;
2869 guid
= itemTarget
->GetGUID();
2873 sLog
.outDebug( "WORLD: Open Lock - No GameObject/Item Target!");
2877 if(!lockId
) // possible case for GO and maybe for items.
2879 SendLoot(guid
, loottype
);
2884 LockEntry
const *lockInfo
= sLockStore
.LookupEntry(lockId
);
2888 sLog
.outError( "Spell::EffectOpenLock: %s [guid = %u] has an unknown lockId: %u!",
2889 (gameObjTarget
? "gameobject" : "item"), GUID_LOPART(guid
), lockId
);
2890 SendCastResult(SPELL_FAILED_BAD_TARGETS
);
2895 for(int i
= 0; i
< 5; ++i
)
2897 // type==1 This means lockInfo->key[i] is an item
2898 if(lockInfo
->keytype
[i
]==LOCK_KEY_ITEM
&& lockInfo
->key
[i
] && m_CastItem
&& m_CastItem
->GetEntry()==lockInfo
->key
[i
])
2900 SendLoot(guid
, loottype
);
2906 // Check and skill-up skill
2907 if( m_spellInfo
->Effect
[1] == SPELL_EFFECT_SKILL
)
2908 SkillId
= m_spellInfo
->EffectMiscValue
[1];
2909 // pickpocketing spells
2910 else if( m_spellInfo
->EffectMiscValue
[0] == LOCKTYPE_PICKLOCK
)
2911 SkillId
= SKILL_LOCKPICKING
;
2913 // skill bonus provided by casting spell (mostly item spells)
2914 uint32 spellSkillBonus
= uint32(m_currentBasePoints
[0]+1);
2916 uint32 reqSkillValue
= lockInfo
->requiredminingskill
;
2918 if(lockInfo
->requiredlockskill
) // required pick lock skill applying
2920 if(SkillId
!= SKILL_LOCKPICKING
) // wrong skill (cheating?)
2922 SendCastResult(SPELL_FAILED_FIZZLE
);
2926 reqSkillValue
= lockInfo
->requiredlockskill
;
2928 else if(SkillId
== SKILL_LOCKPICKING
) // apply picklock skill to wrong target
2930 SendCastResult(SPELL_FAILED_BAD_TARGETS
);
2936 loottype
= LOOT_SKINNING
;
2937 if ( player
->GetSkillValue(SkillId
) + spellSkillBonus
< reqSkillValue
)
2939 SendCastResult(SPELL_FAILED_LOW_CASTLEVEL
);
2943 // update skill if really known
2944 uint32 SkillValue
= player
->GetPureSkillValue(SkillId
);
2945 if(SkillValue
) // non only item base skill
2949 // Allow one skill-up until respawned
2950 if ( !gameObjTarget
->IsInSkillupList( player
->GetGUIDLow() ) &&
2951 player
->UpdateGatherSkill(SkillId
, SkillValue
, reqSkillValue
) )
2952 gameObjTarget
->AddToSkillupList( player
->GetGUIDLow() );
2957 uint32 SkillValue
= player
->GetPureSkillValue(SkillId
);
2958 player
->UpdateGatherSkill(SkillId
, SkillValue
, reqSkillValue
);
2963 SendLoot(guid
, loottype
);
2966 void Spell::EffectSummonChangeItem(uint32 i
)
2968 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
2971 Player
*player
= (Player
*)m_caster
;
2973 // applied only to using item
2977 // ... only to item in own inventory/bank/equip_slot
2978 if(m_CastItem
->GetOwnerGUID()!=player
->GetGUID())
2981 uint32 newitemid
= m_spellInfo
->EffectItemType
[i
];
2985 uint16 pos
= m_CastItem
->GetPos();
2987 Item
*pNewItem
= Item::CreateItem( newitemid
, 1, player
);
2991 for(uint8 i
= PERM_ENCHANTMENT_SLOT
; i
<=TEMP_ENCHANTMENT_SLOT
; ++i
)
2993 if(m_CastItem
->GetEnchantmentId(EnchantmentSlot(i
)))
2994 pNewItem
->SetEnchantment(EnchantmentSlot(i
), m_CastItem
->GetEnchantmentId(EnchantmentSlot(i
)), m_CastItem
->GetEnchantmentDuration(EnchantmentSlot(i
)), m_CastItem
->GetEnchantmentCharges(EnchantmentSlot(i
)));
2997 if(m_CastItem
->GetUInt32Value(ITEM_FIELD_DURABILITY
) < m_CastItem
->GetUInt32Value(ITEM_FIELD_MAXDURABILITY
))
2999 double loosePercent
= 1 - m_CastItem
->GetUInt32Value(ITEM_FIELD_DURABILITY
) / double(m_CastItem
->GetUInt32Value(ITEM_FIELD_MAXDURABILITY
));
3000 player
->DurabilityLoss(pNewItem
, loosePercent
);
3003 if( player
->IsInventoryPos( pos
) )
3005 ItemPosCountVec dest
;
3006 uint8 msg
= player
->CanStoreItem( m_CastItem
->GetBagSlot(), m_CastItem
->GetSlot(), dest
, pNewItem
, true );
3007 if( msg
== EQUIP_ERR_OK
)
3009 player
->DestroyItem(m_CastItem
->GetBagSlot(), m_CastItem
->GetSlot(),true);
3011 // prevent crash at access and unexpected charges counting with item update queue corrupt
3012 if(m_CastItem
==m_targets
.getItemTarget())
3013 m_targets
.setItemTarget(NULL
);
3017 player
->StoreItem( dest
, pNewItem
, true);
3021 else if( player
->IsBankPos ( pos
) )
3023 ItemPosCountVec dest
;
3024 uint8 msg
= player
->CanBankItem( m_CastItem
->GetBagSlot(), m_CastItem
->GetSlot(), dest
, pNewItem
, true );
3025 if( msg
== EQUIP_ERR_OK
)
3027 player
->DestroyItem(m_CastItem
->GetBagSlot(), m_CastItem
->GetSlot(),true);
3029 // prevent crash at access and unexpected charges counting with item update queue corrupt
3030 if(m_CastItem
==m_targets
.getItemTarget())
3031 m_targets
.setItemTarget(NULL
);
3035 player
->BankItem( dest
, pNewItem
, true);
3039 else if( player
->IsEquipmentPos ( pos
) )
3042 uint8 msg
= player
->CanEquipItem( m_CastItem
->GetSlot(), dest
, pNewItem
, true );
3043 if( msg
== EQUIP_ERR_OK
)
3045 player
->DestroyItem(m_CastItem
->GetBagSlot(), m_CastItem
->GetSlot(),true);
3047 // prevent crash at access and unexpected charges counting with item update queue corrupt
3048 if(m_CastItem
==m_targets
.getItemTarget())
3049 m_targets
.setItemTarget(NULL
);
3053 player
->EquipItem( dest
, pNewItem
, true);
3054 player
->AutoUnequipOffhandIfNeed();
3063 void Spell::EffectOpenSecretSafe(uint32 i
)
3065 EffectOpenLock(i
); //no difference for now
3068 void Spell::EffectProficiency(uint32
/*i*/)
3070 if (!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
3072 Player
*p_target
= (Player
*)unitTarget
;
3074 uint32 subClassMask
= m_spellInfo
->EquippedItemSubClassMask
;
3075 if(m_spellInfo
->EquippedItemClass
== 2 && !(p_target
->GetWeaponProficiency() & subClassMask
))
3077 p_target
->AddWeaponProficiency(subClassMask
);
3078 p_target
->SendProficiency(uint8(0x02),p_target
->GetWeaponProficiency());
3080 if(m_spellInfo
->EquippedItemClass
== 4 && !(p_target
->GetArmorProficiency() & subClassMask
))
3082 p_target
->AddArmorProficiency(subClassMask
);
3083 p_target
->SendProficiency(uint8(0x04),p_target
->GetArmorProficiency());
3087 void Spell::EffectApplyAreaAura(uint32 i
)
3091 if(!unitTarget
->isAlive())
3094 AreaAura
* Aur
= new AreaAura(m_spellInfo
, i
, &m_currentBasePoints
[i
], unitTarget
, m_caster
, m_CastItem
);
3095 unitTarget
->AddAura(Aur
);
3098 void Spell::EffectSummonType(uint32 i
)
3100 switch(m_spellInfo
->EffectMiscValueB
[i
])
3102 case SUMMON_TYPE_GUARDIAN
:
3103 case SUMMON_TYPE_POSESSED
:
3104 case SUMMON_TYPE_POSESSED2
:
3105 EffectSummonGuardian(i
);
3107 case SUMMON_TYPE_WILD
:
3108 EffectSummonWild(i
);
3110 case SUMMON_TYPE_DEMON
:
3111 EffectSummonDemon(i
);
3113 case SUMMON_TYPE_SUMMON
:
3116 case SUMMON_TYPE_CRITTER
:
3117 case SUMMON_TYPE_CRITTER2
:
3118 case SUMMON_TYPE_CRITTER3
:
3119 EffectSummonCritter(i
);
3121 case SUMMON_TYPE_TOTEM_SLOT1
:
3122 case SUMMON_TYPE_TOTEM_SLOT2
:
3123 case SUMMON_TYPE_TOTEM_SLOT3
:
3124 case SUMMON_TYPE_TOTEM_SLOT4
:
3125 case SUMMON_TYPE_TOTEM
:
3126 EffectSummonTotem(i
);
3128 case SUMMON_TYPE_UNKNOWN1
:
3129 case SUMMON_TYPE_UNKNOWN2
:
3130 case SUMMON_TYPE_UNKNOWN3
:
3131 case SUMMON_TYPE_UNKNOWN4
:
3132 case SUMMON_TYPE_UNKNOWN5
:
3135 sLog
.outError("EffectSummonType: Unhandled summon type %u", m_spellInfo
->EffectMiscValueB
[i
]);
3140 void Spell::EffectSummon(uint32 i
)
3142 if(m_caster
->GetPetGUID())
3147 uint32 pet_entry
= m_spellInfo
->EffectMiscValue
[i
];
3150 uint32 level
= m_caster
->getLevel();
3151 Pet
* spawnCreature
= new Pet(SUMMON_PET
);
3153 if(spawnCreature
->LoadPetFromDB(m_caster
,pet_entry
))
3155 // set timer for unsummon
3156 int32 duration
= GetSpellDuration(m_spellInfo
);
3158 spawnCreature
->SetDuration(duration
);
3163 Map
*map
= m_caster
->GetMap();
3164 uint32 pet_number
= objmgr
.GeneratePetNumber();
3165 if(!spawnCreature
->Create(objmgr
.GenerateLowGuid(HIGHGUID_PET
),map
,m_spellInfo
->EffectMiscValue
[i
], pet_number
))
3167 sLog
.outErrorDb("Spell::EffectSummon: no such creature entry %u",m_spellInfo
->EffectMiscValue
[i
]);
3168 delete spawnCreature
;
3172 // Summon in dest location
3174 if(m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
3176 x
= m_targets
.m_destX
;
3177 y
= m_targets
.m_destY
;
3178 z
= m_targets
.m_destZ
;
3181 m_caster
->GetClosePoint(x
,y
,z
,spawnCreature
->GetObjectSize());
3183 spawnCreature
->Relocate(x
,y
,z
,-m_caster
->GetOrientation());
3185 if(!spawnCreature
->IsPositionValid())
3187 sLog
.outError("ERROR: Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %d Y: ^%d)", spawnCreature
->GetGUIDLow(), spawnCreature
->GetEntry(), spawnCreature
->GetPositionX(), spawnCreature
->GetPositionY());
3188 delete spawnCreature
;
3192 // set timer for unsummon
3193 int32 duration
= GetSpellDuration(m_spellInfo
);
3195 spawnCreature
->SetDuration(duration
);
3197 spawnCreature
->SetUInt64Value(UNIT_FIELD_SUMMONEDBY
,m_caster
->GetGUID());
3198 spawnCreature
->SetUInt32Value(UNIT_NPC_FLAGS
, 0);
3199 spawnCreature
->setPowerType(POWER_MANA
);
3200 spawnCreature
->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE
,m_caster
->getFaction());
3201 spawnCreature
->SetUInt32Value(UNIT_FIELD_FLAGS
,0);
3202 spawnCreature
->SetUInt32Value(UNIT_FIELD_BYTES_0
,2048);
3203 spawnCreature
->SetUInt32Value(UNIT_FIELD_BYTES_1
,0);
3204 spawnCreature
->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP
,0);
3205 spawnCreature
->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE
,0);
3206 spawnCreature
->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP
,1000);
3207 spawnCreature
->SetUInt64Value(UNIT_FIELD_CREATEDBY
, m_caster
->GetGUID());
3208 spawnCreature
->SetUInt32Value(UNIT_CREATED_BY_SPELL
, m_spellInfo
->Id
);
3210 spawnCreature
->InitStatsForLevel(level
);
3212 spawnCreature
->GetCharmInfo()->SetPetNumber(pet_number
, false);
3214 spawnCreature
->AIM_Initialize();
3215 spawnCreature
->InitPetCreateSpells();
3216 spawnCreature
->SetHealth(spawnCreature
->GetMaxHealth());
3217 spawnCreature
->SetPower(POWER_MANA
, spawnCreature
->GetMaxPower(POWER_MANA
));
3219 std::string name
= m_caster
->GetName();
3220 name
.append(petTypeSuffix
[spawnCreature
->getPetType()]);
3221 spawnCreature
->SetName( name
);
3223 map
->Add((Creature
*)spawnCreature
);
3225 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
3227 m_caster
->SetPet(spawnCreature
);
3228 spawnCreature
->GetCharmInfo()->SetReactState( REACT_DEFENSIVE
);
3229 spawnCreature
->SavePetToDB(PET_SAVE_AS_CURRENT
);
3230 ((Player
*)m_caster
)->PetSpellInitialize();
3234 void Spell::EffectLearnSpell(uint32 i
)
3239 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
3241 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
3242 EffectLearnPetSpell(i
);
3247 Player
*player
= (Player
*)unitTarget
;
3249 uint32 spellToLearn
= (m_spellInfo
->Id
==SPELL_ID_GENERIC_LEARN
) ? damage
: m_spellInfo
->EffectTriggerSpell
[i
];
3250 player
->learnSpell(spellToLearn
);
3252 sLog
.outDebug( "Spell: Player %u have learned spell %u from NpcGUID=%u", player
->GetGUIDLow(), spellToLearn
, m_caster
->GetGUIDLow() );
3255 void Spell::EffectDispel(uint32 i
)
3260 // Fill possible dispell list
3261 std::vector
<Aura
*> dispel_list
;
3263 // Create dispel mask by dispel type
3264 uint32 dispel_type
= m_spellInfo
->EffectMiscValue
[i
];
3265 uint32 dispelMask
= GetDispellMask( DispelType(dispel_type
) );
3266 Unit::AuraMap
const& auras
= unitTarget
->GetAuras();
3267 for(Unit::AuraMap::const_iterator itr
= auras
.begin(); itr
!= auras
.end(); ++itr
)
3269 Aura
*aur
= (*itr
).second
;
3270 if (aur
&& (1<<aur
->GetSpellProto()->Dispel
) & dispelMask
)
3272 if(aur
->GetSpellProto()->Dispel
== DISPEL_MAGIC
)
3274 bool positive
= true;
3275 if (!aur
->IsPositive())
3278 positive
= (aur
->GetSpellProto()->AttributesEx
& SPELL_ATTR_EX_NEGATIVE
)==0;
3280 // do not remove positive auras if friendly target
3281 // negative auras if non-friendly target
3282 if(positive
== unitTarget
->IsFriendlyTo(m_caster
))
3285 // Add aura to dispel list
3286 dispel_list
.push_back(aur
);
3289 // Ok if exist some buffs for dispel try dispel it
3290 if (!dispel_list
.empty())
3292 std::list
< std::pair
<uint32
,uint64
> > success_list
;// (spell_id,casterGuid)
3293 std::list
< uint32
> fail_list
; // spell_id
3294 int32 list_size
= dispel_list
.size();
3295 // Dispell N = damage buffs (or while exist buffs for dispel)
3296 for (int32 count
=0; count
< damage
&& list_size
> 0; ++count
)
3298 // Random select buff for dispel
3299 Aura
*aur
= dispel_list
[urand(0, list_size
-1)];
3301 SpellEntry
const* spellInfo
= aur
->GetSpellProto();
3302 // Base dispel chance
3303 // TODO: possible chance depend from spell level??
3304 int32 miss_chance
= 0;
3305 // Apply dispel mod from aura caster
3306 if (Unit
*caster
= aur
->GetCaster())
3308 if ( Player
* modOwner
= caster
->GetSpellModOwner() )
3309 modOwner
->ApplySpellMod(spellInfo
->Id
, SPELLMOD_RESIST_DISPEL_CHANCE
, miss_chance
, this);
3312 if (roll_chance_i(miss_chance
))
3313 fail_list
.push_back(aur
->GetId());
3315 success_list
.push_back(std::pair
<uint32
,uint64
>(aur
->GetId(),aur
->GetCasterGUID()));
3316 // Remove buff from list for prevent doubles
3317 for (std::vector
<Aura
*>::iterator j
= dispel_list
.begin(); j
!= dispel_list
.end(); )
3319 Aura
*dispeled
= *j
;
3320 if (dispeled
->GetId() == aur
->GetId() && dispeled
->GetCasterGUID() == aur
->GetCasterGUID())
3322 j
= dispel_list
.erase(j
);
3329 // Send success log and really remove auras
3330 if (!success_list
.empty())
3332 int32 count
= success_list
.size();
3333 WorldPacket
data(SMSG_SPELLDISPELLOG
, 8+8+4+1+4+count
*5);
3334 data
.append(unitTarget
->GetPackGUID()); // Victim GUID
3335 data
.append(m_caster
->GetPackGUID()); // Caster GUID
3336 data
<< uint32(m_spellInfo
->Id
); // Dispell spell id
3337 data
<< uint8(0); // not used
3338 data
<< uint32(count
); // count
3339 for (std::list
<std::pair
<uint32
,uint64
> >::iterator j
= success_list
.begin(); j
!= success_list
.end(); ++j
)
3341 SpellEntry
const* spellInfo
= sSpellStore
.LookupEntry(j
->first
);
3342 data
<< uint32(spellInfo
->Id
); // Spell Id
3343 data
<< uint8(0); // 0 - dispeled !=0 cleansed
3344 unitTarget
->RemoveAurasDueToSpellByDispel(spellInfo
->Id
, j
->second
, m_caster
);
3346 m_caster
->SendMessageToSet(&data
, true);
3350 if (m_spellInfo
->SpellFamilyName
== SPELLFAMILY_WARLOCK
&& m_spellInfo
->Category
== 12)
3352 uint32 heal_spell
= 0;
3353 switch (m_spellInfo
->Id
)
3355 case 19505: heal_spell
= 19658; break;
3356 case 19731: heal_spell
= 19732; break;
3357 case 19734: heal_spell
= 19733; break;
3358 case 19736: heal_spell
= 19735; break;
3359 case 27276: heal_spell
= 27278; break;
3360 case 27277: heal_spell
= 27279; break;
3362 sLog
.outDebug("Spell for Devour Magic %d not handled in Spell::EffectDispel", m_spellInfo
->Id
);
3366 m_caster
->CastSpell(m_caster
, heal_spell
, true);
3369 // Send fail log to client
3370 if (!fail_list
.empty())
3372 // Failed to dispell
3373 WorldPacket
data(SMSG_DISPEL_FAILED
, 8+8+4+4*fail_list
.size());
3374 data
<< uint64(m_caster
->GetGUID()); // Caster GUID
3375 data
<< uint64(unitTarget
->GetGUID()); // Victim GUID
3376 data
<< uint32(m_spellInfo
->Id
); // Dispell spell id
3377 for (std::list
< uint32
>::iterator j
= fail_list
.begin(); j
!= fail_list
.end(); ++j
)
3378 data
<< uint32(*j
); // Spell Id
3379 m_caster
->SendMessageToSet(&data
, true);
3384 void Spell::EffectDualWield(uint32
/*i*/)
3386 if (unitTarget
->GetTypeId() == TYPEID_PLAYER
)
3387 ((Player
*)unitTarget
)->SetCanDualWield(true);
3390 void Spell::EffectPull(uint32
/*i*/)
3392 // TODO: create a proper pull towards distract spell center for distract
3393 sLog
.outDebug("WORLD: Spell Effect DUMMY");
3396 void Spell::EffectDistract(uint32
/*i*/)
3398 // Check for possible target
3399 if (!unitTarget
|| unitTarget
->isInCombat())
3402 // target must be OK to do this
3403 if( unitTarget
->hasUnitState(UNIT_STAT_CONFUSED
| UNIT_STAT_STUNNED
| UNIT_STAT_FLEEING
) )
3406 float angle
= unitTarget
->GetAngle(m_targets
.m_destX
, m_targets
.m_destY
);
3408 if ( unitTarget
->GetTypeId() == TYPEID_PLAYER
)
3410 // For players just turn them
3412 ((Player
*)unitTarget
)->BuildTeleportAckMsg(&data
, unitTarget
->GetPositionX(), unitTarget
->GetPositionY(), unitTarget
->GetPositionZ(), angle
);
3413 ((Player
*)unitTarget
)->GetSession()->SendPacket( &data
);
3414 ((Player
*)unitTarget
)->SetPosition(unitTarget
->GetPositionX(), unitTarget
->GetPositionY(), unitTarget
->GetPositionZ(), angle
, false);
3418 // Set creature Distracted, Stop it, And turn it
3419 unitTarget
->SetOrientation(angle
);
3420 unitTarget
->StopMoving();
3421 unitTarget
->GetMotionMaster()->MoveDistract(damage
*1000);
3425 void Spell::EffectPickPocket(uint32
/*i*/)
3427 if( m_caster
->GetTypeId() != TYPEID_PLAYER
)
3430 // victim must be creature and attackable
3431 if( !unitTarget
|| unitTarget
->GetTypeId() != TYPEID_UNIT
|| m_caster
->IsFriendlyTo(unitTarget
) )
3434 // victim have to be alive and humanoid or undead
3435 if( unitTarget
->isAlive() && (unitTarget
->GetCreatureTypeMask() &CREATURE_TYPEMASK_HUMANOID_OR_UNDEAD
) != 0)
3437 int32 chance
= 10 + int32(m_caster
->getLevel()) - int32(unitTarget
->getLevel());
3439 if (chance
> irand(0, 19))
3441 // Stealing successful
3442 //sLog.outDebug("Sending loot from pickpocket");
3443 ((Player
*)m_caster
)->SendLoot(unitTarget
->GetGUID(),LOOT_PICKPOCKETING
);
3447 // Reveal action + get attack
3448 m_caster
->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH
);
3449 if (((Creature
*)unitTarget
)->AI())
3450 ((Creature
*)unitTarget
)->AI()->AttackStart(m_caster
);
3455 void Spell::EffectAddFarsight(uint32 i
)
3457 float radius
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[i
]));
3458 int32 duration
= GetSpellDuration(m_spellInfo
);
3459 DynamicObject
* dynObj
= new DynamicObject
;
3460 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
))
3465 dynObj
->SetUInt32Value(OBJECT_FIELD_TYPE
, 65);
3466 dynObj
->SetUInt32Value(DYNAMICOBJECT_BYTES
, 0x80000002);
3467 m_caster
->AddDynObject(dynObj
);
3468 MapManager::Instance().GetMap(dynObj
->GetMapId(), dynObj
)->Add(dynObj
);
3469 m_caster
->SetUInt64Value(PLAYER_FARSIGHT
, dynObj
->GetGUID());
3472 void Spell::EffectSummonWild(uint32 i
)
3474 uint32 creature_entry
= m_spellInfo
->EffectMiscValue
[i
];
3478 uint32 level
= m_caster
->getLevel();
3480 // level of creature summoned using engineering item based at engineering skill level
3481 if(m_caster
->GetTypeId()==TYPEID_PLAYER
&& m_CastItem
)
3483 ItemPrototype
const *proto
= m_CastItem
->GetProto();
3484 if(proto
&& proto
->RequiredSkill
== SKILL_ENGINERING
)
3486 uint16 skill202
= ((Player
*)m_caster
)->GetSkillValue(SKILL_ENGINERING
);
3494 // select center of summon position
3495 float center_x
= m_targets
.m_destX
;
3496 float center_y
= m_targets
.m_destY
;
3497 float center_z
= m_targets
.m_destZ
;
3499 float radius
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[i
]));
3501 int32 amount
= damage
> 0 ? damage
: 1;
3503 for(int32 count
= 0; count
< amount
; ++count
)
3506 // If dest location if present
3507 if (m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
3509 // Summon 1 unit in dest location
3512 px
= m_targets
.m_destX
;
3513 py
= m_targets
.m_destY
;
3514 pz
= m_targets
.m_destZ
;
3516 // Summon in random point all other units if location present
3518 m_caster
->GetRandomPoint(center_x
,center_y
,center_z
,radius
,px
,py
,pz
);
3520 // Summon if dest location not present near caster
3522 m_caster
->GetClosePoint(px
,py
,pz
,3.0f
);
3524 int32 duration
= GetSpellDuration(m_spellInfo
);
3526 TempSummonType summonType
= (duration
== 0) ? TEMPSUMMON_DEAD_DESPAWN
: TEMPSUMMON_TIMED_OR_DEAD_DESPAWN
;
3528 m_caster
->SummonCreature(creature_entry
,px
,py
,pz
,m_caster
->GetOrientation(),summonType
,duration
);
3532 void Spell::EffectSummonGuardian(uint32 i
)
3534 uint32 pet_entry
= m_spellInfo
->EffectMiscValue
[i
];
3538 // Jewelery statue case (totem like)
3539 if(m_spellInfo
->SpellIconID
==2056)
3541 EffectSummonTotem(i
);
3545 // set timer for unsummon
3546 int32 duration
= GetSpellDuration(m_spellInfo
);
3548 // Search old Guardian only for players (if casted spell not have duration or cooldown)
3549 // FIXME: some guardians have control spell applied and controlled by player and anyway player can't summon in this time
3550 // so this code hack in fact
3551 if( m_caster
->GetTypeId() == TYPEID_PLAYER
&& (duration
<= 0 || GetSpellRecoveryTime(m_spellInfo
)==0) )
3552 if(((Player
*)m_caster
)->HasGuardianWithEntry(pet_entry
))
3553 return; // find old guardian, ignore summon
3555 // in another case summon new
3556 uint32 level
= m_caster
->getLevel();
3558 // level of pet summoned using engineering item based at engineering skill level
3559 if(m_caster
->GetTypeId()==TYPEID_PLAYER
&& m_CastItem
)
3561 ItemPrototype
const *proto
= m_CastItem
->GetProto();
3562 if(proto
&& proto
->RequiredSkill
== SKILL_ENGINERING
)
3564 uint16 skill202
= ((Player
*)m_caster
)->GetSkillValue(SKILL_ENGINERING
);
3572 // select center of summon position
3573 float center_x
= m_targets
.m_destX
;
3574 float center_y
= m_targets
.m_destY
;
3575 float center_z
= m_targets
.m_destZ
;
3577 float radius
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[i
]));
3579 int32 amount
= damage
> 0 ? damage
: 1;
3581 for(int32 count
= 0; count
< amount
; ++count
)
3583 Pet
* spawnCreature
= new Pet(GUARDIAN_PET
);
3585 Map
*map
= m_caster
->GetMap();
3586 uint32 pet_number
= objmgr
.GeneratePetNumber();
3587 if(!spawnCreature
->Create(objmgr
.GenerateLowGuid(HIGHGUID_PET
), map
,m_spellInfo
->EffectMiscValue
[i
], pet_number
))
3589 sLog
.outError("no such creature entry %u",m_spellInfo
->EffectMiscValue
[i
]);
3590 delete spawnCreature
;
3595 // If dest location if present
3596 if (m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
3598 // Summon 1 unit in dest location
3601 px
= m_targets
.m_destX
;
3602 py
= m_targets
.m_destY
;
3603 pz
= m_targets
.m_destZ
;
3605 // Summon in random point all other units if location present
3607 m_caster
->GetRandomPoint(center_x
,center_y
,center_z
,radius
,px
,py
,pz
);
3609 // Summon if dest location not present near caster
3611 m_caster
->GetClosePoint(px
,py
,pz
,spawnCreature
->GetObjectSize());
3613 spawnCreature
->Relocate(px
,py
,pz
,m_caster
->GetOrientation());
3615 if(!spawnCreature
->IsPositionValid())
3617 sLog
.outError("ERROR: Pet (guidlow %d, entry %d) not created base at creature. Suggested coordinates isn't valid (X: %d Y: ^%d)", spawnCreature
->GetGUIDLow(), spawnCreature
->GetEntry(), spawnCreature
->GetPositionX(), spawnCreature
->GetPositionY());
3618 delete spawnCreature
;
3623 spawnCreature
->SetDuration(duration
);
3625 spawnCreature
->SetUInt64Value(UNIT_FIELD_SUMMONEDBY
,m_caster
->GetGUID());
3626 spawnCreature
->setPowerType(POWER_MANA
);
3627 spawnCreature
->SetUInt32Value(UNIT_NPC_FLAGS
, 0);
3628 spawnCreature
->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE
,m_caster
->getFaction());
3629 spawnCreature
->SetUInt32Value(UNIT_FIELD_FLAGS
,0);
3630 spawnCreature
->SetUInt32Value(UNIT_FIELD_BYTES_1
,0);
3631 spawnCreature
->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP
,0);
3632 spawnCreature
->SetUInt64Value(UNIT_FIELD_CREATEDBY
, m_caster
->GetGUID());
3633 spawnCreature
->SetUInt32Value(UNIT_CREATED_BY_SPELL
, m_spellInfo
->Id
);
3635 spawnCreature
->InitStatsForLevel(level
);
3636 spawnCreature
->GetCharmInfo()->SetPetNumber(pet_number
, false);
3638 spawnCreature
->AIM_Initialize();
3640 if(m_caster
->GetTypeId()==TYPEID_PLAYER
)
3641 ((Player
*)m_caster
)->AddGuardian(spawnCreature
);
3643 map
->Add((Creature
*)spawnCreature
);
3647 void Spell::EffectTeleUnitsFaceCaster(uint32 i
)
3652 if(unitTarget
->isInFlight())
3655 uint32 mapid
= m_caster
->GetMapId();
3656 float dis
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[i
]));
3659 m_caster
->GetClosePoint(fx
,fy
,fz
,unitTarget
->GetObjectSize(),dis
);
3661 if(unitTarget
->GetTypeId() == TYPEID_PLAYER
)
3662 ((Player
*)unitTarget
)->TeleportTo(mapid
, fx
, fy
, fz
, -m_caster
->GetOrientation(), TELE_TO_NOT_LEAVE_COMBAT
| TELE_TO_NOT_UNSUMMON_PET
| (unitTarget
==m_caster
? TELE_TO_SPELL
: 0));
3664 MapManager::Instance().GetMap(mapid
, m_caster
)->CreatureRelocation((Creature
*)m_caster
, fx
, fy
, fz
, -m_caster
->GetOrientation());
3667 void Spell::EffectLearnSkill(uint32 i
)
3669 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
3675 uint32 skillid
= m_spellInfo
->EffectMiscValue
[i
];
3676 uint16 skillval
= ((Player
*)unitTarget
)->GetPureSkillValue(skillid
);
3677 ((Player
*)unitTarget
)->SetSkill(skillid
, skillval
?skillval
:1, damage
*75);
3680 void Spell::EffectAddHonor(uint32
/*i*/)
3682 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
3685 sLog
.outDebug("SpellEffect::AddHonor called for spell_id %u , that rewards %d honor points to player: %u", m_spellInfo
->Id
, this->damage
, ((Player
*)unitTarget
)->GetGUIDLow());
3687 // TODO: find formula for honor reward based on player's level!
3689 // now fixed only for level 70 players:
3690 if (((Player
*)unitTarget
)->getLevel() == 70)
3691 ((Player
*)unitTarget
)->RewardHonor(NULL
, 1, this->damage
);
3694 void Spell::EffectTradeSkill(uint32
/*i*/)
3696 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
3698 // uint32 skillid = m_spellInfo->EffectMiscValue[i];
3699 // uint16 skillmax = ((Player*)unitTarget)->(skillid);
3700 // ((Player*)unitTarget)->SetSkill(skillid,skillval?skillval:1,skillmax+75);
3703 void Spell::EffectEnchantItemPerm(uint32 i
)
3705 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
3710 Player
* p_caster
= (Player
*)m_caster
;
3712 p_caster
->UpdateCraftSkill(m_spellInfo
->Id
);
3714 if (m_spellInfo
->EffectMiscValue
[i
])
3716 uint32 enchant_id
= m_spellInfo
->EffectMiscValue
[i
];
3718 SpellItemEnchantmentEntry
const *pEnchant
= sSpellItemEnchantmentStore
.LookupEntry(enchant_id
);
3722 // item can be in trade slot and have owner diff. from caster
3723 Player
* item_owner
= itemTarget
->GetOwner();
3727 if(item_owner
!=p_caster
&& p_caster
->GetSession()->GetSecurity() > SEC_PLAYER
&& sWorld
.getConfig(CONFIG_GM_LOG_TRADE
) )
3728 sLog
.outCommand("GM %s (Account: %u) enchanting(perm): %s (Entry: %d) for player: %s (Account: %u)",
3729 p_caster
->GetName(),p_caster
->GetSession()->GetAccountId(),
3730 itemTarget
->GetProto()->Name1
,itemTarget
->GetEntry(),
3731 item_owner
->GetName(),item_owner
->GetSession()->GetAccountId());
3733 // remove old enchanting before applying new if equipped
3734 item_owner
->ApplyEnchantment(itemTarget
,PERM_ENCHANTMENT_SLOT
,false);
3736 itemTarget
->SetEnchantment(PERM_ENCHANTMENT_SLOT
, enchant_id
, 0, 0);
3738 // add new enchanting if equipped
3739 item_owner
->ApplyEnchantment(itemTarget
,PERM_ENCHANTMENT_SLOT
,true);
3743 void Spell::EffectEnchantItemTmp(uint32 i
)
3745 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
3748 Player
* p_caster
= (Player
*)m_caster
;
3753 uint32 enchant_id
= m_spellInfo
->EffectMiscValue
[i
];
3755 // Shaman Rockbiter Weapon
3756 if(i
==0 && m_spellInfo
->Effect
[1]==SPELL_EFFECT_DUMMY
)
3758 int32 enchnting_damage
= m_currentBasePoints
[1]+1;
3760 // enchanting id selected by calculated damage-per-sec stored in Effect[1] base value
3761 // with already applied percent bonus from Elemental Weapons talent
3762 // Note: damage calculated (correctly) with rounding int32(float(v)) but
3763 // RW enchantments applied damage int32(float(v)+0.5), this create 0..1 difference sometime
3764 switch(enchnting_damage
)
3767 case 2: enchant_id
= 29; break; // 0% [ 7% == 2, 14% == 2, 20% == 2]
3769 case 4: enchant_id
= 6; break; // 0% [ 7% == 4, 14% == 4]
3770 case 5: enchant_id
= 3025; break; // 20%
3772 case 6: enchant_id
= 1; break; // 0% [ 7% == 6, 14% == 6]
3773 case 7: enchant_id
= 3027; break; // 20%
3775 case 9: enchant_id
= 3032; break; // 0% [ 7% == 6]
3776 case 10: enchant_id
= 503; break; // 14%
3777 case 11: enchant_id
= 3031; break; // 20%
3779 case 15: enchant_id
= 3035; break; // 0%
3780 case 16: enchant_id
= 1663; break; // 7%
3781 case 17: enchant_id
= 3033; break; // 14%
3782 case 18: enchant_id
= 3034; break; // 20%
3784 case 28: enchant_id
= 3038; break; // 0%
3785 case 29: enchant_id
= 683; break; // 7%
3786 case 31: enchant_id
= 3036; break; // 14%
3787 case 33: enchant_id
= 3037; break; // 20%
3789 case 40: enchant_id
= 3041; break; // 0%
3790 case 42: enchant_id
= 1664; break; // 7%
3791 case 45: enchant_id
= 3039; break; // 14%
3792 case 48: enchant_id
= 3040; break; // 20%
3794 case 49: enchant_id
= 3044; break; // 0%
3795 case 52: enchant_id
= 2632; break; // 7%
3796 case 55: enchant_id
= 3042; break; // 14%
3797 case 58: enchant_id
= 3043; break; // 20%
3799 case 62: enchant_id
= 2633; break; // 0%
3800 case 66: enchant_id
= 3018; break; // 7%
3801 case 70: enchant_id
= 3019; break; // 14%
3802 case 74: enchant_id
= 3020; break; // 20%
3804 sLog
.outError("Spell::EffectEnchantItemTmp: Damage %u not handled in S'RW",enchnting_damage
);
3811 sLog
.outError("Spell %u Effect %u (SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY) have 0 as enchanting id",m_spellInfo
->Id
,i
);
3815 SpellItemEnchantmentEntry
const *pEnchant
= sSpellItemEnchantmentStore
.LookupEntry(enchant_id
);
3818 sLog
.outError("Spell %u Effect %u (SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY) have not existed enchanting id %u ",m_spellInfo
->Id
,i
,enchant_id
);
3822 // select enchantment duration
3825 // rogue family enchantments exception by duration
3826 if(m_spellInfo
->Id
==38615)
3827 duration
= 1800; // 30 mins
3828 // other rogue family enchantments always 1 hour (some have spell damage=0, but some have wrong data in EffBasePoints)
3829 else if(m_spellInfo
->SpellFamilyName
==SPELLFAMILY_ROGUE
)
3830 duration
= 3600; // 1 hour
3831 // shaman family enchantments
3832 else if(m_spellInfo
->SpellFamilyName
==SPELLFAMILY_SHAMAN
)
3833 duration
= 1800; // 30 mins
3834 // other cases with this SpellVisual already selected
3835 else if(m_spellInfo
->SpellVisual
==215)
3836 duration
= 1800; // 30 mins
3837 // some fishing pole bonuses
3838 else if(m_spellInfo
->SpellVisual
==563)
3839 duration
= 600; // 10 mins
3840 // shaman rockbiter enchantments
3841 else if(m_spellInfo
->SpellVisual
==0)
3842 duration
= 1800; // 30 mins
3843 else if(m_spellInfo
->Id
==29702)
3844 duration
= 300; // 5 mins
3845 else if(m_spellInfo
->Id
==37360)
3846 duration
= 300; // 5 mins
3849 duration
= 3600; // 1 hour
3851 // item can be in trade slot and have owner diff. from caster
3852 Player
* item_owner
= itemTarget
->GetOwner();
3856 if(item_owner
!=p_caster
&& p_caster
->GetSession()->GetSecurity() > SEC_PLAYER
&& sWorld
.getConfig(CONFIG_GM_LOG_TRADE
) )
3857 sLog
.outCommand("GM %s (Account: %u) enchanting(temp): %s (Entry: %d) for player: %s (Account: %u)",
3858 p_caster
->GetName(),p_caster
->GetSession()->GetAccountId(),
3859 itemTarget
->GetProto()->Name1
,itemTarget
->GetEntry(),
3860 item_owner
->GetName(),item_owner
->GetSession()->GetAccountId());
3862 // remove old enchanting before applying new if equipped
3863 item_owner
->ApplyEnchantment(itemTarget
,TEMP_ENCHANTMENT_SLOT
,false);
3865 itemTarget
->SetEnchantment(TEMP_ENCHANTMENT_SLOT
, enchant_id
, duration
*1000, 0);
3867 // add new enchanting if equipped
3868 item_owner
->ApplyEnchantment(itemTarget
,TEMP_ENCHANTMENT_SLOT
,true);
3871 void Spell::EffectTameCreature(uint32
/*i*/)
3873 if(m_caster
->GetPetGUID())
3879 if(unitTarget
->GetTypeId() == TYPEID_PLAYER
)
3882 Creature
* creatureTarget
= (Creature
*)unitTarget
;
3884 if(creatureTarget
->isPet())
3887 if(m_caster
->getClass() != CLASS_HUNTER
)
3890 // cast finish successfully
3891 //SendChannelUpdate(0);
3894 Pet
* pet
= m_caster
->CreateTamedPetFrom(creatureTarget
,m_spellInfo
->Id
);
3896 // kill original creature
3897 creatureTarget
->setDeathState(JUST_DIED
);
3898 creatureTarget
->RemoveCorpse();
3899 creatureTarget
->SetHealth(0); // just for nice GM-mode view
3901 // prepare visual effect for levelup
3902 pet
->SetUInt32Value(UNIT_FIELD_LEVEL
,creatureTarget
->getLevel()-1);
3905 MapManager::Instance().GetMap(pet
->GetMapId(), pet
)->Add((Creature
*)pet
);
3907 // visual effect for levelup
3908 pet
->SetUInt32Value(UNIT_FIELD_LEVEL
,creatureTarget
->getLevel());
3910 // caster have pet now
3911 m_caster
->SetPet(pet
);
3913 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
3915 pet
->SavePetToDB(PET_SAVE_AS_CURRENT
);
3916 ((Player
*)m_caster
)->PetSpellInitialize();
3920 void Spell::EffectSummonPet(uint32 i
)
3922 uint32 petentry
= m_spellInfo
->EffectMiscValue
[i
];
3924 Pet
*OldSummon
= m_caster
->GetPet();
3926 // if pet requested type already exist
3929 if(petentry
== 0 || OldSummon
->GetEntry() == petentry
)
3931 // pet in corpse state can't be summoned
3932 if( OldSummon
->isDead() )
3935 MapManager::Instance().GetMap(OldSummon
->GetMapId(), OldSummon
)->Remove((Creature
*)OldSummon
,false);
3936 OldSummon
->SetMapId(m_caster
->GetMapId());
3939 m_caster
->GetClosePoint(px
, py
, pz
, OldSummon
->GetObjectSize());
3941 OldSummon
->Relocate(px
, py
, pz
, OldSummon
->GetOrientation());
3942 MapManager::Instance().GetMap(m_caster
->GetMapId(), m_caster
)->Add((Creature
*)OldSummon
);
3944 if(m_caster
->GetTypeId() == TYPEID_PLAYER
&& OldSummon
->isControlled() )
3946 ((Player
*)m_caster
)->PetSpellInitialize();
3951 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
3952 ((Player
*)m_caster
)->RemovePet(OldSummon
,(OldSummon
->getPetType()==HUNTER_PET
? PET_SAVE_AS_DELETED
: PET_SAVE_NOT_IN_SLOT
),false);
3957 Pet
* NewSummon
= new Pet
;
3959 // petentry==0 for hunter "call pet" (current pet summoned if any)
3960 if(NewSummon
->LoadPetFromDB(m_caster
,petentry
))
3962 if(NewSummon
->getPetType()==SUMMON_PET
)
3964 // Remove Demonic Sacrifice auras (known pet)
3965 Unit::AuraList
const& auraClassScripts
= m_caster
->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS
);
3966 for(Unit::AuraList::const_iterator itr
= auraClassScripts
.begin();itr
!=auraClassScripts
.end();)
3968 if((*itr
)->GetModifier()->m_miscvalue
==2228)
3970 m_caster
->RemoveAurasDueToSpell((*itr
)->GetId());
3971 itr
= auraClassScripts
.begin();
3981 // not error in case fail hunter call pet
3988 CreatureInfo
const* cInfo
= sCreatureStorage
.LookupEntry
<CreatureInfo
>(petentry
);
3992 sLog
.outError("EffectSummonPet: creature entry %u not found.",petentry
);
3997 Map
*map
= m_caster
->GetMap();
3998 uint32 pet_number
= objmgr
.GeneratePetNumber();
3999 if(!NewSummon
->Create(objmgr
.GenerateLowGuid(HIGHGUID_PET
), map
, petentry
, pet_number
))
4006 m_caster
->GetClosePoint(px
, py
, pz
, NewSummon
->GetObjectSize());
4008 NewSummon
->Relocate(px
, py
, pz
, m_caster
->GetOrientation());
4010 if(!NewSummon
->IsPositionValid())
4012 sLog
.outError("ERROR: Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %d Y: ^%d)", NewSummon
->GetGUIDLow(), NewSummon
->GetEntry(), NewSummon
->GetPositionX(), NewSummon
->GetPositionY());
4017 uint32 petlevel
= m_caster
->getLevel();
4018 NewSummon
->setPetType(SUMMON_PET
);
4020 uint32 faction
= m_caster
->getFaction();
4021 if(m_caster
->GetTypeId() == TYPEID_UNIT
)
4023 if ( ((Creature
*)m_caster
)->isTotem() )
4024 NewSummon
->GetCharmInfo()->SetReactState(REACT_AGGRESSIVE
);
4026 NewSummon
->GetCharmInfo()->SetReactState(REACT_DEFENSIVE
);
4029 NewSummon
->SetUInt64Value(UNIT_FIELD_SUMMONEDBY
, m_caster
->GetGUID());
4030 NewSummon
->SetUInt64Value(UNIT_FIELD_CREATEDBY
, m_caster
->GetGUID());
4031 NewSummon
->SetUInt32Value(UNIT_NPC_FLAGS
, 0);
4032 NewSummon
->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE
, faction
);
4033 NewSummon
->SetUInt32Value(UNIT_FIELD_BYTES_0
,2048);
4034 NewSummon
->SetUInt32Value(UNIT_FIELD_BYTES_1
,0);
4035 NewSummon
->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP
,time(NULL
));
4036 NewSummon
->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE
,0);
4037 NewSummon
->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP
,1000);
4038 NewSummon
->SetUInt32Value(UNIT_CREATED_BY_SPELL
, m_spellInfo
->Id
);
4040 NewSummon
->GetCharmInfo()->SetPetNumber(pet_number
, true);
4041 // this enables pet details window (Shift+P)
4043 // this enables popup window (pet dismiss, cancel), hunter pet additional flags set later
4044 NewSummon
->SetUInt32Value(UNIT_FIELD_FLAGS
,UNIT_FLAG_PVP_ATTACKABLE
);
4046 NewSummon
->InitStatsForLevel( petlevel
);
4047 NewSummon
->InitPetCreateSpells();
4049 if(NewSummon
->getPetType()==SUMMON_PET
)
4051 // Remove Demonic Sacrifice auras (new pet)
4052 Unit::AuraList
const& auraClassScripts
= m_caster
->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS
);
4053 for(Unit::AuraList::const_iterator itr
= auraClassScripts
.begin();itr
!=auraClassScripts
.end();)
4055 if((*itr
)->GetModifier()->m_miscvalue
==2228)
4057 m_caster
->RemoveAurasDueToSpell((*itr
)->GetId());
4058 itr
= auraClassScripts
.begin();
4064 // generate new name for summon pet
4065 std::string new_name
=objmgr
.GeneratePetName(petentry
);
4066 if(!new_name
.empty())
4067 NewSummon
->SetName(new_name
);
4069 else if(NewSummon
->getPetType()==HUNTER_PET
)
4070 NewSummon
->SetByteValue(UNIT_FIELD_BYTES_2
, 2, UNIT_RENAME_NOT_ALLOWED
);
4072 NewSummon
->AIM_Initialize();
4073 NewSummon
->SetHealth(NewSummon
->GetMaxHealth());
4074 NewSummon
->SetPower(POWER_MANA
, NewSummon
->GetMaxPower(POWER_MANA
));
4076 map
->Add((Creature
*)NewSummon
);
4078 m_caster
->SetPet(NewSummon
);
4079 sLog
.outDebug("New Pet has guid %u", NewSummon
->GetGUIDLow());
4081 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
4083 NewSummon
->SavePetToDB(PET_SAVE_AS_CURRENT
);
4084 ((Player
*)m_caster
)->PetSpellInitialize();
4088 void Spell::EffectLearnPetSpell(uint32 i
)
4090 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
4093 Player
*_player
= (Player
*)m_caster
;
4095 Pet
*pet
= _player
->GetPet();
4101 SpellEntry
const *learn_spellproto
= sSpellStore
.LookupEntry(m_spellInfo
->EffectTriggerSpell
[i
]);
4102 if(!learn_spellproto
)
4105 pet
->SetTP(pet
->m_TrainingPoints
- pet
->GetTPForSpell(learn_spellproto
->Id
));
4106 pet
->learnSpell(learn_spellproto
->Id
);
4108 pet
->SavePetToDB(PET_SAVE_AS_CURRENT
);
4109 _player
->PetSpellInitialize();
4112 void Spell::EffectTaunt(uint32
/*i*/)
4114 // this effect use before aura Taunt apply for prevent taunt already attacking target
4115 // for spell as marked "non effective at already attacking target"
4116 if(unitTarget
&& unitTarget
->GetTypeId() != TYPEID_PLAYER
)
4118 if(unitTarget
->getVictim()==m_caster
)
4120 SendCastResult(SPELL_FAILED_DONT_REPORT
);
4125 // Also use this effect to set the taunter's threat to the taunted creature's highest value
4126 if(unitTarget
->CanHaveThreatList() && unitTarget
->getThreatManager().getCurrentVictim())
4127 unitTarget
->getThreatManager().addThreat(m_caster
,unitTarget
->getThreatManager().getCurrentVictim()->getThreat());
4130 void Spell::EffectWeaponDmg(uint32 i
)
4134 if(!unitTarget
->isAlive())
4137 // multiple weapon dmg effect workaround
4138 // execute only the last weapon damage
4139 // and handle all effects at once
4140 for (int j
= 0; j
< 3; j
++)
4142 switch(m_spellInfo
->Effect
[j
])
4144 case SPELL_EFFECT_WEAPON_DAMAGE
:
4145 case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL
:
4146 case SPELL_EFFECT_NORMALIZED_WEAPON_DMG
:
4147 case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE
:
4148 if (j
< i
) // we must calculate only at last weapon effect
4154 // some spell specific modifiers
4155 bool customBonusDamagePercentMod
= false;
4156 float bonusDamagePercentMod
= 1.0f
; // applied to fixed effect damage bonus if set customBonusDamagePercentMod
4157 float weaponDamagePercentMod
= 1.0f
; // applied to weapon damage (and to fixed effect damage bonus if customBonusDamagePercentMod not set
4158 float totalDamagePercentMod
= 1.0f
; // applied to final bonus+weapon damage
4159 bool normalized
= false;
4161 int32 spell_bonus
= 0; // bonus specific for spell
4162 switch(m_spellInfo
->SpellFamilyName
)
4164 case SPELLFAMILY_WARRIOR
:
4166 // Whirlwind, single only spell with 2 weapon white damage apply if have
4167 if(m_caster
->GetTypeId()==TYPEID_PLAYER
&& (m_spellInfo
->SpellFamilyFlags
& 0x00000400000000LL
))
4169 if(((Player
*)m_caster
)->GetWeaponForAttack(OFF_ATTACK
,true))
4170 spell_bonus
+= m_caster
->CalculateDamage (OFF_ATTACK
, normalized
);
4172 // Devastate bonus and sunder armor refresh
4173 else if(m_spellInfo
->SpellVisual
== 671 && m_spellInfo
->SpellIconID
== 1508)
4175 customBonusDamagePercentMod
= true;
4176 bonusDamagePercentMod
= 0.0f
; // only applied if auras found
4178 Unit::AuraList
const& list
= unitTarget
->GetAurasByType(SPELL_AURA_MOD_RESISTANCE
);
4179 for(Unit::AuraList::const_iterator itr
=list
.begin();itr
!=list
.end();++itr
)
4181 SpellEntry
const *proto
= (*itr
)->GetSpellProto();
4182 if(proto
->SpellVisual
== 406 && proto
->SpellIconID
== 565)
4184 int32 duration
= GetSpellDuration(proto
);
4185 (*itr
)->SetAuraDuration(duration
);
4186 (*itr
)->UpdateAuraDuration();
4187 bonusDamagePercentMod
+= 1.0f
; // +100%
4193 case SPELLFAMILY_ROGUE
:
4196 if(m_spellInfo
->SpellFamilyFlags
& 0x00000200LL
)
4198 customBonusDamagePercentMod
= true;
4199 bonusDamagePercentMod
= 2.5f
; // 250%
4201 // Mutilate (for each hand)
4202 else if(m_spellInfo
->SpellFamilyFlags
& 0x600000000LL
)
4206 if(unitTarget
->HasAuraState(AURA_STATE_DEADLY_POISON
))
4211 Unit::AuraMap
const& auras
= unitTarget
->GetAuras();
4212 for(Unit::AuraMap::const_iterator itr
= auras
.begin(); itr
!=auras
.end(); ++itr
)
4214 if(itr
->second
->GetSpellProto()->Dispel
== DISPEL_POISON
)
4223 totalDamagePercentMod
*= 1.5f
; // 150% if poisoned
4227 case SPELLFAMILY_PALADIN
:
4229 // Seal of Command - receive benefit from Spell Damage and Healing
4230 if(m_spellInfo
->SpellFamilyFlags
& 0x00000002000000LL
)
4232 spell_bonus
+= int32(0.20f
*m_caster
->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo
)));
4233 spell_bonus
+= int32(0.29f
*m_caster
->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo
), unitTarget
));
4237 case SPELLFAMILY_SHAMAN
:
4239 // Skyshatter Harness item set bonus
4241 if(m_spellInfo
->SpellFamilyFlags
& 0x001000000000LL
)
4243 Unit::AuraList
const& m_OverrideClassScript
= m_caster
->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS
);
4244 for(Unit::AuraList::const_iterator i
= m_OverrideClassScript
.begin(); i
!= m_OverrideClassScript
.end(); ++i
)
4246 // Stormstrike AP Buff
4247 if ( (*i
)->GetModifier()->m_miscvalue
== 5634 )
4249 m_caster
->CastSpell(m_caster
,38430,true,NULL
,*i
);
4257 int32 fixed_bonus
= 0;
4258 for (int j
= 0; j
< 3; j
++)
4260 switch(m_spellInfo
->Effect
[j
])
4262 case SPELL_EFFECT_WEAPON_DAMAGE
:
4263 case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL
:
4264 fixed_bonus
+= CalculateDamage(j
,unitTarget
);
4266 case SPELL_EFFECT_NORMALIZED_WEAPON_DMG
:
4267 fixed_bonus
+= CalculateDamage(j
,unitTarget
);
4270 case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE
:
4271 weaponDamagePercentMod
*= float(CalculateDamage(j
,unitTarget
)) / 100.0f
;
4273 // applied only to prev.effects fixed damage
4274 if(customBonusDamagePercentMod
)
4275 fixed_bonus
= int32(fixed_bonus
*bonusDamagePercentMod
);
4277 fixed_bonus
= int32(fixed_bonus
*weaponDamagePercentMod
);
4280 break; // not weapon damage effect, just skip
4284 // non-weapon damage
4285 int32 bonus
= spell_bonus
+ fixed_bonus
;
4287 // apply to non-weapon bonus weapon total pct effect, weapon total flat effect included in weapon damage
4291 switch(m_attackType
)
4294 case BASE_ATTACK
: unitMod
= UNIT_MOD_DAMAGE_MAINHAND
; break;
4295 case OFF_ATTACK
: unitMod
= UNIT_MOD_DAMAGE_OFFHAND
; break;
4296 case RANGED_ATTACK
: unitMod
= UNIT_MOD_DAMAGE_RANGED
; break;
4299 float weapon_total_pct
= m_caster
->GetModifierValue(unitMod
, TOTAL_PCT
);
4300 bonus
= int32(bonus
*weapon_total_pct
);
4303 // + weapon damage with applied weapon% dmg to base weapon damage in call
4304 bonus
+= int32(m_caster
->CalculateDamage(m_attackType
, normalized
)*weaponDamagePercentMod
);
4307 bonus
= int32(bonus
*totalDamagePercentMod
);
4309 // prevent negative damage
4310 uint32 eff_damage
= uint32(bonus
> 0 ? bonus
: 0);
4312 const uint32 nohitMask
= HITINFO_ABSORB
| HITINFO_RESIST
| HITINFO_MISS
;
4315 VictimState victimState
= VICTIMSTATE_NORMAL
;
4316 uint32 blocked_dmg
= 0;
4317 uint32 absorbed_dmg
= 0;
4318 uint32 resisted_dmg
= 0;
4319 CleanDamage cleanDamage
= CleanDamage(0, BASE_ATTACK
, MELEE_HIT_NORMAL
);
4321 m_caster
->DoAttackDamage(unitTarget
, &eff_damage
, &cleanDamage
, &blocked_dmg
, m_spellSchoolMask
, &hitInfo
, &victimState
, &absorbed_dmg
, &resisted_dmg
, m_attackType
, m_spellInfo
, m_IsTriggeredSpell
);
4323 if ((hitInfo
& nohitMask
) && m_attackType
!= RANGED_ATTACK
) // not send ranged miss/etc
4324 m_caster
->SendAttackStateUpdate(hitInfo
& nohitMask
, unitTarget
, 1, m_spellSchoolMask
, eff_damage
, absorbed_dmg
, resisted_dmg
, VICTIMSTATE_NORMAL
, blocked_dmg
);
4326 bool criticalhit
= (hitInfo
& HITINFO_CRITICALHIT
);
4327 m_caster
->SendSpellNonMeleeDamageLog(unitTarget
, m_spellInfo
->Id
, eff_damage
, m_spellSchoolMask
, absorbed_dmg
, resisted_dmg
, false, blocked_dmg
, criticalhit
);
4329 if (eff_damage
> (absorbed_dmg
+ resisted_dmg
+ blocked_dmg
))
4331 eff_damage
-= (absorbed_dmg
+ resisted_dmg
+ blocked_dmg
);
4335 cleanDamage
.damage
+= eff_damage
;
4339 // SPELL_SCHOOL_NORMAL use for weapon-like threat and rage calculation
4340 m_caster
->DealDamage(unitTarget
, eff_damage
, &cleanDamage
, SPELL_DIRECT_DAMAGE
, SPELL_SCHOOL_MASK_NORMAL
, NULL
, true);
4343 if(m_spellInfo
->SpellFamilyName
==SPELLFAMILY_ROGUE
&& (m_spellInfo
->SpellFamilyFlags
& 0x2000000))
4345 if(m_caster
->GetTypeId()==TYPEID_PLAYER
)
4346 ((Player
*)m_caster
)->AddComboPoints(unitTarget
, 1);
4350 if(m_spellInfo
->SpellFamilyName
==SPELLFAMILY_DRUID
&& (m_spellInfo
->SpellFamilyFlags
==0x0000040000000000LL
))
4352 if(m_caster
->GetTypeId()==TYPEID_PLAYER
)
4353 ((Player
*)m_caster
)->AddComboPoints(unitTarget
,1);
4357 if(m_attackType
== RANGED_ATTACK
&& m_caster
->GetTypeId() == TYPEID_PLAYER
)
4359 Item
*pItem
= ((Player
*)m_caster
)->GetWeaponForAttack( RANGED_ATTACK
);
4361 // wands don't have ammo
4362 if(!pItem
|| pItem
->IsBroken() || pItem
->GetProto()->SubClass
==ITEM_SUBCLASS_WEAPON_WAND
)
4365 if( pItem
->GetProto()->InventoryType
== INVTYPE_THROWN
)
4367 if(pItem
->GetMaxStackCount()==1)
4369 // decrease durability for non-stackable throw weapon
4370 ((Player
*)m_caster
)->DurabilityPointLossForEquipSlot(EQUIPMENT_SLOT_RANGED
);
4374 // decrease items amount for stackable throw weapon
4376 ((Player
*)m_caster
)->DestroyItemCount( pItem
, count
, true);
4379 else if(uint32 ammo
= ((Player
*)m_caster
)->GetUInt32Value(PLAYER_AMMO_ID
))
4380 ((Player
*)m_caster
)->DestroyItemCount(ammo
, 1, true);
4384 void Spell::EffectThreat(uint32
/*i*/)
4386 if(!unitTarget
|| !unitTarget
->isAlive() || !m_caster
->isAlive())
4389 if(!unitTarget
->CanHaveThreatList())
4392 unitTarget
->AddThreat(m_caster
, float(damage
));
4395 void Spell::EffectHealMaxHealth(uint32
/*i*/)
4399 if(!unitTarget
->isAlive())
4402 uint32 heal
= m_caster
->GetMaxHealth();
4404 int32 gain
= unitTarget
->ModifyHealth(heal
);
4405 unitTarget
->getHostilRefManager().threatAssist(m_caster
, float(gain
) * 0.5f
, m_spellInfo
);
4407 m_caster
->SendHealSpellLog(unitTarget
, m_spellInfo
->Id
, heal
);
4410 void Spell::EffectInterruptCast(uint32
/*i*/)
4414 if(!unitTarget
->isAlive())
4417 // TODO: not all spells that used this effect apply cooldown at school spells
4418 // also exist case: apply cooldown to interrupted cast only and to all spells
4419 for (uint32 i
= CURRENT_FIRST_NON_MELEE_SPELL
; i
< CURRENT_MAX_SPELL
; i
++)
4421 if (unitTarget
->m_currentSpells
[i
])
4423 // check if we can interrupt spell
4424 if ( unitTarget
->m_currentSpells
[i
]->m_spellInfo
->InterruptFlags
& SPELL_INTERRUPT_FLAG_INTERRUPT
&& unitTarget
->m_currentSpells
[i
]->m_spellInfo
->PreventionType
== SPELL_PREVENTION_TYPE_SILENCE
)
4426 unitTarget
->ProhibitSpellScholl(GetSpellSchoolMask(unitTarget
->m_currentSpells
[i
]->m_spellInfo
), GetSpellDuration(m_spellInfo
));
4427 unitTarget
->InterruptSpell(i
,false);
4433 void Spell::EffectSummonObjectWild(uint32 i
)
4435 uint32 gameobject_id
= m_spellInfo
->EffectMiscValue
[i
];
4437 GameObject
* pGameObj
= new GameObject
;
4439 WorldObject
* target
= focusObject
;
4444 if(m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
4446 x
= m_targets
.m_destX
;
4447 y
= m_targets
.m_destY
;
4448 z
= m_targets
.m_destZ
;
4451 m_caster
->GetClosePoint(x
,y
,z
,DEFAULT_WORLD_OBJECT_SIZE
);
4453 Map
*map
= target
->GetMap();
4455 if(!pGameObj
->Create(objmgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), gameobject_id
, map
,
4456 x
, y
, z
, target
->GetOrientation(), 0, 0, 0, 0, 100, 1))
4462 int32 duration
= GetSpellDuration(m_spellInfo
);
4463 pGameObj
->SetRespawnTime(duration
> 0 ? duration
/1000 : 0);
4464 pGameObj
->SetSpellId(m_spellInfo
->Id
);
4466 if(pGameObj
->GetGoType() != GAMEOBJECT_TYPE_FLAGDROP
) // make dropped flag clickable for other players (not set owner guid (created by) for this)...
4467 m_caster
->AddGameObject(pGameObj
);
4470 if(pGameObj
->GetMapId() == 489 && pGameObj
->GetGoType() == GAMEOBJECT_TYPE_FLAGDROP
) //WS
4472 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
4474 Player
*pl
= (Player
*)m_caster
;
4475 BattleGround
* bg
= ((Player
*)m_caster
)->GetBattleGround();
4476 if(bg
&& bg
->GetTypeID()==BATTLEGROUND_WS
&& bg
->GetStatus() == STATUS_IN_PROGRESS
)
4478 uint32 team
= ALLIANCE
;
4480 if(pl
->GetTeam() == team
)
4483 ((BattleGroundWS
*)bg
)->SetDroppedFlagGUID(pGameObj
->GetGUID(),team
);
4488 if(pGameObj
->GetMapId() == 566 && pGameObj
->GetGoType() == GAMEOBJECT_TYPE_FLAGDROP
) //EY
4490 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
4492 BattleGround
* bg
= ((Player
*)m_caster
)->GetBattleGround();
4493 if(bg
&& bg
->GetTypeID()==BATTLEGROUND_EY
&& bg
->GetStatus() == STATUS_IN_PROGRESS
)
4495 ((BattleGroundEY
*)bg
)->SetDroppedFlagGUID(pGameObj
->GetGUID());
4500 if(uint32 linkedEntry
= pGameObj
->GetLinkedGameObjectEntry())
4502 GameObject
* linkedGO
= new GameObject
;
4503 if(linkedGO
->Create(objmgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), linkedEntry
, map
,
4504 x
, y
, z
, target
->GetOrientation(), 0, 0, 0, 0, 100, 1))
4506 linkedGO
->SetRespawnTime(duration
> 0 ? duration
/1000 : 0);
4507 linkedGO
->SetSpellId(m_spellInfo
->Id
);
4509 m_caster
->AddGameObject(linkedGO
);
4521 void Spell::EffectScriptEffect(uint32 effIndex
)
4523 // TODO: we must implement hunter pet summon at login there (spell 6962)
4526 switch(m_spellInfo
->Id
)
4531 if(!itemTarget
&& m_caster
->GetTypeId()!=TYPEID_PLAYER
)
4534 uint32 spell_id
= 0;
4537 case 1: spell_id
= 8854; break;
4538 default: spell_id
= 8855; break;
4541 m_caster
->CastSpell(m_caster
,spell_id
,true,NULL
);
4545 // Healthstone creating spells
4555 Unit::AuraList
const& mDummyAuras
= unitTarget
->GetAurasByType(SPELL_AURA_DUMMY
);
4556 for(Unit::AuraList::const_iterator i
= mDummyAuras
.begin();i
!= mDummyAuras
.end(); ++i
)
4558 if((*i
)->GetId() == 18692)
4563 else if((*i
)->GetId() == 18693)
4570 static uint32
const itypes
[6][3] = {
4571 { 5512,19004,19005}, // Minor Healthstone
4572 { 5511,19006,19007}, // Lesser Healthstone
4573 { 5509,19008,19009}, // Healthstone
4574 { 5510,19010,19011}, // Greater Healthstone
4575 { 9421,19012,19013}, // Major Healthstone
4576 {22103,22104,22105} // Master Healthstone
4579 switch(m_spellInfo
->Id
)
4581 case 6201: itemtype
=itypes
[0][rank
];break; // Minor Healthstone
4582 case 6202: itemtype
=itypes
[1][rank
];break; // Lesser Healthstone
4583 case 5699: itemtype
=itypes
[2][rank
];break; // Healthstone
4584 case 11729: itemtype
=itypes
[3][rank
];break; // Greater Healthstone
4585 case 11730: itemtype
=itypes
[4][rank
];break; // Major Healthstone
4586 case 27230: itemtype
=itypes
[5][rank
];break; // Master Healthstone
4590 DoCreateItem( effIndex
, itemtype
);
4593 // Brittle Armor - need remove one 24575 Brittle Armor aura
4595 unitTarget
->RemoveSingleAuraFromStack(24575, 0);
4596 unitTarget
->RemoveSingleAuraFromStack(24575, 1);
4598 // Mercurial Shield - need remove one 26464 Mercurial Shield aura
4600 unitTarget
->RemoveSingleAuraFromStack(26464, 0);
4602 // Orb teleport spells
4616 switch(m_spellInfo
->Id
)
4618 case 25140: spellid
= 32571; break;
4619 case 25143: spellid
= 32572; break;
4620 case 25650: spellid
= 30140; break;
4621 case 25652: spellid
= 30141; break;
4622 case 29128: spellid
= 32568; break;
4623 case 29129: spellid
= 32569; break;
4624 case 35376: spellid
= 25649; break;
4625 case 35727: spellid
= 35730; break;
4630 unitTarget
->CastSpell(unitTarget
,spellid
,false);
4634 // Shadow Flame (All script effects, not just end ones to prevent player from dodging the last triggered spell)
4649 if(!unitTarget
|| !unitTarget
->isAlive())
4652 // Onyxia Scale Cloak
4653 if(unitTarget
->GetDummyAura(22683))
4657 m_caster
->CastSpell(unitTarget
, 22682, true);
4662 // Summon Black Qiraji Battle Tank
4668 // Prevent stacking of mounts
4669 unitTarget
->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED
);
4671 // Two separate mounts depending on area id (allows use both in and out of specific instance)
4672 if (unitTarget
->GetAreaId() == 3428)
4673 unitTarget
->CastSpell(unitTarget
, 25863, false);
4675 unitTarget
->CastSpell(unitTarget
, 26655, false);
4678 // Piccolo of the Flaming Fire
4681 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
4683 unitTarget
->HandleEmoteCommand(EMOTE_STATE_DANCE
);
4692 unitTarget
->CastSpell(unitTarget
, 28694, true);
4701 // 25% chance of casting a random buff
4702 if(roll_chance_i(75))
4705 // triggered spells are 28703 to 28707
4706 // Note: some sources say, that there was the possibility of
4707 // receiving a debuff. However, this seems to be removed by a patch.
4708 const uint32 spellid
= 28703;
4710 // don't overwrite an existing aura
4711 for(uint8 i
=0; i
<5; i
++)
4712 if(unitTarget
->HasAura(spellid
+i
, 0))
4714 unitTarget
->CastSpell(unitTarget
, spellid
+urand(0, 4), true);
4723 // 25% chance of casting Nightmare Pollen
4724 if(roll_chance_i(75))
4726 unitTarget
->CastSpell(unitTarget
, 28721, true);
4730 // Mirren's Drinking Hat
4734 switch ( urand(1,6) )
4736 case 1: case 2: case 3: item
= 23584; break;// Loch Modan Lager
4737 case 4: case 5: item
= 23585; break;// Stouthammer Lite
4738 case 6: item
= 23586; break;// Aerie Peak Pale Ale
4741 DoCreateItem(effIndex
,item
);
4747 // Removes snares and roots.
4748 uint32 mechanic_mask
= (1<<MECHANIC_ROOT
) | (1<<MECHANIC_SNARE
);
4749 Unit::AuraMap
& Auras
= unitTarget
->GetAuras();
4750 for(Unit::AuraMap::iterator iter
= Auras
.begin(), next
; iter
!= Auras
.end(); iter
= next
)
4754 Aura
*aur
= iter
->second
;
4755 if (!aur
->IsPositive()) //only remove negative spells
4757 // check for mechanic mask
4758 if(GetSpellMechanicMask(aur
->GetSpellProto(), aur
->GetEffIndex()) & mechanic_mask
)
4760 unitTarget
->RemoveAurasDueToSpell(aur
->GetId());
4764 next
= Auras
.begin();
4770 case 41126: // Flame Crash
4775 unitTarget
->CastSpell(unitTarget
, 41131, true);
4778 case 44876: // Force Cast - Portal Effect: Sunwell Isle
4783 unitTarget
->CastSpell(unitTarget
, 44870, true);
4787 // Goblin Weather Machine
4809 unitTarget
->CastSpell(unitTarget
, spellId
, true);
4815 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
4818 ((Player
*)unitTarget
)->ModifyMoney(50000000);
4824 if( m_spellInfo
->SpellFamilyName
== SPELLFAMILY_PALADIN
)
4826 switch(m_spellInfo
->SpellFamilyFlags
)
4831 if(!unitTarget
|| !unitTarget
->isAlive())
4833 uint32 spellId2
= 0;
4835 // all seals have aura dummy
4836 Unit::AuraList
const& m_dummyAuras
= m_caster
->GetAurasByType(SPELL_AURA_DUMMY
);
4837 for(Unit::AuraList::const_iterator itr
= m_dummyAuras
.begin(); itr
!= m_dummyAuras
.end(); ++itr
)
4839 SpellEntry
const *spellInfo
= (*itr
)->GetSpellProto();
4841 // search seal (all seals have judgement's aura dummy spell id in 2 effect
4842 if ( !spellInfo
|| !IsSealSpell((*itr
)->GetSpellProto()) || (*itr
)->GetEffIndex() != 2 )
4845 // must be calculated base at raw base points in spell proto, GetModifier()->m_value for S.Righteousness modified by SPELLMOD_DAMAGE
4846 spellId2
= (*itr
)->GetSpellProto()->EffectBasePoints
[2]+1;
4851 // found, remove seal
4852 m_caster
->RemoveAurasDueToSpell((*itr
)->GetId());
4854 // Sanctified Judgement
4855 Unit::AuraList
const& m_auras
= m_caster
->GetAurasByType(SPELL_AURA_DUMMY
);
4856 for(Unit::AuraList::const_iterator i
= m_auras
.begin(); i
!= m_auras
.end(); ++i
)
4858 if ((*i
)->GetSpellProto()->SpellIconID
== 205 && (*i
)->GetSpellProto()->Attributes
== 0x01D0LL
)
4860 int32 chance
= (*i
)->GetModifier()->m_amount
;
4861 if ( roll_chance_i(chance
) )
4863 int32 mana
= spellInfo
->manaCost
;
4864 if ( Player
* modOwner
= m_caster
->GetSpellModOwner() )
4865 modOwner
->ApplySpellMod(spellInfo
->Id
, SPELLMOD_COST
, mana
);
4866 mana
= int32(mana
* 0.8f
);
4867 m_caster
->CastCustomSpell(m_caster
,31930,&mana
,NULL
,NULL
,true,NULL
,*i
);
4876 m_caster
->CastSpell(unitTarget
,spellId2
,true);
4882 // normal DB scripted effect
4886 sLog
.outDebug("Spell ScriptStart spellid %u in EffectScriptEffect ", m_spellInfo
->Id
);
4887 sWorld
.ScriptsStart(sSpellScripts
, m_spellInfo
->Id
, m_caster
, unitTarget
);
4890 void Spell::EffectSanctuary(uint32
/*i*/)
4894 //unitTarget->CombatStop();
4896 unitTarget
->CombatStop();
4897 unitTarget
->getHostilRefManager().deleteReferences(); // stop all fighting
4898 // Vanish allows to remove all threat and cast regular stealth so other spells can be used
4899 if(m_spellInfo
->SpellFamilyName
== SPELLFAMILY_ROGUE
&& (m_spellInfo
->SpellFamilyFlags
& SPELLFAMILYFLAG_ROGUE_VANISH
))
4901 ((Player
*)m_caster
)->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT
);
4905 void Spell::EffectAddComboPoints(uint32
/*i*/)
4910 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
4916 ((Player
*)m_caster
)->AddComboPoints(unitTarget
, damage
);
4919 void Spell::EffectDuel(uint32 i
)
4921 if(!m_caster
|| !unitTarget
|| m_caster
->GetTypeId() != TYPEID_PLAYER
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
4924 Player
*caster
= (Player
*)m_caster
;
4925 Player
*target
= (Player
*)unitTarget
;
4927 // caster or target already have requested duel
4928 if( caster
->duel
|| target
->duel
|| !target
->GetSocial() || target
->GetSocial()->HasIgnore(caster
->GetGUIDLow()) )
4931 // Players can only fight a duel with each other outside (=not inside dungeons and not in capital cities)
4932 // Don't have to check the target's map since you cannot challenge someone across maps
4933 if( caster
->GetMapId() != 0 && caster
->GetMapId() != 1 && caster
->GetMapId() != 530)
4935 SendCastResult(SPELL_FAILED_NO_DUELING
); // Dueling isn't allowed here
4939 AreaTableEntry
const* casterAreaEntry
= GetAreaEntryByAreaID(caster
->GetZoneId());
4940 if(casterAreaEntry
&& (casterAreaEntry
->flags
& AREA_FLAG_CAPITAL
) )
4942 SendCastResult(SPELL_FAILED_NO_DUELING
); // Dueling isn't allowed here
4946 AreaTableEntry
const* targetAreaEntry
= GetAreaEntryByAreaID(target
->GetZoneId());
4947 if(targetAreaEntry
&& (targetAreaEntry
->flags
& AREA_FLAG_CAPITAL
) )
4949 SendCastResult(SPELL_FAILED_NO_DUELING
); // Dueling isn't allowed here
4953 //CREATE DUEL FLAG OBJECT
4954 GameObject
* pGameObj
= new GameObject
;
4956 uint32 gameobject_id
= m_spellInfo
->EffectMiscValue
[i
];
4958 Map
*map
= m_caster
->GetMap();
4959 if(!pGameObj
->Create(objmgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), gameobject_id
, map
,
4960 m_caster
->GetPositionX()+(unitTarget
->GetPositionX()-m_caster
->GetPositionX())/2 ,
4961 m_caster
->GetPositionY()+(unitTarget
->GetPositionY()-m_caster
->GetPositionY())/2 ,
4962 m_caster
->GetPositionZ(),
4963 m_caster
->GetOrientation(), 0, 0, 0, 0, 0, 1))
4969 pGameObj
->SetUInt32Value(GAMEOBJECT_FACTION
, m_caster
->getFaction() );
4970 pGameObj
->SetUInt32Value(GAMEOBJECT_LEVEL
, m_caster
->getLevel()+1 );
4971 int32 duration
= GetSpellDuration(m_spellInfo
);
4972 pGameObj
->SetRespawnTime(duration
> 0 ? duration
/1000 : 0);
4973 pGameObj
->SetSpellId(m_spellInfo
->Id
);
4975 m_caster
->AddGameObject(pGameObj
);
4980 WorldPacket
data(SMSG_DUEL_REQUESTED
, 16);
4981 data
<< pGameObj
->GetGUID();
4982 data
<< caster
->GetGUID();
4983 caster
->GetSession()->SendPacket(&data
);
4984 target
->GetSession()->SendPacket(&data
);
4987 DuelInfo
*duel
= new DuelInfo
;
4988 duel
->initiator
= caster
;
4989 duel
->opponent
= target
;
4990 duel
->startTime
= 0;
4991 duel
->startTimer
= 0;
4992 caster
->duel
= duel
;
4994 DuelInfo
*duel2
= new DuelInfo
;
4995 duel2
->initiator
= caster
;
4996 duel2
->opponent
= caster
;
4997 duel2
->startTime
= 0;
4998 duel2
->startTimer
= 0;
4999 target
->duel
= duel2
;
5001 caster
->SetUInt64Value(PLAYER_DUEL_ARBITER
,pGameObj
->GetGUID());
5002 target
->SetUInt64Value(PLAYER_DUEL_ARBITER
,pGameObj
->GetGUID());
5005 void Spell::EffectStuck(uint32
/*i*/)
5007 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5010 if(!sWorld
.getConfig(CONFIG_CAST_UNSTUCK
))
5013 Player
* pTarget
= (Player
*)unitTarget
;
5015 sLog
.outDebug("Spell Effect: Stuck");
5016 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());
5018 if(pTarget
->isInFlight())
5021 // homebind location is loaded always
5022 pTarget
->TeleportTo(pTarget
->m_homebindMapId
,pTarget
->m_homebindX
,pTarget
->m_homebindY
,pTarget
->m_homebindZ
,pTarget
->GetOrientation(), (unitTarget
==m_caster
? TELE_TO_SPELL
: 0));
5024 // Stuck spell trigger Hearthstone cooldown
5025 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(8690);
5028 Spell
spell(pTarget
,spellInfo
,true,0);
5029 spell
.SendSpellCooldown();
5032 void Spell::EffectSummonPlayer(uint32
/*i*/)
5034 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5037 // Evil Twin (ignore player summon, but hide this for summoner)
5038 if(unitTarget
->GetDummyAura(23445))
5042 m_caster
->GetClosePoint(x
,y
,z
,unitTarget
->GetObjectSize());
5044 ((Player
*)unitTarget
)->SetSummonPoint(m_caster
->GetMapId(),x
,y
,z
);
5046 WorldPacket
data(SMSG_SUMMON_REQUEST
, 8+4+4);
5047 data
<< uint64(m_caster
->GetGUID()); // summoner guid
5048 data
<< uint32(m_caster
->GetZoneId()); // summoner zone
5049 data
<< uint32(MAX_PLAYER_SUMMON_DELAY
*1000); // auto decline after msecs
5050 ((Player
*)unitTarget
)->GetSession()->SendPacket(&data
);
5053 static ScriptInfo
generateActivateCommand()
5056 si
.command
= SCRIPT_COMMAND_ACTIVATE_OBJECT
;
5060 void Spell::EffectActivateObject(uint32 effect_idx
)
5065 static ScriptInfo activateCommand
= generateActivateCommand();
5067 int32 delay_secs
= m_spellInfo
->EffectMiscValue
[effect_idx
];
5069 sWorld
.ScriptCommandStart(activateCommand
, delay_secs
, m_caster
, gameObjTarget
);
5072 void Spell::EffectSummonTotem(uint32 i
)
5075 switch(m_spellInfo
->EffectMiscValueB
[i
])
5077 case SUMMON_TYPE_TOTEM_SLOT1
: slot
= 0; break;
5078 case SUMMON_TYPE_TOTEM_SLOT2
: slot
= 1; break;
5079 case SUMMON_TYPE_TOTEM_SLOT3
: slot
= 2; break;
5080 case SUMMON_TYPE_TOTEM_SLOT4
: slot
= 3; break;
5081 // Battle standard case
5082 case SUMMON_TYPE_TOTEM
: slot
= 254; break;
5083 // jewelery statue case, like totem without slot
5084 case SUMMON_TYPE_GUARDIAN
: slot
= 255; break;
5088 if(slot
< MAX_TOTEM
)
5090 uint64 guid
= m_caster
->m_TotemSlot
[slot
];
5093 Creature
*OldTotem
= ObjectAccessor::GetCreature(*m_caster
, guid
);
5094 if(OldTotem
&& OldTotem
->isTotem())
5095 ((Totem
*)OldTotem
)->UnSummon();
5100 if (m_caster
->GetTypeId()==TYPEID_PLAYER
)
5101 team
= ((Player
*)m_caster
)->GetTeam();
5103 Totem
* pTotem
= new Totem
;
5105 if(!pTotem
->Create(objmgr
.GenerateLowGuid(HIGHGUID_UNIT
), m_caster
->GetMap(), m_spellInfo
->EffectMiscValue
[i
], team
))
5111 float angle
= slot
< MAX_TOTEM
? M_PI
/MAX_TOTEM
- (slot
*2*M_PI
/MAX_TOTEM
) : 0;
5114 m_caster
->GetClosePoint(x
,y
,z
,pTotem
->GetObjectSize(),2.0f
,angle
);
5116 // totem must be at same Z in case swimming caster and etc.
5117 if( fabs( z
- m_caster
->GetPositionZ() ) > 5 )
5118 z
= m_caster
->GetPositionZ();
5120 pTotem
->Relocate(x
, y
, z
, m_caster
->GetOrientation());
5122 if(slot
< MAX_TOTEM
)
5123 m_caster
->m_TotemSlot
[slot
] = pTotem
->GetGUID();
5125 pTotem
->SetOwner(m_caster
->GetGUID());
5126 pTotem
->SetTypeBySummonSpell(m_spellInfo
); // must be after Create call where m_spells initilized
5128 int32 duration
=GetSpellDuration(m_spellInfo
);
5129 if(Player
* modOwner
= m_caster
->GetSpellModOwner())
5130 modOwner
->ApplySpellMod(m_spellInfo
->Id
,SPELLMOD_DURATION
, duration
);
5131 pTotem
->SetDuration(duration
);
5133 if (damage
) // if not spell info, DB values used
5135 pTotem
->SetMaxHealth(damage
);
5136 pTotem
->SetHealth(damage
);
5139 pTotem
->SetUInt32Value(UNIT_CREATED_BY_SPELL
,m_spellInfo
->Id
);
5140 pTotem
->SetFlag(UNIT_FIELD_FLAGS
,UNIT_FLAG_PVP_ATTACKABLE
);
5142 pTotem
->ApplySpellImmune(m_spellInfo
->Id
,IMMUNITY_STATE
,SPELL_AURA_MOD_FEAR
,true);
5143 pTotem
->ApplySpellImmune(m_spellInfo
->Id
,IMMUNITY_STATE
,SPELL_AURA_TRANSFORM
,true);
5145 pTotem
->Summon(m_caster
);
5147 if(slot
< MAX_TOTEM
&& m_caster
->GetTypeId() == TYPEID_PLAYER
)
5149 WorldPacket
data(SMSG_TOTEM_CREATED
, 1+8+4+4);
5150 data
<< uint8(slot
);
5151 data
<< uint64(pTotem
->GetGUID());
5152 data
<< uint32(duration
);
5153 data
<< uint32(m_spellInfo
->Id
);
5154 ((Player
*)m_caster
)->SendDirectMessage(&data
);
5158 void Spell::EffectEnchantHeldItem(uint32 i
)
5160 // this is only item spell effect applied to main-hand weapon of target player (players in area)
5161 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5164 Player
* item_owner
= (Player
*)unitTarget
;
5165 Item
* item
= item_owner
->GetItemByPos(INVENTORY_SLOT_BAG_0
, EQUIPMENT_SLOT_MAINHAND
);
5171 if(!item
->IsEquipped())
5174 if (m_spellInfo
->EffectMiscValue
[i
])
5176 uint32 enchant_id
= m_spellInfo
->EffectMiscValue
[i
];
5177 int32 duration
= GetSpellDuration(m_spellInfo
); //Try duration index first ..
5179 duration
= m_currentBasePoints
[i
]+1; //Base points after ..
5181 duration
= 10; //10 seconds for enchants which don't have listed duration
5183 SpellItemEnchantmentEntry
const *pEnchant
= sSpellItemEnchantmentStore
.LookupEntry(enchant_id
);
5187 // Always go to temp enchantment slot
5188 EnchantmentSlot slot
= TEMP_ENCHANTMENT_SLOT
;
5190 // Enchantment will not be applied if a different one already exists
5191 if(item
->GetEnchantmentId(slot
) && item
->GetEnchantmentId(slot
) != enchant_id
)
5194 // Apply the temporary enchantment
5195 item
->SetEnchantment(slot
, enchant_id
, duration
*1000, 0);
5196 item_owner
->ApplyEnchantment(item
,slot
,true);
5200 void Spell::EffectDisEnchant(uint32
/*i*/)
5202 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5205 Player
* p_caster
= (Player
*)m_caster
;
5206 if(!itemTarget
|| !itemTarget
->GetProto()->DisenchantID
)
5209 p_caster
->UpdateCraftSkill(m_spellInfo
->Id
);
5211 ((Player
*)m_caster
)->SendLoot(itemTarget
->GetGUID(),LOOT_DISENCHANTING
);
5213 // item will be removed at disenchanting end
5216 void Spell::EffectInebriate(uint32
/*i*/)
5218 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5221 Player
*player
= (Player
*)unitTarget
;
5222 uint16 currentDrunk
= player
->GetDrunkValue();
5223 uint16 drunkMod
= damage
* 256;
5224 if (currentDrunk
+ drunkMod
> 0xFFFF)
5225 currentDrunk
= 0xFFFF;
5227 currentDrunk
+= drunkMod
;
5228 player
->SetDrunkValue(currentDrunk
, m_CastItem
?m_CastItem
->GetEntry():0);
5231 void Spell::EffectFeedPet(uint32 i
)
5233 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5236 Player
*_player
= (Player
*)m_caster
;
5241 Pet
*pet
= _player
->GetPet();
5248 int32 benefit
= pet
->GetCurrentFoodBenefitLevel(itemTarget
->GetProto()->ItemLevel
);
5253 _player
->DestroyItemCount(itemTarget
,count
,true);
5254 // TODO: fix crash when a spell has two effects, both pointed at the same item target
5256 m_caster
->CastCustomSpell(m_caster
,m_spellInfo
->EffectTriggerSpell
[i
],&benefit
,NULL
,NULL
,true);
5259 void Spell::EffectDismissPet(uint32
/*i*/)
5261 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5264 Pet
* pet
= m_caster
->GetPet();
5266 // not let dismiss dead pet
5267 if(!pet
||!pet
->isAlive())
5270 ((Player
*)m_caster
)->RemovePet(pet
,PET_SAVE_NOT_IN_SLOT
);
5273 void Spell::EffectSummonObject(uint32 i
)
5275 uint32 go_id
= m_spellInfo
->EffectMiscValue
[i
];
5278 switch(m_spellInfo
->Effect
[i
])
5280 case SPELL_EFFECT_SUMMON_OBJECT_SLOT1
: slot
= 0; break;
5281 case SPELL_EFFECT_SUMMON_OBJECT_SLOT2
: slot
= 1; break;
5282 case SPELL_EFFECT_SUMMON_OBJECT_SLOT3
: slot
= 2; break;
5283 case SPELL_EFFECT_SUMMON_OBJECT_SLOT4
: slot
= 3; break;
5287 uint64 guid
= m_caster
->m_ObjectSlot
[slot
];
5290 GameObject
* obj
= NULL
;
5292 obj
= ObjectAccessor::GetGameObject(*m_caster
, guid
);
5294 if(obj
) obj
->Delete();
5295 m_caster
->m_ObjectSlot
[slot
] = 0;
5298 GameObject
* pGameObj
= new GameObject
;
5300 float rot2
= sin(m_caster
->GetOrientation()/2);
5301 float rot3
= cos(m_caster
->GetOrientation()/2);
5304 // If dest location if present
5305 if (m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
5307 x
= m_targets
.m_destX
;
5308 y
= m_targets
.m_destY
;
5309 z
= m_targets
.m_destZ
;
5311 // Summon in random point all other units if location present
5313 m_caster
->GetClosePoint(x
,y
,z
,DEFAULT_WORLD_OBJECT_SIZE
);
5315 Map
*map
= m_caster
->GetMap();
5316 if(!pGameObj
->Create(objmgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), go_id
, map
, x
, y
, z
, m_caster
->GetOrientation(), 0, 0, rot2
, rot3
, 0, 1))
5322 pGameObj
->SetUInt32Value(GAMEOBJECT_LEVEL
,m_caster
->getLevel());
5323 int32 duration
= GetSpellDuration(m_spellInfo
);
5324 pGameObj
->SetRespawnTime(duration
> 0 ? duration
/1000 : 0);
5325 pGameObj
->SetSpellId(m_spellInfo
->Id
);
5326 m_caster
->AddGameObject(pGameObj
);
5329 WorldPacket
data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE
, 8);
5330 data
<< pGameObj
->GetGUID();
5331 m_caster
->SendMessageToSet(&data
,true);
5333 m_caster
->m_ObjectSlot
[slot
] = pGameObj
->GetGUID();
5336 void Spell::EffectResurrect(uint32 i
)
5340 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5343 if(unitTarget
->isAlive())
5345 if(!unitTarget
->IsInWorld())
5348 switch (m_spellInfo
->Id
)
5350 // Defibrillate (Goblin Jumper Cables) have 33% chance on success
5352 if (roll_chance_i(67))
5354 m_caster
->CastSpell(m_caster
, 8338, true, m_CastItem
);
5358 // Defibrillate (Goblin Jumper Cables XL) have 50% chance on success
5360 if (roll_chance_i(50))
5362 m_caster
->CastSpell(m_caster
, 23055, true, m_CastItem
);
5370 Player
* pTarget
= ((Player
*)unitTarget
);
5372 if(pTarget
->isRessurectRequested()) // already have one active request
5375 uint32 health
= pTarget
->GetMaxHealth() * damage
/ 100;
5376 uint32 mana
= pTarget
->GetMaxPower(POWER_MANA
) * damage
/ 100;
5378 pTarget
->setResurrectRequestData(m_caster
->GetGUID(), m_caster
->GetMapId(), m_caster
->GetPositionX(), m_caster
->GetPositionY(), m_caster
->GetPositionZ(), health
, mana
);
5379 SendResurrectRequest(pTarget
);
5382 void Spell::EffectAddExtraAttacks(uint32
/*i*/)
5384 if(!unitTarget
|| !unitTarget
->isAlive())
5387 if( unitTarget
->m_extraAttacks
)
5390 unitTarget
->m_extraAttacks
= damage
;
5393 void Spell::EffectParry(uint32
/*i*/)
5395 if (unitTarget
->GetTypeId() == TYPEID_PLAYER
)
5397 ((Player
*)unitTarget
)->SetCanParry(true);
5401 void Spell::EffectBlock(uint32
/*i*/)
5403 if (unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5406 ((Player
*)unitTarget
)->SetCanBlock(true);
5409 void Spell::EffectMomentMove(uint32 i
)
5411 if(unitTarget
->isInFlight())
5414 if( m_spellInfo
->rangeIndex
== 1) //self range
5416 uint32 mapid
= m_caster
->GetMapId();
5417 float dis
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[i
]));
5421 unitTarget
->GetClosePoint(fx
,fy
,fz
,unitTarget
->GetObjectSize(),dis
);
5423 unitTarget
->GetPosition(ox
,oy
,oz
);
5425 float fx2
,fy2
,fz2
; // getObjectHitPos overwrite last args in any result case
5426 if(VMAP::VMapFactory::createOrGetVMapManager()->getObjectHitPos(mapid
, ox
,oy
,oz
+0.5, fx
,fy
,oz
+0.5,fx2
,fy2
,fz2
, -0.5))
5431 unitTarget
->UpdateGroundPositionZ(fx
,fy
,fz
);
5434 if(unitTarget
->GetTypeId() == TYPEID_PLAYER
)
5435 ((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));
5437 MapManager::Instance().GetMap(mapid
, unitTarget
)->CreatureRelocation((Creature
*)unitTarget
, fx
, fy
, fz
, unitTarget
->GetOrientation());
5441 void Spell::EffectReputation(uint32 i
)
5443 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5446 Player
*_player
= (Player
*)unitTarget
;
5448 int32 rep_change
= m_currentBasePoints
[i
]+1; // field store reputation change -1
5450 uint32 faction_id
= m_spellInfo
->EffectMiscValue
[i
];
5452 FactionEntry
const* factionEntry
= sFactionStore
.LookupEntry(faction_id
);
5457 _player
->ModifyFactionReputation(factionEntry
,rep_change
);
5460 void Spell::EffectQuestComplete(uint32 i
)
5462 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5465 Player
*_player
= (Player
*)m_caster
;
5467 uint32 quest_id
= m_spellInfo
->EffectMiscValue
[i
];
5468 _player
->AreaExploredOrEventHappens(quest_id
);
5471 void Spell::EffectSelfResurrect(uint32 i
)
5473 if(!unitTarget
|| unitTarget
->isAlive())
5475 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5477 if(!unitTarget
->IsInWorld())
5486 health
= uint32(-damage
);
5487 mana
= m_spellInfo
->EffectMiscValue
[i
];
5492 health
= uint32(damage
/100.0f
*unitTarget
->GetMaxHealth());
5493 if(unitTarget
->GetMaxPower(POWER_MANA
) > 0)
5494 mana
= uint32(damage
/100.0f
*unitTarget
->GetMaxPower(POWER_MANA
));
5497 Player
*plr
= ((Player
*)unitTarget
);
5498 plr
->ResurrectPlayer(0.0f
);
5500 plr
->SetHealth( health
);
5501 plr
->SetPower(POWER_MANA
, mana
);
5502 plr
->SetPower(POWER_RAGE
, 0 );
5503 plr
->SetPower(POWER_ENERGY
, plr
->GetMaxPower(POWER_ENERGY
) );
5505 plr
->SpawnCorpseBones();
5510 void Spell::EffectSkinning(uint32
/*i*/)
5512 if(unitTarget
->GetTypeId() != TYPEID_UNIT
)
5514 if(!m_caster
|| m_caster
->GetTypeId() != TYPEID_PLAYER
)
5517 Creature
* creature
= (Creature
*) unitTarget
;
5518 int32 targetLevel
= creature
->getLevel();
5520 uint32 skill
= creature
->GetCreatureInfo()->GetRequiredLootSkill();
5522 ((Player
*)m_caster
)->SendLoot(creature
->GetGUID(),LOOT_SKINNING
);
5523 creature
->RemoveFlag(UNIT_FIELD_FLAGS
, UNIT_FLAG_SKINNABLE
);
5525 int32 reqValue
= targetLevel
< 10 ? 0 : targetLevel
< 20 ? (targetLevel
-10)*10 : targetLevel
*5;
5527 int32 skillValue
= ((Player
*)m_caster
)->GetPureSkillValue(skill
);
5529 // Double chances for elites
5530 ((Player
*)m_caster
)->UpdateGatherSkill(skill
, skillValue
, reqValue
, creature
->isElite() ? 2 : 1 );
5533 void Spell::EffectCharge(uint32
/*i*/)
5535 if(!unitTarget
|| !m_caster
)
5539 unitTarget
->GetContactPoint(m_caster
, x
, y
, z
);
5540 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5541 ((Creature
*)unitTarget
)->StopMoving();
5543 // Only send MOVEMENTFLAG_WALK_MODE, client has strange issues with other move flags
5544 m_caster
->SendMonsterMove(x
, y
, z
, 0, MOVEMENTFLAG_WALK_MODE
, 1);
5546 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5547 MapManager::Instance().GetMap(m_caster
->GetMapId(), m_caster
)->CreatureRelocation((Creature
*)m_caster
,x
,y
,z
,m_caster
->GetOrientation());
5549 // not all charge effects used in negative spells
5550 if ( !IsPositiveSpell(m_spellInfo
->Id
))
5551 m_caster
->Attack(unitTarget
,true);
5554 void Spell::EffectSummonCritter(uint32 i
)
5556 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5558 Player
* player
= (Player
*)m_caster
;
5560 uint32 pet_entry
= m_spellInfo
->EffectMiscValue
[i
];
5564 Pet
* old_critter
= player
->GetMiniPet();
5566 // for same pet just despawn
5567 if(old_critter
&& old_critter
->GetEntry() == pet_entry
)
5569 player
->RemoveMiniPet();
5573 // despawn old pet before summon new
5575 player
->RemoveMiniPet();
5578 Pet
* critter
= new Pet(MINI_PET
);
5580 Map
*map
= m_caster
->GetMap();
5581 uint32 pet_number
= objmgr
.GeneratePetNumber();
5582 if(!critter
->Create(objmgr
.GenerateLowGuid(HIGHGUID_PET
),
5583 map
, pet_entry
, pet_number
))
5585 sLog
.outError("Spell::EffectSummonCritter, spellid %u: no such creature entry %u", m_spellInfo
->Id
, pet_entry
);
5591 // If dest location if present
5592 if (m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
5594 x
= m_targets
.m_destX
;
5595 y
= m_targets
.m_destY
;
5596 z
= m_targets
.m_destZ
;
5598 // Summon if dest location not present near caster
5600 m_caster
->GetClosePoint(x
,y
,z
,critter
->GetObjectSize());
5602 critter
->Relocate(x
,y
,z
,m_caster
->GetOrientation());
5604 if(!critter
->IsPositionValid())
5606 sLog
.outError("ERROR: Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %d Y: ^%d)", critter
->GetGUIDLow(), critter
->GetEntry(), critter
->GetPositionX(), critter
->GetPositionY());
5611 critter
->SetUInt64Value(UNIT_FIELD_SUMMONEDBY
,m_caster
->GetGUID());
5612 critter
->SetUInt64Value(UNIT_FIELD_CREATEDBY
,m_caster
->GetGUID());
5613 critter
->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE
,m_caster
->getFaction());
5614 critter
->SetUInt32Value(UNIT_CREATED_BY_SPELL
, m_spellInfo
->Id
);
5616 critter
->AIM_Initialize();
5617 critter
->InitPetCreateSpells(); // e.g. disgusting oozeling has a create spell as critter...
5618 critter
->SetMaxHealth(1);
5619 critter
->SetHealth(1);
5620 critter
->SetLevel(1);
5622 // set timer for unsummon
5623 int32 duration
= GetSpellDuration(m_spellInfo
);
5625 critter
->SetDuration(duration
);
5627 std::string name
= player
->GetName();
5628 name
.append(petTypeSuffix
[critter
->getPetType()]);
5629 critter
->SetName( name
);
5630 player
->SetMiniPet(critter
);
5632 map
->Add((Creature
*)critter
);
5635 void Spell::EffectKnockBack(uint32 i
)
5637 if(!unitTarget
|| !m_caster
)
5640 // Effect only works on players
5641 if(unitTarget
->GetTypeId()!=TYPEID_PLAYER
)
5644 float vsin
= sin(m_caster
->GetAngle(unitTarget
));
5645 float vcos
= cos(m_caster
->GetAngle(unitTarget
));
5647 WorldPacket
data(SMSG_MOVE_KNOCK_BACK
, (8+4+4+4+4+4));
5648 data
.append(unitTarget
->GetPackGUID());
5649 data
<< uint32(0); // Sequence
5650 data
<< float(vcos
); // x direction
5651 data
<< float(vsin
); // y direction
5652 data
<< float(m_spellInfo
->EffectMiscValue
[i
])/10; // Horizontal speed
5653 data
<< float(damage
/-10); // Z Movement speed (vertical)
5655 ((Player
*)unitTarget
)->GetSession()->SendPacket(&data
);
5658 void Spell::EffectSendTaxi(uint32 i
)
5660 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5663 TaxiPathEntry
const* entry
= sTaxiPathStore
.LookupEntry(m_spellInfo
->EffectMiscValue
[i
]);
5667 std::vector
<uint32
> nodes
;
5670 nodes
[0] = entry
->from
;
5671 nodes
[1] = entry
->to
;
5674 switch(m_spellInfo
->Id
)
5676 case 31606: //Stormcrow Amulet
5679 case 45071: //Quest - Sunwell Daily - Dead Scar Bombing Run
5680 case 45113: //Quest - Sunwell Daily - Ship Bombing Run
5681 case 45353: //Quest - Sunwell Daily - Ship Bombing Run Return
5684 case 34905: //Stealth Flight
5689 ((Player
*)unitTarget
)->ActivateTaxiPathTo(nodes
,mountid
);
5693 void Spell::EffectPlayerPull(uint32 i
)
5695 if(!unitTarget
|| !m_caster
)
5698 // Effect only works on players
5699 if(unitTarget
->GetTypeId()!=TYPEID_PLAYER
)
5702 float vsin
= sin(unitTarget
->GetAngle(m_caster
));
5703 float vcos
= cos(unitTarget
->GetAngle(m_caster
));
5705 WorldPacket
data(SMSG_MOVE_KNOCK_BACK
, (8+4+4+4+4+4));
5706 data
.append(unitTarget
->GetPackGUID());
5707 data
<< uint32(0); // Sequence
5708 data
<< float(vcos
); // x direction
5709 data
<< float(vsin
); // y direction
5711 data
<< float(damage
? damage
: unitTarget
->GetDistance2d(m_caster
));
5712 data
<< float(m_spellInfo
->EffectMiscValue
[i
])/-10; // Z Movement speed
5714 ((Player
*)unitTarget
)->GetSession()->SendPacket(&data
);
5717 void Spell::EffectDispelMechanic(uint32 i
)
5722 uint32 mechanic
= m_spellInfo
->EffectMiscValue
[i
];
5724 Unit::AuraMap
& Auras
= unitTarget
->GetAuras();
5725 for(Unit::AuraMap::iterator iter
= Auras
.begin(), next
; iter
!= Auras
.end(); iter
= next
)
5729 SpellEntry
const *spell
= sSpellStore
.LookupEntry(iter
->second
->GetSpellProto()->Id
);
5730 if(spell
->Mechanic
== mechanic
|| spell
->EffectMechanic
[iter
->second
->GetEffIndex()] == mechanic
)
5732 unitTarget
->RemoveAurasDueToSpell(spell
->Id
);
5736 next
= Auras
.begin();
5742 void Spell::EffectSummonDeadPet(uint32
/*i*/)
5744 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5746 Player
*_player
= (Player
*)m_caster
;
5747 Pet
*pet
= _player
->GetPet();
5754 pet
->SetUInt32Value(UNIT_DYNAMIC_FLAGS
, 0);
5755 pet
->RemoveFlag (UNIT_FIELD_FLAGS
, UNIT_FLAG_SKINNABLE
);
5756 pet
->setDeathState( ALIVE
);
5757 pet
->clearUnitState(UNIT_STAT_ALL_STATE
);
5758 pet
->SetHealth( uint32(pet
->GetMaxHealth()*(float(damage
)/100)));
5760 pet
->AIM_Initialize();
5762 _player
->PetSpellInitialize();
5763 pet
->SavePetToDB(PET_SAVE_AS_CURRENT
);
5766 void Spell::EffectDestroyAllTotems(uint32
/*i*/)
5769 for(int slot
= 0; slot
< MAX_TOTEM
; ++slot
)
5771 if(!m_caster
->m_TotemSlot
[slot
])
5774 Creature
* totem
= ObjectAccessor::GetCreature(*m_caster
,m_caster
->m_TotemSlot
[slot
]);
5775 if(totem
&& totem
->isTotem())
5777 uint32 spell_id
= totem
->GetUInt32Value(UNIT_CREATED_BY_SPELL
);
5778 SpellEntry
const* spellInfo
= sSpellStore
.LookupEntry(spell_id
);
5780 mana
+= spellInfo
->manaCost
* damage
/ 100;
5781 ((Totem
*)totem
)->UnSummon();
5785 int32 gain
= m_caster
->ModifyPower(POWER_MANA
,int32(mana
));
5786 m_caster
->SendEnergizeSpellLog(m_caster
, m_spellInfo
->Id
, gain
, POWER_MANA
);
5789 void Spell::EffectDurabilityDamage(uint32 i
)
5791 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5794 int32 slot
= m_spellInfo
->EffectMiscValue
[i
];
5796 // FIXME: some spells effects have value -1/-2
5797 // Possibly its mean -1 all player equipped items and -2 all items
5800 ((Player
*)unitTarget
)->DurabilityPointsLossAll(damage
,(slot
< -1));
5804 // invalid slot value
5805 if(slot
>= INVENTORY_SLOT_BAG_END
)
5808 if(Item
* item
= ((Player
*)unitTarget
)->GetItemByPos(INVENTORY_SLOT_BAG_0
,slot
))
5809 ((Player
*)unitTarget
)->DurabilityPointsLoss(item
,damage
);
5812 void Spell::EffectDurabilityDamagePCT(uint32 i
)
5814 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5817 int32 slot
= m_spellInfo
->EffectMiscValue
[i
];
5819 // FIXME: some spells effects have value -1/-2
5820 // Possibly its mean -1 all player equipped items and -2 all items
5823 ((Player
*)unitTarget
)->DurabilityLossAll(double(damage
)/100.0f
,(slot
< -1));
5827 // invalid slot value
5828 if(slot
>= INVENTORY_SLOT_BAG_END
)
5834 if(Item
* item
= ((Player
*)unitTarget
)->GetItemByPos(INVENTORY_SLOT_BAG_0
,slot
))
5835 ((Player
*)unitTarget
)->DurabilityLoss(item
,double(damage
)/100.0f
);
5838 void Spell::EffectModifyThreatPercent(uint32
/*effIndex*/)
5843 unitTarget
->getThreatManager().modifyThreatPercent(m_caster
, damage
);
5846 void Spell::EffectTransmitted(uint32 effIndex
)
5848 uint32 name_id
= m_spellInfo
->EffectMiscValue
[effIndex
];
5850 GameObjectInfo
const* goinfo
= objmgr
.GetGameObjectInfo(name_id
);
5854 sLog
.outErrorDb("Gameobject (Entry: %u) not exist and not created at spell (ID: %u) cast",name_id
, m_spellInfo
->Id
);
5860 if(m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
5862 fx
= m_targets
.m_destX
;
5863 fy
= m_targets
.m_destY
;
5864 fz
= m_targets
.m_destZ
;
5866 //FIXME: this can be better check for most objects but still hack
5867 else if(m_spellInfo
->EffectRadiusIndex
[effIndex
] && m_spellInfo
->speed
==0)
5869 float dis
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[effIndex
]));
5870 m_caster
->GetClosePoint(fx
,fy
,fz
,DEFAULT_WORLD_OBJECT_SIZE
, dis
);
5874 float min_dis
= GetSpellMinRange(sSpellRangeStore
.LookupEntry(m_spellInfo
->rangeIndex
));
5875 float max_dis
= GetSpellMaxRange(sSpellRangeStore
.LookupEntry(m_spellInfo
->rangeIndex
));
5876 float dis
= rand_norm() * (max_dis
- min_dis
) + min_dis
;
5878 m_caster
->GetClosePoint(fx
,fy
,fz
,DEFAULT_WORLD_OBJECT_SIZE
, dis
);
5881 Map
*cMap
= m_caster
->GetMap();
5883 if(goinfo
->type
==GAMEOBJECT_TYPE_FISHINGNODE
)
5885 if ( !cMap
->IsInWater(fx
,fy
,fz
-0.5f
)) // Hack to prevent fishing bobber from failing to land on fishing hole
5886 { // but this is not proper, we really need to ignore not materialized objects
5887 SendCastResult(SPELL_FAILED_NOT_HERE
);
5888 SendChannelUpdate(0);
5892 // replace by water level in this case
5893 fz
= cMap
->GetWaterLevel(fx
,fy
);
5895 // if gameobject is summoning object, it should be spawned right on caster's position
5896 else if(goinfo
->type
==GAMEOBJECT_TYPE_SUMMONING_RITUAL
)
5898 m_caster
->GetPosition(fx
,fy
,fz
);
5901 GameObject
* pGameObj
= new GameObject
;
5903 if(!pGameObj
->Create(objmgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), name_id
, cMap
,
5904 fx
, fy
, fz
, m_caster
->GetOrientation(), 0, 0, 0, 0, 100, 1))
5910 int32 duration
= GetSpellDuration(m_spellInfo
);
5912 switch(goinfo
->type
)
5914 case GAMEOBJECT_TYPE_FISHINGNODE
:
5916 m_caster
->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT
,pGameObj
->GetGUID());
5918 pGameObj
->SetFloatValue(GAMEOBJECT_ROTATION
+ 2, 0.88431775569915771 );
5920 pGameObj
->SetFloatValue(GAMEOBJECT_ROTATION
+ 3, -0.4668855369091033 );
5921 m_caster
->AddGameObject(pGameObj
); // will removed at spell cancel
5923 // end time of range when possible catch fish (FISHING_BOBBER_READY_TIME..GetDuration(m_spellInfo))
5924 // start time == fish-FISHING_BOBBER_READY_TIME (0..GetDuration(m_spellInfo)-FISHING_BOBBER_READY_TIME)
5928 case 0: lastSec
= 3; break;
5929 case 1: lastSec
= 7; break;
5930 case 2: lastSec
= 13; break;
5931 case 3: lastSec
= 17; break;
5934 duration
= duration
- lastSec
*1000 + FISHING_BOBBER_READY_TIME
*1000;
5937 case GAMEOBJECT_TYPE_SUMMONING_RITUAL
:
5939 if(m_caster
->GetTypeId()==TYPEID_PLAYER
)
5941 pGameObj
->AddUniqueUse((Player
*)m_caster
);
5942 m_caster
->AddGameObject(pGameObj
); // will removed at spell cancel
5946 case GAMEOBJECT_TYPE_FISHINGHOLE
:
5947 case GAMEOBJECT_TYPE_CHEST
:
5954 pGameObj
->SetRespawnTime(duration
> 0 ? duration
/1000 : 0);
5956 pGameObj
->SetOwnerGUID(m_caster
->GetGUID() );
5958 pGameObj
->SetUInt32Value(GAMEOBJECT_LEVEL
, m_caster
->getLevel() );
5959 pGameObj
->SetSpellId(m_spellInfo
->Id
);
5961 DEBUG_LOG("AddObject at SpellEfects.cpp EffectTransmitted\n");
5962 //m_caster->AddGameObject(pGameObj);
5963 //m_ObjToDel.push_back(pGameObj);
5965 cMap
->Add(pGameObj
);
5967 WorldPacket
data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE
, 8);
5968 data
<< uint64(pGameObj
->GetGUID());
5969 m_caster
->SendMessageToSet(&data
,true);
5971 if(uint32 linkedEntry
= pGameObj
->GetLinkedGameObjectEntry())
5973 GameObject
* linkedGO
= new GameObject
;
5974 if(linkedGO
->Create(objmgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), linkedEntry
, cMap
,
5975 fx
, fy
, fz
, m_caster
->GetOrientation(), 0, 0, 0, 0, 100, 1))
5977 linkedGO
->SetRespawnTime(duration
> 0 ? duration
/1000 : 0);
5978 linkedGO
->SetUInt32Value(GAMEOBJECT_LEVEL
, m_caster
->getLevel() );
5979 linkedGO
->SetSpellId(m_spellInfo
->Id
);
5980 linkedGO
->SetOwnerGUID(m_caster
->GetGUID() );
5982 MapManager::Instance().GetMap(linkedGO
->GetMapId(), linkedGO
)->Add(linkedGO
);
5993 void Spell::EffectProspecting(uint32
/*i*/)
5995 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5998 Player
* p_caster
= (Player
*)m_caster
;
5999 if(!itemTarget
|| !(itemTarget
->GetProto()->BagFamily
& BAG_FAMILY_MASK_MINING_SUPP
))
6002 if(itemTarget
->GetCount() < 5)
6005 if( sWorld
.getConfig(CONFIG_SKILL_PROSPECTING
))
6007 uint32 SkillValue
= p_caster
->GetPureSkillValue(SKILL_JEWELCRAFTING
);
6008 uint32 reqSkillValue
= itemTarget
->GetProto()->RequiredSkillRank
;
6009 p_caster
->UpdateGatherSkill(SKILL_JEWELCRAFTING
, SkillValue
, reqSkillValue
);
6012 ((Player
*)m_caster
)->SendLoot(itemTarget
->GetGUID(), LOOT_PROSPECTING
);
6015 void Spell::EffectSkill(uint32
/*i*/)
6017 sLog
.outDebug("WORLD: SkillEFFECT");
6020 void Spell::EffectSummonDemon(uint32 i
)
6022 float px
= m_targets
.m_destX
;
6023 float py
= m_targets
.m_destY
;
6024 float pz
= m_targets
.m_destZ
;
6026 Creature
* Charmed
= m_caster
->SummonCreature(m_spellInfo
->EffectMiscValue
[i
], px
, py
, pz
, m_caster
->GetOrientation(),TEMPSUMMON_TIMED_OR_DEAD_DESPAWN
,3600000);
6030 // might not always work correctly, maybe the creature that dies from CoD casts the effect on itself and is therefore the caster?
6031 Charmed
->SetLevel(m_caster
->getLevel());
6033 // TODO: Add damage/mana/hp according to level
6035 if (m_spellInfo
->EffectMiscValue
[i
] == 89) // Inferno summon
6037 // Enslave demon effect, without mana cost and cooldown
6038 m_caster
->CastSpell(Charmed
, 20882, true); // FIXME: enslave does not scale with level, level 62+ minions cannot be enslaved
6041 Charmed
->CastSpell(Charmed
, 22703, true, 0);
6045 /* There is currently no need for this effect. We handle it in BattleGround.cpp
6046 If we would handle the resurrection here, the spiritguide would instantly disappear as the
6047 player revives, and so we wouldn't see the spirit heal visual effect on the npc.
6048 This is why we use a half sec delay between the visual effect and the resurrection itself */
6049 void Spell::EffectSpiritHeal(uint32
/*i*/)
6052 if(!unitTarget || unitTarget->isAlive())
6054 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
6056 if(!unitTarget->IsInWorld())
6059 //m_spellInfo->EffectBasePoints[i]; == 99 (percent?)
6060 //((Player*)unitTarget)->setResurrect(m_caster->GetGUID(), unitTarget->GetPositionX(), unitTarget->GetPositionY(), unitTarget->GetPositionZ(), unitTarget->GetMaxHealth(), unitTarget->GetMaxPower(POWER_MANA));
6061 ((Player*)unitTarget)->ResurrectPlayer(1.0f);
6062 ((Player*)unitTarget)->SpawnCorpseBones();
6066 // remove insignia spell effect
6067 void Spell::EffectSkinPlayerCorpse(uint32
/*i*/)
6069 sLog
.outDebug("Effect: SkinPlayerCorpse");
6070 if ( (m_caster
->GetTypeId() != TYPEID_PLAYER
) || (unitTarget
->GetTypeId() != TYPEID_PLAYER
) || (unitTarget
->isAlive()) )
6073 ((Player
*)unitTarget
)->RemovedInsignia( (Player
*)m_caster
);
6076 void Spell::EffectStealBeneficialBuff(uint32 i
)
6078 sLog
.outDebug("Effect: StealBeneficialBuff");
6080 if(!unitTarget
|| unitTarget
==m_caster
) // can't steal from self
6083 std::vector
<Aura
*> steal_list
;
6084 // Create dispel mask by dispel type
6085 uint32 dispelMask
= GetDispellMask( DispelType(m_spellInfo
->EffectMiscValue
[i
]) );
6086 Unit::AuraMap
const& auras
= unitTarget
->GetAuras();
6087 for(Unit::AuraMap::const_iterator itr
= auras
.begin(); itr
!= auras
.end(); ++itr
)
6089 Aura
*aur
= (*itr
).second
;
6090 if (aur
&& (1<<aur
->GetSpellProto()->Dispel
) & dispelMask
)
6092 // Need check for passive? this
6093 if (aur
->IsPositive() && !aur
->IsPassive())
6094 steal_list
.push_back(aur
);
6097 // Ok if exist some buffs for dispel try dispel it
6098 if (!steal_list
.empty())
6100 std::list
< std::pair
<uint32
,uint64
> > success_list
;
6101 int32 list_size
= steal_list
.size();
6102 // Dispell N = damage buffs (or while exist buffs for dispel)
6103 for (int32 count
=0; count
< damage
&& list_size
> 0; ++count
)
6105 // Random select buff for dispel
6106 Aura
*aur
= steal_list
[urand(0, list_size
-1)];
6107 // Not use chance for steal
6108 // TODO possible need do it
6109 success_list
.push_back( std::pair
<uint32
,uint64
>(aur
->GetId(),aur
->GetCasterGUID()));
6111 // Remove buff from list for prevent doubles
6112 for (std::vector
<Aura
*>::iterator j
= steal_list
.begin(); j
!= steal_list
.end(); )
6115 if (stealed
->GetId() == aur
->GetId() && stealed
->GetCasterGUID() == aur
->GetCasterGUID())
6117 j
= steal_list
.erase(j
);
6124 // Really try steal and send log
6125 if (!success_list
.empty())
6127 int32 count
= success_list
.size();
6128 WorldPacket
data(SMSG_SPELLSTEALLOG
, 8+8+4+1+4+count
*5);
6129 data
.append(unitTarget
->GetPackGUID()); // Victim GUID
6130 data
.append(m_caster
->GetPackGUID()); // Caster GUID
6131 data
<< uint32(m_spellInfo
->Id
); // Dispell spell id
6132 data
<< uint8(0); // not used
6133 data
<< uint32(count
); // count
6134 for (std::list
<std::pair
<uint32
,uint64
> >::iterator j
= success_list
.begin(); j
!= success_list
.end(); ++j
)
6136 SpellEntry
const* spellInfo
= sSpellStore
.LookupEntry(j
->first
);
6137 data
<< uint32(spellInfo
->Id
); // Spell Id
6138 data
<< uint8(0); // 0 - steals !=0 transfers
6139 unitTarget
->RemoveAurasDueToSpellBySteal(spellInfo
->Id
, j
->second
, m_caster
);
6141 m_caster
->SendMessageToSet(&data
, true);
6146 void Spell::EffectKillCredit(uint32 i
)
6148 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
6151 ((Player
*)unitTarget
)->KilledMonster(m_spellInfo
->EffectMiscValue
[i
], 0);
6154 void Spell::EffectQuestFail(uint32 i
)
6156 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
6159 ((Player
*)unitTarget
)->FailQuest(m_spellInfo
->EffectMiscValue
[i
]);