aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server/game/Entities/Player/Player.cpp3
-rw-r--r--src/server/game/Handlers/PetHandler.cpp1
-rw-r--r--src/server/game/Handlers/SpellHandler.cpp54
-rw-r--r--src/server/game/Spells/Spell.cpp29
-rw-r--r--src/server/game/Spells/Spell.h1
5 files changed, 31 insertions, 57 deletions
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index c08aeb7ba7f..7cf2edefaab 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -8081,6 +8081,7 @@ void Player::CastItemUseSpell(Item* item, SpellCastTargets const& targets, uint8
}
Spell* spell = new Spell(this, spellInfo, TRIGGERED_NONE);
+ spell->m_fromClient = true;
spell->m_CastItem = item;
spell->m_cast_count = cast_count; //set count of casts
spell->SetSpellValue(SPELLVALUE_BASE_POINT0, learning_spell_id);
@@ -8109,6 +8110,7 @@ void Player::CastItemUseSpell(Item* item, SpellCastTargets const& targets, uint8
}
Spell* spell = new Spell(this, spellInfo, TRIGGERED_NONE);
+ spell->m_fromClient = true;
spell->m_CastItem = item;
spell->m_cast_count = cast_count; // set count of casts
spell->m_glyphIndex = glyphIndex; // glyph index
@@ -8136,6 +8138,7 @@ void Player::CastItemUseSpell(Item* item, SpellCastTargets const& targets, uint8
}
Spell* spell = new Spell(this, spellInfo, TRIGGERED_NONE);
+ spell->m_fromClient = true;
spell->m_CastItem = item;
spell->m_cast_count = cast_count; // set count of casts
spell->m_glyphIndex = glyphIndex; // glyph index
diff --git a/src/server/game/Handlers/PetHandler.cpp b/src/server/game/Handlers/PetHandler.cpp
index a068faff376..68d3c77be6b 100644
--- a/src/server/game/Handlers/PetHandler.cpp
+++ b/src/server/game/Handlers/PetHandler.cpp
@@ -799,6 +799,7 @@ void WorldSession::HandlePetCastSpellOpcode(WorldPacket& recvPacket)
}
Spell* spell = new Spell(caster, spellInfo, triggerCastFlags);
+ spell->m_fromClient = true;
spell->m_cast_count = castCount; // probably pending spell cast
spell->m_targets = targets;
diff --git a/src/server/game/Handlers/SpellHandler.cpp b/src/server/game/Handlers/SpellHandler.cpp
index 3991676dca9..62921828e5a 100644
--- a/src/server/game/Handlers/SpellHandler.cpp
+++ b/src/server/game/Handlers/SpellHandler.cpp
@@ -67,10 +67,6 @@ void WorldSession::HandleUseItemOpcode(WorldPacket& recvPacket)
/// @todo add targets.read() check
Player* pUser = _player;
- // ignore for remote control state
- if (pUser->IsCharming())
- return;
-
uint8 bagIndex, slot, castFlags;
uint8 castCount; // next cast if exists (single or not)
ObjectGuid itemGUID;
@@ -179,7 +175,7 @@ void WorldSession::HandleOpenItemOpcode(WorldPacket& recvPacket)
Player* player = GetPlayer();
// ignore for remote control state
- if (player->IsCharming())
+ if (player->IsCharmed())
return;
// additional check, client outputs message on its own
@@ -299,7 +295,7 @@ void WorldSession::HandleGameObjectUseOpcode(WorldPacket& recvData)
if (GameObject* obj = GetPlayer()->GetGameObjectIfCanInteractWith(guid))
{
// ignore for remote control state
- if (GetPlayer()->IsCharming())
+ if (GetPlayer()->IsCharmed())
if (!(GetPlayer()->IsOnVehicle(GetPlayer()->GetCharmed()) || GetPlayer()->IsMounted()) && !obj->GetGOInfo()->IsUsableMounted())
return;
@@ -315,7 +311,7 @@ void WorldSession::HandleGameobjectReportUse(WorldPacket& recvPacket)
TC_LOG_DEBUG("network", "WORLD: Recvd CMSG_GAMEOBJ_REPORT_USE Message [%s]", guid.ToString().c_str());
// ignore for remote control state
- if (_player->IsCharming())
+ if (_player->IsCharmed())
return;
if (GameObject* go = GetPlayer()->GetGameObjectIfCanInteractWith(guid))
@@ -336,14 +332,6 @@ void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket)
TC_LOG_DEBUG("network", "WORLD: got cast spell packet, castCount: %u, spellId: %u, castFlags: %u, data length = %u", castCount, spellId, castFlags, (uint32)recvPacket.size());
- // ignore for remote control state (for player case)
- Unit* mover = GetGameClient()->GetActivelyMovedUnit();
- if (!mover || (mover != _player && mover->GetTypeId() == TYPEID_PLAYER))
- {
- recvPacket.rfinish(); // prevent spam at ignore packet
- return;
- }
-
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId);
if (!spellInfo)
{
@@ -358,37 +346,23 @@ void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket)
return;
}
- Unit* caster = mover;
- if (caster->GetTypeId() == TYPEID_UNIT && !caster->ToCreature()->HasSpell(spellId))
- {
- // 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(caster) || spellInfo->CheckVehicle(_player) != SPELL_CAST_OK)
- {
- recvPacket.rfinish(); // prevent spam at ignore packet
- return;
- }
-
- caster = _player;
- }
-
// client provided targets
SpellCastTargets targets;
- targets.Read(recvPacket, caster);
+ targets.Read(recvPacket, _player);
HandleClientCastFlags(recvPacket, castFlags, targets);
// not have spell in spellbook
- if (caster->GetTypeId() == TYPEID_PLAYER && !caster->ToPlayer()->HasActiveSpell(spellId))
+ if (_player->GetTypeId() == TYPEID_PLAYER && !_player->ToPlayer()->HasActiveSpell(spellId))
{
bool allow = false;
// allow casting of unknown spells for special lock cases
if (GameObject *go = targets.GetGOTarget())
- if (go->GetSpellForLock(caster->ToPlayer()) == spellInfo)
+ if (go->GetSpellForLock(_player->ToPlayer()) == spellInfo)
allow = true;
// allow casting of spells triggered by clientside periodic trigger auras
- if (caster->HasAuraTypeWithTriggerSpell(SPELL_AURA_PERIODIC_TRIGGER_SPELL_FROM_CLIENT, spellId))
+ if (_player->HasAuraTypeWithTriggerSpell(SPELL_AURA_PERIODIC_TRIGGER_SPELL_FROM_CLIENT, spellId))
{
allow = true;
triggerFlag = TRIGGERED_FULL_MASK;
@@ -398,16 +372,12 @@ void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket)
return;
}
- // can't use our own spells when we're in possession of another unit,
- if (_player->isPossessing())
- return;
-
// Client is resending autoshot cast opcode when other spell is cast during shoot rotation
// Skip it to prevent "interrupt" message
// Also check targets! target may have changed and we need to interrupt current spell
if (spellInfo->IsAutoRepeatRangedSpell())
{
- if (Spell* spell = caster->GetCurrentSpell(CURRENT_AUTOREPEAT_SPELL))
+ if (Spell* spell = _player->GetCurrentSpell(CURRENT_AUTOREPEAT_SPELL))
{
if (spell->m_spellInfo == spellInfo && spell->m_targets.GetUnitTargetGUID() == targets.GetUnitTargetGUID())
{
@@ -429,13 +399,17 @@ void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket)
spellInfo = actualSpellInfo;
}
- Spell* spell = new Spell(caster, spellInfo, triggerFlag);
+ Spell* spell = new Spell(_player, spellInfo, triggerFlag);
+ spell->m_fromClient = true;
spell->m_cast_count = castCount; // set count of casts
spell->prepare(targets);
}
void WorldSession::HandleCancelCastOpcode(WorldPackets::Spells::CancelCast& cancelCast)
{
+ if (_player->IsCharmed())
+ return;
+
if (_player->IsNonMeleeSpellCast(false))
_player->InterruptNonMeleeSpells(false, cancelCast.SpellID, false);
}
@@ -571,7 +545,7 @@ void WorldSession::HandleCancelChanneling(WorldPackets::Spells::CancelChannellin
void WorldSession::HandleTotemDestroyed(WorldPackets::Totem::TotemDestroyed& totemDestroyed)
{
// ignore for remote control state
- if (_player->IsCharming())
+ 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 dfdc492b0eb..ecc4855eacd 100644
--- a/src/server/game/Spells/Spell.cpp
+++ b/src/server/game/Spells/Spell.cpp
@@ -504,6 +504,7 @@ m_caster((info->HasAttribute(SPELL_ATTR6_CAST_BY_CHARMER) && caster->GetCharmerO
, m_spellValue(new SpellValue(m_spellInfo)), _spellEvent(nullptr)
{
m_customError = SPELL_CUSTOM_ERROR_NONE;
+ m_fromClient = false;
m_selfContainer = nullptr;
m_referencedFromCurrentSpell = false;
m_executedCurrently = false;
@@ -4170,7 +4171,7 @@ void Spell::SendSpellStart()
if (schoolImmunityMask || mechanicImmunityMask)
castFlags |= CAST_FLAG_IMMUNITY;
- if (((IsTriggered() && !m_spellInfo->IsAutoRepeatRangedSpell()) || m_triggeredByAuraSpell) && !m_cast_count)
+ if (((IsTriggered() && !m_spellInfo->IsAutoRepeatRangedSpell()) || m_triggeredByAuraSpell) && !m_fromClient)
castFlags |= CAST_FLAG_PENDING;
if (m_spellInfo->HasAttribute(SPELL_ATTR0_REQ_AMMO) || m_spellInfo->HasAttribute(SPELL_ATTR0_CU_NEEDS_AMMO_DATA))
@@ -4227,7 +4228,7 @@ void Spell::SendSpellGo()
uint32 castFlags = CAST_FLAG_UNKNOWN_9;
// triggered spells with spell visual != 0
- if (((IsTriggered() && !m_spellInfo->IsAutoRepeatRangedSpell()) || m_triggeredByAuraSpell) && !m_cast_count)
+ if (((IsTriggered() && !m_spellInfo->IsAutoRepeatRangedSpell()) || m_triggeredByAuraSpell) && !m_fromClient)
castFlags |= CAST_FLAG_PENDING;
if (m_spellInfo->HasAttribute(SPELL_ATTR0_REQ_AMMO) || m_spellInfo->HasAttribute(SPELL_ATTR0_CU_NEEDS_AMMO_DATA))
@@ -4318,10 +4319,9 @@ void Spell::SendSpellGo()
}
// should be sent to self only
- if (castFlags & CAST_FLAG_POWER_LEFT_SELF)
+ if (castFlags & CAST_FLAG_POWER_LEFT_SELF && m_caster->IsPlayer())
{
- if (Player* player = m_caster->GetAffectingPlayer())
- player->SendDirectMessage(packet.Write());
+ m_caster->ToPlayer()->SendDirectMessage(packet.Write());
packet.Clear();
@@ -5221,6 +5221,9 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint
return SPELL_FAILED_MOVING;
}
+ if (unitCaster->IsCharmed() && m_spellInfo->HasAttribute(SPELL_ATTR5_NOT_USABLE_WHILE_CHARMED))
+ return SPELL_FAILED_CHARMED;
+
// Check vehicle flags
if (!(_triggeredCastFlags & TRIGGERED_IGNORE_CASTER_MOUNTED_OR_ON_VEHICLE))
{
@@ -5931,7 +5934,7 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint
return SPELL_FAILED_NO_PET;
if (pet->GetCharmerGUID())
- return SPELL_FAILED_CHARMED;
+ return SPELL_FAILED_ALREADY_HAVE_CHARM;
break;
}
case SPELL_AURA_MOD_POSSESS:
@@ -5964,7 +5967,7 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint
return SPELL_FAILED_CANT_BE_CHARMED;
if (target->GetCharmerGUID())
- return SPELL_FAILED_CHARMED;
+ return SPELL_FAILED_CANT_BE_CHARMED;
if (target->GetOwner() && target->GetOwner()->GetTypeId() == TYPEID_PLAYER)
return SPELL_FAILED_TARGET_IS_PLAYER_CONTROLLED;
@@ -6170,16 +6173,8 @@ SpellCastResult Spell::CheckCasterAuras(uint32* param1) const
// Get unit state
uint32 const unitflag = unitCaster->GetUnitFlags();
- // 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())
- {
- if (Unit* charmer = unitCaster->GetCharmer())
- if (charmer->GetCharmed() != 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
diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h
index f71c8829164..3359bf6d730 100644
--- a/src/server/game/Spells/Spell.h
+++ b/src/server/game/Spells/Spell.h
@@ -394,6 +394,7 @@ class TC_GAME_API Spell
ObjectGuid m_castItemGUID;
uint32 m_castItemEntry;
uint8 m_cast_count;
+ bool m_fromClient;
uint32 m_glyphIndex;
SpellCastTargets m_targets;