mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-16 07:30:42 +01:00
Core/Spells: implement corpse target type support and properly fix resurrections (#24921)
* Core/Spells: implement corpse target type support and properly fix resurrections (cherry picked from commitdf193945d9) * Core/Spells: implement TARGET_CORPSE_SRC_AREA_RAID and updated remaining resurrection effect handlers for updated corpse targeting (cherry picked from commit98b075cb4b) * Fix no-pch Co-authored-by: Ovahlord <dreadkiller@gmx.de> (cherry picked from commitcc71da35b5)
This commit is contained in:
@@ -572,6 +572,7 @@ m_spellValue(new SpellValue(m_spellInfo, caster)), _spellEvent(nullptr)
|
||||
unitTarget = nullptr;
|
||||
itemTarget = nullptr;
|
||||
gameObjTarget = nullptr;
|
||||
corpseTarget = nullptr;
|
||||
destTarget = nullptr;
|
||||
damage = 0;
|
||||
targetMissInfo = SPELL_MISS_NONE;
|
||||
@@ -1127,6 +1128,17 @@ void Spell::SelectImplicitNearbyTargets(SpellEffectInfo const& spellEffectInfo,
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case TARGET_OBJECT_TYPE_CORPSE:
|
||||
if (Corpse* corpseTarget = target->ToCorpse())
|
||||
AddCorpseTarget(corpseTarget, effMask);
|
||||
else
|
||||
{
|
||||
TC_LOG_DEBUG("spells", "Spell::SelectImplicitNearbyTargets: OnObjectTargetSelect script hook for spell Id %u set object of wrong type, expected corpse, got %s, effect %u", m_spellInfo->Id, target->GetGUID().GetTypeName(), effMask);
|
||||
SendCastResult(SPELL_FAILED_BAD_IMPLICIT_TARGETS);
|
||||
finish(false);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case TARGET_OBJECT_TYPE_DEST:
|
||||
{
|
||||
SpellDestination dest(*target);
|
||||
@@ -1188,12 +1200,14 @@ void Spell::SelectImplicitConeTargets(SpellEffectInfo const& spellEffectInfo, Sp
|
||||
if (uint32 maxTargets = m_spellValue->MaxAffectedTargets)
|
||||
Trinity::Containers::RandomResize(targets, maxTargets);
|
||||
|
||||
for (std::list<WorldObject*>::iterator itr = targets.begin(); itr != targets.end(); ++itr)
|
||||
for (WorldObject* itr : targets)
|
||||
{
|
||||
if (Unit* unit = (*itr)->ToUnit())
|
||||
if (Unit* unit = itr->ToUnit())
|
||||
AddUnitTarget(unit, effMask, false);
|
||||
else if (GameObject* gObjTarget = (*itr)->ToGameObject())
|
||||
else if (GameObject* gObjTarget = itr->ToGameObject())
|
||||
AddGOTarget(gObjTarget, effMask);
|
||||
else if (Corpse* corpse = itr->ToCorpse())
|
||||
AddCorpseTarget(corpse, effMask);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1309,12 +1323,14 @@ void Spell::SelectImplicitAreaTargets(SpellEffectInfo const& spellEffectInfo, Sp
|
||||
targets.resize(maxTargets);
|
||||
}
|
||||
|
||||
for (std::list<WorldObject*>::iterator itr = targets.begin(); itr != targets.end(); ++itr)
|
||||
for (WorldObject* itr : targets)
|
||||
{
|
||||
if (Unit* unit = (*itr)->ToUnit())
|
||||
if (Unit* unit = itr->ToUnit())
|
||||
AddUnitTarget(unit, effMask, false, true, center);
|
||||
else if (GameObject* gObjTarget = (*itr)->ToGameObject())
|
||||
else if (GameObject* gObjTarget = itr->ToGameObject())
|
||||
AddGOTarget(gObjTarget, effMask);
|
||||
else if (Corpse* corpse = itr->ToCorpse())
|
||||
AddCorpseTarget(corpse, effMask);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1616,6 +1632,8 @@ void Spell::SelectImplicitCasterObjectTargets(SpellEffectInfo const& spellEffect
|
||||
AddUnitTarget(unit, 1 << spellEffectInfo.EffectIndex, checkIfValid);
|
||||
else if (GameObject* go = target->ToGameObject())
|
||||
AddGOTarget(go, 1 << spellEffectInfo.EffectIndex);
|
||||
else if (Corpse* corpse = target->ToCorpse())
|
||||
AddCorpseTarget(corpse, 1 << spellEffectInfo.EffectIndex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1633,6 +1651,8 @@ void Spell::SelectImplicitTargetObjectTargets(SpellEffectInfo const& spellEffect
|
||||
AddUnitTarget(unit, 1 << spellEffectInfo.EffectIndex, true, false);
|
||||
else if (GameObject* gobj = target->ToGameObject())
|
||||
AddGOTarget(gobj, 1 << spellEffectInfo.EffectIndex);
|
||||
else if (Corpse* corpse = target->ToCorpse())
|
||||
AddCorpseTarget(corpse, 1 << spellEffectInfo.EffectIndex);
|
||||
|
||||
SelectImplicitChainTargets(spellEffectInfo, targetType, target, 1 << spellEffectInfo.EffectIndex);
|
||||
}
|
||||
@@ -1817,6 +1837,8 @@ void Spell::SelectImplicitLineTargets(SpellEffectInfo const& spellEffectInfo, Sp
|
||||
AddUnitTarget(unit, effMask, false);
|
||||
else if (GameObject* gObjTarget = (*itr)->ToGameObject())
|
||||
AddGOTarget(gObjTarget, effMask);
|
||||
else if (Corpse* corpse = (*itr)->ToCorpse())
|
||||
AddCorpseTarget(corpse, 1 << spellEffectInfo.EffectIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1854,7 +1876,7 @@ void Spell::SelectEffectTypeImplicitTargets(SpellEffectInfo const& spellEffectIn
|
||||
if (player->IsImmunedToSpellEffect(spell->GetSpellInfo(), spellEffectInfo, nullptr))
|
||||
return;
|
||||
|
||||
spell->HandleEffects(player, nullptr, nullptr, spellEffectInfo, SPELL_EFFECT_HANDLE_HIT_TARGET);
|
||||
spell->HandleEffects(player, nullptr, nullptr, nullptr, spellEffectInfo, SPELL_EFFECT_HANDLE_HIT_TARGET);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1886,11 +1908,7 @@ void Spell::SelectEffectTypeImplicitTargets(SpellEffectInfo const& spellEffectIn
|
||||
else if (targetMask & TARGET_FLAG_CORPSE_MASK)
|
||||
{
|
||||
if (Corpse* corpseTarget = m_targets.GetCorpseTarget())
|
||||
{
|
||||
/// @todo this is a workaround - corpses should be added to spell target map too, but we can't do that so we add owner instead
|
||||
if (Player* owner = ObjectAccessor::FindPlayer(corpseTarget->GetOwnerGUID()))
|
||||
target = owner;
|
||||
}
|
||||
target = corpseTarget;
|
||||
}
|
||||
else //if (targetMask & TARGET_FLAG_UNIT_MASK)
|
||||
target = m_caster;
|
||||
@@ -1921,6 +1939,8 @@ void Spell::SelectEffectTypeImplicitTargets(SpellEffectInfo const& spellEffectIn
|
||||
AddUnitTarget(target->ToUnit(), 1 << spellEffectInfo.EffectIndex, false);
|
||||
else if (target->ToGameObject())
|
||||
AddGOTarget(target->ToGameObject(), 1 << spellEffectInfo.EffectIndex);
|
||||
else if (target->ToCorpse())
|
||||
AddCorpseTarget(target->ToCorpse(), 1 << spellEffectInfo.EffectIndex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1934,6 +1954,12 @@ uint32 Spell::GetSearcherTypeMask(SpellTargetObjectTypes objType, ConditionConta
|
||||
{
|
||||
case TARGET_OBJECT_TYPE_UNIT:
|
||||
case TARGET_OBJECT_TYPE_UNIT_AND_DEST:
|
||||
if (!m_spellInfo->HasAttribute(SPELL_ATTR2_CAN_TARGET_DEAD))
|
||||
{
|
||||
retMask &= GRID_MAP_TYPE_MASK_PLAYER | GRID_MAP_TYPE_MASK_CREATURE;
|
||||
break;
|
||||
}
|
||||
[[fallthrough]];
|
||||
case TARGET_OBJECT_TYPE_CORPSE:
|
||||
case TARGET_OBJECT_TYPE_CORPSE_ENEMY:
|
||||
case TARGET_OBJECT_TYPE_CORPSE_ALLY:
|
||||
@@ -1946,8 +1972,7 @@ uint32 Spell::GetSearcherTypeMask(SpellTargetObjectTypes objType, ConditionConta
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (!m_spellInfo->HasAttribute(SPELL_ATTR2_CAN_TARGET_DEAD))
|
||||
retMask &= ~GRID_MAP_TYPE_MASK_CORPSE;
|
||||
|
||||
if (m_spellInfo->HasAttribute(SPELL_ATTR3_ONLY_TARGET_PLAYERS))
|
||||
retMask &= GRID_MAP_TYPE_MASK_CORPSE | GRID_MAP_TYPE_MASK_PLAYER;
|
||||
if (m_spellInfo->HasAttribute(SPELL_ATTR3_ONLY_TARGET_GHOSTS))
|
||||
@@ -2386,6 +2411,58 @@ void Spell::AddItemTarget(Item* item, uint32 effectMask)
|
||||
m_UniqueItemInfo.emplace_back(std::move(target));
|
||||
}
|
||||
|
||||
void Spell::AddCorpseTarget(Corpse* corpse, uint32 effectMask)
|
||||
{
|
||||
for (SpellEffectInfo const& spellEffectInfo : m_spellInfo->GetEffects())
|
||||
if (!spellEffectInfo.IsEffect())
|
||||
effectMask &= ~(1 << spellEffectInfo.EffectIndex);
|
||||
|
||||
// no effects left
|
||||
if (!effectMask)
|
||||
return;
|
||||
|
||||
ObjectGuid targetGUID = corpse->GetGUID();
|
||||
|
||||
// Lookup target in already in list
|
||||
auto ihit = std::find_if(std::begin(m_UniqueCorpseTargetInfo), std::end(m_UniqueCorpseTargetInfo), [targetGUID](CorpseTargetInfo const& target) { return target.TargetGUID == targetGUID; });
|
||||
if (ihit != std::end(m_UniqueCorpseTargetInfo)) // Found in list
|
||||
{
|
||||
// Add only effect mask
|
||||
ihit->EffectMask |= effectMask;
|
||||
return;
|
||||
}
|
||||
|
||||
// This is new target calculate data for him
|
||||
CorpseTargetInfo target;
|
||||
target.TargetGUID = targetGUID;
|
||||
target.EffectMask = effectMask;
|
||||
|
||||
// Spell have speed - need calculate incoming time
|
||||
if (m_caster != corpse)
|
||||
{
|
||||
float hitDelay = m_spellInfo->LaunchDelay;
|
||||
if (m_spellInfo->HasAttribute(SPELL_ATTR9_SPECIAL_DELAY_CALCULATION))
|
||||
hitDelay += m_spellInfo->Speed;
|
||||
else if (m_spellInfo->Speed > 0.0f)
|
||||
{
|
||||
// calculate spell incoming interval
|
||||
float dist = std::max(m_caster->GetDistance(corpse->GetPositionX(), corpse->GetPositionY(), corpse->GetPositionZ()), 5.0f);
|
||||
hitDelay += dist / m_spellInfo->Speed;
|
||||
}
|
||||
|
||||
target.TimeDelay = uint64(std::floor(hitDelay * 1000.0f));
|
||||
}
|
||||
else
|
||||
target.TimeDelay = 0LL;
|
||||
|
||||
// Calculate minimum incoming time
|
||||
if (target.TimeDelay && (!m_delayMoment || m_delayMoment > target.TimeDelay))
|
||||
m_delayMoment = target.TimeDelay;
|
||||
|
||||
// Add target to list
|
||||
m_UniqueCorpseTargetInfo.emplace_back(std::move(target));
|
||||
}
|
||||
|
||||
void Spell::AddDestTarget(SpellDestination const& dest, uint32 effIndex)
|
||||
{
|
||||
m_destTargets[effIndex] = dest;
|
||||
@@ -2415,6 +2492,14 @@ int64 Spell::GetItemTargetCountForEffect(SpellEffIndex effect) const
|
||||
});
|
||||
}
|
||||
|
||||
int64 Spell::GetCorpseTargetCountForEffect(SpellEffIndex effect) const
|
||||
{
|
||||
return std::count_if(m_UniqueCorpseTargetInfo.begin(), m_UniqueCorpseTargetInfo.end(), [effect](CorpseTargetInfo const& targetInfo)
|
||||
{
|
||||
return targetInfo.EffectMask & (1 << effect);
|
||||
});
|
||||
}
|
||||
|
||||
void Spell::TargetInfo::PreprocessTarget(Spell* spell)
|
||||
{
|
||||
Unit* unit = spell->m_caster->GetGUID() == TargetGUID ? spell->m_caster->ToUnit() : ObjectAccessor::GetUnit(*spell->m_caster, TargetGUID);
|
||||
@@ -2744,7 +2829,7 @@ void Spell::GOTargetInfo::DoTargetSpellHit(Spell* spell, SpellEffectInfo const&
|
||||
|
||||
spell->CallScriptBeforeHitHandlers(SPELL_MISS_NONE);
|
||||
|
||||
spell->HandleEffects(nullptr, nullptr, go, spellEffectInfo, SPELL_EFFECT_HANDLE_HIT_TARGET);
|
||||
spell->HandleEffects(nullptr, nullptr, go, nullptr, spellEffectInfo, SPELL_EFFECT_HANDLE_HIT_TARGET);
|
||||
|
||||
// AI functions
|
||||
if (go->AI())
|
||||
@@ -2763,7 +2848,21 @@ void Spell::ItemTargetInfo::DoTargetSpellHit(Spell* spell, SpellEffectInfo const
|
||||
{
|
||||
spell->CallScriptBeforeHitHandlers(SPELL_MISS_NONE);
|
||||
|
||||
spell->HandleEffects(nullptr, TargetItem, nullptr, spellEffectInfo, SPELL_EFFECT_HANDLE_HIT_TARGET);
|
||||
spell->HandleEffects(nullptr, TargetItem, nullptr, nullptr, spellEffectInfo, SPELL_EFFECT_HANDLE_HIT_TARGET);
|
||||
|
||||
spell->CallScriptOnHitHandlers();
|
||||
spell->CallScriptAfterHitHandlers();
|
||||
}
|
||||
|
||||
void Spell::CorpseTargetInfo::DoTargetSpellHit(Spell* spell, SpellEffectInfo const& spellEffectInfo)
|
||||
{
|
||||
Corpse* corpse = ObjectAccessor::GetCorpse(*spell->m_caster, TargetGUID);
|
||||
if (!corpse)
|
||||
return;
|
||||
|
||||
spell->CallScriptBeforeHitHandlers(SPELL_MISS_NONE);
|
||||
|
||||
spell->HandleEffects(nullptr, nullptr, nullptr, corpse, spellEffectInfo, SPELL_EFFECT_HANDLE_HIT_TARGET);
|
||||
|
||||
spell->CallScriptOnHitHandlers();
|
||||
spell->CallScriptAfterHitHandlers();
|
||||
@@ -2969,7 +3068,7 @@ void Spell::DoSpellEffectHit(Unit* unit, SpellEffectInfo const& spellEffectInfo,
|
||||
}
|
||||
|
||||
_spellAura = hitInfo.HitAura;
|
||||
HandleEffects(unit, nullptr, nullptr, spellEffectInfo, SPELL_EFFECT_HANDLE_HIT_TARGET);
|
||||
HandleEffects(unit, nullptr, nullptr, nullptr, spellEffectInfo, SPELL_EFFECT_HANDLE_HIT_TARGET);
|
||||
_spellAura = nullptr;
|
||||
}
|
||||
|
||||
@@ -3684,6 +3783,8 @@ void Spell::handle_immediate()
|
||||
|
||||
DoProcessTargetContainer(m_UniqueGOTargetInfo);
|
||||
|
||||
DoProcessTargetContainer(m_UniqueCorpseTargetInfo);
|
||||
|
||||
FinishTargetProcessing();
|
||||
|
||||
// spell is finished, perform some last features of the spell here
|
||||
@@ -3820,7 +3921,7 @@ void Spell::_handle_immediate_phase()
|
||||
continue;
|
||||
|
||||
// call effect handlers to handle destination hit
|
||||
HandleEffects(nullptr, nullptr, nullptr, spellEffectInfo, SPELL_EFFECT_HANDLE_HIT);
|
||||
HandleEffects(nullptr, nullptr, nullptr, nullptr, spellEffectInfo, SPELL_EFFECT_HANDLE_HIT);
|
||||
}
|
||||
|
||||
// process items
|
||||
@@ -4548,6 +4649,9 @@ void Spell::UpdateSpellCastDataTargets(WorldPackets::Spells::SpellCastData& data
|
||||
for (GOTargetInfo const& targetInfo : m_UniqueGOTargetInfo)
|
||||
data.HitTargets.push_back(targetInfo.TargetGUID); // Always hits
|
||||
|
||||
for (CorpseTargetInfo const& targetInfo : m_UniqueCorpseTargetInfo)
|
||||
data.HitTargets.push_back(targetInfo.TargetGUID); // Always hits
|
||||
|
||||
// Reset m_needAliveTargetMask for non channeled spell
|
||||
if (!m_spellInfo->IsChanneled())
|
||||
m_channelTargetEffectMask = 0;
|
||||
@@ -5160,12 +5264,13 @@ void Spell::HandleThreatSpells()
|
||||
TC_LOG_DEBUG("spells", "Spell %u, added an additional %f threat for %s %u target(s)", m_spellInfo->Id, threat, IsPositive() ? "assisting" : "harming", uint32(m_UniqueTargetInfo.size()));
|
||||
}
|
||||
|
||||
void Spell::HandleEffects(Unit* pUnitTarget, Item* pItemTarget, GameObject* pGOTarget, SpellEffectInfo const& spellEffectInfo, SpellEffectHandleMode mode)
|
||||
void Spell::HandleEffects(Unit* pUnitTarget, Item* pItemTarget, GameObject* pGoTarget, Corpse* pCorpseTarget, SpellEffectInfo const& spellEffectInfo, SpellEffectHandleMode mode)
|
||||
{
|
||||
effectHandleMode = mode;
|
||||
unitTarget = pUnitTarget;
|
||||
itemTarget = pItemTarget;
|
||||
gameObjTarget = pGOTarget;
|
||||
gameObjTarget = pGoTarget;
|
||||
corpseTarget = pCorpseTarget;
|
||||
destTarget = &m_destTargets[spellEffectInfo.EffectIndex]._position;
|
||||
effectInfo = &spellEffectInfo;
|
||||
unitCaster = m_originalCaster ? m_originalCaster : m_caster->ToUnit();
|
||||
@@ -7803,7 +7908,7 @@ void Spell::HandleLaunchPhase()
|
||||
if (!spellEffectInfo.IsEffect())
|
||||
continue;
|
||||
|
||||
HandleEffects(nullptr, nullptr, nullptr, spellEffectInfo, SPELL_EFFECT_HANDLE_LAUNCH);
|
||||
HandleEffects(nullptr, nullptr, nullptr, nullptr, spellEffectInfo, SPELL_EFFECT_HANDLE_LAUNCH);
|
||||
}
|
||||
|
||||
PrepareTargetProcessing();
|
||||
@@ -7847,7 +7952,7 @@ void Spell::DoEffectOnLaunchTarget(TargetInfo& targetInfo, float multiplier, Spe
|
||||
m_damage = 0;
|
||||
m_healing = 0;
|
||||
|
||||
HandleEffects(unit, nullptr, nullptr, spellEffectInfo, SPELL_EFFECT_HANDLE_LAUNCH_TARGET);
|
||||
HandleEffects(unit, nullptr, nullptr, nullptr, spellEffectInfo, SPELL_EFFECT_HANDLE_LAUNCH_TARGET);
|
||||
|
||||
if (m_originalCaster && m_damage > 0)
|
||||
{
|
||||
@@ -8449,13 +8554,15 @@ bool WorldObjectSpellTargetCheck::operator()(WorldObject* target) const
|
||||
case TARGET_CHECK_ENEMY:
|
||||
if (unitTarget->IsTotem())
|
||||
return false;
|
||||
if (!_caster->IsValidAttackTarget(unitTarget, _spellInfo))
|
||||
// TODO: restore IsValidAttackTarget for corpses using corpse owner (faction, etc)
|
||||
if (!target->IsCorpse() && !_caster->IsValidAttackTarget(unitTarget, _spellInfo))
|
||||
return false;
|
||||
break;
|
||||
case TARGET_CHECK_ALLY:
|
||||
if (unitTarget->IsTotem())
|
||||
return false;
|
||||
if (!_caster->IsValidAssistTarget(unitTarget, _spellInfo))
|
||||
// TODO: restore IsValidAttackTarget for corpses using corpse owner (faction, etc)
|
||||
if (!target->IsCorpse() && !_caster->IsValidAssistTarget(unitTarget, _spellInfo))
|
||||
return false;
|
||||
break;
|
||||
case TARGET_CHECK_PARTY:
|
||||
@@ -8463,7 +8570,8 @@ bool WorldObjectSpellTargetCheck::operator()(WorldObject* target) const
|
||||
return false;
|
||||
if (unitTarget->IsTotem())
|
||||
return false;
|
||||
if (!_caster->IsValidAssistTarget(unitTarget, _spellInfo))
|
||||
// TODO: restore IsValidAttackTarget for corpses using corpse owner (faction, etc)
|
||||
if (!target->IsCorpse() && !_caster->IsValidAssistTarget(unitTarget, _spellInfo))
|
||||
return false;
|
||||
if (!refUnit->IsInPartyWith(unitTarget))
|
||||
return false;
|
||||
@@ -8479,7 +8587,8 @@ bool WorldObjectSpellTargetCheck::operator()(WorldObject* target) const
|
||||
return false;
|
||||
if (unitTarget->IsTotem())
|
||||
return false;
|
||||
if (!_caster->IsValidAssistTarget(unitTarget, _spellInfo))
|
||||
// TODO: restore IsValidAttackTarget for corpses using corpse owner (faction, etc)
|
||||
if (!target->IsCorpse() && !_caster->IsValidAssistTarget(unitTarget, _spellInfo))
|
||||
return false;
|
||||
if (!refUnit->IsInRaidWith(unitTarget))
|
||||
return false;
|
||||
|
||||
@@ -523,7 +523,7 @@ class TC_GAME_API Spell
|
||||
void SendChannelStart(uint32 duration);
|
||||
void SendResurrectRequest(Player* target);
|
||||
|
||||
void HandleEffects(Unit* pUnitTarget, Item* pItemTarget, GameObject* pGOTarget, SpellEffectInfo const& spellEffectInfo, SpellEffectHandleMode mode);
|
||||
void HandleEffects(Unit* pUnitTarget, Item* pItemTarget, GameObject* pGoTarget, Corpse* pCorpseTarget, SpellEffectInfo const& spellEffectInfo, SpellEffectHandleMode mode);
|
||||
void HandleThreatSpells();
|
||||
static Spell const* ExtractSpellFromEvent(BasicEvent* event);
|
||||
|
||||
@@ -629,6 +629,7 @@ class TC_GAME_API Spell
|
||||
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);
|
||||
@@ -688,6 +689,7 @@ class TC_GAME_API Spell
|
||||
Unit* unitTarget;
|
||||
Item* itemTarget;
|
||||
GameObject* gameObjTarget;
|
||||
Corpse* corpseTarget;
|
||||
WorldLocation* destTarget;
|
||||
int32 damage;
|
||||
SpellMissInfo targetMissInfo;
|
||||
@@ -779,6 +781,15 @@ class TC_GAME_API Spell
|
||||
};
|
||||
std::vector<ItemTargetInfo> m_UniqueItemInfo;
|
||||
|
||||
struct CorpseTargetInfo : public TargetInfoBase
|
||||
{
|
||||
void DoTargetSpellHit(Spell* spell, SpellEffectInfo const& spellEffectInfo) override;
|
||||
|
||||
ObjectGuid TargetGUID;
|
||||
uint64 TimeDelay = 0ULL;
|
||||
};
|
||||
std::vector<CorpseTargetInfo> m_UniqueCorpseTargetInfo;
|
||||
|
||||
template <class Container>
|
||||
void DoProcessTargetContainer(Container& targetContainer);
|
||||
|
||||
@@ -787,6 +798,7 @@ class TC_GAME_API Spell
|
||||
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);
|
||||
|
||||
@@ -52,6 +52,7 @@
|
||||
#include "Map.h"
|
||||
#include "MiscPackets.h"
|
||||
#include "MotionMaster.h"
|
||||
#include "ObjectAccessor.h"
|
||||
#include "ObjectMgr.h"
|
||||
#include "Opcodes.h"
|
||||
#include "OutdoorPvPMgr.h"
|
||||
@@ -386,25 +387,27 @@ void Spell::EffectResurrectNew()
|
||||
if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
|
||||
return;
|
||||
|
||||
if (!unitTarget || unitTarget->IsAlive())
|
||||
if (!corpseTarget && !unitTarget)
|
||||
return;
|
||||
|
||||
if (unitTarget->GetTypeId() != TYPEID_PLAYER)
|
||||
Player* player = nullptr;
|
||||
|
||||
if (corpseTarget)
|
||||
player = ObjectAccessor::FindPlayer(corpseTarget->GetOwnerGUID());
|
||||
else if (unitTarget)
|
||||
player = unitTarget->ToPlayer();
|
||||
|
||||
if (!player || player->IsAlive() || !player->IsInWorld())
|
||||
return;
|
||||
|
||||
if (!unitTarget->IsInWorld())
|
||||
return;
|
||||
|
||||
Player* target = unitTarget->ToPlayer();
|
||||
|
||||
if (target->IsResurrectRequested()) // already have one active request
|
||||
if (player->IsResurrectRequested()) // already have one active request
|
||||
return;
|
||||
|
||||
uint32 health = damage;
|
||||
uint32 mana = effectInfo->MiscValue;
|
||||
ExecuteLogEffectResurrect(SpellEffectName(effectInfo->Effect), target);
|
||||
target->SetResurrectRequestData(m_caster, health, mana, 0);
|
||||
SendResurrectRequest(target);
|
||||
ExecuteLogEffectResurrect(SpellEffectName(effectInfo->Effect), player);
|
||||
player->SetResurrectRequestData(m_caster, health, mana, 0);
|
||||
SendResurrectRequest(player);
|
||||
}
|
||||
|
||||
void Spell::EffectInstaKill()
|
||||
@@ -519,7 +522,7 @@ void Spell::EffectDummy()
|
||||
if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
|
||||
return;
|
||||
|
||||
if (!unitTarget && !gameObjTarget && !itemTarget)
|
||||
if (!unitTarget && !gameObjTarget && !itemTarget && !corpseTarget)
|
||||
return;
|
||||
|
||||
// pet auras
|
||||
@@ -1037,6 +1040,8 @@ void Spell::EffectSendEvent()
|
||||
target = unitTarget;
|
||||
else if (gameObjTarget)
|
||||
target = gameObjTarget;
|
||||
else if (corpseTarget)
|
||||
target = corpseTarget;
|
||||
}
|
||||
else // if (effectHandleMode == SPELL_EFFECT_HANDLE_HIT)
|
||||
{
|
||||
@@ -3547,24 +3552,29 @@ void Spell::EffectResurrect()
|
||||
if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
|
||||
return;
|
||||
|
||||
if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
|
||||
if (!corpseTarget && !unitTarget)
|
||||
return;
|
||||
|
||||
if (unitTarget->IsAlive() || !unitTarget->IsInWorld())
|
||||
Player* player = nullptr;
|
||||
|
||||
if (corpseTarget)
|
||||
player = ObjectAccessor::FindPlayer(corpseTarget->GetOwnerGUID());
|
||||
else if (unitTarget)
|
||||
player = unitTarget->ToPlayer();
|
||||
|
||||
if (!player || player->IsAlive() || !player->IsInWorld())
|
||||
return;
|
||||
|
||||
Player* target = unitTarget->ToPlayer();
|
||||
|
||||
if (target->IsResurrectRequested()) // already have one active request
|
||||
if (player->IsResurrectRequested()) // already have one active request
|
||||
return;
|
||||
|
||||
uint32 health = target->CountPctFromMaxHealth(damage);
|
||||
uint32 mana = CalculatePct(target->GetMaxPower(POWER_MANA), damage);
|
||||
uint32 health = player->CountPctFromMaxHealth(damage);
|
||||
uint32 mana = CalculatePct(player->GetMaxPower(POWER_MANA), damage);
|
||||
|
||||
ExecuteLogEffectResurrect(SpellEffectName(effectInfo->Effect), target);
|
||||
ExecuteLogEffectResurrect(SpellEffectName(effectInfo->Effect), player);
|
||||
|
||||
target->SetResurrectRequestData(m_caster, health, mana, 0);
|
||||
SendResurrectRequest(target);
|
||||
player->SetResurrectRequestData(m_caster, health, mana, 0);
|
||||
SendResurrectRequest(player);
|
||||
}
|
||||
|
||||
void Spell::EffectAddExtraAttacks()
|
||||
@@ -4503,7 +4513,13 @@ void Spell::EffectSkinPlayerCorpse()
|
||||
TC_LOG_DEBUG("spells", "Effect: SkinPlayerCorpse");
|
||||
|
||||
Player* player = m_caster->ToPlayer();
|
||||
Player* target = unitTarget->ToPlayer();
|
||||
|
||||
Player* target = nullptr;
|
||||
if (unitTarget)
|
||||
target = unitTarget->ToPlayer();
|
||||
else if (corpseTarget)
|
||||
target = ObjectAccessor::FindPlayer(corpseTarget->GetOwnerGUID());
|
||||
|
||||
if (!player || !target || target->IsAlive())
|
||||
return;
|
||||
|
||||
|
||||
@@ -561,6 +561,17 @@ int64 SpellScript::GetItemTargetCountForEffect(SpellEffIndex effect) const
|
||||
return m_spell->GetItemTargetCountForEffect(effect);
|
||||
}
|
||||
|
||||
int64 SpellScript::GetCorpseTargetCountForEffect(SpellEffIndex effect) const
|
||||
{
|
||||
if (!IsAfterTargetSelectionPhase())
|
||||
{
|
||||
TC_LOG_ERROR("scripts", "Script: `%s` Spell: `%u`: function SpellScript::GetCorpseTargetCountForEffect was called, but function has no effect in current hook! (spell has not selected targets yet)",
|
||||
m_scriptName->c_str(), m_scriptSpellId);
|
||||
return 0;
|
||||
}
|
||||
return m_spell->GetCorpseTargetCountForEffect(effect);
|
||||
}
|
||||
|
||||
Unit* SpellScript::GetHitUnit() const
|
||||
{
|
||||
if (!IsInTargetHook())
|
||||
|
||||
@@ -486,6 +486,7 @@ class TC_GAME_API SpellScript : public _SpellScript
|
||||
int64 GetUnitTargetCountForEffect(SpellEffIndex effect) const;
|
||||
int64 GetGameObjectTargetCountForEffect(SpellEffIndex effect) const;
|
||||
int64 GetItemTargetCountForEffect(SpellEffIndex effect) const;
|
||||
int64 GetCorpseTargetCountForEffect(SpellEffIndex effect) const;
|
||||
|
||||
// methods useable only during spell hit on target, or during spell launch on target:
|
||||
// returns: target of current effect if it was Unit otherwise NULL
|
||||
|
||||
Reference in New Issue
Block a user