[0086] Updated CMSG_SPELL_CAST, CMSG_USE_ITEM, CMSG_PET_SPELL_CAST, SMSG_SPELL_START, SMSG_SPELL_GO and some other spell opcodes

This commit is contained in:
Yaki Khadafi 2012-08-14 14:40:00 +03:00 committed by Antz
parent 5d91e6f24c
commit 6407b24a03
8 changed files with 217 additions and 77 deletions

View file

@ -2109,10 +2109,86 @@ MovementStatusElements MovementSetCanFlyAckSequence[] =
MSEEnd, MSEEnd,
}; };
MovementStatusElements MovementCastSpellSequence[] =
{
MSEPositionZ,
MSEPositionY,
MSEPositionX,
MSEHasFallData,
MSEHasTimestamp,
MSEHasOrientation,
MSEHasSpline,
MSEHasUnknownBit,
MSEGuidBit6,
MSEGuidBit4,
MSEHasMovementFlags2,
MSEGuidBit3,
MSEGuidBit5,
MSEHasSplineElevation,
MSEHasPitch,
MSEGuidBit7,
MSEHasTransportData,
MSEGuidBit2,
MSEHasMovementFlags,
MSEGuidBit1,
MSEGuidBit0,
MSETransportGuidBit6,
MSETransportGuidBit2,
MSETransportGuidBit5,
MSEHasTransportTime2,
MSETransportGuidBit7,
MSETransportGuidBit4,
MSEHasTransportTime3,
MSETransportGuidBit0,
MSETransportGuidBit1,
MSETransportGuidBit3,
MSEFlags2,
MSEFlags,
MSEHasFallDirection,
MSEGuidByte1,
MSEGuidByte4,
MSEGuidByte7,
MSEGuidByte3,
MSEGuidByte0,
MSEGuidByte2,
MSEGuidByte5,
MSEGuidByte6,
MSETransportSeat,
MSETransportPositionO,
MSETransportTime,
MSETransportGuidByte6,
MSETransportGuidByte5,
MSETransportTime3,
MSETransportPositionX,
MSETransportGuidByte4,
MSETransportPositionZ,
MSETransportGuidByte2,
MSETransportGuidByte0,
MSETransportTime2,
MSETransportGuidByte1,
MSETransportGuidByte3,
MSETransportPositionY,
MSETransportGuidByte7,
MSEPositionO,
MSESplineElevation,
MSEFallTime,
MSEFallHorizontalSpeed,
MSEFallCosAngle,
MSEFallSinAngle,
MSEFallVerticalSpeed,
MSETimestamp,
MSEPitch,
MSEEnd,
};
MovementStatusElements* GetMovementStatusElementsSequence(uint16 opcode) MovementStatusElements* GetMovementStatusElementsSequence(uint16 opcode)
{ {
switch(opcode) switch(opcode)
{ {
case CMSG_CAST_SPELL:
case CMSG_PET_CAST_SPELL:
case CMSG_USE_ITEM:
return MovementCastSpellSequence;
case CMSG_MOVE_CHNG_TRANSPORT: case CMSG_MOVE_CHNG_TRANSPORT:
return MovementChngTransportSequence; return MovementChngTransportSequence;
case CMSG_MOVE_FALL_LAND: case CMSG_MOVE_FALL_LAND:

View file

@ -234,7 +234,7 @@ void InitializeOpcodes()
//OPCODE(CMSG_CHANNEL_MODERATE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleChannelModerateOpcode ); //OPCODE(CMSG_CHANNEL_MODERATE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleChannelModerateOpcode );
OPCODE(SMSG_UPDATE_OBJECT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); OPCODE(SMSG_UPDATE_OBJECT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
OPCODE(SMSG_DESTROY_OBJECT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); OPCODE(SMSG_DESTROY_OBJECT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
//OPCODE(CMSG_USE_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleUseItemOpcode ); OPCODE(CMSG_USE_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleUseItemOpcode );
//OPCODE(CMSG_OPEN_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleOpenItemOpcode ); //OPCODE(CMSG_OPEN_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleOpenItemOpcode );
//OPCODE(CMSG_READ_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleReadItemOpcode ); //OPCODE(CMSG_READ_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleReadItemOpcode );
//OPCODE(SMSG_READ_ITEM_OK, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); //OPCODE(SMSG_READ_ITEM_OK, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
@ -374,15 +374,15 @@ void InitializeOpcodes()
OPCODE(SMSG_LEARNED_SPELL, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); OPCODE(SMSG_LEARNED_SPELL, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
OPCODE(SMSG_SUPERCEDED_SPELL, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); OPCODE(SMSG_SUPERCEDED_SPELL, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
//OPCODE(CMSG_NEW_SPELL_SLOT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); //OPCODE(CMSG_NEW_SPELL_SLOT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
//OPCODE(CMSG_CAST_SPELL, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleCastSpellOpcode ); OPCODE(CMSG_CAST_SPELL, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleCastSpellOpcode );
//OPCODE(CMSG_CANCEL_CAST, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleCancelCastOpcode ); OPCODE(CMSG_CANCEL_CAST, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleCancelCastOpcode );
//OPCODE(SMSG_CAST_FAILED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); OPCODE(SMSG_CAST_FAILED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
//OPCODE(SMSG_SPELL_START, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); OPCODE(SMSG_SPELL_START, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
//OPCODE(SMSG_SPELL_GO, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); OPCODE(SMSG_SPELL_GO, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
//OPCODE(SMSG_SPELL_FAILURE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); //OPCODE(SMSG_SPELL_FAILURE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
//OPCODE(SMSG_SPELL_COOLDOWN, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); //OPCODE(SMSG_SPELL_COOLDOWN, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
//OPCODE(SMSG_COOLDOWN_EVENT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); //OPCODE(SMSG_COOLDOWN_EVENT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
//OPCODE(CMSG_CANCEL_AURA, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCancelAuraOpcode ); OPCODE(CMSG_CANCEL_AURA, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCancelAuraOpcode );
//OPCODE(SMSG_EQUIPMENT_SET_ID, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); //OPCODE(SMSG_EQUIPMENT_SET_ID, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
//OPCODE(SMSG_PET_CAST_FAILED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); //OPCODE(SMSG_PET_CAST_FAILED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
//OPCODE(MSG_CHANNEL_START, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); //OPCODE(MSG_CHANNEL_START, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
@ -565,7 +565,7 @@ void InitializeOpcodes()
//OPCODE(SMSG_ITEM_TIME_UPDATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); //OPCODE(SMSG_ITEM_TIME_UPDATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
//OPCODE(SMSG_ITEM_ENCHANT_TIME_UPDATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); //OPCODE(SMSG_ITEM_ENCHANT_TIME_UPDATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
//OPCODE(MSG_GM_SHOWLABEL, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); //OPCODE(MSG_GM_SHOWLABEL, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
//OPCODE(CMSG_PET_CAST_SPELL, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePetCastSpellOpcode ); OPCODE(CMSG_PET_CAST_SPELL, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePetCastSpellOpcode );
//OPCODE(MSG_SAVE_GUILD_EMBLEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSaveGuildEmblemOpcode ); //OPCODE(MSG_SAVE_GUILD_EMBLEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSaveGuildEmblemOpcode );
//OPCODE(MSG_TABARDVENDOR_ACTIVATE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleTabardVendorActivateOpcode); //OPCODE(MSG_TABARDVENDOR_ACTIVATE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleTabardVendorActivateOpcode);
OPCODE(SMSG_PLAY_SPELL_VISUAL, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); OPCODE(SMSG_PLAY_SPELL_VISUAL, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );

View file

@ -228,7 +228,7 @@ enum Opcodes
CMSG_CHANNEL_MODERATE = 0x10A9, CMSG_CHANNEL_MODERATE = 0x10A9,
SMSG_UPDATE_OBJECT = 0x4715, // 4.3.4 15595 SMSG_UPDATE_OBJECT = 0x4715, // 4.3.4 15595
SMSG_DESTROY_OBJECT = 0x4724, // 4.3.4 15595 SMSG_DESTROY_OBJECT = 0x4724, // 4.3.4 15595
CMSG_USE_ITEM = 0x10AC, CMSG_USE_ITEM = 0x2C06, // 4.3.4 15595
CMSG_OPEN_ITEM = 0x10AD, CMSG_OPEN_ITEM = 0x10AD,
CMSG_READ_ITEM = 0x10AE, CMSG_READ_ITEM = 0x10AE,
SMSG_READ_ITEM_OK = 0x10AF, SMSG_READ_ITEM_OK = 0x10AF,
@ -359,15 +359,15 @@ enum Opcodes
SMSG_LEARNED_SPELL = 0x58A2, // 4.3.4 15595 SMSG_LEARNED_SPELL = 0x58A2, // 4.3.4 15595
SMSG_SUPERCEDED_SPELL = 0x35B0, // 4.3.4 15595 SMSG_SUPERCEDED_SPELL = 0x35B0, // 4.3.4 15595
CMSG_NEW_SPELL_SLOT = 0x112E, CMSG_NEW_SPELL_SLOT = 0x112E,
CMSG_CAST_SPELL = 0x112F, CMSG_CAST_SPELL = 0x4C07, // 4.3.4 15595
CMSG_CANCEL_CAST = 0x1130, CMSG_CANCEL_CAST = 0x0115, // 4.3.4 15595
SMSG_CAST_FAILED = 0x1131, SMSG_CAST_FAILED = 0x4D16, // 4.3.4 15595
SMSG_SPELL_START = 0x1132, SMSG_SPELL_START = 0x6415, // 4.3.4 15595
SMSG_SPELL_GO = 0x1133, SMSG_SPELL_GO = 0x6E16, // 4.3.4 15595
SMSG_SPELL_FAILURE = 0x1134, SMSG_SPELL_FAILURE = 0x1134,
SMSG_SPELL_COOLDOWN = 0x1135, SMSG_SPELL_COOLDOWN = 0x1135,
SMSG_COOLDOWN_EVENT = 0x1136, SMSG_COOLDOWN_EVENT = 0x1136,
CMSG_CANCEL_AURA = 0x1137, CMSG_CANCEL_AURA = 0x0E26, // 4.3.4 15595
SMSG_EQUIPMENT_SET_ID = 0x1138, SMSG_EQUIPMENT_SET_ID = 0x1138,
SMSG_PET_CAST_FAILED = 0x1139, SMSG_PET_CAST_FAILED = 0x1139,
MSG_CHANNEL_START = 0x113A, MSG_CHANNEL_START = 0x113A,
@ -550,7 +550,7 @@ enum Opcodes
SMSG_ITEM_TIME_UPDATE = 0x11EB, SMSG_ITEM_TIME_UPDATE = 0x11EB,
SMSG_ITEM_ENCHANT_TIME_UPDATE = 0x11EC, SMSG_ITEM_ENCHANT_TIME_UPDATE = 0x11EC,
MSG_GM_SHOWLABEL = 0x11F0, MSG_GM_SHOWLABEL = 0x11F0,
CMSG_PET_CAST_SPELL = 0x11F1, CMSG_PET_CAST_SPELL = 0x6337, // 4.3.4 15595
MSG_SAVE_GUILD_EMBLEM = 0x11F2, MSG_SAVE_GUILD_EMBLEM = 0x11F2,
MSG_TABARDVENDOR_ACTIVATE = 0x11F3, MSG_TABARDVENDOR_ACTIVATE = 0x11F3,
SMSG_PLAY_SPELL_VISUAL = 0x55A5, // 4.3.4 15595 SMSG_PLAY_SPELL_VISUAL = 0x55A5, // 4.3.4 15595

View file

@ -633,11 +633,11 @@ void WorldSession::HandlePetCastSpellOpcode(WorldPacket& recvPacket)
ObjectGuid guid; ObjectGuid guid;
uint32 spellid; uint32 spellid;
uint8 cast_count; uint8 cast_count;
uint8 unk_flags; // flags (if 0x02 - some additional data are received) uint8 cast_flags; // flags (if 0x02 - some additional data are received)
recvPacket >> guid >> cast_count >> spellid >> unk_flags; recvPacket >> guid >> cast_count >> spellid >> cast_flags;
DEBUG_LOG("WORLD: CMSG_PET_CAST_SPELL, %s, cast_count: %u, spellid %u, unk_flags %u", guid.GetString().c_str(), cast_count, spellid, unk_flags); DEBUG_LOG("WORLD: CMSG_PET_CAST_SPELL, %s, cast_count: %u, spellid %u, cast_flags %u", guid.GetString().c_str(), cast_count, spellid, cast_flags);
Creature* pet = _player->GetMap()->GetAnyTypeCreature(guid); Creature* pet = _player->GetMap()->GetAnyTypeCreature(guid);
@ -666,6 +666,8 @@ void WorldSession::HandlePetCastSpellOpcode(WorldPacket& recvPacket)
recvPacket >> targets.ReadForCaster(pet); recvPacket >> targets.ReadForCaster(pet);
targets.ReadAdditionalData(recvPacket, cast_flags);
pet->clearUnitState(UNIT_STAT_MOVING); pet->clearUnitState(UNIT_STAT_MOVING);
Spell* spell = new Spell(pet, spellInfo, false); Spell* spell = new Spell(pet, spellInfo, false);

View file

@ -314,6 +314,43 @@ void SpellCastTargets::write(ByteBuffer& data) const
data << m_strTarget; data << m_strTarget;
} }
void SpellCastTargets::ReadAdditionalData(WorldPacket& data, uint8& cast_flags)
{
if (cast_flags & 0x02) // has trajectory data
{
data >> m_elevation >> m_speed;
bool hasMovementData;
data >> hasMovementData;
if (hasMovementData)
{
MovementInfo mi;
data >> mi;
}
}
else if (cast_flags & 0x08) // has archaeology weight
{
uint32 count;
uint8 type;
data >> count;
for (uint32 i = 0; i < count; ++i)
{
data >> type;
switch (type)
{
case 1: // Fragments
data >> Unused<uint32>(); // Currency entry
data >> Unused<uint32>(); // Currency count
break;
case 2: // Keystones
data >> Unused<uint32>(); // Item entry
data >> Unused<uint32>(); // Item count
break;
}
}
}
}
Spell::Spell(Unit* caster, SpellEntry const* info, bool triggered, ObjectGuid originalCasterGUID, SpellEntry const* triggeredBy) Spell::Spell(Unit* caster, SpellEntry const* info, bool triggered, ObjectGuid originalCasterGUID, SpellEntry const* triggeredBy)
{ {
MANGOS_ASSERT(caster != NULL && info != NULL); MANGOS_ASSERT(caster != NULL && info != NULL);
@ -4046,12 +4083,14 @@ void Spell::SendSpellStart()
DEBUG_FILTER_LOG(LOG_FILTER_SPELL_CAST, "Sending SMSG_SPELL_START id=%u", m_spellInfo->Id); DEBUG_FILTER_LOG(LOG_FILTER_SPELL_CAST, "Sending SMSG_SPELL_START id=%u", m_spellInfo->Id);
uint32 castFlags = CAST_FLAG_UNKNOWN2; uint32 castFlags = CAST_FLAG_UNKNOWN2;
if (IsRangedSpell())
castFlags |= CAST_FLAG_AMMO;
if (m_spellInfo->runeCostID) if (m_spellInfo->runeCostID)
castFlags |= CAST_FLAG_UNKNOWN19; castFlags |= CAST_FLAG_UNKNOWN19;
if ((m_caster->GetTypeId() == TYPEID_PLAYER ||
m_caster->GetTypeId() == TYPEID_UNIT && ((Creature*)m_caster)->IsPet()) &&
m_spellInfo->powerType != POWER_HEALTH)
castFlags |= CAST_FLAG_PREDICTED_POWER;
WorldPacket data(SMSG_SPELL_START, (8 + 8 + 4 + 4 + 2)); WorldPacket data(SMSG_SPELL_START, (8 + 8 + 4 + 4 + 2));
if (m_CastItem) if (m_CastItem)
data << m_CastItem->GetPackGUID(); data << m_CastItem->GetPackGUID();
@ -4063,24 +4102,30 @@ void Spell::SendSpellStart()
data << uint32(m_spellInfo->Id); // spellId data << uint32(m_spellInfo->Id); // spellId
data << uint32(castFlags); // cast flags data << uint32(castFlags); // cast flags
data << uint32(m_timer); // delay? data << uint32(m_timer); // delay?
data << uint32(m_casttime); // m_casttime
data << m_targets; data << m_targets;
if (castFlags & CAST_FLAG_PREDICTED_POWER) // predicted power if (castFlags & CAST_FLAG_PREDICTED_POWER) // predicted power
data << uint32(0); data << uint32(m_caster->GetPower(Powers(m_spellInfo->powerType)));
if (castFlags & CAST_FLAG_PREDICTED_RUNES) // predicted runes if (castFlags & CAST_FLAG_PREDICTED_RUNES) // predicted runes
{ {
uint8 v1 = 0;// m_runesState; if (m_caster->GetTypeId() == TYPEID_PLAYER)
uint8 v2 = 0;//((Player*)m_caster)->GetRunesState();
data << uint8(v1); // runes state before
data << uint8(v2); // runes state after
for (uint8 i = 0; i < MAX_RUNES; ++i)
{ {
uint8 m = (1 << i); Player* caster = (Player*)m_caster;
if (m & v1) // usable before...
if (!(m & v2)) // ...but on cooldown now... data << uint8(m_runesState);
data << uint8(0); // some unknown byte (time?) data << uint8(caster->GetRunesState());
for (uint8 i = 0; i < MAX_RUNES; ++i)
data << uint8(255 - ((caster->GetRuneCooldown(i) / REGEN_TIME_FULL) * 51));
}
else
{
data << uint8(0);
data << uint8(0);
for (uint8 i = 0; i < MAX_RUNES; ++i)
data << uint8(0);
} }
} }
@ -4093,6 +4138,15 @@ void Spell::SendSpellStart()
data << uint32(0); // used for SetCastImmunities data << uint32(0); // used for SetCastImmunities
} }
if (castFlags & CAST_FLAG_HEAL_PREDICTION)
{
uint8 unk = 0;
data << uint32(0);
data << uint8(unk);
if (unk == 2)
data << ObjectGuid().WriteAsPacked();
}
m_caster->SendMessageToSet(&data, true); m_caster->SendMessageToSet(&data, true);
} }
@ -4105,13 +4159,15 @@ void Spell::SendSpellGo()
DEBUG_FILTER_LOG(LOG_FILTER_SPELL_CAST, "Sending SMSG_SPELL_GO id=%u", m_spellInfo->Id); DEBUG_FILTER_LOG(LOG_FILTER_SPELL_CAST, "Sending SMSG_SPELL_GO id=%u", m_spellInfo->Id);
uint32 castFlags = CAST_FLAG_UNKNOWN9; uint32 castFlags = CAST_FLAG_UNKNOWN9;
if (IsRangedSpell())
castFlags |= CAST_FLAG_AMMO; // arrows/bullets visual
if ((m_caster->GetTypeId() == TYPEID_PLAYER) && (m_caster->getClass() == CLASS_DEATH_KNIGHT) && m_spellInfo->runeCostID) if ((m_caster->GetTypeId() == TYPEID_PLAYER ||
m_caster->GetTypeId() == TYPEID_UNIT && ((Creature*)m_caster)->IsPet()) &&
m_spellInfo->powerType != POWER_HEALTH)
castFlags |= CAST_FLAG_PREDICTED_POWER;
if (m_caster->GetTypeId() == TYPEID_PLAYER && m_caster->getClass() == CLASS_DEATH_KNIGHT && m_spellInfo->runeCostID)
{ {
castFlags |= CAST_FLAG_UNKNOWN19; // same as in SMSG_SPELL_START castFlags |= CAST_FLAG_UNKNOWN19; // same as in SMSG_SPELL_START
castFlags |= CAST_FLAG_PREDICTED_POWER; // makes cooldowns visible
castFlags |= CAST_FLAG_PREDICTED_RUNES; // rune cooldowns list castFlags |= CAST_FLAG_PREDICTED_RUNES; // rune cooldowns list
} }
@ -4126,6 +4182,7 @@ void Spell::SendSpellGo()
data << uint8(m_cast_count); // pending spell cast? data << uint8(m_cast_count); // pending spell cast?
data << uint32(m_spellInfo->Id); // spellId data << uint32(m_spellInfo->Id); // spellId
data << uint32(castFlags); // cast flags data << uint32(castFlags); // cast flags
data << uint32(m_timer);
data << uint32(WorldTimer::getMSTime()); // timestamp data << uint32(WorldTimer::getMSTime()); // timestamp
WriteSpellGoTargets(&data); WriteSpellGoTargets(&data);
@ -4133,27 +4190,32 @@ void Spell::SendSpellGo()
data << m_targets; data << m_targets;
if (castFlags & CAST_FLAG_PREDICTED_POWER) // predicted power if (castFlags & CAST_FLAG_PREDICTED_POWER) // predicted power
data << uint32(0); data << uint32(m_caster->GetPower(Powers(m_spellInfo->powerType)));
if (castFlags & CAST_FLAG_PREDICTED_RUNES) // predicted runes if (castFlags & CAST_FLAG_PREDICTED_RUNES) // predicted runes
{ {
uint8 v1 = m_runesState; if (m_caster->GetTypeId() == TYPEID_PLAYER)
uint8 v2 = m_caster->getClass() == CLASS_DEATH_KNIGHT ? ((Player*)m_caster)->GetRunesState() : 0;
data << uint8(v1); // runes state before
data << uint8(v2); // runes state after
for (uint8 i = 0; i < MAX_RUNES; ++i)
{ {
uint8 m = (1 << i); Player* caster = (Player*)m_caster;
if (m & v1) // usable before...
if (!(m & v2)) // ...but on cooldown now... data << uint8(m_runesState);
data << uint8(0); // some unknown byte (time?) data << uint8(caster->GetRunesState());
for (uint8 i = 0; i < MAX_RUNES; ++i)
data << uint8(255 - ((caster->GetRuneCooldown(i) / REGEN_TIME_FULL) * 51));
}
else
{
data << uint8(0);
data << uint8(0);
for (uint8 i = 0; i < MAX_RUNES; ++i)
data << uint8(0);
} }
} }
if (castFlags & CAST_FLAG_ADJUST_MISSILE) // adjust missile trajectory duration if (castFlags & CAST_FLAG_ADJUST_MISSILE) // adjust missile trajectory duration
{ {
data << float(0); data << float(m_targets.GetElevation());
data << uint32(0); data << uint32(m_delayMoment);
} }
if (castFlags & CAST_FLAG_AMMO) // projectile info if (castFlags & CAST_FLAG_AMMO) // projectile info

View file

@ -61,7 +61,12 @@ enum SpellCastFlags
CAST_FLAG_VISUAL_CHAIN = 0x00080000, // wotlk CAST_FLAG_VISUAL_CHAIN = 0x00080000, // wotlk
CAST_FLAG_UNKNOWN21 = 0x00100000, CAST_FLAG_UNKNOWN21 = 0x00100000,
CAST_FLAG_PREDICTED_RUNES = 0x00200000, // wotlk, rune cooldown list CAST_FLAG_PREDICTED_RUNES = 0x00200000, // wotlk, rune cooldown list
CAST_FLAG_IMMUNITY = 0x04000000 // spell cast school imminity info CAST_FLAG_IMMUNITY = 0x04000000, // spell cast school imminity info
CAST_FLAG_UNKNOWN24 = 0x08000000,
CAST_FLAG_UNKNOWN25 = 0x10000000,
CAST_FLAG_UNKNOWN26 = 0x20000000,
CAST_FLAG_HEAL_PREDICTION = 0x40000000, // heal prediction
CAST_FLAG_UNKNOWN28 = 0x80000000,
}; };
enum SpellFlags enum SpellFlags
@ -111,6 +116,7 @@ class SpellCastTargets
void write(ByteBuffer& data) const; void write(ByteBuffer& data) const;
SpellCastTargetsReader ReadForCaster(Unit* caster) { return SpellCastTargetsReader(*this, caster); } SpellCastTargetsReader ReadForCaster(Unit* caster) { return SpellCastTargetsReader(*this, caster); }
void ReadAdditionalData(WorldPacket& data, uint8& cast_flags);
SpellCastTargets& operator=(const SpellCastTargets& target) SpellCastTargets& operator=(const SpellCastTargets& target)
{ {
@ -139,6 +145,9 @@ class SpellCastTargets
m_targetMask = target.m_targetMask; m_targetMask = target.m_targetMask;
m_elevation = target.m_elevation;
m_speed = target.m_speed;
return *this; return *this;
} }
@ -177,6 +186,9 @@ class SpellCastTargets
float m_destX, m_destY, m_destZ; float m_destX, m_destY, m_destZ;
std::string m_strTarget; std::string m_strTarget;
float GetElevation() const { return m_elevation; }
float GetSpeed() const { return m_speed; }
uint32 m_targetMask; uint32 m_targetMask;
private: private:
// objects (can be used at spell creating and after Update at casting // objects (can be used at spell creating and after Update at casting
@ -192,6 +204,9 @@ class SpellCastTargets
ObjectGuid m_srcTransportGUID; ObjectGuid m_srcTransportGUID;
ObjectGuid m_destTransportGUID; ObjectGuid m_destTransportGUID;
uint32 m_itemTargetEntry; uint32 m_itemTargetEntry;
float m_elevation;
float m_speed;
}; };
inline ByteBuffer& operator<< (ByteBuffer& buf, SpellCastTargets const& targets) inline ByteBuffer& operator<< (ByteBuffer& buf, SpellCastTargets const& targets)

