Skip to content

Commit

Permalink
SL: Rework Murmur Intro RP (#710)
Browse files Browse the repository at this point in the history
* Add worldstates that handle the respawn of runners between groups in murmur room

* remove hardcoded shadow bolt attacks from casts npcs onto murmur, will now get handled via db

* Check if target has string id insteat of movementtype

* pGroup->group

* Simplyfy the code a bit more and jsut check for targets that have string assigned to get killed

* Finish murmur rework

* Add cabal assasin handling

* When engaging blackheart the inciter, despawn assasins

* update requested changed
  • Loading branch information
miraco authored Dec 25, 2024
1 parent be092be commit f189b1e
Show file tree
Hide file tree
Showing 5 changed files with 153 additions and 62 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ EndScriptData */
#include "shadow_labyrinth.h"
#include "AI/ScriptDevAI/base/CombatAI.h"
#include "Spells/Scripts/SpellScript.h"
#include "World/WorldStateDefines.h"

enum
{
Expand Down Expand Up @@ -105,6 +106,9 @@ struct boss_blackheart_the_inciterAI : public CombatAI
case 1: DoBroadcastText(SAY_AGGRO_2, m_creature); break;
}

m_creature->GetMap()->GetVariableManager().SetVariable(WORLD_STATE_SHADOW_LAB_ASSASIN_01, 0);
m_creature->GetMap()->GetVariableManager().SetVariable(WORLD_STATE_SHADOW_LAB_ASSASIN_02, 0);

if (m_instance)
m_instance->SetData(TYPE_INCITER, IN_PROGRESS);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

/* ScriptData
SDName: Boss_Murmur
SD%Complete: 75
SD%Complete: 90
SDComment: Sonic Boom and Murmur's Touch require additional research and core support
SDCategory: Auchindoun, Shadow Labyrinth
EndScriptData */
Expand Down Expand Up @@ -48,24 +48,27 @@ enum
enum MurmurActions
{
MURMUR_ACTION_MAX,
// After door opens 2 Cabal Spellbinder run out of the room, both get killed from murmur individually
MURMUR_INTRO_KILL_01,
MURMUR_INTRO_KILL_02,
// Random cast of Suppresion Blast or Murmurs Wrath
MURMUR_OOC_RP_ATTACK,
MURMUR_OOC_CASTER_ATTACK
};

struct boss_murmurAI : public CombatAI
{
boss_murmurAI(Creature* creature) : CombatAI(creature, MURMUR_ACTION_MAX),
m_instance(static_cast<ScriptedInstance*>(creature->GetInstanceData())), m_bIsRegularMode(creature->GetMap()->IsRegularDifficulty())
m_instance(static_cast<ScriptedInstance*>(creature->GetInstanceData())), m_bIsRegularMode(creature->GetMap()->IsRegularDifficulty()),
m_firstCast(false)
{
AddCustomAction(MURMUR_INTRO_KILL_01, true, [&]() { HandleIntroKill01(); }, TIMER_COMBAT_OOC);
AddCustomAction(MURMUR_INTRO_KILL_02, true, [&]() { HandleIntroKill02(); }, TIMER_COMBAT_OOC);
AddCustomAction(MURMUR_OOC_RP_ATTACK, true, [&]() { HandleOocAttack(); }, TIMER_COMBAT_OOC);
AddCustomAction(MURMUR_OOC_CASTER_ATTACK, true, [&]() { HandleOocCasterAttack(); }, TIMER_COMBAT_OOC);
}

ScriptedInstance* m_instance;
bool m_bIsRegularMode;

GuidVector spellbindersVector;
GuidVector summonersVector;
bool m_firstCast;

uint32 m_uiResonanceTimer;
uint32 m_uiThunderingStormTimer;
Expand All @@ -83,10 +86,33 @@ struct boss_murmurAI : public CombatAI
{
if (eventType == AI_EVENT_CUSTOM_A)
{
ResetTimer(MURMUR_OOC_CASTER_ATTACK, urand(8000, 10000));
ResetTimer(MURMUR_OOC_RP_ATTACK, urand(8000, 10000));
m_instance->GetCreatureGuidVectorFromStorage(NPC_CABAL_SPELLBINDER, spellbindersVector);
m_instance->GetCreatureGuidVectorFromStorage(NPC_CABAL_SUMMONER, summonersVector);
// Murmur can cast Supression Blast first after door opens
// resulting in a higher timer to kill the 2 Spellbinders that run out of the room
ResetTimer(MURMUR_INTRO_KILL_01, urand(0, 5000));
ResetTimer(MURMUR_INTRO_KILL_02, urand(0, 5000));
// Murmur can start casting Supression Blast pretty fast after door opens
ResetTimer(MURMUR_OOC_RP_ATTACK, urand(0, 3000));
}
}

// After door opens 2 Cabal Spellbinder run out of the room, both get killed from murmur individually
void HandleIntroKill01()
{
std::vector<Creature*> const* killTarget = m_creature->GetMap()->GetCreatures(MURMURS_WRATH_TARGETS_01);
if (killTarget)
{
for (Creature* creature : *killTarget)
DoCastSpellIfCan(creature, SPELL_MURMURS_WRATH);
}
}

void HandleIntroKill02()
{
std::vector<Creature*> const* killTarget = m_creature->GetMap()->GetCreatures(MURMURS_WRATH_TARGETS_02);
if (killTarget)
{
for (Creature* creature : *killTarget)
DoCastSpellIfCan(creature, SPELL_MURMURS_WRATH);
}
}

Expand All @@ -95,71 +121,43 @@ struct boss_murmurAI : public CombatAI
if (m_creature->IsInCombat())
return;

// kill one that's moving
if (urand(0, 1))
// First cast after door opens should always be a Suprression Blast
if (!m_firstCast)
{
GuidVector moversVector;
for (ObjectGuid& guid : spellbindersVector)
{
if (Creature* creature = m_creature->GetMap()->GetCreature(guid))
{
if (creature->GetMotionMaster()->GetCurrentMovementGeneratorType() == WAYPOINT_MOTION_TYPE)
{
moversVector.push_back(guid);
}
}
}
for (ObjectGuid& guid : summonersVector)
DoCastSpellIfCan(nullptr, SPELL_SUPPRESSION_BLAST);
m_firstCast = true;
}
else
{
// Kill a moving target
if (urand(0, 1))
{
if (Creature* creature = m_creature->GetMap()->GetCreature(guid))
GuidVector WrathTargetGuid;
std::vector<Creature*> const* WrathTarget = m_creature->GetMap()->GetCreatures(MURMURS_WRATH_TARGETS_03);
if (WrathTarget)
{
if (creature->GetMotionMaster()->GetCurrentMovementGeneratorType() == WAYPOINT_MOTION_TYPE)
{
moversVector.push_back(guid);
}
for (Creature* creature : *WrathTarget)
if(creature->IsAlive() && !creature->IsInCombat())
WrathTargetGuid.push_back(creature->GetObjectGuid());
}
}
if (moversVector.size() > 0)
{
if (ObjectGuid& guid = moversVector[urand(0, moversVector.size() - 1)])

if (WrathTargetGuid.size() > 0)
{
ObjectGuid guid = WrathTargetGuid[urand(0, WrathTargetGuid.size() - 1)];
if (Creature* creature = m_creature->GetMap()->GetCreature(guid))
{
DoCastSpellIfCan(creature, SPELL_MURMURS_WRATH);
}
}
}
}
// stun 5 targets
else
DoCastSpellIfCan(nullptr, SPELL_SUPPRESSION_BLAST);
}
// stun 5 targets
else
DoCastSpellIfCan(nullptr, SPELL_SUPPRESSION_BLAST);

ResetTimer(MURMUR_OOC_RP_ATTACK, 3000);
}

