diff options
author | Ovahlord <dreadkiller@gmx.de> | 2023-11-06 11:51:37 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-11-06 11:51:37 +0100 |
commit | 24dab9326df00f981ddb7f8d8077c079c2ac0c16 (patch) | |
tree | 143e769c715453e51bd5dbdbf332e46da84a96db | |
parent | 0e2f04172864e3cff2b5559ac89ded23ade5f92e (diff) |
Scripts/LCT: implement General Husam encounter (#29414)
5 files changed, 757 insertions, 0 deletions
diff --git a/sql/updates/world/master/2023_11_06_00_world.sql b/sql/updates/world/master/2023_11_06_00_world.sql new file mode 100644 index 00000000000..69ab13ce5d9 --- /dev/null +++ b/sql/updates/world/master/2023_11_06_00_world.sql @@ -0,0 +1,72 @@ +DELETE FROM `instance_template` WHERE `map`= 755; +INSERT INTO `instance_template` (`map`, `parent`, `script`) VALUES +(755, 1, 'instance_lost_city_of_the_tolvir'); + +-- General Husam +UPDATE `creature_template` SET `mechanic_immune_mask`= 667893759, `ScriptName`= 'boss_general_husam' WHERE `entry`= 44577; +-- Shockwave Stalker +UPDATE `creature_template` SET `faction`= 35, `unit_flags`= 33554432, `flags_extra`= 128, `speed_run`= 1.14286 WHERE `entry`= 44711; +-- Shockwave Visual +UPDATE `creature_template` SET `faction`= 14, `unit_flags`= 33554432, `flags_extra`= 128 WHERE `entry`= 44712; +-- Tol'Vir Land Mine +UPDATE `creature_template` SET `faction`= 14, `unit_flags`= 33554432, `flags_extra`= 0, `ScriptName`= 'npc_husam_tolvir_land_mine' WHERE `entry`= 44840; +-- Tol'Vir Land Mine Vehicle +UPDATE `creature_template` SET `faction`= 14, `unit_flags`= 33554432, `flags_extra`= 0, `VehicleId`= 1050, `ScriptName`= 'npc_husam_tolvir_land_mine' WHERE `entry`= 44798; +-- Tol'Vir Land Mine 2 +UPDATE `creature_template` SET `faction`= 14, `unit_flags`= 33554432, `flags_extra`= 0, `ScriptName`= 'npc_husam_tolvir_land_mine' WHERE `entry`= 44796; +-- Bad Intentions Target +UPDATE `creature_template` SET `flags_extra`= 128 WHERE `entry`= 44586; + +DELETE FROM `creature_template_movement` WHERE `CreatureId` IN (44711, 44712, 44840, 44798, 44796, 44586); +INSERT INTO `creature_template_movement` (`CreatureId`, `Ground`, `Swim`, `Flight`, `Rooted`) VALUES +(44711, 0, 0, 1, 0), +(44712, 0, 0, 1, 1), +(44840, 0, 0, 1, 1), +(44798, 0, 0, 1, 1), +(44796, 0, 0, 1, 0), +(44586, 0, 0, 1, 0); + +DELETE FROM `npc_spellclick_spells` WHERE `npc_entry`= 44798; +DELETE FROM `vehicle_template_accessory` WHERE `entry`= 44798; + +UPDATE `creature_template` SET `ScriptName`= 'npc_husam_bad_intentions_target', `AIName`='' WHERE `entry`= 44586; +UPDATE `creature_template` SET `ScriptName`= 'npc_husam_shockwave_visual', `AIName`='' WHERE `entry`= 44712; + +DELETE FROM `creature_text` WHERE `CreatureID`= 44577; +INSERT INTO `creature_text` (`CreatureID`, `groupid`, `id`, `text`, `type`, `language`, `probability`, `emote`, `duration`, `sound`, `BroadcastTextId`, `comment`) VALUES +(44577, 0, 0, 'Invaders, you shall go no further!', 14, 0, 100, 0, 0, 0, 49310, 'General Husam - Aggro'), +(44577, 1, 0, 'Insolent rat!', 14, 0, 100, 0, 0, 0, 49311, 'General Husam - Slay'), +(44577, 2, 0, 'Murkash!', 14, 0, 100, 0, 0, 0, 49313, 'General Husam - Shockwave'), +(44577, 3, 0, '|TInterface\\Icons\\spell_nature_earthquake.blp:20|t%s begins to cast |cFFFF0000|Hspell:83445|h[Shockwave]!|h|r', 41, 0, 100, 0, 0, 0, 44921, 'General Husam - Announce Shockwave'), +(44577, 4, 0, 'Tread Lightly.', 14, 0, 100, 0, 0, 0, 49314, 'General Husam - Detonate Mines'), +(44577, 5, 0, 'Siamat must not be freed! Turn back before it is too late!', 14, 0, 100, 0, 0, 0, 49312, 'General Husam - Death'); + +DELETE FROM `spell_script_names` WHERE `ScriptName` IN +('spell_husam_hammer_fist', +'spell_husam_shockwave_summon_search', +'spell_husam_shockwave', +'spell_husam_detonate_traps', +'spell_husam_bad_intentions', +'spell_husam_hurl', +'spell_husam_hurl_vehicle', +'spell_husam_land_mine_player_search_effect'); + +INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES +(83654, 'spell_husam_hammer_fist'), +(83466, 'spell_husam_shockwave_summon_search'), +(83445, 'spell_husam_shockwave'), +(91263, 'spell_husam_detonate_traps'), +(83113, 'spell_husam_bad_intentions'), +(83236, 'spell_husam_hurl'), +(83235, 'spell_husam_hurl_vehicle'), +(83112, 'spell_husam_land_mine_player_search_effect'); + +DELETE FROM `creature_template_addon` WHERE `entry` IN (44712, 44840, 44798, 44796); +INSERT INTO `creature_template_addon` (`entry`, `SheathState`, `Auras`) VALUES +(44712, 1, '83127'); + +DELETE FROM conditions WHERE `SourceTypeOrReferenceId`= 13 AND `SourceEntry` IN (83466, 83445, 91263); +INSERT INTO conditions (SourceTypeOrReferenceId, SourceGroup, SourceEntry, SourceId, ElseGroup, ConditionTypeOrReference, ConditionTarget, ConditionValue1, ConditionValue2, ConditionValue3, NegativeCondition, ErrorType, ScriptName, Comment) VALUES +(13, 0x1, 83466, 0, 0, 51, 0, 5, 44712, 0, 0, 0, '', 'Shockwave Summon Search - Target Shockwave Visual'), +(13, 0x1, 83445, 0, 0, 51, 0, 5, 44711, 0, 0, 0, '', 'Shockwave - Target Shockwave Stalker'), +(13, 0x1, 91263, 0, 0, 51, 0, 5, 44796, 0, 0, 0, '', 'Detonate Traps - Target Tolvir Land Mine'); diff --git a/src/server/scripts/Kalimdor/LostCityOfTheTolvir/boss_general_husam.cpp b/src/server/scripts/Kalimdor/LostCityOfTheTolvir/boss_general_husam.cpp new file mode 100644 index 00000000000..6da8fefc1a1 --- /dev/null +++ b/src/server/scripts/Kalimdor/LostCityOfTheTolvir/boss_general_husam.cpp @@ -0,0 +1,548 @@ +/* +* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information +* +* 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 <http://www.gnu.org/licenses/>. +*/ + +#include "ScriptMgr.h" +#include "Containers.h" +#include "InstanceScript.h" +#include "lost_city_of_the_tolvir.h" +#include "MoveSplineInit.h" +#include "MotionMaster.h" +#include "PassiveAI.h" +#include "ScriptedCreature.h" +#include "SpellInfo.h" +#include "SpellScript.h" +#include "TemporarySummon.h" +#include "Vehicle.h" + +enum Spells +{ + // General Husam + SPELL_HAMMER_FIST = 83654, + SPELL_SHOCKWAVE = 83445, + SPELL_SHOCKWAVE_VISUAL = 83130, + SPELL_SUMMON_SHOCKWAVE_TARGET_N = 83131, + SPELL_SUMMON_SHOCKWAVE_TARGET_S = 83132, + SPELL_SUMMON_SHOCKWAVE_TARGET_E = 83133, + SPELL_SUMMON_SHOCKWAVE_TARGET_W = 83134, + SPELL_MYSTIC_TRAP = 83644, + SPELL_THROW_LAND_MINES = 83122, + SPELL_DETONATE_TRAPS = 91263, + SPELL_BAD_INTENTIONS = 83113, + SPELL_HURL = 83236, + SPELL_THROW_VISUAL = 83371, + + // Shockwave Stalker + SPELL_SHOCKWAVE_SUMMON_EFFECT = 83128, + SPELL_SHOCKWAVE_VISUAL_PERIODIC_SUMMON_TRIGGER = 83129, + + // Shockwave Visual + SPELL_SHOCKWAVE_DAMAGE = 83454, + + // Tol'Vir Land Mine + SPELL_TOLVIR_LAND_MINE_VISUAL = 83110, + SPELL_LAND_MINE_PLAYER_SEARCH_TRIGGER = 83111, + SPELL_LAND_MINE_PLAYER_SEARCH_EFFECT = 83112, + SPELL_LAND_MINE_PERIODIC = 85523, + SPELL_MYSTIC_TRAP_DAMAGE = 83171, + + // Bad Intentions Target + SPELL_HARD_IMPACT = 83339, + SPELL_EJECT_ALL_PASSENGERS = 50630 +}; + +enum Events +{ + // General Husam + EVENT_HAMMER_FIST = 1, + EVENT_MYSTIC_TRAP, + EVENT_BAD_INTENTIONS, + EVENT_THROW_PLAYER, + EVENT_SHOCKWAVE, + EVENT_DETONATE_TRAPS, + + // Tol'Vir Land Mine + EVENT_READY_MINE, + EVENT_START_COUNTDOWN, + EVENT_CLEAR_AURAS +}; + +enum Actions +{ + // General Husam + ACTION_SAY_DETONATE_TRAPS = 0, + + // Tol'vir Land Mine + ACTION_INITIATE_COUNTDOWN = 0, + ACTION_DETONATE = 1 +}; + +enum Texts +{ + // General Husam + SAY_AGGRO = 0, + SAY_SLAY = 1, + SAY_SHOCKWAVE = 2, + SAY_ANNOUNCE_SHOCKWAVE = 3, + SAY_DETONATE_MINES = 4, + SAY_DEATH = 5 +}; + +enum Misc +{ + SEAT_PLAYER = 0 +}; + +struct boss_general_husam : public BossAI +{ + boss_general_husam(Creature* creature) : BossAI(creature, BOSS_GENERAL_HUSAM), _shockwaveStalkerCount(0) { } + + void JustEngagedWith(Unit* who) override + { + BossAI::JustEngagedWith(who); + instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me, 1); + Talk(SAY_AGGRO); + + events.ScheduleEvent(EVENT_HAMMER_FIST, 7s, 10s); + events.ScheduleEvent(EVENT_MYSTIC_TRAP, 7s, 10s); + events.ScheduleEvent(EVENT_BAD_INTENTIONS, 12s, 13s); + events.ScheduleEvent(EVENT_SHOCKWAVE, IsHeroic() ? 15s : 18s); + if (IsHeroic()) + events.ScheduleEvent(EVENT_DETONATE_TRAPS, 22s); + } + + void KilledUnit(Unit* victim) override + { + if (victim->IsPlayer()) + Talk(SAY_SLAY); + } + + void JustDied(Unit* /*killer*/) override + { + _JustDied(); + summons.DespawnAll(); + instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me); + Talk(SAY_DEATH); + } + + void EnterEvadeMode(EvadeReason /*why*/) override + { + _EnterEvadeMode(); + summons.DespawnAll(); + instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me); + _DespawnAtEvade(); + } + + void JustSummoned(Creature* summon) override + { + summons.Summon(summon); + + switch (summon->GetEntry()) + { + case NPC_SHOCKWAVE_STALKER: + { + ++_shockwaveStalkerCount; + float orientation = summon->GetAbsoluteAngle(me) + float(M_PI); + Position dest = summon->GetPosition(); + dest.m_positionX += std::cos(orientation) * 40.f; + dest.m_positionY += std::sin(orientation) * 40.f; + + std::function<void(Movement::MoveSplineInit&)> initializer = [dest](Movement::MoveSplineInit& init) + { + init.MoveTo(dest.GetPositionX(), dest.GetPositionY(), dest.GetPositionZ(), false); + init.SetVelocity(8.f); + }; + summon->GetMotionMaster()->LaunchMoveSpline(std::move(initializer)); + summon->CastSpell(nullptr, SPELL_SHOCKWAVE_VISUAL_PERIODIC_SUMMON_TRIGGER); + + if (_shockwaveStalkerCount == 4) + { + DoCastSelf(SPELL_SHOCKWAVE); + _shockwaveStalkerCount = 0; + } + break; + } + default: + break; + } + } + + void PassengerBoarded(Unit* /*passenger*/, int8 /*seatId*/, bool apply) override + { + if (apply) + events.ScheduleEvent(EVENT_THROW_PLAYER, 1s); + } + + void DoAction(int32 action) override + { + if (action == ACTION_SAY_DETONATE_TRAPS) + Talk(SAY_DETONATE_MINES); + } + + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_HAMMER_FIST: + DoCastSelf(SPELL_HAMMER_FIST); + events.Repeat(21s); + break; + case EVENT_MYSTIC_TRAP: + DoCastAOE(SPELL_MYSTIC_TRAP, CastSpellExtraArgs().AddSpellMod(SPELLVALUE_MAX_TARGETS, 3)); + events.Repeat(11s, 12s); + break; + case EVENT_BAD_INTENTIONS: + if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, NonTankTargetSelector(me))) + DoCast(target, SPELL_BAD_INTENTIONS); + break; + case EVENT_SHOCKWAVE: + Talk(SAY_ANNOUNCE_SHOCKWAVE); + Talk(SAY_SHOCKWAVE); + DoCastSelf(SPELL_SUMMON_SHOCKWAVE_TARGET_N); + DoCastSelf(SPELL_SUMMON_SHOCKWAVE_TARGET_S); + DoCastSelf(SPELL_SUMMON_SHOCKWAVE_TARGET_E); + DoCastSelf(SPELL_SUMMON_SHOCKWAVE_TARGET_W); + + events.RescheduleEvent(EVENT_MYSTIC_TRAP, 8s, 10s); + events.RescheduleEvent(EVENT_HAMMER_FIST, 10s, 12s); + events.RescheduleEvent(EVENT_BAD_INTENTIONS, 17s); + events.Repeat(39s); + break; + case EVENT_DETONATE_TRAPS: + DoCastSelf(SPELL_DETONATE_TRAPS); + events.DelayEvents(2s); + events.Repeat(32s); + break; + case EVENT_THROW_PLAYER: + DoCastSelf(SPELL_HURL); + DoCastSelf(SPELL_THROW_VISUAL); + me->SetReactState(REACT_AGGRESSIVE); + break; + default: + break; + } + } + DoMeleeAttackIfReady(); + } + +private: + uint8 _shockwaveStalkerCount; +}; + +struct npc_husam_tolvir_land_mine : public NullCreatureAI +{ + npc_husam_tolvir_land_mine(Creature* creature) : NullCreatureAI(creature), _instance(nullptr) { } + + void InitializeAI() override + { + _instance = me->GetInstanceScript(); + } + + void JustAppeared() override + { + if (!_instance) + return; + + switch (me->GetEntry()) + { + case NPC_TOLVIR_LAND_MINE_TARGET: + if (Creature* husam = _instance->GetCreature(BOSS_GENERAL_HUSAM)) + husam->CastSpell(me, SPELL_THROW_LAND_MINES); + me->DespawnOrUnsummon(6s); + break; + case NPC_TOLVIR_LAND_MINE_VEHICLE: + if (Creature* husam = _instance->GetCreature(BOSS_GENERAL_HUSAM)) + { + if (CreatureAI* ai = husam->AI()) + { + ai->JustSummoned(me); + if (Creature* landMine = DoSummon(NPC_TOLVIR_LAND_MINE_CASTER, me->GetPosition(), 0s, TEMPSUMMON_MANUAL_DESPAWN)) + ai->JustSummoned(landMine); + } + } + break; + case NPC_TOLVIR_LAND_MINE_CASTER: + if (me->IsSummon()) + if (Unit* summoner = me->ToTempSummon()->GetSummonerUnit()) + me->EnterVehicle(summoner); + _events.ScheduleEvent(EVENT_READY_MINE, 2s); + break; + default: + break; + } + } + + void PassengerBoarded(Unit* /*passenger*/, int8 /*seatId*/, bool apply) override + { + // If our casting land mine has despawned, we also despawn alongside it. + if (me->GetEntry() == NPC_TOLVIR_LAND_MINE_VEHICLE && !apply) + me->DespawnOrUnsummon(); + } + + void DoAction(int32 action) override + { + switch (action) + { + case ACTION_INITIATE_COUNTDOWN: + _events.RescheduleEvent(EVENT_START_COUNTDOWN, 1ms); + break; + case ACTION_DETONATE: + _events.Reset(); + DoCastSelf(SPELL_MYSTIC_TRAP_DAMAGE); + me->RemoveAurasDueToSpell(SPELL_LAND_MINE_PLAYER_SEARCH_TRIGGER); + me->RemoveAurasDueToSpell(SPELL_TOLVIR_LAND_MINE_VISUAL); + me->RemoveAurasDueToSpell(SPELL_LAND_MINE_PERIODIC); + me->DespawnOrUnsummon(6s); + break; + default: + break; + } + } + + void UpdateAI(uint32 diff) override + { + _events.Update(diff); + + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_READY_MINE: + DoCastSelf(SPELL_TOLVIR_LAND_MINE_VISUAL); + DoCastSelf(SPELL_LAND_MINE_PLAYER_SEARCH_TRIGGER); + _events.ScheduleEvent(EVENT_START_COUNTDOWN, 20s); + break; + case EVENT_START_COUNTDOWN: + DoCastSelf(SPELL_LAND_MINE_PERIODIC); + _events.ScheduleEvent(EVENT_CLEAR_AURAS, 5s); + break; + case EVENT_CLEAR_AURAS: + me->RemoveAurasDueToSpell(SPELL_TOLVIR_LAND_MINE_VISUAL); + me->RemoveAurasDueToSpell(SPELL_LAND_MINE_PLAYER_SEARCH_TRIGGER); + me->DespawnOrUnsummon(6s); + break; + default: + break; + } + } + } + +private: + EventMap _events; + InstanceScript* _instance; +}; + +struct npc_husam_bad_intentions_target : public NullCreatureAI +{ + npc_husam_bad_intentions_target(Creature* creature) : NullCreatureAI(creature) { } + + void PassengerBoarded(Unit* passenger, int8 /*seatId*/, bool apply) override + { + if (apply) + { + me->m_Events.AddEventAtOffset([&, passenger]() + { + if (passenger) + { + DoCast(passenger, SPELL_HARD_IMPACT); + DoCastSelf(SPELL_EJECT_ALL_PASSENGERS); + } + }, 400ms); + } + } +}; + +struct npc_husam_shockwave_visual : public NullCreatureAI +{ + npc_husam_shockwave_visual(Creature* creature) : NullCreatureAI(creature) { } + + void JustAppeared() override + { + me->m_Events.AddEventAtOffset([&]() { DoCastSelf(SPELL_SHOCKWAVE_DAMAGE); }, 4s + 600ms); + me->m_Events.AddEventAtOffset([&]() { me->RemoveAllAuras(); }, 7s); + me->DespawnOrUnsummon(12s); + } +}; + +class spell_husam_hammer_fist : public AuraScript +{ + bool Validate(SpellInfo const* spellInfo) override + { + return ValidateSpellEffect({ { spellInfo->Id, EFFECT_0 } }) && ValidateSpellInfo({ spellInfo->GetEffect(EFFECT_0).TriggerSpell }); + } + + void HandleTick(AuraEffect const* /*aurEff*/) + { + PreventDefaultAction(); + GetTarget()->CastSpell(GetCaster()->GetVictim(), GetSpellInfo()->GetEffect(EFFECT_0).TriggerSpell, true); + } + + void Register() override + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_husam_hammer_fist::HandleTick, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL); + } +}; + +class spell_husam_shockwave : public SpellScript +{ + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo({ SPELL_SHOCKWAVE_VISUAL }); + } + + void EffectScriptEffect(SpellEffIndex /*effIndex*/) + { + GetCaster()->CastSpell(GetHitUnit(), SPELL_SHOCKWAVE_VISUAL, true); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_husam_shockwave::EffectScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } +}; + +class spell_husam_shockwave_summon_search : public SpellScript +{ + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo({ SPELL_SHOCKWAVE_SUMMON_EFFECT }); + } + + void FilterTargets(std::list<WorldObject*>& targets) + { + if (targets.empty()) + GetCaster()->CastSpell(GetCaster(), SPELL_SHOCKWAVE_SUMMON_EFFECT, true); + } + + void Register() override + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_husam_shockwave_summon_search::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY); + } +}; + +class spell_husam_detonate_traps : public SpellScript +{ + void HandlePostCastText() + { + if (Creature* caster = GetCaster()->ToCreature()) + if (CreatureAI* ai = caster->AI()) + ai->DoAction(ACTION_SAY_DETONATE_TRAPS); + } + + void HandleScriptEffect(SpellEffIndex /*effIndex*/) + { + if (Creature* target = GetHitCreature()) + if (CreatureAI* ai = target->AI()) + ai->DoAction(ACTION_INITIATE_COUNTDOWN); + } + + void Register() override + { + AfterCast += SpellCastFn(spell_husam_detonate_traps::HandlePostCastText); + OnEffectHitTarget += SpellEffectFn(spell_husam_detonate_traps::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } +}; + +class spell_husam_bad_intentions : public SpellScript +{ + bool Validate(SpellInfo const* spellInfo) override + { + return ValidateSpellEffect({ { spellInfo->Id, EFFECT_0 } }) && ValidateSpellInfo({ static_cast<uint32>(spellInfo->GetEffect(EFFECT_0).BasePoints) }); + } + + void HandleScriptEffect(SpellEffIndex /*effIndex*/) + { + if (Unit* caster = GetCaster()) + { + Unit* target = GetHitUnit(); + target->CastStop(); + target->CastSpell(caster, GetSpellInfo()->GetEffect(EFFECT_1).BasePoints, true); + } + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_husam_bad_intentions::HandleScriptEffect, EFFECT_1, SPELL_EFFECT_SCRIPT_EFFECT); + } +}; + +class spell_husam_hurl : public SpellScript +{ + bool Validate(SpellInfo const* spellInfo) override + { + return ValidateSpellEffect({ { spellInfo->Id, EFFECT_0 } }) && ValidateSpellInfo({ static_cast<uint32>(spellInfo->GetEffect(EFFECT_0).BasePoints) }); + } + + void HandleScriptEffect(SpellEffIndex /*effIndex*/) + { + if (Vehicle* vehicle = GetCaster()->GetVehicleKit()) + { + if (Unit* passenger = vehicle->GetPassenger(SEAT_PLAYER)) + { + if (Creature* intentionsTarget = GetCaster()->FindNearestCreature(NPC_BAD_INTENTIONS_TARGET, 100.0f)) + passenger->CastSpell(intentionsTarget, static_cast<uint32>(GetSpellInfo()->GetEffect(EFFECT_0).BasePoints), true); + else + passenger->ExitVehicle(); // Safety case to avoid players getting stuck in Husam's hand + } + } + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_husam_hurl::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } +}; + +class spell_husam_land_mine_player_search_effect : public SpellScript +{ + void HandleDummyEffect(SpellEffIndex /*effIndex*/) + { + if (Unit* caster = GetCaster()) + if (Creature* creature = caster->ToCreature()) + if (creature->IsAIEnabled()) + creature->AI()->DoAction(ACTION_DETONATE); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_husam_land_mine_player_search_effect::HandleDummyEffect, EFFECT_0, SPELL_EFFECT_DUMMY); + } +}; + +void AddSC_boss_general_husam() +{ + RegisterLostCityOfTheTolvirAI(boss_general_husam); + RegisterLostCityOfTheTolvirAI(npc_husam_tolvir_land_mine); + RegisterLostCityOfTheTolvirAI(npc_husam_bad_intentions_target); + RegisterLostCityOfTheTolvirAI(npc_husam_shockwave_visual); + RegisterSpellScript(spell_husam_hammer_fist); + RegisterSpellScript(spell_husam_shockwave); + RegisterSpellScript(spell_husam_shockwave_summon_search); + RegisterSpellScript(spell_husam_detonate_traps); + RegisterSpellScript(spell_husam_bad_intentions); + RegisterSpellScript(spell_husam_hurl); + RegisterSpellScript(spell_husam_land_mine_player_search_effect); +} diff --git a/src/server/scripts/Kalimdor/LostCityOfTheTolvir/instance_lost_city_of_the_tolvir.cpp b/src/server/scripts/Kalimdor/LostCityOfTheTolvir/instance_lost_city_of_the_tolvir.cpp new file mode 100644 index 00000000000..7a01516ad20 --- /dev/null +++ b/src/server/scripts/Kalimdor/LostCityOfTheTolvir/instance_lost_city_of_the_tolvir.cpp @@ -0,0 +1,65 @@ +/* + * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information + * + * 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 <http://www.gnu.org/licenses/>. + */ + +#include "ScriptMgr.h" +#include "InstanceScript.h" +#include "lost_city_of_the_tolvir.h" + +static constexpr ObjectData const creatureData[] = +{ + { NPC_GENERAL_HUSAM, BOSS_GENERAL_HUSAM }, + { NPC_LOCKMAW, DATA_LOCKMAW }, + { NPC_AUGH, DATA_AUGH }, + { NPC_HIGH_PROPHET_BARIM, BOSS_HIGH_PROPHET_BARIM }, + { NPC_SIAMAT, BOSS_SIAMAT }, + { 0, 0 } // End +}; + +static constexpr DungeonEncounterData const encounters[] = +{ + { BOSS_GENERAL_HUSAM, {{ 1052 }} }, + { BOSS_LOCKMAW_AND_AUGH, {{ 1054 }} }, + { BOSS_HIGH_PROPHET_BARIM, {{ 1053 }} }, + { BOSS_SIAMAT, {{ 1055 }} } +}; + +class instance_lost_city_of_the_tolvir : public InstanceMapScript +{ +public: + instance_lost_city_of_the_tolvir() : InstanceMapScript(LCTScriptName, 755) { } + + struct instance_lost_city_of_the_tolvir_InstanceMapScript : public InstanceScript + { + instance_lost_city_of_the_tolvir_InstanceMapScript(InstanceMap* map) : InstanceScript(map) + { + SetHeaders(DataHeader); + SetBossNumber(EncounterCount); + LoadDungeonEncounterData(encounters); + LoadObjectData(creatureData, nullptr); + } + }; + + InstanceScript* GetInstanceScript(InstanceMap* map) const override + { + return new instance_lost_city_of_the_tolvir_InstanceMapScript(map); + } +}; + +void AddSC_instance_lost_city_of_the_tolvir() +{ + new instance_lost_city_of_the_tolvir(); +} diff --git a/src/server/scripts/Kalimdor/LostCityOfTheTolvir/lost_city_of_the_tolvir.h b/src/server/scripts/Kalimdor/LostCityOfTheTolvir/lost_city_of_the_tolvir.h new file mode 100644 index 00000000000..d397617ac29 --- /dev/null +++ b/src/server/scripts/Kalimdor/LostCityOfTheTolvir/lost_city_of_the_tolvir.h @@ -0,0 +1,66 @@ +/* + * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information + * + * 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 <http://www.gnu.org/licenses/>. + */ + +#ifndef LostCityOfTheTolvir_h__ +#define LostCityOfTheTolvir_h__ + +#include "CreatureAIImpl.h" + +#define DataHeader "LCT" +#define LCTScriptName "instance_lost_city_of_the_tolvir" + +static constexpr uint32 EncounterCount = 4; + +enum LCTData +{ + // Encounters + BOSS_GENERAL_HUSAM = 0, + BOSS_LOCKMAW_AND_AUGH = 1, + BOSS_HIGH_PROPHET_BARIM = 2, + BOSS_SIAMAT = 3, + + DATA_LOCKMAW, + DATA_AUGH +}; + +enum LCTCreatureIds +{ + // Bosses + NPC_GENERAL_HUSAM = 44577, + NPC_LOCKMAW = 43614, + NPC_AUGH = 49045, + NPC_HIGH_PROPHET_BARIM = 43612, + NPC_SIAMAT = 44819, + + // Encounter related creatures + /*General Husam*/ + NPC_BAD_INTENTIONS_TARGET = 44586, + NPC_SHOCKWAVE_STALKER = 44711, + NPC_TOLVIR_LAND_MINE_TARGET = 44840, + NPC_TOLVIR_LAND_MINE_VEHICLE = 44798, + NPC_TOLVIR_LAND_MINE_CASTER = 44796 +}; + +template <class AI, class T> +inline AI* GetLostCityOfTheTolvirAI(T* obj) +{ + return GetInstanceAI<AI>(obj, LCTScriptName); +} + +#define RegisterLostCityOfTheTolvirAI(ai_name) RegisterCreatureAIWithFactory(ai_name, GetLostCityOfTheTolvirAI) + +#endif // LostCityOfTheTolvir_h__ diff --git a/src/server/scripts/Kalimdor/kalimdor_script_loader.cpp b/src/server/scripts/Kalimdor/kalimdor_script_loader.cpp index 7f60f5e4fb0..eb5b043da2f 100644 --- a/src/server/scripts/Kalimdor/kalimdor_script_loader.cpp +++ b/src/server/scripts/Kalimdor/kalimdor_script_loader.cpp @@ -95,6 +95,9 @@ void AddSC_boss_twinemperors(); void AddSC_boss_ouro(); void AddSC_npc_anubisath_sentinel(); void AddSC_instance_temple_of_ahnqiraj(); +// The Lost City of the Tol'vir +void AddSC_boss_general_husam(); +void AddSC_instance_lost_city_of_the_tolvir(); // Wailing caverns void AddSC_wailing_caverns(); void AddSC_instance_wailing_caverns(); @@ -216,6 +219,9 @@ void AddKalimdorScripts() AddSC_boss_ouro(); AddSC_npc_anubisath_sentinel(); AddSC_instance_temple_of_ahnqiraj(); + // The Lost City of the Tol'vir + AddSC_boss_general_husam(); + AddSC_instance_lost_city_of_the_tolvir(); // Wailing caverns AddSC_wailing_caverns(); AddSC_instance_wailing_caverns(); |