From 708710e109c40f8267cc53c51e9c331bed82e86e Mon Sep 17 00:00:00 2001 From: Shauren Date: Sun, 9 Jul 2023 14:45:49 +0200 Subject: [PATCH] Core/Spells: Corrected client control checks in spell packets Closes #26510 Closes #27863 (cherry picked from commit 0a34290484f3e90a2a642986de682a8b0c7e3815) --- src/server/game/Handlers/SpellHandler.cpp | 44 ++++++++--------------- src/server/game/Spells/Spell.cpp | 12 ++----- 2 files changed, 16 insertions(+), 40 deletions(-) diff --git a/src/server/game/Handlers/SpellHandler.cpp b/src/server/game/Handlers/SpellHandler.cpp index 574a52b00f..319e5db0b1 100644 --- a/src/server/game/Handlers/SpellHandler.cpp +++ b/src/server/game/Handlers/SpellHandler.cpp @@ -48,10 +48,6 @@ void WorldSession::HandleUseItemOpcode(WorldPackets::Spells::UseItem& packet) { - // ignore for remote control state - if (_player->GetUnitBeingMoved() != _player) - return; - // Skip casting invalid spells right away SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(packet.Cast.SpellID, _player->GetMap()->GetDifficultyID()); if (!spellInfo) @@ -71,8 +67,9 @@ void WorldSession::HandleOpenItemOpcode(WorldPackets::Spells::OpenItem& packet) Player* player = GetPlayer(); // ignore for remote control state - if (player->GetUnitBeingMoved() != player) + if (player->IsCharmed()) return; + TC_LOG_INFO("network", "bagIndex: {}, slot: {}", packet.Slot, packet.PackSlot); // additional check, client outputs message on its own @@ -205,8 +202,8 @@ void WorldSession::HandleGameObjectUseOpcode(WorldPackets::GameObject::GameObjUs if (GameObject* obj = GetPlayer()->GetGameObjectIfCanInteractWith(packet.Guid)) { // ignore for remote control state - if (GetPlayer()->GetUnitBeingMoved() != GetPlayer()) - if (!(GetPlayer()->IsOnVehicle(GetPlayer()->GetUnitBeingMoved()) || GetPlayer()->IsMounted()) && !obj->GetGOInfo()->IsUsableMounted()) + if (GetPlayer()->IsCharmed()) + if (!(GetPlayer()->IsOnVehicle(GetPlayer()->GetCharmed()) || GetPlayer()->IsMounted()) && !obj->GetGOInfo()->IsUsableMounted()) return; obj->Use(GetPlayer()); @@ -216,7 +213,7 @@ void WorldSession::HandleGameObjectUseOpcode(WorldPackets::GameObject::GameObjUs void WorldSession::HandleGameobjectReportUse(WorldPackets::GameObject::GameObjReportUse& packet) { // ignore for remote control state - if (_player->GetUnitBeingMoved() != _player) + if (_player->IsCharmed()) return; if (GameObject* go = GetPlayer()->GetGameObjectIfCanInteractWith(packet.Guid)) @@ -238,33 +235,20 @@ void WorldSession::HandleCastSpellOpcode(WorldPackets::Spells::CastSpell& castRe return; } - // ignore for remote control state (for player case) - Unit* mover = _player->GetUnitBeingMoved(); - if (mover != _player && mover->GetTypeId() == TYPEID_PLAYER) - return; - - Unit* castingUnit = mover; - if (castingUnit->IsCreature() && !castingUnit->ToCreature()->HasSpell(spellInfo->Id)) - { - // If the vehicle creature does not have the spell but it allows the passenger to cast own spells - // change caster to player and let him cast - if (!_player->IsOnVehicle(castingUnit) || spellInfo->CheckVehicle(_player) != SPELL_CAST_OK) - return; - - castingUnit = _player; - } - if (castRequest.Cast.MoveUpdate.has_value()) HandleMovementOpcode(CMSG_MOVE_STOP, *castRequest.Cast.MoveUpdate); - if (_player->CanRequestSpellCast(spellInfo, castingUnit)) - _player->RequestSpellCast(std::make_unique(std::move(castRequest.Cast), castingUnit->GetGUID())); + if (_player->CanRequestSpellCast(spellInfo, _player)) + _player->RequestSpellCast(std::make_unique(std::move(castRequest.Cast), _player->GetGUID())); else Spell::SendCastResult(_player, spellInfo, {}, castRequest.Cast.CastID, SPELL_FAILED_SPELL_IN_PROGRESS); } void WorldSession::HandleCancelCastOpcode(WorldPackets::Spells::CancelCast& packet) { + if (_player->IsCharmed()) + return; + if (_player->IsNonMeleeSpellCast(false)) { _player->InterruptNonMeleeSpells(false, packet.SpellID, false); @@ -378,7 +362,7 @@ void WorldSession::HandleCancelChanneling(WorldPackets::Spells::CancelChannellin { // ignore for remote control state (for player case) Unit* mover = _player->GetUnitBeingMoved(); - if (mover != _player && mover->GetTypeId() == TYPEID_PLAYER) + if (!mover) return; SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(cancelChanneling.ChannelSpell, mover->GetMap()->GetDifficultyID()); @@ -405,7 +389,7 @@ void WorldSession::HandleSpellEmpowerRelease(WorldPackets::Spells::SpellEmpowerR { // ignore for remote control state (for player case) Unit* mover = _player->GetUnitBeingMoved(); - if (mover != _player && mover->GetTypeId() == TYPEID_PLAYER) + if (!mover) return; Spell* spell = mover->GetCurrentSpell(CURRENT_CHANNELED_SPELL); @@ -419,7 +403,7 @@ void WorldSession::HandleSpellEmpowerRestart(WorldPackets::Spells::SpellEmpowerR { // ignore for remote control state (for player case) Unit* mover = _player->GetUnitBeingMoved(); - if (mover != _player && mover->GetTypeId() == TYPEID_PLAYER) + if (!mover) return; Spell* spell = mover->GetCurrentSpell(CURRENT_CHANNELED_SPELL); @@ -432,7 +416,7 @@ void WorldSession::HandleSpellEmpowerRestart(WorldPackets::Spells::SpellEmpowerR void WorldSession::HandleTotemDestroyed(WorldPackets::Totem::TotemDestroyed& totemDestroyed) { // ignore for remote control state - if (_player->GetUnitBeingMoved() != _player) + if (_player->IsCharmed()) return; uint8 slotId = totemDestroyed.Slot; diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index fd241174fc..31b7e412d5 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -6958,16 +6958,8 @@ SpellCastResult Spell::CheckCasterAuras(int32* param1) const // Get unit state uint32 const unitflag = unitCaster->m_unitData->Flags; - // this check should only be done when player does cast directly - // (ie not when it's called from a script) Breaks for example PlayerAI when charmed - /* - if (!unitCaster->GetCharmerGUID().IsEmpty()) - { - if (Unit* charmer = unitCaster->GetCharmer()) - if (charmer->GetUnitBeingMoved() != unitCaster && !CheckSpellCancelsCharm(param1)) - result = SPELL_FAILED_CHARMED; - } - */ + if (m_fromClient && unitCaster->IsCharmed() && unitCaster->IsPlayer() && !CheckSpellCancelsCharm(param1)) + result = SPELL_FAILED_CHARMED; // spell has attribute usable while having a cc state, check if caster has allowed mechanic auras, another mechanic types must prevent cast spell auto mechanicCheck = [&](AuraType type) -> SpellCastResult