diff options
author | Giacomo Pozzoni <giacomopoz@gmail.com> | 2020-06-29 21:03:03 +0000 |
---|---|---|
committer | Shauren <shauren.trinity@gmail.com> | 2022-01-20 00:13:02 +0100 |
commit | 8f4db9aa6919e2b3b22ec21ffea4eacb605e9bc2 (patch) | |
tree | 9863a03c733072d6c7f8ab4125e8e683f72c3d6b /src | |
parent | b9666481bbf943000c6c925c3287c1e1c9a94e7f (diff) |
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 commit df193945d9aff8596985a20e2c654105354b0af7)
* Core/Spells: implement TARGET_CORPSE_SRC_AREA_RAID and updated remaining resurrection effect handlers for updated corpse targeting
(cherry picked from commit 98b075cb4b0da126d409ab42daa63a1f531a70ea)
* Fix no-pch
Co-authored-by: Ovahlord <dreadkiller@gmx.de>
(cherry picked from commit cc71da35b5dc74abf71f8691161525a23d870bb5)
Diffstat (limited to 'src')
-rw-r--r-- | src/server/game/Spells/Spell.cpp | 161 | ||||
-rw-r--r-- | src/server/game/Spells/Spell.h | 14 | ||||
-rw-r--r-- | src/server/game/Spells/SpellEffects.cpp | 60 | ||||
-rw-r--r-- | src/server/game/Spells/SpellScript.cpp | 11 | ||||
-rw-r--r-- | src/server/game/Spells/SpellScript.h | 1 |
5 files changed, 198 insertions, 49 deletions
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 9e1158407f0..e6e5e552767 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -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; diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h index aa4de827863..b8ef1260655 100644 --- a/src/server/game/Spells/Spell.h +++ b/src/server/game/Spells/Spell.h @@ -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); diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index b216bb5f372..01ea58864e8 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -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) - return; + Player* player = nullptr; - if (!unitTarget->IsInWorld()) - return; + if (corpseTarget) + player = ObjectAccessor::FindPlayer(corpseTarget->GetOwnerGUID()); + else if (unitTarget) + player = unitTarget->ToPlayer(); - Player* target = unitTarget->ToPlayer(); + if (!player || player->IsAlive() || !player->IsInWorld()) + return; - 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()) - return; + Player* player = nullptr; - Player* target = unitTarget->ToPlayer(); + if (corpseTarget) + player = ObjectAccessor::FindPlayer(corpseTarget->GetOwnerGUID()); + else if (unitTarget) + player = unitTarget->ToPlayer(); - if (target->IsResurrectRequested()) // already have one active request + if (!player || player->IsAlive() || !player->IsInWorld()) return; - uint32 health = target->CountPctFromMaxHealth(damage); - uint32 mana = CalculatePct(target->GetMaxPower(POWER_MANA), damage); + if (player->IsResurrectRequested()) // already have one active request + return; - ExecuteLogEffectResurrect(SpellEffectName(effectInfo->Effect), target); + uint32 health = player->CountPctFromMaxHealth(damage); + uint32 mana = CalculatePct(player->GetMaxPower(POWER_MANA), damage); - 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::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; diff --git a/src/server/game/Spells/SpellScript.cpp b/src/server/game/Spells/SpellScript.cpp index 2941b1400e6..69e7da62a73 100644 --- a/src/server/game/Spells/SpellScript.cpp +++ b/src/server/game/Spells/SpellScript.cpp @@ -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()) diff --git a/src/server/game/Spells/SpellScript.h b/src/server/game/Spells/SpellScript.h index 16724dc3fa0..28d4e103a1d 100644 --- a/src/server/game/Spells/SpellScript.h +++ b/src/server/game/Spells/SpellScript.h @@ -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 |