/*
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see .
*/
#ifndef __SPELL_H
#define __SPELL_H
#include "ConditionMgr.h"
#include "DBCEnums.h"
#include "ObjectGuid.h"
#include "Optional.h"
#include "Position.h"
#include "SharedDefines.h"
#include "SpellDefines.h"
#include
namespace WorldPackets
{
namespace Spells
{
struct SpellAmmo;
struct SpellCastData;
}
}
class Aura;
class AuraEffect;
class BasicEvent;
class Corpse;
class DamageInfo;
class DynamicObject;
class DynObjAura;
class GameObject;
class Item;
class Object;
class PathGenerator;
class Player;
class SpellEffectInfo;
class SpellEvent;
class SpellImplicitTargetInfo;
class SpellInfo;
class SpellScript;
class Unit;
class UnitAura;
class WorldObject;
struct SpellPowerCost;
struct SummonPropertiesEntry;
enum AuraType : uint32;
enum CurrentSpellTypes : uint8;
enum LootType : uint8;
enum ProcFlagsHit : uint32;
enum SpellTargetCheckTypes : uint8;
enum SpellTargetObjectTypes : uint8;
enum SpellValueMod : uint8;
enum TriggerCastFlags : uint32;
enum WeaponAttackType : uint8;
#define SPELL_CHANNEL_UPDATE_INTERVAL (1 * IN_MILLISECONDS)
#define MAX_SPELL_RANGE_TOLERANCE 3.0f
#define TRAJECTORY_MISSILE_SIZE 3.0f
enum SpellCastFlags
{
CAST_FLAG_NONE = 0x00000000,
CAST_FLAG_PENDING = 0x00000001, // aoe combat log?
CAST_FLAG_HAS_TRAJECTORY = 0x00000002,
CAST_FLAG_UNKNOWN_3 = 0x00000004,
CAST_FLAG_UNKNOWN_4 = 0x00000008, // ignore AOE visual
CAST_FLAG_UNKNOWN_5 = 0x00000010,
CAST_FLAG_PROJECTILE = 0x00000020,
CAST_FLAG_UNKNOWN_7 = 0x00000040,
CAST_FLAG_UNKNOWN_8 = 0x00000080,
CAST_FLAG_UNKNOWN_9 = 0x00000100,
CAST_FLAG_UNKNOWN_10 = 0x00000200,
CAST_FLAG_UNKNOWN_11 = 0x00000400,
CAST_FLAG_POWER_LEFT_SELF = 0x00000800,
CAST_FLAG_UNKNOWN_13 = 0x00001000,
CAST_FLAG_UNKNOWN_14 = 0x00002000,
CAST_FLAG_UNKNOWN_15 = 0x00004000,
CAST_FLAG_UNKNOWN_16 = 0x00008000,
CAST_FLAG_UNKNOWN_17 = 0x00010000,
CAST_FLAG_ADJUST_MISSILE = 0x00020000,
CAST_FLAG_NO_GCD = 0x00040000, // no GCD for spell casts from charm/summon (vehicle spells is an example)
CAST_FLAG_VISUAL_CHAIN = 0x00080000,
CAST_FLAG_UNKNOWN_21 = 0x00100000,
CAST_FLAG_RUNE_LIST = 0x00200000,
CAST_FLAG_UNKNOWN_23 = 0x00400000,
CAST_FLAG_UNKNOWN_24 = 0x00800000,
CAST_FLAG_UNKNOWN_25 = 0x01000000,
CAST_FLAG_UNKNOWN_26 = 0x02000000,
CAST_FLAG_IMMUNITY = 0x04000000,
CAST_FLAG_UNKNOWN_28 = 0x08000000,
CAST_FLAG_UNKNOWN_29 = 0x10000000,
CAST_FLAG_UNKNOWN_30 = 0x20000000,
CAST_FLAG_HEAL_PREDICTION = 0x40000000,
CAST_FLAG_UNKNOWN_32 = 0x80000000
};
enum SpellCastFlagsEx
{
CAST_FLAG_EX_NONE = 0x00000,
CAST_FLAG_EX_UNKNOWN_1 = 0x00001,
CAST_FLAG_EX_UNKNOWN_2 = 0x00002,
CAST_FLAG_EX_UNKNOWN_3 = 0x00004,
CAST_FLAG_EX_UNKNOWN_4 = 0x00008,
CAST_FLAG_EX_UNKNOWN_5 = 0x00010,
CAST_FLAG_EX_UNKNOWN_6 = 0x00020,
CAST_FLAG_EX_UNKNOWN_7 = 0x00040,
CAST_FLAG_EX_UNKNOWN_8 = 0x00080,
CAST_FLAG_EX_UNKNOWN_9 = 0x00100,
CAST_FLAG_EX_IGNORE_COOLDOWN = 0x00200, // makes client not automatically start cooldown after SPELL_GO
CAST_FLAG_EX_UNKNOWN_11 = 0x00400,
CAST_FLAG_EX_UNKNOWN_12 = 0x00800,
CAST_FLAG_EX_UNKNOWN_13 = 0x01000,
CAST_FLAG_EX_UNKNOWN_14 = 0x02000,
CAST_FLAG_EX_UNKNOWN_15 = 0x04000,
CAST_FLAG_EX_USE_TOY_SPELL = 0x08000, // Starts cooldown on toy
CAST_FLAG_EX_UNKNOWN_17 = 0x10000,
CAST_FLAG_EX_UNKNOWN_18 = 0x20000,
CAST_FLAG_EX_UNKNOWN_19 = 0x40000,
CAST_FLAG_EX_UNKNOWN_20 = 0x80000
};
enum SpellCastSource : uint8
{
SPELL_CAST_SOURCE_PLAYER = 2,
SPELL_CAST_SOURCE_NORMAL = 3,
SPELL_CAST_SOURCE_ITEM = 4,
SPELL_CAST_SOURCE_PASSIVE = 7,
SPELL_CAST_SOURCE_PET = 9,
SPELL_CAST_SOURCE_AURA = 13,
SPELL_CAST_SOURCE_SPELL = 16,
};
enum SpellRangeFlag
{
SPELL_RANGE_DEFAULT = 0,
SPELL_RANGE_MELEE = 1, //melee
SPELL_RANGE_RANGED = 2 //hunter range and ranged weapon
};
enum SpellFinishReason : uint8
{
SPELL_FINISHED_SUCCESSFUL_CAST = 0, // spell has sucessfully launched
SPELL_FINISHED_CANCELED = 1, // spell has been canceled (interrupts)
SPELL_FINISHED_CHANNELING_COMPLETE = 2 // spell channeling has been finished
};
struct SpellLogEffectPowerDrainParams
{
ObjectGuid Victim;
uint32 Points = 0;
uint32 PowerType = 0;
float Amplitude = 0;
};
struct SpellLogEffectExtraAttacksParams
{
ObjectGuid Victim;
uint32 NumAttacks = 0;
};
struct SpellLogEffectDurabilityDamageParams
{
ObjectGuid Victim;
int32 ItemID = 0;
int32 Amount = 0;
};
struct SpellLogEffectGenericVictimParams
{
ObjectGuid Victim;
};
struct SpellLogEffectTradeSkillItemParams
{
int32 ItemID = 0;
};
struct SpellLogEffectFeedPetParams
{
int32 ItemID = 0;
};
struct SpellLogEffect
{
int32 Effect = 0;
Optional> PowerDrainTargets;
Optional> ExtraAttacksTargets;
Optional> DurabilityDamageTargets;
Optional> GenericVictimTargets;
Optional> TradeSkillTargets;
Optional> FeedPetTargets;
};
struct SpellValue
{
explicit SpellValue(SpellInfo const* proto, WorldObject const* caster);
int32 EffectBasePoints[MAX_SPELL_EFFECTS];
uint32 CustomBasePointsMask;
uint32 MaxAffectedTargets;
float RadiusMod;
int32 AuraStackAmount;
float DurationMul;
float CriticalChance;
Optional Duration;
};
enum SpellState
{
SPELL_STATE_NULL = 0,
SPELL_STATE_PREPARING = 1,
SPELL_STATE_CASTING = 2,
SPELL_STATE_FINISHED = 3,
SPELL_STATE_IDLE = 4,
SPELL_STATE_DELAYED = 5
};
enum SpellEffectHandleMode
{
SPELL_EFFECT_HANDLE_LAUNCH,
SPELL_EFFECT_HANDLE_LAUNCH_TARGET,
SPELL_EFFECT_HANDLE_HIT,
SPELL_EFFECT_HANDLE_HIT_TARGET
};
typedef std::vector> DispelList;
static const uint32 SPELL_INTERRUPT_NONPLAYER = 32747;
class TC_GAME_API Spell
{
friend void SetUnitCurrentCastSpell(Unit* unit, Spell* spell);
friend class SpellScript;
public:
void EffectNULL();
void EffectUnused();
void EffectDistract();
void EffectSchoolDMG();
void EffectEnvironmentalDMG();
void EffectInstaKill();
void EffectDummy();
void EffectTeleportUnits();
void EffectTeleportUnitsWithVisualLoadingScreen();
void EffectApplyAura();
void EffectSendEvent();
void EffectPowerBurn();
void EffectPowerDrain();
void EffectHeal();
void EffectBind();
void EffectTeleportToReturnPoint();
void EffectHealthLeech();
void EffectQuestComplete();
void EffectCreateItem();
void EffectCreateItem2();
void EffectCreateRandomItem();
void EffectPersistentAA();
void EffectEnergize();
void EffectOpenLock();
void EffectSummonChangeItem();
void EffectProficiency();
void EffectSummonType();
void EffectLearnSpell();
void EffectDispel();
void EffectDualWield();
void EffectPickPocket();
void EffectAddFarsight();
void EffectUntrainTalents();
void EffectHealMechanical();
void EffectJump();
void EffectJumpDest();
void EffectLeapBack();
void EffectQuestClear();
void EffectTeleUnitsFaceCaster();
void EffectLearnSkill();
void EffectPlayMovie();
void EffectTradeSkill();
void EffectEnchantItemPerm();
void EffectEnchantItemTmp();
void EffectTameCreature();
void EffectSummonPet();
void EffectLearnPetSpell();
void EffectWeaponDmg();
void EffectForceCast();
void EffectTriggerSpell();
void EffectTriggerMissileSpell();
void EffectThreat();
void EffectHealMaxHealth();
void EffectInterruptCast();
void EffectSummonObjectWild();
void EffectScriptEffect();
void EffectSanctuary();
void EffectDuel();
void EffectStuck();
void EffectSummonPlayer();
void EffectActivateObject();
void EffectApplyGlyph();
void EffectEnchantHeldItem();
void EffectSummonObject();
void EffectChangeRaidMarker();
void EffectResurrect();
void EffectParry();
void EffectBlock();
void EffectLeap();
void EffectTransmitted();
void EffectDisEnchant();
void EffectInebriate();
void EffectFeedPet();
void EffectDismissPet();
void EffectReputation();
void EffectForceDeselect();
void EffectSelfResurrect();
void EffectSkinning();
void EffectCharge();
void EffectChargeDest();
void EffectProspecting();
void EffectMilling();
void EffectRenamePet();
void EffectSendTaxi();
void EffectKnockBack();
void EffectPullTowards();
void EffectPullTowardsDest();
void EffectDispelMechanic();
void EffectResurrectPet();
void EffectDestroyAllTotems();
void EffectDurabilityDamage();
void EffectSkill();
void EffectTaunt();
void EffectDurabilityDamagePCT();
void EffectModifyThreatPercent();
void EffectResurrectNew();
void EffectAddExtraAttacks();
void EffectSpiritHeal();
void EffectSkinPlayerCorpse();
void EffectStealBeneficialBuff();
void EffectUnlearnSpecialization();
void EffectHealPct();
void EffectEnergizePct();
void EffectTriggerRitualOfSummoning();
void EffectSummonRaFFriend();
void EffectUnlockGuildVaultTab();
void EffectKillCreditPersonal();
void EffectKillCredit();
void EffectQuestFail();
void EffectQuestStart();
void EffectRedirectThreat();
void EffectGameObjectDamage();
void EffectGameObjectRepair();
void EffectGameObjectSetDestructionState();
void EffectCreateTamedPet();
void EffectDiscoverTaxi();
void EffectTitanGrip();
void EffectEnchantItemPrismatic();
void EffectPlayMusic();
void EffectActivateSpec();
void EffectPlaySound();
void EffectRemoveAura();
void EffectDamageFromMaxHealthPCT();
void EffectCastButtons();
void EffectRechargeItem();
void EffectGiveCurrency();
void EffectSummonPersonalGameObject();
void EffectResurrectWithAura();
void EffectCreateAreaTrigger();
void EffectRemoveTalent();
void EffectDestroyItem();
void EffectLearnGarrisonBuilding();
void EffectCreateGarrison();
void EffectCreateConversation();
void EffectCancelConversation();
void EffectAddGarrisonFollower();
void EffectActivateGarrisonBuilding();
void EffectGrantBattlePetLevel();
void EffectHealBattlePetPct();
void EffectEnableBattlePets();
void EffectChangeBattlePetQuality();
void EffectLaunchQuestChoice();
void EffectUncageBattlePet();
void EffectCreateHeirloomItem();
void EffectUpgradeHeirloom();
void EffectApplyEnchantIllusion();
void EffectUpdatePlayerPhase();
void EffectUpdateZoneAurasAndPhases();
void EffectGiveArtifactPower();
void EffectGiveArtifactPowerNoBonus();
void EffectPlaySceneScriptPackage();
void EffectCreateSceneObject();
void EffectCreatePrivateSceneObject();
void EffectPlayScene();
void EffectGiveHonor();
void EffectJumpCharge();
void EffectLearnTransmogSet();
void EffectRespecAzeriteEmpoweredItem();
void EffectLearnAzeriteEssencePower();
void EffectCreatePrivateConversation();
void EffectSendChatMessage();
void EffectGrantBattlePetExperience();
typedef std::unordered_set UsedSpellMods;
Spell(WorldObject* caster, SpellInfo const* info, TriggerCastFlags triggerFlags, ObjectGuid originalCasterGUID = ObjectGuid::Empty, ObjectGuid originalCastId = ObjectGuid::Empty);
~Spell();
void InitExplicitTargets(SpellCastTargets const& targets);
void SelectExplicitTargets();
void SelectSpellTargets();
void SelectEffectImplicitTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType, uint32& processedEffectMask);
void SelectImplicitChannelTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType);
void SelectImplicitNearbyTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType, uint32 effMask);
void SelectImplicitConeTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType, uint32 effMask);
void SelectImplicitAreaTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType, uint32 effMask);
void SelectImplicitCasterDestTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType);
void SelectImplicitTargetDestTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType);
void SelectImplicitDestDestTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType);
void SelectImplicitCasterObjectTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType);
void SelectImplicitTargetObjectTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType);
void SelectImplicitChainTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType, WorldObject* target, uint32 effMask);
void SelectImplicitTrajTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType);
void SelectImplicitLineTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType, uint32 effMask);
void SelectEffectTypeImplicitTargets(SpellEffectInfo const& spellEffectInfo);
uint32 GetSearcherTypeMask(SpellTargetObjectTypes objType, ConditionContainer* condList);
template void SearchTargets(SEARCHER& searcher, uint32 containerMask, WorldObject* referer, Position const* pos, float radius);
WorldObject* SearchNearbyTarget(float range, SpellTargetObjectTypes objectType, SpellTargetCheckTypes selectionType, ConditionContainer* condList = nullptr);
void SearchAreaTargets(std::list& targets, float range, Position const* position, WorldObject* referer, SpellTargetObjectTypes objectType, SpellTargetCheckTypes selectionType, ConditionContainer* condList);
void SearchChainTargets(std::list& targets, uint32 chainTargets, WorldObject* target, SpellTargetObjectTypes objectType, SpellTargetCheckTypes selectType, ConditionContainer* condList, bool isChainHeal);
GameObject* SearchSpellFocus();
SpellCastResult prepare(SpellCastTargets const& targets, AuraEffect const* triggeredByAura = nullptr);
void cancel();
void update(uint32 difftime);
void cast(bool skipCheck = false);
void finish(bool ok = true);
void TakePower();
void TakeRunePower(bool didHit);
void TakeReagents();
void TakeCastItem();
SpellCastResult CheckCast(bool strict, int32* param1 = nullptr, int32* param2 = nullptr);
SpellCastResult CheckPetCast(Unit* target);
// handlers
void handle_immediate();
uint64 handle_delayed(uint64 t_offset);
// handler helpers
void _handle_immediate_phase();
void _handle_finish_phase();
SpellCastResult CheckItems(int32* param1, int32* param2) const;
SpellCastResult CheckRange(bool strict) const;
SpellCastResult CheckPower() const;
SpellCastResult CheckRuneCost() const;
SpellCastResult CheckCasterAuras(int32* param1) const;
SpellCastResult CheckArenaAndRatedBattlegroundCastRules();
bool CheckSpellCancelsAuraEffect(AuraType auraType, int32* param1) const;
bool CheckSpellCancelsCharm(int32* param1) const;
bool CheckSpellCancelsStun(int32* param1) const;
bool CheckSpellCancelsSilence(int32* param1) const;
bool CheckSpellCancelsPacify(int32* param1) const;
bool CheckSpellCancelsFear(int32* param1) const;
bool CheckSpellCancelsConfuse(int32* param1) const;
bool CheckSpellCancelsNoActions(int32* param1) const;
int32 CalculateDamage(SpellEffectInfo const& spellEffectInfo, Unit const* target, float* var = nullptr) const;
void Delayed();
void DelayedChannel();
uint32 getState() const { return m_spellState; }
void setState(uint32 state) { m_spellState = state; }
void DoCreateItem(uint32 itemId, ItemContext context = ItemContext::NONE, std::vector const& bonusListIDs = std::vector());
bool CheckEffectTarget(Unit const* target, SpellEffectInfo const& spellEffectInfo, Position const* losPosition) const;
bool CheckEffectTarget(GameObject const* target, SpellEffectInfo const& spellEffectInfo) const;
bool CheckEffectTarget(Item const* target, SpellEffectInfo const& spellEffectInfo) const;
bool CanAutoCast(Unit* target);
void CheckSrc();
void CheckDst();
static void SendCastResult(Player* caster, SpellInfo const* spellInfo, SpellCastVisual spellVisual, ObjectGuid cast_count, SpellCastResult result, SpellCustomErrors customError = SPELL_CUSTOM_ERROR_NONE, int32* param1 = nullptr, int32* param2 = nullptr);
void SendCastResult(SpellCastResult result, int32* param1 = nullptr, int32* param2 = nullptr) const;
void SendPetCastResult(SpellCastResult result, int32* param1 = nullptr, int32* param2 = nullptr) const;
void SendMountResult(MountResult result);
void SendSpellStart();
void SendSpellGo();
void SendSpellCooldown();
void SendSpellExecuteLog();
SpellLogEffect& GetExecuteLogEffect(SpellEffectName effect);
template
std::vector& GetExecuteLogEffectTargets(SpellEffectName effect, Optional> SpellLogEffect::* member)
{
Optional>& opt = GetExecuteLogEffect(effect).*member;
if (!opt)
opt.emplace();
return *opt;
}
void ExecuteLogEffectTakeTargetPower(SpellEffectName effect, Unit* target, uint32 powerType, uint32 points, float amplitude);
void ExecuteLogEffectExtraAttacks(SpellEffectName effect, Unit* victim, uint32 numAttacks);
void ExecuteLogEffectDurabilityDamage(SpellEffectName effect, Unit* victim, int32 itemId, int32 amount);
void ExecuteLogEffectOpenLock(SpellEffectName effect, Object* obj);
void ExecuteLogEffectCreateItem(SpellEffectName effect, uint32 entry);
void ExecuteLogEffectDestroyItem(SpellEffectName effect, uint32 entry);
void ExecuteLogEffectSummonObject(SpellEffectName effect, WorldObject* obj);
void ExecuteLogEffectUnsummonObject(SpellEffectName effect, WorldObject* obj);
void ExecuteLogEffectResurrect(SpellEffectName effect, Unit* target);
void SendSpellInterruptLog(Unit* victim, uint32 spellId);
void SendInterrupted(uint8 result);
void SendChannelUpdate(uint32 time);
void SendChannelStart(uint32 duration);
void SendResurrectRequest(Player* target);
void HandleEffects(Unit* pUnitTarget, Item* pItemTarget, GameObject* pGoTarget, Corpse* pCorpseTarget, SpellEffectInfo const& spellEffectInfo, SpellEffectHandleMode mode);
void HandleThreatSpells();
static Spell const* ExtractSpellFromEvent(BasicEvent* event);
SpellInfo const* const m_spellInfo;
Item* m_CastItem;
ObjectGuid m_castItemGUID;
uint32 m_castItemEntry;
int32 m_castItemLevel;
ObjectGuid m_castId;
ObjectGuid m_originalCastId;
bool m_fromClient;
uint32 m_castFlagsEx;
union
{
// Alternate names for this value
uint32 TalentId;
// SPELL_EFFECT_APPLY_GLYPH
uint32 SpellId;
// SPELL_EFFECT_TALENT_SPEC_SELECT
uint32 SpecializationId;
// SPELL_EFFECT_SET_FOLLOWER_QUALITY
// SPELL_EFFECT_INCREASE_FOLLOWER_ITEM_LEVEL
// SPELL_EFFECT_INCREASE_FOLLOWER_EXPERIENCE
// SPELL_EFFECT_RANDOMIZE_FOLLOWER_ABILITIES
// SPELL_EFFECT_LEARN_FOLLOWER_ABILITY
struct
{
uint32 Id;
uint32 AbilityId; // only SPELL_EFFECT_LEARN_FOLLOWER_ABILITY
} GarrFollower;
// SPELL_EFFECT_FINISH_GARRISON_MISSION
uint32 GarrMissionId;
// SPELL_EFFECT_UPGRADE_HEIRLOOM
uint32 ItemId;
struct
{
uint32 Data[2];
} Raw;
} m_misc;
SpellCastVisual m_SpellVisual;
SpellCastTargets m_targets;
int8 m_comboPointGain;
SpellCustomErrors m_customError;
UsedSpellMods m_appliedMods;
int32 GetCastTime() const { return m_casttime; }
bool IsAutoRepeat() const { return m_autoRepeat; }
void SetAutoRepeat(bool rep) { m_autoRepeat = rep; }
void ReSetTimer() { m_timer = m_casttime > 0 ? m_casttime : 0; }
bool IsTriggered() const;
bool IsIgnoringCooldowns() const;
bool IsFocusDisabled() const;
bool IsProcDisabled() const;
bool IsChannelActive() const;
bool IsAutoActionResetSpell() const;
bool IsPositive() const;
bool IsTriggeredByAura(SpellInfo const* auraSpellInfo) const { return (auraSpellInfo == m_triggeredByAuraSpell); }
bool IsDeletable() const { return !m_referencedFromCurrentSpell && !m_executedCurrently; }
void SetReferencedFromCurrent(bool yes) { m_referencedFromCurrentSpell = yes; }
bool IsInterruptable() const { return !m_executedCurrently; }
void SetExecutedCurrently(bool yes) {m_executedCurrently = yes;}
uint64 GetDelayStart() const { return m_delayStart; }
void SetDelayStart(uint64 m_time) { m_delayStart = m_time; }
uint64 GetDelayMoment() const { return m_delayMoment; }
uint64 CalculateDelayMomentForDst(float launchDelay) const;
void RecalculateDelayMomentForDst();
uint8 GetRuneState() const { return m_runesState; }
void SetRuneState(uint8 value) { m_runesState = value; }
bool IsNeedSendToClient() const;
CurrentSpellTypes GetCurrentContainer() const;
WorldObject* GetCaster() const { return m_caster; }
ObjectGuid GetOriginalCasterGUID() const { return m_originalCasterGUID; }
Unit* GetOriginalCaster() const { return m_originalCaster; }
SpellInfo const* GetSpellInfo() const { return m_spellInfo; }
Difficulty GetCastDifficulty() const;
std::vector const& GetPowerCost() const { return m_powerCost; }
bool HasPowerTypeCost(Powers power) const;
Optional GetPowerTypeCostAmount(Powers power) const;
bool UpdatePointers(); // must be used at call Spell code after time delay (non triggered spell cast/update spell call/etc)
void CleanupTargetList();
void SetSpellValue(SpellValueMod mod, int32 value);
Spell** m_selfContainer; // pointer to our spell container (if applicable)
SpellInfo const* GetTriggeredByAuraSpell() const { return m_triggeredByAuraSpell; }
int32 GetTimer() const { return m_timer; }
int64 GetUnitTargetCountForEffect(SpellEffIndex effect) const;
int64 GetGameObjectTargetCountForEffect(SpellEffIndex effect) const;
int64 GetItemTargetCountForEffect(SpellEffIndex effect) const;
int64 GetCorpseTargetCountForEffect(SpellEffIndex effect) const;
std::string GetDebugInfo() const;
void CallScriptOnResistAbsorbCalculateHandlers(DamageInfo const& damageInfo, uint32& resistAmount, int32& absorbAmount);
protected:
bool HasGlobalCooldown() const;
void TriggerGlobalCooldown();
void CancelGlobalCooldown();
void _cast(bool skipCheck = false);
void SendLoot(ObjectGuid guid, LootType loottype);
std::pair GetMinMaxRange(bool strict) const;
WorldObject* const m_caster;
SpellValue* const m_spellValue;
ObjectGuid m_originalCasterGUID; // real source of cast (aura caster/etc), used for spell targets selection
// e.g. damage around area spell trigered by victim aura and damage enemies of aura caster
Unit* m_originalCaster; // cached pointer for m_originalCaster, updated at Spell::UpdatePointers()
// Spell data
SpellSchoolMask m_spellSchoolMask; // Spell school (can be overwrite for some spells (wand shoot for example)
WeaponAttackType m_attackType; // For weapon based attack
std::vector m_powerCost; // Calculated spell cost initialized only in Spell::prepare
int32 m_casttime; // Calculated spell cast time initialized only in Spell::prepare
int32 m_channeledDuration; // Calculated channeled spell duration in order to calculate correct pushback.
bool m_canReflect; // can reflect this spell?
bool m_autoRepeat;
uint8 m_runesState;
uint8 m_delayAtDamageCount;
bool IsDelayableNoMore()
{
if (m_delayAtDamageCount >= 2)
return true;
++m_delayAtDamageCount;
return false;
}
// Delayed spells system
uint64 m_delayStart; // time of spell delay start, filled by event handler, zero = just started
uint64 m_delayMoment; // moment of next delay call, used internally
bool m_launchHandled; // were launch actions handled
bool m_immediateHandled; // were immediate actions handled? (used by delayed spells only)
// These vars are used in both delayed spell system and modified immediate spell system
bool m_referencedFromCurrentSpell; // mark as references to prevent deleted and access by dead pointers
bool m_executedCurrently; // mark as executed to prevent deleted and access by dead pointers
bool m_needComboPoints;
uint32 m_applyMultiplierMask;
float m_damageMultipliers[MAX_SPELL_EFFECTS];
// Current targets, to be used in SpellEffects (MUST BE USED ONLY IN SPELL EFFECTS)
Unit* unitTarget;
Item* itemTarget;
GameObject* gameObjTarget;
Corpse* m_corpseTarget;
WorldLocation* destTarget;
int32 damage;
SpellMissInfo targetMissInfo;
float variance;
SpellEffectHandleMode effectHandleMode;
SpellEffectInfo const* effectInfo;
// used in effects handlers
Unit* GetUnitCasterForEffectHandlers() const;
UnitAura* _spellAura;
DynObjAura* _dynObjAura;
// -------------------------------------------
GameObject* focusObject;
// Damage and healing in effects need just calculate
int32 m_damage; // Damage in effects count here
int32 m_healing; // Healing in effects count here
// ******************************************
// Spell trigger system
// ******************************************
ProcFlagsInit m_procAttacker; // Attacker trigger flags
ProcFlagsInit m_procVictim; // Victim trigger flags
ProcFlagsHit m_hitMask;
void prepareDataForTriggerSystem();
// *****************************************
// Spell target subsystem
// *****************************************
// Targets store structures and data
struct TargetInfoBase
{
virtual void PreprocessTarget(Spell* /*spell*/) { }
virtual void DoTargetSpellHit(Spell* spell, SpellEffectInfo const& spellEffectInfo) = 0;
virtual void DoDamageAndTriggers(Spell* /*spell*/) { }
uint32 EffectMask = 0;
protected:
TargetInfoBase() { }
virtual ~TargetInfoBase() { }
};
struct TargetInfo : public TargetInfoBase
{
void PreprocessTarget(Spell* spell) override;
void DoTargetSpellHit(Spell* spell, SpellEffectInfo const& spellEffectInfo) override;
void DoDamageAndTriggers(Spell* spell) override;
ObjectGuid TargetGUID;
uint64 TimeDelay = 0ULL;
int32 Damage = 0;
int32 Healing = 0;
SpellMissInfo MissCondition = SPELL_MISS_NONE;
SpellMissInfo ReflectResult = SPELL_MISS_NONE;
bool IsAlive = false;
bool IsCrit = false;
// info set at PreprocessTarget, used by DoTargetSpellHit
DiminishingGroup DRGroup = DIMINISHING_NONE;
int32 AuraDuration = 0;
int32 AuraBasePoints[MAX_SPELL_EFFECTS] = { };
bool Positive = true;
UnitAura* HitAura = nullptr;
private:
Unit* _spellHitTarget = nullptr; // changed for example by reflect
bool _enablePVP = false; // need to enable PVP at DoDamageAndTriggers?
};
std::vector m_UniqueTargetInfo;
uint32 m_channelTargetEffectMask; // Mask req. alive targets
struct GOTargetInfo : public TargetInfoBase
{
void DoTargetSpellHit(Spell* spell, SpellEffectInfo const& spellEffectInfo) override;
ObjectGuid TargetGUID;
uint64 TimeDelay = 0ULL;
};
std::vector m_UniqueGOTargetInfo;
struct ItemTargetInfo : public TargetInfoBase
{
void DoTargetSpellHit(Spell* spell, SpellEffectInfo const& spellEffectInfo) override;
Item* TargetItem = nullptr;
};
std::vector m_UniqueItemInfo;
struct CorpseTargetInfo : public TargetInfoBase
{
void DoTargetSpellHit(Spell* spell, SpellEffectInfo const& spellEffectInfo) override;
ObjectGuid TargetGUID;
uint64 TimeDelay = 0ULL;
};
std::vector m_UniqueCorpseTargetInfo;
template
void DoProcessTargetContainer(Container& targetContainer);
SpellDestination m_destTargets[MAX_SPELL_EFFECTS];
void AddUnitTarget(Unit* target, uint32 effectMask, bool checkIfValid = true, bool implicit = true, Position const* losPosition = nullptr);
void AddGOTarget(GameObject* target, uint32 effectMask);
void AddItemTarget(Item* item, uint32 effectMask);
void AddCorpseTarget(Corpse* target, uint32 effectMask);
void AddDestTarget(SpellDestination const& dest, uint32 effIndex);
SpellMissInfo PreprocessSpellHit(Unit* unit, TargetInfo& targetInfo);
void DoSpellEffectHit(Unit* unit, SpellEffectInfo const& spellEffectInfo, TargetInfo& targetInfo);
void DoTriggersOnSpellHit(Unit* unit, uint32 effMask);
bool UpdateChanneledTargetList();
bool IsValidDeadOrAliveTarget(Unit const* target) const;
void HandleLaunchPhase();
void DoEffectOnLaunchTarget(TargetInfo& targetInfo, float multiplier, SpellEffectInfo const& spellEffectInfo);
void PrepareTargetProcessing();
void FinishTargetProcessing();
// Scripting system
void LoadScripts();
void CallScriptOnPrecastHandler();
void CallScriptBeforeCastHandlers();
void CallScriptOnCastHandlers();
void CallScriptAfterCastHandlers();
SpellCastResult CallScriptCheckCastHandlers();
bool CallScriptEffectHandlers(SpellEffIndex effIndex, SpellEffectHandleMode mode);
void CallScriptSuccessfulDispel(SpellEffIndex effIndex);
void CallScriptBeforeHitHandlers(SpellMissInfo missInfo);
void CallScriptOnHitHandlers();
void CallScriptAfterHitHandlers();
public:
void CallScriptCalcCritChanceHandlers(Unit const* victim, float& chance);
protected:
void CallScriptObjectAreaTargetSelectHandlers(std::list& targets, SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType);
void CallScriptObjectTargetSelectHandlers(WorldObject*& target, SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType);
void CallScriptDestinationTargetSelectHandlers(SpellDestination& target, SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType);
bool CheckScriptEffectImplicitTargets(uint32 effIndex, uint32 effIndexToCheck);
std::vector m_loadedScripts;
struct HitTriggerSpell
{
HitTriggerSpell(SpellInfo const* spellInfo, SpellInfo const* auraSpellInfo, int32 procChance) :
triggeredSpell(spellInfo), triggeredByAura(auraSpellInfo), chance(procChance) { }
SpellInfo const* triggeredSpell;
SpellInfo const* triggeredByAura;
// uint8 triggeredByEffIdx This might be needed at a later stage - No need known for now
int32 chance;
};
bool CanExecuteTriggersOnHit(uint32 effMask, SpellInfo const* triggeredByAura = nullptr) const;
void PrepareTriggersExecutedOnHit();
typedef std::vector HitTriggerSpellList;
HitTriggerSpellList m_hitTriggerSpells;
// effect helpers
void SummonGuardian(SpellEffectInfo const* effect, uint32 entry, SummonPropertiesEntry const* properties, uint32 numSummons, ObjectGuid privateObjectOwner);
void CalculateJumpSpeeds(SpellEffectInfo const* effInfo, float dist, float& speedXY, float& speedZ);
void UpdateSpellCastDataTargets(WorldPackets::Spells::SpellCastData& data);
void UpdateSpellCastDataAmmo(WorldPackets::Spells::SpellAmmo& data);
SpellCastResult CanOpenLock(SpellEffectInfo const& effect, uint32 lockid, SkillType& skillid, int32& reqSkillValue, int32& skillValue);
// -------------------------------------------
uint32 m_spellState;
int32 m_timer;
SpellEvent* _spellEvent;
TriggerCastFlags _triggeredCastFlags;
// if need this can be replaced by Aura copy
// we can't store original aura link to prevent access to deleted auras
// and in same time need aura data and after aura deleting.
SpellInfo const* m_triggeredByAuraSpell;
std::unique_ptr m_preGeneratedPath;
std::vector _executeLogEffects;
Spell(Spell const& right) = delete;
Spell& operator=(Spell const& right) = delete;
};
namespace Trinity
{
struct TC_GAME_API WorldObjectSpellTargetCheck
{
protected:
WorldObject* _caster;
WorldObject* _referer;
SpellInfo const* _spellInfo;
SpellTargetCheckTypes _targetSelectionType;
std::unique_ptr _condSrcInfo;
ConditionContainer const* _condList;
SpellTargetObjectTypes _objectType;
WorldObjectSpellTargetCheck(WorldObject* caster, WorldObject* referer, SpellInfo const* spellInfo,
SpellTargetCheckTypes selectionType, ConditionContainer const* condList, SpellTargetObjectTypes objectType);
~WorldObjectSpellTargetCheck();
bool operator()(WorldObject* target) const;
};
struct TC_GAME_API WorldObjectSpellNearbyTargetCheck : public WorldObjectSpellTargetCheck
{
float _range;
Position const* _position;
WorldObjectSpellNearbyTargetCheck(float range, WorldObject* caster, SpellInfo const* spellInfo,
SpellTargetCheckTypes selectionType, ConditionContainer const* condList, SpellTargetObjectTypes objectType);
bool operator()(WorldObject* target);
};
struct TC_GAME_API WorldObjectSpellAreaTargetCheck : public WorldObjectSpellTargetCheck
{
float _range;
Position const* _position;
WorldObjectSpellAreaTargetCheck(float range, Position const* position, WorldObject* caster,
WorldObject* referer, SpellInfo const* spellInfo, SpellTargetCheckTypes selectionType, ConditionContainer const* condList, SpellTargetObjectTypes objectType);
bool operator()(WorldObject* target) const;
};
struct TC_GAME_API WorldObjectSpellConeTargetCheck : public WorldObjectSpellAreaTargetCheck
{
Position _coneSrc;
float _coneAngle;
float _lineWidth;
WorldObjectSpellConeTargetCheck(Position const& coneSrc, float coneAngle, float lineWidth, float range, WorldObject* caster,
SpellInfo const* spellInfo, SpellTargetCheckTypes selectionType, ConditionContainer const* condList, SpellTargetObjectTypes objectType);
bool operator()(WorldObject* target) const;
};
struct TC_GAME_API WorldObjectSpellTrajTargetCheck : public WorldObjectSpellTargetCheck
{
float _range;
Position const* _position;
WorldObjectSpellTrajTargetCheck(float range, Position const* position, WorldObject* caster,
SpellInfo const* spellInfo, SpellTargetCheckTypes selectionType, ConditionContainer const* condList, SpellTargetObjectTypes objectType);
bool operator()(WorldObject* target) const;
};
struct TC_GAME_API WorldObjectSpellLineTargetCheck : public WorldObjectSpellAreaTargetCheck
{
Position _position;
float _lineWidth;
WorldObjectSpellLineTargetCheck(Position const* srcPosition, Position const* dstPosition, float lineWidth, float range, WorldObject* caster,
SpellInfo const* spellInfo, SpellTargetCheckTypes selectionType, ConditionContainer const* condList, SpellTargetObjectTypes objectType);
bool operator()(WorldObject* target) const;
};
TC_GAME_API void SelectRandomInjuredTargets(std::list& targets, size_t maxTargets, bool prioritizePlayers);
}
using SpellEffectHandlerFn = void(Spell::*)();
#endif