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::EffectNULL
, //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, false);
203 void Spell::EffectSchoolDMG(uint32 i
)
205 if( unitTarget
&& unitTarget
->isAlive() )
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 // skip non hostile to caster enemy creatures
228 if( !((Creature
*)unitTarget
)->IsHostileTo(m_caster
->getVictim()) )
231 // only from same creature faction
232 if(unitTarget
->getFaction() != m_caster
->getFaction() )
235 // only if enimy is player or pet.
236 if( m_caster
->getVictim()->GetTypeId() == TYPEID_PLAYER
|| ((Creature
*)m_caster
->getVictim())->isPet() )
238 // and finally if creature not figthing currently
239 if( !unitTarget
->isInCombat() )
241 ((Creature
*)m_caster
)->SetNoCallAssistence(true);
242 ((Creature
*)unitTarget
)->SetNoCallAssistence(true);
243 ((Creature
*)unitTarget
)->AI().AttackStart(m_caster
->getVictim());
249 // Preparation Rogue - immediately finishes the cooldown on other Rogue abilities
250 if(m_spellInfo
->Id
== 14185)
252 if(m_caster
->GetTypeId()!=TYPEID_PLAYER
)
255 const PlayerSpellMap
& sp_list
= ((Player
*)m_caster
)->GetSpellMap();
256 for (PlayerSpellMap::const_iterator itr
= sp_list
.begin(); itr
!= sp_list
.end(); ++itr
)
258 uint32 classspell
= itr
->first
;
259 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(classspell
);
261 if (spellInfo
->SpellFamilyName
== SPELLFAMILY_ROGUE
&& spellInfo
->Id
!= 14185 &&
262 (spellInfo
->RecoveryTime
> 0 || spellInfo
->CategoryRecoveryTime
> 0))
264 ((Player
*)m_caster
)->RemoveSpellCooldown(classspell
);
266 WorldPacket
data(SMSG_CLEAR_COOLDOWN
, (4+8+4));
268 data
<< m_caster
->GetGUID();
270 ((Player
*)m_caster
)->GetSession()->SendPacket(&data
);
276 // Cold Snap - immediately finishes the cooldown on Frost spells
277 if(m_spellInfo
->Id
== 12472)
279 if(m_caster
->GetTypeId()!=TYPEID_PLAYER
)
282 const PlayerSpellMap
& sp_list
= ((Player
*)m_caster
)->GetSpellMap();
283 for (PlayerSpellMap::const_iterator itr
= sp_list
.begin(); itr
!= sp_list
.end(); ++itr
)
285 if (itr
->second
->state
== PLAYERSPELL_REMOVED
) continue;
286 uint32 classspell
= itr
->first
;
287 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(classspell
);
289 if (spellInfo
->SpellFamilyName
== SPELLFAMILY_MAGE
&& spellInfo
->School
== SPELL_SCHOOL_FROST
&& spellInfo
->Id
!= 12472 &&
290 (spellInfo
->RecoveryTime
> 0 || spellInfo
->CategoryRecoveryTime
> 0))
292 ((Player
*)m_caster
)->RemoveSpellCooldown(classspell
);
294 WorldPacket
data(SMSG_CLEAR_COOLDOWN
, (4+8+4));
296 data
<< m_caster
->GetGUID();
298 ((Player
*)m_caster
)->GetSession()->SendPacket(&data
);
304 // If spell cannibalize and his casted, check special requirements and cast aura Cannibalize is all ok
305 if(m_spellInfo
->Id
== 20577)
307 // non-standard cast requirement check
308 SpellRangeEntry
const* srange
= sSpellRangeStore
.LookupEntry(m_spellInfo
->rangeIndex
);
309 float max_range
= GetMaxRange(srange
);
311 CellPair
p(MaNGOS::ComputeCellPair(m_caster
->GetPositionX(), m_caster
->GetPositionY()));
312 Cell cell
= RedZone::GetZone(p
);
313 cell
.data
.Part
.reserved
= ALL_DISTRICT
;
318 MaNGOS::CannibalizeUnitCheck
u_check(m_caster
, max_range
);
319 MaNGOS::UnitSearcher
<MaNGOS::CannibalizeUnitCheck
> searcher(result
, u_check
);
321 TypeContainerVisitor
<MaNGOS::UnitSearcher
<MaNGOS::CannibalizeUnitCheck
>, TypeMapContainer
<AllObjectTypes
> > unit_searcher(searcher
);
322 CellLock
<GridReadGuard
> cell_lock(cell
, p
);
323 cell_lock
->Visit(cell_lock
, unit_searcher
, *MapManager::Instance().GetMap(m_caster
->GetMapId()));
327 // clear cooldown at fail
328 if(m_caster
->GetTypeId()==TYPEID_PLAYER
)
330 ((Player
*)m_caster
)->RemoveSpellCooldown(20577);
332 WorldPacket
data(SMSG_CLEAR_COOLDOWN
, (4+8+4));
333 data
<< uint32(20577); // spell id
334 data
<< m_caster
->GetGUID();
336 ((Player
*)m_caster
)->GetSession()->SendPacket(&data
);
339 SendCastResult(CAST_FAIL_NO_NEARBY_CORPSES_TO_EAT
);
343 // ok, main function spell can be casted
345 finish(); // prepere to replacing this cpell cast to main function spell
348 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry( 20578 );
349 Spell
*spell
= new Spell(m_caster
, spellInfo
, false, 0);
352 sLog
.outError("WORLD: unknown spell id %i\n", 20578);
356 SpellCastTargets targets
;
357 targets
.setUnitTarget(m_caster
);
358 spell
->prepare(&targets
);
362 // More generic code later
364 // starshards/curse of agony hack .. this applies to 1.10 only
365 if (m_triggeredByAura
)
367 SpellEntry
const *trig_info
= m_triggeredByAura
->GetSpellProto();
368 if ((trig_info
->SpellIconID
== 1485 && trig_info
->SpellFamilyName
== SPELLFAMILY_PRIEST
) ||
369 (trig_info
->SpellIconID
== 544 && trig_info
->SpellFamilyName
== SPELLFAMILY_WARLOCK
))
371 Unit
*tmpTarget
= unitTarget
;
372 unitTarget
= m_triggeredByAura
->GetTarget();
373 damage
= trig_info
->EffectBasePoints
[i
]+1;
375 unitTarget
= tmpTarget
;
379 //Holy Shock For Paladins
380 if (m_spellInfo
->SpellFamilyName
== SPELLFAMILY_PALADIN
&& m_spellInfo
->SpellIconID
== 156)
385 switch(m_spellInfo
->Id
)
403 if(m_caster
->IsFriendlyTo(unitTarget
))
404 m_caster
->CastSpell(unitTarget
, heal
, true, 0);
406 m_caster
->CastSpell(unitTarget
, hurt
, true, 0);
409 if(m_spellInfo
->SpellIconID
== 1648)
412 dmg
+= uint32(m_caster
->GetPower(POWER_RAGE
)/10 * objmgr
.GetSpellRank(m_spellInfo
->Id
)*3);
413 SpellEntry
const *tspellInfo
= sSpellStore
.LookupEntry(20647);
414 SpellEntry sInfo
= *tspellInfo
;
415 sInfo
.EffectBasePoints
[0] = dmg
;
416 m_caster
->CastSpell(unitTarget
, &sInfo
, true, 0);
417 m_caster
->SetPower(POWER_RAGE
,0);
421 if(m_spellInfo
->SpellVisual
== 1225 && m_spellInfo
->SpellIconID
== 208)
423 int32 mod
= m_spellInfo
->EffectBasePoints
[0]+1;
426 if(m_caster
->GetHealth()>mod
)
428 m_caster
->ModifyHealth(-mod
);
429 m_caster
->ModifyPower(POWER_MANA
,mod
);
435 void Spell::EffectTriggerSpell(uint32 i
)
437 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry( m_spellInfo
->EffectTriggerSpell
[i
] );
441 sLog
.outError("WORLD: unknown spell id %i\n", m_spellInfo
->EffectTriggerSpell
[i
]);
445 m_TriggerSpell
.push_back(spellInfo
);
449 void Spell::EffectTeleportUnits(uint32 i
)
453 HandleTeleport(m_spellInfo
->Id
,unitTarget
);
456 void Spell::EffectApplyAura(uint32 i
)
460 if(!unitTarget
->isAlive())
463 //If m_immuneToState type contain this aura type, IMMUNE aura.
464 if(unitTarget
->IsImmunedToSpellEffect(m_spellInfo
->EffectApplyAuraName
[i
]))
466 SendCastResult(CAST_FAIL_IMMUNE
);
470 sLog
.outDebug("Spell: Aura is: %u", m_spellInfo
->EffectApplyAuraName
[i
]);
472 Aura
* Aur
= new Aura(m_spellInfo
, i
, unitTarget
,m_caster
, m_CastItem
);
474 if (!Aur
->IsPositive() && Aur
->GetCasterGUID() != Aur
->GetTarget()->GetGUID())
476 switch (Aur
->GetModifier()->m_auraname
)
478 case SPELL_AURA_MOD_DETECT_RANGE
:
479 case SPELL_AURA_AURAS_VISIBLE
:
480 case SPELL_AURA_MOD_CHARM
:
483 if(Aur
->GetTarget()->GetTypeId() == TYPEID_UNIT
)
484 ((Creature
*)Aur
->GetTarget())->AI().AttackStart(m_caster
);
487 m_caster
->Attack(Aur
->GetTarget());
488 m_caster
->SetInCombat();
489 Aur
->GetTarget()->SetInCombat();
494 bool added
= unitTarget
->AddAura(Aur
);
498 // Check for Power Word: Shield
499 // TODO Make a way so it works for every related spell!
500 if(unitTarget
->GetTypeId()==TYPEID_PLAYER
) // Negative buff should only be applied on players
502 // This should cover all Power Word: Shield spells
503 if ((m_spellInfo
->SpellVisual
== 784) && (m_spellInfo
->SpellIconID
== 566))
506 SpellEntry
const *WeakenedSoulSpellInfo
= sSpellStore
.LookupEntry( 6788 );
507 Aura
* WeakenedSoulAura
= new Aura(WeakenedSoulSpellInfo
, 0, unitTarget
,m_caster
, 0);
508 unitTarget
->AddAura(WeakenedSoulAura
, 0);
509 sLog
.outDebug("Spell: Additinal Aura is: %u", WeakenedSoulSpellInfo
->EffectApplyAuraName
[i
]);
516 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(m_spellInfo
->EffectTriggerSpell
[i
]);
517 if (!spellInfo
) return;
518 if (spellInfo
->EffectImplicitTargetA
[0] == TARGET_SINGLE_ENEMY
&& m_caster
->GetTypeId() == TYPEID_PLAYER
)
520 Unit
*target
= ObjectAccessor::Instance().GetUnit(*m_caster
, ((Player
*)m_caster
)->GetSelection());
523 if (!m_caster
->IsFriendlyTo(target
))
524 Aur
->SetTarget(target
);
535 void Spell::EffectManaDrain(uint32 i
)
537 if(m_spellInfo
->EffectMiscValue
[i
] > 4)
540 Powers drain_power
= Powers(m_spellInfo
->EffectMiscValue
[i
]);
544 if(!unitTarget
->isAlive())
546 if(unitTarget
->getPowerType() != drain_power
)
549 uint32 curPower
= unitTarget
->GetPower(drain_power
);
550 float tmpvalue
= m_spellInfo
->EffectMultipleValue
[i
];
555 if(curPower
< damage
)
556 new_damage
= curPower
;
560 unitTarget
->ModifyPower(drain_power
,-new_damage
);
562 if(drain_power
== POWER_MANA
)
563 m_caster
->ModifyPower(POWER_MANA
,uint32(new_damage
*tmpvalue
));
566 void Spell::EffectSendEvent(uint32 i
)
568 sWorld
.ScriptsStart(sSpellScripts
, m_spellInfo
->Id
, m_caster
, focusObject
);
571 void Spell::EffectPowerDrain(uint32 i
)
575 if(!unitTarget
->isAlive())
577 if(unitTarget
->getPowerType()!=POWER_MANA
)
580 uint32 curPower
= unitTarget
->GetPower(POWER_MANA
);
583 if(curPower
< damage
)
584 new_damage
= curPower
;
588 int32 tmpvalue
= int32(new_damage
*m_spellInfo
->EffectMultipleValue
[i
]);
590 unitTarget
->ModifyPower(POWER_MANA
,-new_damage
);
592 m_caster
->ModifyPower(POWER_MANA
,tmpvalue
);
593 m_caster
->SpellNonMeleeDamageLog(unitTarget
, m_spellInfo
->Id
, new_damage
/2, m_IsTriggeredSpell
);
597 void Spell::EffectHeal( uint32 i
)
599 if( unitTarget
&& unitTarget
->isAlive() )
601 int32 addhealth
= m_caster
->SpellHealingBonus(m_spellInfo
, damage
);
602 bool crit
= m_caster
->SpellCriticalBonus(m_spellInfo
, &addhealth
);
603 if(unitTarget
->GetTypeId() == TYPEID_PLAYER
)
604 SendHealSpellOnPlayer(((Player
*)unitTarget
), m_spellInfo
->Id
, addhealth
, crit
);
606 unitTarget
->ModifyHealth( addhealth
);
608 uint32 procHealer
= PROC_FLAG_HEAL
;
610 procHealer
|= PROC_FLAG_CRIT_HEAL
;
611 if (m_caster
!= unitTarget
)
612 m_caster
->ProcDamageAndSpell(unitTarget
,procHealer
,PROC_FLAG_NONE
,addhealth
,m_spellInfo
,m_IsTriggeredSpell
);
616 void Spell::EffectHealthLeach(uint32 i
)
620 if(!unitTarget
->isAlive())
623 sLog
.outDebug("HealthLeach :%u", damage
);
625 uint32 curHealth
= unitTarget
->GetHealth();
628 if(curHealth
< damage
)
629 new_damage
= curHealth
;
633 int32 tmpvalue
= int32(new_damage
*m_spellInfo
->EffectMultipleValue
[i
]);
635 m_caster
->ModifyHealth(tmpvalue
);
637 if(unitTarget
->GetTypeId() == TYPEID_PLAYER
)
638 SendHealSpellOnPlayer(((Player
*)unitTarget
), m_spellInfo
->Id
, uint32(tmpvalue
));
640 m_caster
->SpellNonMeleeDamageLog(unitTarget
, m_spellInfo
->Id
, new_damage
, m_IsTriggeredSpell
);
643 void Spell::DoCreateItem(uint32 i
, uint32 itemtype
)
645 if (m_caster
->GetTypeId() != TYPEID_PLAYER
)
648 Player
* player
= (Player
*)m_caster
;
650 uint32 newitemid
= itemtype
;
651 ItemPrototype
const *pProto
= objmgr
.GetItemPrototype( newitemid
);
654 player
->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND
, NULL
, NULL
);
660 if(pProto
->Class
!= ITEM_CLASS_CONSUMABLE
|| m_spellInfo
->SpellFamilyName
!= SPELLFAMILY_MAGE
)
661 num_to_add
= max(m_spellInfo
->EffectBasePoints
[i
]+1, 1);
662 else if(player
->getLevel() >= m_spellInfo
->spellLevel
)
663 num_to_add
= ((player
->getLevel() - (m_spellInfo
->spellLevel
-1))*2);
668 uint8 msg
= player
->CanStoreNewItem( NULL_BAG
, NULL_SLOT
, dest
, newitemid
, num_to_add
, false);
669 if( msg
!= EQUIP_ERR_OK
)
671 player
->SendEquipError( msg
, NULL
, NULL
);
675 Item
*pItem
= player
->StoreNewItem( dest
, newitemid
, num_to_add
, true);
679 player
->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND
, NULL
, NULL
);
683 if( pItem
->GetProto()->Class
!= ITEM_CLASS_CONSUMABLE
)
684 pItem
->SetUInt32Value(ITEM_FIELD_CREATOR
,player
->GetGUIDLow());
686 //should send message "create item" to client.-FIX ME
687 player
->UpdateCraftSkill(m_spellInfo
->Id
);
690 void Spell::EffectCreateItem(uint32 i
)
692 DoCreateItem(i
,m_spellInfo
->EffectItemType
[i
]);
695 void Spell::EffectPersistentAA(uint32 i
)
697 float radius
= GetRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[i
]));
698 int32 duration
= GetDuration(m_spellInfo
);
699 DynamicObject
* dynObj
= new DynamicObject();
700 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
))
705 dynObj
->SetUInt32Value(OBJECT_FIELD_TYPE
, 65);
706 dynObj
->SetUInt32Value(GAMEOBJECT_DISPLAYID
, 368003);
707 dynObj
->SetUInt32Value(DYNAMICOBJECT_BYTES
, 0x01eeeeee);
708 m_caster
->AddDynObject(dynObj
);
709 dynObj
->AddToWorld();
710 MapManager::Instance().GetMap(dynObj
->GetMapId())->Add(dynObj
);
714 void Spell::EffectEnergize(uint32 i
)
718 if(!unitTarget
->isAlive())
721 if(m_spellInfo
->EffectMiscValue
[i
] > 4)
724 Powers power
= Powers(m_spellInfo
->EffectMiscValue
[i
]);
726 if(unitTarget
->getPowerType() != power
)
729 unitTarget
->ModifyPower(power
,damage
);
732 void Spell::EffectOpenLock(uint32 i
)
735 if(!m_caster
|| m_caster
->GetTypeId() != TYPEID_PLAYER
)
737 sLog
.outDebug( "WORLD: Open Lock - No Player Caster!");
741 Player
* player
= (Player
*)m_caster
;
743 LootType loottype
= LOOT_CORPSE
;
750 lockId
= gameObjTarget
->GetGOInfo()->sound0
;
751 guid
= gameObjTarget
->GetGUID();
755 lockId
= itemTarget
->GetProto()->LockID
;
756 guid
= itemTarget
->GetGUID();
760 sLog
.outDebug( "WORLD: Open Lock - No GameObject/Item Target!");
764 if(!lockId
) // possible case for GO and maybe for items.
766 player
->SendLoot(guid
,loottype
);
771 LockEntry
const *lockInfo
= sLockStore
.LookupEntry(lockId
);
775 sLog
.outError( "Spell::EffectOpenLock: %s [guid = %u] has an unknown lockId: %u!",
776 (gameObjTarget
? "gameobject" : "item"), GUID_LOPART(guid
), lockId
);
777 SendCastResult(CAST_FAIL_INVALID_TARGET
);
782 // Check and skill-up skill
783 if(m_spellInfo
->Effect
[1]==SPELL_EFFECT_SKILL
)
784 SkillId
= m_spellInfo
->EffectMiscValue
[1];
786 if(m_spellInfo
->EffectMiscValue
[0]==1) // picklocking spells
787 SkillId
= SKILL_LOCKPICKING
;
789 // skill bonus provided by casting spell (mostly item spells)
790 uint32 spellSkillBonus
= uint32(m_spellInfo
->EffectBasePoints
[0]+1);
792 uint32 reqSkillValue
= lockInfo
->requiredskill
;
794 if(lockInfo
->requiredlockskill
) // required pick lock skill applying
796 if(SkillId
!= SKILL_LOCKPICKING
) // wrong skill (cheating?)
798 SendCastResult(CAST_FAIL_FIZZLED
);
802 reqSkillValue
= lockInfo
->requiredlockskill
;
805 if(SkillId
== SKILL_LOCKPICKING
) // apply picklock skill to wrong target
807 SendCastResult(CAST_FAIL_INVALID_TARGET
);
813 loottype
= LOOT_SKINNING
;
814 if ( player
->GetSkillValue(SkillId
) + spellSkillBonus
< reqSkillValue
)
816 SendCastResult(CAST_FAIL_SKILL_NOT_HIGH_ENOUGH
);
820 // update skill if really known
821 uint32 SkillValue
= player
->GetPureSkillValue(SkillId
);
822 if(SkillValue
) // non only item base skill
826 // Allow one skill-up until respawned
827 if ( !gameObjTarget
->IsInSkillupList( player
->GetGUIDLow() ) &&
828 player
->UpdateGatherSkill(SkillId
, SkillValue
, reqSkillValue
) )
829 gameObjTarget
->AddToSkillupList( player
->GetGUIDLow() );
834 uint32 SkillValue
= player
->GetPureSkillValue(SkillId
);
835 player
->UpdateGatherSkill(SkillId
, SkillValue
, reqSkillValue
);
841 player
->SendLoot(guid
,loottype
);
844 void Spell::EffectSummonChangeItem(uint32 i
)
846 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
849 Player
*player
= (Player
*)m_caster
;
851 // applied only to using item
855 // ... only to item in own inventory/bank/equip_slot
856 if(m_CastItem
->GetOwnerGUID()!=player
->GetGUID())
859 uint32 newitemid
= m_spellInfo
->EffectItemType
[i
];
863 uint16 pos
= (m_CastItem
->GetBagSlot() << 8) | m_CastItem
->GetSlot();
865 Item
*pNewItem
= player
->CreateItem( newitemid
, 1 );
872 if( player
->IsInventoryPos( pos
) )
874 msg
= player
->CanStoreItem( m_CastItem
->GetBagSlot(), m_CastItem
->GetSlot(), dest
, pNewItem
, true );
875 if( msg
== EQUIP_ERR_OK
)
877 player
->DestroyItem(m_CastItem
->GetBagSlot(), m_CastItem
->GetSlot(),true);
878 player
->StoreItem( dest
, pNewItem
, true);
882 else if( player
->IsBankPos ( pos
) )
884 msg
= player
->CanBankItem( m_CastItem
->GetBagSlot(), m_CastItem
->GetSlot(), dest
, pNewItem
, true );
885 if( msg
== EQUIP_ERR_OK
)
887 player
->DestroyItem(m_CastItem
->GetBagSlot(), m_CastItem
->GetSlot(),true);
888 player
->BankItem( dest
, pNewItem
, true);
892 else if( player
->IsEquipmentPos ( pos
) )
894 msg
= player
->CanEquipItem( m_CastItem
->GetSlot(), dest
, pNewItem
, true );
895 if( msg
== EQUIP_ERR_OK
)
897 player
->DestroyItem(m_CastItem
->GetBagSlot(), m_CastItem
->GetSlot(),true);
898 player
->EquipItem( dest
, pNewItem
, true);
907 void Spell::EffectOpenSecretSafe(uint32 i
)
909 EffectOpenLock(i
); //no difference for now
912 void Spell::EffectProficiency(uint32 i
)
914 if (!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
916 Player
*p_target
= (Player
*)unitTarget
;
918 uint32 subClassMask
= m_spellInfo
->EquippedItemSubClassMask
;
919 if(m_spellInfo
->EquippedItemClass
== 2 && !(p_target
->GetWeaponProficiency() & subClassMask
))
921 p_target
->AddWeaponProficiency(subClassMask
);
922 p_target
->SendProficiency(uint8(0x02),p_target
->GetWeaponProficiency());
924 if(m_spellInfo
->EquippedItemClass
== 4 && !(p_target
->GetArmorProficiency() & subClassMask
))
926 p_target
->AddArmorProficiency(subClassMask
);
927 p_target
->SendProficiency(uint8(0x04),p_target
->GetArmorProficiency());
931 void Spell::EffectApplyAA(uint32 i
)
935 if(!unitTarget
->isAlive())
938 AreaAura
* Aur
= new AreaAura(m_spellInfo
, i
, unitTarget
, m_caster
);
939 unitTarget
->AddAura(Aur
);
942 void Spell::EffectSummon(uint32 i
)
944 if(m_caster
->GetPetGUID())
949 uint32 pet_entry
= m_spellInfo
->EffectMiscValue
[i
];
952 uint32 level
= m_caster
->getLevel();
953 Pet
* spawnCreature
= new Pet(SUMMON_PET
);
955 if(!spawnCreature
->Create(objmgr
.GenerateLowGuid(HIGHGUID_UNIT
),
956 m_caster
->GetMapId(),
957 m_caster
->GetPositionX(),m_caster
->GetPositionY(),
958 m_caster
->GetPositionZ(),m_caster
->GetOrientation(),
959 m_spellInfo
->EffectMiscValue
[i
]))
961 sLog
.outError("no such creature entry %u",m_spellInfo
->EffectMiscValue
[i
]);
962 delete spawnCreature
;
966 spawnCreature
->SetUInt64Value(UNIT_FIELD_SUMMONEDBY
,m_caster
->GetGUID());
967 spawnCreature
->SetUInt32Value(UNIT_NPC_FLAGS
, 0);
968 spawnCreature
->setPowerType(POWER_MANA
);
969 spawnCreature
->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE
,m_caster
->getFaction());
970 spawnCreature
->SetUInt32Value(UNIT_FIELD_FLAGS
,0);
971 spawnCreature
->SetUInt32Value(UNIT_FIELD_BYTES_1
,0);
972 spawnCreature
->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP
,0);
973 spawnCreature
->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE
,0);
974 spawnCreature
->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP
,1000);
975 spawnCreature
->SetUInt64Value(UNIT_FIELD_CREATEDBY
, m_caster
->GetGUID());
977 spawnCreature
->InitStatsForLevel(level
);
979 spawnCreature
->AIM_Initialize();
982 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
983 name
= ((Player
*)m_caster
)->GetName();
985 name
= ((Creature
*)m_caster
)->GetCreatureInfo()->Name
;
986 name
.append(petTypeSuffix
[spawnCreature
->getPetType()]);
987 spawnCreature
->SetName( name
);
989 spawnCreature
->AddToWorld();
990 MapManager::Instance().GetMap(m_caster
->GetMapId())->Add((Creature
*)spawnCreature
);
992 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
994 m_caster
->SetPet(spawnCreature
);
995 spawnCreature
->SavePetToDB(PET_SAVE_AS_CURRENT
);
996 ((Player
*)m_caster
)->PetSpellInitialize();
1000 void Spell::EffectLearnSpell(uint32 i
)
1005 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
1007 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
1009 Creature
*pet
= m_caster
->GetPet();
1011 if( !pet
|| !pet
->isPet() || pet
!=unitTarget
|| !pet
->isAlive() )
1014 EffectLearnPetSpell(i
);
1019 Player
*player
= (Player
*)unitTarget
;
1021 uint32 spellToLearn
= m_spellInfo
->EffectTriggerSpell
[i
];
1022 //data.Initialize(SMSG_LEARNED_SPELL);
1023 //data << spellToLearn;
1024 //player->GetSession()->SendPacket(&data);
1025 player
->learnSpell((uint16
)spellToLearn
);
1026 //some addspell isn't needed if you have a good DB,FISHING && MINING && HERBALISM have to be needed.
1027 switch(spellToLearn
)
1029 case 4036: //SKILL_ENGINERING
1031 player
->learnSpell(3918);
1032 player
->learnSpell(3919);
1033 player
->learnSpell(3920);
1036 case 3908: //SKILL_TAILORING
1038 player
->learnSpell(2387);
1039 player
->learnSpell(2963);
1042 case 7411: //SKILL_ENCHANTING
1044 player
->learnSpell(7418);
1045 player
->learnSpell(7421);
1046 player
->learnSpell(13262);
1049 case 2259: //SKILL_ALCHEMY
1051 player
->learnSpell(2329);
1052 player
->learnSpell(7183);
1053 player
->learnSpell(2330);
1056 case 2018: //SKILL_BLACKSMITHING
1058 player
->learnSpell(2663);
1059 player
->learnSpell(12260);
1060 player
->learnSpell(2660);
1061 player
->learnSpell(3115);
1064 case 2108: //SKILL_LEATHERWORKING
1066 player
->learnSpell(2152);
1067 player
->learnSpell(9058);
1068 player
->learnSpell(9059);
1069 player
->learnSpell(2149);
1070 player
->learnSpell(7126);
1071 player
->learnSpell(2881);
1074 case 2550: //SKILL_COOKING
1076 player
->learnSpell(818);
1077 player
->learnSpell(2540);
1078 player
->learnSpell(2538);
1079 player
->learnSpell(8604);
1082 case 3273: //SKILL_FIRST_AID
1084 player
->learnSpell(3275);
1087 case 7620: //SKILL_FISHING
1089 player
->learnSpell(7738);
1092 case 2575: //SKILL_MINING
1094 player
->learnSpell(2580);
1095 player
->learnSpell(2656);
1096 player
->learnSpell(2657);
1099 case 2366: //SKILL_HERBALISM
1101 player
->learnSpell(2383);
1104 case 264: //SKILL_BOWS
1106 if(!player
->HasSpell(75))
1107 player
->learnSpell(2480);
1110 case 266: //SKILL_GUNS
1112 if(!player
->HasSpell(75))
1113 player
->learnSpell(7918);
1116 case 5011: //SKILL_CROSSBOWS
1118 if(!player
->HasSpell(75))
1119 player
->learnSpell(7919);
1122 case 2567: //SKILL_THROWN
1124 player
->learnSpell(2764);
1127 case 2842: //SKILL_POISONS
1129 player
->learnSpell(8681);
1134 sLog
.outDebug( "Spell: Player %u have learned spell %u from NpcGUID=%u", player
->GetGUIDLow(), spellToLearn
, m_caster
->GetGUIDLow() );
1137 void Spell::EffectDispel(uint32 i
)
1139 m_caster
->RemoveFirstAuraByDispel(m_spellInfo
->EffectMiscValue
[i
]);
1142 void Spell::EffectDualWield(uint32 i
)
1144 if (unitTarget
->GetTypeId() == TYPEID_PLAYER
)
1145 ((Player
*)unitTarget
)->SetCanDualWield(true);
1148 void Spell::EffectPickPocket(uint32 i
)
1150 if( m_caster
->GetTypeId() != TYPEID_PLAYER
)
1153 //victim must be creature and attackable
1154 if( !unitTarget
|| unitTarget
->GetTypeId() != TYPEID_UNIT
|| m_caster
->IsFriendlyTo(unitTarget
) )
1157 //victim have to be alive and humanoid or undead
1158 if( unitTarget
->isAlive() &&
1159 (((Creature
*)unitTarget
)->GetCreatureInfo()->type
== CREATURE_TYPE_HUMANOID
||
1160 ((Creature
*)unitTarget
)->GetCreatureInfo()->type
== CREATURE_TYPE_UNDEAD
))
1162 int chance
= 10 + m_caster
->getLevel() - unitTarget
->getLevel();
1164 if ( ( rand() % 20 ) <= chance
)
1166 //Stealing successfull
1167 //sLog.outDebug("Sending loot from pickpocket");
1168 ((Player
*)m_caster
)->SendLoot(unitTarget
->GetGUID(),LOOT_PICKPOKETING
);
1172 //Reveal action + get attack
1173 m_caster
->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH
);
1174 ((Creature
*)unitTarget
)->AI().AttackStart(m_caster
);
1179 void Spell::EffectSummonWild(uint32 i
)
1183 uint32 pet_entry
= m_spellInfo
->EffectMiscValue
[i
];
1187 Pet
* old_wild
= NULL
;
1190 CellPair
p(MaNGOS::ComputeCellPair(m_caster
->GetPositionX(), m_caster
->GetPositionY()));
1191 Cell cell
= RedZone::GetZone(p
);
1192 cell
.data
.Part
.reserved
= ALL_DISTRICT
;
1195 PetWithIdCheck
u_check(m_caster
, pet_entry
);
1196 MaNGOS::UnitSearcher
<PetWithIdCheck
> checker((Unit
*&)old_wild
, u_check
);
1197 TypeContainerVisitor
<MaNGOS::UnitSearcher
<PetWithIdCheck
>, TypeMapContainer
<AllObjectTypes
> > object_checker(checker
);
1198 CellLock
<GridReadGuard
> cell_lock(cell
, p
);
1199 cell_lock
->Visit(cell_lock
, object_checker
, *MapManager::Instance().GetMap(m_caster
->GetMapId()));
1202 if (old_wild
) // find old critter, unsummon
1204 old_wild
->Remove(PET_SAVE_AS_DELETED
);
1207 else // in another case summon new
1210 uint32 level
= m_caster
->getLevel();
1212 // level of pet summoned using engineering item based at engineering skill level
1213 if(m_caster
->GetTypeId()==TYPEID_PLAYER
&& m_CastItem
)
1215 ItemPrototype
const *proto
= m_CastItem
->GetProto();
1216 if(proto
&& proto
->RequiredSkill
== SKILL_ENGINERING
)
1218 uint16 skill202
= ((Player
*)m_caster
)->GetSkillValue(SKILL_ENGINERING
);
1226 Pet
* spawnCreature
= new Pet(GUARDIAN_PET
);
1228 if(!spawnCreature
->Create(objmgr
.GenerateLowGuid(HIGHGUID_UNIT
),
1229 m_caster
->GetMapId(),
1230 m_caster
->GetPositionX(),m_caster
->GetPositionY(),
1231 m_caster
->GetPositionZ(),m_caster
->GetOrientation(),
1232 m_spellInfo
->EffectMiscValue
[i
]))
1234 sLog
.outError("no such creature entry %u",m_spellInfo
->EffectMiscValue
[i
]);
1235 delete spawnCreature
;
1239 spawnCreature
->SetUInt64Value(UNIT_FIELD_SUMMONEDBY
,m_caster
->GetGUID());
1240 spawnCreature
->setPowerType(POWER_MANA
);
1241 spawnCreature
->SetPower( POWER_MANA
,28 + 10 * level
);
1242 spawnCreature
->SetMaxPower(POWER_MANA
,28 + 10 * level
);
1243 spawnCreature
->SetUInt32Value(UNIT_NPC_FLAGS
, 0);
1244 spawnCreature
->SetHealth( 28 + 30*level
);
1245 spawnCreature
->SetMaxHealth( 28 + 30*level
);
1246 spawnCreature
->SetLevel(level
);
1247 spawnCreature
->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE
,m_caster
->getFaction());
1248 spawnCreature
->SetUInt32Value(UNIT_FIELD_FLAGS
,0);
1249 spawnCreature
->SetUInt32Value(UNIT_FIELD_BYTES_1
,0);
1250 spawnCreature
->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP
,0);
1251 spawnCreature
->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE
,0);
1252 spawnCreature
->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP
,1000);
1253 spawnCreature
->SetUInt64Value(UNIT_FIELD_CREATEDBY
, m_caster
->GetGUID());
1255 spawnCreature
->SetArmor(level
*50);
1256 spawnCreature
->AIM_Initialize();
1259 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
1260 name
= ((Player
*)m_caster
)->GetName();
1262 name
= ((Creature
*)m_caster
)->GetCreatureInfo()->Name
;
1263 name
.append(petTypeSuffix
[spawnCreature
->getPetType()]);
1264 spawnCreature
->SetName( name
);
1266 spawnCreature
->AddToWorld();
1267 MapManager::Instance().GetMap(m_caster
->GetMapId())->Add((Creature
*)spawnCreature
);
1269 guardians and wilds can't be controled
1270 if(m_caster->GetTypeId() == TYPEID_PLAYER)
1272 m_caster->SetPet(spawnCreature);
1273 ((Player*)m_caster)->PetSpellInitialize();
1274 ((Player*)m_caster)->SavePet();
1280 void Spell::EffectTeleUnitsFaceCaster(uint32 i
)
1285 if(unitTarget
->isInFlight())
1288 uint32 mapid
= m_caster
->GetMapId();
1289 float dis
= GetRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[i
]));
1290 float fx
= m_caster
->GetPositionX() + dis
* cos(m_caster
->GetOrientation());
1291 float fy
= m_caster
->GetPositionY() + dis
* sin(m_caster
->GetOrientation());
1292 // teleport a bit above terrainlevel to avoid falling below it
1293 float fz
= MapManager::Instance ().GetMap(mapid
)->GetHeight(fx
,fy
) + 1.5;
1295 if(unitTarget
->GetTypeId() == TYPEID_PLAYER
)
1296 ((Player
*)unitTarget
)->TeleportTo(mapid
, fx
, fy
, fz
, -m_caster
->GetOrientation(), false);
1298 MapManager::Instance().GetMap(mapid
)->CreatureRelocation((Creature
*)m_caster
, fx
, fy
, fz
, -m_caster
->GetOrientation());
1301 void Spell::EffectLearnSkill(uint32 i
)
1303 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
1306 uint32 skillid
= m_spellInfo
->EffectMiscValue
[i
];
1307 uint16 skillval
= ((Player
*)unitTarget
)->GetPureSkillValue(skillid
);
1308 ((Player
*)unitTarget
)->SetSkill(skillid
,skillval
?skillval
:1,damage
*75);
1311 void Spell::EffectTradeSkill(uint32 i
)
1313 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
1315 // uint32 skillid = m_spellInfo->EffectMiscValue[i];
1316 // uint16 skillmax = ((Player*)unitTarget)->(skillid);
1317 // ((Player*)unitTarget)->SetSkill(skillid,skillval?skillval:1,skillmax+75);
1320 void Spell::EffectEnchantItemPerm(uint32 i
)
1322 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
1327 Player
* p_caster
= (Player
*)m_caster
;
1329 p_caster
->UpdateCraftSkill(m_spellInfo
->Id
);
1331 if (m_spellInfo
->EffectMiscValue
[i
])
1333 uint32 enchant_id
= m_spellInfo
->EffectMiscValue
[i
];
1335 SpellItemEnchantmentEntry
const *pEnchant
= sSpellItemEnchantmentStore
.LookupEntry(enchant_id
);
1339 // item can be in trade slot and have owner diff. from caster
1340 Player
* item_owner
= itemTarget
->GetOwner();
1344 if(item_owner
!=p_caster
&& p_caster
->GetSession()->GetSecurity() > 0 && sWorld
.getConfig(CONFIG_GM_LOG_TRADE
) )
1345 sLog
.outCommand("GM Enchanting: %s (Entry: %d) GM: %s (Account: %u) Player: %s (Account: %u)",
1346 itemTarget
->GetProto()->Name1
,itemTarget
->GetEntry(),
1347 p_caster
->GetName(),p_caster
->GetSession()->GetAccountId(),
1348 item_owner
->GetName(),item_owner
->GetSession()->GetAccountId());
1350 // remove old enchanting before appling new if equiped
1351 if(itemTarget
->IsEquipped())
1352 if(uint32 old_enchant_id
= itemTarget
->GetUInt32Value(ITEM_FIELD_ENCHANTMENT
))
1353 item_owner
->AddItemEnchant(itemTarget
,old_enchant_id
,false);
1355 for(int x
=0;x
<3;x
++)
1356 itemTarget
->SetUInt32Value(ITEM_FIELD_ENCHANTMENT
+x
,0);
1358 itemTarget
->SetUInt32Value(ITEM_FIELD_ENCHANTMENT
, enchant_id
);
1360 // add new enchanting if equiped
1361 if(itemTarget
->IsEquipped())
1362 item_owner
->AddItemEnchant(itemTarget
,enchant_id
,true);
1364 itemTarget
->SetState(ITEM_CHANGED
);
1368 void Spell::EffectEnchantItemTmp(uint32 i
)
1370 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
1373 Player
* p_caster
= (Player
*)m_caster
;
1378 if (m_spellInfo
->EffectMiscValue
[i
])
1380 uint32 enchant_id
= m_spellInfo
->EffectMiscValue
[i
];
1381 int32 duration
= GetDuration(m_spellInfo
);
1383 duration
= m_spellInfo
->EffectBasePoints
[i
]+1;
1386 SpellItemEnchantmentEntry
const *pEnchant
= sSpellItemEnchantmentStore
.LookupEntry(enchant_id
);
1390 // item can be in trade slot and have owner diff. from caster
1391 Player
* item_owner
= itemTarget
->GetOwner();
1395 if(item_owner
!=p_caster
&& p_caster
->GetSession()->GetSecurity() > 0 && sWorld
.getConfig(CONFIG_GM_LOG_TRADE
) )
1396 sLog
.outCommand("GM Enchanting: %s (Entry: %d) GM: %s (Account: %u) Player: %s (Account: %u)",
1397 itemTarget
->GetProto()->Name1
,itemTarget
->GetEntry(),
1398 p_caster
->GetName(),p_caster
->GetSession()->GetAccountId(),
1399 item_owner
->GetName(),item_owner
->GetSession()->GetAccountId());
1401 // remove old enchanting before applying new if equipped
1402 if(uint32 old_enchant_id
= itemTarget
->GetUInt32Value(ITEM_FIELD_ENCHANTMENT
+1*3))
1404 if(itemTarget
->IsEquipped())
1405 item_owner
->AddItemEnchant(itemTarget
,old_enchant_id
,false);
1407 // duration == 0 will remove EnchantDuration
1408 item_owner
->AddEnchantDuration(itemTarget
,1,0);
1411 for(int x
=0;x
<3;x
++)
1412 itemTarget
->SetUInt32Value(ITEM_FIELD_ENCHANTMENT
+3+x
,0);
1414 itemTarget
->SetUInt32Value(ITEM_FIELD_ENCHANTMENT
+3, enchant_id
);
1415 itemTarget
->SetUInt32Value(ITEM_FIELD_ENCHANTMENT
+3+1, duration
*1000);
1416 if(m_spellInfo
->SpellFamilyName
== 8)
1417 itemTarget
->SetUInt32Value(ITEM_FIELD_ENCHANTMENT
+3+2, 45+objmgr
.GetSpellRank(m_spellInfo
->Id
)*15);
1419 // add new enchanting if equipped
1420 if(itemTarget
->IsEquipped())
1421 item_owner
->AddItemEnchant(itemTarget
,enchant_id
,true);
1423 itemTarget
->SetState(ITEM_CHANGED
);
1426 item_owner
->AddEnchantDuration(itemTarget
,1,duration
*1000);
1430 void Spell::EffectTameCreature(uint32 i
)
1432 if(m_caster
->GetPetGUID())
1438 if(unitTarget
->GetTypeId() == TYPEID_PLAYER
)
1441 Creature
* creatureTarget
= (Creature
*)unitTarget
;
1443 if(creatureTarget
->isPet())
1446 if(m_caster
->getClass() == CLASS_HUNTER
)
1448 creatureTarget
->AttackStop();
1449 if(m_caster
->getVictim()==creatureTarget
)
1450 m_caster
->AttackStop();
1452 creatureTarget
->CombatStop();
1453 creatureTarget
->StopMoving();
1455 // cast finish succesfully
1456 SendChannelUpdate(0);
1459 Pet
* pet
= new Pet(HUNTER_PET
);
1461 pet
->CreateBaseAtCreature(creatureTarget
);
1463 ObjectAccessor::Instance().RemoveCreatureCorpseFromPlayerView(creatureTarget
);
1464 creatureTarget
->setDeathState(JUST_DIED
);
1466 pet
->SetUInt64Value(UNIT_FIELD_SUMMONEDBY
, m_caster
->GetGUID());
1467 pet
->SetUInt64Value(UNIT_FIELD_CREATEDBY
, m_caster
->GetGUID());
1468 pet
->SetMaxPower(POWER_HAPPINESS
,1000000);
1469 pet
->SetPower( POWER_HAPPINESS
,600000);
1470 pet
->setPowerType(POWER_FOCUS
);
1471 pet
->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE
,m_caster
->getFaction());
1472 pet
->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP
,0);
1473 pet
->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE
,0);
1474 pet
->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP
,1000);
1475 pet
->SetUInt32Value(UNIT_FIELD_FLAGS
, UNIT_FLAG_UNKNOWN1
+ UNIT_FLAG_RESTING
+ UNIT_FLAG_RENAME
);
1476 // this enables popup window (pet detals, abandon, rename)
1477 pet
->SetUInt32Value(UNIT_FIELD_PETNUMBER
,1);
1478 // this enables pet detals window (Shift+P)
1479 pet
->AIM_Initialize();
1482 MapManager::Instance().GetMap(pet
->GetMapId())->Add((Creature
*)pet
);
1484 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
1486 m_caster
->SetPet(pet
);
1487 pet
->SavePetToDB(PET_SAVE_AS_CURRENT
);
1488 ((Player
*)m_caster
)->PetSpellInitialize();
1493 void Spell::EffectSummonPet(uint32 i
)
1496 m_caster
->GetClosePoint(NULL
, px
, py
, pz
);
1498 uint32 petentry
= m_spellInfo
->EffectMiscValue
[i
];
1500 Pet
*OldSummon
= m_caster
->GetPet();
1502 // if pet requested type already exist
1506 if(petentry
== 0 || OldSummon
->GetCreatureInfo()->Entry
== petentry
)
1508 // pet in corpse state can't be summoned
1509 if( OldSummon
->isDead() )
1512 MapManager::Instance().GetMap(OldSummon
->GetMapId())->Remove((Creature
*)OldSummon
,false);
1513 OldSummon
->SetMapId(m_caster
->GetMapId());
1514 OldSummon
->Relocate(px
, py
, pz
, OldSummon
->GetOrientation());
1515 MapManager::Instance().GetMap(m_caster
->GetMapId())->Add((Creature
*)OldSummon
);
1517 if(m_caster
->GetTypeId() == TYPEID_PLAYER
&& OldSummon
->isControlled() )
1519 ((Player
*)m_caster
)->PetSpellInitialize();
1524 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
1525 ((Player
*)m_caster
)->RemovePet(OldSummon
,PET_SAVE_AS_DELETED
);
1530 Pet
* NewSummon
= new Pet(m_caster
->getClass() == CLASS_HUNTER
? HUNTER_PET
: SUMMON_PET
);
1532 // petentry==0 for hunter "call pet" (current pet summoned if any)
1533 if(NewSummon
->LoadPetFromDB(m_caster
,petentry
))
1535 NewSummon
->SavePetToDB(PET_SAVE_AS_CURRENT
);
1539 // not error in case fail hunter call pet
1543 CreatureInfo
const* cInfo
= sCreatureStorage
.LookupEntry
<CreatureInfo
>(petentry
);
1547 sLog
.outError("EffectSummonPet: creature entry %u not found.",petentry
);
1551 if( NewSummon
->Create(objmgr
.GenerateLowGuid(HIGHGUID_UNIT
), m_caster
->GetMapId(), px
, py
, pz
+1, m_caster
->GetOrientation(), petentry
))
1553 uint32 petlevel
= m_caster
->getLevel();
1555 NewSummon
->SetUInt64Value(UNIT_FIELD_SUMMONEDBY
, m_caster
->GetGUID());
1556 NewSummon
->SetUInt64Value(UNIT_FIELD_CREATEDBY
, m_caster
->GetGUID());
1557 NewSummon
->SetUInt32Value(UNIT_NPC_FLAGS
, 0);
1558 NewSummon
->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE
,m_caster
->getFaction());
1559 NewSummon
->SetUInt32Value(UNIT_FIELD_BYTES_0
,2048);
1560 NewSummon
->SetUInt32Value(UNIT_FIELD_BYTES_1
,0);
1561 NewSummon
->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP
,5);
1562 NewSummon
->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE
,0);
1563 NewSummon
->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP
,1000);
1564 NewSummon
->SetUInt32Value(UNIT_CREATED_BY_SPELL
, m_spellInfo
->Id
);
1565 NewSummon
->SetUInt32Value(UNIT_FIELD_PETNUMBER
,1); // this enables pet detals window (Shift+P)
1567 // this enables popup window (pet dismiss, cancel), hunter pet additinal flags set later
1568 NewSummon
->SetUInt32Value(UNIT_FIELD_FLAGS
,UNIT_FLAG_UNKNOWN1
);
1570 NewSummon
->InitStatsForLevel( petlevel
);
1572 for(uint32 i
=0; i
< CREATURE_MAX_SPELLS
; i
++)
1573 NewSummon
->m_spells
[i
] = 0;
1575 if(petentry
== 416) //imp
1577 NewSummon
->m_spells
[0] = 3110; //3110---fire bolt 1
1578 NewSummon
->AddActState(STATE_RA_SPELL1
);
1581 // generate new name for summon pet
1582 if(NewSummon
->getPetType()==SUMMON_PET
)
1584 std::string new_name
=objmgr
.GeneratePetName(petentry
);
1586 NewSummon
->SetName(new_name
);
1588 else if(NewSummon
->getPetType()==HUNTER_PET
)
1590 // this enables popup window (pet detals, abandon, rename)
1591 NewSummon
->SetFlag(UNIT_FIELD_FLAGS
,(UNIT_FLAG_RESTING
| UNIT_FLAG_RENAME
));
1594 NewSummon
->AIM_Initialize();
1596 NewSummon
->AddToWorld();
1597 MapManager::Instance().GetMap(NewSummon
->GetMapId())->Add((Creature
*)NewSummon
);
1599 m_caster
->SetPet(NewSummon
);
1600 sLog
.outDebug("New Pet has guid %u", NewSummon
->GetGUIDLow());
1602 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
1604 NewSummon
->SavePetToDB(PET_SAVE_AS_CURRENT
);
1605 ((Player
*)m_caster
)->PetSpellInitialize();
1612 void Spell::EffectLearnPetSpell(uint32 i
)
1614 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
1617 Player
*_player
= (Player
*)m_caster
;
1619 Pet
*pet
= _player
->GetPet();
1625 SpellEntry
const *learn_spellproto
= sSpellStore
.LookupEntry(m_spellInfo
->EffectTriggerSpell
[i
]);
1626 if(!learn_spellproto
)
1629 for(int8 x
=0;x
<4;x
++)
1631 SpellEntry
const *has_spellproto
= sSpellStore
.LookupEntry(pet
->m_spells
[x
]);
1634 pet
->m_spells
[x
] = learn_spellproto
->Id
;
1637 else if(has_spellproto
->SpellIconID
== learn_spellproto
->SpellIconID
)
1639 pet
->m_spells
[x
] = learn_spellproto
->Id
;
1643 pet
->SavePetToDB(PET_SAVE_AS_CURRENT
);
1644 _player
->PetSpellInitialize();
1647 void Spell::EffectAttackMe(uint32 i
)
1649 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
1651 unitTarget
->SetInFront(m_caster
);
1652 ((Creature
*)unitTarget
)->AI().AttackStart(m_caster
);
1656 void Spell::EffectWeaponDmg(uint32 i
)
1660 if(!unitTarget
->isAlive())
1663 uint32 wp
[4] = { SPELL_EFFECT_WEAPON_DAMAGE
, SPELL_EFFECT_WEAPON_PERCENT_DAMAGE
, SPELL_EFFECT_NORMALIZED_WEAPON_DMG
, SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL
};
1665 // multiple weap dmg effect workaround
1666 // execute only the first weapon damage
1667 // and handle all effects at once
1671 for (j
= 0; j
< 3; j
++)
1673 for (k
= 0; k
< 4; k
++)
1674 if (m_spellInfo
->Effect
[j
] == wp
[k
])
1680 if (m_spellInfo
->Effect
[j
] != SPELL_EFFECT_WEAPON_PERCENT_DAMAGE
)
1681 bonus
+= m_spellInfo
->EffectBasePoints
[j
]+1;
1685 WeaponAttackType attType
= BASE_ATTACK
;
1686 if(m_spellInfo
->rangeIndex
!= 1 && m_spellInfo
->rangeIndex
!= 2 && m_spellInfo
->rangeIndex
!= 7)
1687 attType
= RANGED_ATTACK
;
1690 uint32 nohitMask
= HITINFO_ABSORB
| HITINFO_RESIST
| HITINFO_MISS
;
1691 uint32 damageType
= NORMAL_DAMAGE
;
1692 uint32 victimState
= VICTIMSTATE_NORMAL
;
1694 uint32 blocked_dmg
= 0;
1695 uint32 absorbed_dmg
= 0;
1696 uint32 resisted_dmg
= 0;
1697 bool criticalhit
= false;
1699 if( unitTarget
->IsImmunedToPhysicalDamage() )
1701 m_caster
->SendAttackStateUpdate (HITINFO_MISS
, unitTarget
, 1, NORMAL_DAMAGE
, 0, 0, 0, VICTIMSTATE_IS_IMMUNE
, 0);
1705 m_caster
->DoAttackDamage(unitTarget
, &damage
, &blocked_dmg
, &damageType
, &hitInfo
, &victimState
, &absorbed_dmg
, &resisted_dmg
, attType
, m_spellInfo
, m_IsTriggeredSpell
);
1707 // not add bonus to 0 damage
1708 if( damage
> 0 && damage
+ bonus
> 0 )
1713 for (j
= 0; j
< 3; j
++)
1714 if (m_spellInfo
->Effect
[j
] == SPELL_EFFECT_WEAPON_PERCENT_DAMAGE
)
1715 damage
= uint32(damage
* (m_spellInfo
->EffectBasePoints
[j
]+1) / 100);
1717 if (hitInfo
& nohitMask
)
1718 m_caster
->SendAttackStateUpdate(hitInfo
& nohitMask
, unitTarget
, 1, m_spellInfo
->School
, damage
, absorbed_dmg
, resisted_dmg
, 1, blocked_dmg
);
1720 if(hitInfo
& HITINFO_CRITICALHIT
)
1723 m_caster
->SendSpellNonMeleeDamageLog(unitTarget
, m_spellInfo
->Id
, damage
+ absorbed_dmg
+ resisted_dmg
+ blocked_dmg
, m_spellInfo
->School
, absorbed_dmg
, resisted_dmg
, false, blocked_dmg
, criticalhit
);
1724 m_caster
->DealDamage(unitTarget
, damage
, SPELL_DIRECT_DAMAGE
, 0, true);
1727 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
1729 if(m_spellInfo
->rangeIndex
!= 1 && m_spellInfo
->rangeIndex
!= 2 && m_spellInfo
->rangeIndex
!= 7)
1731 Item
*pItem
= ((Player
*)m_caster
)->GetItemByPos( INVENTORY_SLOT_BAG_0
, EQUIPMENT_SLOT_RANGED
);
1732 if(!pItem
|| pItem
->IsBroken())
1735 if( pItem
->GetProto()->InventoryType
== INVTYPE_THROWN
)
1738 ((Player
*)m_caster
)->DestroyItemCount( pItem
, count
, true);
1741 if(uint32 ammo
= ((Player
*)m_caster
)->GetUInt32Value(PLAYER_AMMO_ID
))
1742 ((Player
*)m_caster
)->DestroyItemCount( ammo
, 1, true);
1743 // wand not have ammo
1747 /*if(m_spellInfo->Effect[i] == 121)
1749 m_caster->resetAttackTimer(BASE_ATTACK);
1750 m_caster->resetAttackTimer(OFF_ATTACK);
1751 m_caster->resetAttackTimer(RANGED_ATTACK);
1755 void Spell::EffectThreat(uint32 i
)
1757 if(!unitTarget
|| !unitTarget
->isAlive() || !m_caster
->isAlive())
1759 unitTarget
->AddHostil(m_caster
->GetGUID(),float(damage
));
1762 void Spell::EffectHealMaxHealth(uint32 i
)
1766 if(!unitTarget
->isAlive())
1769 uint32 heal
= m_caster
->GetMaxHealth();
1771 unitTarget
->ModifyHealth(heal
);
1773 if(unitTarget
->GetTypeId() == TYPEID_PLAYER
)
1774 SendHealSpellOnPlayer((Player
*)unitTarget
, m_spellInfo
->Id
, heal
);
1777 void Spell::EffectInterruptCast(uint32 i
)
1781 if(!unitTarget
->isAlive())
1784 // TODO: not all spells that used this effect apply cooldown at school spells
1785 // also exist case: apply cooldown to interupted cast only and to all spells
1786 if (unitTarget
->m_currentSpell
&& unitTarget
->m_currentSpell
->m_spellInfo
)
1788 unitTarget
->ProhibitSpellScholl(unitTarget
->m_currentSpell
->m_spellInfo
->School
, GetDuration(m_spellInfo
));
1789 unitTarget
->InterruptSpell();
1793 void Spell::EffectSummonObjectWild(uint32 i
)
1795 GameObject
* pGameObj
= new GameObject();
1797 uint32 gameobject_id
= m_spellInfo
->EffectMiscValue
[i
];
1799 WorldObject
* target
= focusObject
;
1803 if(!pGameObj
->Create(objmgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), gameobject_id
, target
->GetMapId(),
1804 target
->GetPositionX(), target
->GetPositionY(), target
->GetPositionZ(),
1805 target
->GetOrientation(), 0, 0, 0, 0, 0, 0))
1810 pGameObj
->SetRespawnTime(GetDuration(m_spellInfo
)/1000);
1812 m_caster
->AddGameObject(pGameObj
);
1813 MapManager::Instance().GetMap(pGameObj
->GetMapId())->Add(pGameObj
);
1816 void Spell::EffectScriptEffect(uint32 i
)
1818 if(!m_spellInfo
->Reagent
[0])
1820 // paladin's holy light / flash of light
1821 if ((m_spellInfo
->SpellFamilyName
== SPELLFAMILY_PALADIN
) &&
1822 (m_spellInfo
->SpellIconID
== 70 || m_spellInfo
->SpellIconID
== 242))
1825 if(m_spellInfo
->SpellFamilyName
== SPELLFAMILY_PALADIN
&& (m_spellInfo
->SpellFamilyFlags
& (1<<23)))
1827 // paladin's judgement
1828 if(!unitTarget
|| !unitTarget
->isAlive())
1830 uint32 spellId2
= 0;
1831 Unit::AuraMap
& m_auras
= m_caster
->GetAuras();
1832 Unit::AuraMap::iterator itr
,next
;
1834 for(itr
= m_auras
.begin(); itr
!= m_auras
.end(); itr
= next
)
1840 SpellEntry
const *spellInfo
= itr
->second
->GetSpellProto();
1841 if (!spellInfo
) continue;
1842 if (spellInfo
->SpellVisual
!= 5622 || spellInfo
->SpellFamilyName
!= SPELLFAMILY_PALADIN
) continue;
1843 spellId2
= spellInfo
->EffectBasePoints
[2]+1;
1846 m_caster
->RemoveAurasDueToSpell(spellInfo
->Id
);
1847 next
= m_auras
.begin();
1852 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(spellId2
);
1855 Spell
*p_spell
= new Spell(m_caster
,spellInfo
,true,0);
1857 SpellCastTargets targets
;
1858 Unit
*ptarget
= unitTarget
;
1859 targets
.setUnitTarget(ptarget
);
1860 p_spell
->prepare(&targets
);
1862 delete p_spell
; // triggered spell not self deleted
1868 switch(m_spellInfo
->Id
)
1871 itemtype
= 5512; //spell 6261; //primary healstone
1874 itemtype
= 5511; //spell 6262; //inferior healstone
1877 itemtype
= 5509; //spell 5720; //healstone
1880 itemtype
= 5510; //spell 5723; //strong healstone
1883 itemtype
= 9421; //spell 11732; //super healstone
1888 DoCreateItem( i
, itemtype
);
1892 void Spell::EffectAddComboPoints(uint32 i
)
1897 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
1900 uint8 comboPoints
= ((m_caster
->GetUInt32Value(PLAYER_FIELD_BYTES
) & 0xFF00) >> 8);
1901 if(m_caster
->GetUInt64Value(PLAYER_FIELD_COMBO_TARGET
) != unitTarget
->GetGUID())
1903 comboPoints
= damage
;
1904 m_caster
->SetUInt64Value(PLAYER_FIELD_COMBO_TARGET
,unitTarget
->GetGUID());
1905 m_caster
->SetUInt32Value(PLAYER_FIELD_BYTES
,((m_caster
->GetUInt32Value(PLAYER_FIELD_BYTES
) & ~(0xFF << 8)) | (comboPoints
<< 8)));
1907 else if(comboPoints
< 5)
1909 comboPoints
+= damage
;
1912 m_caster
->SetUInt32Value(PLAYER_FIELD_BYTES
,((m_caster
->GetUInt32Value(PLAYER_FIELD_BYTES
) & ~(0xFF << 8)) | (comboPoints
<< 8)));
1917 void Spell::EffectDuel(uint32 i
)
1919 if(!m_caster
|| !unitTarget
|| m_caster
->GetTypeId() != TYPEID_PLAYER
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
1922 Player
*caster
= (Player
*)m_caster
;
1923 Player
*target
= (Player
*)unitTarget
;
1925 // caster or target already have requested duel
1926 if( caster
->duel
|| target
->duel
|| target
->HasInIgnoreList(caster
->GetGUID()) )
1929 //CREATE DUEL FLAG OBJECT
1930 GameObject
* pGameObj
= new GameObject();
1932 uint32 gameobject_id
= m_spellInfo
->EffectMiscValue
[i
];
1934 if(!pGameObj
->Create(objmgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), gameobject_id
,m_caster
->GetMapId(),
1935 m_caster
->GetPositionX()+(unitTarget
->GetPositionX()-m_caster
->GetPositionX())/2 ,
1936 m_caster
->GetPositionY()+(unitTarget
->GetPositionY()-m_caster
->GetPositionY())/2 ,
1937 m_caster
->GetPositionZ(),
1938 m_caster
->GetOrientation(), 0, 0, 0, 0, 0, 0))
1943 pGameObj
->SetFloatValue(OBJECT_FIELD_SCALE_X
,1.0f
);
1945 pGameObj
->SetUInt32Value(GAMEOBJECT_DISPLAYID
, 787 );
1946 pGameObj
->SetUInt32Value(GAMEOBJECT_FACTION
, m_caster
->getFaction() );
1947 pGameObj
->SetUInt32Value(GAMEOBJECT_TYPE_ID
, 16 );
1948 pGameObj
->SetUInt32Value(GAMEOBJECT_LEVEL
, m_caster
->getLevel()+1 );
1949 pGameObj
->SetRespawnTime(GetDuration(m_spellInfo
)/1000);
1950 pGameObj
->SetSpellId(m_spellInfo
->Id
);
1952 m_caster
->AddGameObject(pGameObj
);
1953 MapManager::Instance().GetMap(pGameObj
->GetMapId())->Add(pGameObj
);
1957 WorldPacket
data(SMSG_DUEL_REQUESTED
, 16);
1958 data
<< pGameObj
->GetGUID();
1959 data
<< caster
->GetGUID();
1960 caster
->GetSession()->SendPacket(&data
);
1961 target
->GetSession()->SendPacket(&data
);
1964 DuelInfo
*duel
= new DuelInfo
;
1965 duel
->initiator
= caster
;
1966 duel
->opponent
= target
;
1967 duel
->startTime
= 0;
1968 duel
->startTimer
= 0;
1969 caster
->duel
= duel
;
1971 DuelInfo
*duel2
= new DuelInfo
;
1972 duel2
->initiator
= caster
;
1973 duel2
->opponent
= caster
;
1974 duel2
->startTime
= 0;
1975 duel2
->startTimer
= 0;
1976 target
->duel
= duel2
;
1978 caster
->SetUInt64Value(PLAYER_DUEL_ARBITER
,pGameObj
->GetGUID());
1979 target
->SetUInt64Value(PLAYER_DUEL_ARBITER
,pGameObj
->GetGUID());
1983 void Spell::EffectSummonTotem(uint32 i
)
1986 switch(m_spellInfo
->Effect
[i
])
1988 case SPELL_EFFECT_SUMMON_TOTEM_SLOT1
: slot
= 0; break;
1989 case SPELL_EFFECT_SUMMON_TOTEM_SLOT2
: slot
= 1; break;
1990 case SPELL_EFFECT_SUMMON_TOTEM_SLOT3
: slot
= 2; break;
1991 case SPELL_EFFECT_SUMMON_TOTEM_SLOT4
: slot
= 3; break;
1995 float angle
= m_caster
->GetOrientation() + M_PI
/4 - (slot
*M_PI
/2);
1996 float x
= m_caster
->GetPositionX() + 2 * cos(angle
);
1997 float y
= m_caster
->GetPositionY() + 2 * sin(angle
);
1998 float z
= m_caster
->GetPositionZ();
2000 Map
* map
= MapManager::Instance().GetMap(m_caster
->GetMapId());
2001 float z2
= map
->GetHeight(x
,y
);
2002 if( abs( z2
- z
) < 5 )
2005 uint64 guid
= m_caster
->m_TotemSlot
[slot
];
2008 Creature
*OldTotem
= ObjectAccessor::Instance().GetCreature(*m_caster
, guid
);
2009 if(OldTotem
&& OldTotem
->isTotem()) ((Totem
*)OldTotem
)->UnSummon();
2010 m_caster
->m_TotemSlot
[slot
] = 0;
2013 Totem
* pTotem
= new Totem();
2015 if(!pTotem
->Create(objmgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
),
2016 m_caster
->GetMapId(), x
, y
, z
, m_caster
->GetOrientation(),
2017 m_spellInfo
->EffectMiscValue
[i
] ))
2023 m_caster
->m_TotemSlot
[slot
] = pTotem
->GetGUID();
2024 pTotem
->SetOwner(m_caster
->GetGUID());
2025 //pTotem->SetSpell(pTotem->GetCreatureInfo()->spell1);
2026 pTotem
->SetSpell(m_spellInfo
->Id
); //use SummonTotem spellid
2027 pTotem
->SetDuration(GetDuration(m_spellInfo
));
2028 pTotem
->SetHealth(5);
2029 pTotem
->SetMaxHealth(5);
2033 void Spell::EffectEnchantHeldItem(uint32 i
)
2035 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
2038 Player
* p_caster
= (Player
*)m_caster
;
2044 if(!itemTarget
->IsEquipped())
2047 if (m_spellInfo
->EffectMiscValue
[i
])
2049 uint32 enchant_id
= m_spellInfo
->EffectMiscValue
[i
];
2050 int32 duration
= GetDuration(m_spellInfo
);
2052 duration
= m_spellInfo
->EffectBasePoints
[i
]+1;
2055 SpellItemEnchantmentEntry
const *pEnchant
= sSpellItemEnchantmentStore
.LookupEntry(enchant_id
);
2059 // can be held by another player and accessable to caster in trade slot
2060 Player
* item_owner
= itemTarget
->GetOwner();
2064 if(item_owner
!=p_caster
&& p_caster
->GetSession()->GetSecurity() > 0 && sWorld
.getConfig(CONFIG_GM_LOG_TRADE
) )
2065 sLog
.outCommand("GM Enchanting: %s (Entry: %d) GM: %s (Account: %u) Player: %s (Account: %u)",
2066 itemTarget
->GetProto()->Name1
,itemTarget
->GetEntry(),
2067 p_caster
->GetName(),p_caster
->GetSession()->GetAccountId(),
2068 item_owner
->GetName(),item_owner
->GetSession()->GetAccountId());
2070 // remove old enchanting before appling new
2071 if(uint32 old_enchant_id
= itemTarget
->GetUInt32Value(ITEM_FIELD_ENCHANTMENT
+pEnchant
->display_type
*3))
2072 item_owner
->AddItemEnchant(itemTarget
,old_enchant_id
,false);
2074 for(int x
=0;x
<3;x
++)
2075 itemTarget
->SetUInt32Value(ITEM_FIELD_ENCHANTMENT
+pEnchant
->display_type
*3+x
,0);
2077 itemTarget
->SetUInt32Value(ITEM_FIELD_ENCHANTMENT
+pEnchant
->display_type
*3, enchant_id
);
2078 itemTarget
->SetUInt32Value(ITEM_FIELD_ENCHANTMENT
+pEnchant
->display_type
*3+1, duration
*1000);
2079 itemTarget
->SetState(ITEM_CHANGED
);
2081 // add new enchanting
2082 item_owner
->AddItemEnchant(itemTarget
,enchant_id
,true);
2085 item_owner
->AddEnchantDuration(itemTarget
,1,duration
*1000);
2089 void Spell::EffectDisEnchant(uint32 i
)
2091 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
2094 Player
* p_caster
= (Player
*)m_caster
;
2097 uint32 item_level
= itemTarget
->GetProto()->ItemLevel
;
2098 uint32 item_quality
= itemTarget
->GetProto()->Quality
;
2102 if(item_level
>= 66)
2109 else if(item_level
>= 51 && item_level
<= 65)
2111 if(item_quality
== 4)
2116 else if(item_quality
== 3)
2121 else if(item_quality
== 2)
2123 count
= urand(1,(item_level
/10));
2124 if(urand(1,100)< 85)
2130 else if(item_level
>= 46 && item_level
<= 50)
2132 if(item_quality
== 4)
2137 else if(item_quality
== 3)
2142 else if(item_quality
== 2)
2144 count
= urand(1,(item_level
/10));
2145 if(urand(1,100)< 85)
2151 else if(item_level
>= 41 && item_level
<= 45)
2153 if(item_quality
== 4)
2158 else if(item_quality
== 3)
2163 else if(item_quality
== 2)
2165 count
= urand(1,(item_level
/10));
2166 if(urand(1,100)< 85)
2172 else if(item_level
>= 36 && item_level
<= 40)
2174 if(item_quality
== 4)
2179 else if(item_quality
== 3)
2184 else if(item_quality
== 2)
2186 count
= urand(1,(item_level
/10));
2187 if(urand(1,100)< 85)
2193 else if(item_level
>= 31 && item_level
<= 35)
2195 if(item_quality
== 4)
2200 else if(item_quality
== 3)
2205 else if(item_quality
== 2)
2207 count
= (item_level
/10);
2208 if(urand(1,100)< 85)
2214 else if(item_level
>= 25 && item_level
<= 30)
2216 if(item_quality
== 4)
2221 else if(item_quality
== 3)
2226 else if(item_quality
== 2)
2228 count
= (item_level
/10);
2229 if(urand(1,100)< 85)
2235 else if(item_level
>= 21 && item_level
<= 25)
2237 if(item_quality
== 4)
2242 else if(item_quality
== 3)
2247 else if(item_quality
== 2)
2249 count
= (item_level
/10);
2250 if(urand(1,100)< 85)
2256 else if(item_level
>= 1 && item_level
<= 20)
2258 if(item_quality
== 4)
2263 else if(item_quality
== 3 && item_level
>=16)
2268 else if(item_quality
== 2)
2270 if(urand(1,100)< 70)
2275 else if(item_level
<=15 && urand(1,100)< 70 )
2280 else if(urand(1,100)< 50)
2293 if ( item
== 0 || count
== 0 )
2295 SendCastResult(CAST_FAIL_CANT_BE_DISENCHANTED
);
2296 //SendChannelUpdate(0);
2300 uint32 item_count
= 1;
2301 p_caster
->DestroyItemCount(itemTarget
,item_count
, true);
2302 p_caster
->UpdateCraftSkill(m_spellInfo
->Id
);
2305 uint8 msg
= p_caster
->CanStoreNewItem( NULL_BAG
, NULL_SLOT
, dest
, item
, count
, false );
2306 if( msg
== EQUIP_ERR_OK
)
2307 p_caster
->StoreNewItem( dest
, item
, count
, true );
2309 p_caster
->SendEquipError( msg
, NULL
, NULL
);
2313 void Spell::EffectInebriate(uint32 i
)
2315 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
2318 Player
*player
= (Player
*)m_caster
;
2319 uint16 currentDrunk
= player
->GetDrunkValue();
2320 uint16 drunkMod
= (m_spellInfo
->EffectBasePoints
[i
]+1) * 0xFFFF / 100;
2321 if (currentDrunk
+ drunkMod
> 0xFFFF)
2322 currentDrunk
= 0xFFFF;
2324 currentDrunk
+= drunkMod
;
2325 player
->SetDrunkValue(currentDrunk
);
2328 void Spell::EffectFeedPet(uint32 i
)
2330 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
2333 Player
*_player
= (Player
*)m_caster
;
2338 Creature
*pet
= _player
->GetPet();
2344 pet
->ModifyPower(POWER_HAPPINESS
,damage
);
2347 _player
->DestroyItemCount(itemTarget
,count
,true);
2349 SpellEntry
const *spellinfo
= sSpellStore
.LookupEntry(m_spellInfo
->EffectTriggerSpell
[i
]);
2350 Spell
_spell(m_caster
, spellinfo
, true, 0);
2351 SpellCastTargets targets
;
2352 targets
.setUnitTarget(m_caster
);
2353 _spell
.prepare(&targets
);
2356 void Spell::EffectDismissPet(uint32 i
)
2358 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
2361 Pet
* pet
= m_caster
->GetPet();
2363 // not let dismiss dead pet
2364 if(!pet
||!pet
->isAlive())
2367 ((Player
*)m_caster
)->RemovePet(pet
,PET_SAVE_AS_CURRENT
);
2370 void Spell::EffectSummonObject(uint32 i
)
2373 switch(m_spellInfo
->Effect
[i
])
2375 case SPELL_EFFECT_SUMMON_OBJECT_SLOT1
: slot
= 0; break;
2376 case SPELL_EFFECT_SUMMON_OBJECT_SLOT2
: slot
= 1; break;
2377 case SPELL_EFFECT_SUMMON_OBJECT_SLOT3
: slot
= 2; break;
2378 case SPELL_EFFECT_SUMMON_OBJECT_SLOT4
: slot
= 3; break;
2382 uint64 guid
= m_caster
->m_ObjectSlot
[slot
];
2385 GameObject
* obj
= NULL
;
2387 obj
= ObjectAccessor::Instance().GetGameObject(*m_caster
, guid
);
2389 if(obj
) obj
->Delete();
2390 m_caster
->m_ObjectSlot
[slot
] = 0;
2393 GameObject
* pGameObj
= new GameObject();
2394 uint32 display_id
= m_spellInfo
->EffectMiscValue
[i
];
2396 float rot2
= sin(m_caster
->GetOrientation()/2);
2397 float rot3
= cos(m_caster
->GetOrientation()/2);
2399 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))
2405 pGameObj
->SetUInt32Value(GAMEOBJECT_LEVEL
,m_caster
->getLevel());
2406 pGameObj
->SetRespawnTime(GetDuration(m_spellInfo
)/1000);
2407 pGameObj
->SetSpellId(m_spellInfo
->Id
);
2408 pGameObj
->SetLootState(GO_CLOSED
);
2409 m_caster
->AddGameObject(pGameObj
);
2411 MapManager::Instance().GetMap(pGameObj
->GetMapId())->Add(pGameObj
);
2412 WorldPacket
data(SMSG_GAMEOBJECT_SPAWN_ANIM
, 8);
2413 data
<< pGameObj
->GetGUID();
2414 m_caster
->SendMessageToSet(&data
,true);
2416 m_caster
->m_ObjectSlot
[slot
] = pGameObj
->GetGUID();
2419 void Spell::EffectResurrect(uint32 i
)
2424 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
2427 if(unitTarget
->isAlive())
2429 if(!unitTarget
->IsInWorld())
2432 Player
* pTarget
= ((Player
*)unitTarget
);
2434 uint32 health
= m_spellInfo
->EffectBasePoints
[i
]+1;
2435 uint32 mana
= m_spellInfo
->EffectMiscValue
[i
];
2437 ((Player
*)unitTarget
)->setResurrect(m_caster
->GetGUID(), m_caster
->GetPositionX(), m_caster
->GetPositionY(), m_caster
->GetPositionZ(), health
, mana
);
2438 SendResurrectRequest(pTarget
);
2441 void Spell::EffectParry(uint32 i
)
2443 if (unitTarget
->GetTypeId() == TYPEID_PLAYER
)
2445 ((Player
*)unitTarget
)->SetCanParry(true);
2449 void Spell::EffectMomentMove(uint32 i
)
2451 if(unitTarget
->isInFlight())
2454 if( m_spellInfo
->rangeIndex
== 1) //self range
2456 uint32 mapid
= m_caster
->GetMapId();
2457 float dis
= GetRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[i
]));
2458 float fx
= m_caster
->GetPositionX() + dis
* cos(m_caster
->GetOrientation());
2459 float fy
= m_caster
->GetPositionY() + dis
* sin(m_caster
->GetOrientation());
2460 // teleport a bit above terrainlevel to avoid falling below it
2461 float fz
= MapManager::Instance ().GetMap(mapid
)->GetHeight(fx
,fy
) + 1.5;
2463 if(unitTarget
->GetTypeId() == TYPEID_PLAYER
)
2464 ((Player
*)unitTarget
)->TeleportTo(mapid
, fx
, fy
, fz
, m_caster
->GetOrientation(), false);
2466 MapManager::Instance().GetMap(mapid
)->CreatureRelocation((Creature
*)m_caster
, fx
, fy
, fz
, m_caster
->GetOrientation());
2470 void Spell::EffectReputation(uint32 i
)
2472 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
2475 Player
*_player
= (Player
*)m_caster
;
2477 int32 rep_change
= m_spellInfo
->EffectBasePoints
[i
]+1; // field store reputation change -1
2479 uint32 faction_id
= m_spellInfo
->EffectMiscValue
[i
];
2481 FactionEntry
const* factionEntry
= sFactionStore
.LookupEntry(faction_id
);
2486 _player
->ModifyFactionReputation(factionEntry
,rep_change
);
2489 void Spell::EffectQuestComplete(uint32 i
)
2491 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
2494 Player
*_player
= (Player
*)m_caster
;
2496 uint32 quest_id
= m_spellInfo
->EffectMiscValue
[i
];
2498 if(_player
->CanCompleteQuest( quest_id
) )
2499 _player
->CompleteQuest( quest_id
);
2503 if(_player
->GetQuestRewardStatus( quest_id
))
2506 _player
->PlayerTalkClass
->SendQuestGiverOfferReward( quest_id
, _player
->GetGUID(), true, NULL
, 0 );
2509 void Spell::EffectSelfResurrect(uint32 i
)
2511 if(!unitTarget
) return;
2512 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
) return;
2513 if(unitTarget
->isAlive()) return;
2514 if(!unitTarget
->IsInWorld()) return;
2519 if(m_spellInfo
->SpellVisual
== 99 && m_spellInfo
->SpellIconID
==1)
2521 health
= m_spellInfo
->EffectBasePoints
[i
]+1 > 0 ? m_spellInfo
->EffectBasePoints
[i
]+1 :(-(m_spellInfo
->EffectBasePoints
[i
]+1));
2522 if(unitTarget
->getPowerType() == POWER_MANA
)
2523 mana
= m_spellInfo
->EffectMiscValue
[i
];
2527 health
= uint32(damage
/100*unitTarget
->GetMaxHealth());
2528 if(unitTarget
->getPowerType() == POWER_MANA
)
2529 mana
= uint32(damage
/100*unitTarget
->GetMaxPower(unitTarget
->getPowerType()));
2531 ((Player
*)unitTarget
)->setResurrect(m_caster
->GetGUID(), m_caster
->GetPositionX(), m_caster
->GetPositionY(), m_caster
->GetPositionZ(), health
, mana
);
2532 SendResurrectRequest((Player
*)unitTarget
);
2535 void Spell::EffectSkinning(uint32 i
)
2537 if(unitTarget
->GetTypeId() != TYPEID_UNIT
)
2539 if(!m_caster
|| m_caster
->GetTypeId() != TYPEID_PLAYER
)
2542 int32 targetLevel
= unitTarget
->getLevel();
2544 ((Player
*)m_caster
)->SendLoot(unitTarget
->GetGUID(),LOOT_SKINNING
);
2545 unitTarget
->RemoveFlag(UNIT_FIELD_FLAGS
, UNIT_FLAG_SKINNABLE
);
2547 int32 reqValue
= targetLevel
< 10 ? 0 : targetLevel
< 20 ? (targetLevel
-10)*10 : targetLevel
*5;
2549 int32 skinningValue
= ((Player
*)m_caster
)->GetPureSkillValue(SKILL_SKINNING
);
2551 // Double chances for elites
2552 ((Player
*)m_caster
)->UpdateGatherSkill(SKILL_SKINNING
, skinningValue
, reqValue
, ((Creature
*)unitTarget
)->isElite() ? 2 : 1 );
2555 void Spell::EffectCharge(uint32 i
)
2557 if(!unitTarget
|| !m_caster
)
2561 unitTarget
->GetClosePoint(m_caster
, x
, y
, z
);
2562 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
2563 ((Creature
*)unitTarget
)->StopMoving();
2565 m_caster
->SendMonsterMove(x
, y
, z
, false,true,1);
2566 m_caster
->Attack(unitTarget
);
2569 void Spell::EffectSummonCritter(uint32 i
)
2571 uint32 pet_entry
= m_spellInfo
->EffectMiscValue
[i
];
2575 Unit
* old_critter
= NULL
;
2578 CellPair
p(MaNGOS::ComputeCellPair(m_caster
->GetPositionX(), m_caster
->GetPositionY()));
2579 Cell cell
= RedZone::GetZone(p
);
2580 cell
.data
.Part
.reserved
= ALL_DISTRICT
;
2583 PetWithIdCheck
u_check(m_caster
, pet_entry
);
2584 MaNGOS::UnitSearcher
<PetWithIdCheck
> checker(old_critter
, u_check
);
2585 TypeContainerVisitor
<MaNGOS::UnitSearcher
<PetWithIdCheck
>, TypeMapContainer
<AllObjectTypes
> > object_checker(checker
);
2586 CellLock
<GridReadGuard
> cell_lock(cell
, p
);
2587 cell_lock
->Visit(cell_lock
, object_checker
, *MapManager::Instance().GetMap(m_caster
->GetMapId()));
2590 if (old_critter
) // find old critter, unsummon
2592 // PetWithIdCheck return only Pets
2593 ((Pet
*)old_critter
)->Remove(PET_SAVE_AS_DELETED
);
2596 else // in another case summon new
2598 Pet
* critter
= new Pet(MINI_PET
);
2600 if(!critter
->Create(objmgr
.GenerateLowGuid(HIGHGUID_UNIT
),
2601 m_caster
->GetMapId(),
2602 m_caster
->GetPositionX(),m_caster
->GetPositionY(),
2603 m_caster
->GetPositionZ(),m_caster
->GetOrientation(),
2604 m_spellInfo
->EffectMiscValue
[i
]))
2606 sLog
.outError("no such creature entry %u",m_spellInfo
->EffectMiscValue
[i
]);
2611 critter
->SetUInt64Value(UNIT_FIELD_SUMMONEDBY
,m_caster
->GetGUID());
2612 critter
->SetUInt64Value(UNIT_FIELD_CREATEDBY
,m_caster
->GetGUID());
2613 critter
->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE
,m_caster
->getFaction());
2615 critter
->AIM_Initialize();
2618 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
2619 name
= ((Player
*)m_caster
)->GetName();
2621 name
= ((Creature
*)m_caster
)->GetCreatureInfo()->Name
;
2622 name
.append(petTypeSuffix
[critter
->getPetType()]);
2623 critter
->SetName( name
);
2624 //m_caster->SetPet(critter);
2626 critter
->AddToWorld();
2627 MapManager::Instance().GetMap(m_caster
->GetMapId())->Add((Creature
*)critter
);
2631 void Spell::EffectKnockBack(uint32 i
)
2633 if(!unitTarget
|| !m_caster
)
2636 //Effect only works on players
2637 if(unitTarget
->GetTypeId()!=TYPEID_PLAYER
)
2641 int32 basePoints
= m_spellInfo
->EffectBasePoints
[i
];
2642 int32 randomPoints
= m_spellInfo
->EffectDieSides
[i
];
2643 if (randomPoints
) value
= basePoints
+ rand()%randomPoints
;
2644 else value
= basePoints
;
2646 //Only allowed to knock ourselves straight up to prevent exploiting
2647 if (unitTarget
== m_caster
)value
= 0;
2649 WorldPacket
data(SMSG_MOVE_KNOCK_BACK
, (8+4+4+4+4+4));
2650 data
.append(unitTarget
->GetPackGUID());
2651 data
<< uint32(0); //Sequence
2652 data
<< cos(m_caster
->GetAngle(unitTarget
)); //xdirection
2653 data
<< sin(m_caster
->GetAngle(unitTarget
)); //ydirection
2654 data
<< value
/10; //Horizontal speed
2655 data
<< float(m_spellInfo
->EffectMiscValue
[i
])/-10; //Z Movement speed
2657 ((Player
*)unitTarget
)->SendMessageToSet(&data
,true);
2660 void Spell::EffectSummonDeadPet(uint32 i
)
2662 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
2664 Player
*_player
= (Player
*)m_caster
;
2665 Pet
*pet
= _player
->GetPet();
2670 pet
->SetUInt32Value(UNIT_DYNAMIC_FLAGS
, 0);
2671 pet
->RemoveFlag (UNIT_FIELD_FLAGS
, UNIT_FLAG_SKINNABLE
);
2672 pet
->setDeathState( ALIVE
);
2673 pet
->clearUnitState(UNIT_STAT_ALL_STATE
);
2674 pet
->SetHealth( uint32(pet
->GetMaxHealth()*damage
/100));
2676 pet
->AIM_Initialize();
2678 _player
->PetSpellInitialize();
2679 pet
->SavePetToDB(PET_SAVE_AS_CURRENT
);
2682 void Spell::EffectTransmitted(uint32 i
)
2686 float min_dis
= GetMinRange(sSpellRangeStore
.LookupEntry(m_spellInfo
->rangeIndex
));
2687 float max_dis
= GetMaxRange(sSpellRangeStore
.LookupEntry(m_spellInfo
->rangeIndex
));
2688 float diff
= max_dis
- min_dis
+ 1;
2689 float dis
= (float)(rand()%(uint32
)diff
+ (uint32
)min_dis
);
2691 fx
= m_caster
->GetPositionX() + dis
* cos(m_caster
->GetOrientation());
2692 fy
= m_caster
->GetPositionY() + dis
* sin(m_caster
->GetOrientation());
2694 float fz
= MapManager::Instance ().GetMap(m_caster
->GetMapId())->GetHeight(fx
,fy
);
2696 if(m_spellInfo
->EffectMiscValue
[i
] == 35591)
2698 Map
* map
= MapManager::Instance().GetMap(m_caster
->GetMapId());
2699 if ( !map
->IsUnderWater(fx
,fy
,fz
) )
2701 SendCastResult(CAST_FAIL_CANT_BE_CAST_HERE
);
2703 SendChannelUpdate(0);
2707 // replace by water level in this case
2708 fz
= MapManager::Instance ().GetMap(m_caster
->GetMapId())->GetWaterLevel(fx
,fy
);
2712 GameObject
* pGameObj
= new GameObject();
2713 uint32 name_id
= m_spellInfo
->EffectMiscValue
[i
];
2715 if(!pGameObj
->Create(objmgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), name_id
,m_caster
->GetMapId(),
2716 fx
, fy
, fz
, m_caster
->GetOrientation(), 0, 0, 0, 0, 100, 0))
2722 if(m_spellInfo
->EffectMiscValue
[i
] == 35591)
2724 m_caster
->SetUInt32Value(UNIT_FIELD_CHANNEL_OBJECT
,pGameObj
->GetGUIDLow());
2725 m_caster
->SetUInt32Value(UNIT_FIELD_CHANNEL_OBJECT
+1,pGameObj
->GetGUIDHigh());
2727 pGameObj
->SetFloatValue(GAMEOBJECT_ROTATION
+ 2, 0.88431775569915771 );
2729 pGameObj
->SetFloatValue(GAMEOBJECT_ROTATION
+ 3, -0.4668855369091033 );
2730 pGameObj
->SetLootState(GO_NOT_READY
); // bobber not move
2731 m_caster
->AddGameObject(pGameObj
); // will removed at spell cancel
2733 // end time of range when posable catch fish (FISHING_BOBBER_READY_TIME..GetDuration(m_spellInfo))
2734 // start time == fish-FISHING_BOBBER_READY_TIME (0..GetDuration(m_spellInfo)-FISHING_BOBBER_READY_TIME)
2735 uint32 fish
= urand(FISHING_BOBBER_READY_TIME
,GetDuration(m_spellInfo
)/1000);
2736 pGameObj
->SetRespawnTime(fish
);
2740 pGameObj
->SetOwnerGUID(m_caster
->GetGUID() );
2741 pGameObj
->SetRespawnTime(GetDuration(m_spellInfo
)/1000);
2744 pGameObj
->SetUInt32Value(12, 0x3F63BB3C );
2745 pGameObj
->SetUInt32Value(13, 0xBEE9E017 );
2746 pGameObj
->SetUInt32Value(GAMEOBJECT_LEVEL
, m_caster
->getLevel() );
2747 pGameObj
->SetSpellId(m_spellInfo
->Id
);
2749 DEBUG_LOG("AddObject at SpellEfects.cpp EffectTransmitted\n");
2750 //m_caster->AddGameObject(pGameObj);
2751 //m_ObjToDel.push_back(pGameObj);
2753 MapManager::Instance().GetMap(pGameObj
->GetMapId())->Add(pGameObj
);
2754 pGameObj
->AddToWorld();
2756 WorldPacket
data(SMSG_GAMEOBJECT_SPAWN_ANIM
, 8);
2757 data
<< uint64(pGameObj
->GetGUID());
2758 m_caster
->SendMessageToSet(&data
,true);
2761 void Spell::EffectSkill(uint32 i
)
2763 sLog
.outDebug("WORLD: SkillEFFECT");