void WorldSession::HandlePetSpellAutocastOpcode( WorldPacket& recvPacket )
{
DETAIL_LOG("CMSG_PET_SPELL_AUTOCAST");
uint64 guid;
uint32 spellid;
uint8 state; //1 for on, 0 for off
recvPacket >> guid >> spellid >> state;
if (!_player->GetPet() && !_player->GetCharm())
return;
if (ObjectAccessor::FindPlayer(guid))
return;
Creature* pet=ObjectAccessor::GetCreatureOrPetOrVehicle(*_player,guid);
if (!pet || (pet != _player->GetPet() && pet != _player->GetCharm()))
{
sLog.outError( "HandlePetSpellAutocastOpcode.Pet %u isn't pet of player %s .", uint32(GUID_LOPART(guid)),GetPlayer()->GetName() );
return;
}
// do not add not learned spells/ passive spells
if (!pet->HasSpell(spellid) || IsPassiveSpell(spellid))
return;
CharmInfo *charmInfo = pet->GetCharmInfo();
if (!charmInfo)
{
sLog.outError("WorldSession::HandlePetSpellAutocastOpcod: object (GUID: %u TypeId: %u) is considered pet-like but doesn't have a charminfo!", pet->GetGUIDLow(), pet->GetTypeId());
return;
}
if (pet->isCharmed())
//state can be used as boolean
pet->GetCharmInfo()->ToggleCreatureAutocast(spellid, state);
else
((Pet*)pet)->ToggleAutocast(spellid, state);
charmInfo->SetSpellAutocast(spellid,state);
}
void WorldSession::HandleCancelAuraOpcode(WorldPacket& recvPacket)
{
uint32 spellId;
recvPacket >> spellId;
SpellEntry const* spellInfo = sSpellStore.LookupEntry(spellId);
if (!spellInfo)
return;
// not allow remove non positive spells and spells with attr SPELL_ATTR_CANT_CANCEL
if (spellInfo->Attributes & SPELL_ATTR0_CANT_CANCEL)
return;
// channeled spell case (it currently casted then)
if (IsChanneledSpell(spellInfo))
{
if (Spell* spell = _player->GetCurrentSpell(CURRENT_CHANNELED_SPELL))
{
if (spell->m_spellInfo->Id == spellId)
spell->cancel();
}
return;
}
// non channeled case:
// don't allow remove non positive spells
// don't allow cancelling passive auras (some of them are visible)
if (!IsPositiveSpell(spellId) || IsPassiveSpell(spellId))
return;
// non channeled case
if (!IsPositiveSpell(spellId))
return;
_player->RemoveAurasDueToSpellByCancel(spellId);
}
void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket)
{
uint32 spellId;
recvPacket >> spellId;
// 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, data length = " SIZEFMTD,
spellId, 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;
}
if (mover->GetTypeId() == TYPEID_PLAYER)
{
// not have spell in spellbook or spell passive and not casted by client
if (!((Player*)mover)->HasActiveSpell(spellId) || 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;
}
}
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;
}
}
// client provided targets
SpellCastTargets targets;
recvPacket >> targets.ReadForCaster(_player);
// auto-selection buff level base at target level (in spellInfo)
if (Unit* target = targets.getUnitTarget())
{
// if rank not found then function return nullptr but in explicit cast case original spell can be casted and later failed with appropriate error message
if (SpellEntry const* actualSpellInfo = sSpellMgr.SelectAuraRankForLevel(spellInfo, _player, target))
spellInfo = actualSpellInfo;
}
Spell* spell = new Spell(_player, spellInfo, false);
spell->SpellStart(&targets);
}
//.........这里部分代码省略.........
if (pet->GetTypeId() == TYPEID_UNIT)
pet->ToCreature()->SetReactState(ReactStates(spellid));
break;
}
break;
case ACT_DISABLED: // 0x81 spell (disabled), ignore
case ACT_PASSIVE: // 0x01
case ACT_ENABLED: // 0xC1 spell
{
Unit* unit_target = NULL;
if (guid2)
unit_target = ObjectAccessor::GetUnit(*_player,guid2);
// do not cast unknown spells
SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellid);
if (!spellInfo)
{
sLog->outError("WORLD: unknown PET spell id %i", spellid);
return;
}
if (spellInfo->StartRecoveryCategory > 0)
if (pet->ToCreature()->GetGlobalCooldown() > 0)
return;
for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i)
{
if (spellInfo->EffectImplicitTargetA[i] == TARGET_UNIT_AREA_ENEMY_SRC || spellInfo->EffectImplicitTargetA[i] == TARGET_UNIT_AREA_ENEMY_DST || spellInfo->EffectImplicitTargetA[i] == TARGET_DEST_DYNOBJ_ENEMY)
return;
}
// do not cast not learned spells
if (!pet->HasSpell(spellid) || IsPassiveSpell(spellid))
return;
// Clear the flags as if owner clicked 'attack'. AI will reset them
// after AttackStart, even if spell failed
if (pet->GetCharmInfo())
{
pet->GetCharmInfo()->SetIsAtStay(false);
pet->GetCharmInfo()->SetIsCommandAttack(true);
pet->GetCharmInfo()->SetIsReturning(false);
pet->GetCharmInfo()->SetIsFollowing(false);
}
Spell *spell = new Spell(pet, spellInfo, false);
SpellCastResult result = spell->CheckPetCast(unit_target);
//auto turn to target unless possessed
if (result == SPELL_FAILED_UNIT_NOT_INFRONT && !pet->isPossessed() && !pet->IsVehicle())
{
if (unit_target)
{
pet->SetInFront(unit_target);
if (unit_target->GetTypeId() == TYPEID_PLAYER)
pet->SendUpdateToPlayer((Player*)unit_target);
}
else if (Unit *unit_target2 = spell->m_targets.getUnitTarget())
{
pet->SetInFront(unit_target2);
if (unit_target2->GetTypeId() == TYPEID_PLAYER)
pet->SendUpdateToPlayer((Player*)unit_target2);
}
if (Unit* powner = pet->GetCharmerOrOwner())
void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket)
{
uint32 spellId;
uint8 cast_count, cast_flags;
recvPacket >> cast_count;
recvPacket >> spellId;
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: CMSG_CAST_SPELL, spellId - %u, cast_count: %u, unk_flags %u, data length = " SIZEFMTD,
spellId, cast_count, cast_flags, recvPacket.size());
SpellEntry const* spellInfo = sSpellTemplate.LookupEntry<SpellEntry>(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;
}
}
// client provided targets
SpellCastTargets targets;
#ifdef BUILD_PLAYERBOT
recvPacket >> targets.ReadForCaster(mover);
#else
recvPacket >> targets.ReadForCaster(_player);
#endif
// some spell cast packet including more data (for projectiles)
targets.ReadAdditionalSpellData(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 nullptr 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 ? TRIGGERED_OLD_TRIGGERED : TRIGGERED_NONE, mover->GetObjectGuid(), triggeredByAura ? triggeredByAura->GetSpellProto() : nullptr);
spell->m_cast_count = cast_count; // set count of casts
spell->SpellStart(&targets, triggeredByAura);
}
请发表评论