Beispiel #1
0
void WorldSession::HandleClientCastFlags(WorldPacket& recvPacket, uint8 castFlags, SpellCastTargets& targets)
{
    // some spell cast packet including more data (for projectiles?)
    if (castFlags & 0x02)
    {
        // not sure about these two
        float elevation, speed;
        recvPacket >> elevation;
        recvPacket >> speed;

        targets.SetElevation(elevation);
        targets.SetSpeed(speed);

        uint8 hasMovementData;
        recvPacket >> hasMovementData;
        if (hasMovementData)
        {
            recvPacket.rfinish();
            // movement packet for caster of the spell
            /*recvPacket.read_skip<uint32>(); // MSG_MOVE_STOP - hardcoded in client
            uint64 guid;
            recvPacket.readPackGUID(guid);

            MovementInfo movementInfo;
            movementInfo.guid = guid;
            ReadMovementInfo(recvPacket, &movementInfo);*/
        }
    }
void WorldSession::HandleClientCastFlags(WorldPacket& recvPacket, uint8 castFlags, SpellCastTargets& targets)
{
    // some spell cast packet including more data (for projectiles?)
    if (castFlags & 0x02)
    {
        // not sure about these two
        float elevation, speed;
        recvPacket >> elevation;
        recvPacket >> speed;

        targets.SetElevation(elevation);
        targets.SetSpeed(speed);

        uint8 hasMovementData;
        recvPacket >> hasMovementData;
        if (hasMovementData)
            HandleMovementOpcodes(recvPacket);
    }
Beispiel #3
0
void WorldSession::HandlePetCastSpellOpcode(WorldPacket& recvPacket)
{
    TC_LOG_DEBUG("network", "WORLD: CMSG_PET_CAST_SPELL");

    ObjectGuid casterGUID;
    ObjectGuid unkGUID1;
    ObjectGuid transportDstGUID;
    ObjectGuid transportSrcGUID;
    ObjectGuid targetGUID;
    ObjectGuid unkGUID2;
    bool hasDestPos;
    bool hasSrcPos;
    bool hasSpeed;
    bool hasSpell;
    bool hasGlyphIndex;
    bool hasTargetFlags;
    bool hasElevation;
    bool hasString;
    bool hasCastCount;
    bool hasUnk5bits;
    uint32 archeologyCounter = 0;
    WorldLocation dstLoc, srcLoc;
    float speed = 0.0f;
    float elevation = 0.0f;
    uint32 targetFlags = 0;
    uint32 spellID = 0;
    uint32 stringLenght = 0;
    uint8 castCount = 0;

    recvPacket.ReadBitSeq<3, 5>(casterGUID);
    hasDestPos = recvPacket.ReadBit();
    recvPacket.ReadBit();                   // unk bit
    hasSpeed = !recvPacket.ReadBit();
    hasSrcPos = recvPacket.ReadBit();
    hasSpell = !recvPacket.ReadBit();
    recvPacket.ReadBitSeq<0>(casterGUID);
    hasGlyphIndex = !recvPacket.ReadBit();
    recvPacket.ReadBitSeq<7>(casterGUID);
    hasTargetFlags = !recvPacket.ReadBit();
    hasElevation = !recvPacket.ReadBit();
    recvPacket.ReadBit();                   // has movement info
    hasString = !recvPacket.ReadBit();
    recvPacket.ReadBit();                   // !inverse bit, unk
    hasCastCount = !recvPacket.ReadBit();
    recvPacket.ReadBitSeq<2, 4>(casterGUID);
    archeologyCounter = recvPacket.ReadBits(2);
    recvPacket.ReadBitSeq<1>(casterGUID);
    hasUnk5bits = !recvPacket.ReadBit();

    for (uint32 i = 0; i < archeologyCounter; i++)
        recvPacket.ReadBits(2);             // archeology type

    recvPacket.ReadBitSeq<6>(casterGUID);

    if (hasDestPos)
        recvPacket.ReadBitSeq<2, 7, 4, 0, 1, 6, 5, 3>(transportDstGUID);

    // movement block (disabled by patch client-side)

    if (hasSrcPos)
        recvPacket.ReadBitSeq<6, 2, 3, 1, 5, 4, 0, 7>(transportSrcGUID);

    if (hasUnk5bits)
        recvPacket.ReadBits(5);             // unk 5 bits

    // Target GUID
    recvPacket.ReadBitSeq<3, 5, 6, 2, 4, 1, 7, 0>(targetGUID);

    // unkGUID1
    recvPacket.ReadBitSeq<3, 1, 5, 2, 4, 7, 0, 6>(unkGUID1);

    if (hasTargetFlags)
        targetFlags = recvPacket.ReadBits(20);

    if (hasString)
        stringLenght = recvPacket.ReadBits(7);

    recvPacket.ReadByteSeq<0, 4, 5, 1, 2, 3, 7>(casterGUID);

    for (uint32 i = 0; i < archeologyCounter; i++)
    {
        recvPacket.read_skip<uint32>(); // entry
        recvPacket.read_skip<uint32>(); // counter
    }

    recvPacket.ReadByteSeq<6>(casterGUID);
    recvPacket.ReadByteSeq<1, 5, 4, 2, 7, 3, 0>(unkGUID1);

    if (hasSrcPos)
    {
        recvPacket.ReadByteSeq<4>(transportSrcGUID);
        srcLoc.m_positionY = recvPacket.read<float>();
        recvPacket.ReadByteSeq<2, 6>(transportSrcGUID);
        srcLoc.m_positionZ = recvPacket.read<float>();
        srcLoc.m_positionX = recvPacket.read<float>();
        recvPacket.ReadByteSeq<1, 3, 5, 7, 0>(transportSrcGUID);
    }

    // Target GUID
    recvPacket.ReadByteSeq<7, 4, 2, 6, 3, 0, 5, 1>(targetGUID);

    if (hasDestPos)
    {
        dstLoc.m_positionX = recvPacket.read<float>();
        recvPacket.ReadByteSeq<5, 7, 2, 0, 1, 3, 6>(transportDstGUID);
        dstLoc.m_positionZ = recvPacket.read<float>();
        dstLoc.m_positionY = recvPacket.read<float>();
        recvPacket.ReadByteSeq<4>(transportDstGUID);
    }

    if (hasGlyphIndex)
        recvPacket.read_skip<uint32>();     // glyph index

    if (hasElevation)
        elevation = recvPacket.read<float>();

    if (hasSpell)
        spellID = recvPacket.read<uint32>();

    if (hasCastCount)
        castCount = recvPacket.read<uint8>();

    if (hasString)
        recvPacket.ReadString(stringLenght);

    if (hasSpeed)
        speed = recvPacket.read<float>();

    TC_LOG_DEBUG("network", "WORLD: CMSG_PET_CAST_SPELL, castCount: %u, spellId %u, targetFlags %u", castCount, spellID, targetFlags);

    // This opcode is also sent from charmed and possessed units (players and creatures)
    if (!_player->GetGuardianPet() && !_player->GetCharm())
        return;

    Unit* caster = ObjectAccessor::GetUnit(*_player, casterGUID);

    if (!caster || (caster != _player->GetGuardianPet() && caster != _player->GetCharm()))
    {
        TC_LOG_ERROR("network", "HandlePetCastSpellOpcode: Pet %u isn't pet of player %s .", uint32(GUID_LOPART(casterGUID)), GetPlayer()->GetName().c_str());
        return;
    }

    SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellID);
    if (!spellInfo)
    {
        TC_LOG_ERROR("network", "WORLD: unknown PET spell id %i", spellID);
        return;
    }

    if (spellInfo->StartRecoveryCategory > 0) // Check if spell is affected by GCD
        if (caster->GetTypeId() == TYPEID_UNIT && caster->GetCharmInfo() && caster->GetCharmInfo()->GetGlobalCooldownMgr().HasGlobalCooldown(caster, spellInfo))
        {
            caster->SendPetCastFail(spellID, SPELL_FAILED_NOT_READY);
            return;
        }

    // do not cast not learned spells
    if (!caster->HasSpell(spellID) || spellInfo->IsPassive())
        return;

    SpellCastTargets targets;
    targets.Initialize(targetFlags, targetGUID, unkGUID1, transportDstGUID, dstLoc, transportSrcGUID, srcLoc);
    targets.SetElevation(elevation);
    targets.SetSpeed(speed);
    targets.Update(caster);

    // Interrupt auto-cast if other spell is forced by player
    if (caster->IsNonMeleeSpellCasted(false, true, true, false, true))
        caster->InterruptNonMeleeSpells(false, 0, false);

    caster->ClearUnitState(UNIT_STATE_FOLLOW);

    Spell* spell = new Spell(caster, spellInfo, TRIGGERED_NONE, 0, false, true);
    spell->m_cast_count = castCount;                    // probably pending spell cast
    spell->m_targets = targets;

    // TODO: need to check victim?
    SpellCastResult result;
    if (caster->m_movedPlayer)
        result = spell->CheckPetCast(caster->m_movedPlayer->GetSelectedUnit());
    else
        result = spell->CheckPetCast(NULL);
    if (result == SPELL_CAST_OK)
    {
        if (caster->GetTypeId() == TYPEID_UNIT)
        {
            Creature* pet = caster->ToCreature();
            pet->AddCreatureSpellCooldown(spellID);
            if (pet->isPet())
            {
                Pet* p = (Pet*)pet;
                // 10% chance to play special pet attack talk, else growl
                // actually this only seems to happen on special spells, fire shield for imp, torment for voidwalker, but it's stupid to check every spell
                if (p->getPetType() == SUMMON_PET && (urand(0, 100) < 10))
                    pet->SendPetTalk((uint32)PET_TALK_SPECIAL_SPELL);
                else
                    pet->SendPetAIReaction(spellID);
            }
        }

        spell->prepare(&(spell->m_targets));
    }
    else
    {
        caster->SendPetCastFail(spellID, result);
        if (caster->GetTypeId() == TYPEID_PLAYER)
        {
            if (!caster->ToPlayer()->HasSpellCooldown(spellID))
                GetPlayer()->SendClearCooldown(spellID, caster);
        }
        else
        {
            if (!caster->ToCreature()->HasSpellCooldown(spellID))
                GetPlayer()->SendClearCooldown(spellID, caster);
        }

        spell->finish(false);
        delete spell;
    }
}