aboutsummaryrefslogtreecommitdiff
path: root/src/server/game
diff options
context:
space:
mode:
Diffstat (limited to 'src/server/game')
-rw-r--r--src/server/game/AI/ScriptedAI/ScriptedCreature.h6
-rwxr-xr-xsrc/server/game/Scripting/ScriptLoader.cpp2
-rwxr-xr-xsrc/server/game/Spells/Spell.cpp38
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()