View file

@ -32,13 +32,13 @@
void WorldSession::HandleUseItemOpcode(WorldPacket& recvPacket) void WorldSession::HandleUseItemOpcode(WorldPacket& recvPacket)
{ {
uint8 bagIndex, slot; uint8 bagIndex, slot;
uint8 unk_flags; // flags (if 0x02 - some additional data are received) uint8 cast_flags; // flags (if 0x02 - some additional data are received)
uint8 cast_count; // next cast if exists (single or not) uint8 cast_count; // next cast if exists (single or not)
ObjectGuid itemGuid; ObjectGuid itemGuid;
uint32 glyphIndex; // something to do with glyphs? uint32 glyphIndex; // something to do with glyphs?
uint32 spellid; // casted spell id uint32 spellid; // casted spell id
recvPacket >> bagIndex >> slot >> cast_count >> spellid >> itemGuid >> glyphIndex >> unk_flags; recvPacket >> bagIndex >> slot >> cast_count >> spellid >> itemGuid >> glyphIndex >> cast_flags;
// TODO: add targets.read() check // TODO: add targets.read() check
Player* pUser = _player; Player* pUser = _player;
@ -73,7 +73,7 @@ void WorldSession::HandleUseItemOpcode(WorldPacket& recvPacket)
return; return;
} }
DETAIL_LOG("WORLD: CMSG_USE_ITEM packet, bagIndex: %u, slot: %u, cast_count: %u, spellid: %u, Item: %u, glyphIndex: %u, unk_flags: %u, data length = %i", bagIndex, slot, cast_count, spellid, pItem->GetEntry(), glyphIndex, unk_flags, (uint32)recvPacket.size()); DETAIL_LOG("WORLD: CMSG_USE_ITEM packet, bagIndex: %u, slot: %u, cast_count: %u, spellid: %u, Item: %u, glyphIndex: %u, unk_flags: %u, data length = %i", bagIndex, slot, cast_count, spellid, pItem->GetEntry(), glyphIndex, cast_flags, (uint32)recvPacket.size());
ItemPrototype const* proto = pItem->GetProto(); ItemPrototype const* proto = pItem->GetProto();
if (!proto) if (!proto)
@ -157,6 +157,8 @@ void WorldSession::HandleUseItemOpcode(WorldPacket& recvPacket)
targets.Update(pUser); targets.Update(pUser);
targets.ReadAdditionalData(recvPacket, cast_flags);
if (!pItem->IsTargetValidForItemUse(targets.getUnitTarget())) if (!pItem->IsTargetValidForItemUse(targets.getUnitTarget()))
{ {
// free gray item after use fail // free gray item after use fail
@ -336,11 +338,11 @@ void WorldSession::HandleGameobjectReportUse(WorldPacket& recvPacket)
void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket) void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket)
{ {
uint32 spellId; uint32 spellId, glyphIndex;
uint8 cast_count, unk_flags; uint8 cast_count, cast_flags;
recvPacket >> cast_count; recvPacket >> cast_count;
recvPacket >> spellId; recvPacket >> spellId >> glyphIndex;
recvPacket >> unk_flags; // flags (if 0x02 - some additional data are received) recvPacket >> cast_flags; // flags (if 0x02 - some additional data are received)
// ignore for remote control state (for player case) // ignore for remote control state (for player case)
Unit* mover = _player->GetMover(); Unit* mover = _player->GetMover();
@ -350,8 +352,8 @@ void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket)
return; return;
} }
DEBUG_LOG("WORLD: got cast spell packet, spellId - %u, cast_count: %u, unk_flags %u, data length = %i", DEBUG_LOG("WORLD: got cast spell packet, spellId - %u, cast_count: %u, cast_flags %u, data length = %i",
spellId, cast_count, unk_flags, (uint32)recvPacket.size()); spellId, cast_count, cast_flags, (uint32)recvPacket.size());
SpellEntry const* spellInfo = sSpellStore.LookupEntry(spellId); SpellEntry const* spellInfo = sSpellStore.LookupEntry(spellId);
@ -389,24 +391,7 @@ void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket)
recvPacket >> targets.ReadForCaster(mover); recvPacket >> targets.ReadForCaster(mover);
// some spell cast packet including more data (for projectiles?) targets.ReadAdditionalData(recvPacket, cast_flags);
if (unk_flags & 0x02)
{
uint8 unk1;
recvPacket >> Unused<float>(); // unk1, coords?
recvPacket >> Unused<float>(); // unk1, coords?
recvPacket >> unk1; // >> 1 or 0
if (unk1)
{
ObjectGuid guid; // guid - unused
MovementInfo movementInfo;
recvPacket >> Unused<uint32>(); // >> CMSG_MOVE_STOP
recvPacket >> guid.ReadAsPacked();
recvPacket >> movementInfo;
}
}
// auto-selection buff level base at target level (in spellInfo) // auto-selection buff level base at target level (in spellInfo)
if (Unit* target = targets.getUnitTarget()) if (Unit* target = targets.getUnitTarget())

View file

@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__ #ifndef __REVISION_NR_H__
#define __REVISION_NR_H__ #define __REVISION_NR_H__
#define REVISION_NR "12091" #define REVISION_NR "0086"
#endif // __REVISION_NR_H__ #endif // __REVISION_NR_H__