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();