diff --git a/data/sql/updates/pending_db_world/rev_1684616338556943400.sql b/data/sql/updates/pending_db_world/rev_1684616338556943400.sql new file mode 100644 index 000000000..1e4b8691a --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1684616338556943400.sql @@ -0,0 +1,48 @@ +-- +UPDATE `creature_template` SET `ScriptName` = '' WHERE `entry` IN (19523, 19524); + +DELETE FROM `creature_template_movement` WHERE (`CreatureId` IN (19523, 19524)); +INSERT INTO `creature_template_movement` (`CreatureId`, `Ground`, `Swim`, `Flight`, `Rooted`, `Chase`, `Random`, `InteractionPauseTimer`) VALUES +(19523, 0, 0, 1, 1, 0, 0, 0), +(19524, 0, 0, 1, 1, 0, 0, 0); + +DELETE FROM `creature_text` WHERE `CreatureID` IN (16809, 19523, 19524); +INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES +(16809, 0, 0, '%s roars!', 16, 0, 100, 0, 0, 0, 14029, 0, 'O\'mrogg Burning Maul'), + +(19523, 0, 0, 'Smash!', 14, 0, 100, 0, 0, 10306, 14046, 0, 'O\'mrogg Left Head Aggro 1'), +(19523, 1, 0, 'If you nice me let you live.', 14, 0, 100, 0, 0, 10308, 14048, 0, 'O\'mrogg Left Head Aggro 2'), +(19523, 2, 0, 'Me hungry!', 14, 0, 100, 0, 0, 10309, 16918, 0, 'O\'mrogg Left Head Aggro 3'), + +(19523, 3, 0, 'You stay here. Me go kill someone else!', 14, 0, 100, 0, 0, 10303, 16898, 0, 'O\'mrogg Left Head Beatdown'), +(19523, 3, 1, 'We kill someone else!', 14, 0, 100, 0, 0, 10302, 16895, 0, 'O\'mrogg Left Head Beatdown'), +(19523, 3, 2, 'Me not like this one...', 14, 0, 100, 0, 0, 10300, 14043, 0, 'O\'mrogg Left Head Beatdown'), +(19523, 3, 3, 'We kill his friend!', 14, 0, 100, 0, 0, 10301, 14045, 0, 'O\'mrogg Left Head Beatdown'), + +(19523, 4, 0, 'Me get bored.', 14, 0, 100, 0, 0, 10305, 16902, 0, 'O\'mrogg Left Head Beatdown Reply'), +(19523, 5, 0, 'Ha ha ha.', 14, 0, 100, 0, 0, 10304, 16900, 0, 'O\'mrogg Left Head Beatdown Reply'), + +(19523, 6, 0, 'Hey...', 14, 0, 100, 0, 0, 10307, 16917, 0, 'O\'mrogg Left Head Kill Reply'), +(19523, 7, 0, 'This one die easy!', 14, 0, 100, 0, 0, 10310, 16922, 0, 'O\'mrogg Left Head Kill'), + +(19523, 8, 0, 'This all... your fault!', 14, 0, 100, 0, 0, 10311, 16924, 0, 'O\'mrogg Left Head Death'), + +(19524, 0, 0, 'Why don\'t you let me do the talking?', 14, 0, 100, 0, 0, 10317, 14047, 0, 'O\'mrogg Right Head Aggro 1'), +(19524, 1, 0, 'No, we will NOT let you live.', 14, 0, 100, 0, 0, 10318, 16916, 0, 'O\'mrogg Right Head Aggro 2'), +(19524, 2, 0, 'You\'re always hungry. That\'s why we so fat!', 14, 0, 100, 0, 0, 10319, 16919, 0, 'O\'mrogg Right Head Aggro 3'), + +(19524, 3, 0, 'What are you doing?', 14, 0, 100, 0, 0, 10315, 16901, 0, 'O\'mrogg Right Head Beatdown'), +(19524, 3, 1, 'I\'m not done yet, idiot!', 14, 0, 100, 0, 0, 10313, 16896, 0, 'O\'mrogg Right Head Beatdown'), +(19524, 3, 2, 'Hey, you numbskull!', 14, 0, 100, 0, 0, 10312, 14044, 0, 'O\'mrogg Right Head Beatdown'), + +(19524, 4, 0, 'Bored? He was almost dead!', 14, 0, 100, 0, 0, 10316, 16903, 0, 'O\'mrogg Right Head Beatdown Reply'), +(19524, 5, 0, 'That\'s not funny!', 14, 0, 100, 0, 0, 10314, 16899, 0, 'O\'mrogg Right Head Beatdown Reply'), + +(19524, 6, 0, 'I\'m tired. You kill next one!', 14, 0, 100, 0, 0, 10320, 16921, 0, 'O\'mrogg Right Head Kill'), +(19524, 7, 0, 'That\'s because I do all the hard work!', 14, 0, 100, 0, 0, 10321, 16923, 0, 'O\'mrogg Right Head Kill Reply'), + +(19524, 8, 0, 'I... hate... you.', 14, 0, 100, 0, 0, 10322, 16925, 0, 'O\'mrogg Right Head Death'); + +DELETE FROM `spell_script_names` WHERE `spell_id` = 30598 AND `ScriptName` = 'spell_burning_maul'; +INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES +(30598, 'spell_burning_maul'); diff --git a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_warbringer_omrogg.cpp b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_warbringer_omrogg.cpp index eb6ebc266..46d074148 100644 --- a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_warbringer_omrogg.cpp +++ b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_warbringer_omrogg.cpp @@ -17,6 +17,8 @@ #include "ScriptMgr.h" #include "ScriptedCreature.h" +#include "SpellScript.h" +#include "TaskScheduler.h" #include "shattered_halls.h" enum Spells @@ -34,32 +36,23 @@ enum Equip EQUIP_BURNING_MAUL = 2 }; -enum Creatures +enum HeadYells { - NPC_LEFT_HEAD = 19523, - NPC_RIGHT_HEAD = 19524 + SAY_ON_AGGRO = 0, + SAY_ON_AGGRO_2, + SAY_ON_AGGRO_3, + SAY_ON_BEATDOWN, + SAY_ON_BEATDOWN_2, + SAY_ON_BEATDOWN_3, + SAY_ON_KILL, + SAY_ON_KILL_2, + SAY_ON_DEATH }; enum Misc { - EMOTE_ENRAGE = 0, - - SETDATA_DATA = 1, - SETDATA_YELL = 1 -}; - -enum Events -{ - EVENT_AGGRO_YELL_1 = 1, - EVENT_AGGRO_YELL_2 = 2, - EVENT_AGGRO_YELL_3 = 3, - EVENT_THREAT_YELL_L_1 = 4, - EVENT_THREAT_YELL_L_2 = 5, - EVENT_THREAT_YELL_L_3 = 6, - EVENT_THREAT_YELL_R_1 = 7, - EVENT_KILL_YELL_LEFT = 8, - EVENT_KILL_YELL_RIGHT = 9, - EVENT_DEATH_YELL = 10 + EMOTE_BURNING_MAUL = 0, + DATA_BURNING_MAUL_END = 1 }; enum Phase @@ -79,217 +72,218 @@ struct boss_warbringer_omrogg : public BossAI }); } - EventMap events2; - - Creature* GetLeftHead() + void HandleHeadTalk(HeadYells yell) { - return summons.GetCreatureWithEntry(NPC_LEFT_HEAD); - } - - Creature* GetRightHead() - { - return summons.GetCreatureWithEntry(NPC_RIGHT_HEAD); - } - - void JustEngagedWith(Unit* /*who*/) override - { - me->SummonCreature(NPC_LEFT_HEAD, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_DEAD_DESPAWN, 0); - me->SummonCreature(NPC_RIGHT_HEAD, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_DEAD_DESPAWN, 0); - - if (Creature* LeftHead = GetLeftHead()) + switch (yell) { - uint8 aggroYell = urand(EVENT_AGGRO_YELL_1, EVENT_AGGRO_YELL_3); - LeftHead->AI()->Talk(aggroYell - 1); - events2.ScheduleEvent(aggroYell, 3000); - } - - _JustEngagedWith(); - scheduler.Schedule(500ms, GROUP_FULL_PHASE, [this](TaskContext context) - { - scheduler.Schedule(12100ms, 17300ms, GROUP_NON_BURNING_PHASE, [this](TaskContext context) + case SAY_ON_AGGRO: { - DoCastAOE(SPELL_THUNDERCLAP); - context.Repeat(17200ms, 24200ms); - }).Schedule(20s, 30s, GROUP_NON_BURNING_PHASE, [this](TaskContext /*context*/) - { - DoCastSelf(SPELL_BEATDOWN); - me->SetUnitFlag(UNIT_FLAG_PACIFIED); - me->SetReactState(REACT_PASSIVE); - scheduler.Schedule(200ms, GROUP_NON_BURNING_PHASE, [this](TaskContext /*context*/) + uint8 group = urand(SAY_ON_AGGRO, SAY_ON_AGGRO_3); + if (Creature* leftHead = instance->GetCreature(DATA_OMROGG_LEFT_HEAD)) { - if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0)) - { - uint8 threatYell = urand(EVENT_THREAT_YELL_L_1, EVENT_THREAT_YELL_R_1); - if (Creature* head = threatYell == EVENT_THREAT_YELL_R_1 ? GetRightHead() : GetLeftHead()) + leftHead->AI()->Talk(group); + _headTalk.Schedule(3600ms, [this, group](TaskContext /*context*/) { - head->AI()->Talk(threatYell - 1); - } - events.ScheduleEvent(threatYell, 3000); - DoResetThreatList(); - me->AddThreat(target, 2250.0f); - scheduler.Schedule(1200ms, GROUP_BURNING_PHASE, [this](TaskContext /*context*/) - { - me->SetReactState(REACT_AGGRESSIVE); - me->RemoveUnitFlag(UNIT_FLAG_PACIFIED); + if (Creature* rightHead = instance->GetCreature(DATA_OMROGG_RIGHT_HEAD)) + rightHead->AI()->Talk(group); }); - } - }).Schedule(40s, 60s, GROUP_NON_BURNING_PHASE, [this](TaskContext /*context*/) + } + break; + } + case SAY_ON_BEATDOWN: + { + if (Creature* leftHead = instance->GetCreature(DATA_OMROGG_LEFT_HEAD)) { - me->SetUnitFlag(UNIT_FLAG_PACIFIED); - me->SetReactState(REACT_PASSIVE); - scheduler.Schedule(1200ms, GROUP_NON_BURNING_PHASE, [this](TaskContext /*context*/) - { - DoCastSelf(SPELL_FEAR); - DoCastSelf(SPELL_BURNING_MAUL); - me->LoadEquipment(EQUIP_BURNING_MAUL); - scheduler.CancelGroup(GROUP_NON_BURNING_PHASE); - scheduler.Schedule(200ms, GROUP_BURNING_PHASE, [this](TaskContext /*context*/) + leftHead->AI()->Talk(SAY_ON_BEATDOWN); + _headTalk.Schedule(3600ms, [this](TaskContext context) { - me->Yell("%s roars!", LANG_UNIVERSAL); - scheduler.Schedule(2200ms, GROUP_BURNING_PHASE, [this](TaskContext /*context*/) + if (Creature* rightHead = instance->GetCreature(DATA_OMROGG_RIGHT_HEAD)) + rightHead->AI()->Talk(SAY_ON_BEATDOWN); + context.Schedule(3600ms, [this](TaskContext context) { - if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0)) + uint8 group = urand(SAY_ON_BEATDOWN_2, SAY_ON_BEATDOWN_3); + if (Creature* leftHead = instance->GetCreature(DATA_OMROGG_LEFT_HEAD)) + leftHead->AI()->Talk(group); + context.Schedule(3600ms, [this, group](TaskContext /*context*/) { - uint8 threatYell = urand(EVENT_THREAT_YELL_L_1, EVENT_THREAT_YELL_R_1); - if (Creature* head = threatYell == EVENT_THREAT_YELL_R_1 ? GetRightHead() : GetLeftHead()) - { - head->AI()->Talk(threatYell - 1); - } - events.ScheduleEvent(threatYell, 3000); - DoResetThreatList(); - me->AddThreat(target, 2250.0f); - me->SetReactState(REACT_AGGRESSIVE); - me->RemoveUnitFlag(UNIT_FLAG_PACIFIED); - } + if (Creature* rightHead = instance->GetCreature(DATA_OMROGG_RIGHT_HEAD)) + rightHead->AI()->Talk(group); + }); }); }); - scheduler.Schedule(4850ms, 8500ms, GROUP_BURNING_PHASE, [this](TaskContext context) - { - DoCastAOE(SPELL_BLAST_WAVE, false); - context.Repeat(4850ms, 8500ms); - }).Schedule(45s, 60s, GROUP_BURNING_PHASE, [this](TaskContext context) - { - me->LoadEquipment(EQUIP_STANDARD); - context.CancelGroup(GROUP_BURNING_PHASE); - scheduler.RescheduleGroup(GROUP_NON_BURNING_PHASE, 5ms); - context.RescheduleGroup(GROUP_NON_BURNING_PHASE, 5ms); - context.RescheduleGroup(GROUP_FULL_PHASE, 1050ms); - }); + } + break; + } + case SAY_ON_KILL: + { + uint8 group = urand(SAY_ON_KILL, SAY_ON_KILL_2); + if (Creature* leftHead = instance->GetCreature(DATA_OMROGG_LEFT_HEAD)) + leftHead->AI()->Talk(group); + _headTalk.Schedule(3600ms, [this, group](TaskContext /*context*/) + { + if (Creature* rightHead = instance->GetCreature(DATA_OMROGG_RIGHT_HEAD)) + rightHead->AI()->Talk(group); }); - }); - }); - context.Repeat(130s, 150s); - }); + break; + } + case SAY_ON_DEATH: + { + if (Creature* leftHead = instance->GetCreature(DATA_OMROGG_LEFT_HEAD)) + leftHead->AI()->Talk(SAY_ON_DEATH); + _headTalk.Schedule(3600ms, [this](TaskContext /*context*/) + { + if (Creature* rightHead = instance->GetCreature(DATA_OMROGG_RIGHT_HEAD)) + rightHead->AI()->Talk(SAY_ON_DEATH); + }); + break; + } + default: + break; + } } - void JustSummoned(Creature* summoned) override + void SetData(uint32 data, uint32) override { - summons.Summon(summoned); - } - - void KilledUnit(Unit* /*victim*/) override - { - Creature* head = nullptr; - uint32 eventId = EVENT_KILL_YELL_LEFT; - if (urand(0, 1)) - { - head = GetLeftHead(); - eventId = EVENT_KILL_YELL_LEFT; - } - else - { - head = GetRightHead(); - eventId = EVENT_KILL_YELL_RIGHT; - } - - if (head) - { - head->AI()->Talk(eventId - 1); - } - events2.ScheduleEvent(eventId, 3000); - } - - void JustDied(Unit* /*killer*/) override - { - Creature* LeftHead = GetLeftHead(); - Creature* RightHead = GetRightHead(); - if (!LeftHead || !RightHead) + if (data != DATA_BURNING_MAUL_END) return; - LeftHead->DespawnOrUnsummon(5000); - RightHead->DespawnOrUnsummon(5000); - LeftHead->AI()->Talk(EVENT_DEATH_YELL - 1); - RightHead->AI()->SetData(SETDATA_DATA, SETDATA_YELL); - instance->SetBossState(DATA_OMROGG, DONE); + scheduler.CancelGroup(GROUP_BURNING_PHASE); + ScheduleNonBurningPhase(); + ScheduleBurningPhase(); + } + + void ScheduleNonBurningPhase() + { + scheduler. + Schedule(12100ms, 17300ms, GROUP_NON_BURNING_PHASE, [this](TaskContext context) + { + DoCastAOE(SPELL_THUNDERCLAP); + context.Repeat(17200ms, 24200ms); + }) + .Schedule(20s, 30s, GROUP_NON_BURNING_PHASE, [this](TaskContext context) + { + DoCastSelf(SPELL_BEATDOWN); + me->AttackStop(); + me->SetReactState(REACT_PASSIVE); + context.Schedule(200ms, GROUP_NON_BURNING_PHASE, [this](TaskContext context) + { + DoResetThreatList(); + if (Unit* newTarget = SelectTarget(SelectTargetMethod::Random, 1)) + me->AddThreat(newTarget, 2250.f); + HandleHeadTalk(SAY_ON_BEATDOWN); + context.Schedule(1200ms, GROUP_NON_BURNING_PHASE, [this](TaskContext /*context*/) + { + me->SetReactState(REACT_AGGRESSIVE); + }); + }); + context.Repeat(); + }); + } + + void ScheduleBurningPhase() + { + scheduler. + Schedule(45s, 60s, GROUP_BURNING_PHASE, [this](TaskContext context) + { + me->AttackStop(); + me->SetReactState(REACT_PASSIVE); + context.CancelGroup(GROUP_NON_BURNING_PHASE); + context.Schedule(1200ms, [this](TaskContext context) + { + DoCastAOE(SPELL_FEAR); + DoCast(SPELL_BURNING_MAUL); + context.Schedule(200ms, [this](TaskContext context) + { + Talk(EMOTE_BURNING_MAUL); + context.Schedule(2200ms, [this](TaskContext context) + { + DoResetThreatList(); + if (Unit* newTarget = SelectTarget(SelectTargetMethod::Random, 1)) + me->AddThreat(newTarget, 2250.f); + me->SetReactState(REACT_AGGRESSIVE); + context.Schedule(4850ms, 8500ms, GROUP_BURNING_PHASE, [this](TaskContext context) + { + DoCastAOE(SPELL_BLAST_WAVE); + context.Repeat(); + }); + }); + }); + }); + + }); + } + + void JustEngagedWith(Unit* who) override + { + BossAI::JustEngagedWith(who); + _headTalk.CancelAll(); + HandleHeadTalk(SAY_ON_AGGRO); + + ScheduleNonBurningPhase(); + ScheduleBurningPhase(); + } + + void KilledUnit(Unit* victim) override + { + if (victim && victim->GetTypeId() == TYPEID_PLAYER) + HandleHeadTalk(SAY_ON_KILL); + } + + void JustDied(Unit* killer) override + { + HandleHeadTalk(SAY_ON_DEATH); + BossAI::JustDied(killer); } void UpdateAI(uint32 diff) override { - events2.Update(diff); - scheduler.Update(diff); - switch (uint32 eventId = events2.ExecuteEvent()) - { - case EVENT_AGGRO_YELL_1: - case EVENT_AGGRO_YELL_2: - case EVENT_AGGRO_YELL_3: - case EVENT_KILL_YELL_LEFT: - case EVENT_THREAT_YELL_L_1: - case EVENT_THREAT_YELL_L_2: - case EVENT_THREAT_YELL_L_3: - if (Creature* RightHead = GetRightHead()) - { - RightHead->AI()->Talk(eventId - 1); - } - break; - case EVENT_KILL_YELL_RIGHT: - case EVENT_THREAT_YELL_R_1: - if (Creature* LeftHead = GetLeftHead()) - { - LeftHead->AI()->Talk(eventId - 1); - } - break; - } + _headTalk.Update(diff); if (!UpdateVictim()) return; - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; - - DoMeleeAttackIfReady(); + scheduler.Update(diff, [this] + { + DoMeleeAttackIfReady(); + }); } + + protected: + TaskScheduler _headTalk; }; -struct npc_omrogg_heads : public NullCreatureAI +class spell_burning_maul : public AuraScript { - npc_omrogg_heads(Creature* creature) : NullCreatureAI(creature) - { - timer = 0; - } + PrepareAuraScript(spell_burning_maul); - void SetData(uint32 data, uint32 value) override + void HandleOnRemove(AuraEffect const* /* aurEff */, AuraEffectHandleModes /* mode */) + { + if (Unit* caster = GetCaster()) { - if (data == SETDATA_DATA && value == SETDATA_YELL) - timer = 1; - } - - void UpdateAI(uint32 diff) override - { - if (timer) + if (Creature* omrogg = caster->ToCreature()) { - timer += diff; - if (timer >= 3000) - { - timer = 0; - Talk(EVENT_DEATH_YELL - 1); - } + omrogg->LoadEquipment(EQUIP_STANDARD); + omrogg->AI()->SetData(DATA_BURNING_MAUL_END, 0); } } - uint32 timer; + } + + void HandleOnApply(AuraEffect const* /* aurEff */, AuraEffectHandleModes /* mode */) + { + if (Unit* caster = GetCaster()) + if (Creature* omrogg = caster->ToCreature()) + omrogg->LoadEquipment(EQUIP_BURNING_MAUL); + } + + void Register() override + { + OnEffectRemove += AuraEffectRemoveFn(spell_burning_maul::HandleOnRemove, EFFECT_1, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL); + OnEffectApply += AuraEffectApplyFn(spell_burning_maul::HandleOnApply, EFFECT_1, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL); + } }; void AddSC_boss_warbringer_omrogg() { RegisterShatteredHallsCreatureAI(boss_warbringer_omrogg); - RegisterShatteredHallsCreatureAI(npc_omrogg_heads); + RegisterSpellScript(spell_burning_maul); } diff --git a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/instance_shattered_halls.cpp b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/instance_shattered_halls.cpp index 7f5fbcee7..7ae1c3304 100644 --- a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/instance_shattered_halls.cpp +++ b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/instance_shattered_halls.cpp @@ -22,9 +22,11 @@ ObjectData const creatureData[] = { - { NPC_GRAND_WARLOCK_NETHEKURSE, DATA_NETHEKURSE }, - { NPC_WARCHIEF_KARGATH, DATA_KARGATH }, - { 0, 0 } + { NPC_GRAND_WARLOCK_NETHEKURSE , DATA_NETHEKURSE }, + { NPC_WARCHIEF_KARGATH , DATA_KARGATH }, + { NPC_OMROGG_LEFT_HEAD , DATA_OMROGG_LEFT_HEAD }, + { NPC_OMROGG_RIGHT_HEAD , DATA_OMROGG_RIGHT_HEAD }, + { 0 , 0 } }; DoorData const doorData[] = diff --git a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/shattered_halls.h b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/shattered_halls.h index 249224ae4..df137d902 100644 --- a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/shattered_halls.h +++ b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/shattered_halls.h @@ -35,7 +35,9 @@ enum DataTypes DATA_PRISONER_1 = 11, DATA_PRISONER_2 = 12, DATA_PRISONER_3 = 13, - DATA_EXECUTIONER = 14 + DATA_EXECUTIONER = 14, + DATA_OMROGG_LEFT_HEAD = 15, + DATA_OMROGG_RIGHT_HEAD = 16 }; enum CreatureIds @@ -44,6 +46,10 @@ enum CreatureIds NPC_WARCHIEF_KARGATH = 16808, NPC_FEL_ORC_CONVERT = 17083, + // O'MROGG + NPC_OMROGG_LEFT_HEAD = 19523, + NPC_OMROGG_RIGHT_HEAD = 19524, + // Trial of the Naaru: Mercy NPC_SHATTERED_EXECUTIONER = 17301, NPC_RIFLEMAN_BROWNBEARD = 17289,