2 * Copyright (C) 2005,2006,2007 MaNGOS <http://www.mangosproject.org/>
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 "Database/DatabaseEnv.h"
21 #include "WorldPacket.h"
22 #include "WorldSession.h"
25 #include "UpdateMask.h"
27 #include "ObjectMgr.h"
30 #include "CreatureAI.h"
32 #include "DynamicObject.h"
33 #include "SpellAuras.h"
35 #include "UpdateData.h"
36 #include "MapManager.h"
37 #include "ObjectAccessor.h"
38 #include "RedZoneDistrict.h"
40 #include "SharedDefines.h"
42 #include "GameObject.h"
43 #include "GossipDef.h"
46 #include "CreatureAI.h"
47 #include "GridNotifiers.h"
48 #include "GridNotifiersImpl.h"
50 pEffect SpellEffects
[TOTAL_SPELL_EFFECTS
]=
52 &Spell::EffectNULL
, //nothing
53 &Spell::EffectInstaKill
, //SPELL_EFFECT_INSTAKILL = 1
54 &Spell::EffectSchoolDMG
, //SPELL_EFFECT_SCHOOL_DAMAGE = 2
55 &Spell::EffectDummy
, //SPELL_EFFECT_DUMMY = 3
56 &Spell::EffectNULL
, //SPELL_EFFECT_PORTAL_TELEPORT = 4
57 &Spell::EffectTeleportUnits
, //SPELL_EFFECT_TELEPORT_UNITS = 5
58 &Spell::EffectApplyAura
, //SPELL_EFFECT_APPLY_AURA = 6
59 &Spell::EffectSchoolDMG
, //SPELL_EFFECT_ENVIRONMENTAL_DAMAGE =7
60 &Spell::EffectManaDrain
, //SPELL_EFFECT_MANA_DRAIN = 8
61 &Spell::EffectHealthLeach
, //SPELL_EFFECT_HEALTH_LEECH = 9
62 &Spell::EffectHeal
, //SPELL_EFFECT_HEAL = 10
63 &Spell::EffectNULL
, //SPELL_EFFECT_BIND = 11
64 &Spell::EffectNULL
, //SPELL_EFFECT_PORTAL = 12
65 &Spell::EffectNULL
, //SPELL_EFFECT_RITUAL_BASE = 13
66 &Spell::EffectNULL
, //SPELL_EFFECT_RITUAL_SPECIALIZE = 14
67 &Spell::EffectNULL
, //SPELL_EFFECT_RITUAL_ACTIVATE_PORTAL = 15
68 &Spell::EffectQuestComplete
, //SPELL_EFFECT_QUEST_COMPLETE = 16
69 &Spell::EffectWeaponDmg
, //SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL = 17
70 &Spell::EffectResurrect
, //SPELL_EFFECT_RESURRECT = 18
71 &Spell::EffectNULL
, //SPELL_EFFECT_ADD_EXTRA_ATTACKS = 19
72 &Spell::EffectNULL
, //SPELL_EFFECT_DODGE = 20
73 &Spell::EffectNULL
, //SPELL_EFFECT_EVADE = 21
74 &Spell::EffectParry
, //SPELL_EFFECT_PARRY = 22
75 &Spell::EffectNULL
, //SPELL_EFFECT_BLOCK = 23
76 &Spell::EffectCreateItem
, //SPELL_EFFECT_CREATE_ITEM = 24
77 &Spell::EffectNULL
, //SPELL_EFFECT_WEAPON = 25
78 &Spell::EffectNULL
, //SPELL_EFFECT_DEFENSE = 26
79 &Spell::EffectPersistentAA
, //SPELL_EFFECT_PERSISTENT_AREA_AURA = 27
80 &Spell::EffectSummon
, //SPELL_EFFECT_SUMMON = 28
81 &Spell::EffectMomentMove
, //SPELL_EFFECT_LEAP = 29
82 &Spell::EffectEnergize
, //SPELL_EFFECT_ENERGIZE = 30
83 &Spell::EffectWeaponDmg
, //SPELL_EFFECT_WEAPON_PERCENT_DAMAGE = 31
84 &Spell::EffectNULL
, //SPELL_EFFECT_TRIGGER_MISSILE = 32 //Useless
85 &Spell::EffectOpenLock
, //SPELL_EFFECT_OPEN_LOCK = 33
86 &Spell::EffectSummonChangeItem
, //SPELL_EFFECT_SUMMON_CHANGE_ITEM = 34
87 &Spell::EffectApplyAA
, //SPELL_EFFECT_APPLY_AREA_AURA = 35
88 &Spell::EffectLearnSpell
, //SPELL_EFFECT_LEARN_SPELL = 36
89 &Spell::EffectNULL
, //SPELL_EFFECT_SPELL_DEFENSE = 37 //Useless
90 &Spell::EffectDispel
, //SPELL_EFFECT_DISPEL = 38
91 &Spell::EffectNULL
, //SPELL_EFFECT_LANGUAGE = 39
92 &Spell::EffectDualWield
, //SPELL_EFFECT_DUAL_WIELD = 40
93 &Spell::EffectSummonWild
, //SPELL_EFFECT_SUMMON_WILD = 41
94 &Spell::EffectSummonWild
, //SPELL_EFFECT_SUMMON_GUARDIAN = 42
95 &Spell::EffectTeleUnitsFaceCaster
, //SPELL_EFFECT_TELEPORT_UNITS_FACE_CASTER = 43
96 &Spell::EffectLearnSkill
, //SPELL_EFFECT_SKILL_STEP = 44
97 &Spell::EffectNULL
, //unknown45 = 45
98 &Spell::EffectNULL
, //SPELL_EFFECT_SPAWN = 46
99 &Spell::EffectTradeSkill
, //SPELL_EFFECT_TRADE_SKILL = 47
100 &Spell::EffectNULL
, //SPELL_EFFECT_STEALTH = 48 //Useless
101 &Spell::EffectNULL
, //SPELL_EFFECT_DETECT = 49
102 &Spell::EffectTransmitted
, //SPELL_EFFECT_TRANS_DOOR = 50
103 &Spell::EffectNULL
, //SPELL_EFFECT_FORCE_CRITICAL_HIT = 51 //Useless
104 &Spell::EffectNULL
, //SPELL_EFFECT_GUARANTEE_HIT = 52
105 &Spell::EffectEnchantItemPerm
, //SPELL_EFFECT_ENCHANT_ITEM = 53
106 &Spell::EffectEnchantItemTmp
, //SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY = 54
107 &Spell::EffectTameCreature
, //SPELL_EFFECT_TAMECREATURE = 55
108 &Spell::EffectSummonPet
, //SPELL_EFFECT_SUMMON_PET = 56
109 &Spell::EffectLearnPetSpell
, //SPELL_EFFECT_LEARN_PET_SPELL = 57
110 &Spell::EffectWeaponDmg
, //SPELL_EFFECT_WEAPON_DAMAGE = 58
111 &Spell::EffectOpenSecretSafe
, //SPELL_EFFECT_OPEN_LOCK_ITEM = 59
112 &Spell::EffectProficiency
, //SPELL_EFFECT_PROFICIENCY = 60
113 &Spell::EffectSendEvent
, //SPELL_EFFECT_SEND_EVENT = 61
114 &Spell::EffectPowerDrain
, //SPELL_EFFECT_POWER_BURN = 62
115 &Spell::EffectThreat
, //SPELL_EFFECT_THREAT = 63
116 &Spell::EffectTriggerSpell
, //SPELL_EFFECT_TRIGGER_SPELL = 64
117 &Spell::EffectNULL
, //SPELL_EFFECT_HEALTH_FUNNEL = 65 //Useless
118 &Spell::EffectNULL
, //SPELL_EFFECT_POWER_FUNNEL = 66 //Useless
119 &Spell::EffectHealMaxHealth
, //SPELL_EFFECT_HEAL_MAX_HEALTH = 67
120 &Spell::EffectInterruptCast
, //SPELL_EFFECT_INTERRUPT_CAST = 68
121 &Spell::EffectNULL
, //SPELL_EFFECT_DISTRACT = 69
122 &Spell::EffectNULL
, //SPELL_EFFECT_PULL = 70
123 &Spell::EffectPickPocket
, //SPELL_EFFECT_PICKPOCKET = 71
124 &Spell::EffectNULL
, //SPELL_EFFECT_ADD_FARSIGHT = 72
125 &Spell::EffectSummonWild
, //SPELL_EFFECT_SUMMON_POSSESSED = 73
126 &Spell::EffectNULL
, //SPELL_EFFECT_SUMMON_TOTEM = 74 //Useless
127 &Spell::EffectNULL
, //SPELL_EFFECT_HEAL_MECHANICAL = 75
128 &Spell::EffectSummonObjectWild
, //SPELL_EFFECT_SUMMON_OBJECT_WILD = 76
129 &Spell::EffectScriptEffect
, //SPELL_EFFECT_SCRIPT_EFFECT = 77
130 &Spell::EffectNULL
, //SPELL_EFFECT_ATTACK = 78 //Useless
131 &Spell::EffectSanctuary
, //SPELL_EFFECT_SANCTUARY = 79
132 &Spell::EffectAddComboPoints
, //SPELL_EFFECT_ADD_COMBO_POINTS = 80
133 &Spell::EffectNULL
, //SPELL_EFFECT_CREATE_HOUSE = 81
134 &Spell::EffectNULL
, //SPELL_EFFECT_BIND_SIGHT = 82
135 &Spell::EffectDuel
, //SPELL_EFFECT_DUEL = 83
136 &Spell::EffectNULL
, //SPELL_EFFECT_STUCK = 84
137 &Spell::EffectNULL
, //SPELL_EFFECT_SUMMON_PLAYER = 85
138 &Spell::EffectNULL
, //SPELL_EFFECT_ACTIVATE_OBJECT = 86
139 &Spell::EffectSummonTotem
, //SPELL_EFFECT_SUMMON_TOTEM_SLOT1 = 87
140 &Spell::EffectSummonTotem
, //SPELL_EFFECT_SUMMON_TOTEM_SLOT2 = 88
141 &Spell::EffectSummonTotem
, //SPELL_EFFECT_SUMMON_TOTEM_SLOT3 = 89
142 &Spell::EffectSummonTotem
, //SPELL_EFFECT_SUMMON_TOTEM_SLOT4 = 90
143 &Spell::EffectNULL
, //SPELL_EFFECT_THREAT_ALL = 91
144 &Spell::EffectEnchantHeldItem
, //SPELL_EFFECT_ENCHANT_HELD_ITEM = 92
145 &Spell::EffectNULL
, //SPELL_EFFECT_SUMMON_PHANTASM = 93
146 &Spell::EffectSelfResurrect
, //SPELL_EFFECT_SELF_RESURRECT = 94
147 &Spell::EffectSkinning
, //SPELL_EFFECT_SKINNING = 95
148 &Spell::EffectCharge
, //SPELL_EFFECT_CHARGE = 96
149 &Spell::EffectSummonCritter
, //SPELL_EFFECT_SUMMON_CRITTER = 97
150 &Spell::EffectKnockBack
, //SPELL_EFFECT_KNOCK_BACK = 98
151 &Spell::EffectDisEnchant
, //SPELL_EFFECT_DISENCHANT = 99
152 &Spell::EffectInebriate
, //SPELL_EFFECT_INEBRIATE = 100
153 &Spell::EffectFeedPet
, //SPELL_EFFECT_FEED_PET = 101
154 &Spell::EffectDismissPet
, //SPELL_EFFECT_DISMISS_PET = 102
155 &Spell::EffectReputation
, //SPELL_EFFECT_REPUTATION = 103
156 &Spell::EffectSummonObject
, //SPELL_EFFECT_SUMMON_OBJECT_SLOT1 = 104
157 &Spell::EffectSummonObject
, //SPELL_EFFECT_SUMMON_OBJECT_SLOT2 = 105
158 &Spell::EffectSummonObject
, //SPELL_EFFECT_SUMMON_OBJECT_SLOT3 = 106
159 &Spell::EffectSummonObject
, //SPELL_EFFECT_SUMMON_OBJECT_SLOT4 = 107
160 &Spell::EffectNULL
, //SPELL_EFFECT_DISPEL_MECHANIC = 108
161 &Spell::EffectSummonDeadPet
, //SPELL_EFFECT_SUMMON_DEAD_PET = 109
162 &Spell::EffectNULL
, //SPELL_EFFECT_DESTROY_ALL_TOTEMS = 110
163 &Spell::EffectNULL
, //SPELL_EFFECT_DURABILITY_DAMAGE = 111
164 &Spell::EffectNULL
, //SPELL_EFFECT_SUMMON_DEMON = 112
165 &Spell::EffectResurrectNew
, //SPELL_EFFECT_RESURRECT_NEW = 113
166 &Spell::EffectAttackMe
, //SPELL_EFFECT_ATTACK_ME = 114
167 &Spell::EffectNULL
, //SPELL_EFFECT_DURABILITY_DAMAGE_PCT = 115
168 &Spell::EffectNULL
, //SPELL_EFFECT_SKIN_PLAYER_CORPSE = 116
169 &Spell::EffectNULL
, //SPELL_EFFECT_SPIRIT_HEAL = 117
170 &Spell::EffectSkill
, //SPELL_EFFECT_SKILL = 118 -- professions and more
171 &Spell::EffectNULL
, //SPELL_EFFECT_APPLY_AURA_NEW = 119
172 &Spell::EffectNULL
, //SPELL_EFFECT_TELEPORT_GRAVEYARD = 120
173 &Spell::EffectWeaponDmg
//SPELL_EFFECT_NORMALIZED_WEAPON_DMG = 121
176 void Spell::EffectNULL(uint32 i
)
178 sLog
.outDebug("WORLD: Spell Effect DUMMY");
181 void Spell::EffectResurrectNew(uint32 i
)
183 if(!unitTarget
) return;
184 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
) return;
185 if(unitTarget
->isAlive()) return;
186 if(!unitTarget
->IsInWorld()) return;
188 uint32 health
= m_spellInfo
->EffectBasePoints
[i
]+1;
189 uint32 mana
= m_spellInfo
->EffectMiscValue
[i
];
190 ((Player
*)unitTarget
)->setResurrect(m_caster
->GetGUID(), m_caster
->GetPositionX(), m_caster
->GetPositionY(), m_caster
->GetPositionZ(), health
, mana
);
191 SendResurrectRequest((Player
*)unitTarget
);
194 void Spell::EffectInstaKill(uint32 i
)
196 if( unitTarget
&& unitTarget
->isAlive() )
198 uint32 health
= unitTarget
->GetHealth();
199 m_caster
->DealDamage(unitTarget
, health
, DIRECT_DAMAGE
, 0, NULL
, 0, false);
203 void Spell::EffectSchoolDMG(uint32 i
)
205 if( unitTarget
&& unitTarget
->isAlive() && damage
>= 0)
206 m_caster
->SpellNonMeleeDamageLog(unitTarget
, m_spellInfo
->Id
, damage
, m_IsTriggeredSpell
);
208 if (m_caster
->GetTypeId()==TYPEID_PLAYER
&& m_spellInfo
->Attributes
== 0x150010)
209 m_caster
->AttackStop();
212 void Spell::EffectDummy(uint32 i
)
217 // More spell specific code in begining
218 if( m_spellInfo
->Id
== SPELL_ID_AGGRO
)
220 if( !unitTarget
|| !m_caster
|| !m_caster
->getVictim() )
223 // only creature to creature
224 if( unitTarget
->GetTypeId() != TYPEID_UNIT
|| m_caster
->GetTypeId() != TYPEID_UNIT
)
227 // if creature not figthing currently
228 if( unitTarget
->isInCombat() )
231 // skip non hostile to caster enemy creatures
232 if( !((Creature
*)unitTarget
)->IsHostileTo(m_caster
->getVictim()) )
235 // only from same creature faction
236 if(unitTarget
->getFaction() != m_caster
->getFaction() )
239 ((Creature
*)m_caster
)->SetNoCallAssistence(true);
240 ((Creature
*)unitTarget
)->SetNoCallAssistence(true);
241 ((Creature
*)unitTarget
)->AI().AttackStart(m_caster
->getVictim());
245 // Preparation Rogue - immediately finishes the cooldown on other Rogue abilities
246 if(m_spellInfo
->Id
== 14185)
248 if(m_caster
->GetTypeId()!=TYPEID_PLAYER
)
251 const PlayerSpellMap
& sp_list
= ((Player
*)m_caster
)->GetSpellMap();
252 for (PlayerSpellMap::const_iterator itr
= sp_list
.begin(); itr
!= sp_list
.end(); ++itr
)
254 uint32 classspell
= itr
->first
;
255 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(classspell
);
257 if (spellInfo
->SpellFamilyName
== SPELLFAMILY_ROGUE
&& spellInfo
->Id
!= 14185 &&
258 (spellInfo
->RecoveryTime
> 0 || spellInfo
->CategoryRecoveryTime
> 0))
260 ((Player
*)m_caster
)->RemoveSpellCooldown(classspell
);
262 WorldPacket
data(SMSG_CLEAR_COOLDOWN
, (4+8+4));
264 data
<< m_caster
->GetGUID();
266 ((Player
*)m_caster
)->GetSession()->SendPacket(&data
);
272 // Cold Snap - immediately finishes the cooldown on Frost spells
273 if(m_spellInfo
->Id
== 12472)
275 if(m_caster
->GetTypeId()!=TYPEID_PLAYER
)
278 const PlayerSpellMap
& sp_list
= ((Player
*)m_caster
)->GetSpellMap();
279 for (PlayerSpellMap::const_iterator itr
= sp_list
.begin(); itr
!= sp_list
.end(); ++itr
)
281 if (itr
->second
->state
== PLAYERSPELL_REMOVED
) continue;
282 uint32 classspell
= itr
->first
;
283 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(classspell
);
285 if (spellInfo
->SpellFamilyName
== SPELLFAMILY_MAGE
&& spellInfo
->School
== SPELL_SCHOOL_FROST
&& spellInfo
->Id
!= 12472 &&
286 (spellInfo
->RecoveryTime
> 0 || spellInfo
->CategoryRecoveryTime
> 0))
288 ((Player
*)m_caster
)->RemoveSpellCooldown(classspell
);
290 WorldPacket
data(SMSG_CLEAR_COOLDOWN
, (4+8+4));
292 data
<< m_caster
->GetGUID();
294 ((Player
*)m_caster
)->GetSession()->SendPacket(&data
);
300 // If spell cannibalize and his casted, check special requirements and cast aura Cannibalize is all ok
301 if(m_spellInfo
->Id
== 20577)
303 // non-standard cast requirement check
304 SpellRangeEntry
const* srange
= sSpellRangeStore
.LookupEntry(m_spellInfo
->rangeIndex
);
305 float max_range
= GetMaxRange(srange
);
307 CellPair
p(MaNGOS::ComputeCellPair(m_caster
->GetPositionX(), m_caster
->GetPositionY()));
308 Cell cell
= RedZone::GetZone(p
);
309 cell
.data
.Part
.reserved
= ALL_DISTRICT
;
314 MaNGOS::CannibalizeUnitCheck
u_check(m_caster
, max_range
);
315 MaNGOS::UnitSearcher
<MaNGOS::CannibalizeUnitCheck
> searcher(result
, u_check
);
317 TypeContainerVisitor
<MaNGOS::UnitSearcher
<MaNGOS::CannibalizeUnitCheck
>, TypeMapContainer
<AllObjectTypes
> > unit_searcher(searcher
);
318 CellLock
<GridReadGuard
> cell_lock(cell
, p
);
319 cell_lock
->Visit(cell_lock
, unit_searcher
, *MapManager::Instance().GetMap(m_caster
->GetMapId()));
323 // clear cooldown at fail
324 if(m_caster
->GetTypeId()==TYPEID_PLAYER
)
326 ((Player
*)m_caster
)->RemoveSpellCooldown(20577);
328 WorldPacket
data(SMSG_CLEAR_COOLDOWN
, (4+8+4));
329 data
<< uint32(20577); // spell id
330 data
<< m_caster
->GetGUID();
332 ((Player
*)m_caster
)->GetSession()->SendPacket(&data
);
335 SendCastResult(CAST_FAIL_NO_NEARBY_CORPSES_TO_EAT
);
339 // ok, main function spell can be casted
341 finish(); // prepere to replacing this cpell cast to main function spell
344 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry( 20578 );
345 Spell
*spell
= new Spell(m_caster
, spellInfo
, false, 0);
348 sLog
.outError("WORLD: unknown spell id %i\n", 20578);
352 SpellCastTargets targets
;
353 targets
.setUnitTarget(m_caster
);
354 spell
->prepare(&targets
);
358 // More generic code later
360 // starshards/curse of agony hack .. this applies to 1.10 only
361 if (m_triggeredByAura
)
363 SpellEntry
const *trig_info
= m_triggeredByAura
->GetSpellProto();
364 if ((trig_info
->SpellIconID
== 1485 && trig_info
->SpellFamilyName
== SPELLFAMILY_PRIEST
) ||
365 (trig_info
->SpellIconID
== 544 && trig_info
->SpellFamilyName
== SPELLFAMILY_WARLOCK
))
367 Unit
*tmpTarget
= unitTarget
;
368 unitTarget
= m_triggeredByAura
->GetTarget();
369 damage
= trig_info
->EffectBasePoints
[i
]+1;
371 unitTarget
= tmpTarget
;
375 //Holy Shock For Paladins
376 if (m_spellInfo
->SpellFamilyName
== SPELLFAMILY_PALADIN
&& m_spellInfo
->SpellIconID
== 156)
381 switch(m_spellInfo
->Id
)
399 if(m_caster
->IsFriendlyTo(unitTarget
))
400 m_caster
->CastSpell(unitTarget
, heal
, true, 0);
402 m_caster
->CastSpell(unitTarget
, hurt
, true, 0);
405 if(m_spellInfo
->SpellIconID
== 1648)
408 dmg
+= int32(m_caster
->GetPower(POWER_RAGE
)/10 * objmgr
.GetSpellRank(m_spellInfo
->Id
)*3);
409 SpellEntry
const *tspellInfo
= sSpellStore
.LookupEntry(20647);
410 SpellEntry sInfo
= *tspellInfo
;
411 sInfo
.EffectBasePoints
[0] = dmg
;
412 m_caster
->CastSpell(unitTarget
, &sInfo
, true, 0);
413 m_caster
->SetPower(POWER_RAGE
,0);
417 if(m_spellInfo
->SpellVisual
== 1225 && m_spellInfo
->SpellIconID
== 208)
419 int32 mod
= m_spellInfo
->EffectBasePoints
[0]+1;
422 if(m_caster
->GetHealth()>mod
)
424 m_caster
->ModifyHealth(-mod
);
425 m_caster
->ModifyPower(POWER_MANA
,mod
);
431 void Spell::EffectTriggerSpell(uint32 i
)
433 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry( m_spellInfo
->EffectTriggerSpell
[i
] );
437 sLog
.outError("WORLD: unknown spell id %i\n", m_spellInfo
->EffectTriggerSpell
[i
]);
441 m_TriggerSpell
.push_back(spellInfo
);
444 void Spell::EffectTeleportUnits(uint32 i
)
448 HandleTeleport(m_spellInfo
->Id
,unitTarget
);
451 void Spell::EffectApplyAura(uint32 i
)
455 if(!unitTarget
->isAlive())
458 //If m_immuneToState type contain this aura type, IMMUNE aura.
459 if(unitTarget
->IsImmunedToSpellEffect(m_spellInfo
->EffectApplyAuraName
[i
]))
461 SendCastResult(CAST_FAIL_IMMUNE
);
465 sLog
.outDebug("Spell: Aura is: %u", m_spellInfo
->EffectApplyAuraName
[i
]);
467 Aura
* Aur
= new Aura(m_spellInfo
, i
, unitTarget
,m_caster
, m_CastItem
);
469 if (!Aur
->IsPositive() && Aur
->GetCasterGUID() != Aur
->GetTarget()->GetGUID())
471 switch (Aur
->GetModifier()->m_auraname
)
473 case SPELL_AURA_MOD_DETECT_RANGE
:
474 case SPELL_AURA_AURAS_VISIBLE
:
475 case SPELL_AURA_MOD_CHARM
:
478 if(Aur
->GetTarget()->GetTypeId() == TYPEID_UNIT
&& !Aur
->GetTarget()->isInCombat())
479 ((Creature
*)Aur
->GetTarget())->AI().AttackStart(m_caster
);
482 m_caster
->Attack(Aur
->GetTarget());
483 m_caster
->SetInCombat();
484 Aur
->GetTarget()->SetInCombat();
489 bool added
= unitTarget
->AddAura(Aur
);
493 // Check for Power Word: Shield
494 // TODO Make a way so it works for every related spell!
495 if(unitTarget
->GetTypeId()==TYPEID_PLAYER
) // Negative buff should only be applied on players
497 // This should cover all Power Word: Shield spells
498 if ((m_spellInfo
->SpellVisual
== 784) && (m_spellInfo
->SpellIconID
== 566))
501 SpellEntry
const *WeakenedSoulSpellInfo
= sSpellStore
.LookupEntry( 6788 );
502 Aura
* WeakenedSoulAura
= new Aura(WeakenedSoulSpellInfo
, 0, unitTarget
,m_caster
, 0);
503 unitTarget
->AddAura(WeakenedSoulAura
, 0);
504 sLog
.outDebug("Spell: Additinal Aura is: %u", WeakenedSoulSpellInfo
->EffectApplyAuraName
[i
]);
511 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(m_spellInfo
->EffectTriggerSpell
[i
]);
512 if (!spellInfo
) return;
513 if (spellInfo
->EffectImplicitTargetA
[0] == TARGET_SINGLE_ENEMY
&& m_caster
->GetTypeId() == TYPEID_PLAYER
)
515 Unit
*target
= ObjectAccessor::Instance().GetUnit(*m_caster
, ((Player
*)m_caster
)->GetSelection());
518 if (!m_caster
->IsFriendlyTo(target
))
519 Aur
->SetTarget(target
);
530 void Spell::EffectManaDrain(uint32 i
)
532 if(m_spellInfo
->EffectMiscValue
[i
] > 4)
535 Powers drain_power
= Powers(m_spellInfo
->EffectMiscValue
[i
]);
539 if(!unitTarget
->isAlive())
541 if(unitTarget
->getPowerType() != drain_power
)
546 uint32 curPower
= unitTarget
->GetPower(drain_power
);
547 float tmpvalue
= m_spellInfo
->EffectMultipleValue
[i
];
552 if(curPower
< uint32(damage
))
553 new_damage
= curPower
;
557 unitTarget
->ModifyPower(drain_power
,-new_damage
);
559 if(drain_power
== POWER_MANA
)
560 m_caster
->ModifyPower(POWER_MANA
,uint32(new_damage
*tmpvalue
));
563 void Spell::EffectSendEvent(uint32 i
)
565 sWorld
.ScriptsStart(sSpellScripts
, m_spellInfo
->Id
, m_caster
, focusObject
);
568 void Spell::EffectPowerDrain(uint32 i
)
572 if(!unitTarget
->isAlive())
574 if(unitTarget
->getPowerType()!=POWER_MANA
)
579 uint32 curPower
= unitTarget
->GetPower(POWER_MANA
);
582 if(curPower
< uint32(damage
))
583 new_damage
= curPower
;
587 int32 tmpvalue
= int32(new_damage
*m_spellInfo
->EffectMultipleValue
[i
]);
589 unitTarget
->ModifyPower(POWER_MANA
,-new_damage
);
591 m_caster
->ModifyPower(POWER_MANA
,tmpvalue
);
592 m_caster
->SpellNonMeleeDamageLog(unitTarget
, m_spellInfo
->Id
, new_damage
/2, m_IsTriggeredSpell
);
596 void Spell::EffectHeal( uint32 i
)
598 if( unitTarget
&& unitTarget
->isAlive() && damage
>= 0)
600 int32 addhealth
= m_caster
->SpellHealingBonus(m_spellInfo
, uint32(damage
));
601 bool crit
= m_caster
->SpellCriticalBonus(m_spellInfo
, &addhealth
);
602 if(unitTarget
->GetTypeId() == TYPEID_PLAYER
)
603 SendHealSpellOnPlayer(((Player
*)unitTarget
), m_spellInfo
->Id
, addhealth
, crit
);
605 unitTarget
->ModifyHealth( addhealth
);
607 uint32 procHealer
= PROC_FLAG_HEAL
;
609 procHealer
|= PROC_FLAG_CRIT_HEAL
;
610 if (m_caster
!= unitTarget
)
611 m_caster
->ProcDamageAndSpell(unitTarget
,procHealer
,PROC_FLAG_NONE
,addhealth
,m_spellInfo
,m_IsTriggeredSpell
);
615 void Spell::EffectHealthLeach(uint32 i
)
619 if(!unitTarget
->isAlive())
625 sLog
.outDebug("HealthLeach :%i", damage
);
627 uint32 curHealth
= unitTarget
->GetHealth();
630 if(curHealth
< uint32(damage
))
631 new_damage
= curHealth
;
635 int32 tmpvalue
= int32(new_damage
*m_spellInfo
->EffectMultipleValue
[i
]);
637 m_caster
->ModifyHealth(tmpvalue
);
639 if(unitTarget
->GetTypeId() == TYPEID_PLAYER
)
640 SendHealSpellOnPlayer(((Player
*)unitTarget
), m_spellInfo
->Id
, uint32(tmpvalue
));
642 m_caster
->SpellNonMeleeDamageLog(unitTarget
, m_spellInfo
->Id
, new_damage
, m_IsTriggeredSpell
);
645 void Spell::DoCreateItem(uint32 i
, uint32 itemtype
)
647 if (m_caster
->GetTypeId() != TYPEID_PLAYER
)
650 Player
* player
= (Player
*)m_caster
;
652 uint32 newitemid
= itemtype
;
653 ItemPrototype
const *pProto
= objmgr
.GetItemPrototype( newitemid
);
656 player
->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND
, NULL
, NULL
);
662 if(pProto
->Class
!= ITEM_CLASS_CONSUMABLE
|| m_spellInfo
->SpellFamilyName
!= SPELLFAMILY_MAGE
)
663 num_to_add
= max(m_spellInfo
->EffectBasePoints
[i
]+1, 1);
664 else if(player
->getLevel() >= m_spellInfo
->spellLevel
)
665 num_to_add
= ((player
->getLevel() - (m_spellInfo
->spellLevel
-1))*2);
670 uint8 msg
= player
->CanStoreNewItem( NULL_BAG
, NULL_SLOT
, dest
, newitemid
, num_to_add
, false);
671 if( msg
!= EQUIP_ERR_OK
)
673 player
->SendEquipError( msg
, NULL
, NULL
);
677 Item
*pItem
= player
->StoreNewItem( dest
, newitemid
, num_to_add
, true);
681 player
->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND
, NULL
, NULL
);
685 if( pItem
->GetProto()->Class
!= ITEM_CLASS_CONSUMABLE
)
686 pItem
->SetUInt32Value(ITEM_FIELD_CREATOR
,player
->GetGUIDLow());
688 player
->SendNewItem(pItem
, num_to_add
, true, true);
689 player
->UpdateCraftSkill(m_spellInfo
->Id
);
692 void Spell::EffectCreateItem(uint32 i
)
694 DoCreateItem(i
,m_spellInfo
->EffectItemType
[i
]);
697 void Spell::EffectPersistentAA(uint32 i
)
699 float radius
= GetRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[i
]));
700 int32 duration
= GetDuration(m_spellInfo
);
701 DynamicObject
* dynObj
= new DynamicObject();
702 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
))
707 dynObj
->SetUInt32Value(OBJECT_FIELD_TYPE
, 65);
708 dynObj
->SetUInt32Value(GAMEOBJECT_DISPLAYID
, 368003);
709 dynObj
->SetUInt32Value(DYNAMICOBJECT_BYTES
, 0x01eeeeee);
710 m_caster
->AddDynObject(dynObj
);
711 dynObj
->AddToWorld();
712 MapManager::Instance().GetMap(dynObj
->GetMapId())->Add(dynObj
);
716 void Spell::EffectEnergize(uint32 i
)
720 if(!unitTarget
->isAlive())
723 if(m_spellInfo
->EffectMiscValue
[i
] > 4)
729 Powers power
= Powers(m_spellInfo
->EffectMiscValue
[i
]);
731 if(unitTarget
->getPowerType() != power
)
734 unitTarget
->ModifyPower(power
,damage
);
737 void Spell::EffectOpenLock(uint32 i
)
740 if(!m_caster
|| m_caster
->GetTypeId() != TYPEID_PLAYER
)
742 sLog
.outDebug( "WORLD: Open Lock - No Player Caster!");
746 Player
* player
= (Player
*)m_caster
;
748 LootType loottype
= LOOT_CORPSE
;
755 lockId
= gameObjTarget
->GetGOInfo()->sound0
;
756 guid
= gameObjTarget
->GetGUID();
760 lockId
= itemTarget
->GetProto()->LockID
;
761 guid
= itemTarget
->GetGUID();
765 sLog
.outDebug( "WORLD: Open Lock - No GameObject/Item Target!");
769 if(!lockId
) // possible case for GO and maybe for items.
771 player
->SendLoot(guid
,loottype
);
776 LockEntry
const *lockInfo
= sLockStore
.LookupEntry(lockId
);
780 sLog
.outError( "Spell::EffectOpenLock: %s [guid = %u] has an unknown lockId: %u!",
781 (gameObjTarget
? "gameobject" : "item"), GUID_LOPART(guid
), lockId
);
782 SendCastResult(CAST_FAIL_INVALID_TARGET
);
787 if(lockInfo
->key
&& m_CastItem
&& m_CastItem
->GetEntry()==lockInfo
->key
)
789 player
->SendLoot(guid
,loottype
);
794 // Check and skill-up skill
795 if(m_spellInfo
->Effect
[1]==SPELL_EFFECT_SKILL
)
796 SkillId
= m_spellInfo
->EffectMiscValue
[1];
798 if(m_spellInfo
->EffectMiscValue
[0]==1) // picklocking spells
799 SkillId
= SKILL_LOCKPICKING
;
801 // skill bonus provided by casting spell (mostly item spells)
802 uint32 spellSkillBonus
= uint32(m_spellInfo
->EffectBasePoints
[0]+1);
804 uint32 reqSkillValue
= lockInfo
->requiredskill
;
806 if(lockInfo
->requiredlockskill
) // required pick lock skill applying
808 if(SkillId
!= SKILL_LOCKPICKING
) // wrong skill (cheating?)
810 SendCastResult(CAST_FAIL_FIZZLED
);
814 reqSkillValue
= lockInfo
->requiredlockskill
;
817 if(SkillId
== SKILL_LOCKPICKING
) // apply picklock skill to wrong target
819 SendCastResult(CAST_FAIL_INVALID_TARGET
);
825 loottype
= LOOT_SKINNING
;
826 if ( player
->GetSkillValue(SkillId
) + spellSkillBonus
< reqSkillValue
)
828 SendCastResult(CAST_FAIL_SKILL_NOT_HIGH_ENOUGH
);
832 // update skill if really known
833 uint32 SkillValue
= player
->GetPureSkillValue(SkillId
);
834 if(SkillValue
) // non only item base skill
838 // Allow one skill-up until respawned
839 if ( !gameObjTarget
->IsInSkillupList( player
->GetGUIDLow() ) &&
840 player
->UpdateGatherSkill(SkillId
, SkillValue
, reqSkillValue
) )
841 gameObjTarget
->AddToSkillupList( player
->GetGUIDLow() );
846 uint32 SkillValue
= player
->GetPureSkillValue(SkillId
);
847 player
->UpdateGatherSkill(SkillId
, SkillValue
, reqSkillValue
);
853 player
->SendLoot(guid
,loottype
);
856 void Spell::EffectSummonChangeItem(uint32 i
)
858 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
861 Player
*player
= (Player
*)m_caster
;
863 // applied only to using item
867 // ... only to item in own inventory/bank/equip_slot
868 if(m_CastItem
->GetOwnerGUID()!=player
->GetGUID())
871 uint32 newitemid
= m_spellInfo
->EffectItemType
[i
];
875 uint16 pos
= (m_CastItem
->GetBagSlot() << 8) | m_CastItem
->GetSlot();
877 Item
*pNewItem
= player
->CreateItem( newitemid
, 1 );
884 if( player
->IsInventoryPos( pos
) )
886 msg
= player
->CanStoreItem( m_CastItem
->GetBagSlot(), m_CastItem
->GetSlot(), dest
, pNewItem
, true );
887 if( msg
== EQUIP_ERR_OK
)
889 player
->DestroyItem(m_CastItem
->GetBagSlot(), m_CastItem
->GetSlot(),true);
890 player
->StoreItem( dest
, pNewItem
, true);
894 else if( player
->IsBankPos ( pos
) )
896 msg
= player
->CanBankItem( m_CastItem
->GetBagSlot(), m_CastItem
->GetSlot(), dest
, pNewItem
, true );
897 if( msg
== EQUIP_ERR_OK
)
899 player
->DestroyItem(m_CastItem
->GetBagSlot(), m_CastItem
->GetSlot(),true);
900 player
->BankItem( dest
, pNewItem
, true);
904 else if( player
->IsEquipmentPos ( pos
) )
906 msg
= player
->CanEquipItem( m_CastItem
->GetSlot(), dest
, pNewItem
, true );
907 if( msg
== EQUIP_ERR_OK
)
909 player
->DestroyItem(m_CastItem
->GetBagSlot(), m_CastItem
->GetSlot(),true);
910 player
->EquipItem( dest
, pNewItem
, true);
919 void Spell::EffectOpenSecretSafe(uint32 i
)
921 EffectOpenLock(i
); //no difference for now
924 void Spell::EffectProficiency(uint32 i
)
926 if (!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
928 Player
*p_target
= (Player
*)unitTarget
;
930 uint32 subClassMask
= m_spellInfo
->EquippedItemSubClassMask
;
931 if(m_spellInfo
->EquippedItemClass
== 2 && !(p_target
->GetWeaponProficiency() & subClassMask
))
933 p_target
->AddWeaponProficiency(subClassMask
);
934 p_target
->SendProficiency(uint8(0x02),p_target
->GetWeaponProficiency());
936 if(m_spellInfo
->EquippedItemClass
== 4 && !(p_target
->GetArmorProficiency() & subClassMask
))
938 p_target
->AddArmorProficiency(subClassMask
);
939 p_target
->SendProficiency(uint8(0x04),p_target
->GetArmorProficiency());
943 void Spell::EffectApplyAA(uint32 i
)
947 if(!unitTarget
->isAlive())
950 AreaAura
* Aur
= new AreaAura(m_spellInfo
, i
, unitTarget
, m_caster
);
951 unitTarget
->AddAura(Aur
);
954 void Spell::EffectSummon(uint32 i
)
956 if(m_caster
->GetPetGUID())
961 uint32 pet_entry
= m_spellInfo
->EffectMiscValue
[i
];
964 uint32 level
= m_caster
->getLevel();
965 Pet
* spawnCreature
= new Pet(SUMMON_PET
);
967 if(!spawnCreature
->Create(objmgr
.GenerateLowGuid(HIGHGUID_UNIT
),
968 m_caster
->GetMapId(),
969 m_caster
->GetPositionX(),m_caster
->GetPositionY(),
970 m_caster
->GetPositionZ(),m_caster
->GetOrientation(),
971 m_spellInfo
->EffectMiscValue
[i
]))
973 sLog
.outError("no such creature entry %u",m_spellInfo
->EffectMiscValue
[i
]);
974 delete spawnCreature
;
978 spawnCreature
->SetUInt64Value(UNIT_FIELD_SUMMONEDBY
,m_caster
->GetGUID());
979 spawnCreature
->SetUInt32Value(UNIT_NPC_FLAGS
, 0);
980 spawnCreature
->setPowerType(POWER_MANA
);
981 spawnCreature
->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE
,m_caster
->getFaction());
982 spawnCreature
->SetUInt32Value(UNIT_FIELD_FLAGS
,0);
983 spawnCreature
->SetUInt32Value(UNIT_FIELD_BYTES_1
,0);
984 spawnCreature
->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP
,0);
985 spawnCreature
->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE
,0);
986 spawnCreature
->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP
,1000);
987 spawnCreature
->SetUInt64Value(UNIT_FIELD_CREATEDBY
, m_caster
->GetGUID());
989 spawnCreature
->InitStatsForLevel(level
);
991 spawnCreature
->AIM_Initialize();
994 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
995 name
= ((Player
*)m_caster
)->GetName();
997 name
= ((Creature
*)m_caster
)->GetCreatureInfo()->Name
;
998 name
.append(petTypeSuffix
[spawnCreature
->getPetType()]);
999 spawnCreature
->SetName( name
);
1001 spawnCreature
->AddToWorld();
1002 MapManager::Instance().GetMap(m_caster
->GetMapId())->Add((Creature
*)spawnCreature
);
1004 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
1006 m_caster
->SetPet(spawnCreature
);
1007 spawnCreature
->SavePetToDB(PET_SAVE_AS_CURRENT
);
1008 ((Player
*)m_caster
)->PetSpellInitialize();
1012 void Spell::EffectLearnSpell(uint32 i
)
1017 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
1019 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
1021 Creature
*pet
= m_caster
->GetPet();
1023 if( !pet
|| !pet
->isPet() || pet
!=unitTarget
|| !pet
->isAlive() )
1026 EffectLearnPetSpell(i
);
1031 Player
*player
= (Player
*)unitTarget
;
1033 uint32 spellToLearn
= m_spellInfo
->EffectTriggerSpell
[i
];
1034 //data.Initialize(SMSG_LEARNED_SPELL);
1035 //data << spellToLearn;
1036 //player->GetSession()->SendPacket(&data);
1037 player
->learnSpell((uint16
)spellToLearn
);
1038 //some addspell isn't needed if you have a good DB,FISHING && MINING && HERBALISM have to be needed.
1039 switch(spellToLearn
)
1041 case 4036: //SKILL_ENGINERING
1043 player
->learnSpell(3918);
1044 player
->learnSpell(3919);
1045 player
->learnSpell(3920);
1048 case 3908: //SKILL_TAILORING
1050 player
->learnSpell(2387);
1051 player
->learnSpell(2963);
1054 case 7411: //SKILL_ENCHANTING
1056 player
->learnSpell(7418);
1057 player
->learnSpell(7421);
1058 player
->learnSpell(13262);
1061 case 2259: //SKILL_ALCHEMY
1063 player
->learnSpell(2329);
1064 player
->learnSpell(7183);
1065 player
->learnSpell(2330);
1068 case 2018: //SKILL_BLACKSMITHING
1070 player
->learnSpell(2663);
1071 player
->learnSpell(12260);
1072 player
->learnSpell(2660);
1073 player
->learnSpell(3115);
1076 case 2108: //SKILL_LEATHERWORKING
1078 player
->learnSpell(2152);
1079 player
->learnSpell(9058);
1080 player
->learnSpell(9059);
1081 player
->learnSpell(2149);
1082 player
->learnSpell(7126);
1083 player
->learnSpell(2881);
1086 case 2550: //SKILL_COOKING
1088 player
->learnSpell(818);
1089 player
->learnSpell(2540);
1090 player
->learnSpell(2538);
1091 player
->learnSpell(8604);
1094 case 3273: //SKILL_FIRST_AID
1096 player
->learnSpell(3275);
1099 case 7620: //SKILL_FISHING
1101 player
->learnSpell(7738);
1104 case 2575: //SKILL_MINING
1106 player
->learnSpell(2580);
1107 player
->learnSpell(2656);
1108 player
->learnSpell(2657);
1111 case 2366: //SKILL_HERBALISM
1113 player
->learnSpell(2383);
1116 case 264: //SKILL_BOWS
1118 if(!player
->HasSpell(75))
1119 player
->learnSpell(2480);
1122 case 266: //SKILL_GUNS
1124 if(!player
->HasSpell(75))
1125 player
->learnSpell(7918);
1128 case 5011: //SKILL_CROSSBOWS
1130 if(!player
->HasSpell(75))
1131 player
->learnSpell(7919);
1134 case 2567: //SKILL_THROWN
1136 player
->learnSpell(2764);
1139 case 2842: //SKILL_POISONS
1141 player
->learnSpell(8681);
1146 sLog
.outDebug( "Spell: Player %u have learned spell %u from NpcGUID=%u", player
->GetGUIDLow(), spellToLearn
, m_caster
->GetGUIDLow() );
1149 void Spell::EffectDispel(uint32 i
)
1151 m_caster
->RemoveFirstAuraByDispel(m_spellInfo
->EffectMiscValue
[i
]);
1154 void Spell::EffectDualWield(uint32 i
)
1156 if (unitTarget
->GetTypeId() == TYPEID_PLAYER
)
1157 ((Player
*)unitTarget
)->SetCanDualWield(true);
1160 void Spell::EffectPickPocket(uint32 i
)
1162 if( m_caster
->GetTypeId() != TYPEID_PLAYER
)
1165 //victim must be creature and attackable
1166 if( !unitTarget
|| unitTarget
->GetTypeId() != TYPEID_UNIT
|| m_caster
->IsFriendlyTo(unitTarget
) )
1169 //victim have to be alive and humanoid or undead
1170 if( unitTarget
->isAlive() &&
1171 (((Creature
*)unitTarget
)->GetCreatureInfo()->type
== CREATURE_TYPE_HUMANOID
||
1172 ((Creature
*)unitTarget
)->GetCreatureInfo()->type
== CREATURE_TYPE_UNDEAD
))
1174 int chance
= 10 + m_caster
->getLevel() - unitTarget
->getLevel();
1176 if ( ( rand() % 20 ) <= chance
)
1178 //Stealing successfull
1179 //sLog.outDebug("Sending loot from pickpocket");
1180 ((Player
*)m_caster
)->SendLoot(unitTarget
->GetGUID(),LOOT_PICKPOKETING
);
1184 //Reveal action + get attack
1185 m_caster
->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH
);
1186 ((Creature
*)unitTarget
)->AI().AttackStart(m_caster
);
1191 void Spell::EffectSummonWild(uint32 i
)
1195 uint32 pet_entry
= m_spellInfo
->EffectMiscValue
[i
];
1199 Pet
* old_wild
= NULL
;
1202 CellPair
p(MaNGOS::ComputeCellPair(m_caster
->GetPositionX(), m_caster
->GetPositionY()));
1203 Cell cell
= RedZone::GetZone(p
);
1204 cell
.data
.Part
.reserved
= ALL_DISTRICT
;
1207 PetWithIdCheck
u_check(m_caster
, pet_entry
);
1208 MaNGOS::UnitSearcher
<PetWithIdCheck
> checker((Unit
*&)old_wild
, u_check
);
1209 TypeContainerVisitor
<MaNGOS::UnitSearcher
<PetWithIdCheck
>, TypeMapContainer
<AllObjectTypes
> > object_checker(checker
);
1210 CellLock
<GridReadGuard
> cell_lock(cell
, p
);
1211 cell_lock
->Visit(cell_lock
, object_checker
, *MapManager::Instance().GetMap(m_caster
->GetMapId()));
1214 if (old_wild
) // find old critter, unsummon
1216 old_wild
->Remove(PET_SAVE_AS_DELETED
);
1219 else // in another case summon new
1222 uint32 level
= m_caster
->getLevel();
1224 // level of pet summoned using engineering item based at engineering skill level
1225 if(m_caster
->GetTypeId()==TYPEID_PLAYER
&& m_CastItem
)
1227 ItemPrototype
const *proto
= m_CastItem
->GetProto();
1228 if(proto
&& proto
->RequiredSkill
== SKILL_ENGINERING
)
1230 uint16 skill202
= ((Player
*)m_caster
)->GetSkillValue(SKILL_ENGINERING
);
1238 Pet
* spawnCreature
= new Pet(GUARDIAN_PET
);
1240 if(!spawnCreature
->Create(objmgr
.GenerateLowGuid(HIGHGUID_UNIT
),
1241 m_caster
->GetMapId(),
1242 m_caster
->GetPositionX(),m_caster
->GetPositionY(),
1243 m_caster
->GetPositionZ(),m_caster
->GetOrientation(),
1244 m_spellInfo
->EffectMiscValue
[i
]))
1246 sLog
.outError("no such creature entry %u",m_spellInfo
->EffectMiscValue
[i
]);
1247 delete spawnCreature
;
1251 spawnCreature
->SetUInt64Value(UNIT_FIELD_SUMMONEDBY
,m_caster
->GetGUID());
1252 spawnCreature
->setPowerType(POWER_MANA
);
1253 spawnCreature
->SetPower( POWER_MANA
,28 + 10 * level
);
1254 spawnCreature
->SetMaxPower(POWER_MANA
,28 + 10 * level
);
1255 spawnCreature
->SetUInt32Value(UNIT_NPC_FLAGS
, 0);
1256 spawnCreature
->SetHealth( 28 + 30*level
);
1257 spawnCreature
->SetMaxHealth( 28 + 30*level
);
1258 spawnCreature
->SetLevel(level
);
1259 spawnCreature
->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE
,m_caster
->getFaction());
1260 spawnCreature
->SetUInt32Value(UNIT_FIELD_FLAGS
,0);
1261 spawnCreature
->SetUInt32Value(UNIT_FIELD_BYTES_1
,0);
1262 spawnCreature
->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP
,0);
1263 spawnCreature
->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE
,0);
1264 spawnCreature
->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP
,1000);
1265 spawnCreature
->SetUInt64Value(UNIT_FIELD_CREATEDBY
, m_caster
->GetGUID());
1267 spawnCreature
->SetArmor(level
*50);
1268 spawnCreature
->AIM_Initialize();
1271 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
1272 name
= ((Player
*)m_caster
)->GetName();
1274 name
= ((Creature
*)m_caster
)->GetCreatureInfo()->Name
;
1275 name
.append(petTypeSuffix
[spawnCreature
->getPetType()]);
1276 spawnCreature
->SetName( name
);
1278 spawnCreature
->AddToWorld();
1279 MapManager::Instance().GetMap(m_caster
->GetMapId())->Add((Creature
*)spawnCreature
);
1281 guardians and wilds can't be controled
1282 if(m_caster->GetTypeId() == TYPEID_PLAYER)
1284 m_caster->SetPet(spawnCreature);
1285 ((Player*)m_caster)->PetSpellInitialize();
1286 ((Player*)m_caster)->SavePet();
1292 void Spell::EffectTeleUnitsFaceCaster(uint32 i
)
1297 if(unitTarget
->isInFlight())
1300 uint32 mapid
= m_caster
->GetMapId();
1301 float dis
= GetRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[i
]));
1302 float fx
= m_caster
->GetPositionX() + dis
* cos(m_caster
->GetOrientation());
1303 float fy
= m_caster
->GetPositionY() + dis
* sin(m_caster
->GetOrientation());
1304 // teleport a bit above terrainlevel to avoid falling below it
1305 float fz
= MapManager::Instance ().GetMap(mapid
)->GetHeight(fx
,fy
) + 1.5;
1307 if(unitTarget
->GetTypeId() == TYPEID_PLAYER
)
1308 ((Player
*)unitTarget
)->TeleportTo(mapid
, fx
, fy
, fz
, -m_caster
->GetOrientation(), false);
1310 MapManager::Instance().GetMap(mapid
)->CreatureRelocation((Creature
*)m_caster
, fx
, fy
, fz
, -m_caster
->GetOrientation());
1313 void Spell::EffectLearnSkill(uint32 i
)
1315 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
1320 uint32 skillid
= m_spellInfo
->EffectMiscValue
[i
];
1321 uint16 skillval
= ((Player
*)unitTarget
)->GetPureSkillValue(skillid
);
1322 ((Player
*)unitTarget
)->SetSkill(skillid
,skillval
?skillval
:1,damage
*75);
1325 void Spell::EffectTradeSkill(uint32 i
)
1327 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
1329 // uint32 skillid = m_spellInfo->EffectMiscValue[i];
1330 // uint16 skillmax = ((Player*)unitTarget)->(skillid);
1331 // ((Player*)unitTarget)->SetSkill(skillid,skillval?skillval:1,skillmax+75);
1334 void Spell::EffectEnchantItemPerm(uint32 i
)
1336 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
1341 Player
* p_caster
= (Player
*)m_caster
;
1343 p_caster
->UpdateCraftSkill(m_spellInfo
->Id
);
1345 if (m_spellInfo
->EffectMiscValue
[i
])
1347 uint32 enchant_id
= m_spellInfo
->EffectMiscValue
[i
];
1349 SpellItemEnchantmentEntry
const *pEnchant
= sSpellItemEnchantmentStore
.LookupEntry(enchant_id
);
1353 // item can be in trade slot and have owner diff. from caster
1354 Player
* item_owner
= itemTarget
->GetOwner();
1358 if(item_owner
!=p_caster
&& p_caster
->GetSession()->GetSecurity() > 0 && sWorld
.getConfig(CONFIG_GM_LOG_TRADE
) )
1359 sLog
.outCommand("GM Enchanting: %s (Entry: %d) GM: %s (Account: %u) Player: %s (Account: %u)",
1360 itemTarget
->GetProto()->Name1
,itemTarget
->GetEntry(),
1361 p_caster
->GetName(),p_caster
->GetSession()->GetAccountId(),
1362 item_owner
->GetName(),item_owner
->GetSession()->GetAccountId());
1364 // remove old enchanting before appling new if equiped
1365 if(itemTarget
->IsEquipped())
1366 if(uint32 old_enchant_id
= itemTarget
->GetUInt32Value(ITEM_FIELD_ENCHANTMENT
))
1367 item_owner
->AddItemEnchant(itemTarget
,old_enchant_id
,0,false);
1369 for(int x
=0;x
<3;x
++)
1370 itemTarget
->SetUInt32Value(ITEM_FIELD_ENCHANTMENT
+x
,0);
1372 itemTarget
->SetUInt32Value(ITEM_FIELD_ENCHANTMENT
, enchant_id
);
1374 // add new enchanting if equiped
1375 if(itemTarget
->IsEquipped())
1376 item_owner
->AddItemEnchant(itemTarget
,enchant_id
,0,true);
1378 itemTarget
->SetState(ITEM_CHANGED
);
1382 void Spell::EffectEnchantItemTmp(uint32 i
)
1384 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
1387 Player
* p_caster
= (Player
*)m_caster
;
1392 if (m_spellInfo
->EffectMiscValue
[i
])
1394 uint32 enchant_id
= m_spellInfo
->EffectMiscValue
[i
];
1395 int32 duration
= GetDuration(m_spellInfo
);
1397 duration
= m_spellInfo
->EffectBasePoints
[i
]+1;
1400 SpellItemEnchantmentEntry
const *pEnchant
= sSpellItemEnchantmentStore
.LookupEntry(enchant_id
);
1404 // item can be in trade slot and have owner diff. from caster
1405 Player
* item_owner
= itemTarget
->GetOwner();
1409 if(item_owner
!=p_caster
&& p_caster
->GetSession()->GetSecurity() > 0 && sWorld
.getConfig(CONFIG_GM_LOG_TRADE
) )
1410 sLog
.outCommand("GM Enchanting: %s (Entry: %d) GM: %s (Account: %u) Player: %s (Account: %u)",
1411 itemTarget
->GetProto()->Name1
,itemTarget
->GetEntry(),
1412 p_caster
->GetName(),p_caster
->GetSession()->GetAccountId(),
1413 item_owner
->GetName(),item_owner
->GetSession()->GetAccountId());
1415 // remove old enchanting before applying new if equipped
1416 if(uint32 old_enchant_id
= itemTarget
->GetUInt32Value(ITEM_FIELD_ENCHANTMENT
+1*3))
1418 if(itemTarget
->IsEquipped())
1419 item_owner
->AddItemEnchant(itemTarget
,old_enchant_id
,1,false);
1421 // duration == 0 will remove EnchantDuration
1422 item_owner
->AddEnchantDuration(itemTarget
,1,0);
1425 for(int x
=0;x
<3;x
++)
1426 itemTarget
->SetUInt32Value(ITEM_FIELD_ENCHANTMENT
+1*3+x
,0);
1428 itemTarget
->SetUInt32Value(ITEM_FIELD_ENCHANTMENT
+1*3, enchant_id
);
1429 itemTarget
->SetUInt32Value(ITEM_FIELD_ENCHANTMENT
+1*3+1, duration
*1000);
1430 if(m_spellInfo
->SpellFamilyName
== 8)
1431 itemTarget
->SetUInt32Value(ITEM_FIELD_ENCHANTMENT
+1*3+2, 45+objmgr
.GetSpellRank(m_spellInfo
->Id
)*15);
1433 // add new enchanting if equipped
1434 if(itemTarget
->IsEquipped())
1435 item_owner
->AddItemEnchant(itemTarget
,enchant_id
,1,true);
1437 itemTarget
->SetState(ITEM_CHANGED
);
1440 item_owner
->AddEnchantDuration(itemTarget
,1,duration
*1000);
1444 void Spell::EffectTameCreature(uint32 i
)
1446 if(m_caster
->GetPetGUID())
1452 if(unitTarget
->GetTypeId() == TYPEID_PLAYER
)
1455 Creature
* creatureTarget
= (Creature
*)unitTarget
;
1457 if(creatureTarget
->isPet())
1460 if(m_caster
->getClass() == CLASS_HUNTER
)
1462 creatureTarget
->AttackStop();
1463 if(m_caster
->getVictim()==creatureTarget
)
1464 m_caster
->AttackStop();
1466 creatureTarget
->CombatStop();
1467 creatureTarget
->StopMoving();
1469 // cast finish succesfully
1470 SendChannelUpdate(0);
1473 Pet
* pet
= new Pet(HUNTER_PET
);
1475 pet
->CreateBaseAtCreature(creatureTarget
);
1477 pet
->SetUInt64Value(UNIT_FIELD_SUMMONEDBY
, m_caster
->GetGUID());
1478 pet
->SetUInt64Value(UNIT_FIELD_CREATEDBY
, m_caster
->GetGUID());
1479 pet
->SetMaxPower(POWER_HAPPINESS
,1000000);
1480 pet
->SetPower( POWER_HAPPINESS
,600000);
1481 pet
->setPowerType(POWER_FOCUS
);
1482 pet
->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE
,m_caster
->getFaction());
1483 pet
->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP
,0);
1484 pet
->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE
,0);
1485 pet
->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP
,1000);
1486 pet
->SetUInt32Value(UNIT_FIELD_FLAGS
, UNIT_FLAG_UNKNOWN1
+ UNIT_FLAG_RESTING
+ UNIT_FLAG_RENAME
);
1487 // this enables popup window (pet detals, abandon, rename)
1488 pet
->SetUInt32Value(UNIT_FIELD_PETNUMBER
,1);
1489 // this enables pet detals window (Shift+P)
1490 pet
->AIM_Initialize();
1493 MapManager::Instance().GetMap(pet
->GetMapId())->Add((Creature
*)pet
);
1495 ObjectAccessor::Instance().RemoveCreatureCorpseFromPlayerView(creatureTarget
);
1496 creatureTarget
->setDeathState(JUST_DIED
);
1498 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
1500 m_caster
->SetPet(pet
);
1501 pet
->SavePetToDB(PET_SAVE_AS_CURRENT
);
1502 ((Player
*)m_caster
)->PetSpellInitialize();
1507 void Spell::EffectSummonPet(uint32 i
)
1510 m_caster
->GetClosePoint(NULL
, px
, py
, pz
);
1512 uint32 petentry
= m_spellInfo
->EffectMiscValue
[i
];
1514 Pet
*OldSummon
= m_caster
->GetPet();
1516 // if pet requested type already exist
1520 if(petentry
== 0 || OldSummon
->GetCreatureInfo()->Entry
== petentry
)
1522 // pet in corpse state can't be summoned
1523 if( OldSummon
->isDead() )
1526 MapManager::Instance().GetMap(OldSummon
->GetMapId())->Remove((Creature
*)OldSummon
,false);
1527 OldSummon
->SetMapId(m_caster
->GetMapId());
1528 OldSummon
->Relocate(px
, py
, pz
, OldSummon
->GetOrientation());
1529 MapManager::Instance().GetMap(m_caster
->GetMapId())->Add((Creature
*)OldSummon
);
1531 if(m_caster
->GetTypeId() == TYPEID_PLAYER
&& OldSummon
->isControlled() )
1533 ((Player
*)m_caster
)->PetSpellInitialize();
1538 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
1539 ((Player
*)m_caster
)->RemovePet(OldSummon
,PET_SAVE_AS_DELETED
);
1544 Pet
* NewSummon
= new Pet(m_caster
->getClass() == CLASS_HUNTER
? HUNTER_PET
: SUMMON_PET
);
1546 // petentry==0 for hunter "call pet" (current pet summoned if any)
1547 if(NewSummon
->LoadPetFromDB(m_caster
,petentry
))
1549 NewSummon
->SavePetToDB(PET_SAVE_AS_CURRENT
);
1553 // not error in case fail hunter call pet
1557 CreatureInfo
const* cInfo
= sCreatureStorage
.LookupEntry
<CreatureInfo
>(petentry
);
1561 sLog
.outError("EffectSummonPet: creature entry %u not found.",petentry
);
1565 if( NewSummon
->Create(objmgr
.GenerateLowGuid(HIGHGUID_UNIT
), m_caster
->GetMapId(), px
, py
, pz
+1, m_caster
->GetOrientation(), petentry
))
1567 uint32 petlevel
= m_caster
->getLevel();
1569 NewSummon
->SetUInt64Value(UNIT_FIELD_SUMMONEDBY
, m_caster
->GetGUID());
1570 NewSummon
->SetUInt64Value(UNIT_FIELD_CREATEDBY
, m_caster
->GetGUID());
1571 NewSummon
->SetUInt32Value(UNIT_NPC_FLAGS
, 0);
1572 NewSummon
->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE
,m_caster
->getFaction());
1573 NewSummon
->SetUInt32Value(UNIT_FIELD_BYTES_0
,2048);
1574 NewSummon
->SetUInt32Value(UNIT_FIELD_BYTES_1
,0);
1575 NewSummon
->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP
,5);
1576 NewSummon
->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE
,0);
1577 NewSummon
->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP
,1000);
1578 NewSummon
->SetUInt32Value(UNIT_CREATED_BY_SPELL
, m_spellInfo
->Id
);
1579 NewSummon
->SetUInt32Value(UNIT_FIELD_PETNUMBER
,1); // this enables pet detals window (Shift+P)
1581 // this enables popup window (pet dismiss, cancel), hunter pet additinal flags set later
1582 NewSummon
->SetUInt32Value(UNIT_FIELD_FLAGS
,UNIT_FLAG_UNKNOWN1
);
1584 NewSummon
->InitStatsForLevel( petlevel
);
1586 for(uint32 i
=0; i
< CREATURE_MAX_SPELLS
; i
++)
1587 NewSummon
->m_spells
[i
] = 0;
1589 if(petentry
== 416) //imp
1591 NewSummon
->m_spells
[0] = 3110; //3110---fire bolt 1
1592 NewSummon
->AddActState(STATE_RA_SPELL1
);
1595 // generate new name for summon pet
1596 if(NewSummon
->getPetType()==SUMMON_PET
)
1598 std::string new_name
=objmgr
.GeneratePetName(petentry
);
1600 NewSummon
->SetName(new_name
);
1602 else if(NewSummon
->getPetType()==HUNTER_PET
)
1604 // this enables popup window (pet detals, abandon, rename)
1605 NewSummon
->SetFlag(UNIT_FIELD_FLAGS
,(UNIT_FLAG_RESTING
| UNIT_FLAG_RENAME
));
1608 NewSummon
->AIM_Initialize();
1610 NewSummon
->AddToWorld();
1611 MapManager::Instance().GetMap(NewSummon
->GetMapId())->Add((Creature
*)NewSummon
);
1613 m_caster
->SetPet(NewSummon
);
1614 sLog
.outDebug("New Pet has guid %u", NewSummon
->GetGUIDLow());
1616 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
1618 NewSummon
->SavePetToDB(PET_SAVE_AS_CURRENT
);
1619 ((Player
*)m_caster
)->PetSpellInitialize();
1626 void Spell::EffectLearnPetSpell(uint32 i
)
1628 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
1631 Player
*_player
= (Player
*)m_caster
;
1633 Pet
*pet
= _player
->GetPet();
1639 SpellEntry
const *learn_spellproto
= sSpellStore
.LookupEntry(m_spellInfo
->EffectTriggerSpell
[i
]);
1640 if(!learn_spellproto
)
1643 for(int8 x
=0;x
<4;x
++)
1645 SpellEntry
const *has_spellproto
= sSpellStore
.LookupEntry(pet
->m_spells
[x
]);
1648 pet
->m_spells
[x
] = learn_spellproto
->Id
;
1651 else if(has_spellproto
->SpellIconID
== learn_spellproto
->SpellIconID
)
1653 pet
->m_spells
[x
] = learn_spellproto
->Id
;
1657 pet
->SavePetToDB(PET_SAVE_AS_CURRENT
);
1658 _player
->PetSpellInitialize();
1661 void Spell::EffectAttackMe(uint32 i
)
1663 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
1665 unitTarget
->SetInFront(m_caster
);
1666 ((Creature
*)unitTarget
)->AI().AttackStart(m_caster
);
1670 void Spell::EffectWeaponDmg(uint32 i
)
1674 if(!unitTarget
->isAlive())
1677 uint32 wp
[4] = { SPELL_EFFECT_WEAPON_DAMAGE
, SPELL_EFFECT_WEAPON_PERCENT_DAMAGE
, SPELL_EFFECT_NORMALIZED_WEAPON_DMG
, SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL
};
1679 // multiple weap dmg effect workaround
1680 // execute only the first weapon damage
1681 // and handle all effects at once
1685 for (j
= 0; j
< 3; j
++)
1687 for (k
= 0; k
< 4; k
++)
1688 if (m_spellInfo
->Effect
[j
] == wp
[k
])
1694 if (m_spellInfo
->Effect
[j
] != SPELL_EFFECT_WEAPON_PERCENT_DAMAGE
)
1695 bonus
+= m_spellInfo
->EffectBasePoints
[j
]+1;
1699 WeaponAttackType attType
= BASE_ATTACK
;
1700 if(m_spellInfo
->rangeIndex
!= 1 && m_spellInfo
->rangeIndex
!= 2 && m_spellInfo
->rangeIndex
!= 7)
1701 attType
= RANGED_ATTACK
;
1704 uint32 nohitMask
= HITINFO_ABSORB
| HITINFO_RESIST
| HITINFO_MISS
;
1705 uint32 damageType
= NORMAL_DAMAGE
;
1706 uint32 victimState
= VICTIMSTATE_NORMAL
;
1707 uint32 eff_damage
= 0;
1708 uint32 blocked_dmg
= 0;
1709 uint32 absorbed_dmg
= 0;
1710 uint32 resisted_dmg
= 0;
1711 bool criticalhit
= false;
1713 if( unitTarget
->IsImmunedToPhysicalDamage() )
1715 m_caster
->SendAttackStateUpdate (HITINFO_MISS
, unitTarget
, 1, NORMAL_DAMAGE
, 0, 0, 0, VICTIMSTATE_IS_IMMUNE
, 0);
1719 m_caster
->DoAttackDamage(unitTarget
, &eff_damage
, &blocked_dmg
, &damageType
, &hitInfo
, &victimState
, &absorbed_dmg
, &resisted_dmg
, attType
, m_spellInfo
, m_IsTriggeredSpell
);
1721 // not add bonus to 0 damage
1722 if( eff_damage
> 0 && eff_damage
+ bonus
> 0 )
1723 eff_damage
+= bonus
;
1727 for (j
= 0; j
< 3; j
++)
1728 if (m_spellInfo
->Effect
[j
] == SPELL_EFFECT_WEAPON_PERCENT_DAMAGE
)
1729 eff_damage
= uint32(eff_damage
* (m_spellInfo
->EffectBasePoints
[j
]+1) / 100);
1731 if ((hitInfo
& nohitMask
) && attType
!= RANGED_ATTACK
) // not send ranged miss/etc
1732 m_caster
->SendAttackStateUpdate(hitInfo
& nohitMask
, unitTarget
, 1, m_spellInfo
->School
, eff_damage
, absorbed_dmg
, resisted_dmg
, 1, blocked_dmg
);
1734 if(hitInfo
& HITINFO_CRITICALHIT
)
1737 m_caster
->SendSpellNonMeleeDamageLog(unitTarget
, m_spellInfo
->Id
, eff_damage
, m_spellInfo
->School
, absorbed_dmg
, resisted_dmg
, false, blocked_dmg
, criticalhit
);
1739 if (eff_damage
> (absorbed_dmg
+ resisted_dmg
+ blocked_dmg
))
1740 eff_damage
-= (absorbed_dmg
+ resisted_dmg
+ blocked_dmg
);
1744 m_caster
->DealDamage(unitTarget
, eff_damage
, SPELL_DIRECT_DAMAGE
, 0, NULL
, 0, true);
1747 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
1749 if(m_spellInfo
->rangeIndex
!= 1 && m_spellInfo
->rangeIndex
!= 2 && m_spellInfo
->rangeIndex
!= 7)
1751 Item
*pItem
= ((Player
*)m_caster
)->GetItemByPos( INVENTORY_SLOT_BAG_0
, EQUIPMENT_SLOT_RANGED
);
1752 if(!pItem
|| pItem
->IsBroken())
1755 if( pItem
->GetProto()->InventoryType
== INVTYPE_THROWN
)
1758 ((Player
*)m_caster
)->DestroyItemCount( pItem
, count
, true);
1761 if(uint32 ammo
= ((Player
*)m_caster
)->GetUInt32Value(PLAYER_AMMO_ID
))
1762 ((Player
*)m_caster
)->DestroyItemCount( ammo
, 1, true);
1763 // wand not have ammo
1767 /*if(m_spellInfo->Effect[i] == 121)
1769 m_caster->resetAttackTimer(BASE_ATTACK);
1770 m_caster->resetAttackTimer(OFF_ATTACK);
1771 m_caster->resetAttackTimer(RANGED_ATTACK);
1775 void Spell::EffectThreat(uint32 i
)
1777 if(!unitTarget
|| !unitTarget
->isAlive() || !m_caster
->isAlive())
1780 if(!unitTarget
->CanHaveThreatList())
1783 unitTarget
->AddThreat(m_caster
, float(damage
));
1786 void Spell::EffectHealMaxHealth(uint32 i
)
1790 if(!unitTarget
->isAlive())
1793 uint32 heal
= m_caster
->GetMaxHealth();
1795 unitTarget
->ModifyHealth(heal
);
1797 if(unitTarget
->GetTypeId() == TYPEID_PLAYER
)
1798 SendHealSpellOnPlayer((Player
*)unitTarget
, m_spellInfo
->Id
, heal
);
1801 void Spell::EffectInterruptCast(uint32 i
)
1805 if(!unitTarget
->isAlive())
1808 // TODO: not all spells that used this effect apply cooldown at school spells
1809 // also exist case: apply cooldown to interupted cast only and to all spells
1810 if (unitTarget
->m_currentSpell
&& unitTarget
->m_currentSpell
->m_spellInfo
)
1812 unitTarget
->ProhibitSpellScholl(unitTarget
->m_currentSpell
->m_spellInfo
->School
, GetDuration(m_spellInfo
));
1813 unitTarget
->InterruptSpell();
1817 void Spell::EffectSummonObjectWild(uint32 i
)
1819 GameObject
* pGameObj
= new GameObject();
1821 uint32 gameobject_id
= m_spellInfo
->EffectMiscValue
[i
];
1823 WorldObject
* target
= focusObject
;
1827 if(!pGameObj
->Create(objmgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), gameobject_id
, target
->GetMapId(),
1828 target
->GetPositionX(), target
->GetPositionY(), target
->GetPositionZ(),
1829 target
->GetOrientation(), 0, 0, 0, 0, 0, 0))
1835 int32 duration
= GetDuration(m_spellInfo
);
1836 pGameObj
->SetRespawnTime(duration
> 0 ? duration
/1000 : 0);
1838 m_caster
->AddGameObject(pGameObj
);
1839 pGameObj
->AddToWorld();
1840 MapManager::Instance().GetMap(pGameObj
->GetMapId())->Add(pGameObj
);
1843 void Spell::EffectScriptEffect(uint32 i
)
1845 if(!m_spellInfo
->Reagent
[0])
1847 // paladin's holy light / flash of light
1848 if ((m_spellInfo
->SpellFamilyName
== SPELLFAMILY_PALADIN
) &&
1849 (m_spellInfo
->SpellIconID
== 70 || m_spellInfo
->SpellIconID
== 242))
1852 if(m_spellInfo
->SpellFamilyName
== SPELLFAMILY_PALADIN
&& (m_spellInfo
->SpellFamilyFlags
& (1<<23)))
1854 // paladin's judgement
1855 if(!unitTarget
|| !unitTarget
->isAlive())
1857 uint32 spellId2
= 0;
1858 Unit::AuraMap
& m_auras
= m_caster
->GetAuras();
1859 Unit::AuraMap::iterator itr
,next
;
1861 for(itr
= m_auras
.begin(); itr
!= m_auras
.end(); itr
= next
)
1867 SpellEntry
const *spellInfo
= itr
->second
->GetSpellProto();
1868 if (!spellInfo
) continue;
1869 if (spellInfo
->SpellVisual
!= 5622 || spellInfo
->SpellFamilyName
!= SPELLFAMILY_PALADIN
) continue;
1870 spellId2
= spellInfo
->EffectBasePoints
[2]+1;
1873 m_caster
->RemoveAurasDueToSpell(spellInfo
->Id
);
1874 next
= m_auras
.begin();
1879 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(spellId2
);
1882 Spell
spell(m_caster
,spellInfo
,true,0);
1884 SpellCastTargets targets
;
1885 Unit
*ptarget
= unitTarget
;
1886 targets
.setUnitTarget(ptarget
);
1887 spell
.prepare(&targets
);
1893 switch(m_spellInfo
->Id
)
1896 itemtype
= 5512; //spell 6261; //primary healstone
1899 itemtype
= 5511; //spell 6262; //inferior healstone
1902 itemtype
= 5509; //spell 5720; //healstone
1905 itemtype
= 5510; //spell 5723; //strong healstone
1908 itemtype
= 9421; //spell 11732; //super healstone
1913 DoCreateItem( i
, itemtype
);
1917 void Spell::EffectSanctuary(uint32 i
)
1921 unitTarget
->CombatStop();
1924 void Spell::EffectAddComboPoints(uint32 i
)
1929 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
1935 uint8 comboPoints
= ((m_caster
->GetUInt32Value(PLAYER_FIELD_BYTES
) & 0xFF00) >> 8);
1936 if(m_caster
->GetUInt64Value(PLAYER_FIELD_COMBO_TARGET
) != unitTarget
->GetGUID())
1938 comboPoints
= damage
;
1939 m_caster
->SetUInt64Value(PLAYER_FIELD_COMBO_TARGET
,unitTarget
->GetGUID());
1940 m_caster
->SetUInt32Value(PLAYER_FIELD_BYTES
,((m_caster
->GetUInt32Value(PLAYER_FIELD_BYTES
) & ~(0xFF << 8)) | (comboPoints
<< 8)));
1942 else if(comboPoints
< 5)
1944 comboPoints
+= damage
;
1947 m_caster
->SetUInt32Value(PLAYER_FIELD_BYTES
,((m_caster
->GetUInt32Value(PLAYER_FIELD_BYTES
) & ~(0xFF << 8)) | (comboPoints
<< 8)));
1952 void Spell::EffectDuel(uint32 i
)
1954 if(!m_caster
|| !unitTarget
|| m_caster
->GetTypeId() != TYPEID_PLAYER
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
1957 Player
*caster
= (Player
*)m_caster
;
1958 Player
*target
= (Player
*)unitTarget
;
1960 // caster or target already have requested duel
1961 if( caster
->duel
|| target
->duel
|| target
->HasInIgnoreList(caster
->GetGUID()) )
1964 //CREATE DUEL FLAG OBJECT
1965 GameObject
* pGameObj
= new GameObject();
1967 uint32 gameobject_id
= m_spellInfo
->EffectMiscValue
[i
];
1969 if(!pGameObj
->Create(objmgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), gameobject_id
,m_caster
->GetMapId(),
1970 m_caster
->GetPositionX()+(unitTarget
->GetPositionX()-m_caster
->GetPositionX())/2 ,
1971 m_caster
->GetPositionY()+(unitTarget
->GetPositionY()-m_caster
->GetPositionY())/2 ,
1972 m_caster
->GetPositionZ(),
1973 m_caster
->GetOrientation(), 0, 0, 0, 0, 0, 0))
1978 pGameObj
->SetFloatValue(OBJECT_FIELD_SCALE_X
,1.0f
);
1980 pGameObj
->SetUInt32Value(GAMEOBJECT_DISPLAYID
, 787 );
1981 pGameObj
->SetUInt32Value(GAMEOBJECT_FACTION
, m_caster
->getFaction() );
1982 pGameObj
->SetUInt32Value(GAMEOBJECT_TYPE_ID
, 16 );
1983 pGameObj
->SetUInt32Value(GAMEOBJECT_LEVEL
, m_caster
->getLevel()+1 );
1984 int32 duration
= GetDuration(m_spellInfo
);
1985 pGameObj
->SetRespawnTime(duration
> 0 ? duration
/1000 : 0);
1986 pGameObj
->SetSpellId(m_spellInfo
->Id
);
1988 m_caster
->AddGameObject(pGameObj
);
1989 pGameObj
->AddToWorld();
1990 MapManager::Instance().GetMap(pGameObj
->GetMapId())->Add(pGameObj
);
1994 WorldPacket
data(SMSG_DUEL_REQUESTED
, 16);
1995 data
<< pGameObj
->GetGUID();
1996 data
<< caster
->GetGUID();
1997 caster
->GetSession()->SendPacket(&data
);
1998 target
->GetSession()->SendPacket(&data
);
2001 DuelInfo
*duel
= new DuelInfo
;
2002 duel
->initiator
= caster
;
2003 duel
->opponent
= target
;
2004 duel
->startTime
= 0;
2005 duel
->startTimer
= 0;
2006 caster
->duel
= duel
;
2008 DuelInfo
*duel2
= new DuelInfo
;
2009 duel2
->initiator
= caster
;
2010 duel2
->opponent
= caster
;
2011 duel2
->startTime
= 0;
2012 duel2
->startTimer
= 0;
2013 target
->duel
= duel2
;
2015 caster
->SetUInt64Value(PLAYER_DUEL_ARBITER
,pGameObj
->GetGUID());
2016 target
->SetUInt64Value(PLAYER_DUEL_ARBITER
,pGameObj
->GetGUID());
2020 void Spell::EffectSummonTotem(uint32 i
)
2023 switch(m_spellInfo
->Effect
[i
])
2025 case SPELL_EFFECT_SUMMON_TOTEM_SLOT1
: slot
= 0; break;
2026 case SPELL_EFFECT_SUMMON_TOTEM_SLOT2
: slot
= 1; break;
2027 case SPELL_EFFECT_SUMMON_TOTEM_SLOT3
: slot
= 2; break;
2028 case SPELL_EFFECT_SUMMON_TOTEM_SLOT4
: slot
= 3; break;
2032 float angle
= m_caster
->GetOrientation() + M_PI
/4 - (slot
*M_PI
/2);
2033 float x
= m_caster
->GetPositionX() + 2 * cos(angle
);
2034 float y
= m_caster
->GetPositionY() + 2 * sin(angle
);
2035 float z
= m_caster
->GetPositionZ();
2037 Map
* map
= MapManager::Instance().GetMap(m_caster
->GetMapId());
2038 float z2
= map
->GetHeight(x
,y
);
2039 if( abs( z2
- z
) < 5 )
2042 uint64 guid
= m_caster
->m_TotemSlot
[slot
];
2045 Creature
*OldTotem
= ObjectAccessor::Instance().GetCreature(*m_caster
, guid
);
2046 if(OldTotem
&& OldTotem
->isTotem()) ((Totem
*)OldTotem
)->UnSummon();
2047 m_caster
->m_TotemSlot
[slot
] = 0;
2050 Totem
* pTotem
= new Totem();
2052 if(!pTotem
->Create(objmgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
),
2053 m_caster
->GetMapId(), x
, y
, z
, m_caster
->GetOrientation(),
2054 m_spellInfo
->EffectMiscValue
[i
] ))
2060 m_caster
->m_TotemSlot
[slot
] = pTotem
->GetGUID();
2061 pTotem
->SetOwner(m_caster
->GetGUID());
2062 //pTotem->SetSpell(pTotem->GetCreatureInfo()->spell1);
2063 pTotem
->SetSpell(m_spellInfo
->Id
); //use SummonTotem spellid
2064 pTotem
->SetDuration(GetDuration(m_spellInfo
));
2065 pTotem
->SetHealth(5);
2066 pTotem
->SetMaxHealth(5);
2070 void Spell::EffectEnchantHeldItem(uint32 i
)
2072 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
2075 Player
* p_caster
= (Player
*)m_caster
;
2081 if(!itemTarget
->IsEquipped())
2084 if (m_spellInfo
->EffectMiscValue
[i
])
2086 uint32 enchant_id
= m_spellInfo
->EffectMiscValue
[i
];
2087 int32 duration
= GetDuration(m_spellInfo
);
2089 duration
= m_spellInfo
->EffectBasePoints
[i
]+1;
2092 SpellItemEnchantmentEntry
const *pEnchant
= sSpellItemEnchantmentStore
.LookupEntry(enchant_id
);
2096 // can be held by another player and accessable to caster in trade slot
2097 Player
* item_owner
= itemTarget
->GetOwner();
2101 if(item_owner
!=p_caster
&& p_caster
->GetSession()->GetSecurity() > 0 && sWorld
.getConfig(CONFIG_GM_LOG_TRADE
) )
2102 sLog
.outCommand("GM Enchanting: %s (Entry: %d) GM: %s (Account: %u) Player: %s (Account: %u)",
2103 itemTarget
->GetProto()->Name1
,itemTarget
->GetEntry(),
2104 p_caster
->GetName(),p_caster
->GetSession()->GetAccountId(),
2105 item_owner
->GetName(),item_owner
->GetSession()->GetAccountId());
2107 // remove old enchanting before appling new
2108 if(uint32 old_enchant_id
= itemTarget
->GetUInt32Value(ITEM_FIELD_ENCHANTMENT
+pEnchant
->display_type
*3))
2109 item_owner
->AddItemEnchant(itemTarget
,old_enchant_id
,pEnchant
->display_type
,false);
2111 for(int x
=0;x
<3;x
++)
2112 itemTarget
->SetUInt32Value(ITEM_FIELD_ENCHANTMENT
+pEnchant
->display_type
*3+x
,0);
2114 itemTarget
->SetUInt32Value(ITEM_FIELD_ENCHANTMENT
+pEnchant
->display_type
*3, enchant_id
);
2115 itemTarget
->SetUInt32Value(ITEM_FIELD_ENCHANTMENT
+pEnchant
->display_type
*3+1, duration
*1000);
2116 itemTarget
->SetState(ITEM_CHANGED
);
2118 // add new enchanting
2119 item_owner
->AddItemEnchant(itemTarget
,enchant_id
,pEnchant
->display_type
,true);
2122 item_owner
->AddEnchantDuration(itemTarget
,1,duration
*1000);
2126 void Spell::EffectDisEnchant(uint32 i
)
2128 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
2131 Player
* p_caster
= (Player
*)m_caster
;
2132 if(!itemTarget
|| !itemTarget
->GetProto()->DisenchantID
)
2135 p_caster
->UpdateCraftSkill(m_spellInfo
->Id
);
2137 ((Player
*)m_caster
)->SendLoot(itemTarget
->GetGUID(),LOOT_DISENCHANTING
);
2139 // item will be removed at disenchanting end
2142 void Spell::EffectInebriate(uint32 i
)
2144 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
2147 Player
*player
= (Player
*)m_caster
;
2148 uint16 currentDrunk
= player
->GetDrunkValue();
2149 uint16 drunkMod
= (m_spellInfo
->EffectBasePoints
[i
]+1) * 0xFFFF / 100;
2150 if (currentDrunk
+ drunkMod
> 0xFFFF)
2151 currentDrunk
= 0xFFFF;
2153 currentDrunk
+= drunkMod
;
2154 player
->SetDrunkValue(currentDrunk
);
2157 void Spell::EffectFeedPet(uint32 i
)
2159 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
2162 Player
*_player
= (Player
*)m_caster
;
2167 Creature
*pet
= _player
->GetPet();
2174 pet
->ModifyPower(POWER_HAPPINESS
,damage
);
2177 _player
->DestroyItemCount(itemTarget
,count
,true);
2179 SpellEntry
const *spellinfo
= sSpellStore
.LookupEntry(m_spellInfo
->EffectTriggerSpell
[i
]);
2180 Spell
_spell(m_caster
, spellinfo
, true, 0);
2181 SpellCastTargets targets
;
2182 targets
.setUnitTarget(m_caster
);
2183 _spell
.prepare(&targets
);
2186 void Spell::EffectDismissPet(uint32 i
)
2188 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
2191 Pet
* pet
= m_caster
->GetPet();
2193 // not let dismiss dead pet
2194 if(!pet
||!pet
->isAlive())
2197 ((Player
*)m_caster
)->RemovePet(pet
,PET_SAVE_AS_CURRENT
);
2200 void Spell::EffectSummonObject(uint32 i
)
2203 switch(m_spellInfo
->Effect
[i
])
2205 case SPELL_EFFECT_SUMMON_OBJECT_SLOT1
: slot
= 0; break;
2206 case SPELL_EFFECT_SUMMON_OBJECT_SLOT2
: slot
= 1; break;
2207 case SPELL_EFFECT_SUMMON_OBJECT_SLOT3
: slot
= 2; break;
2208 case SPELL_EFFECT_SUMMON_OBJECT_SLOT4
: slot
= 3; break;
2212 uint64 guid
= m_caster
->m_ObjectSlot
[slot
];
2215 GameObject
* obj
= NULL
;
2217 obj
= ObjectAccessor::Instance().GetGameObject(*m_caster
, guid
);
2219 if(obj
) obj
->Delete();
2220 m_caster
->m_ObjectSlot
[slot
] = 0;
2223 GameObject
* pGameObj
= new GameObject();
2224 uint32 display_id
= m_spellInfo
->EffectMiscValue
[i
];
2226 float rot2
= sin(m_caster
->GetOrientation()/2);
2227 float rot3
= cos(m_caster
->GetOrientation()/2);
2229 if(!pGameObj
->Create(objmgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), display_id
,m_caster
->GetMapId(), m_caster
->GetPositionX(), m_caster
->GetPositionY(), m_caster
->GetPositionZ(), m_caster
->GetOrientation(), 0, 0, rot2
, rot3
, 0, 0))
2235 pGameObj
->SetUInt32Value(GAMEOBJECT_LEVEL
,m_caster
->getLevel());
2236 int32 duration
= GetDuration(m_spellInfo
);
2237 pGameObj
->SetRespawnTime(duration
> 0 ? duration
/1000 : 0);
2238 pGameObj
->SetSpellId(m_spellInfo
->Id
);
2239 pGameObj
->SetLootState(GO_CLOSED
);
2240 m_caster
->AddGameObject(pGameObj
);
2242 pGameObj
->AddToWorld();
2243 MapManager::Instance().GetMap(pGameObj
->GetMapId())->Add(pGameObj
);
2244 WorldPacket
data(SMSG_GAMEOBJECT_SPAWN_ANIM
, 8);
2245 data
<< pGameObj
->GetGUID();
2246 m_caster
->SendMessageToSet(&data
,true);
2248 m_caster
->m_ObjectSlot
[slot
] = pGameObj
->GetGUID();
2251 void Spell::EffectResurrect(uint32 i
)
2256 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
2259 if(unitTarget
->isAlive())
2261 if(!unitTarget
->IsInWorld())
2264 Player
* pTarget
= ((Player
*)unitTarget
);
2266 uint32 health
= m_spellInfo
->EffectBasePoints
[i
]+1;
2267 uint32 mana
= m_spellInfo
->EffectMiscValue
[i
];
2269 ((Player
*)unitTarget
)->setResurrect(m_caster
->GetGUID(), m_caster
->GetPositionX(), m_caster
->GetPositionY(), m_caster
->GetPositionZ(), health
, mana
);
2270 SendResurrectRequest(pTarget
);
2273 void Spell::EffectParry(uint32 i
)
2275 if (unitTarget
->GetTypeId() == TYPEID_PLAYER
)
2277 ((Player
*)unitTarget
)->SetCanParry(true);
2281 void Spell::EffectMomentMove(uint32 i
)
2283 if(unitTarget
->isInFlight())
2286 if( m_spellInfo
->rangeIndex
== 1) //self range
2288 uint32 mapid
= m_caster
->GetMapId();
2289 float dis
= GetRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[i
]));
2290 float fx
= m_caster
->GetPositionX() + dis
* cos(m_caster
->GetOrientation());
2291 float fy
= m_caster
->GetPositionY() + dis
* sin(m_caster
->GetOrientation());
2292 // teleport a bit above terrainlevel to avoid falling below it
2293 float fz
= MapManager::Instance ().GetMap(mapid
)->GetHeight(fx
,fy
) + 1.5;
2295 if(unitTarget
->GetTypeId() == TYPEID_PLAYER
)
2296 ((Player
*)unitTarget
)->TeleportTo(mapid
, fx
, fy
, fz
, m_caster
->GetOrientation(), false);
2298 MapManager::Instance().GetMap(mapid
)->CreatureRelocation((Creature
*)m_caster
, fx
, fy
, fz
, m_caster
->GetOrientation());
2302 void Spell::EffectReputation(uint32 i
)
2304 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
2307 Player
*_player
= (Player
*)m_caster
;
2309 int32 rep_change
= m_spellInfo
->EffectBasePoints
[i
]+1; // field store reputation change -1
2311 uint32 faction_id
= m_spellInfo
->EffectMiscValue
[i
];
2313 FactionEntry
const* factionEntry
= sFactionStore
.LookupEntry(faction_id
);
2318 _player
->ModifyFactionReputation(factionEntry
,rep_change
);
2321 void Spell::EffectQuestComplete(uint32 i
)
2323 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
2326 Player
*_player
= (Player
*)m_caster
;
2328 uint32 quest_id
= m_spellInfo
->EffectMiscValue
[i
];
2330 if(_player
->CanCompleteQuest( quest_id
) )
2331 _player
->CompleteQuest( quest_id
);
2335 if(_player
->GetQuestRewardStatus( quest_id
))
2338 _player
->PlayerTalkClass
->SendQuestGiverOfferReward( quest_id
, _player
->GetGUID(), true, NULL
, 0 );
2341 void Spell::EffectSelfResurrect(uint32 i
)
2343 if(!unitTarget
) return;
2344 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
) return;
2345 if(unitTarget
->isAlive()) return;
2346 if(!unitTarget
->IsInWorld()) return;
2351 if(m_spellInfo
->SpellVisual
== 99 && m_spellInfo
->SpellIconID
==1)
2353 health
= m_spellInfo
->EffectBasePoints
[i
]+1 > 0 ? m_spellInfo
->EffectBasePoints
[i
]+1 :(-(m_spellInfo
->EffectBasePoints
[i
]+1));
2354 if(unitTarget
->getPowerType() == POWER_MANA
)
2355 mana
= m_spellInfo
->EffectMiscValue
[i
];
2359 if(damage
< 0) return;
2360 health
= uint32(damage
/100*unitTarget
->GetMaxHealth());
2361 if(unitTarget
->getPowerType() == POWER_MANA
)
2362 mana
= uint32(damage
/100*unitTarget
->GetMaxPower(unitTarget
->getPowerType()));
2364 ((Player
*)unitTarget
)->setResurrect(m_caster
->GetGUID(), m_caster
->GetPositionX(), m_caster
->GetPositionY(), m_caster
->GetPositionZ(), health
, mana
);
2365 SendResurrectRequest((Player
*)unitTarget
);
2368 void Spell::EffectSkinning(uint32 i
)
2370 if(unitTarget
->GetTypeId() != TYPEID_UNIT
)
2372 if(!m_caster
|| m_caster
->GetTypeId() != TYPEID_PLAYER
)
2375 int32 targetLevel
= unitTarget
->getLevel();
2377 ((Player
*)m_caster
)->SendLoot(unitTarget
->GetGUID(),LOOT_SKINNING
);
2378 unitTarget
->RemoveFlag(UNIT_FIELD_FLAGS
, UNIT_FLAG_SKINNABLE
);
2380 int32 reqValue
= targetLevel
< 10 ? 0 : targetLevel
< 20 ? (targetLevel
-10)*10 : targetLevel
*5;
2382 int32 skinningValue
= ((Player
*)m_caster
)->GetPureSkillValue(SKILL_SKINNING
);
2384 // Double chances for elites
2385 ((Player
*)m_caster
)->UpdateGatherSkill(SKILL_SKINNING
, skinningValue
, reqValue
, ((Creature
*)unitTarget
)->isElite() ? 2 : 1 );
2388 void Spell::EffectCharge(uint32 i
)
2390 if(!unitTarget
|| !m_caster
)
2394 unitTarget
->GetClosePoint(m_caster
, x
, y
, z
);
2395 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
2396 ((Creature
*)unitTarget
)->StopMoving();
2398 m_caster
->SendMonsterMove(x
, y
, z
, false,true,1);
2399 m_caster
->Attack(unitTarget
);
2402 void Spell::EffectSummonCritter(uint32 i
)
2404 uint32 pet_entry
= m_spellInfo
->EffectMiscValue
[i
];
2408 Unit
* old_critter
= NULL
;
2411 CellPair
p(MaNGOS::ComputeCellPair(m_caster
->GetPositionX(), m_caster
->GetPositionY()));
2412 Cell cell
= RedZone::GetZone(p
);
2413 cell
.data
.Part
.reserved
= ALL_DISTRICT
;
2416 PetWithIdCheck
u_check(m_caster
, pet_entry
);
2417 MaNGOS::UnitSearcher
<PetWithIdCheck
> checker(old_critter
, u_check
);
2418 TypeContainerVisitor
<MaNGOS::UnitSearcher
<PetWithIdCheck
>, TypeMapContainer
<AllObjectTypes
> > object_checker(checker
);
2419 CellLock
<GridReadGuard
> cell_lock(cell
, p
);
2420 cell_lock
->Visit(cell_lock
, object_checker
, *MapManager::Instance().GetMap(m_caster
->GetMapId()));
2423 if (old_critter
) // find old critter, unsummon
2425 // PetWithIdCheck return only Pets
2426 ((Pet
*)old_critter
)->Remove(PET_SAVE_AS_DELETED
);
2429 else // in another case summon new
2431 Pet
* critter
= new Pet(MINI_PET
);
2433 if(!critter
->Create(objmgr
.GenerateLowGuid(HIGHGUID_UNIT
),
2434 m_caster
->GetMapId(),
2435 m_caster
->GetPositionX(),m_caster
->GetPositionY(),
2436 m_caster
->GetPositionZ(),m_caster
->GetOrientation(),
2437 m_spellInfo
->EffectMiscValue
[i
]))
2439 sLog
.outError("no such creature entry %u",m_spellInfo
->EffectMiscValue
[i
]);
2444 critter
->SetUInt64Value(UNIT_FIELD_SUMMONEDBY
,m_caster
->GetGUID());
2445 critter
->SetUInt64Value(UNIT_FIELD_CREATEDBY
,m_caster
->GetGUID());
2446 critter
->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE
,m_caster
->getFaction());
2448 critter
->AIM_Initialize();
2451 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
2452 name
= ((Player
*)m_caster
)->GetName();
2454 name
= ((Creature
*)m_caster
)->GetCreatureInfo()->Name
;
2455 name
.append(petTypeSuffix
[critter
->getPetType()]);
2456 critter
->SetName( name
);
2457 //m_caster->SetPet(critter);
2459 critter
->AddToWorld();
2460 MapManager::Instance().GetMap(m_caster
->GetMapId())->Add((Creature
*)critter
);
2464 void Spell::EffectKnockBack(uint32 i
)
2466 if(!unitTarget
|| !m_caster
)
2469 //Effect only works on players
2470 if(unitTarget
->GetTypeId()!=TYPEID_PLAYER
)
2474 int32 basePoints
= m_spellInfo
->EffectBasePoints
[i
];
2475 int32 randomPoints
= m_spellInfo
->EffectDieSides
[i
];
2476 if (randomPoints
) value
= basePoints
+ rand()%randomPoints
;
2477 else value
= basePoints
;
2479 //Only allowed to knock ourselves straight up to prevent exploiting
2480 if (unitTarget
== m_caster
)value
= 0;
2482 WorldPacket
data(SMSG_MOVE_KNOCK_BACK
, (8+4+4+4+4+4));
2483 data
.append(unitTarget
->GetPackGUID());
2484 data
<< uint32(0); //Sequence
2485 data
<< cos(m_caster
->GetAngle(unitTarget
)); //xdirection
2486 data
<< sin(m_caster
->GetAngle(unitTarget
)); //ydirection
2487 data
<< value
/10; //Horizontal speed
2488 data
<< float(m_spellInfo
->EffectMiscValue
[i
])/-10; //Z Movement speed
2490 ((Player
*)unitTarget
)->SendMessageToSet(&data
,true);
2493 void Spell::EffectSummonDeadPet(uint32 i
)
2495 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
2497 Player
*_player
= (Player
*)m_caster
;
2498 Pet
*pet
= _player
->GetPet();
2505 pet
->SetUInt32Value(UNIT_DYNAMIC_FLAGS
, 0);
2506 pet
->RemoveFlag (UNIT_FIELD_FLAGS
, UNIT_FLAG_SKINNABLE
);
2507 pet
->setDeathState( ALIVE
);
2508 pet
->clearUnitState(UNIT_STAT_ALL_STATE
);
2509 pet
->SetHealth( uint32(pet
->GetMaxHealth()*(float(damage
)/100)));
2511 pet
->AIM_Initialize();
2513 _player
->PetSpellInitialize();
2514 pet
->SavePetToDB(PET_SAVE_AS_CURRENT
);
2517 void Spell::EffectTransmitted(uint32 i
)
2521 float min_dis
= GetMinRange(sSpellRangeStore
.LookupEntry(m_spellInfo
->rangeIndex
));
2522 float max_dis
= GetMaxRange(sSpellRangeStore
.LookupEntry(m_spellInfo
->rangeIndex
));
2523 float diff
= max_dis
- min_dis
+ 1;
2524 float dis
= (float)(rand()%(uint32
)diff
+ (uint32
)min_dis
);
2526 fx
= m_caster
->GetPositionX() + dis
* cos(m_caster
->GetOrientation());
2527 fy
= m_caster
->GetPositionY() + dis
* sin(m_caster
->GetOrientation());
2529 float fz
= MapManager::Instance ().GetMap(m_caster
->GetMapId())->GetHeight(fx
,fy
);
2531 if(m_spellInfo
->EffectMiscValue
[i
] == 35591)
2533 Map
* map
= MapManager::Instance().GetMap(m_caster
->GetMapId());
2534 if ( !map
->IsUnderWater(fx
,fy
,fz
) )
2536 SendCastResult(CAST_FAIL_CANT_BE_CAST_HERE
);
2538 SendChannelUpdate(0);
2542 // replace by water level in this case
2543 fz
= MapManager::Instance ().GetMap(m_caster
->GetMapId())->GetWaterLevel(fx
,fy
);
2547 GameObject
* pGameObj
= new GameObject();
2548 uint32 name_id
= m_spellInfo
->EffectMiscValue
[i
];
2550 if(!pGameObj
->Create(objmgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), name_id
,m_caster
->GetMapId(),
2551 fx
, fy
, fz
, m_caster
->GetOrientation(), 0, 0, 0, 0, 100, 0))
2557 if(m_spellInfo
->EffectMiscValue
[i
] == 35591)
2559 m_caster
->SetUInt32Value(UNIT_FIELD_CHANNEL_OBJECT
,pGameObj
->GetGUIDLow());
2560 m_caster
->SetUInt32Value(UNIT_FIELD_CHANNEL_OBJECT
+1,pGameObj
->GetGUIDHigh());
2562 pGameObj
->SetFloatValue(GAMEOBJECT_ROTATION
+ 2, 0.88431775569915771 );
2564 pGameObj
->SetFloatValue(GAMEOBJECT_ROTATION
+ 3, -0.4668855369091033 );
2565 pGameObj
->SetLootState(GO_NOT_READY
); // bobber not move
2566 m_caster
->AddGameObject(pGameObj
); // will removed at spell cancel
2568 // end time of range when posable catch fish (FISHING_BOBBER_READY_TIME..GetDuration(m_spellInfo))
2569 // start time == fish-FISHING_BOBBER_READY_TIME (0..GetDuration(m_spellInfo)-FISHING_BOBBER_READY_TIME)
2570 uint32 fish
= urand(FISHING_BOBBER_READY_TIME
,GetDuration(m_spellInfo
)/1000);
2571 pGameObj
->SetRespawnTime(fish
);
2575 pGameObj
->SetOwnerGUID(m_caster
->GetGUID() );
2576 int32 duration
= GetDuration(m_spellInfo
);
2577 pGameObj
->SetRespawnTime(duration
> 0 ? duration
/1000 : 0);
2580 pGameObj
->SetUInt32Value(12, 0x3F63BB3C );
2581 pGameObj
->SetUInt32Value(13, 0xBEE9E017 );
2582 pGameObj
->SetUInt32Value(GAMEOBJECT_LEVEL
, m_caster
->getLevel() );
2583 pGameObj
->SetSpellId(m_spellInfo
->Id
);
2585 DEBUG_LOG("AddObject at SpellEfects.cpp EffectTransmitted\n");
2586 //m_caster->AddGameObject(pGameObj);
2587 //m_ObjToDel.push_back(pGameObj);
2589 pGameObj
->AddToWorld();
2590 MapManager::Instance().GetMap(pGameObj
->GetMapId())->Add(pGameObj
);
2592 WorldPacket
data(SMSG_GAMEOBJECT_SPAWN_ANIM
, 8);
2593 data
<< uint64(pGameObj
->GetGUID());
2594 m_caster
->SendMessageToSet(&data
,true);
2597 void Spell::EffectSkill(uint32 i
)
2599 sLog
.outDebug("WORLD: SkillEFFECT");