PageRenderTime 88ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 1ms

/src/server/game/Spells/Spell.cpp

https://gitlab.com/IlluminatiCore/IlluminatiCore
C++ | 7453 lines | 5814 code | 1007 blank | 632 comment | 2218 complexity | d9e7a50b5eb0c9922b1987c566c7600b MD5 | raw file
Possible License(s): GPL-2.0, BSD-2-Clause

Large files files are truncated, but you can click here to view the full file

  1. /*
  2. * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/>
  3. * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
  4. *
  5. * This program is free software; you can redistribute it and/or modify it
  6. * under the terms of the GNU General Public License as published by the
  7. * Free Software Foundation; either version 2 of the License, or (at your
  8. * option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful, but WITHOUT
  11. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  13. * more details.
  14. *
  15. * You should have received a copy of the GNU General Public License along
  16. * with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. #include "Common.h"
  19. #include "DatabaseEnv.h"
  20. #include "WorldPacket.h"
  21. #include "WorldSession.h"
  22. #include "GridNotifiers.h"
  23. #include "GridNotifiersImpl.h"
  24. #include "Opcodes.h"
  25. #include "Log.h"
  26. #include "UpdateMask.h"
  27. #include "World.h"
  28. #include "ObjectMgr.h"
  29. #include "SpellMgr.h"
  30. #include "Player.h"
  31. #include "Pet.h"
  32. #include "Unit.h"
  33. #include "Totem.h"
  34. #include "Spell.h"
  35. #include "DynamicObject.h"
  36. #include "Guild.h"
  37. #include "Group.h"
  38. #include "UpdateData.h"
  39. #include "MapManager.h"
  40. #include "ObjectAccessor.h"
  41. #include "CellImpl.h"
  42. #include "SharedDefines.h"
  43. #include "LootMgr.h"
  44. #include "VMapFactory.h"
  45. #include "Battleground.h"
  46. #include "Util.h"
  47. #include "TemporarySummon.h"
  48. #include "Vehicle.h"
  49. #include "SpellAuraEffects.h"
  50. #include "ScriptMgr.h"
  51. #include "ConditionMgr.h"
  52. #include "DisableMgr.h"
  53. #include "SpellScript.h"
  54. #include "InstanceScript.h"
  55. #include "SpellInfo.h"
  56. #include "DB2Stores.h"
  57. #include "Battlefield.h"
  58. #include "BattlefieldMgr.h"
  59. extern pEffect SpellEffects[TOTAL_SPELL_EFFECTS];
  60. SpellDestination::SpellDestination()
  61. {
  62. _position.Relocate(0, 0, 0, 0);
  63. _transportGUID.Clear();
  64. _transportOffset.Relocate(0, 0, 0, 0);
  65. }
  66. SpellDestination::SpellDestination(float x, float y, float z, float orientation, uint32 mapId)
  67. {
  68. _position.Relocate(x, y, z, orientation);
  69. _transportGUID.Clear();
  70. _position.m_mapId = mapId;
  71. _transportOffset.Relocate(0, 0, 0, 0);
  72. }
  73. SpellDestination::SpellDestination(Position const& pos)
  74. {
  75. _position.Relocate(pos);
  76. _transportGUID.Clear();
  77. _transportOffset.Relocate(0, 0, 0, 0);
  78. }
  79. SpellDestination::SpellDestination(WorldObject const& wObj)
  80. {
  81. _transportGUID = wObj.GetTransGUID();
  82. _transportOffset.Relocate(wObj.GetTransOffsetX(), wObj.GetTransOffsetY(), wObj.GetTransOffsetZ(), wObj.GetTransOffsetO());
  83. _position.Relocate(wObj);
  84. }
  85. void SpellDestination::Relocate(Position const& pos)
  86. {
  87. if (_transportGUID)
  88. {
  89. Position offset;
  90. _position.GetPositionOffsetTo(pos, offset);
  91. _transportOffset.RelocateOffset(offset);
  92. }
  93. _position.Relocate(pos);
  94. }
  95. void SpellDestination::RelocateOffset(Position const& offset)
  96. {
  97. if (_transportGUID)
  98. _transportOffset.RelocateOffset(offset);
  99. _position.RelocateOffset(offset);
  100. }
  101. SpellCastTargets::SpellCastTargets() : m_elevation(0), m_speed(0), m_strTarget()
  102. {
  103. m_objectTarget = NULL;
  104. m_itemTarget = NULL;
  105. m_itemTargetEntry = 0;
  106. m_targetMask = 0;
  107. }
  108. SpellCastTargets::~SpellCastTargets() { }
  109. void SpellCastTargets::Read(ByteBuffer& data, Unit* caster)
  110. {
  111. data >> m_targetMask;
  112. if (m_targetMask == TARGET_FLAG_NONE)
  113. return;
  114. if (m_targetMask & (TARGET_FLAG_UNIT | TARGET_FLAG_UNIT_MINIPET | TARGET_FLAG_GAMEOBJECT | TARGET_FLAG_CORPSE_ENEMY | TARGET_FLAG_CORPSE_ALLY))
  115. data >> m_objectTargetGUID.ReadAsPacked();
  116. if (m_targetMask & (TARGET_FLAG_ITEM | TARGET_FLAG_TRADE_ITEM))
  117. data >> m_itemTargetGUID.ReadAsPacked();
  118. if (m_targetMask & TARGET_FLAG_SOURCE_LOCATION)
  119. {
  120. data >> m_src._transportGUID.ReadAsPacked();
  121. if (m_src._transportGUID)
  122. data >> m_src._transportOffset.PositionXYZStream();
  123. else
  124. data >> m_src._position.PositionXYZStream();
  125. }
  126. else
  127. {
  128. m_src._transportGUID = caster->GetTransGUID();
  129. if (m_src._transportGUID)
  130. m_src._transportOffset.Relocate(caster->GetTransOffsetX(), caster->GetTransOffsetY(), caster->GetTransOffsetZ(), caster->GetTransOffsetO());
  131. else
  132. m_src._position.Relocate(caster);
  133. }
  134. if (m_targetMask & TARGET_FLAG_DEST_LOCATION)
  135. {
  136. data >> m_dst._transportGUID.ReadAsPacked();
  137. if (m_dst._transportGUID)
  138. data >> m_dst._transportOffset.PositionXYZStream();
  139. else
  140. data >> m_dst._position.PositionXYZStream();
  141. }
  142. else
  143. {
  144. m_dst._transportGUID = caster->GetTransGUID();
  145. if (m_dst._transportGUID)
  146. m_dst._transportOffset.Relocate(caster->GetTransOffsetX(), caster->GetTransOffsetY(), caster->GetTransOffsetZ(), caster->GetTransOffsetO());
  147. else
  148. m_dst._position.Relocate(caster);
  149. }
  150. if (m_targetMask & TARGET_FLAG_STRING)
  151. data >> m_strTarget;
  152. Update(caster);
  153. }
  154. void SpellCastTargets::Write(ByteBuffer& data)
  155. {
  156. data << uint32(m_targetMask);
  157. if (m_targetMask & (TARGET_FLAG_UNIT | TARGET_FLAG_CORPSE_ALLY | TARGET_FLAG_GAMEOBJECT | TARGET_FLAG_CORPSE_ENEMY | TARGET_FLAG_UNIT_MINIPET))
  158. data << m_objectTargetGUID.WriteAsPacked();
  159. if (m_targetMask & (TARGET_FLAG_ITEM | TARGET_FLAG_TRADE_ITEM))
  160. {
  161. if (m_itemTarget)
  162. data << m_itemTarget->GetPackGUID();
  163. else
  164. data << uint8(0);
  165. }
  166. if (m_targetMask & TARGET_FLAG_SOURCE_LOCATION)
  167. {
  168. data << m_src._transportGUID.WriteAsPacked(); // relative position guid here - transport for example
  169. if (m_src._transportGUID)
  170. data << m_src._transportOffset.PositionXYZStream();
  171. else
  172. data << m_src._position.PositionXYZStream();
  173. }
  174. if (m_targetMask & TARGET_FLAG_DEST_LOCATION)
  175. {
  176. data << m_dst._transportGUID.WriteAsPacked(); // relative position guid here - transport for example
  177. if (m_dst._transportGUID)
  178. data << m_dst._transportOffset.PositionXYZStream();
  179. else
  180. data << m_dst._position.PositionXYZStream();
  181. }
  182. if (m_targetMask & TARGET_FLAG_STRING)
  183. data << m_strTarget;
  184. }
  185. ObjectGuid SpellCastTargets::GetOrigUnitTargetGUID() const
  186. {
  187. switch (m_origObjectTargetGUID.GetHigh())
  188. {
  189. case HIGHGUID_PLAYER:
  190. case HIGHGUID_VEHICLE:
  191. case HIGHGUID_UNIT:
  192. case HIGHGUID_PET:
  193. return m_origObjectTargetGUID;
  194. default:
  195. return ObjectGuid();
  196. }
  197. }
  198. void SpellCastTargets::SetOrigUnitTarget(Unit* target)
  199. {
  200. if (!target)
  201. return;
  202. m_origObjectTargetGUID = target->GetGUID();
  203. }
  204. ObjectGuid SpellCastTargets::GetUnitTargetGUID() const
  205. {
  206. if (m_objectTargetGUID.IsUnit())
  207. return m_objectTargetGUID;
  208. return ObjectGuid::Empty;
  209. }
  210. Unit* SpellCastTargets::GetUnitTarget() const
  211. {
  212. if (m_objectTarget)
  213. return m_objectTarget->ToUnit();
  214. return NULL;
  215. }
  216. void SpellCastTargets::SetUnitTarget(Unit* target)
  217. {
  218. if (!target)
  219. return;
  220. m_objectTarget = target;
  221. m_objectTargetGUID = target->GetGUID();
  222. m_targetMask |= TARGET_FLAG_UNIT;
  223. }
  224. ObjectGuid SpellCastTargets::GetGOTargetGUID() const
  225. {
  226. if (m_objectTargetGUID.IsAnyTypeGameObject())
  227. return m_objectTargetGUID;
  228. return ObjectGuid::Empty;
  229. }
  230. GameObject* SpellCastTargets::GetGOTarget() const
  231. {
  232. if (m_objectTarget)
  233. return m_objectTarget->ToGameObject();
  234. return NULL;
  235. }
  236. void SpellCastTargets::SetGOTarget(GameObject* target)
  237. {
  238. if (!target)
  239. return;
  240. m_objectTarget = target;
  241. m_objectTargetGUID = target->GetGUID();
  242. m_targetMask |= TARGET_FLAG_GAMEOBJECT;
  243. }
  244. ObjectGuid SpellCastTargets::GetCorpseTargetGUID() const
  245. {
  246. if (m_objectTargetGUID.IsCorpse())
  247. return m_objectTargetGUID;
  248. return ObjectGuid::Empty;
  249. }
  250. Corpse* SpellCastTargets::GetCorpseTarget() const
  251. {
  252. if (m_objectTarget)
  253. return m_objectTarget->ToCorpse();
  254. return NULL;
  255. }
  256. WorldObject* SpellCastTargets::GetObjectTarget() const
  257. {
  258. return m_objectTarget;
  259. }
  260. ObjectGuid SpellCastTargets::GetObjectTargetGUID() const
  261. {
  262. return m_objectTargetGUID;
  263. }
  264. void SpellCastTargets::RemoveObjectTarget()
  265. {
  266. m_objectTarget = NULL;
  267. m_objectTargetGUID.Clear();
  268. m_targetMask &= ~(TARGET_FLAG_UNIT_MASK | TARGET_FLAG_CORPSE_MASK | TARGET_FLAG_GAMEOBJECT_MASK);
  269. }
  270. void SpellCastTargets::SetItemTarget(Item* item)
  271. {
  272. if (!item)
  273. return;
  274. m_itemTarget = item;
  275. m_itemTargetGUID = item->GetGUID();
  276. m_itemTargetEntry = item->GetEntry();
  277. m_targetMask |= TARGET_FLAG_ITEM;
  278. }
  279. void SpellCastTargets::SetTradeItemTarget(Player* caster)
  280. {
  281. m_itemTargetGUID.Set(uint64(TRADE_SLOT_NONTRADED));
  282. m_itemTargetEntry = 0;
  283. m_targetMask |= TARGET_FLAG_TRADE_ITEM;
  284. Update(caster);
  285. }
  286. void SpellCastTargets::UpdateTradeSlotItem()
  287. {
  288. if (m_itemTarget && (m_targetMask & TARGET_FLAG_TRADE_ITEM))
  289. {
  290. m_itemTargetGUID = m_itemTarget->GetGUID();
  291. m_itemTargetEntry = m_itemTarget->GetEntry();
  292. }
  293. }
  294. SpellDestination const* SpellCastTargets::GetSrc() const
  295. {
  296. return &m_src;
  297. }
  298. Position const* SpellCastTargets::GetSrcPos() const
  299. {
  300. return &m_src._position;
  301. }
  302. void SpellCastTargets::SetSrc(float x, float y, float z)
  303. {
  304. m_src = SpellDestination(x, y, z);
  305. m_targetMask |= TARGET_FLAG_SOURCE_LOCATION;
  306. }
  307. void SpellCastTargets::SetSrc(Position const& pos)
  308. {
  309. m_src = SpellDestination(pos);
  310. m_targetMask |= TARGET_FLAG_SOURCE_LOCATION;
  311. }
  312. void SpellCastTargets::SetSrc(WorldObject const& wObj)
  313. {
  314. m_src = SpellDestination(wObj);
  315. m_targetMask |= TARGET_FLAG_SOURCE_LOCATION;
  316. }
  317. void SpellCastTargets::ModSrc(Position const& pos)
  318. {
  319. ASSERT(m_targetMask & TARGET_FLAG_SOURCE_LOCATION);
  320. m_src.Relocate(pos);
  321. }
  322. void SpellCastTargets::RemoveSrc()
  323. {
  324. m_targetMask &= ~(TARGET_FLAG_SOURCE_LOCATION);
  325. }
  326. SpellDestination const* SpellCastTargets::GetDst() const
  327. {
  328. return &m_dst;
  329. }
  330. WorldLocation const* SpellCastTargets::GetDstPos() const
  331. {
  332. return &m_dst._position;
  333. }
  334. void SpellCastTargets::SetDst(float x, float y, float z, float orientation, uint32 mapId)
  335. {
  336. m_dst = SpellDestination(x, y, z, orientation, mapId);
  337. m_targetMask |= TARGET_FLAG_DEST_LOCATION;
  338. }
  339. void SpellCastTargets::SetDst(Position const& pos)
  340. {
  341. m_dst = SpellDestination(pos);
  342. m_targetMask |= TARGET_FLAG_DEST_LOCATION;
  343. }
  344. void SpellCastTargets::SetDst(WorldObject const& wObj)
  345. {
  346. m_dst = SpellDestination(wObj);
  347. m_targetMask |= TARGET_FLAG_DEST_LOCATION;
  348. }
  349. void SpellCastTargets::SetDst(SpellDestination const& spellDest)
  350. {
  351. m_dst = spellDest;
  352. m_targetMask |= TARGET_FLAG_DEST_LOCATION;
  353. }
  354. void SpellCastTargets::SetDst(SpellCastTargets const& spellTargets)
  355. {
  356. m_dst = spellTargets.m_dst;
  357. m_targetMask |= TARGET_FLAG_DEST_LOCATION;
  358. }
  359. void SpellCastTargets::ModDst(Position const& pos)
  360. {
  361. ASSERT(m_targetMask & TARGET_FLAG_DEST_LOCATION);
  362. m_dst.Relocate(pos);
  363. }
  364. void SpellCastTargets::ModDst(SpellDestination const& spellDest)
  365. {
  366. ASSERT(m_targetMask & TARGET_FLAG_DEST_LOCATION);
  367. m_dst = spellDest;
  368. }
  369. void SpellCastTargets::RemoveDst()
  370. {
  371. m_targetMask &= ~(TARGET_FLAG_DEST_LOCATION);
  372. }
  373. void SpellCastTargets::Update(Unit* caster)
  374. {
  375. m_objectTarget = m_objectTargetGUID ? ((m_objectTargetGUID == caster->GetGUID()) ? caster : ObjectAccessor::GetWorldObject(*caster, m_objectTargetGUID)) : NULL;
  376. m_itemTarget = NULL;
  377. if (caster->GetTypeId() == TYPEID_PLAYER)
  378. {
  379. Player* player = caster->ToPlayer();
  380. if (m_targetMask & TARGET_FLAG_ITEM)
  381. m_itemTarget = player->GetItemByGuid(m_itemTargetGUID);
  382. else if (m_targetMask & TARGET_FLAG_TRADE_ITEM)
  383. if (m_itemTargetGUID.GetRawValue() == TRADE_SLOT_NONTRADED) // here it is not guid but slot. Also prevents hacking slots
  384. if (TradeData* pTrade = player->GetTradeData())
  385. m_itemTarget = pTrade->GetTraderData()->GetItem(TRADE_SLOT_NONTRADED);
  386. if (m_itemTarget)
  387. m_itemTargetEntry = m_itemTarget->GetEntry();
  388. }
  389. // update positions by transport move
  390. if (HasSrc() && m_src._transportGUID)
  391. {
  392. if (WorldObject* transport = ObjectAccessor::GetWorldObject(*caster, m_src._transportGUID))
  393. {
  394. m_src._position.Relocate(transport);
  395. m_src._position.RelocateOffset(m_src._transportOffset);
  396. }
  397. }
  398. if (HasDst() && m_dst._transportGUID)
  399. {
  400. if (WorldObject* transport = ObjectAccessor::GetWorldObject(*caster, m_dst._transportGUID))
  401. {
  402. m_dst._position.Relocate(transport);
  403. m_dst._position.RelocateOffset(m_dst._transportOffset);
  404. }
  405. }
  406. }
  407. void SpellCastTargets::OutDebug() const
  408. {
  409. if (!m_targetMask)
  410. TC_LOG_INFO("spells", "No targets");
  411. TC_LOG_INFO("spells", "target mask: %u", m_targetMask);
  412. if (m_targetMask & (TARGET_FLAG_UNIT_MASK | TARGET_FLAG_CORPSE_MASK | TARGET_FLAG_GAMEOBJECT_MASK))
  413. TC_LOG_INFO("spells", "Object target: %s", m_objectTargetGUID.ToString().c_str());
  414. if (m_targetMask & TARGET_FLAG_ITEM)
  415. TC_LOG_INFO("spells", "Item target: %s", m_itemTargetGUID.ToString().c_str());
  416. if (m_targetMask & TARGET_FLAG_TRADE_ITEM)
  417. TC_LOG_INFO("spells", "Trade item target: %s", m_itemTargetGUID.ToString().c_str());
  418. if (m_targetMask & TARGET_FLAG_SOURCE_LOCATION)
  419. TC_LOG_INFO("spells", "Source location: transport guid:%s trans offset: %s position: %s", m_src._transportGUID.ToString().c_str(), m_src._transportOffset.ToString().c_str(), m_src._position.ToString().c_str());
  420. if (m_targetMask & TARGET_FLAG_DEST_LOCATION)
  421. TC_LOG_INFO("spells", "Destination location: transport guid:%s trans offset: %s position: %s", m_dst._transportGUID.ToString().c_str(), m_dst._transportOffset.ToString().c_str(), m_dst._position.ToString().c_str());
  422. if (m_targetMask & TARGET_FLAG_STRING)
  423. TC_LOG_INFO("spells", "String: %s", m_strTarget.c_str());
  424. TC_LOG_INFO("spells", "speed: %f", m_speed);
  425. TC_LOG_INFO("spells", "elevation: %f", m_elevation);
  426. }
  427. SpellValue::SpellValue(SpellInfo const* proto)
  428. {
  429. for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i)
  430. EffectBasePoints[i] = proto->Effects[i].BasePoints;
  431. MaxAffectedTargets = proto->MaxAffectedTargets;
  432. RadiusMod = 1.0f;
  433. AuraStackAmount = 1;
  434. }
  435. Spell::Spell(Unit* caster, SpellInfo const* info, TriggerCastFlags triggerFlags, ObjectGuid originalCasterGUID, bool skipCheck) :
  436. m_spellInfo(sSpellMgr->GetSpellForDifficultyFromSpell(info, caster)),
  437. m_caster((info->AttributesEx6 & SPELL_ATTR6_CAST_BY_CHARMER && caster->GetCharmerOrOwner()) ? caster->GetCharmerOrOwner() : caster)
  438. , m_spellValue(new SpellValue(m_spellInfo)), m_preGeneratedPath(PathGenerator(m_caster))
  439. {
  440. m_customError = SPELL_CUSTOM_ERROR_NONE;
  441. m_skipCheck = skipCheck;
  442. m_selfContainer = NULL;
  443. m_referencedFromCurrentSpell = false;
  444. m_executedCurrently = false;
  445. m_needComboPoints = m_spellInfo->NeedsComboPoints();
  446. m_comboPointGain = 0;
  447. m_delayStart = 0;
  448. m_delayAtDamageCount = 0;
  449. m_applyMultiplierMask = 0;
  450. m_auraScaleMask = 0;
  451. memset(m_damageMultipliers, 0, sizeof(m_damageMultipliers));
  452. // Get data for type of attack
  453. switch (m_spellInfo->DmgClass)
  454. {
  455. case SPELL_DAMAGE_CLASS_MELEE:
  456. if (m_spellInfo->AttributesEx3 & SPELL_ATTR3_REQ_OFFHAND)
  457. m_attackType = OFF_ATTACK;
  458. else
  459. m_attackType = BASE_ATTACK;
  460. break;
  461. case SPELL_DAMAGE_CLASS_RANGED:
  462. m_attackType = m_spellInfo->IsRangedWeaponSpell() ? RANGED_ATTACK : BASE_ATTACK;
  463. break;
  464. default:
  465. // Wands
  466. if (m_spellInfo->AttributesEx2 & SPELL_ATTR2_AUTOREPEAT_FLAG)
  467. m_attackType = RANGED_ATTACK;
  468. else
  469. m_attackType = BASE_ATTACK;
  470. break;
  471. }
  472. m_spellSchoolMask = info->GetSchoolMask(); // Can be override for some spell (wand shoot for example)
  473. if (m_attackType == RANGED_ATTACK)
  474. // wand case
  475. if ((m_caster->getClassMask() & CLASSMASK_WAND_USERS) != 0 && m_caster->GetTypeId() == TYPEID_PLAYER)
  476. if (Item* pItem = m_caster->ToPlayer()->GetWeaponForAttack(RANGED_ATTACK))
  477. m_spellSchoolMask = SpellSchoolMask(1 << pItem->GetTemplate()->DamageType);
  478. if (originalCasterGUID)
  479. m_originalCasterGUID = originalCasterGUID;
  480. else
  481. m_originalCasterGUID = m_caster->GetGUID();
  482. if (m_originalCasterGUID == m_caster->GetGUID())
  483. m_originalCaster = m_caster;
  484. else
  485. {
  486. m_originalCaster = ObjectAccessor::GetUnit(*m_caster, m_originalCasterGUID);
  487. if (m_originalCaster && !m_originalCaster->IsInWorld())
  488. m_originalCaster = NULL;
  489. }
  490. m_spellState = SPELL_STATE_NULL;
  491. _triggeredCastFlags = triggerFlags;
  492. if (info->AttributesEx4 & SPELL_ATTR4_TRIGGERED)
  493. _triggeredCastFlags = TriggerCastFlags(TRIGGERED_FULL_MASK & ~TRIGGERED_IGNORE_EQUIPPED_ITEM_REQUIREMENT);
  494. m_CastItem = NULL;
  495. m_castItemGUID.Clear();
  496. m_castItemEntry = 0;
  497. unitTarget = NULL;
  498. itemTarget = NULL;
  499. gameObjTarget = NULL;
  500. destTarget = NULL;
  501. damage = 0;
  502. effectHandleMode = SPELL_EFFECT_HANDLE_LAUNCH;
  503. m_diminishLevel = DIMINISHING_LEVEL_1;
  504. m_diminishGroup = DIMINISHING_NONE;
  505. m_damage = 0;
  506. m_healing = 0;
  507. m_procAttacker = 0;
  508. m_procVictim = 0;
  509. m_procEx = 0;
  510. focusObject = NULL;
  511. m_cast_count = 0;
  512. m_glyphIndex = 0;
  513. m_preCastSpell = 0;
  514. m_triggeredByAuraSpell = NULL;
  515. m_spellAura = NULL;
  516. //Auto Shot & Shoot (wand)
  517. m_autoRepeat = m_spellInfo->IsAutoRepeatRangedSpell();
  518. m_runesState = 0;
  519. m_powerCost = 0; // setup to correct value in Spell::prepare, must not be used before.
  520. m_casttime = 0; // setup to correct value in Spell::prepare, must not be used before.
  521. m_timer = 0; // will set to castime in prepare
  522. m_channeledDuration = 0; // will be setup in Spell::handle_immediate
  523. m_immediateHandled = false;
  524. m_channelTargetEffectMask = 0;
  525. // Determine if spell can be reflected back to the caster
  526. // Patch 1.2 notes: Spell Reflection no longer reflects abilities
  527. m_canReflect = m_spellInfo->DmgClass == SPELL_DAMAGE_CLASS_MAGIC && !(m_spellInfo->Attributes & SPELL_ATTR0_ABILITY)
  528. && !(m_spellInfo->AttributesEx & SPELL_ATTR1_CANT_BE_REFLECTED) && !(m_spellInfo->Attributes & SPELL_ATTR0_UNAFFECTED_BY_INVULNERABILITY)
  529. && !m_spellInfo->IsPassive() && !m_spellInfo->IsPositive();
  530. CleanupTargetList();
  531. memset(m_effectExecuteData, 0, MAX_SPELL_EFFECTS * sizeof(ByteBuffer*));
  532. for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
  533. m_destTargets[i] = SpellDestination(*m_caster);
  534. }
  535. Spell::~Spell()
  536. {
  537. // unload scripts
  538. while (!m_loadedScripts.empty())
  539. {
  540. std::list<SpellScript*>::iterator itr = m_loadedScripts.begin();
  541. (*itr)->_Unload();
  542. delete (*itr);
  543. m_loadedScripts.erase(itr);
  544. }
  545. if (m_referencedFromCurrentSpell && m_selfContainer && *m_selfContainer == this)
  546. {
  547. // Clean the reference to avoid later crash.
  548. // If this error is repeating, we may have to add an ASSERT to better track down how we get into this case.
  549. TC_LOG_ERROR("spells", "SPELL: deleting spell for spell ID %u. However, spell still referenced.", m_spellInfo->Id);
  550. *m_selfContainer = NULL;
  551. }
  552. if (m_caster && m_caster->GetTypeId() == TYPEID_PLAYER)
  553. ASSERT(m_caster->ToPlayer()->m_spellModTakingSpell != this);
  554. delete m_spellValue;
  555. CheckEffectExecuteData();
  556. }
  557. void Spell::InitExplicitTargets(SpellCastTargets const& targets)
  558. {
  559. m_targets = targets;
  560. m_targets.SetOrigUnitTarget(m_targets.GetUnitTarget());
  561. // this function tries to correct spell explicit targets for spell
  562. // client doesn't send explicit targets correctly sometimes - we need to fix such spells serverside
  563. // this also makes sure that we correctly send explicit targets to client (removes redundant data)
  564. uint32 neededTargets = m_spellInfo->GetExplicitTargetMask();
  565. if (WorldObject* target = m_targets.GetObjectTarget())
  566. {
  567. // check if object target is valid with needed target flags
  568. // for unit case allow corpse target mask because player with not released corpse is a unit target
  569. if ((target->ToUnit() && !(neededTargets & (TARGET_FLAG_UNIT_MASK | TARGET_FLAG_CORPSE_MASK)))
  570. || (target->ToGameObject() && !(neededTargets & TARGET_FLAG_GAMEOBJECT_MASK))
  571. || (target->ToCorpse() && !(neededTargets & TARGET_FLAG_CORPSE_MASK)))
  572. m_targets.RemoveObjectTarget();
  573. }
  574. else
  575. {
  576. // try to select correct unit target if not provided by client or by serverside cast
  577. if (neededTargets & (TARGET_FLAG_UNIT_MASK))
  578. {
  579. Unit* unit = NULL;
  580. // try to use player selection as a target
  581. if (Player* playerCaster = m_caster->ToPlayer())
  582. {
  583. // selection has to be found and to be valid target for the spell
  584. if (Unit* selectedUnit = ObjectAccessor::GetUnit(*m_caster, playerCaster->GetTarget()))
  585. if (m_spellInfo->CheckExplicitTarget(m_caster, selectedUnit) == SPELL_CAST_OK)
  586. unit = selectedUnit;
  587. }
  588. // try to use attacked unit as a target
  589. else if ((m_caster->GetTypeId() == TYPEID_UNIT) && neededTargets & (TARGET_FLAG_UNIT_ENEMY | TARGET_FLAG_UNIT))
  590. unit = m_caster->GetVictim();
  591. // didn't find anything - let's use self as target
  592. if (!unit && neededTargets & (TARGET_FLAG_UNIT_RAID | TARGET_FLAG_UNIT_PARTY | TARGET_FLAG_UNIT_ALLY))
  593. unit = m_caster;
  594. m_targets.SetUnitTarget(unit);
  595. }
  596. }
  597. // check if spell needs dst target
  598. if (neededTargets & TARGET_FLAG_DEST_LOCATION)
  599. {
  600. // and target isn't set
  601. if (!m_targets.HasDst())
  602. {
  603. // try to use unit target if provided
  604. if (WorldObject* target = targets.GetObjectTarget())
  605. m_targets.SetDst(*target);
  606. // or use self if not available
  607. else
  608. m_targets.SetDst(*m_caster);
  609. }
  610. }
  611. else
  612. m_targets.RemoveDst();
  613. if (neededTargets & TARGET_FLAG_SOURCE_LOCATION)
  614. {
  615. if (!targets.HasSrc())
  616. m_targets.SetSrc(*m_caster);
  617. }
  618. else
  619. m_targets.RemoveSrc();
  620. }
  621. void Spell::SelectExplicitTargets()
  622. {
  623. // here go all explicit target changes made to explicit targets after spell prepare phase is finished
  624. if (Unit* target = m_targets.GetUnitTarget())
  625. {
  626. // check for explicit target redirection, for Grounding Totem for example
  627. if (m_spellInfo->GetExplicitTargetMask() & TARGET_FLAG_UNIT_ENEMY
  628. || (m_spellInfo->GetExplicitTargetMask() & TARGET_FLAG_UNIT && !m_spellInfo->IsPositive()))
  629. {
  630. Unit* redirect;
  631. switch (m_spellInfo->DmgClass)
  632. {
  633. case SPELL_DAMAGE_CLASS_MAGIC:
  634. redirect = m_caster->GetMagicHitRedirectTarget(target, m_spellInfo);
  635. break;
  636. case SPELL_DAMAGE_CLASS_MELEE:
  637. case SPELL_DAMAGE_CLASS_RANGED:
  638. redirect = m_caster->GetMeleeHitRedirectTarget(target, m_spellInfo);
  639. break;
  640. default:
  641. redirect = NULL;
  642. break;
  643. }
  644. if (redirect && (redirect != target))
  645. m_targets.SetUnitTarget(redirect);
  646. }
  647. }
  648. }
  649. void Spell::SelectSpellTargets()
  650. {
  651. // select targets for cast phase
  652. SelectExplicitTargets();
  653. uint32 processedAreaEffectsMask = 0;
  654. for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i)
  655. {
  656. // not call for empty effect.
  657. // Also some spells use not used effect targets for store targets for dummy effect in triggered spells
  658. if (!m_spellInfo->Effects[i].IsEffect())
  659. continue;
  660. // set expected type of implicit targets to be sent to client
  661. uint32 implicitTargetMask = GetTargetFlagMask(m_spellInfo->Effects[i].TargetA.GetObjectType()) | GetTargetFlagMask(m_spellInfo->Effects[i].TargetB.GetObjectType());
  662. if (implicitTargetMask & TARGET_FLAG_UNIT)
  663. m_targets.SetTargetFlag(TARGET_FLAG_UNIT);
  664. if (implicitTargetMask & (TARGET_FLAG_GAMEOBJECT | TARGET_FLAG_GAMEOBJECT_ITEM))
  665. m_targets.SetTargetFlag(TARGET_FLAG_GAMEOBJECT);
  666. SelectEffectImplicitTargets(SpellEffIndex(i), m_spellInfo->Effects[i].TargetA, processedAreaEffectsMask);
  667. SelectEffectImplicitTargets(SpellEffIndex(i), m_spellInfo->Effects[i].TargetB, processedAreaEffectsMask);
  668. // Select targets of effect based on effect type
  669. // those are used when no valid target could be added for spell effect based on spell target type
  670. // some spell effects use explicit target as a default target added to target map (like SPELL_EFFECT_LEARN_SPELL)
  671. // some spell effects add target to target map only when target type specified (like SPELL_EFFECT_WEAPON)
  672. // some spell effects don't add anything to target map (confirmed with sniffs) (like SPELL_EFFECT_DESTROY_ALL_TOTEMS)
  673. SelectEffectTypeImplicitTargets(i);
  674. if (m_targets.HasDst())
  675. AddDestTarget(*m_targets.GetDst(), i);
  676. if (m_spellInfo->IsChanneled())
  677. {
  678. uint8 mask = (1 << i);
  679. for (std::list<TargetInfo>::iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
  680. {
  681. if (ihit->effectMask & mask)
  682. {
  683. m_channelTargetEffectMask |= mask;
  684. break;
  685. }
  686. }
  687. }
  688. else if (m_auraScaleMask)
  689. {
  690. bool checkLvl = !m_UniqueTargetInfo.empty();
  691. for (std::list<TargetInfo>::iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end();)
  692. {
  693. // remove targets which did not pass min level check
  694. if (m_auraScaleMask && ihit->effectMask == m_auraScaleMask)
  695. {
  696. // Do not check for selfcast
  697. if (!ihit->scaleAura && ihit->targetGUID != m_caster->GetGUID())
  698. {
  699. m_UniqueTargetInfo.erase(ihit++);
  700. continue;
  701. }
  702. }
  703. ++ihit;
  704. }
  705. if (checkLvl && m_UniqueTargetInfo.empty())
  706. {
  707. SendCastResult(SPELL_FAILED_LOWLEVEL);
  708. finish(false);
  709. }
  710. }
  711. }
  712. if (m_targets.HasDst())
  713. {
  714. if (m_targets.HasTraj())
  715. {
  716. float speed = m_targets.GetSpeedXY();
  717. if (speed > 0.0f)
  718. m_delayMoment = uint64(std::floor(m_targets.GetDist2d() / speed * 1000.0f));
  719. }
  720. else if (m_spellInfo->Speed > 0.0f)
  721. {
  722. float dist = m_caster->GetDistance(*m_targets.GetDstPos());
  723. if (!(m_spellInfo->AttributesEx9 & SPELL_ATTR9_SPECIAL_DELAY_CALCULATION))
  724. m_delayMoment = uint64(std::floor(dist / m_spellInfo->Speed * 1000.0f));
  725. else
  726. m_delayMoment = uint64(m_spellInfo->Speed * 1000.0f);
  727. }
  728. }
  729. }
  730. void Spell::SelectEffectImplicitTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType, uint32& processedEffectMask)
  731. {
  732. if (!targetType.GetTarget())
  733. return;
  734. uint32 effectMask = 1 << effIndex;
  735. // set the same target list for all effects
  736. // some spells appear to need this, however this requires more research
  737. switch (targetType.GetSelectionCategory())
  738. {
  739. case TARGET_SELECT_CATEGORY_NEARBY:
  740. case TARGET_SELECT_CATEGORY_CONE:
  741. case TARGET_SELECT_CATEGORY_AREA:
  742. // targets for effect already selected
  743. if (effectMask & processedEffectMask)
  744. return;
  745. // choose which targets we can select at once
  746. for (uint32 j = effIndex + 1; j < MAX_SPELL_EFFECTS; ++j)
  747. {
  748. SpellEffectInfo const* effects = GetSpellInfo()->Effects;
  749. if (effects[j].IsEffect() &&
  750. effects[effIndex].TargetA.GetTarget() == effects[j].TargetA.GetTarget() &&
  751. effects[effIndex].TargetB.GetTarget() == effects[j].TargetB.GetTarget() &&
  752. effects[effIndex].ImplicitTargetConditions == effects[j].ImplicitTargetConditions &&
  753. effects[effIndex].CalcRadius(m_caster) == effects[j].CalcRadius(m_caster) &&
  754. CheckScriptEffectImplicitTargets(effIndex, j))
  755. {
  756. effectMask |= 1 << j;
  757. }
  758. }
  759. processedEffectMask |= effectMask;
  760. break;
  761. default:
  762. break;
  763. }
  764. switch (targetType.GetSelectionCategory())
  765. {
  766. case TARGET_SELECT_CATEGORY_CHANNEL:
  767. SelectImplicitChannelTargets(effIndex, targetType);
  768. break;
  769. case TARGET_SELECT_CATEGORY_NEARBY:
  770. SelectImplicitNearbyTargets(effIndex, targetType, effectMask);
  771. break;
  772. case TARGET_SELECT_CATEGORY_CONE:
  773. SelectImplicitConeTargets(effIndex, targetType, effectMask);
  774. break;
  775. case TARGET_SELECT_CATEGORY_AREA:
  776. SelectImplicitAreaTargets(effIndex, targetType, effectMask);
  777. break;
  778. case TARGET_SELECT_CATEGORY_DEFAULT:
  779. switch (targetType.GetObjectType())
  780. {
  781. case TARGET_OBJECT_TYPE_SRC:
  782. switch (targetType.GetReferenceType())
  783. {
  784. case TARGET_REFERENCE_TYPE_CASTER:
  785. m_targets.SetSrc(*m_caster);
  786. break;
  787. default:
  788. ASSERT(false && "Spell::SelectEffectImplicitTargets: received not implemented select target reference type for TARGET_TYPE_OBJECT_SRC");
  789. break;
  790. }
  791. break;
  792. case TARGET_OBJECT_TYPE_DEST:
  793. switch (targetType.GetReferenceType())
  794. {
  795. case TARGET_REFERENCE_TYPE_CASTER:
  796. SelectImplicitCasterDestTargets(effIndex, targetType);
  797. break;
  798. case TARGET_REFERENCE_TYPE_TARGET:
  799. SelectImplicitTargetDestTargets(effIndex, targetType);
  800. break;
  801. case TARGET_REFERENCE_TYPE_DEST:
  802. SelectImplicitDestDestTargets(effIndex, targetType);
  803. break;
  804. default:
  805. ASSERT(false && "Spell::SelectEffectImplicitTargets: received not implemented select target reference type for TARGET_TYPE_OBJECT_DEST");
  806. break;
  807. }
  808. break;
  809. default:
  810. switch (targetType.GetReferenceType())
  811. {
  812. case TARGET_REFERENCE_TYPE_CASTER:
  813. SelectImplicitCasterObjectTargets(effIndex, targetType);
  814. break;
  815. case TARGET_REFERENCE_TYPE_TARGET:
  816. SelectImplicitTargetObjectTargets(effIndex, targetType);
  817. break;
  818. default:
  819. ASSERT(false && "Spell::SelectEffectImplicitTargets: received not implemented select target reference type for TARGET_TYPE_OBJECT");
  820. break;
  821. }
  822. break;
  823. }
  824. break;
  825. case TARGET_SELECT_CATEGORY_NYI:
  826. TC_LOG_DEBUG("spells", "SPELL: target type %u, found in spellID %u, effect %u is not implemented yet!", m_spellInfo->Id, effIndex, targetType.GetTarget());
  827. break;
  828. default:
  829. ASSERT(false && "Spell::SelectEffectImplicitTargets: received not implemented select target category");
  830. break;
  831. }
  832. }
  833. void Spell::SelectImplicitChannelTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType)
  834. {
  835. if (targetType.GetReferenceType() != TARGET_REFERENCE_TYPE_CASTER)
  836. {
  837. ASSERT(false && "Spell::SelectImplicitChannelTargets: received not implemented target reference type");
  838. return;
  839. }
  840. Spell* channeledSpell = m_originalCaster->GetCurrentSpell(CURRENT_CHANNELED_SPELL);
  841. if (!channeledSpell)
  842. {
  843. TC_LOG_DEBUG("spells", "Spell::SelectImplicitChannelTargets: cannot find channel spell for spell ID %u, effect %u", m_spellInfo->Id, effIndex);
  844. return;
  845. }
  846. switch (targetType.GetTarget())
  847. {
  848. case TARGET_UNIT_CHANNEL_TARGET:
  849. {
  850. WorldObject* target = ObjectAccessor::GetUnit(*m_caster, m_originalCaster->GetChannelObjectGuid());
  851. CallScriptObjectTargetSelectHandlers(target, effIndex, targetType);
  852. // unit target may be no longer avalible - teleported out of map for example
  853. if (target && target->ToUnit())
  854. AddUnitTarget(target->ToUnit(), 1 << effIndex);
  855. else
  856. TC_LOG_DEBUG("spells", "SPELL: cannot find channel spell target for spell ID %u, effect %u", m_spellInfo->Id, effIndex);
  857. break;
  858. }
  859. case TARGET_DEST_CHANNEL_TARGET:
  860. if (channeledSpell->m_targets.HasDst())
  861. m_targets.SetDst(channeledSpell->m_targets);
  862. else if (WorldObject* target = ObjectAccessor::GetWorldObject(*m_caster, m_originalCaster->GetChannelObjectGuid()))
  863. {
  864. CallScriptObjectTargetSelectHandlers(target, effIndex, targetType);
  865. if (target)
  866. m_targets.SetDst(*target);
  867. }
  868. else
  869. TC_LOG_DEBUG("spells", "SPELL: cannot find channel spell destination for spell ID %u, effect %u", m_spellInfo->Id, effIndex);
  870. break;
  871. case TARGET_DEST_CHANNEL_CASTER:
  872. m_targets.SetDst(*channeledSpell->GetCaster());
  873. break;
  874. default:
  875. ASSERT(false && "Spell::SelectImplicitChannelTargets: received not implemented target type");
  876. break;
  877. }
  878. }
  879. void Spell::SelectImplicitNearbyTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType, uint32 effMask)
  880. {
  881. if (targetType.GetReferenceType() != TARGET_REFERENCE_TYPE_CASTER)
  882. {
  883. ASSERT(false && "Spell::SelectImplicitNearbyTargets: received not implemented target reference type");
  884. return;
  885. }
  886. float range = 0.0f;
  887. switch (targetType.GetCheckType())
  888. {
  889. case TARGET_CHECK_ENEMY:
  890. range = m_spellInfo->GetMaxRange(false, m_caster, this);
  891. break;
  892. case TARGET_CHECK_ALLY:
  893. case TARGET_CHECK_PARTY:
  894. case TARGET_CHECK_RAID:
  895. case TARGET_CHECK_RAID_CLASS:
  896. range = m_spellInfo->GetMaxRange(true, m_caster, this);
  897. break;
  898. case TARGET_CHECK_ENTRY:
  899. case TARGET_CHECK_DEFAULT:
  900. range = m_spellInfo->GetMaxRange(m_spellInfo->IsPositive(), m_caster, this);
  901. break;
  902. default:
  903. ASSERT(false && "Spell::SelectImplicitNearbyTargets: received not implemented selection check type");
  904. break;
  905. }
  906. ConditionList* condList = m_spellInfo->Effects[effIndex].ImplicitTargetConditions;
  907. // handle emergency case - try to use other provided targets if no conditions provided
  908. if (targetType.GetCheckType() == TARGET_CHECK_ENTRY && (!condList || condList->empty()))
  909. {
  910. TC_LOG_DEBUG("spells", "Spell::SelectImplicitNearbyTargets: no conditions entry for target with TARGET_CHECK_ENTRY of spell ID %u, effect %u - selecting default targets", m_spellInfo->Id, effIndex);
  911. switch (targetType.GetObjectType())
  912. {
  913. case TARGET_OBJECT_TYPE_GOBJ:
  914. if (m_spellInfo->RequiresSpellFocus)
  915. {
  916. if (focusObject)
  917. AddGOTarget(focusObject, effMask);
  918. return;
  919. }
  920. break;
  921. case TARGET_OBJECT_TYPE_DEST:
  922. if (m_spellInfo->RequiresSpellFocus)
  923. {
  924. if (focusObject)
  925. m_targets.SetDst(*focusObject);
  926. return;
  927. }
  928. break;
  929. default:
  930. break;
  931. }
  932. }
  933. WorldObject* target = SearchNearbyTarget(range, targetType.GetObjectType(), targetType.GetCheckType(), condList);
  934. if (!target)
  935. {
  936. TC_LOG_DEBUG("spells", "Spell::SelectImplicitNearbyTargets: cannot find nearby target for spell ID %u, effect %u", m_spellInfo->Id, effIndex);
  937. return;
  938. }
  939. CallScriptObjectTargetSelectHandlers(target, effIndex, targetType);
  940. if (!target)
  941. {
  942. TC_LOG_DEBUG("spells", "Spell::SelectImplicitNearbyTargets: OnObjectTargetSelect script hook for spell Id %u set NULL target, effect %u", m_spellInfo->Id, effIndex);
  943. return;
  944. }
  945. switch (targetType.GetObjectType())
  946. {
  947. case TARGET_OBJECT_TYPE_UNIT:
  948. {
  949. if (Unit* unitTarget = target->ToUnit())
  950. AddUnitTarget(unitTarget, effMask, true, false);
  951. else
  952. {
  953. TC_LOG_DEBUG("spells", "Spell::SelectImplicitNearbyTargets: OnObjectTargetSelect script hook for spell Id %u set object of wrong type, expected unit, got %s, effect %u", m_spellInfo->Id, target->GetGUID().GetTypeName(), effMask);
  954. return;
  955. }
  956. break;
  957. }
  958. case TARGET_OBJECT_TYPE_GOBJ:
  959. if (GameObject* gobjTarget = target->ToGameObject())
  960. AddGOTarget(gobjTarget, effMask);
  961. else
  962. {
  963. TC_LOG_DEBUG("spells", "Spell::SelectImplicitNearbyTargets: OnObjectTargetSelect script hook for spell Id %u set object of wrong type, expected gameobject, got %s, effect %u", m_spellInfo->Id, target->GetGUID().GetTypeName(), effMask);
  964. return;
  965. }
  966. break;
  967. case TARGET_OBJECT_TYPE_DEST:
  968. m_targets.SetDst(*target);
  969. break;
  970. default:
  971. ASSERT(false && "Spell::SelectImplicitNearbyTargets: received not implemented target object type");
  972. break;
  973. }
  974. SelectImplicitChainTargets(effIndex, targetType, target, effMask);
  975. }
  976. void Spell::SelectImplicitConeTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType, uint32 effMask)
  977. {
  978. if (targetType.GetReferenceType() != TARGET_REFERENCE_TYPE_CASTER)
  979. {
  980. ASSERT(false && "Spell::SelectImplicitConeTargets: received not implemented target reference type");
  981. return;
  982. }
  983. std::list<WorldObject*> targets;
  984. SpellTargetObjectTypes objectType = targetType.GetObjectType();
  985. SpellTargetCheckTypes selectionType = targetType.GetCheckType();
  986. ConditionList* condList = m_spellInfo->Effects[effIndex].ImplicitTargetConditions;
  987. float coneAngle = float(M_PI) / 2;
  988. float radius = m_spellInfo->Effects[effIndex].CalcRadius(m_caster) * m_spellValue->RadiusMod;
  989. if (uint32 containerTypeMask = GetSearcherTypeMask(objectType, condList))
  990. {
  991. Trinity::WorldObjectSpellConeTargetCheck check(coneAngle, radius, m_caster, m_spellInfo, selectionType, condList);
  992. Trinity::WorldObjectListSearcher<Trinity::WorldObjectSpellConeTargetCheck> searcher(m_caster, targets, check, containerTypeMask);
  993. SearchTargets<Trinity::WorldObjectListSearcher<Trinity::WorldObjectSpellConeTargetCheck> >(searcher, containerTypeMask, m_caster, m_caster, radius);
  994. CallScriptObjectAreaTargetSelectHandlers(targets, effIndex, targetType);
  995. if (!targets.empty())
  996. {
  997. // Other special target selection goes here
  998. if (uint32 maxTargets = m_spellValue->MaxAffectedTargets)
  999. Trinity::Containers::RandomResizeList(targets, maxTargets);
  1000. for (std::list<WorldObject*>::iterator itr = targets.begin(); itr != targets.end(); ++itr)
  1001. {
  1002. if (Unit* unitTarget = (*itr)->ToUnit())
  1003. AddUnitTarget(unitTarget, effMask, false);
  1004. else if (GameObject* gObjTarget = (*itr)->ToGameObject())
  1005. AddGOTarget(gObjTarget, effMask);
  1006. }
  1007. }
  1008. }
  1009. }
  1010. void Spell::SelectImplicitAreaTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType, uint32 effMask)
  1011. {
  1012. Unit* referer = NULL;
  1013. switch (targetType.GetReferenceType())
  1014. {
  1015. case TARGET_REFERENCE_TYPE_SRC:
  1016. case TARGET_REFERENCE_TYPE_DEST:
  1017. case TARGET_REFERENCE_TYPE_CASTER:
  1018. referer = m_caster;
  1019. break;
  1020. case TARGET_REFERENCE_TYPE_TARGET:
  1021. referer = m_targets.GetUnitTarget();
  1022. break;
  1023. case TARGET_REFERENCE_TYPE_LAST:
  1024. {
  1025. // find last added target for this effect
  1026. for (std::list<TargetInfo>::reverse_iterator ihit = m_UniqueTargetInfo.rbegin(); ihit != m_UniqueTargetInfo.rend(); ++ihit)
  1027. {
  1028. if (ihit->effectMask & (1<<effIndex))
  1029. {
  1030. referer = ObjectAccessor::GetUnit(*m_caster, ihit->targetGUID);
  1031. break;
  1032. }
  1033. }
  1034. break;
  1035. }
  1036. default:
  1037. ASSERT(false && "Spell::SelectImplicitAreaTargets: received not implemented target reference type");
  1038. return;
  1039. }
  1040. if (!referer)
  1041. return;
  1042. Position const* center = NULL;
  1043. switch (targetType.GetReferenceType())
  1044. {
  1045. case TARGET_REFERENCE_TYPE_SRC:
  1046. center = m_targets.GetSrcPos();
  1047. break;
  1048. case TARGET_REFERENCE_TYPE_DEST:
  1049. center = m_targets.GetDstPos();
  1050. break;
  1051. case TARGET_REFERENCE_TYPE_CASTER:
  1052. case TARGET_REFERENCE_TYPE_TARGET:
  1053. case TARGET_REFERENCE_TYPE_LAST:
  1054. center = referer;
  1055. break;
  1056. default:
  1057. ASSERT(false && "Spell::SelectImplicitAreaTargets: received not implemented target reference type");
  1058. return;
  1059. }
  1060. std::list<WorldObject*> targets;
  1061. float radius = m_spellInfo->Effects[effIndex].CalcRadius(m_caster) * m_spellValue->RadiusMod;
  1062. SearchAreaTargets(targets, radius, center, referer, targetType.GetObjectType(), targetType.GetCheckType(), m_spellInfo->Effects[effIndex].ImplicitTargetConditions);
  1063. CallScriptObjectAreaTargetSelectHandlers(targets, effIndex, targetType);
  1064. if (!targets.empty())
  1065. {
  1066. // Other special target selection goes here
  1067. if (uint32 maxTargets = m_spellValue->MaxAffectedTargets)
  1068. Trinity::Containers::RandomResizeList(targets, maxTargets);
  1069. for (std::list<WorldObject*>::iterator itr = targets.begin(); itr != targets.end(); ++itr)
  1070. {
  1071. if (Unit* unitTarget = (*itr)->ToUnit())
  1072. AddUnitTarget(unitTarget, effMask, false, true, center);
  1073. else if (GameObject* gObjTarget = (*itr)->ToGameObject())
  1074. AddGOTarget(gObjTarget, effMask);
  1075. }
  1076. }
  1077. }
  1078. void Spell::SelectImplicitCasterDestTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType)
  1079. {
  1080. SpellDestination dest(*m_caster);
  1081. switch (targetType.GetTarget())
  1082. {
  1083. case TARGET_DEST_CASTER:
  1084. break;
  1085. case TARGET_DEST_HOME:
  1086. if (Player* playerCaster = m_caster->ToPlayer())
  1087. dest = SpellDestination(playerCaster->m_homebindX, playerCaster->m_homebindY, playerCaster->m_homebindZ, playerCaster->GetOrientation(), playerCaster->m_homebindMapId);
  1088. break;
  1089. case TARGET_DEST_DB:
  1090. if (SpellTargetPosition const* st = sSpellMgr->GetSpellTargetPosition(m_spellInfo->Id, effIndex))
  1091. {
  1092. /// @todo fix this check
  1093. if (m_spellInfo->HasEffect(SPELL_EFFECT_TELEPORT_UNITS) || m_spellInfo->HasEffect(SPELL_EFFECT_BIND))
  1094. dest = SpellDestination(st->target_X, st->target_Y, st->target_Z, st->target_Orientation, (int32)st->target_mapId);
  1095. else if (st->target_mapId == m_caster->GetMapId())
  1096. dest = SpellDestination(st->target_X, st->target_Y, st->target_Z, st->target_Orientation);
  1097. }
  1098. else
  1099. {
  1100. TC_LOG_DEBUG("spells", "SPELL: unknown target coordinates for spell ID %u", m_spellInfo->Id);
  1101. if (WorldObject* target = m_targets.GetObjectTarget())
  1102. dest = SpellDestination(*target);
  1103. }
  1104. break;
  1105. case TARGET_DEST_CASTER_FISHING:
  1106. {
  1107. float minDist = m_spellInfo->GetMinRange(true);
  1108. float maxDist = m_spellInfo->GetMaxRange(true);
  1109. float dist = frand(minDist, maxDist);
  1110. float x, y, z;
  1111. float angle = float(rand_norm()) * static_cast<float>(M_PI * 35.0f / 180.0f) - static_cast<float>(M_PI * 17.5f / 180.0f);
  1112. m_caster->GetClosePoint(x, y, z, DEFAULT_WORLD_OBJECT_SIZE, dist, angle);
  1113. float ground = m_caster->GetMap()->GetHeight(m_caster->GetPhaseMask(), x, y, z, true, 50.0f);
  1114. float liquidLevel = VMAP_INVALID_HEIGHT_VALUE;
  1115. LiquidData liquidData;
  1116. if (m_caster->GetMap()->getLiquidStatus(x, y, z, MAP_ALL_LIQUIDS, &liquidData))
  1117. liquidLevel = liquidData.level;
  1118. if (liquidLevel <= ground) // When there is no liquid Map::GetWaterOrGroundLevel returns ground level
  1119. {
  1120. SendCastResult(SPELL_FAILED_NOT_HERE);
  1121. SendChannelUpdate(0);
  1122. finish(false);
  1123. return;
  1124. }
  1125. if (ground + 0.75 > liquidLevel)
  1126. {
  1127. SendCastResult(SPELL_FAILED_TOO_SHALLOW);
  1128. SendChannelUpdate(0);
  1129. finish(false);
  1130. return;
  1131. }
  1132. dest = SpellDestination(x, y, liquidLevel, m_caster->GetOrientation());
  1133. break;
  1134. }
  1135. default:
  1136. {
  1137. float dist;
  1138. float angle = targetType.CalcDirectionAngle();
  1139. float objSize = m_caster->GetObjectSize();
  1140. if (targetType.GetTarget() == TARGET_DEST_CASTER_SUMMON)
  1141. dist = PET_FOLLOW_DIST;
  1142. else
  1143. dist = m_spellInfo->Effects[effIndex].CalcRadius(m_caster);
  1144. if (dist < objSize)
  1145. dist = objSize;
  1146. else if (targetType.GetTarget() == TARGET_DEST_CASTER_RANDOM)
  1147. dist = objSize + (dist - objSize) * float(rand_norm());
  1148. Position pos = dest._position;
  1149. m_caster->MovePositionToFirstCollision(pos, dist, angle);
  1150. dest.Relocate(pos);
  1151. break;
  1152. }
  1153. }
  1154. CallScriptDestinationTargetSelectHandlers(dest, effIndex, targetType);
  1155. m_targets.SetDst(dest);
  1156. }
  1157. void Spell::SelectImplicitTargetDestTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType)
  1158. {
  1159. ASSERT(m_targets.GetObjectTarget() && "Spell::SelectImplicitTargetDestTargets - no explicit object target available!");
  1160. WorldObject* target = m_targets.GetObjectTarget();
  1161. SpellDestination dest(*target);
  1162. switch (targetType.GetTarget())
  1163. {
  1164. case TARGET_DEST_TARGET_ENEMY:
  1165. case TARGET_DEST_TARGET_ANY:
  1166. break;
  1167. default:
  1168. {
  1169. float angle = targetType.CalcDirectionAngle();
  1170. float objSize = target->GetObjectSize();
  1171. float dist = m_spellInfo->Effects[effIndex].CalcRadius(m_caster);
  1172. if (dist < objSize)
  1173. dist = objSize;
  1174. else if (targetType.GetTarget() == TARGET_DEST_TARGET_RANDOM)
  1175. dist = objSize + (dist - objSize) * float(rand_norm());
  1176. Position pos = dest._position;
  1177. target->MovePositionToFirstCollision(pos, dist, angle);
  1178. dest.Relocate(pos);
  1179. break;
  1180. }
  1181. }
  1182. CallScriptDestinationTargetSelectHandlers(dest, effIndex, targetType);
  1183. m_targets.SetDst(dest);
  1184. }
  1185. void Spell::SelectImplicitDestDestTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType)
  1186. {
  1187. // set destination to caster if no dest provided
  1188. // can only happen if previous destination target could not be set for some reason
  1189. // (not found nearby target, or channel target for example
  1190. // maybe we should abort the spell in such case?
  1191. CheckDst();
  1192. SpellDestination dest(*m_targets.GetDst());
  1193. switch (targetType.GetTarget())
  1194. {
  1195. case TARGET_DEST_DYNOBJ_ENEMY:
  1196. case TARGET_DEST_DYNOBJ_ALLY:
  1197. case TARGET_DEST_DYNOBJ_NONE:
  1198. case TARGET_DEST_DEST:
  1199. return;
  1200. case TARGET_DEST_TRAJ:
  1201. SelectImplicitTrajTargets(effIndex);
  1202. return;
  1203. default:
  1204. {
  1205. float angle = targetType.CalcDirectionAngle();
  1206. float dist = m_spellInfo->Effects[effIndex].CalcRadius(m_caster);
  1207. if (targetType.GetTarget() == TARGET_DEST_DEST_RANDOM)
  1208. dist *= float(rand_norm());
  1209. Position pos = dest._position;
  1210. m_ca

Large files files are truncated, but you can click here to view the full file