void HandleOocCasterAttack()
{
if (m_creature->IsInCombat())
return;

for (ObjectGuid& guid : spellbindersVector)
{
if (Creature* creature = m_creature->GetMap()->GetCreature(guid))
{
m_creature->AI()->SendAIEvent(AI_EVENT_CUSTOM_EVENTAI_A, m_creature, creature);
}
}
for (ObjectGuid& guid : summonersVector)
{
if (Creature* creature = m_creature->GetMap()->GetCreature(guid))
{
m_creature->AI()->SendAIEvent(AI_EVENT_CUSTOM_EVENTAI_A, m_creature, creature);
}
}

ResetTimer(MURMUR_OOC_CASTER_ATTACK, urand(3000, 8000));
}

void OnSpellCast(SpellEntry const* spellInfo, Unit* /*target*/) override
{
if (spellInfo->Id == SPELL_SONIC_BOOM || spellInfo->Id == SPELL_SONIC_BOOM_H)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,57 @@ void instance_shadow_labyrinth::OnCreatureRespawn(Creature* creature)
}
}

// The Screaming Hall
// All Worldstates get Activated via database when door opens
void instance_shadow_labyrinth::OnCreatureGroupDespawn(CreatureGroup* group, Creature* /*pCreature*/)
{

switch (group->GetGroupId())
{
// Blackheart the Inciter room
// All groups have a chance to spawn assasins
case SL_BLACKHEAT_GROUP_01:
case SL_BLACKHEAT_GROUP_02:
case SL_BLACKHEAT_GROUP_03:
case SL_BLACKHEAT_GROUP_04:
case SL_BLACKHEAT_GROUP_05:
case SL_BLACKHEAT_GROUP_06:
case SL_BLACKHEAT_GROUP_07:
case SL_BLACKHEAT_GROUP_08:
case SL_BLACKHEAT_GROUP_09:
case SL_BLACKHEAT_GROUP_10:
case SL_BLACKHEAT_GROUP_11:
case SL_BLACKHEAT_GROUP_12:
{
switch (urand(0, 5))
{
case 0:
instance->GetVariableManager().SetVariable(WORLD_STATE_SHADOW_LAB_ASSASIN_01, 1);
}

switch (urand(0, 5))
{
case 0:
instance->GetVariableManager().SetVariable(WORLD_STATE_SHADOW_LAB_ASSASIN_02, 1);
}
break;
}
// Murmur Room
case SL_SPAWN_GROUP_043:
instance->GetVariableManager().SetVariable(WORLD_STATE_SHADOW_LAB_GROUP_49, 0);
break;
case SL_SPAWN_GROUP_044:
instance->GetVariableManager().SetVariable(WORLD_STATE_SHADOW_LAB_GROUP_50, 0);
break;
case SL_SPAWN_GROUP_045:
instance->GetVariableManager().SetVariable(WORLD_STATE_SHADOW_LAB_GROUP_51, 0);
break;
case SL_SPAWN_GROUP_046:
instance->GetVariableManager().SetVariable(WORLD_STATE_SHADOW_LAB_GROUP_52, 0);
break;
}
}

