mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-19 00:48:56 +01:00
Scripts/DarkmaulCitadel: Implement Tunk encounter (#31195)
This commit is contained in:
23
sql/updates/world/master/2025_09_20_02_world.sql
Normal file
23
sql/updates/world/master/2025_09_20_02_world.sql
Normal file
@@ -0,0 +1,23 @@
|
||||
DELETE FROM `instance_template` WHERE `map`=2236;
|
||||
INSERT INTO `instance_template` (`map`, `parent`, `script`) VALUES
|
||||
(2236, 0, 'instance_darkmaul_citadel');
|
||||
|
||||
DELETE FROM `areatrigger_template` WHERE (`Id`=22171 AND `IsCustom`=0);
|
||||
INSERT INTO `areatrigger_template` (`Id`, `IsCustom`, `Flags`, `VerifiedBuild`) VALUES
|
||||
(22171, 0, 0, 49570);
|
||||
|
||||
DELETE FROM `areatrigger_create_properties` WHERE (`Id`=18034 AND `IsCustom`=0);
|
||||
INSERT INTO `areatrigger_create_properties` (`Id`, `IsCustom`, `AreaTriggerId`, `IsAreatriggerCustom`, `Flags`, `MoveCurveId`, `ScaleCurveId`, `MorphCurveId`, `FacingCurveId`, `AnimId`, `AnimKitId`, `DecalPropertiesId`, `SpellForVisuals`, `TimeToTargetScale`, `Speed`, `SpeedIsTime`, `Shape`, `ShapeData0`, `ShapeData1`, `ShapeData2`, `ShapeData3`, `ShapeData4`, `ShapeData5`, `ShapeData6`, `ShapeData7`, `ScriptName`, `VerifiedBuild`) VALUES
|
||||
(18034, 0, 22171, 0, 0, 0, 0, 13613, 0, -1, 0, 0, NULL, 6000, 6, 1, 4, 3, 3, 6, 6, 0.300000011920928955, 0.300000011920928955, 0, 0, 'at_tunk_seismic_slam', 49570); -- Spell: 308455 (Seismic Slam)
|
||||
|
||||
UPDATE `creature_template` SET `ScriptName`='boss_tunk' WHERE `entry`=157300;
|
||||
|
||||
DELETE FROM `spell_script_names` WHERE `ScriptName` IN('spell_tunk_seismic_slam_selector', 'spell_tunk_interrupting_shout');
|
||||
INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES
|
||||
(308454, 'spell_tunk_seismic_slam_selector'),
|
||||
(321240, 'spell_tunk_interrupting_shout');
|
||||
|
||||
DELETE FROM `creature_text` WHERE `CreatureID`=157300;
|
||||
INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES
|
||||
(157300, 0, 0, '|TINTERFACE\\ICONS\\Ability_Earthen_Pillar.blp:20|t Avoid Tunk\'s |cFFFF0404|Hspell:308463|h[Seismic Slam]|h|r by moving to the left or right!', 42, 0, 100, 0, 0, 0, 0, 0, 'Tunk to Player'), -- Missing BroadcastTextId
|
||||
(157300, 1, 0, '|TINTERFACE\\ICONS\\WARRIOR_DISRUPTINGSHOUT.BLP:20|t Some spells can interrupt your casting. Stop casting to avoid being interrupted by |cFFFF0404|Hspell:321240|h[Interrupting Shout]|h|r!', 42, 0, 100, 0, 0, 0, 0, 0, 'Tunk to Player'); -- Missing BroadcastTextId
|
||||
206
src/server/scripts/ExilesReach/DarkmaulCitadel/boss_tunk.cpp
Normal file
206
src/server/scripts/ExilesReach/DarkmaulCitadel/boss_tunk.cpp
Normal file
@@ -0,0 +1,206 @@
|
||||
/*
|
||||
* 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 "AreaTrigger.h"
|
||||
#include "AreaTriggerAI.h"
|
||||
#include "InstanceScript.h"
|
||||
#include "PathGenerator.h"
|
||||
#include "Player.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "SpellInfo.h"
|
||||
#include "SpellMgr.h"
|
||||
#include "SpellScript.h"
|
||||
#include "darkmaul_citadel.h"
|
||||
|
||||
enum TunkSpells
|
||||
{
|
||||
SPELL_INTERRUPTING_SHOUT = 321240,
|
||||
SPELL_SEISMIC_SLAM_SELECTOR = 308454,
|
||||
SPELL_SEISMIC_SLAM_AT = 308455,
|
||||
SPELL_SEISMIC_SLAM_DAMAGE = 308463
|
||||
};
|
||||
|
||||
enum TunkEvents
|
||||
{
|
||||
EVENT_INTERRUPTING_SHOUT = 1,
|
||||
EVENT_SEISMIC_SLAM
|
||||
};
|
||||
|
||||
enum TunkTexts
|
||||
{
|
||||
SAY_WARNING_SEISMIC_SLAM = 0,
|
||||
SAY_WARNING_INTERRUPT = 1
|
||||
};
|
||||
|
||||
// 157300 - Tunk
|
||||
struct boss_tunk : public BossAI
|
||||
{
|
||||
boss_tunk(Creature* creature) : BossAI(creature, DATA_TUNK) { }
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
|
||||
_JustDied();
|
||||
}
|
||||
|
||||
void EnterEvadeMode(EvadeReason /*why*/) override
|
||||
{
|
||||
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
|
||||
_EnterEvadeMode();
|
||||
_DespawnAtEvade();
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* who) override
|
||||
{
|
||||
BossAI::JustEngagedWith(who);
|
||||
instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me, 1);
|
||||
|
||||
events.ScheduleEvent(EVENT_INTERRUPTING_SHOUT, 7s);
|
||||
events.ScheduleEvent(EVENT_SEISMIC_SLAM, 14s);
|
||||
}
|
||||
|
||||
void SpellHitTarget(WorldObject* target, SpellInfo const* spellInfo) override
|
||||
{
|
||||
if (!target->IsPlayer())
|
||||
return;
|
||||
|
||||
if (spellInfo->Id == SPELL_SEISMIC_SLAM_DAMAGE)
|
||||
Talk(SAY_WARNING_SEISMIC_SLAM, target);
|
||||
}
|
||||
|
||||
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_INTERRUPTING_SHOUT:
|
||||
{
|
||||
DoCastSelf(SPELL_INTERRUPTING_SHOUT);
|
||||
events.Repeat(20s);
|
||||
break;
|
||||
}
|
||||
case EVENT_SEISMIC_SLAM:
|
||||
{
|
||||
DoCast(SPELL_SEISMIC_SLAM_SELECTOR);
|
||||
events.Repeat(30s);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 308454 - Seismic Slam
|
||||
class spell_tunk_seismic_slam_selector : public SpellScript
|
||||
{
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo({ SPELL_SEISMIC_SLAM_AT });
|
||||
}
|
||||
|
||||
void HandleHitTarget(SpellEffIndex /*effIndex*/) const
|
||||
{
|
||||
GetCaster()->CastSpell(GetHitUnit()->GetPosition(), SPELL_SEISMIC_SLAM_AT, CastSpellExtraArgsInit{
|
||||
.TriggerFlags = TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR,
|
||||
.TriggeringSpell = GetSpell()
|
||||
});
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectHitTarget += SpellEffectFn(spell_tunk_seismic_slam_selector::HandleHitTarget, EFFECT_0, SPELL_EFFECT_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
// 308455 - Seismic Slam
|
||||
struct at_tunk_seismic_slam : AreaTriggerAI
|
||||
{
|
||||
using AreaTriggerAI::AreaTriggerAI;
|
||||
|
||||
void OnInitialize() override
|
||||
{
|
||||
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(at->GetSpellId(), DIFFICULTY_NONE);
|
||||
if (!spellInfo)
|
||||
return;
|
||||
|
||||
Unit* caster = at->GetCaster();
|
||||
if (!caster)
|
||||
return;
|
||||
|
||||
Position destPos = at->GetFirstCollisionPosition(spellInfo->GetMaxRange(false, caster), 0.0f);
|
||||
PathGenerator path(at);
|
||||
|
||||
path.CalculatePath(destPos.GetPositionX(), destPos.GetPositionY(), destPos.GetPositionZ(), false);
|
||||
|
||||
at->InitSplines(path.GetPath());
|
||||
}
|
||||
|
||||
void OnUnitEnter(Unit* unit) override
|
||||
{
|
||||
if (Unit* caster = at->GetCaster())
|
||||
if (caster->IsValidAttackTarget(unit))
|
||||
caster->CastSpell(unit, SPELL_SEISMIC_SLAM_DAMAGE, TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR);
|
||||
}
|
||||
};
|
||||
|
||||
// 321240 - Interrupting Shout
|
||||
class spell_tunk_interrupting_shout : public SpellScript
|
||||
{
|
||||
void HandleLaunchTarget(SpellEffIndex /*effIndex*/) const
|
||||
{
|
||||
Creature* caster = GetCaster()->ToCreature();
|
||||
if (!caster)
|
||||
return;
|
||||
|
||||
Player* hitPlayer = GetHitUnit()->ToPlayer();
|
||||
if (!hitPlayer)
|
||||
return;
|
||||
|
||||
if (hitPlayer->GetCurrentSpell(CurrentSpellTypes::CURRENT_GENERIC_SPELL) != nullptr)
|
||||
caster->AI()->Talk(SAY_WARNING_INTERRUPT, hitPlayer);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectLaunchTarget += SpellEffectFn(spell_tunk_interrupting_shout::HandleLaunchTarget, EFFECT_1, SPELL_EFFECT_INTERRUPT_CAST);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_tunk()
|
||||
{
|
||||
RegisterDarkmaulCitadelCreatureAI(boss_tunk);
|
||||
|
||||
RegisterSpellScript(spell_tunk_seismic_slam_selector);
|
||||
RegisterSpellScript(spell_tunk_interrupting_shout);
|
||||
|
||||
RegisterAreaTriggerAI(at_tunk_seismic_slam);
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* 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 DEF_DARKMAUL_CITADEL_H_
|
||||
#define DEF_DARKMAUL_CITADEL_H_
|
||||
|
||||
#include "CreatureAIImpl.h"
|
||||
|
||||
#define DCScriptName "instance_darkmaul_citadel"
|
||||
#define DataHeader "DarkmaulCitadel"
|
||||
|
||||
constexpr uint32 EncounterCount = 2;
|
||||
|
||||
enum DarkmaulCitadelDataTypes
|
||||
{
|
||||
// Encounters
|
||||
DATA_TUNK = 0,
|
||||
DATA_RAVNYR = 1,
|
||||
|
||||
DATA_GORGROTH
|
||||
};
|
||||
|
||||
enum DarkmaulCitadelCreatureIds
|
||||
{
|
||||
// Bosses
|
||||
BOSS_TUNK = 157300,
|
||||
BOSS_GORGROTH = 156814,
|
||||
BOSS_RAVNYR = 156501
|
||||
};
|
||||
|
||||
enum DarkmaulCitadelGameObjectIds
|
||||
{
|
||||
GO_SHADOWY_DOOR = 334578,
|
||||
GO_TEMP_DOOR = 334502
|
||||
};
|
||||
|
||||
template <class AI, class T>
|
||||
inline AI* GetDarkmaulCitadelAI(T* obj)
|
||||
{
|
||||
return GetInstanceAI<AI>(obj, DCScriptName);
|
||||
}
|
||||
|
||||
#define RegisterDarkmaulCitadelCreatureAI(ai_name) RegisterCreatureAIWithFactory(ai_name, GetDarkmaulCitadelAI)
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* 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 "Creature.h"
|
||||
#include "CreatureAI.h"
|
||||
#include "InstanceScript.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "darkmaul_citadel.h"
|
||||
|
||||
ObjectData const creatureData[] =
|
||||
{
|
||||
{ BOSS_TUNK, DATA_TUNK },
|
||||
{ BOSS_GORGROTH, DATA_GORGROTH },
|
||||
{ BOSS_RAVNYR, DATA_RAVNYR },
|
||||
{ 0, 0 } // END
|
||||
};
|
||||
|
||||
static DoorData const doorData[] =
|
||||
{
|
||||
{ GO_TEMP_DOOR, DATA_TUNK, EncounterDoorBehavior::OpenWhenDone },
|
||||
{ 0, 0, EncounterDoorBehavior::OpenWhenNotInProgress }
|
||||
};
|
||||
|
||||
DungeonEncounterData const encounters[] =
|
||||
{
|
||||
{ DATA_TUNK, {{ 2325 }} },
|
||||
{ DATA_RAVNYR, {{ 2326 }} }
|
||||
};
|
||||
|
||||
class instance_darkmaul_citadel : public InstanceMapScript
|
||||
{
|
||||
public:
|
||||
instance_darkmaul_citadel() : InstanceMapScript(DCScriptName, 2236) { }
|
||||
|
||||
struct instance_darkmaul_citadel_InstanceMapScript: public InstanceScript
|
||||
{
|
||||
instance_darkmaul_citadel_InstanceMapScript(InstanceMap* map) : InstanceScript(map)
|
||||
{
|
||||
SetHeaders(DataHeader);
|
||||
SetBossNumber(EncounterCount);
|
||||
LoadObjectData(creatureData, nullptr);
|
||||
LoadDoorData(doorData);
|
||||
LoadDungeonEncounterData(encounters);
|
||||
}
|
||||
};
|
||||
|
||||
InstanceScript* GetInstanceScript(InstanceMap* map) const override
|
||||
{
|
||||
return new instance_darkmaul_citadel_InstanceMapScript(map);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_instance_darkmaul_citadel()
|
||||
{
|
||||
new instance_darkmaul_citadel();
|
||||
}
|
||||
@@ -18,9 +18,17 @@
|
||||
// This is where scripts' loading functions should be declared:
|
||||
void AddSC_zone_exiles_reach();
|
||||
|
||||
// Darkmaul Citacel
|
||||
void AddSC_instance_darkmaul_citadel();
|
||||
void AddSC_boss_tunk();
|
||||
|
||||
// The name of this function should match:
|
||||
// void Add${NameOfDirectory}Scripts()
|
||||
void AddExilesReachScripts()
|
||||
{
|
||||
AddSC_zone_exiles_reach();
|
||||
|
||||
// Darkmaul Citacel
|
||||
AddSC_instance_darkmaul_citadel();
|
||||
AddSC_boss_tunk();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user