36#include "G3DPosition.hpp"
132 m_itemTargetEntry(0), m_pitch(0.0f), m_speed(0.0f)
137 m_targetMask(spellCastRequest.Target.Flags), m_objectTarget(nullptr), m_itemTarget(nullptr),
138 m_objectTargetGUID(spellCastRequest.Target.
Unit), m_itemTargetGUID(spellCastRequest.Target.
Item),
139 m_itemTargetEntry(0), m_pitch(0.0f), m_speed(0.0f), m_strTarget(spellCastRequest.Target.
Name)
476 EffectBasePoints[spellEffectInfo.EffectIndex] = spellEffectInfo.CalcBaseValue(caster,
nullptr, 0, -1);
507m_spellValue(new
SpellValue(m_spellInfo, caster)), _spellEvent(nullptr)
538 if (!originalCasterGUID.
IsEmpty())
607 m_empower = std::make_unique<EmpowerData>();
666 Unit* unit =
nullptr;
722 Unit* redirect =
nullptr;
736 if (redirect && (redirect != target))
747 uint32 processedAreaEffectsMask = 0;
753 if (!spellEffectInfo.IsEffect())
785 return target.EffectMask & effectMask;
799 return target.EffectMask & effectMask && target.MissCondition != SPELL_MISS_IMMUNE && target.MissCondition != SPELL_MISS_IMMUNE2;
802 if (!anyNonImmuneTargetFound)
821 uint32 mask = (1 << spellEffectInfo.EffectIndex);
824 if (ihit->EffectMask & mask)
871 return uint64(std::floor(launchDelay * 1000.0f));
894 return targetInfo.TargetGUID == unit->GetGUID();
897 uint64 oldDelay = itr->TimeDelay;
898 itr->TimeDelay = hitDelay;
907 return itr.TimeDelay && itr.TimeDelay < smallest.TimeDelay;
933 if (effectMask & processedEffectMask)
939 if (effects[j].IsEffect() &&
948 effectMask |= 1 << j;
951 processedEffectMask |= effectMask;
991 ABORT_MSG(
"Spell::SelectEffectImplicitTargets: received not implemented select target reference type for TARGET_TYPE_OBJECT_SRC");
1008 ABORT_MSG(
"Spell::SelectEffectImplicitTargets: received not implemented select target reference type for TARGET_TYPE_OBJECT_DEST");
1022 ABORT_MSG(
"Spell::SelectEffectImplicitTargets: received not implemented select target reference type for TARGET_TYPE_OBJECT");
1032 ABORT_MSG(
"Spell::SelectEffectImplicitTargets: received not implemented select target category");
1041 ABORT_MSG(
"Spell::SelectImplicitChannelTargets: received not implemented target reference type");
1046 if (!channeledSpell)
1103 ABORT_MSG(
"Spell::SelectImplicitChannelTargets: received not implemented target type");
1112 ABORT_MSG(
"Spell::SelectImplicitNearbyTargets: received not implemented target reference type");
1133 ABORT_MSG(
"Spell::SelectImplicitNearbyTargets: received not implemented selection check type");
1142 TC_LOG_DEBUG(
"spells",
"Spell::SelectImplicitNearbyTargets: no conditions entry for target with TARGET_CHECK_ENTRY of spell ID {}, effect {} - selecting default targets",
m_spellInfo->
Id,
uint32(spellEffectInfo.
EffectIndex));
1183 dest =
SpellDestination(st->target_X, st->target_Y, st->target_Z, st->target_Orientation);
1187 if (randomRadius > 0.0f)
1203 float randomRadius = 0.0f;
1243 TC_LOG_DEBUG(
"spells",
"Spell::SelectImplicitNearbyTargets: OnObjectTargetSelect script hook for spell Id {} set object of wrong type, expected unit, got {}, effect {}",
m_spellInfo->
Id, target->
GetGUID().
GetTypeName(), effMask);
1254 TC_LOG_DEBUG(
"spells",
"Spell::SelectImplicitNearbyTargets: OnObjectTargetSelect script hook for spell Id {} set object of wrong type, expected gameobject, got {}, effect {}",
m_spellInfo->
Id, target->
GetGUID().
GetTypeName(), effMask);
1265 TC_LOG_DEBUG(
"spells",
"Spell::SelectImplicitNearbyTargets: OnObjectTargetSelect script hook for spell Id {} set object of wrong type, expected corpse, got {}, effect {}",
m_spellInfo->
Id, target->
GetGUID().
GetTypeName(), effMask);
1274 if (randomRadius > 0.0f)
1285 ABORT_MSG(
"Spell::SelectImplicitNearbyTargets: received not implemented target object type");
1311 if (coneAngle == 0.0f)
1318 std::list<WorldObject*> targets;
1329 SearchTargets<Trinity::WorldObjectListSearcher<Trinity::WorldObjectSpellConeTargetCheck> >(searcher, containerTypeMask,
m_caster,
m_caster, radius + extraSearchRadius);
1333 if (!targets.empty())
1372 if (ihit->EffectMask & (1 << spellEffectInfo.
EffectIndex))
1381 ABORT_MSG(
"Spell::SelectImplicitAreaTargets: received not implemented target reference type");
1403 ABORT_MSG(
"Spell::SelectImplicitAreaTargets: received not implemented target reference type");
1408 std::list<WorldObject*> targets;
1414 if (
Vehicle const* vehicleKit = unit->GetVehicleKit())
1416 if (
Unit* passenger = vehicleKit->GetPassenger(seat))
1417 targets.push_back(passenger);
1436 for (
ThreatReference const* threatRef : unit->GetThreatManager().GetUnsortedThreatList())
1438 targets.push_back(threateningUnit);
1442 for (
ObjectGuid const& tapperGuid : creature->GetTapList())
1444 targets.push_back(tapper);
1468 if (!targets.empty())
1475 else if (targets.size() > maxTargets)
1476 targets.resize(maxTargets);
1508 dest =
SpellDestination(st->target_X, st->target_Y, st->target_Z, st->target_Orientation, (
int32)st->target_mapId);
1510 dest =
SpellDestination(st->target_X, st->target_Y, st->target_Z, st->target_Orientation);
1523 float dist =
frand(minDist, maxDist);
1525 float angle =
rand_norm() *
static_cast<float>(
M_PI * 35.0f / 180.0f) -
static_cast<float>(
M_PI * 17.5f / 180.0f);
1532 liquidLevel = liquidData.
level;
1534 if (liquidLevel <= ground)
1542 if (ground + 0.75 > liquidLevel)
1560 float dist = spellEffectInfo.
CalcRadius(unitCaster, targetIndex);
1577 return static_cast<float>(
M_PI);
1580 return static_cast<float>(
M_PI / 2);
1582 return static_cast<float>(
M_PI / 4);
1584 return static_cast<float>(3 *
M_PI / 4);
1587 return static_cast<float>(-
M_PI / 2);
1589 return static_cast<float>(-
M_PI / 4);
1591 return static_cast<float>(-3 *
M_PI / 4);
1611 if (
WorldObject const* summoner = casterSummon->GetSummoner())
1627 dist = objSize + (dist - objSize);
1634 static float const DefaultTotemDistance = 3.0f;
1635 if (!spellEffectInfo.
HasRadius(targetIndex))
1636 dist = DefaultTotemDistance;
1677 float dist = spellEffectInfo.
CalcRadius(
nullptr, targetIndex);
1749 bool checkIfValid =
true;
1755 checkIfValid =
false;
1762 target = unitCaster->GetGuardianPet();
1766 if (unitCaster->IsSummon())
1767 target = unitCaster->ToTempSummon()->GetSummonerUnit();
1771 target = unitCaster->GetVehicleBase();
1782 if (vehicleBase->IsVehicle())
1787 if (!creatureCaster->GetTapList().empty())
1844 for (
size_t k = spellEffectInfo.
EffectIndex; k < m_spellInfo->GetEffects().
size(); ++k)
1845 if (effMask & (1 << k))
1849 std::list<WorldObject*> targets;
1858 for (std::list<WorldObject*>::iterator itr = targets.begin(); itr != targets.end(); ++itr)
1875 if (x < 100000.0f && x > -100000.0f)
return x;
1876 if (x >= 100000.0f)
return 100000.0f;
1877 if (x <= 100000.0f)
return -100000.0f;
1894 std::list<WorldObject*> targets;
1897 SearchTargets<Trinity::WorldObjectListSearcher<Trinity::WorldObjectSpellTrajTargetCheck> > (searcher,
GRID_MAP_TYPE_MASK_ALL,
m_caster, &srcPos, dist2d);
1898 if (targets.empty())
1904 float a = (srcToDestDelta - dist2d * b) / (dist2d * dist2d);
1912 bestDist = std::min(std::max(bestDist, triggerSpellInfo->GetMaxRange(
false)), std::min(dist2d, 300.0f));
1916 for (
auto itr = targets.begin(); itr != targets.end(); ++itr)
1923 if (unitCaster == *itr || unitCaster->
IsOnVehicle(unit) || unit->GetVehicle())
1933 float const size = std::max((*itr)->GetCombatReach(), 1.0f);
1935 float const dz = (*itr)->GetPositionZ() - srcPos.
m_positionZ;
1937 float const horizontalDistToTraj = std::fabs(objDist2d * std::sin(srcPos.
GetRelativeAngle(*itr)));
1938 float const sizeFactor = std::cos((horizontalDistToTraj /
size) * (
M_PI / 2.0f));
1939 float const distToHitPoint = std::max(objDist2d * std::cos(srcPos.
GetRelativeAngle(*itr)) -
size * sizeFactor, 0.0f);
1940 float const height = distToHitPoint * (a * distToHitPoint + b);
1945 if (distToHitPoint < bestDist)
1947 bestDist = distToHitPoint;
1952 if (dist2d > bestDist)
1969 std::list<WorldObject*> targets;
1988 ABORT_MSG(
"Spell::SelectImplicitLineTargets: received not implemented target reference type");
1999 SearchTargets<Trinity::WorldObjectListSearcher<Trinity::WorldObjectSpellLineTargetCheck>>(searcher, containerTypeMask,
m_caster,
m_caster, radius);
2003 if (!targets.empty())
2008 if (maxTargets < targets.size())
2011 targets.resize(maxTargets);
2015 for (std::list<WorldObject*>::iterator itr = targets.begin(); itr != targets.end(); ++itr)
2031 switch (spellEffectInfo.
Effect)
2052 Player* player = ObjectAccessor::GetPlayer(map, targetGuid);
2057 if (player->IsImmunedToSpellEffect(spell->GetSpellInfo(), spellEffectInfo, nullptr))
2060 spell->HandleEffects(player, nullptr, nullptr, nullptr, spellEffectInfo, SPELL_EFFECT_HANDLE_HIT_TARGET);
2092 target = corpseTarget;
2158 retMask &= ~GRID_MAP_TYPE_MASK_PLAYER;
2161 retMask &=
sConditionMgr->GetSearcherTypeMaskForConditionList(*condList);
2165template<
class SEARCHER>
2174 if (searchInGrid || searchInWorld)
2200 if (!containerTypeMask)
2206 SearchTargets<Trinity::WorldObjectLastSearcher<Trinity::WorldObjectSpellNearbyTargetCheck>>(searcher, containerTypeMask,
m_caster,
m_caster, range);
2215 if (!containerTypeMask)
2222 SearchTargets<Trinity::WorldObjectListSearcher<Trinity::WorldObjectSpellAreaTargetCheck>>(searcher, containerTypeMask,
m_caster, position, range + extraSearchRadius);
2229 float jumpRadius = 0.0f;
2255 float searchRadius = [&]()
2263 return jumpRadius * chainTargets;
2267 std::list<WorldObject*> tempTargets;
2270 tempTargets.remove(target);
2282 while (chainTargets)
2285 std::list<WorldObject*>::iterator foundItr = tempTargets.end();
2290 for (std::list<WorldObject*>::iterator itr = tempTargets.begin(); itr != tempTargets.end(); ++itr)
2294 uint32 deficit = unit->GetMaxHealth() - unit->GetHealth();
2298 maxHPDeficit = deficit;
2306 for (std::list<WorldObject*>::iterator itr = tempTargets.begin(); itr != tempTargets.end(); ++itr)
2308 bool isBestDistanceMatch = foundItr != tempTargets.end() ? chainSource->
GetDistanceOrder(*itr, *foundItr) : chainSource->
IsWithinDist(*itr, jumpRadius);
2309 if (!isBestDistanceMatch)
2322 if (foundItr == tempTargets.end())
2326 chainSource = *foundItr;
2328 targets.push_back(*foundItr);
2329 tempTargets.erase(foundItr);
2425 if (!spellEffectInfo.IsEffect() || !
CheckEffectTarget(target, spellEffectInfo, losPosition))
2426 effectMask &= ~(1 << spellEffectInfo.EffectIndex);
2439 effectMask &= ~(1 << spellEffectInfo.EffectIndex);
2448 ihit->EffectMask |= effectMask;
2461 targetInfo.
IsCrit =
false;
2477 return (target.EffectMask & effectMask) != 0;
2484 missileSource = previousTarget;
2486 targetInfo.
TimeDelay += previousTargetItr->TimeDelay;
2533 effectMask &= ~(1 << spellEffectInfo.EffectIndex);
2546 ihit->EffectMask |= effectMask;
2586 effectMask &= ~(1 << spellEffectInfo.EffectIndex);
2597 ihit->EffectMask |= effectMask;
2613 if (!spellEffectInfo.IsEffect())
2614 effectMask &= ~(1 << spellEffectInfo.EffectIndex);
2627 ihit->EffectMask |= effectMask;
2672 if (uniqueTargetInfo.MissCondition ==
SPELL_MISS_NONE && uniqueTargetInfo.EffectMask & (1 << effect))
2674 if (uniqueTargetInfo.TargetGUID == target)
2688 return targetInfo.MissCondition == SPELL_MISS_NONE && targetInfo.EffectMask & (1 << effect);
2696 return targetInfo.EffectMask & (1 << effect);
2704 return targetInfo.EffectMask & (1 << effect);
2712 return targetInfo.EffectMask & (1 << effect);
2784 if (_spellHitTarget)
2800 if (_spellHitTarget)
2822 if (canEffectTrigger && !procAttacker && !procVictim)
2824 bool positive =
true;
2832 if (EffectMask && !(EffectMask & (1 << i)))
2892 bool hasHealing =
false;
2893 std::unique_ptr<DamageInfo> spellDamageInfo;
2894 std::unique_ptr<HealInfo> healInfo;
2910 spell->
m_healing = healInfo->GetEffectiveHeal();
2916 bool hasDamage =
false;
2945 damageInfo.
damage = victimCreature->CalculateDamageForSparring(damageInfo.
attacker, damageInfo.
damage);
2956 if (canEffectTrigger)
2964 if (!hasHealing && !hasDamage)
2970 if (canEffectTrigger)
2972 spellDamageInfo = std::make_unique<DamageInfo>(damageInfo,
NODAMAGE, spell->
m_attackType, hitMask);
2986 if (canEffectTrigger)
3012 if (unitCaster->IsPlayer())
3013 targetCreature->SetTappedBy(unitCaster);
3025 if (_spellHitTarget)
3029 if (
CreatureAI* hitTargetAI = cHitTarget->AI())
3039 if (
AuraApplication* aurApp = HitAura->GetApplicationOfTarget(_spellHitTarget->GetGUID()))
3042 uint32 effMask = EffectMask & aurApp->GetEffectsToApply();
3044 if ((effMask & (1 << i)) && aurApp->HasEffect(i))
3045 effMask &= ~(1 << i);
3048 _spellHitTarget->_ApplyAura(aurApp, effMask);
3050 if (aurApp->IsNeedClientUpdate() && aurApp->GetRemoveMode() ==
AURA_REMOVE_NONE)
3052 aurApp->ClientUpdate(
false);
3053 _spellHitTarget->RemoveVisibleAuraUpdate(aurApp);
3124 if (creatureTarget->IsEvadingAttacks())
3162 playerOwner->SetContestedPvP();
3163 playerOwner->UpdatePvP(
true);
3205 if (origCaster == unit || !origCaster->
IsFriendlyTo(unit))
3210 if (hitInfo.
EffectMask & (1 << auraSpellEffect.EffectIndex) &&
3211 auraSpellEffect.IsUnitOwnedAuraEffect() &&
3241 bool refresh =
false;
3289 if (
int32 period = auraEff->GetPeriod())
3329 int32 _duration = 0;
3335 .SetTriggeringSpell(
this)
3336 .SetCastDifficulty(i->triggeredSpell->Difficulty));
3337 TC_LOG_DEBUG(
"spells",
"Spell {} triggered spell {} by SPELL_AURA_ADD_TARGET_TRIGGER aura",
m_spellInfo->
Id, i->triggeredSpell->Id);
3341 if (i->triggeredSpell->GetDuration() == -1)
3351 triggeredAur->SetDuration(_duration);
3362 for (std::vector<int32>::const_iterator i = spellTriggered->begin(); i != spellTriggered->end(); ++i)
3381 uint32 channelAuraMask = 0;
3384 channelAuraMask |= 1 << spellEffectInfo.EffectIndex;
3386 channelAuraMask &= channelTargetEffectMask;
3389 if (channelAuraMask)
3401 if (targetInfo.MissCondition ==
SPELL_MISS_NONE && (channelTargetEffectMask & targetInfo.EffectMask))
3407 unitCaster->RemoveChannelObject(targetInfo.TargetGUID);
3413 if (channelAuraMask & targetInfo.EffectMask)
3419 targetInfo.EffectMask &= ~aurApp->GetEffectMask();
3422 unitCaster->RemoveChannelObject(targetInfo.TargetGUID);
3429 unitCaster->RemoveChannelObject(targetInfo.TargetGUID);
3434 channelTargetEffectMask &= ~targetInfo.EffectMask;
3440 return channelTargetEffectMask == 0;
3466 if (triggeredByAura)
3498 int32 param1 = 0, param2 = 0;
3516 if (param1 || param2)
3557 return movementResult;
3605 unitCaster->SetCurrentCastSpell(
this);
3614 if (caster->IsAIEnabled())
3617 if (willCastDirectly)
3681 Spell* lastSpellMod =
nullptr;
3716 sScriptMgr->OnPlayerSpellCast(playerCaster,
this, skipCheck);
3725 if (
CreatureAI* controlledAI = cControlled->AI())
3726 controlledAI->OwnerAttacked(target);
3757 int32 param1 = 0, param2 = 0;
3761 cleanupSpell(castResult, ¶m1, ¶m2);
3773 if (!my_trade->IsInAcceptProcess())
3789 if (spellEffectInfo.IsUnitOwnedAuraEffect())
3790 aura_effmask |= 1 << spellEffectInfo.EffectIndex;
3801 if (target->HasStrongerAuraWithDR(
m_spellInfo, caster))
3814 if (!creatureCaster->GetTarget().IsEmpty() && !creatureCaster->HasUnitFlag(
UNIT_FLAG_POSSESSED))
3816 creatureCaster->SetInFront(target);
3838 pet->DespawnOrUnsummon();
3897 creatureCaster->ReleaseSpellFocus(
this);
3912 if (unitCaster->HasUnitState(
UNIT_STATE_CASTING) && !unitCaster->IsNonMeleeSpellCast(
false,
false,
true))
3928 for (
int32 id : *spell_triggered)
3933 unitCaster->RemoveAurasDueToSpell(-
id);
3937 .SetTriggeringSpell(
this));
3998 if (caster->IsAIEnabled())
4002template <
class Container>
4006 target.PreprocessTarget(
this);
4010 if (target.EffectMask & (1 << spellEffectInfo.EffectIndex))
4011 target.DoTargetSpellHit(
this, spellEffectInfo);
4014 target.DoDamageAndTriggers(
this);
4027 int32 originalDuration = duration;
4041 float ratio = float(duration) / float(originalDuration);
4044 for (std::size_t i = 0; i <
m_empower->StageDurations.size() - 1; ++i)
4047 totalExceptLastStage +=
m_empower->StageDurations[i];
4066 else if (duration == -1)
4118 bool ignoreTargetInfoTimeDelay = single_missile;
4124 if (launchMoment > t_offset)
4125 return launchMoment;
4133 ignoreTargetInfoTimeDelay =
false;
4151 std::vector<TargetInfo> delayedTargets;
4154 if (ignoreTargetInfoTimeDelay || target.TimeDelay <= t_offset)
4156 target.TimeDelay = t_offset;
4157 delayedTargets.emplace_back(std::move(target));
4160 else if (!single_missile && (next_time == 0 || target.
TimeDelay < next_time))
4171 std::vector<GOTargetInfo> delayedGOTargets;
4174 if (ignoreTargetInfoTimeDelay || goTarget.TimeDelay <= t_offset)
4176 goTarget.TimeDelay = t_offset;
4177 delayedGOTargets.emplace_back(std::move(goTarget));
4180 else if (!single_missile && (next_time == 0 || goTarget.TimeDelay < next_time))
4181 next_time = goTarget.TimeDelay;
4192 modOwner->SetSpellModTakingSpell(
this,
false);
4221 if (!spellEffectInfo.IsEffect())
4353 for (std::size_t i = 0; i <
m_empower->StageDurations.size(); ++i)
4360 return m_empower->StageDurations.size();
4363 if (completedStages !=
m_empower->CompletedStages)
4371 m_empower->CompletedStages = completedStages;
4393 if (creatureCaster->IsAIEnabled())
4394 creatureCaster->AI()->OnChannelFinished(
m_spellInfo);
4436 ((
Puppet*)charm)->UnSummon();