void instance_shadow_labyrinth::Load(const char* chrIn)
{
if (!chrIn)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,33 @@ enum

SPELL_BANISH = 30231, // spell is handled in creature_template_addon;
SPELL_SHAPE_OF_BEAST = 33949,

// Blackheart the Inciter
SL_BLACKHEAT_GROUP_01 = 5550030,
SL_BLACKHEAT_GROUP_02 = 5550031,
SL_BLACKHEAT_GROUP_03 = 5550032,
SL_BLACKHEAT_GROUP_04 = 5550033,
SL_BLACKHEAT_GROUP_05 = 5550034,
SL_BLACKHEAT_GROUP_06 = 5550035,
SL_BLACKHEAT_GROUP_07 = 5550036,
SL_BLACKHEAT_GROUP_08 = 5550037,
SL_BLACKHEAT_GROUP_09 = 5550038,
SL_BLACKHEAT_GROUP_10 = 5550039,
SL_BLACKHEAT_GROUP_11 = 5550040,
SL_BLACKHEAT_GROUP_12 = 5550041,
SL_BLACKHEAT_GROUP_13 = 5550042,


SL_SPAWN_GROUP_043 = 5550064, // SpawnGroup that stops respawning of first runner
SL_SPAWN_GROUP_044 = 5550065, // SpawnGroup that stops respawning of 2nd runner
SL_SPAWN_GROUP_045 = 5550066, // SpawnGroup that stops respawning of third runner
SL_SPAWN_GROUP_046 = 5550067, // SpawnGroup that stops respawning of third runner
};

const std::string MURMURS_WRATH_TARGETS_01 = "SL_MURMUR_WRATH_TARGET_01";
const std::string MURMURS_WRATH_TARGETS_02 = "SL_MURMUR_WRATH_TARGET_02";
const std::string MURMURS_WRATH_TARGETS_03 = "SL_MURMUR_WRATH_TARGET_03";

class instance_shadow_labyrinth : public ScriptedInstance
{
public:
Expand All @@ -47,6 +72,8 @@ class instance_shadow_labyrinth : public ScriptedInstance
void OnCreatureDeath(Creature* pCreature) override;
void OnCreatureRespawn(Creature* creature) override;

void OnCreatureGroupDespawn(CreatureGroup* pGroup, Creature* pCreature) override;

void SetData(uint32 uiType, uint32 uiData) override;
uint32 GetData(uint32 uiType) const override;

Expand Down
13 changes: 12 additions & 1 deletion src/game/World/WorldStateDefines.h
Original file line number Diff line number Diff line change
Expand Up @@ -382,7 +382,18 @@ enum WorldStateID : int32
WORLD_STATE_SHADOW_LAB_GROUP_35 = 5550010, // 2 Possible group versions
WORLD_STATE_SHADOW_LAB_GROUP_40 = 5550011, // 2 Possible group versions
WORLD_STATE_SHADOW_LAB_GROUP_41 = 5550012, // 2 Possible group versions
WORLD_STATE_SHADOW_LAB_GROUP_42 = 5550013, // 2 Possible group versions
WORLD_STATE_SHADOW_LAB_GROUP_42 = 5550013, // 2 Possible group versions
// The Screaming Hall
// Worldstates that handle the respawn of runners between the groups in Murmur room
// Activated via database when door opens, deactivated when spawn_group died
WORLD_STATE_SHADOW_LAB_GROUP_48 = 5550014, // 2 Runners that instantly die after reaching last waypoint
WORLD_STATE_SHADOW_LAB_GROUP_49 = 5550015, // First runner
WORLD_STATE_SHADOW_LAB_GROUP_50 = 5550016, // 2nd runner
WORLD_STATE_SHADOW_LAB_GROUP_51 = 5550017, // 3rd runner
WORLD_STATE_SHADOW_LAB_GROUP_52 = 5550018, // 4th and 5th runner
// Cabal Assasins
WORLD_STATE_SHADOW_LAB_ASSASIN_01 = 5550019,
WORLD_STATE_SHADOW_LAB_ASSASIN_02 = 5550020,

// Sethekk Halls
WORLD_STATE_SETHEKK_GROUP_12 = 5560001, // 2 Possible group versions
Expand Down

0 comments on commit f189b1e

Please sign in to comment.