void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket) { uint32 spellId, glyphIndex; uint8 cast_count, cast_flags; recvPacket >> cast_count; recvPacket >> spellId >> glyphIndex; recvPacket >> cast_flags; // flags (if 0x02 - some additional data are received) // ignore for remote control state (for player case) Unit* _mover = GetPlayer()->GetMover(); if (_mover != GetPlayer() && _mover->GetTypeId()==TYPEID_PLAYER) { recvPacket.rpos(recvPacket.wpos()); // prevent spam at ignore packet return; } DEBUG_LOG("WORLD: got cast spell packet, spellId - %u, cast_count: %u, cast_flags %u, data length = " SIZEFMTD, spellId, cast_count, cast_flags, recvPacket.size()); /* process anticheat check */ if (!GetPlayer()->GetAntiCheat()->DoAntiCheatCheck(CHECK_SPELL, spellId, CMSG_CAST_SPELL)) return; SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId ); if(!spellInfo) { sLog.outError("WORLD: unknown spell id %u", spellId); recvPacket.rpos(recvPacket.wpos()); // prevent spam at ignore packet return; } // Players on vehicles may cast many simple spells (like knock) from self Unit* mover = NULL; if (spellInfo->HasAttribute(SPELL_ATTR_EX6_CASTABLE_ON_VEHICLE) && _mover->IsCharmerOrOwnerPlayerOrPlayerItself()) mover = _mover->GetCharmerOrOwnerPlayerOrPlayerItself(); else mover = _mover; // casting own spells on some vehicles if (mover->IsVehicle() && mover->GetCharmerOrOwnerPlayerOrPlayerItself()) { Player *plr = mover->GetCharmerOrOwnerPlayerOrPlayerItself(); if (mover->GetVehicleKit()->GetSeatInfo(plr) && ((mover->GetVehicleKit()->GetSeatInfo(plr)->m_flags & SEAT_FLAG_CAN_ATTACK) || (mover->GetVehicleKit()->GetSeatInfo(plr)->m_flags & SEAT_FLAG_CAN_CAST) )) mover = plr; } bool triggered = false; SpellEntry const* triggeredBy = NULL; Aura const* triggeredByAura = mover->GetTriggeredByClientAura(spellId); if (triggeredByAura) { triggered = true; triggeredBy = triggeredByAura->GetSpellProto(); cast_count = 0; } if (mover->GetTypeId()==TYPEID_PLAYER) { // not have spell in spellbook or spell passive and not casted by client if (((((Player*)mover)->GetUInt16Value(PLAYER_FIELD_BYTES2, 0) == 0 && (!((Player*)mover)->HasActiveSpell(spellId) && !triggered)) || IsPassiveSpell(spellInfo)) && spellId != 1843) { sLog.outError("WorldSession::HandleCastSpellOpcode: %s casts spell %u which he shouldn't have", mover->GetObjectGuid().GetString().c_str(), spellId); //cheater? kick? ban? recvPacket.rpos(recvPacket.wpos()); // prevent spam at ignore packet return; } } else { // not have spell in spellbook or spell passive and not casted by client if ((!((Creature*)mover)->HasSpell(spellId) && !triggered) || IsPassiveSpell(spellInfo)) { sLog.outError("WorldSession::HandleCastSpellOpcode: %s try casts spell %u which he shouldn't have", mover->GetObjectGuid().GetString().c_str(), spellId); //cheater? kick? ban? recvPacket.rpos(recvPacket.wpos()); // prevent spam at ignore packet return; } } Unit::AuraList swaps = mover->GetAurasByType(SPELL_AURA_OVERRIDE_ACTIONBAR_SPELLS); Unit::AuraList const& swaps2 = mover->GetAurasByType(SPELL_AURA_OVERRIDE_ACTIONBAR_SPELLS_2); if (!swaps2.empty()) swaps.insert(swaps.end(), swaps2.begin(), swaps2.end()); for (Unit::AuraList::const_iterator itr = swaps.begin(); itr != swaps.end(); ++itr) { if ((*itr)->isAffectedOnSpell(spellInfo)) { if (SpellEntry const* newInfo = sSpellStore.LookupEntry((*itr)->GetModifier()->m_amount)) { spellInfo = newInfo; spellId = newInfo->Id; } break; } } // client provided targets SpellCastTargets targets; recvPacket >> targets.ReadForCaster(mover); targets.ReadAdditionalData(recvPacket, cast_flags); // auto-selection buff level base at target level (in spellInfo) if (Unit* target = targets.getUnitTarget()) { // if rank not found then function return NULL but in explicit cast case original spell can be casted and later failed with appropriate error message if (SpellEntry const *actualSpellInfo = sSpellMgr.SelectAuraRankForLevel(spellInfo, target->getLevel())) spellInfo = actualSpellInfo; } Spell *spell = new Spell(mover, spellInfo, triggered, mover->GetObjectGuid(), triggeredBy); spell->m_cast_count = cast_count; // set count of casts spell->m_glyphIndex = glyphIndex; spell->prepare(&targets, triggeredByAura); }
void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket) { uint32 spellId, glyphIndex; uint8 cast_count, cast_flags; recvPacket >> cast_count; recvPacket >> spellId >> glyphIndex; recvPacket >> cast_flags; // flags (if 0x02 - some additional data are received) // ignore for remote control state (for player case) Unit* _mover = GetPlayer()->GetMover(); if (_mover != GetPlayer() && _mover->GetTypeId()==TYPEID_PLAYER) { recvPacket.rpos(recvPacket.wpos()); // prevent spam at ignore packet return; } DEBUG_LOG("WORLD: got cast spell packet, spellId - %u, cast_count: %u, cast_flags %u, data length = " SIZEFMTD, spellId, cast_count, cast_flags, recvPacket.size()); /* process anticheat check */ if (!GetPlayer()->GetAntiCheat()->DoAntiCheatCheck(CHECK_SPELL, spellId, CMSG_CAST_SPELL)) return; SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId ); if(!spellInfo) { sLog.outError("WORLD: unknown spell id %u", spellId); recvPacket.rpos(recvPacket.wpos()); // prevent spam at ignore packet return; } // Players on vehicles may cast many simple spells (like knock) from self Unit* mover = NULL; if (spellInfo->HasAttribute(SPELL_ATTR_EX6_CASTABLE_ON_VEHICLE) && _mover->IsCharmerOrOwnerPlayerOrPlayerItself()) mover = _mover->GetCharmerOrOwnerPlayerOrPlayerItself(); else mover = _mover; // casting own spells on some vehicles if (Player* plr = mover->GetCharmerOrOwnerPlayerOrPlayerItself()) { if (mover->IsVehicle() && (mover != plr)) { if (VehicleKitPtr vehicle = mover->GetVehicleKit()) { if (VehicleSeatEntry const* seatInfo = vehicle->GetSeatInfo(plr)) if (seatInfo->m_flags & (SEAT_FLAG_CAN_ATTACK | SEAT_FLAG_CAN_CAST)) mover = plr; } } } bool triggered = false; SpellEntry const* triggeredBy = NULL; Aura const* triggeredByAura = mover->GetTriggeredByClientAura(spellId); if (triggeredByAura) { triggered = true; triggeredBy = triggeredByAura->GetSpellProto(); cast_count = 0; } Unit::AuraList const& m363auras = mover->GetAurasByType(SPELL_AURA_363); for (Unit::AuraList::const_iterator itr = m363auras.begin(); itr != m363auras.end(); ++itr) { if ((*itr)->GetSpellEffect()->EffectTriggerSpell == spellId) { triggered = true; mover->RemoveSpellAuraHolder((*itr)->GetHolder()); break; } } if (!spellInfo->HasAttribute(SPELL_ATTR_EX8_RAID_MARKER)) { if (mover->GetTypeId()==TYPEID_PLAYER) { // not have spell in spellbook or spell passive and not casted by client if ((!((Player*)mover)->HasActiveSpell(spellId) && !triggered || IsPassiveSpell(spellInfo)) && !sSpellMgr.IsAbilityOfSkillType(spellInfo, SKILL_ARCHAEOLOGY)) { sLog.outError("WorldSession::HandleCastSpellOpcode: %s casts spell %u which he shouldn't have", mover->GetObjectGuid().GetString().c_str(), spellId); //cheater? kick? ban? recvPacket.rpos(recvPacket.wpos()); // prevent spam at ignore packet return; } } else { // not have spell in spellbook or spell passive and not casted by client if (!((Creature*)mover)->HasSpell(spellId) && !triggered || IsPassiveSpell(spellInfo)) { sLog.outError("World: Player %u casts spell %u which he shouldn't have", mover->GetGUIDLow(), spellId); //cheater? kick? ban? recvPacket.rpos(recvPacket.wpos()); // prevent spam at ignore packet return; } } } Unit::AuraList swaps = _mover->GetAurasByType(SPELL_AURA_OVERRIDE_ACTIONBAR_SPELLS); Unit::AuraList const& swaps2 = _mover->GetAurasByType(SPELL_AURA_OVERRIDE_ACTIONBAR_SPELLS_2); if (!swaps2.empty()) swaps.insert(swaps.end(), swaps2.begin(), swaps2.end()); for (Unit::AuraList::const_iterator itr = swaps.begin(); itr != swaps.end(); ++itr) { if ((*itr)->isAffectedOnSpell(spellInfo)) { if (SpellEntry const* newInfo = sSpellStore.LookupEntry((*itr)->GetModifier()->m_amount)) { spellInfo = newInfo; spellId = newInfo->Id; // Force triggered to spells mirrored by Dark Simulacrum if ((*itr)->GetId() == 77616) triggered = true; } break; } } // Lifebloom if (spellId == 33763) { // search Tree of Life (Passive) if (Aura* aura = _mover->GetAura(81098, EFFECT_INDEX_1)) { if (SpellEntry const* newInfo = sSpellStore.LookupEntry(aura->GetModifier()->m_amount)) { spellInfo = newInfo; spellId = newInfo->Id; } } } // client provided targets SpellCastTargets targets; recvPacket >> targets.ReadForCaster(mover); targets.ReadAdditionalData(recvPacket, cast_flags); // Multi-Shot hack if (!targets.getUnitTarget() && spellId == 2643) { if (Unit* target = _player->GetMap()->GetUnit(_player->GetSelectionGuid())) targets.setUnitTarget(target); } // auto-selection buff level base at target level (in spellInfo) if (Unit* target = targets.getUnitTarget()) { // if rank not found then function return NULL but in explicit cast case original spell can be casted and later failed with appropriate error message if (SpellEntry const *actualSpellInfo = sSpellMgr.SelectAuraRankForLevel(spellInfo, target->getLevel())) spellInfo = actualSpellInfo; } Spell *spell = new Spell(mover, spellInfo, triggered, mover->GetObjectGuid(), triggeredBy); spell->m_cast_count = cast_count; // set count of casts spell->m_glyphIndex = glyphIndex; spell->prepare(&targets, triggeredByAura); }
void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket) { uint32 spellId, glyphIndex; uint8 cast_count, cast_flags; recvPacket >> cast_count; recvPacket >> spellId >> glyphIndex; recvPacket >> cast_flags; // flags (if 0x02 - some additional data are received) // ignore for remote control state (for player case) Unit* mover = _player->GetMover(); if (mover != _player && mover->GetTypeId() == TYPEID_PLAYER) { recvPacket.rpos(recvPacket.wpos()); // prevent spam at ignore packet return; } DEBUG_LOG("WORLD: got cast spell packet, spellId - %u, cast_count: %u, cast_flags %u, data length = " SIZEFMTD, spellId, cast_count, cast_flags, recvPacket.size()); SpellEntry const* spellInfo = sSpellStore.LookupEntry(spellId); if (!spellInfo) { sLog.outError("WORLD: unknown spell id %u", spellId); recvPacket.rpos(recvPacket.wpos()); // prevent spam at ignore packet return; } Aura* triggeredByAura = mover->GetTriggeredByClientAura(spellId); if (mover->GetTypeId() == TYPEID_PLAYER) { // not have spell in spellbook or spell passive and not casted by client if ((!((Player*)mover)->HasActiveSpell(spellId) && !triggeredByAura) || IsPassiveSpell(spellInfo)) { sLog.outError("World: %s casts spell %u which he shouldn't have", mover->GetGuidStr().c_str(), spellId); // cheater? kick? ban? recvPacket.rpos(recvPacket.wpos()); // prevent spam at ignore packet return; } } else { // not have spell in spellbook or spell passive and not casted by client if (!((Creature*)mover)->HasSpell(spellId) || IsPassiveSpell(spellInfo)) { // cheater? kick? ban? recvPacket.rpos(recvPacket.wpos()); // prevent spam at ignore packet return; } } Unit::AuraList swaps = mover->GetAurasByType(SPELL_AURA_OVERRIDE_ACTIONBAR_SPELLS); Unit::AuraList const& swaps2 = mover->GetAurasByType(SPELL_AURA_OVERRIDE_ACTIONBAR_SPELLS_2); if (!swaps2.empty()) swaps.insert(swaps.end(), swaps2.begin(), swaps2.end()); for (Unit::AuraList::const_iterator itr = swaps.begin(); itr != swaps.end(); ++itr) { if ((*itr)->isAffectedOnSpell(spellInfo)) { if (SpellEntry const* newInfo = sSpellStore.LookupEntry((*itr)->GetModifier()->m_amount)) { spellInfo = newInfo; spellId = newInfo->Id; } break; } } // client provided targets SpellCastTargets targets; recvPacket >> targets.ReadForCaster(mover); targets.ReadAdditionalData(recvPacket, cast_flags); // auto-selection buff level base at target level (in spellInfo) if (Unit* target = targets.getUnitTarget()) { // if rank not found then function return NULL but in explicit cast case original spell can be casted and later failed with appropriate error message if (SpellEntry const* actualSpellInfo = sSpellMgr.SelectAuraRankForLevel(spellInfo, target->getLevel())) spellInfo = actualSpellInfo; } Spell* spell = new Spell(mover, spellInfo, triggeredByAura ? true : false, mover->GetObjectGuid(), triggeredByAura ? triggeredByAura->GetSpellProto() : NULL); spell->m_cast_count = cast_count; // set count of casts spell->m_glyphIndex = glyphIndex; spell->prepare(&targets, triggeredByAura); }