From 5f6656fcd40c8e70a2ea655d85248f1c2f1b00db Mon Sep 17 00:00:00 2001
From: Ovalord <1Don7H4v3@m41L.com>
Date: Sat, 27 Jan 2018 22:09:55 +0100
Subject: [PATCH] Scripts/GB: implement Forgemaster Throngus encounter
---
.../4.3.4/custom_2018_01_27_00_world.sql | 102 +++
.../GrimBatol/boss_forgemaster_throngus.cpp | 767 ++++++++++++++++++
.../EasternKingdoms/GrimBatol/grim_batol.h | 6 +-
.../GrimBatol/instance_grim_batol.cpp | 5 +
.../eastern_kingdoms_script_loader.cpp | 2 +
5 files changed, 881 insertions(+), 1 deletion(-)
create mode 100644 sql/updates/world/4.3.4/custom_2018_01_27_00_world.sql
create mode 100644 src/server/scripts/EasternKingdoms/GrimBatol/boss_forgemaster_throngus.cpp
diff --git a/sql/updates/world/4.3.4/custom_2018_01_27_00_world.sql b/sql/updates/world/4.3.4/custom_2018_01_27_00_world.sql
new file mode 100644
index 00000000000..0b45affb07d
--- /dev/null
+++ b/sql/updates/world/4.3.4/custom_2018_01_27_00_world.sql
@@ -0,0 +1,102 @@
+-- Template Updates
+UPDATE `creature_template` SET `Scriptname`= 'boss_forgemaster_throngus', `flags_extra`= `flags_extra`| 0x40000000, `mechanic_immune_mask`= 617299839 WHERE `entry`= 40177;
+UPDATE `creature_template` SET `flags_extra`= `flags_extra`| 0x40000000 | 1, `mechanic_immune_mask`= 617299839, `minlevel`= 87, `maxlevel`= 87 WHERE `entry`= 48702;
+-- Cave In Stalker
+UPDATE `creature_template` SET `minlevel`= 85, `maxlevel`= 85, `faction`= 7, `unit_flags`= 34078720, `flags_extra`= 131, `ScriptName`= 'npc_throngus_cave_in' WHERE `entry`= 40228;
+-- Fixate Stalker
+UPDATE `creature_template` SET `minlevel`= 80, `maxlevel`= 80, `faction`= 35, `unit_flags`= 33554432, `flags_extra`= 128 WHERE `entry`= 40255;
+-- Fire Patch
+UPDATE `creature_template` SET `minlevel`= 80, `maxlevel`= 80, `faction`= 7, `unit_flags`= 33554432, `flags_extra`= 128 WHERE `entry`= 48711;
+
+-- Template Addons
+DELETE FROM `creature_template_addon` WHERE `entry` IN (40228, 48711);
+INSERT INTO `creature_template_addon` (`entry`, `auras`) VALUES
+(40228, '74990'),
+(48711, '90752');
+
+-- Spells
+DELETE FROM `spell_script_names` WHERE `ScriptName` IN
+('spell_throngus_mighty_stomp',
+'spell_throngus_pick_weapon',
+'spell_throngus_flame_arrow_barrage',
+'spell_throngus_flaming_arrow',
+'spell_throngus_personal_phalanx',
+'spell_throngus_personal_phalanx_aoe',
+'spell_throngus_fixate_effect',
+'spell_throngus_burning_dual_blades',
+'spell_throngus_disorienting_roar',
+'spell_throngus_encumbered',
+'spell_throngus_impaling_slam');
+
+INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES
+(74984, 'spell_throngus_mighty_stomp'),
+(75000, 'spell_throngus_pick_weapon'),
+(74945, 'spell_throngus_flame_arrow_barrage'),
+(74944, 'spell_throngus_flaming_arrow'),
+(90810, 'spell_throngus_flaming_arrow'),
+(74908, 'spell_throngus_personal_phalanx'),
+(74914, 'spell_throngus_personal_phalanx_aoe'),
+(75071, 'spell_throngus_fixate_effect'),
+(74981, 'spell_throngus_burning_dual_blades'),
+(90738, 'spell_throngus_burning_dual_blades'),
+(74976, 'spell_throngus_disorienting_roar'),
+(90737, 'spell_throngus_disorienting_roar'),
+(75007, 'spell_throngus_encumbered'),
+(90729, 'spell_throngus_encumbered'),
+(75056, 'spell_throngus_impaling_slam'),
+(90756, 'spell_throngus_impaling_slam');
+
+-- Texts
+DELETE FROM `creature_text` WHERE `CreatureID`= 40177;
+INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `Comment`) VALUES
+(40177, 0, 0, 'NEIN! Throngus wieder ausgepeitscht, wenn er nicht fertig wird!', 14, 0, 100, 0, 0, 18943, 47777, 'Forgemaster Throngus - Say Aggro'),
+(40177, 1, 0, 'You not get through defenses!', 14, 0, 100, 0, 0, 18947, 47781, 'Forgemaster Throngus - Say Personal Phalanx'),
+(40177, 2, 0, 'Oh, this gonna HURT!', 14, 0, 100, 53, 0, 18949, 47782, 'Forgemaster Throngus - Say Mace'),
+(40177, 3, 0, 'Throngus SLICE you up!', 14, 0, 100, 0, 0, 18948, 47783, 'Forgemaster Throngus - Say Swords'),
+(40177, 4, 0, '|TInterface\\Icons\\inv_shield_76.blp:20|t%s equips his |cFFFF0000Shield|r and gains |cFFFF0000|Hspell:74908|h[Personal Phalanx]|h|r!', 41, 0, 100, 0, 0, 0, 40747, 'Forgemaster Throngus - Announce Personal Phalanx'),
+(40177, 5, 0, '|TInterface\\Icons\\inv_mace_15.blp:20|t%s equips his |cFFFF0000Mace|r and is |cFFFF0000|Hspell:75007|h[Encumbered]|h|r!', 41, 0, 100, 53, 0, 0, 40239, 'Forgemaster Throngus - Announce Mace'),
+(40177, 6, 0, '|TInterface\\Icons\\ability_dualwield.blp:20|t%s equips his |cFFFF0000Swords|r and gains |cFFFF0000|Hspell:74981|h[Dual Blades]|h|r!', 41, 0, 100, 0, 0, 0, 40746, 'Forgemaster Throngus - Announce Swords'),
+(40177, 7, 0, '$n is impaled!', 41, 0, 100, 0, 0, 0, 30718, 'Forgemaster Throngus - Announce Impaled'),
+(40177, 8, 0, 'Throngus use your corpse on body. Somewhere...', 14, 0, 100, 0, 0, 18944, 47778, 'Forgemaster Throngus - Slay 1'),
+(40177, 8, 1, 'You break easy!', 14, 0, 100, 0, 0, 18945, 47779, 'Forgemaster Throngus - Slay 2'),
+(40177, 9, 0, 'Death... Good choice. Not best choice maybe, but better than fail and live.', 14, 0, 100, 0, 0, 18946, 47780, 'Forgemaster Throngus to Player');
+
+
+-- Conditions
+DELETE FROM `conditions` WHERE `SourceEntry` IN (74945, 75071) AND `SourceTypeOrReferenceId`= 13;
+INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ScriptName`, `Comment`) VALUES
+(13, 1, 74945, 0, 0, 31, 0, 3, 40197, 0, 0, 0, '', 'Flame Arrow Barrage - Target Twilight Archer'),
+(13, 1, 75071, 0, 0, 31, 0, 3, 40255, 0, 0, 0, '', 'Fixate Effect - Target Fixate Stalker');
+
+-- Proc Entries
+DELETE FROM `spell_proc` WHERE `SpellId` IN (74981, 90738, 74976, 90737, 90759);
+INSERT INTO `spell_proc` (`SpellId`, `ProcFlags`, `SpellTypeMask`, `SpellPhaseMask`, `Cooldown`) VALUES
+(74981, 0x00000004, 1, 0, 8400),
+(90738, 0x00000004, 1, 0, 8400),
+(90759, 0x00000004, 1, 0, 2000);
+
+INSERT INTO `spell_proc` (`SpellId`, `SchoolMask`, `ProcFlags`, `SpellTypeMask`, `SpellPhaseMask`, `HitMask`) VALUES
+(74976, 1|2|4|8|16|32|64, 0x00015510, 7, 1, 0),
+(90737, 1|2|4|8|16|32|64, 0x00015510, 7, 1, 0);
+
+DELETE FROM `creature_onkill_reward` WHERE `creature_id` IN (40177, 48702);
+INSERT INTO `creature_onkill_reward` (`creature_id`, `CurrencyId1`, `CurrencyCount1`) VALUES
+(40177, 395, 7000),
+(48702, 395, 7000);
+
+UPDATE `creature_template` SET `lootid`= 40177 WHERE `entry`= 40177;
+UPDATE `creature_template` SET `lootid`= 48702 WHERE `entry`= 48702;
+DELETE FROM creature_loot_template WHERE entry IN (40177, 48702);
+INSERT INTO `creature_loot_template` (`Entry`, `Item`, `Chance`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`) VALUES
+(40177, 56119, 0, 1, 1, 1, 1),
+(40177, 56118, 0, 1, 1, 1, 1),
+(40177, 56120, 0, 1, 1, 1, 1),
+(40177, 56121, 0, 1, 1, 1, 1),
+(40177, 56122, 0, 1, 1, 1, 1);
+
+INSERT INTO `creature_loot_template` (`Entry`, `Item`, `Chance`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`) VALUES
+(48702, 56448, 0, 1, 1, 1, 1),
+(48702, 56447, 0, 1, 1, 1, 1),
+(48702, 56445, 0, 1, 1, 1, 1),
+(48702, 56449, 0, 1, 1, 1, 1),
+(48702, 56446, 0, 1, 1, 1, 1);
diff --git a/src/server/scripts/EasternKingdoms/GrimBatol/boss_forgemaster_throngus.cpp b/src/server/scripts/EasternKingdoms/GrimBatol/boss_forgemaster_throngus.cpp
new file mode 100644
index 00000000000..45f03ad6409
--- /dev/null
+++ b/src/server/scripts/EasternKingdoms/GrimBatol/boss_forgemaster_throngus.cpp
@@ -0,0 +1,767 @@
+/*
+* Copyright (C) 2008-2018 TrinityCore
+*
+* This program is free software; you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by the
+* Free Software Foundation; either version 2 of the License, or (at your
+* option) any later version.
+*
+* This program is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+* more details.
+*
+* You should have received a copy of the GNU General Public License along
+* with this program. If not, see .
+*/
+
+#include "ObjectMgr.h"
+#include "ScriptMgr.h"
+#include "ScriptedCreature.h"
+#include "SpellScript.h"
+#include "SpellAuraEffects.h"
+#include "Player.h"
+#include "grim_batol.h"
+
+enum Spells
+{
+ // Forgemaster Throngus
+ SPELL_MIGHTY_STOMP = 74984,
+ SPELL_PICK_WEAPON = 75000,
+ SPELL_PERSONAL_PHALANX = 74908,
+ SPELL_PERSONAL_PHALANX_SUMMON_FIXATE_TRIGGER = 74914,
+ SPELL_SHIELD_VISUAL = 94588,
+ SPELL_FIXATE_EFFECT = 75071,
+ SPELL_FLAMING_SHIELD = 90819,
+ SPELL_BURNING_DUAL_BLADES = 74981,
+ SPELL_DISORIENTING_ROAR = 74976,
+ SPELL_BURNING_FLAMES = 90759,
+ SPELL_ENCUMBERED = 75007,
+ SPELL_IMPALING_SLAM = 75056,
+
+ // Cave In Stalker
+ SPELL_CAVE_IN_VISUAL = 74987
+};
+
+enum Events
+{
+ EVENT_MIGHTY_STOMP = 1,
+ EVENT_PICK_WEAPON,
+ EVENT_FIXATE_PLAYER,
+ EVENT_FIXATE_EFFECT,
+ EVENT_FLAMING_SHIELD,
+ EVENT_DISORIENTING_ROAR,
+ EVENT_IMPALING_SLAM
+};
+
+enum Actions
+{
+ ACTION_PICK_WEAPON = 1,
+ ACTION_START_PHALLANX,
+ ACTION_END_PHALLANX,
+};
+
+enum Weapons
+{
+ WEAPON_TO_BE_DECIDED = -1,
+ WEAPON_PERSONAL_PHALANX = 0,
+ WEAPON_DUAL_BLADES = 1,
+ WEAPON_MACE = 2
+};
+
+enum WeaponModels
+{
+ WEAPON_MODEL_SWORD = 64435,
+ WEAPON_MODEL_MACE = 49737
+};
+
+enum Texts
+{
+ SAY_AGGRO = 0,
+ SAY_PERSONAL_PHALANX = 1,
+ SAY_MACE = 2,
+ SAY_DUAL_BLADES = 3,
+ SAY_ANNOUNCE_PERSONAL_PHALANX = 4,
+ SAY_ANNOUNCE_MACE = 5,
+ SAY_ANNOUNCE_DUAL_BLADES = 6,
+ SAY_ANNOUNCE_IMPALE = 7,
+ SAY_SLAY = 8,
+ SAY_DEATH = 9
+};
+
+enum AuraStacks
+{
+ STACK_AMOUNT_DISORIENTING_ROAR_HC = 3
+};
+
+enum Seats
+{
+ SEAT_THRONGUS = 0
+};
+
+class boss_forgemaster_throngus : public CreatureScript
+{
+ public:
+ boss_forgemaster_throngus() : CreatureScript("boss_forgemaster_throngus") { }
+
+ struct boss_forgemaster_throngusAI : public BossAI
+ {
+ boss_forgemaster_throngusAI(Creature* creature) : BossAI(creature, DATA_FORGEMASTER_THRONGUS)
+ {
+ Initialize();
+ }
+
+ void Initialize()
+ {
+ _lastWeapon = WEAPON_TO_BE_DECIDED;
+ }
+
+ void Reset() override
+ {
+ Initialize();
+ _Reset();
+ }
+
+ void JustEngagedWith(Unit* /*who*/) override
+ {
+ _JustEngagedWith();
+ Talk(SAY_AGGRO);
+ instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me);
+ events.ScheduleEvent(EVENT_MIGHTY_STOMP, Seconds(6) + Milliseconds(500));
+ events.ScheduleEvent(EVENT_PICK_WEAPON, Seconds(10));
+ }
+
+ void KilledUnit(Unit* victim) override
+ {
+ if (victim->GetTypeId() == TYPEID_PLAYER)
+ Talk(SAY_SLAY);
+ }
+
+ void JustDied(Unit* /*killer*/) override
+ {
+ _JustDied();
+ Talk(SAY_DEATH);
+ summons.DespawnAll();
+ instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
+ }
+
+ void EnterEvadeMode(EvadeReason /*why*/) override
+ {
+ _EnterEvadeMode();
+ summons.DespawnAll();
+ instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
+ _DespawnAtEvade();
+ }
+
+ void DoAction(int32 action) override
+ {
+ switch (action)
+ {
+ case ACTION_PICK_WEAPON:
+ {
+ uint8 selectedWeapon = RAND(WEAPON_PERSONAL_PHALANX, WEAPON_MACE);
+ // Make sure that we will never get the same weapon twice in a row
+ if (_lastWeapon == selectedWeapon && selectedWeapon < WEAPON_MACE)
+ selectedWeapon += 1;
+ else if (_lastWeapon == selectedWeapon && selectedWeapon == WEAPON_MACE)
+ selectedWeapon = RAND(WEAPON_PERSONAL_PHALANX, WEAPON_DUAL_BLADES);
+
+ _lastWeapon = selectedWeapon;
+ switch (selectedWeapon)
+ {
+ case WEAPON_PERSONAL_PHALANX:
+ DoCastSelf(SPELL_PERSONAL_PHALANX, true);
+ DoCastSelf(SPELL_SHIELD_VISUAL, true);
+ Talk(SAY_PERSONAL_PHALANX);
+ Talk(SAY_ANNOUNCE_PERSONAL_PHALANX);
+ events.RescheduleEvent(EVENT_FIXATE_PLAYER, Seconds(1));
+ if (IsHeroic())
+ events.ScheduleEvent(EVENT_FLAMING_SHIELD, Seconds(3));
+ break;
+ case WEAPON_DUAL_BLADES:
+ DoCastSelf(SPELL_BURNING_DUAL_BLADES, true);
+ Talk(SAY_DUAL_BLADES);
+ Talk(SAY_ANNOUNCE_DUAL_BLADES);
+ events.RescheduleEvent(EVENT_DISORIENTING_ROAR, Seconds(5));
+ if (IsHeroic())
+ DoCastSelf(SPELL_BURNING_FLAMES, true);
+ break;
+ case WEAPON_MACE:
+ DoCastSelf(SPELL_ENCUMBERED, true);
+ Talk(SAY_MACE);
+ Talk(SAY_ANNOUNCE_MACE);
+ events.RescheduleEvent(EVENT_IMPALING_SLAM, Seconds(6));
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ case ACTION_START_PHALLANX:
+ me->AttackStop();
+ me->SetReactState(REACT_PASSIVE);
+ me->AddUnitState(UNIT_STATE_CANNOT_TURN);
+ break;
+ case ACTION_END_PHALLANX:
+ me->SetReactState(REACT_AGGRESSIVE);
+ me->RemoveAurasDueToSpell(SPELL_FLAMING_SHIELD);
+ me->ClearUnitState(UNIT_STATE_CANNOT_TURN);
+ summons.DespawnEntry(NPC_FIXATE_STALKER);
+ break;
+ default:
+ break;
+
+ }
+ }
+
+ void PassengerBoarded(Unit* passenger, int8 seatId, bool apply) override
+ {
+ if (!me->GetVehicleKit())
+ return;
+
+ if (apply)
+ Talk(SAY_ANNOUNCE_IMPALE, passenger);
+ }
+
+ void JustSummoned(Creature* summon) override
+ {
+ summons.Summon(summon);
+
+ switch (summon->GetEntry())
+ {
+ case NPC_FIXATE_STALKER:
+ events.ScheduleEvent(EVENT_FIXATE_EFFECT, Milliseconds(400));
+ break;
+ default:
+ break;
+ }
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim())
+ return;
+
+ events.Update(diff);
+
+ if (me->HasUnitState(UNIT_STATE_CASTING) && !me->HasAura(SPELL_PERSONAL_PHALANX))
+ return;
+
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_MIGHTY_STOMP:
+ if (!me->HasAura(SPELL_PERSONAL_PHALANX))
+ DoCastAOE(SPELL_MIGHTY_STOMP);
+ events.Repeat(Seconds(49));
+ break;
+ case EVENT_PICK_WEAPON:
+ DoCastSelf(SPELL_PICK_WEAPON);
+ events.Repeat(Seconds(35) + Milliseconds(500));
+ break;
+ case EVENT_FIXATE_PLAYER:
+ if (me->HasAura(SPELL_PERSONAL_PHALANX))
+ {
+ summons.DespawnEntry(NPC_FIXATE_STALKER);
+ DoCastAOE(SPELL_PERSONAL_PHALANX_SUMMON_FIXATE_TRIGGER, true);
+ events.Repeat(Seconds(8) + Milliseconds(500));
+ }
+ break;
+ case EVENT_FIXATE_EFFECT:
+ if (Creature* stalker = me->FindNearestCreature(NPC_FIXATE_STALKER, 500.0f, true))
+ DoCast(stalker, SPELL_FIXATE_EFFECT);
+ break;
+ case EVENT_FLAMING_SHIELD:
+ DoCastSelf(SPELL_FLAMING_SHIELD, true);
+ break;
+ case EVENT_DISORIENTING_ROAR:
+ if (me->CanDualWield())
+ {
+ DoCastAOE(SPELL_DISORIENTING_ROAR);
+ events.Repeat(Seconds(22));
+ }
+ break;
+ case EVENT_IMPALING_SLAM:
+ if (me->GetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID) == WEAPON_MODEL_MACE)
+ {
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, NonTankTargetSelector(me, true)))
+ DoCast(target, SPELL_IMPALING_SLAM);
+ events.Repeat(Seconds(15) + Milliseconds(500));
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ DoMeleeAttackIfReady();
+ }
+ private:
+ int8 _lastWeapon;
+ };
+
+ CreatureAI* GetAI(Creature *creature) const override
+ {
+ return GetGrimBatolAI(creature);
+ }
+};
+
+// The following script is needed to prevent permanent resets due to a core bug
+class npc_throngus_cave_in : public CreatureScript
+{
+ public:
+ npc_throngus_cave_in() : CreatureScript("npc_throngus_cave_in") { }
+
+ struct npc_throngus_cave_inAI : public ScriptedAI
+ {
+ npc_throngus_cave_inAI(Creature* creature) : ScriptedAI(creature) { }
+
+ void IsSummonedBy(Unit* /*summoner*/) override
+ {
+ DoCastAOE(SPELL_CAVE_IN_VISUAL);
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ }
+ };
+
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetGrimBatolAI(creature);
+ }
+};
+
+class spell_throngus_mighty_stomp : public SpellScriptLoader
+{
+ public:
+ spell_throngus_mighty_stomp() : SpellScriptLoader("spell_throngus_mighty_stomp") { }
+
+ class spell_throngus_mighty_stomp_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_throngus_mighty_stomp_SpellScript);
+
+ void FilterTargets(std::list& targets)
+ {
+ if (targets.empty())
+ return;
+
+ Trinity::Containers::RandomResize(targets, 1);
+ }
+
+ void HandleHit(SpellEffIndex effIndex)
+ {
+ PreventHitEffect(effIndex);
+ if (Unit* target = GetHitUnit())
+ target->CastSpell(target, GetSpellInfo()->Effects[EFFECT_0].TriggerSpell, true);
+ }
+
+ void Register()
+ {
+ OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_throngus_mighty_stomp_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
+ OnEffectHitTarget += SpellEffectFn(spell_throngus_mighty_stomp_SpellScript::HandleHit, EFFECT_0, SPELL_EFFECT_FORCE_CAST);
+ }
+ };
+
+ SpellScript* GetSpellScript() const override
+ {
+ return new spell_throngus_mighty_stomp_SpellScript();
+ }
+};
+
+class spell_throngus_pick_weapon : public SpellScriptLoader
+{
+ public:
+ spell_throngus_pick_weapon() : SpellScriptLoader("spell_throngus_pick_weapon") { }
+
+ class spell_throngus_pick_weapon_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_throngus_pick_weapon_SpellScript);
+
+ void HandleScriptEffect(SpellEffIndex /*effIndex*/)
+ {
+ if (GetCaster()->GetEntry() == BOSS_FORGEMASTER_THRONGUS)
+ GetCaster()->ToCreature()->AI()->DoAction(ACTION_PICK_WEAPON);
+ }
+
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_throngus_pick_weapon_SpellScript::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
+ };
+
+ SpellScript* GetSpellScript() const override
+ {
+ return new spell_throngus_pick_weapon_SpellScript();
+ }
+};
+
+class spell_throngus_flame_arrow_barrage : public SpellScriptLoader
+{
+ public:
+ spell_throngus_flame_arrow_barrage() : SpellScriptLoader("spell_throngus_flame_arrow_barrage") { }
+
+ class spell_throngus_flame_arrow_barrage_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_throngus_flame_arrow_barrage_SpellScript);
+
+ void FilterTargets(std::list& targets)
+ {
+ if (targets.empty())
+ return;
+
+ Trinity::Containers::RandomResize(targets, 5);
+ }
+
+ void HandleHit(SpellEffIndex effIndex)
+ {
+ PreventHitEffect(effIndex);
+ if (Unit* target = GetHitUnit())
+ target->CastSpell(target, GetSpellInfo()->Effects[EFFECT_0].TriggerSpell, true);
+ }
+
+ void Register() override
+ {
+ OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_throngus_flame_arrow_barrage_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY);
+ OnEffectHitTarget += SpellEffectFn(spell_throngus_flame_arrow_barrage_SpellScript::HandleHit, EFFECT_0, SPELL_EFFECT_FORCE_CAST);
+ }
+ };
+
+ SpellScript* GetSpellScript() const override
+ {
+ return new spell_throngus_flame_arrow_barrage_SpellScript();
+ }
+};
+
+class spell_throngus_flaming_arrow : public SpellScriptLoader
+{
+ public:
+ spell_throngus_flaming_arrow() : SpellScriptLoader("spell_throngus_flaming_arrow") { }
+
+ class spell_throngus_flaming_arrow_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_throngus_flaming_arrow_SpellScript);
+
+ void FilterTargets(std::list& targets)
+ {
+ if (targets.empty())
+ return;
+
+ Trinity::Containers::RandomResize(targets, 1);
+ }
+
+ void Register() override
+ {
+ OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_throngus_flaming_arrow_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
+ }
+ };
+
+ SpellScript* GetSpellScript() const override
+ {
+ return new spell_throngus_flaming_arrow_SpellScript();
+ }
+};
+
+class spell_throngus_personal_phalanx : public SpellScriptLoader
+{
+ public:
+ spell_throngus_personal_phalanx() : SpellScriptLoader("spell_throngus_personal_phalanx") { }
+
+ class spell_throngus_personal_phalanx_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_throngus_personal_phalanx_AuraScript);
+
+ bool Validate(SpellInfo const* spellInfo) override
+ {
+ return ValidateSpellInfo(
+ {
+ static_cast(spellInfo->Effects[EFFECT_2].BasePoints),
+ SPELL_FLAMING_SHIELD
+ });
+ }
+
+ void OnApply(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
+ {
+ if (Unit* caster = GetOwner()->ToUnit())
+ {
+ caster->CastSpell(caster, aurEff->GetAmount(), true);
+
+ if (Creature* throngus = caster->ToCreature())
+ throngus->AI()->DoAction(ACTION_START_PHALLANX);
+ }
+ }
+
+ void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ if (Unit* caster = GetOwner()->ToUnit())
+ {
+ if (Creature* throngus = caster->ToCreature())
+ throngus->AI()->DoAction(ACTION_END_PHALLANX);
+ }
+ }
+
+ void Register() override
+ {
+ OnEffectApply += AuraEffectApplyFn(spell_throngus_personal_phalanx_AuraScript::OnApply, EFFECT_2, SPELL_AURA_MOD_PACIFY, AURA_EFFECT_HANDLE_REAL);
+ OnEffectRemove += AuraEffectRemoveFn(spell_throngus_personal_phalanx_AuraScript::OnRemove, EFFECT_2, SPELL_AURA_MOD_PACIFY, AURA_EFFECT_HANDLE_REAL);
+ }
+ };
+
+ AuraScript* GetAuraScript() const override
+ {
+ return new spell_throngus_personal_phalanx_AuraScript();
+ }
+};
+
+class spell_throngus_personal_phalanx_aoe : public SpellScriptLoader
+{
+ public:
+ spell_throngus_personal_phalanx_aoe() : SpellScriptLoader("spell_throngus_personal_phalanx_aoe") { }
+
+ class spell_throngus_personal_phalanx_aoe_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_throngus_personal_phalanx_aoe_SpellScript);
+
+ void FilterTargets(std::list& targets)
+ {
+ if (targets.empty())
+ return;
+
+ Trinity::Containers::RandomResize(targets, 1);
+ }
+
+ void HandleSummon(SpellEffIndex effIndex)
+ {
+ PreventHitDefaultEffect(effIndex);
+ GetHitUnit()->CastSpell(GetHitUnit(), GetSpellInfo()->Effects[effIndex].TriggerSpell, true);
+ }
+
+ void Register() override
+ {
+ OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_throngus_personal_phalanx_aoe_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
+ OnEffectHitTarget += SpellEffectFn(spell_throngus_personal_phalanx_aoe_SpellScript::HandleSummon, EFFECT_0, SPELL_EFFECT_FORCE_CAST);
+ }
+ };
+
+ SpellScript* GetSpellScript() const override
+ {
+ return new spell_throngus_personal_phalanx_aoe_SpellScript();
+ }
+};
+
+class spell_throngus_fixate_effect : public SpellScriptLoader
+{
+ public:
+ spell_throngus_fixate_effect() : SpellScriptLoader("spell_throngus_fixate_effect") { }
+
+ class spell_throngus_fixate_effect_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_throngus_fixate_effect_SpellScript);
+
+ void HandleHit(SpellEffIndex /*effIndex*/)
+ {
+ if (Unit* caster = GetCaster())
+ caster->SetOrientation(caster->GetAngle(GetHitUnit()));
+ }
+
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_throngus_fixate_effect_SpellScript::HandleHit, EFFECT_0, SPELL_EFFECT_APPLY_AURA);
+ }
+ };
+
+ SpellScript* GetSpellScript() const override
+ {
+ return new spell_throngus_fixate_effect_SpellScript();
+ }
+};
+
+class spell_throngus_burning_dual_blades : public SpellScriptLoader
+{
+ public:
+ spell_throngus_burning_dual_blades() : SpellScriptLoader("spell_throngus_burning_dual_blades") { }
+
+ class spell_throngus_burning_dual_blades_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_throngus_burning_dual_blades_AuraScript);
+
+ void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ if (Unit* caster = GetOwner()->ToUnit())
+ {
+ caster->SetCanDualWield(true);
+ caster->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, WEAPON_MODEL_SWORD);
+ caster->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 1, WEAPON_MODEL_SWORD);
+ }
+ }
+
+ void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ if (Unit* caster = GetOwner()->ToUnit())
+ {
+ caster->SetCanDualWield(false);
+ caster->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, 0);
+ caster->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 1, 0);
+ }
+ }
+
+ void Register() override
+ {
+ OnEffectApply += AuraEffectApplyFn(spell_throngus_burning_dual_blades_AuraScript::OnApply, EFFECT_0, SPELL_AURA_MOD_HIT_CHANCE, AURA_EFFECT_HANDLE_REAL);
+ OnEffectRemove += AuraEffectRemoveFn(spell_throngus_burning_dual_blades_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_MOD_HIT_CHANCE, AURA_EFFECT_HANDLE_REAL);
+ }
+ };
+
+ AuraScript* GetAuraScript() const override
+ {
+ return new spell_throngus_burning_dual_blades_AuraScript();
+ }
+};
+
+class spell_throngus_disorienting_roar : public SpellScriptLoader
+{
+ public:
+ spell_throngus_disorienting_roar() : SpellScriptLoader("spell_throngus_disorienting_roar") { }
+
+ class spell_throngus_disorienting_roar_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_throngus_disorienting_roar_SpellScript);
+
+ void HandleHeroicDifficulty()
+ {
+ if (Unit* target = GetHitUnit())
+ if (target->GetMap()->IsHeroic())
+ if (Aura* disorientingRoar = target->GetAura(GetSpellInfo()->Id))
+ disorientingRoar->SetStackAmount(STACK_AMOUNT_DISORIENTING_ROAR_HC);
+ }
+
+ void Register() override
+ {
+ AfterHit += SpellHitFn(spell_throngus_disorienting_roar_SpellScript::HandleHeroicDifficulty);
+ }
+ };
+
+ SpellScript* GetSpellScript() const override
+ {
+ return new spell_throngus_disorienting_roar_SpellScript();
+ }
+
+ class spell_throngus_disorienting_roar_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_throngus_disorienting_roar_AuraScript);
+
+ bool CheckProc(ProcEventInfo& /*eventInfo*/)
+ {
+ if (Aura* aura = GetAura())
+ {
+ uint8 stack = aura->GetStackAmount();
+ if (stack > 1)
+ {
+ aura->SetStackAmount(stack - 1);
+ return false;
+ }
+ else
+ aura->Remove();
+ }
+ return false;
+ }
+
+ void Register() override
+ {
+ DoCheckProc += AuraCheckProcFn(spell_throngus_disorienting_roar_AuraScript::CheckProc);
+ }
+ };
+
+ AuraScript* GetAuraScript() const override
+ {
+ return new spell_throngus_disorienting_roar_AuraScript();
+ }
+};
+
+class spell_throngus_encumbered : public SpellScriptLoader
+{
+ public:
+ spell_throngus_encumbered() : SpellScriptLoader("spell_throngus_encumbered") { }
+
+ class spell_throngus_encumbered_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_throngus_encumbered_AuraScript);
+
+ void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ if (Unit* caster = GetOwner()->ToUnit())
+ caster->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, WEAPON_MODEL_MACE);
+ }
+
+ void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ if (Unit* caster = GetOwner()->ToUnit())
+ caster->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, 0);
+ }
+
+ void Register() override
+ {
+ OnEffectApply += AuraEffectApplyFn(spell_throngus_encumbered_AuraScript::OnApply, EFFECT_0, SPELL_AURA_MOD_DAMAGE_PERCENT_DONE, AURA_EFFECT_HANDLE_REAL);
+ OnEffectRemove += AuraEffectRemoveFn(spell_throngus_encumbered_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_MOD_DAMAGE_PERCENT_DONE, AURA_EFFECT_HANDLE_REAL);
+ }
+ };
+
+ AuraScript* GetAuraScript() const override
+ {
+ return new spell_throngus_encumbered_AuraScript();
+ }
+};
+
+class spell_throngus_impaling_slam : public SpellScriptLoader
+{
+ public:
+ spell_throngus_impaling_slam() : SpellScriptLoader("spell_throngus_impaling_slam") { }
+
+ class spell_throngus_impaling_slam_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_throngus_impaling_slam_AuraScript);
+
+ void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ if (Unit* caster = GetCaster())
+ if (Unit* target = GetOwner()->ToUnit())
+ if (caster->GetVehicleKit())
+ target->EnterVehicle(caster, SEAT_THRONGUS);
+ }
+
+ void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ if (Unit* target = GetOwner()->ToUnit())
+ if (target->GetVehicleBase())
+ target->ExitVehicle();
+ }
+
+ void Register() override
+ {
+ OnEffectApply += AuraEffectApplyFn(spell_throngus_impaling_slam_AuraScript::OnApply, EFFECT_2, SPELL_AURA_PERIODIC_DAMAGE, AURA_EFFECT_HANDLE_REAL);
+ OnEffectRemove += AuraEffectRemoveFn(spell_throngus_impaling_slam_AuraScript::OnRemove, EFFECT_2, SPELL_AURA_PERIODIC_DAMAGE, AURA_EFFECT_HANDLE_REAL);
+ }
+ };
+
+ AuraScript* GetAuraScript() const override
+ {
+ return new spell_throngus_impaling_slam_AuraScript();
+ }
+};
+
+void AddSC_boss_forgemaster_throngus()
+{
+ new boss_forgemaster_throngus();
+ new npc_throngus_cave_in();
+ new spell_throngus_mighty_stomp();
+ new spell_throngus_pick_weapon();
+ new spell_throngus_flame_arrow_barrage();
+ new spell_throngus_flaming_arrow();
+ new spell_throngus_personal_phalanx();
+ new spell_throngus_personal_phalanx_aoe();
+ new spell_throngus_fixate_effect();
+ new spell_throngus_burning_dual_blades();
+ new spell_throngus_disorienting_roar();
+ new spell_throngus_encumbered();
+ new spell_throngus_impaling_slam();
+}
diff --git a/src/server/scripts/EasternKingdoms/GrimBatol/grim_batol.h b/src/server/scripts/EasternKingdoms/GrimBatol/grim_batol.h
index f7d6bb86dce..5fe34ae7fd4 100644
--- a/src/server/scripts/EasternKingdoms/GrimBatol/grim_batol.h
+++ b/src/server/scripts/EasternKingdoms/GrimBatol/grim_batol.h
@@ -44,7 +44,11 @@ enum GBCreatureIds
NPC_BLITZ_STALKER = 40040,
NPC_GROUND_SIEGE_STALKER = 40030,
NPC_MALIGNANT_TROGG = 39984,
- NPC_TROGG_DWELLER = 45467
+ NPC_TROGG_DWELLER = 45467,
+
+ // Forgemaster Throngus Encounter
+ NPC_CAVE_IN_STALKER = 40228,
+ NPC_FIXATE_STALKER = 40255,
};
template
diff --git a/src/server/scripts/EasternKingdoms/GrimBatol/instance_grim_batol.cpp b/src/server/scripts/EasternKingdoms/GrimBatol/instance_grim_batol.cpp
index 767ee656ae2..08ee158b22b 100644
--- a/src/server/scripts/EasternKingdoms/GrimBatol/instance_grim_batol.cpp
+++ b/src/server/scripts/EasternKingdoms/GrimBatol/instance_grim_batol.cpp
@@ -53,6 +53,11 @@ class instance_grim_batol : public InstanceMapScript
if (Creature* umbriss = GetCreature(DATA_GENERAL_UMBRISS))
umbriss->AI()->JustSummoned(creature);
break;
+ case NPC_CAVE_IN_STALKER:
+ case NPC_FIXATE_STALKER:
+ if (Creature* throngus = GetCreature(DATA_FORGEMASTER_THRONGUS))
+ throngus->AI()->JustSummoned(creature);
+ break;
default:
break;
}
diff --git a/src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp b/src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp
index 809d8550cf1..e2620ab23b4 100644
--- a/src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp
+++ b/src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp
@@ -75,6 +75,7 @@ void AddSC_gnomeregan(); //Gnomeregan
void AddSC_instance_gnomeregan();
void AddSC_instance_grim_batol(); //Grim Batol
void AddSC_boss_general_umbriss();
+void AddSC_boss_forgemaster_throngus();
void AddSC_boss_attumen(); //Karazhan
void AddSC_boss_curator();
void AddSC_boss_maiden_of_virtue();
@@ -274,6 +275,7 @@ void AddEasternKingdomsScripts()
AddSC_instance_gnomeregan();
AddSC_instance_grim_batol(); //Grim Batol
AddSC_boss_general_umbriss();
+ AddSC_boss_forgemaster_throngus();
AddSC_boss_attumen(); //Karazhan
AddSC_boss_curator();
AddSC_boss_maiden_of_virtue();