diff --git a/src/game/Server/Opcodes.cpp b/src/game/Server/Opcodes.cpp index a7451fa4..8bb18e1c 100644 --- a/src/game/Server/Opcodes.cpp +++ b/src/game/Server/Opcodes.cpp @@ -646,11 +646,11 @@ void Opcodes::BuildOpcodeList() /*0x249*/ StoreOpcode(CMSG_MAIL_DELETE, "CMSG_MAIL_DELETE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMailDelete); /*0x24A*/ StoreOpcode(CMSG_MAIL_CREATE_TEXT_ITEM, "CMSG_MAIL_CREATE_TEXT_ITEM", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMailCreateTextItem); /*[-ZERO] Need check */ /*0x24B*/ StoreOpcode(SMSG_SPELLLOGMISS, "SMSG_SPELLLOGMISS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide); - /*[-ZERO] Need check */ /*0x24C*/ StoreOpcode(SMSG_SPELLLOGEXECUTE, "SMSG_SPELLLOGEXECUTE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide); /*[-ZERO] Need check */ /*0x24D*/ StoreOpcode(SMSG_DEBUGAURAPROC, "SMSG_DEBUGAURAPROC", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide); /*[-ZERO] Need check */ /*0x24E*/ StoreOpcode(SMSG_PERIODICAURALOG, "SMSG_PERIODICAURALOG", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide); /*[-ZERO] Need check */ /*0x24F*/ StoreOpcode(SMSG_SPELLDAMAGESHIELD, "SMSG_SPELLDAMAGESHIELD", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide); /*[-ZERO] Need check */ /*0x250*/ StoreOpcode(SMSG_SPELLNONMELEEDAMAGELOG, "SMSG_SPELLNONMELEEDAMAGELOG", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide); + /*0x24C*/ StoreOpcode(SMSG_SPELLLOGEXECUTE, "SMSG_SPELLLOGEXECUTE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide); /*0x251*/ StoreOpcode(CMSG_LEARN_TALENT, "CMSG_LEARN_TALENT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLearnTalentOpcode); /*[-ZERO] Need check */ /*0x252*/ StoreOpcode(SMSG_RESURRECT_FAILED, "SMSG_RESURRECT_FAILED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide); /*[-ZERO] Need check */ /*0x253*/ StoreOpcode(CMSG_TOGGLE_PVP, "CMSG_TOGGLE_PVP", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleTogglePvP); diff --git a/src/game/WorldHandlers/Spell.cpp b/src/game/WorldHandlers/Spell.cpp index f0871558..161f721b 100644 --- a/src/game/WorldHandlers/Spell.cpp +++ b/src/game/WorldHandlers/Spell.cpp @@ -3496,112 +3496,96 @@ void Spell::WriteSpellGoTargets(WorldPacket* data) void Spell::SendLogExecute() { - Unit* target = m_targets.getUnitTarget() ? m_targets.getUnitTarget() : m_caster; - WorldPacket data(SMSG_SPELLLOGEXECUTE, (8 + 4 + 4 + 4 + 4 + 8)); - - if (m_caster->GetTypeId() == TYPEID_PLAYER) - { data << m_caster->GetPackGUID(); } - else - { data << target->GetPackGUID(); } + WorldPacket data(SMSG_SPELLLOGEXECUTE, (8 + 4 + 4 + (4 + 4 + 8))); // estimate size + data << m_caster->GetPackGUID(); data << uint32(m_spellInfo->Id); - uint32 count1 = 1; - data << uint32(count1); // count1 (effect count?) - for (uint32 i = 0; i < count1; ++i) + + size_t efcount_pos = data.wpos(); + int32 effectCount = 0; + data << uint32(effectCount); // count1 (effect count) if <=0, SMSG ignored + + size_t starteff_pos = data.wpos(); + for (uint32 i = 0; i < MAX_EFFECT_INDEX; ++i) { - data << uint32(m_spellInfo->Effect[EFFECT_INDEX_0]);// spell effect - uint32 count2 = 1; - data << uint32(count2); // count2 (target count?) - for (uint32 j = 0; j < count2; ++j) - { - switch (m_spellInfo->Effect[EFFECT_INDEX_0]) + data << uint32(m_spellInfo->Effect[i]); // spell effect + data << uint32(1); // count2 placeholder (target count) + + bool hasSpecial = true; + { // this block may be iterated (target count) times + switch (m_spellInfo->Effect[i]) { - case SPELL_EFFECT_POWER_DRAIN: - if (Unit* unit = m_targets.getUnitTarget()) - { data << unit->GetPackGUID(); } - else - { data << uint8(0); } - data << uint32(0); - data << uint32(0); - data << float(0); - break; - case SPELL_EFFECT_ADD_EXTRA_ATTACKS: - if (Unit* unit = m_targets.getUnitTarget()) - { data << unit->GetPackGUID(); } - else - { data << uint8(0); } - data << uint32(0); // count? - break; - case SPELL_EFFECT_INTERRUPT_CAST: - if (Unit* unit = m_targets.getUnitTarget()) - { data << unit->GetPackGUID(); } - else - { data << uint8(0); } - data << uint32(0); // spellid - break; - case SPELL_EFFECT_DURABILITY_DAMAGE: - if (Unit* unit = m_targets.getUnitTarget()) - { data << unit->GetPackGUID(); } - else - { data << uint8(0); } - data << uint32(0); - data << uint32(0); - break; - case SPELL_EFFECT_OPEN_LOCK: - case SPELL_EFFECT_OPEN_LOCK_ITEM: - if (Item* item = m_targets.getItemTarget()) - { data << item->GetPackGUID(); } - else - { data << uint8(0); } - break; - case SPELL_EFFECT_CREATE_ITEM: - data << uint32(m_spellInfo->EffectItemType[EFFECT_INDEX_0]); - break; - case SPELL_EFFECT_SUMMON: - case SPELL_EFFECT_SUMMON_WILD: - case SPELL_EFFECT_SUMMON_GUARDIAN: - case SPELL_EFFECT_TRANS_DOOR: - case SPELL_EFFECT_SUMMON_PET: - case SPELL_EFFECT_SUMMON_POSSESSED: - case SPELL_EFFECT_SUMMON_TOTEM: - case SPELL_EFFECT_SUMMON_OBJECT_WILD: - case SPELL_EFFECT_CREATE_HOUSE: - case SPELL_EFFECT_DUEL: - case SPELL_EFFECT_SUMMON_TOTEM_SLOT1: - case SPELL_EFFECT_SUMMON_TOTEM_SLOT2: - case SPELL_EFFECT_SUMMON_TOTEM_SLOT3: - case SPELL_EFFECT_SUMMON_TOTEM_SLOT4: - case SPELL_EFFECT_SUMMON_PHANTASM: - case SPELL_EFFECT_SUMMON_CRITTER: - case SPELL_EFFECT_SUMMON_OBJECT_SLOT1: - case SPELL_EFFECT_SUMMON_OBJECT_SLOT2: - case SPELL_EFFECT_SUMMON_OBJECT_SLOT3: - case SPELL_EFFECT_SUMMON_OBJECT_SLOT4: - case SPELL_EFFECT_SUMMON_DEMON: - if (Unit* unit = m_targets.getUnitTarget()) - { data << unit->GetPackGUID(); } - else if (m_targets.getItemTargetGuid()) - { data << m_targets.getItemTargetGuid().WriteAsPacked(); } - else if (GameObject* go = m_targets.getGOTarget()) - { data << go->GetPackGUID(); } - else - { data << uint8(0); } // guid - break; - case SPELL_EFFECT_FEED_PET: - data << uint32(m_targets.getItemTargetEntry()); - break; - case SPELL_EFFECT_DISMISS_PET: - if (Unit* unit = m_targets.getUnitTarget()) - { data << unit->GetPackGUID(); } - else - { data << uint8(0); } - break; - default: - return; + case SPELL_EFFECT_POWER_DRAIN: + data << m_targets.getUnitTargetGuid(); + data << uint32(0); + data << uint32(0); + data << float(0); + break; + case SPELL_EFFECT_ADD_EXTRA_ATTACKS: + data << m_targets.getUnitTargetGuid(); + data << uint32(0); // count? + break; + case SPELL_EFFECT_INTERRUPT_CAST: + data << m_targets.getUnitTargetGuid(); + data << uint32(0); // spellid being interrupted + break; + case SPELL_EFFECT_DURABILITY_DAMAGE: + data << m_targets.getUnitTargetGuid(); + data << uint32(0); + data << uint32(0); // if both -1, a separate handling + break; + case SPELL_EFFECT_CREATE_ITEM: // here target is not the item but SELF + data << uint32(m_spellInfo->EffectItemType[i]); + break; + case SPELL_EFFECT_FEED_PET: // here we may get both SELF and item targets + data << m_targets.getItemTargetEntry(); + break; + case SPELL_EFFECT_RESURRECT: + case SPELL_EFFECT_DISPEL: + case SPELL_EFFECT_THREAT: + case SPELL_EFFECT_DISTRACT: + case SPELL_EFFECT_SANCTUARY: + case SPELL_EFFECT_THREAT_ALL: + case SPELL_EFFECT_DISPEL_MECHANIC: + case SPELL_EFFECT_RESURRECT_NEW: + case SPELL_EFFECT_ATTACK_ME: + case SPELL_EFFECT_SKIN_PLAYER_CORPSE: + case SPELL_EFFECT_MODIFY_THREAT_PERCENT: + case SPELL_EFFECT_126: + case SPELL_EFFECT_DISMISS_PET: // case is handled separately but has the same input + case SPELL_EFFECT_OPEN_LOCK: // 2 cases are handled separately but have the same input + case SPELL_EFFECT_OPEN_LOCK_ITEM: + case SPELL_EFFECT_INSTAKILL: // separate. Also self instakill will not be logged by client + if (ObjectGuid guid = GetPrefilledOrUnitTargetGuid(SpellEffectIndex(i))) + { data << guid; } + else if (m_targets.getItemTargetGuid()) + { data << m_targets.getItemTargetGuid(); } + else if (m_targets.getGOTargetGuid()) + { data << m_targets.getGOTargetGuid(); } + break; + case SPELL_EFFECT_DUMMY: + break; + default: // including SPELL_EFFECT_DUMMY w/separate handling + hasSpecial = false; // prevent duplicate logging for spells logged w/o target + break; } } + if (hasSpecial) + { + ++effectCount; + starteff_pos = data.wpos(); + } + else + data.wpos(starteff_pos); } + if (!effectCount) // no effect with special handling + { + effectCount = 1; + data << uint32(m_spellInfo->Effect[EFFECT_INDEX_0]); + data << uint32(1); + } + data.put(efcount_pos, effectCount); m_caster->SendMessageToSet(&data, true); }