/*
* 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 "Concepts.h"
#include "ConditionMgr.h"
#include "DBCEnums.h"
#include "Duration.h"
#include "ModelIgnoreFlags.h"
#include "ObjectGuid.h"
#include "Optional.h"
#include "Position.h"
#include "SharedDefines.h"
#include "SpellDefines.h"
#include "Types.h"
#include "UniqueTrackablePtr.h"
#include
#include
namespace WorldPackets::Spells
{
struct SpellCastData;
struct SpellHealPrediction;
}
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 ProcFlagsSpellType : uint32;
enum SpellTargetCheckTypes : uint8;
enum SpellTargetObjectTypes : uint8;
enum SpellValueMod : int32;
enum SpellValueModFloat : int32;
enum TriggerCastFlags : uint32;
enum WeaponAttackType : uint8;
namespace Trinity
{
enum class WorldObjectSpellAreaTargetSearchReason;
template
struct WorldObjectListSearcher;
}
#define SPELL_CHANNEL_UPDATE_INTERVAL (1 * IN_MILLISECONDS)
#define MAX_SPELL_RANGE_TOLERANCE 3.0f
#define TRAJECTORY_MISSILE_SIZE 3.0f
#define AOE_DAMAGE_TARGET_CAP SI64LIT(20)
#define SPELL_EMPOWER_HOLD_TIME_AT_MAX (1 * IN_MILLISECONDS)
#define SPELL_EMPOWER_HARDCODED_GCD 359115u
enum SpellCastFlags : uint32
{
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, // sorts missed targets before hit targets for chain visual
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_TRIGGER_PET_COOLDOWN = 0x80000000 // causes the cooldown to be stored in pets SpellHistory on client
};
enum SpellCastFlagsEx : uint32
{
CAST_FLAG_EX_NONE = 0x00000,
CAST_FLAG_EX_TRIGGER_COOLDOWN_ON_SPELL_START = 0x00001,
CAST_FLAG_EX_UNKNOWN_2 = 0x00002,
CAST_FLAG_EX_DONT_CONSUME_CHARGES = 0x00004,
CAST_FLAG_EX_UNKNOWN_4 = 0x00008,
CAST_FLAG_EX_DELAY_STARTING_COOLDOWNS = 0x00010, // makes client start cooldown after precalculated delay instead of immediately after SPELL_GO (used by empower spells)
CAST_FLAG_EX_UNKNOWN_6 = 0x00020,
CAST_FLAG_EX_UNKNOWN_7 = 0x00040,
CAST_FLAG_EX_UNKNOWN_8 = 0x00080,
CAST_FLAG_EX_IGNORE_PET_COOLDOWN = 0x00100, // makes client not automatically start cooldown for pets after SPELL_GO
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 SpellHealPredictionType : uint8
{
SPELL_HEAL_PREDICTION_TARGET = 0,
SPELL_HEAL_PREDICTION_TARGET_AND_CASTER = 1,
SPELL_HEAL_PREDICTION_TARGET_AND_BEACON = 2,
SPELL_HEAL_PREDICTION_TARGET_PARTY = 3,
};
enum SpellRangeFlag
{
SPELL_RANGE_DEFAULT = 0,
SPELL_RANGE_MELEE = 1, //melee
SPELL_RANGE_RANGED = 2 //hunter range and ranged weapon
};
struct SpellLogEffectPowerDrainParams
{
ObjectGuid Victim;
uint32 Points = 0;
Powers PowerType = POWER_MANA;
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;
Optional ParentSpellTargetCount;
Optional ParentSpellTargetIndex;
};
enum SpellState
{
SPELL_STATE_NULL = 0,
SPELL_STATE_PREPARING = 1,
SPELL_STATE_LAUNCHED = 2,
SPELL_STATE_CHANNELING = 3,
SPELL_STATE_FINISHED = 4,
SPELL_STATE_IDLE = 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 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 EffectIncreaseCurrencyCap();
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 EffectForceCast2();
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 EffectKillCreditLabel();
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 EffectRemoveAuraBySpellLabel();
void EffectCreateGarrison();
void EffectCreateConversation();
void EffectCancelConversation();
void EffectAddGarrisonFollower();
void EffectActivateGarrisonBuilding();
void EffectGrantBattlePetLevel();
void EffectGiveExperience();
void EffectGiveRestedExperience();
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 EffectApplyMountEquipment();
void EffectSendChatMessage();
void EffectGrantBattlePetExperience();
void EffectLearnTransmogIllusion();
void EffectModifyAuraStacks();
void EffectModifyCooldown();
void EffectModifyCooldowns();
void EffectModifyCooldownsByCategory();
void EffectModifySpellCharges();
void EffectCreateTraitTreeConfig();
void EffectChangeActiveCombatTraitConfig();
void EffectTeleportGraveyard();
void EffectUpdateInteractions();
void EffectLearnWarbandScene();
void EffectSetPlayerDataElementAccount();
void EffectSetPlayerDataElementCharacter();
void EffectSetPlayerDataFlagAccount();
void EffectSetPlayerDataFlagCharacter();
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, SpellTargetIndex targetIndex, uint32& processedEffectMask);
void SelectImplicitChannelTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType);
void SelectImplicitNearbyTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType, SpellTargetIndex targetIndex, uint32 effMask);
void SelectImplicitConeTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType, SpellTargetIndex targetIndex, uint32 effMask);
void SelectImplicitAreaTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType, SpellTargetIndex targetIndex, uint32 effMask);
void SelectImplicitCasterDestTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType, SpellTargetIndex targetIndex);
void SelectImplicitTargetDestTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType, SpellTargetIndex targetIndex);
void SelectImplicitDestDestTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType, SpellTargetIndex targetIndex);
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, SpellTargetIndex targetIndex, uint32 effMask);
void SelectEffectTypeImplicitTargets(SpellEffectInfo const& spellEffectInfo);
static uint32 GetSearcherTypeMask(SpellInfo const* spellInfo, SpellEffectInfo const& spellEffectInfo, SpellTargetObjectTypes objType, ConditionContainer const* condList);
template static void SearchTargets(SEARCHER& searcher, uint32 containerMask, WorldObject* referer, Position const* pos, float radius);
WorldObject* SearchNearbyTarget(SpellEffectInfo const& spellEffectInfo, float range, SpellTargetObjectTypes objectType, SpellTargetCheckTypes selectionType, ConditionContainer const* condList = nullptr);
void SearchAreaTargets(std::list& targets, SpellEffectInfo const& spellEffectInfo, float range, Position const* position, WorldObject* referer,
SpellTargetObjectTypes objectType, SpellTargetCheckTypes selectionType, ConditionContainer const* condList,
Trinity::WorldObjectSpellAreaTargetSearchReason searchReason);
void SearchChainTargets(std::list& targets, uint32 chainTargets, WorldObject* target, SpellTargetObjectTypes objectType,
SpellTargetCheckTypes selectType, SpellEffectInfo const& spellEffectInfo, 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(SpellCastResult result = SPELL_CAST_OK);
void TakePower();
void RefundPower();
void TakeRunePower(bool didHit);
void RefundRunePower();
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();
SpellCastResult CheckMovement() const;
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();
SpellState getState() const { return m_spellState; }
void setState(SpellState state) { m_spellState = state; }
void DoCreateItem(uint32 itemId, ItemContext context = ItemContext::NONE, std::vector const* bonusListIDs = nullptr);
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, Powers 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, Optional result = {});
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;
std::any m_customArg;
SpellCastVisual m_SpellVisual;
SpellCastTargets m_targets;
SpellCustomErrors m_customError;
UsedSpellMods m_appliedMods;
Optional> m_scriptResult;
bool m_scriptWaitsForSpellHit = false;
int32 GetCastTime() const { return m_casttime; }
int32 GetRemainingCastTime() const { return m_timer; }
int32 GetChannelDuration() const { return m_channelDuration; }
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 IsEmpowerSpell() const { return m_empower != nullptr; }
void SetEmpowerReleasedByClient(bool release);
bool CanReleaseEmpowerSpell() const;
bool IsTriggeredByAura(SpellInfo const* auraSpellInfo) const { return (auraSpellInfo == m_triggeredByAuraSpell); }
int32 GetProcChainLength() const { return m_procChainLength; }
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();
void UpdateDelayMomentForDst(uint64 hitDelay);
void UpdateDelayMomentForUnitTarget(Unit* unit, uint64 hitDelay);
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(CastSpellExtraArgsInit::SpellValueOverride const& 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;
Trinity::unique_weak_ptr GetWeakPtr() const;
void CallScriptOnResistAbsorbCalculateHandlers(DamageInfo const& damageInfo, uint32& resistAmount, int32& absorbAmount);
bool IsWithinLOS(WorldObject const* source, WorldObject const* target, bool targetAsSourceLocation, VMAP::ModelIgnoreFlags ignoreFlags) const;
bool IsWithinLOS(WorldObject const* source, Position const& target, VMAP::ModelIgnoreFlags ignoreFlags) const;
void MovePosition(Position& pos, WorldObject const* from, float dist, float angle) const;
static bool CanIncreaseRangeByMovement(Unit const* unit);
std::pair GetMinMaxRange(bool strict) const;
protected:
bool HasGlobalCooldown() const;
void TriggerGlobalCooldown();
void CancelGlobalCooldown();
void _cast(bool skipCheck = false);
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_channelDuration; // 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;
}
struct EmpowerData
{
Milliseconds MinHoldTime = 0ms;
std::vector StageDurations;
int32 CompletedStages = 0;
bool IsReleasedByClient = false;
bool IsReleased = false;
};
std::unique_ptr m_empower;
// 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
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;
ProcFlagsSpellType m_procSpellType; // for finish procs
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;
ProcFlagsHit ProcHitMask = { };
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];
int32 GetUnitTargetIndexForEffect(ObjectGuid const& target, SpellEffIndex effect) const;
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);
void PreprocessSpellLaunch(TargetInfo& targetInfo);
SpellMissInfo PreprocessSpellHit(Unit* unit, TargetInfo& targetInfo);
void DoSpellEffectHit(Unit* unit, SpellEffectInfo const& spellEffectInfo, TargetInfo& targetInfo);
void DoTriggersOnSpellHit(Unit* unit);
bool UpdateChanneledTargetList();
bool IsValidDeadOrAliveTarget(Unit const* target) const;
void HandleLaunchPhase();
void DoEffectOnLaunchTarget(TargetInfo& targetInfo, float multiplier, SpellEffectInfo const& spellEffectInfo);
void ResetCombatTimers();
void PrepareTargetProcessing();
void FinishTargetProcessing();
// Scripting system
void LoadScripts();
void CallScriptOnPrecastHandler();
void CallScriptBeforeCastHandlers();
void CallScriptOnCastHandlers();
void CallScriptAfterCastHandlers();
SpellCastResult CallScriptCheckCastHandlers();
int32 CallScriptCalcCastTimeHandlers(int32 originalCastTime);
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);
void CallScriptCalcDamageHandlers(SpellEffectInfo const& spellEffectInfo, Unit* victim, int32& damage, int32& flatMod, float& pctMod);
void CallScriptCalcHealingHandlers(SpellEffectInfo const& spellEffectInfo, Unit* victim, int32& healing, int32& flatMod, float& pctMod);
template
Script* GetScript() const { return static_cast