diff options
Diffstat (limited to 'src/server/game/Spells/Spell.cpp')
| -rw-r--r-- | src/server/game/Spells/Spell.cpp | 289 |
1 files changed, 180 insertions, 109 deletions
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index d8baf713926..ae65161538b 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -16,46 +16,49 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ +#include "Spell.h" +#include "Battlefield.h" +#include "BattlefieldMgr.h" +#include "Battleground.h" +#include "CellImpl.h" #include "Common.h" +#include "ConditionMgr.h" #include "DatabaseEnv.h" -#include "WorldPacket.h" -#include "WorldSession.h" -#include "GameTime.h" +#include "DBCStores.h" +#include "DisableMgr.h" +#include "DynamicObject.h" +#include "GameObjectAI.h" #include "GridNotifiers.h" #include "GridNotifiersImpl.h" -#include "Opcodes.h" +#include "GameTime.h" +#include "InstanceScript.h" +#include "Item.h" #include "Log.h" -#include "UpdateMask.h" -#include "World.h" +#include "LootMgr.h" +#include "ObjectAccessor.h" #include "ObjectMgr.h" -#include "SpellMgr.h" -#include "Player.h" +#include "Opcodes.h" +#include "PathGenerator.h" #include "Pet.h" -#include "Unit.h" -#include "Spell.h" -#include "DynamicObject.h" -#include "UpdateData.h" -#include "ObjectAccessor.h" -#include "CellImpl.h" +#include "Player.h" +#include "ScriptMgr.h" #include "SharedDefines.h" -#include "LootMgr.h" -#include "VMapFactory.h" -#include "Battleground.h" -#include "Util.h" -#include "TemporarySummon.h" -#include "Vehicle.h" #include "SpellAuraEffects.h" -#include "ScriptMgr.h" -#include "ConditionMgr.h" -#include "DisableMgr.h" -#include "SpellScript.h" -#include "InstanceScript.h" -#include "SpellInfo.h" #include "SpellHistory.h" -#include "Battlefield.h" -#include "BattlefieldMgr.h" +#include "SpellInfo.h" +#include "SpellMgr.h" +#include "SpellScript.h" +#include "TemporarySummon.h" #include "TradeData.h" -#include "GameObjectAI.h" +#include "Unit.h" +#include "UpdateData.h" +#include "UpdateMask.h" +#include "Util.h" +#include "Vehicle.h" +#include "VMapFactory.h" +#include "World.h" +#include "WorldPacket.h" +#include "WorldSession.h" extern pEffect SpellEffects[TOTAL_SPELL_EFFECTS]; @@ -109,8 +112,8 @@ void SpellDestination::RelocateOffset(Position const& offset) SpellCastTargets::SpellCastTargets() : m_elevation(0), m_speed(0), m_strTarget() { - m_objectTarget = NULL; - m_itemTarget = NULL; + m_objectTarget = nullptr; + m_itemTarget = nullptr; m_itemTargetEntry = 0; @@ -244,7 +247,7 @@ Unit* SpellCastTargets::GetUnitTarget() const if (m_objectTarget) return m_objectTarget->ToUnit(); - return NULL; + return nullptr; } void SpellCastTargets::SetUnitTarget(Unit* target) @@ -270,7 +273,7 @@ GameObject* SpellCastTargets::GetGOTarget() const if (m_objectTarget) return m_objectTarget->ToGameObject(); - return NULL; + return nullptr; } void SpellCastTargets::SetGOTarget(GameObject* target) @@ -296,7 +299,7 @@ Corpse* SpellCastTargets::GetCorpseTarget() const if (m_objectTarget) return m_objectTarget->ToCorpse(); - return NULL; + return nullptr; } WorldObject* SpellCastTargets::GetObjectTarget() const @@ -311,7 +314,7 @@ ObjectGuid SpellCastTargets::GetObjectTargetGUID() const void SpellCastTargets::RemoveObjectTarget() { - m_objectTarget = NULL; + m_objectTarget = nullptr; m_objectTargetGUID.Clear(); m_targetMask &= ~(TARGET_FLAG_UNIT_MASK | TARGET_FLAG_CORPSE_MASK | TARGET_FLAG_GAMEOBJECT_MASK); } @@ -441,11 +444,21 @@ void SpellCastTargets::RemoveDst() m_targetMask &= ~(TARGET_FLAG_DEST_LOCATION); } +bool SpellCastTargets::HasSrc() const +{ + return (GetTargetMask() & TARGET_FLAG_SOURCE_LOCATION) != 0; +} + +bool SpellCastTargets::HasDst() const +{ + return (GetTargetMask() & TARGET_FLAG_DEST_LOCATION) != 0; +} + void SpellCastTargets::Update(Unit* caster) { - m_objectTarget = m_objectTargetGUID ? ((m_objectTargetGUID == caster->GetGUID()) ? caster : ObjectAccessor::GetWorldObject(*caster, m_objectTargetGUID)) : NULL; + m_objectTarget = m_objectTargetGUID ? ((m_objectTargetGUID == caster->GetGUID()) ? caster : ObjectAccessor::GetWorldObject(*caster, m_objectTargetGUID)) : nullptr; - m_itemTarget = NULL; + m_itemTarget = nullptr; if (caster->GetTypeId() == TYPEID_PLAYER) { Player* player = caster->ToPlayer(); @@ -511,14 +524,28 @@ SpellValue::SpellValue(SpellInfo const* proto) AuraStackAmount = 1; } +class TC_GAME_API SpellEvent : public BasicEvent +{ + public: + SpellEvent(Spell* spell); + virtual ~SpellEvent(); + + bool Execute(uint64 e_time, uint32 p_time) override; + void Abort(uint64 e_time) override; + bool IsDeletable() const override; + + protected: + Spell* m_Spell; +}; + Spell::Spell(Unit* caster, SpellInfo const* info, TriggerCastFlags triggerFlags, ObjectGuid originalCasterGUID, bool skipCheck) : m_spellInfo(sSpellMgr->GetSpellForDifficultyFromSpell(info, caster)), m_caster((info->HasAttribute(SPELL_ATTR6_CAST_BY_CHARMER) && caster->GetCharmerOrOwner()) ? caster->GetCharmerOrOwner() : caster) -, m_spellValue(new SpellValue(m_spellInfo)), _spellEvent(nullptr), m_preGeneratedPath(PathGenerator(m_caster)) +, m_spellValue(new SpellValue(m_spellInfo)), _spellEvent(nullptr) { m_customError = SPELL_CUSTOM_ERROR_NONE; m_skipCheck = skipCheck; - m_selfContainer = NULL; + m_selfContainer = nullptr; m_referencedFromCurrentSpell = false; m_executedCurrently = false; m_needComboPoints = m_spellInfo->NeedsComboPoints(); @@ -552,7 +579,7 @@ m_caster((info->HasAttribute(SPELL_ATTR6_CAST_BY_CHARMER) && caster->GetCharmerO { m_originalCaster = ObjectAccessor::GetUnit(*m_caster, m_originalCasterGUID); if (m_originalCaster && !m_originalCaster->IsInWorld()) - m_originalCaster = NULL; + m_originalCaster = nullptr; } m_spellState = SPELL_STATE_NULL; @@ -560,14 +587,14 @@ m_caster((info->HasAttribute(SPELL_ATTR6_CAST_BY_CHARMER) && caster->GetCharmerO if (info->HasAttribute(SPELL_ATTR4_CAN_CAST_WHILE_CASTING)) _triggeredCastFlags = TriggerCastFlags(uint32(_triggeredCastFlags) | TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_CAST_DIRECTLY); - m_CastItem = NULL; + m_CastItem = nullptr; m_castItemGUID.Clear(); m_castItemEntry = 0; - unitTarget = NULL; - itemTarget = NULL; - gameObjTarget = NULL; - destTarget = NULL; + unitTarget = nullptr; + itemTarget = nullptr; + gameObjTarget = nullptr; + destTarget = nullptr; damage = 0; targetMissInfo = SPELL_MISS_NONE; effectHandleMode = SPELL_EFFECT_HANDLE_LAUNCH; @@ -576,12 +603,12 @@ m_caster((info->HasAttribute(SPELL_ATTR6_CAST_BY_CHARMER) && caster->GetCharmerO m_procAttacker = 0; m_procVictim = 0; m_hitMask = 0; - focusObject = NULL; + focusObject = nullptr; m_cast_count = 0; m_glyphIndex = 0; m_preCastSpell = 0; - m_triggeredByAuraSpell = NULL; - m_spellAura = NULL; + m_triggeredByAuraSpell = nullptr; + m_spellAura = nullptr; //Auto Shot & Shoot (wand) m_autoRepeat = m_spellInfo->IsAutoRepeatRangedSpell(); @@ -622,7 +649,7 @@ Spell::~Spell() // Clean the reference to avoid later crash. // If this error is repeating, we may have to add an ASSERT to better track down how we get into this case. TC_LOG_ERROR("spells", "SPELL: deleting spell for spell ID %u. However, spell still referenced.", m_spellInfo->Id); - *m_selfContainer = NULL; + *m_selfContainer = nullptr; } if (m_caster && m_caster->GetTypeId() == TYPEID_PLAYER) @@ -657,7 +684,7 @@ void Spell::InitExplicitTargets(SpellCastTargets const& targets) // try to select correct unit target if not provided by client or by serverside cast if (neededTargets & (TARGET_FLAG_UNIT_MASK)) { - Unit* unit = NULL; + Unit* unit = nullptr; // try to use player selection as a target if (Player* playerCaster = m_caster->ToPlayer()) { @@ -724,7 +751,7 @@ void Spell::SelectExplicitTargets() redirect = m_caster->GetMeleeHitRedirectTarget(target, m_spellInfo); break; default: - redirect = NULL; + redirect = nullptr; break; } if (redirect && (redirect != target)) @@ -1171,7 +1198,7 @@ void Spell::SelectImplicitConeTargets(SpellEffIndex effIndex, SpellImplicitTarge void Spell::SelectImplicitAreaTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType, uint32 effMask) { - Unit* referer = NULL; + Unit* referer = nullptr; switch (targetType.GetReferenceType()) { case TARGET_REFERENCE_TYPE_SRC: @@ -1202,7 +1229,7 @@ void Spell::SelectImplicitAreaTargets(SpellEffIndex effIndex, SpellImplicitTarge if (!referer) return; - Position const* center = NULL; + Position const* center = nullptr; switch (targetType.GetReferenceType()) { case TARGET_REFERENCE_TYPE_SRC: @@ -1429,7 +1456,7 @@ void Spell::SelectImplicitDestDestTargets(SpellEffIndex effIndex, SpellImplicitT void Spell::SelectImplicitCasterObjectTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType) { - WorldObject* target = NULL; + WorldObject* target = nullptr; bool checkIfValid = true; switch (targetType.GetTarget()) @@ -1498,7 +1525,7 @@ void Spell::SelectImplicitChainTargets(SpellEffIndex effIndex, SpellImplicitTarg { uint32 maxTargets = m_spellInfo->Effects[effIndex].ChainTarget; if (Player* modOwner = m_caster->GetSpellModOwner()) - modOwner->ApplySpellMod<SPELLMOD_JUMP_TARGETS>(m_spellInfo->Id, maxTargets, this); + modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_JUMP_TARGETS, maxTargets, this); if (maxTargets > 1) { @@ -1646,7 +1673,7 @@ void Spell::SelectEffectTypeImplicitTargets(uint8 effIndex) if (!targetMask) return; - WorldObject* target = NULL; + WorldObject* target = nullptr; switch (m_spellInfo->Effects[effIndex].GetImplicitTargetType()) { @@ -1759,10 +1786,10 @@ void Spell::SearchTargets(SEARCHER& searcher, uint32 containerMask, Unit* refere WorldObject* Spell::SearchNearbyTarget(float range, SpellTargetObjectTypes objectType, SpellTargetCheckTypes selectionType, ConditionContainer* condList) { - WorldObject* target = NULL; + WorldObject* target = nullptr; uint32 containerTypeMask = GetSearcherTypeMask(objectType, condList); if (!containerTypeMask) - return NULL; + return nullptr; Trinity::WorldObjectSpellNearbyTargetCheck check(range, m_caster, m_spellInfo, selectionType, condList); Trinity::WorldObjectLastSearcher<Trinity::WorldObjectSpellNearbyTargetCheck> searcher(m_caster, target, check, containerTypeMask); SearchTargets<Trinity::WorldObjectLastSearcher<Trinity::WorldObjectSpellNearbyTargetCheck> > (searcher, containerTypeMask, m_caster, m_caster, range); @@ -1877,7 +1904,7 @@ void Spell::SearchChainTargets(std::list<WorldObject*>& targets, uint32 chainTar GameObject* Spell::SearchSpellFocus() { - GameObject* focus = NULL; + GameObject* focus = nullptr; Trinity::GameObjectFocusCheck check(m_caster, m_spellInfo->RequiresSpellFocus); Trinity::GameObjectSearcher<Trinity::GameObjectFocusCheck> searcher(m_caster, focus, check); SearchTargets<Trinity::GameObjectSearcher<Trinity::GameObjectFocusCheck> > (searcher, GRID_MAP_TYPE_MASK_GAMEOBJECT, m_caster, m_caster, m_caster->GetVisibilityRange()); @@ -2217,7 +2244,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target) // can't use default call because of threading, do stuff as fast as possible for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) if (farMask & (1 << i)) - HandleEffects(unit, NULL, NULL, i, SPELL_EFFECT_HANDLE_HIT_TARGET); + HandleEffects(unit, nullptr, nullptr, i, SPELL_EFFECT_HANDLE_HIT_TARGET); return; } @@ -2656,7 +2683,7 @@ SpellMissInfo Spell::DoSpellHitOnUnit(Unit* unit, uint32 effectMask, bool scaleA for (uint32 effectNumber = 0; effectNumber < MAX_SPELL_EFFECTS; ++effectNumber) if (effectMask & (1 << effectNumber)) - HandleEffects(unit, NULL, NULL, effectNumber, SPELL_EFFECT_HANDLE_HIT_TARGET); + HandleEffects(unit, nullptr, nullptr, effectNumber, SPELL_EFFECT_HANDLE_HIT_TARGET); return SPELL_MISS_NONE; } @@ -2752,7 +2779,7 @@ void Spell::DoAllEffectOnTarget(GOTargetInfo* target) for (uint32 effectNumber = 0; effectNumber < MAX_SPELL_EFFECTS; ++effectNumber) if (effectMask & (1 << effectNumber)) - HandleEffects(NULL, NULL, go, effectNumber, SPELL_EFFECT_HANDLE_HIT_TARGET); + HandleEffects(nullptr, nullptr, go, effectNumber, SPELL_EFFECT_HANDLE_HIT_TARGET); if (go->AI()) go->AI()->SpellHit(m_caster, m_spellInfo); @@ -2772,7 +2799,7 @@ void Spell::DoAllEffectOnTarget(ItemTargetInfo* target) for (uint32 effectNumber = 0; effectNumber < MAX_SPELL_EFFECTS; ++effectNumber) if (effectMask & (1 << effectNumber)) - HandleEffects(NULL, target->item, NULL, effectNumber, SPELL_EFFECT_HANDLE_HIT_TARGET); + HandleEffects(nullptr, target->item, nullptr, effectNumber, SPELL_EFFECT_HANDLE_HIT_TARGET); CallScriptOnHitHandlers(); @@ -2798,7 +2825,7 @@ bool Spell::UpdateChanneledTargetList() { range = m_spellInfo->GetMaxRange(m_spellInfo->IsPositive()); if (Player* modOwner = m_caster->GetSpellModOwner()) - modOwner->ApplySpellMod<SPELLMOD_RANGE>(m_spellInfo->Id, range, this); + modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RANGE, range, this); // add little tolerance level range += std::min(MAX_SPELL_RANGE_TOLERANCE, range*0.1f); // 10% but no more than MAX_SPELL_RANGE_TOLERANCE @@ -3051,7 +3078,7 @@ void Spell::cancel() SetReferencedFromCurrent(false); if (m_selfContainer && *m_selfContainer == this) - *m_selfContainer = NULL; + *m_selfContainer = nullptr; m_caster->RemoveDynObject(m_spellInfo->Id); if (m_spellInfo->IsChanneled()) // if not channeled then the object for the current cast wasn't summoned yet @@ -3106,7 +3133,7 @@ void Spell::_cast(bool skipCheck) // As of 3.0.2 pets begin attacking their owner's target immediately // Let any pets know we've attacked something. Check DmgClass for harmful spells only // This prevents spells such as Hunter's Mark from triggering pet attack - if (this->GetSpellInfo()->DmgClass != SPELL_DAMAGE_CLASS_NONE) + if (GetSpellInfo()->DmgClass != SPELL_DAMAGE_CLASS_NONE) if (Unit* unitTarget = m_targets.GetUnitTarget()) for (Unit* controlled : playerCaster->m_Controlled) if (Creature* cControlled = controlled->ToCreature()) @@ -3317,7 +3344,7 @@ void Spell::handle_immediate() // First mod_duration then haste - see Missile Barrage // Apply duration mod if (Player* modOwner = m_caster->GetSpellModOwner()) - modOwner->ApplySpellMod<SPELLMOD_DURATION>(m_spellInfo->Id, duration); + modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_DURATION, duration); // Apply haste mods m_caster->ModSpellDurationTime(m_spellInfo, duration, this); @@ -3445,7 +3472,7 @@ uint64 Spell::handle_delayed(uint64 t_offset) void Spell::_handle_immediate_phase() { - m_spellAura = NULL; + m_spellAura = nullptr; // handle some immediate features of the spell here HandleThreatSpells(); @@ -3460,7 +3487,7 @@ void Spell::_handle_immediate_phase() continue; // call effect handlers to handle destination hit - HandleEffects(NULL, NULL, NULL, j, SPELL_EFFECT_HANDLE_HIT); + HandleEffects(nullptr, nullptr, nullptr, j, SPELL_EFFECT_HANDLE_HIT); } // process items @@ -3897,7 +3924,7 @@ void Spell::SendPetCastResult(SpellCastResult result) WorldPacket data(SMSG_PET_CAST_FAILED, 1 + 4 + 1); WriteCastResultInfo(data, player, m_spellInfo, m_cast_count, result, m_customError); - player->GetSession()->SendPacket(&data); + player->SendDirectMessage(&data); } void Spell::SendSpellStart() @@ -4221,7 +4248,7 @@ void Spell::SendLogExecute() data.append(*m_effectExecuteData[i]); delete m_effectExecuteData[i]; - m_effectExecuteData[i] = NULL; + m_effectExecuteData[i] = nullptr; } m_caster->SendMessageToSet(&data, true); } @@ -4367,7 +4394,7 @@ void Spell::SendResurrectRequest(Player* target) data << uint8(m_caster->IsSpiritHealer()); // "you'll be afflicted with resurrection sickness" // override delay sent with SMSG_CORPSE_RECLAIM_DELAY, set instant resurrection for spells with this attribute data << uint8(!m_spellInfo->HasAttribute(SPELL_ATTR3_IGNORE_RESURRECTION_TIMER)); - target->GetSession()->SendPacket(&data); + target->SendDirectMessage(&data); } void Spell::TakeCastItem() @@ -4430,9 +4457,9 @@ void Spell::TakeCastItem() // prevent crash at access to deleted m_targets.GetItemTarget if (m_CastItem == m_targets.GetItemTarget()) - m_targets.SetItemTarget(NULL); + m_targets.SetItemTarget(nullptr); - m_CastItem = NULL; + m_CastItem = nullptr; m_castItemGUID.Clear(); m_castItemEntry = 0; } @@ -4455,8 +4482,11 @@ void Spell::TakePower() if (m_caster->GetTypeId() == TYPEID_PLAYER) { if (powerType == POWER_RAGE || powerType == POWER_ENERGY || powerType == POWER_RUNE) + { if (ObjectGuid targetGUID = m_targets.GetUnitTargetGUID()) - for (std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit) + { + for (std::list<TargetInfo>::iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit) + { if (ihit->targetGUID == targetGUID) { if (ihit->missCondition != SPELL_MISS_NONE) @@ -4464,10 +4494,13 @@ void Spell::TakePower() hit = false; //lower spell cost on fail (by talent aura) if (Player* modOwner = m_caster->ToPlayer()->GetSpellModOwner()) - modOwner->ApplySpellMod<SPELLMOD_SPELL_COST_REFUND_ON_FAIL>(m_spellInfo->Id, m_powerCost); + modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_SPELL_COST_REFUND_ON_FAIL, m_powerCost); } break; } + } + } + } } if (powerType == POWER_RUNE) @@ -4556,7 +4589,7 @@ SpellCastResult Spell::CheckRuneCost(uint32 runeCostID) const { runeCost[i] = src->RuneCost[i]; if (Player* modOwner = m_caster->GetSpellModOwner()) - modOwner->ApplySpellMod<SPELLMOD_COST>(m_spellInfo->Id, runeCost[i], const_cast<Spell*>(this)); + modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_COST, runeCost[i], const_cast<Spell*>(this)); } runeCost[RUNE_DEATH] = MAX_RUNES; // calculated later @@ -4596,7 +4629,7 @@ void Spell::TakeRunePower(bool didHit) { runeCost[i] = runeCostData->RuneCost[i]; if (Player* modOwner = m_caster->GetSpellModOwner()) - modOwner->ApplySpellMod<SPELLMOD_COST>(m_spellInfo->Id, runeCost[i], this); + modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_COST, runeCost[i], this); } // Let's say we use a skill that requires a Frost rune. This is the order: @@ -4673,7 +4706,7 @@ void Spell::TakeReagents() if (m_caster->GetTypeId() != TYPEID_PLAYER) return; - ItemTemplate const* castItemTemplate = m_CastItem ? m_CastItem->GetTemplate() : NULL; + ItemTemplate const* castItemTemplate = m_CastItem ? m_CastItem->GetTemplate() : nullptr; // do not take reagents for these item casts if (castItemTemplate && castItemTemplate->Flags & ITEM_FLAG_NO_REAGENT_COST) @@ -4705,14 +4738,14 @@ void Spell::TakeReagents() } } - m_CastItem = NULL; + m_CastItem = nullptr; m_castItemGUID.Clear(); m_castItemEntry = 0; } // if GetItemTarget is also spell reagent if (m_targets.GetItemTargetEntry() == itemid) - m_targets.SetItemTarget(NULL); + m_targets.SetItemTarget(nullptr); p_caster->DestroyItemCount(itemid, itemcount, true); } @@ -4782,7 +4815,7 @@ void Spell::HandleEffects(Unit* pUnitTarget, Item* pItemTarget, GameObject* pGOT TC_LOG_DEBUG("spells", "Spell: %u Effect : %u", m_spellInfo->Id, eff); // we do not need DamageMultiplier here. - damage = CalculateDamage(i, NULL); + damage = CalculateDamage(i, nullptr); bool preventDefault = CallScriptEffectHandlers((SpellEffIndex)i, mode); @@ -4888,7 +4921,7 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint m_needComboPoints = false; if ((*j)->GetMiscValue() == 1) { - reqCombat=false; + reqCombat = false; break; } } @@ -4989,7 +5022,7 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint if (DynamicObject* dynObj = m_caster->GetDynObject(m_triggeredByAuraSpell->Id)) losTarget = dynObj; - if (!m_spellInfo->HasAttribute(SPELL_ATTR2_CAN_TARGET_NOT_IN_LOS) && !DisableMgr::IsDisabledFor(DISABLE_TYPE_SPELL, m_spellInfo->Id, NULL, SPELL_DISABLE_LOS) && !target->IsWithinLOSInMap(losTarget, LINEOFSIGHT_ALL_CHECKS, VMAP::ModelIgnoreFlags::M2)) + if (!m_spellInfo->HasAttribute(SPELL_ATTR2_CAN_TARGET_NOT_IN_LOS) && !DisableMgr::IsDisabledFor(DISABLE_TYPE_SPELL, m_spellInfo->Id, nullptr, SPELL_DISABLE_LOS) && !target->IsWithinLOSInMap(losTarget, LINEOFSIGHT_ALL_CHECKS, VMAP::ModelIgnoreFlags::M2)) return SPELL_FAILED_LINE_OF_SIGHT; } } @@ -5001,7 +5034,7 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint float x, y, z; m_targets.GetDstPos()->GetPosition(x, y, z); - if (!m_spellInfo->HasAttribute(SPELL_ATTR2_CAN_TARGET_NOT_IN_LOS) && !DisableMgr::IsDisabledFor(DISABLE_TYPE_SPELL, m_spellInfo->Id, NULL, SPELL_DISABLE_LOS) && !m_caster->IsWithinLOS(x, y, z, LINEOFSIGHT_ALL_CHECKS, VMAP::ModelIgnoreFlags::M2)) + if (!m_spellInfo->HasAttribute(SPELL_ATTR2_CAN_TARGET_NOT_IN_LOS) && !DisableMgr::IsDisabledFor(DISABLE_TYPE_SPELL, m_spellInfo->Id, nullptr, SPELL_DISABLE_LOS) && !m_caster->IsWithinLOS(x, y, z, LINEOFSIGHT_ALL_CHECKS, VMAP::ModelIgnoreFlags::M2)) return SPELL_FAILED_LINE_OF_SIGHT; } @@ -5262,26 +5295,27 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint float objSize = target->GetCombatReach(); float range = m_spellInfo->GetMaxRange(true, m_caster, this) * 1.5f + objSize; // can't be overly strict - m_preGeneratedPath.SetPathLengthLimit(range); + m_preGeneratedPath = Trinity::make_unique<PathGenerator>(m_caster); + m_preGeneratedPath->SetPathLengthLimit(range); // first try with raycast, if it fails fall back to normal path float targetObjectSize = std::min(target->GetCombatReach(), 4.0f); - bool result = m_preGeneratedPath.CalculatePath(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ() + targetObjectSize, false, true); - if (m_preGeneratedPath.GetPathType() & PATHFIND_SHORT) + bool result = m_preGeneratedPath->CalculatePath(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ() + targetObjectSize, false, true); + if (m_preGeneratedPath->GetPathType() & PATHFIND_SHORT) return SPELL_FAILED_OUT_OF_RANGE; - else if (!result || m_preGeneratedPath.GetPathType() & (PATHFIND_NOPATH | PATHFIND_INCOMPLETE)) + else if (!result || m_preGeneratedPath->GetPathType() & (PATHFIND_NOPATH | PATHFIND_INCOMPLETE)) { - result = m_preGeneratedPath.CalculatePath(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ() + targetObjectSize, false, false); - if (m_preGeneratedPath.GetPathType() & PATHFIND_SHORT) + result = m_preGeneratedPath->CalculatePath(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ() + targetObjectSize, false, false); + if (m_preGeneratedPath->GetPathType() & PATHFIND_SHORT) return SPELL_FAILED_OUT_OF_RANGE; - else if (!result || m_preGeneratedPath.GetPathType() & (PATHFIND_NOPATH | PATHFIND_INCOMPLETE)) + else if (!result || m_preGeneratedPath->GetPathType() & (PATHFIND_NOPATH | PATHFIND_INCOMPLETE)) return SPELL_FAILED_NOPATH; - else if (m_preGeneratedPath.IsInvalidDestinationZ(target)) // Check position z, if not in a straight line + else if (m_preGeneratedPath->IsInvalidDestinationZ(target)) // Check position z, if not in a straight line return SPELL_FAILED_NOPATH; } - else if (m_preGeneratedPath.IsInvalidDestinationZ(target)) // Check position z, if in a straight line + else if (m_preGeneratedPath->IsInvalidDestinationZ(target)) // Check position z, if in a straight line return SPELL_FAILED_NOPATH; - m_preGeneratedPath.ReducePathLenghtByDist(objSize); // move back + m_preGeneratedPath->ReducePathLenghtByDist(objSize); // move back } break; } @@ -5324,7 +5358,7 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint || (m_spellInfo->Effects[i].TargetA.GetTarget() == TARGET_GAMEOBJECT_TARGET && !m_targets.GetGOTarget())) return SPELL_FAILED_BAD_TARGETS; - Item* pTempItem = NULL; + Item* pTempItem = nullptr; if (m_targets.GetTargetMask() & TARGET_FLAG_TRADE_ITEM) { if (TradeData* pTrade = m_caster->ToPlayer()->GetTradeData()) @@ -5424,7 +5458,7 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint { if (strict) //starting cast, trigger pet stun (cast by pet so it doesn't attack player) if (Pet* pet = m_caster->ToPlayer()->GetPet()) - pet->CastSpell(pet, 32752, true, NULL, NULL, pet->GetGUID()); + pet->CastSpell(pet, 32752, true, nullptr, nullptr, pet->GetGUID()); } else if (!m_spellInfo->HasAttribute(SPELL_ATTR1_DISMISS_PET)) return SPELL_FAILED_ALREADY_HAVE_SUMMON; @@ -5938,6 +5972,11 @@ bool Spell::CheckSpellCancelsConfuse(uint32* param1) const return CheckSpellCancelsAuraEffect(SPELL_AURA_MOD_CONFUSE, param1); } +int32 Spell::CalculateDamage(uint8 i, Unit const* target) const +{ + return m_caster->CalculateSpellDamage(target, m_spellInfo, i, &m_spellValue->EffectBasePoints[i]); +} + bool Spell::CanAutoCast(Unit* target) { if (!target) @@ -5994,6 +6033,18 @@ bool Spell::CanAutoCast(Unit* target) return false; } +void Spell::CheckSrc() +{ + if (!m_targets.HasSrc()) + m_targets.SetSrc(*m_caster); +} + +void Spell::CheckDst() +{ + if (!m_targets.HasDst()) + m_targets.SetDst(*m_caster); +} + SpellCastResult Spell::CheckRange(bool strict) const { // Don't check for instant cast spells @@ -6083,7 +6134,7 @@ std::pair<float, float> Spell::GetMinMaxRange(bool strict) const maxRange *= ranged->GetTemplate()->RangedModRange * 0.01f; if (Player* modOwner = m_caster->GetSpellModOwner()) - modOwner->ApplySpellMod<SPELLMOD_RANGE>(m_spellInfo->Id, maxRange, const_cast<Spell*>(this)); + modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RANGE, maxRange, const_cast<Spell*>(this)); maxRange += rangeMod; @@ -6693,7 +6744,7 @@ void Spell::Delayed() // only called in DealDamage() //check pushback reduce int32 delaytime = 500; // spellcasting delay is normally 500ms int32 delayReduce = 100; // must be initialized to 100 for percent modifiers - m_caster->ToPlayer()->ApplySpellMod<SPELLMOD_NOT_LOSE_CASTING_TIME>(m_spellInfo->Id, delayReduce, this); + m_caster->ToPlayer()->ApplySpellMod(m_spellInfo->Id, SPELLMOD_NOT_LOSE_CASTING_TIME, delayReduce, this); delayReduce += m_caster->GetTotalAuraModifier(SPELL_AURA_REDUCE_PUSHBACK) - 100; if (delayReduce >= 100) return; @@ -6731,7 +6782,7 @@ void Spell::DelayedChannel() int32 delaytime = CalculatePct(duration, 25); // channeling delay is normally 25% of its time per hit int32 delayReduce = 100; // must be initialized to 100 for percent modifiers - m_caster->ToPlayer()->ApplySpellMod<SPELLMOD_NOT_LOSE_CASTING_TIME>(m_spellInfo->Id, delayReduce, this); + m_caster->ToPlayer()->ApplySpellMod(m_spellInfo->Id, SPELLMOD_NOT_LOSE_CASTING_TIME, delayReduce, this); delayReduce += m_caster->GetTotalAuraModifier(SPELL_AURA_REDUCE_PUSHBACK) - 100; if (delayReduce >= 100) return; @@ -6768,7 +6819,7 @@ bool Spell::UpdatePointers() { m_originalCaster = ObjectAccessor::GetUnit(*m_caster, m_originalCasterGUID); if (m_originalCaster && !m_originalCaster->IsInWorld()) - m_originalCaster = NULL; + m_originalCaster = nullptr; } if (m_castItemGUID && m_caster->GetTypeId() == TYPEID_PLAYER) @@ -6790,7 +6841,7 @@ bool Spell::UpdatePointers() return true; // cache last transport - WorldObject* transport = NULL; + WorldObject* transport = nullptr; // update effect destinations (in case of moved transport dest target) for (uint8 effIndex = 0; effIndex < MAX_SPELL_EFFECTS; ++effIndex) @@ -6847,11 +6898,11 @@ bool Spell::CheckEffectTarget(Unit const* target, uint32 eff, Position const* lo } // check for ignore LOS on the effect itself - if (m_spellInfo->HasAttribute(SPELL_ATTR2_CAN_TARGET_NOT_IN_LOS) || DisableMgr::IsDisabledFor(DISABLE_TYPE_SPELL, m_spellInfo->Id, NULL, SPELL_DISABLE_LOS)) + if (m_spellInfo->HasAttribute(SPELL_ATTR2_CAN_TARGET_NOT_IN_LOS) || DisableMgr::IsDisabledFor(DISABLE_TYPE_SPELL, m_spellInfo->Id, nullptr, SPELL_DISABLE_LOS)) return true; // if spell is triggered, need to check for LOS disable on the aura triggering it and inherit that behaviour - if (IsTriggered() && m_triggeredByAuraSpell && (m_triggeredByAuraSpell->HasAttribute(SPELL_ATTR2_CAN_TARGET_NOT_IN_LOS) || DisableMgr::IsDisabledFor(DISABLE_TYPE_SPELL, m_triggeredByAuraSpell->Id, NULL, SPELL_DISABLE_LOS))) + if (IsTriggered() && m_triggeredByAuraSpell && (m_triggeredByAuraSpell->HasAttribute(SPELL_ATTR2_CAN_TARGET_NOT_IN_LOS) || DisableMgr::IsDisabledFor(DISABLE_TYPE_SPELL, m_triggeredByAuraSpell->Id, nullptr, SPELL_DISABLE_LOS))) return true; /// @todo shit below shouldn't be here, but it's temporary @@ -6910,7 +6961,7 @@ bool Spell::CheckEffectTarget(Unit const* target, uint32 eff, Position const* lo else { // Get GO cast coordinates if original caster -> GO - WorldObject* caster = NULL; + WorldObject* caster = nullptr; if (m_originalCasterGUID.IsGameObject()) caster = m_caster->GetMap()->GetGameObject(m_originalCasterGUID); if (!caster) @@ -6925,6 +6976,26 @@ bool Spell::CheckEffectTarget(Unit const* target, uint32 eff, Position const* lo return true; } +bool Spell::IsTriggered() const +{ + return (_triggeredCastFlags & TRIGGERED_FULL_MASK) != 0; +} + +bool Spell::IsIgnoringCooldowns() const +{ + return (_triggeredCastFlags & TRIGGERED_IGNORE_SPELL_AND_CATEGORY_CD) != 0; +} + +bool Spell::IsProcDisabled() const +{ + return (_triggeredCastFlags & TRIGGERED_DISALLOW_PROC_EVENTS) != 0; +} + +bool Spell::IsChannelActive() const +{ + return m_caster->GetUInt32Value(UNIT_CHANNEL_SPELL) != 0; +} + bool Spell::IsAutoActionResetSpell() const { /// @todo changed SPELL_INTERRUPT_FLAG_AUTOATTACK -> SPELL_INTERRUPT_FLAG_INTERRUPT to fix compile - is this check correct at all? @@ -7099,7 +7170,7 @@ void Spell::HandleLaunchPhase() if (!m_spellInfo->Effects[i].IsEffect()) continue; - HandleEffects(NULL, NULL, NULL, i, SPELL_EFFECT_HANDLE_LAUNCH); + HandleEffects(nullptr, nullptr, nullptr, i, SPELL_EFFECT_HANDLE_LAUNCH); } float multiplier[MAX_SPELL_EFFECTS]; @@ -7155,7 +7226,7 @@ void Spell::HandleLaunchPhase() void Spell::DoAllEffectOnLaunchTarget(TargetInfo& targetInfo, float* multiplier) { - Unit* unit = NULL; + Unit* unit = nullptr; // In case spell hit target, do all effect on that target if (targetInfo.missCondition == SPELL_MISS_NONE) unit = m_caster->GetGUID() == targetInfo.targetGUID ? m_caster : ObjectAccessor::GetUnit(*m_caster, targetInfo.targetGUID); @@ -7172,7 +7243,7 @@ void Spell::DoAllEffectOnLaunchTarget(TargetInfo& targetInfo, float* multiplier) m_damage = 0; m_healing = 0; - HandleEffects(unit, NULL, NULL, i, SPELL_EFFECT_HANDLE_LAUNCH_TARGET); + HandleEffects(unit, nullptr, nullptr, i, SPELL_EFFECT_HANDLE_LAUNCH_TARGET); if (m_damage > 0) { @@ -7662,7 +7733,7 @@ void Spell::TriggerGlobalCooldown() { // gcd modifier auras are applied only to own spells and only players have such mods if (Player* modOwner = m_caster->GetSpellModOwner()) - modOwner->ApplySpellMod<SPELLMOD_GLOBAL_COOLDOWN>(m_spellInfo->Id, gcd, this); + modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_GLOBAL_COOLDOWN, gcd, this); // Apply haste rating gcd = int32(float(gcd) * m_caster->GetFloatValue(UNIT_MOD_CAST_SPEED)); |
