|
发表于 2010-6-20 18:40:11
|显示全部楼层
3、释放spell流程
opcode = 0x012E // "CMSG_CAST_SPELL"
handler = WorldSession::HandleCastSpellOpcode
void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket)
{
uint32 spellId;
uint8 cast_count, unk_flags;
// 可见参数结构:cast_count(1字节)、spellid(4字节)、unk_flags(1字节,这个一般用来指示target)
recvPacket >> cast_count;
recvPacket >> spellId;
recvPacket >> unk_flags; // flags (if 0x02 - some additional data are received)
// ignore for remote control state (for player case)
Unit* mover = _player->m_mover;
if(mover != _player && mover->GetTypeId() == TYPEID_PLAYER)
{
recvPacket.rpos(recvPacket.wpos()); // prevent spam at ignore packet
return;
}
sLog.outDebug("WORLD: got cast spell packet, spellId - %u, cast_count: %u, unk_flags %u, data length = %i",
spellId, cast_count, unk_flags, (uint32)recvPacket.size());
SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId );
// spell不存在
if(!spellInfo)
{
sLog.outError("WORLD: unknown spell id %u", spellId);
recvPacket.rpos(recvPacket.wpos()); // prevent spam at ignore packet
return;
}
// 释放不会的spell或者passive spell(被动技能)是不行的
if(mover->GetTypeId() == TYPEID_PLAYER)
{
// not have spell in spellbook or spell passive and not casted by client
if (!((Player*)mover)->HasActiveSpell (spellId) || IsPassiveSpell(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(spellId) )
{
//cheater? kick? ban?
recvPacket.rpos(recvPacket.wpos()); // prevent spam at ignore packet
return;
}
}
// Client is resending autoshot cast opcode when other spell is casted during shoot rotation
// Skip it to prevent "interrupt" message
// 自动释放的技能直接忽略
if (IsAutoRepeatRangedSpell(spellInfo) && _player->GetCurrentSpell(CURRENT_AUTOREPEAT_SPELL)
&& _player->GetCurrentSpell(CURRENT_AUTOREPEAT_SPELL)->m_spellInfo == spellInfo)
return;
// can't use our own spells when we're in possession of another unit,
// 被控制时不能放技能
if(_player->isPossessing())
return;
// client provided targets
SpellCastTargets targets;
if(!targets.read(&recvPacket,mover))
{
recvPacket.rpos(recvPacket.wpos()); // prevent spam at ignore packet
return;
}
// some spell cast packet including more data (for projectiles?)
if (unk_flags & 0x02)
{
//recvPacket.read_skip<float>(); // unk1, coords?
//recvPacket.read_skip<float>(); // unk1, coords?
recvPacket.read_skip<uint8>(); // >> 1
recvPacket.read_skip<uint32>(); // >> MSG_MOVE_STOP
MovementInfo movementInfo;
ReadMovementInfo(recvPacket, &movementInfo);
}
// auto-selection buff level base at target level (in spellInfo)
if(targets.getUnitTarget())
{
SpellEntry const *actualSpellInfo = spellmgr.SelectAuraRankForPlayerLevel(spellInfo,targets.getUnitTarget()->getLevel());
// 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(actualSpellInfo)
spellInfo = actualSpellInfo;
}
// 准备释放
Spell *spell = new Spell(mover, spellInfo, false);
spell->m_cast_count = cast_count; // set count of casts
spell->prepare(&targets);
} |
|