diff options
Diffstat (limited to 'src/server/game')
| -rw-r--r-- | src/server/game/AI/ScriptedAI/ScriptedCreature.h | 6 | ||||
| -rwxr-xr-x | src/server/game/Scripting/ScriptLoader.cpp | 2 | ||||
| -rwxr-xr-x | src/server/game/Spells/Spell.cpp | 38 |
3 files changed, 30 insertions, 16 deletions
diff --git a/src/server/game/AI/ScriptedAI/ScriptedCreature.h b/src/server/game/AI/ScriptedAI/ScriptedCreature.h index ba0a94d2590..aa46d555b7d 100644 --- a/src/server/game/AI/ScriptedAI/ScriptedCreature.h +++ b/src/server/game/AI/ScriptedAI/ScriptedCreature.h @@ -41,8 +41,10 @@ class SummonList : public std::list<uint64> template <class Predicate> void DoAction(int32 info, Predicate& predicate, uint16 max = 0) { - Trinity::Containers::RandomResizeList<uint64, Predicate>(*this, predicate, max); - for (iterator i = begin(); i != end(); ) + // We need to use a copy of SummonList here, otherwise original SummonList would be modified + std::list<uint64> listCopy = *this; + Trinity::Containers::RandomResizeList<uint64, Predicate>(listCopy, predicate, max); + for (iterator i = listCopy.begin(); i != listCopy.end(); ) { Creature* summon = Unit::GetCreature(*me, *i++); if (summon && summon->IsAIEnabled) diff --git a/src/server/game/Scripting/ScriptLoader.cpp b/src/server/game/Scripting/ScriptLoader.cpp index e05f35ffbf7..ac0d9466736 100755 --- a/src/server/game/Scripting/ScriptLoader.cpp +++ b/src/server/game/Scripting/ScriptLoader.cpp @@ -319,6 +319,7 @@ void AddSC_bug_trio(); void AddSC_boss_sartura(); void AddSC_boss_skeram(); void AddSC_boss_twinemperors(); +void AddSC_boss_ouro(); void AddSC_mob_anubisath_sentinel(); void AddSC_instance_temple_of_ahnqiraj(); void AddSC_wailing_caverns(); //Wailing caverns @@ -940,6 +941,7 @@ void AddKalimdorScripts() AddSC_boss_sartura(); AddSC_boss_skeram(); AddSC_boss_twinemperors(); + AddSC_boss_ouro(); AddSC_mob_anubisath_sentinel(); AddSC_instance_temple_of_ahnqiraj(); AddSC_wailing_caverns(); //Wailing caverns 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() |
