Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions sql/updates/world/3.3.5/2025_12_130_00_world.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
--
DELETE FROM `creature_formations` WHERE `leaderGUID` = 7483;
INSERT INTO `creature_formations` (`leaderGUID`, `memberGUID`, `dist`, `angle`, `groupAI`, `point_1`, `point_2`) VALUES
(7483,7483,0,0,3,0,0),
(7483,81643,0,0,3,0,0),
(7483,48348,0,0,3,0,0),
(7483,81652,0,0,3,0,0),
(7483,81651,0,0,3,0,0);
208 changes: 122 additions & 86 deletions src/server/scripts/Outland/GruulsLair/boss_high_king_maulgar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,15 @@
*/

/*
* Timers requires update
* The door should open after Maulgar's death, not after all NPCs are dead
* Timers and targets requires to be revisited
*/

#include "ScriptMgr.h"
#include "gruuls_lair.h"
#include "InstanceScript.h"
#include "ObjectAccessor.h"
#include "Map.h"
#include "ScriptedCreature.h"
#include "SpellInfo.h"

enum MaulgarTexts
{
Expand All @@ -38,38 +38,47 @@ enum MaulgarTexts
enum MaulgarSpells
{
// High King Maulgar
SPELL_ARCING_SMASH = 39144,
SPELL_MIGHTY_BLOW = 33230,
SPELL_WHIRLWIND = 33238,
SPELL_BERSERKER_CHARGE = 26561,
SPELL_ROAR = 16508,
SPELL_ARCING_SMASH = 39144,

SPELL_FLURRY = 33232,
SPELL_ROAR = 16508,
SPELL_BERSERKER_CHARGE = 26561,

// Olm the Summoner
SPELL_DARK_DECAY = 33129,
SPELL_DEATH_COIL = 33130,
SPELL_SUMMON_WILD_FELHUNTER = 33131,

// Kiggler the Craed
SPELL_GREATER_POLYMORPH = 33173,
// Kiggler the Crazed
SPELL_LIGHTNING_BOLT = 36152,
SPELL_GREATER_POLYMORPH = 33173,
SPELL_ARCANE_SHOCK = 33175,
SPELL_ARCANE_EXPLOSION = 33237,

// Blindeye the Seer
SPELL_GREATER_PW_SHIELD = 33147,
SPELL_HEAL = 33144,
SPELL_PRAYER_OH = 33152,
SPELL_GREATER_PW_SHIELD = 33147,
SPELL_PRAYER_OF_HEALING = 33152,

// Krosh Firehand
SPELL_GREATER_FIREBALL = 33051,
SPELL_SPELLSHIELD = 33054,
SPELL_SPELL_SHIELD = 33054,
SPELL_BLAST_WAVE = 33061
};

enum MaulgarMisc
{
ACTION_ADD_DEATH = 1
ACTION_OGRE_DEATH = 0
};

static constexpr std::array<uint32, 4> OgreData =
{
DATA_KROSH_FIREHAND,
DATA_OLM_THE_SUMMONER,
DATA_KIGGLER_THE_CRAZED,
DATA_BLINDEYE_THE_SEER
};

// 18831 - High King Maulgar
Expand All @@ -81,65 +90,80 @@ struct boss_high_king_maulgar : public BossAI
{
_Reset();
_enraged = false;
SetEquipmentSlots(true);

for (uint32 data : OgreData)
me->GetMap()->Respawn(SPAWN_TYPE_CREATURE, instance->GetData64(data));
}

void JustEngagedWith(Unit* who) override
{
BossAI::JustEngagedWith(who);
Talk(SAY_AGGRO);

scheduler.Schedule(10s, [this](TaskContext task)
{
DoCastVictim(SPELL_ARCING_SMASH);
task.Repeat(10s);
});

scheduler.Schedule(30s, [this](TaskContext task)
{
DoCastSelf(SPELL_WHIRLWIND);
task.Repeat(55s);
});
Talk(SAY_AGGRO);

scheduler.Schedule(40s, [this](TaskContext task)
{
DoCastVictim(SPELL_MIGHTY_BLOW);
task.Repeat(30s, 40s);
});
scheduler
.SetValidator([this]
{
return !me->HasUnitState(UNIT_STATE_CASTING);
})
.Schedule(15s, 20s, [this](TaskContext task)
{
DoCastVictim(SPELL_MIGHTY_BLOW);
task.Repeat(15s, 20s);
})
.Schedule(55s, 65s, [this](TaskContext task)
{
DoCastSelf(SPELL_WHIRLWIND);
task.Repeat(55s, 60s);
})
.Schedule(10s, [this](TaskContext task)
{
DoCastSelf(SPELL_ARCING_SMASH);
task.Repeat(10s);
});
}

void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
{
if (!_enraged && me->HealthBelowPctDamaged(50, damage))
{
scheduler.Schedule(0s, [this](TaskContext /*task*/)
{
_enraged = true;
Talk(SAY_ENRAGE);
DoCastSelf(SPELL_FLURRY);
SetEquipmentSlots(false, EQUIP_UNEQUIP);
});

scheduler.Schedule(0s, 5s, [this](TaskContext task)
{
DoCastSelf(SPELL_ROAR);
task.Repeat(40s, 50s);
});
_enraged = true;

scheduler
.Schedule(0s, [this](TaskContext /*task*/)
{
DoCastSelf(SPELL_FLURRY);
})
.Schedule(0s, 5s, [this](TaskContext task)
{
DoCastVictim(SPELL_ROAR);
task.Repeat(40s, 50s);
})
.Schedule(10s, 15s, [this](TaskContext task)
{
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
DoCast(target, SPELL_BERSERKER_CHARGE);
task.Repeat(20s);
});
}
}

scheduler.Schedule(10s, 15s, [this](TaskContext task)
{
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
DoCast(target, SPELL_BERSERKER_CHARGE);
task.Repeat(20s);
});
void OnSpellCast(SpellInfo const* spellInfo) override
{
if (spellInfo->Id == SPELL_FLURRY)
{
Talk(SAY_ENRAGE);
SetEquipmentSlots(false, EQUIP_UNEQUIP);
}
}

void DoAction(int32 actionId) override
void DoAction(int32 action) override
{
if (!me->IsAlive())
return;

if (actionId == ACTION_ADD_DEATH)
if (action == ACTION_OGRE_DEATH)
Talk(SAY_OGRE_DEATH);
}

Expand All @@ -159,9 +183,6 @@ struct boss_high_king_maulgar : public BossAI
if (!UpdateVictim())
return;

if (me->HasUnitState(UNIT_STATE_CASTING))
return;

scheduler.Update(diff);

DoMeleeAttackIfReady();
Expand All @@ -175,6 +196,12 @@ struct OgreBaseAI : public ScriptedAI
{
OgreBaseAI(Creature* creature) : ScriptedAI(creature), instance(creature->GetInstanceScript()) { }

void InitializeAI() override
{
me->SetCorpseDelay(5, true);
ScriptedAI::InitializeAI();
}

void Reset() override
{
scheduler.CancelAll();
Expand All @@ -194,9 +221,7 @@ struct OgreBaseAI : public ScriptedAI
void JustDied(Unit* /*killer*/) override
{
if (Creature* maulgar = instance->GetCreature(DATA_MAULGAR))
maulgar->AI()->DoAction(ACTION_ADD_DEATH);

instance->SetBossState(DATA_MAULGAR, DONE);
maulgar->AI()->DoAction(ACTION_OGRE_DEATH);
}

void UpdateAI(uint32 diff) override
Expand All @@ -222,21 +247,20 @@ struct boss_olm_the_summoner : public OgreBaseAI
void ScheduleEvents() override
{
scheduler
.Schedule(10s, [this](TaskContext task)
.Schedule(5s, 10s, [this](TaskContext task)
{
DoCastVictim(SPELL_DARK_DECAY);
task.Repeat(20s);
task.Repeat(5s, 10s);
})
.Schedule(5s, 10s, [this](TaskContext task)
{
DoCastVictim(SPELL_DEATH_COIL);
task.Repeat(5s, 15s);
})
.Schedule(0s, 10s, [this](TaskContext task)
{
DoCastSelf(SPELL_SUMMON_WILD_FELHUNTER);
task.Repeat(50s, 60s);
})
.Schedule(20s, [this](TaskContext task)
{
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
DoCast(target, SPELL_DEATH_COIL);
task.Repeat(20s);
});
}
};
Expand All @@ -251,24 +275,34 @@ struct boss_kiggler_the_crazed : public OgreBaseAI
ScriptedAI::AttackStartCaster(who, 40.0f);
}

void SpellHitTarget(WorldObject* target, SpellInfo const* spellInfo) override
{
Unit* unitTarget = target->ToUnit();
if (!unitTarget)
return;

if (spellInfo->Id == SPELL_ARCANE_EXPLOSION)
ModifyThreatByPercent(unitTarget, -100);
}

void ScheduleEvents() override
{
scheduler
.Schedule(5s, [this](TaskContext task)
{
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
DoCast(target, SPELL_GREATER_POLYMORPH);
task.Repeat(15s, 20s);
})
.Schedule(0s, [this](TaskContext task)
{
DoCastVictim(SPELL_LIGHTNING_BOLT);
task.Repeat(2s);
task.Repeat(2s, 3s);
})
.Schedule(5s, 10s, [this](TaskContext task)
{
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
DoCast(target, SPELL_GREATER_POLYMORPH);
task.Repeat(10s, 35s);
})
.Schedule(20s, [this](TaskContext task)
.Schedule(5s, 15s, [this](TaskContext task)
{
DoCastVictim(SPELL_ARCANE_SHOCK);
task.Repeat(20s);
task.Repeat(5s, 20s);
})
.Schedule(30s, [this](TaskContext task)
{
Expand All @@ -283,23 +317,25 @@ struct boss_blindeye_the_seer : public OgreBaseAI
{
boss_blindeye_the_seer(Creature* creature) : OgreBaseAI(creature) { }

void OnSpellCast(SpellInfo const* spellInfo) override
{
if (spellInfo->Id == SPELL_GREATER_PW_SHIELD)
DoCastSelf(SPELL_PRAYER_OF_HEALING);
}

void ScheduleEvents() override
{
scheduler
.Schedule(5s, [this](TaskContext task)
{
DoCastSelf(SPELL_GREATER_PW_SHIELD);
task.Repeat(40s);
})
.Schedule(25s, 40s, [this](TaskContext task)
.Schedule(7s, [this](TaskContext task)
{
DoCastSelf(SPELL_HEAL);
task.Repeat(25s, 40s);
if (Unit* target = DoSelectLowestHpFriendly(250.0f))
DoCast(target, SPELL_HEAL);
task.Repeat(7s);
})
.Schedule(45s, 55s, [this](TaskContext task)
.Schedule(20s, 30s, [this](TaskContext task)
{
DoCastSelf(SPELL_PRAYER_OH);
task.Repeat(35s, 50s);
DoCastSelf(SPELL_GREATER_PW_SHIELD);
task.Repeat(15s, 25s);
});
}
};
Expand All @@ -319,7 +355,7 @@ struct boss_krosh_firehand : public OgreBaseAI
})
.Schedule(0s, [this](TaskContext task)
{
DoCastSelf(SPELL_SPELLSHIELD);
DoCastSelf(SPELL_SPELL_SHIELD);
task.Repeat(30s);
})
.Schedule(10s, 20s, [this](TaskContext task)
Expand All @@ -333,8 +369,8 @@ struct boss_krosh_firehand : public OgreBaseAI
void AddSC_boss_high_king_maulgar()
{
RegisterGruulsLairCreatureAI(boss_high_king_maulgar);
RegisterGruulsLairCreatureAI(boss_olm_the_summoner);
RegisterGruulsLairCreatureAI(boss_kiggler_the_crazed);
RegisterGruulsLairCreatureAI(boss_blindeye_the_seer);
RegisterGruulsLairCreatureAI(boss_olm_the_summoner);
RegisterGruulsLairCreatureAI(boss_krosh_firehand);
}
11 changes: 9 additions & 2 deletions src/server/scripts/Outland/GruulsLair/gruuls_lair.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,20 @@

uint32 const EncounterCount = 2;

enum GLDataTypes
enum GLEncounters
{
// Encounter States/Boss GUIDs
DATA_MAULGAR = 0,
DATA_GRUUL = 1
};

enum GLDataTypes
{
DATA_KROSH_FIREHAND,
DATA_OLM_THE_SUMMONER,
DATA_KIGGLER_THE_CRAZED,
DATA_BLINDEYE_THE_SEER
};

enum GLCreatureIds
{
NPC_MAULGAR = 18831,
Expand Down
Loading