diff options
Diffstat (limited to 'src/server/game/Spells/Spell.cpp')
-rwxr-xr-x | src/server/game/Spells/Spell.cpp | 38 |
1 files changed, 24 insertions, 14 deletions
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index f5e5572734b..1655256666f 100755 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -4040,41 +4040,47 @@ void Spell::SendSpellGo() m_caster->SendMessageToSet(&data, true); } +/// Writes miss and hit targets for a SMSG_SPELL_GO packet void Spell::WriteSpellGoTargets(WorldPacket* data) { // This function also fill data for channeled spells: // m_needAliveTargetMask req for stop channelig if one target die - uint32 hit = m_UniqueGOTargetInfo.size(); // Always hits on GO - uint32 miss = 0; for (std::list<TargetInfo>::iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit) { if ((*ihit).effectMask == 0) // No effect apply - all immuned add state - { // possibly SPELL_MISS_IMMUNE2 for this?? ihit->missCondition = SPELL_MISS_IMMUNE2; - ++miss; - } - else if ((*ihit).missCondition == SPELL_MISS_NONE) - ++hit; - else - ++miss; } - *data << (uint8)hit; - for (std::list<TargetInfo>::const_iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit) + // Hit and miss target counts are both uint8, that limits us to 255 targets for each + // sending more than 255 targets crashes the client (since count sent would be wrong) + // Spells like 40647 (with a huge radius) can easily reach this limit (spell might need + // target conditions but we still need to limit the number of targets sent and keeping + // correct count for both hit and miss). + + uint32 hit = 0; + size_t hitPos = data->wpos(); + *data << (uint8)0; // placeholder + for (std::list<TargetInfo>::const_iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end() && hit <= 255; ++ihit) { if ((*ihit).missCondition == SPELL_MISS_NONE) // Add only hits { *data << uint64(ihit->targetGUID); m_channelTargetEffectMask |=ihit->effectMask; + ++hit; } } - for (std::list<GOTargetInfo>::const_iterator ighit = m_UniqueGOTargetInfo.begin(); ighit != m_UniqueGOTargetInfo.end(); ++ighit) + for (std::list<GOTargetInfo>::const_iterator ighit = m_UniqueGOTargetInfo.begin(); ighit != m_UniqueGOTargetInfo.end() && hit <= 255; ++ighit) + { *data << uint64(ighit->targetGUID); // Always hits + ++hit; + } - *data << (uint8)miss; - for (std::list<TargetInfo>::const_iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit) + uint32 miss = 0; + size_t missPos = data->wpos(); + *data << (uint8)0; // placeholder + for (std::list<TargetInfo>::const_iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end() && miss <= 255; ++ihit) { if (ihit->missCondition != SPELL_MISS_NONE) // Add only miss { @@ -4082,11 +4088,15 @@ void Spell::WriteSpellGoTargets(WorldPacket* data) *data << uint8(ihit->missCondition); if (ihit->missCondition == SPELL_MISS_REFLECT) *data << uint8(ihit->reflectResult); + ++miss; } } // Reset m_needAliveTargetMask for non channeled spell if (!m_spellInfo->IsChanneled()) m_channelTargetEffectMask = 0; + + data->put<uint8>(hitPos, (uint8)hit); + data->put<uint8>(missPos, (uint8)miss); } void Spell::SendLogExecute() |