Scripts/Aberrus: Implement Kazzara introduction (#29155)

Co-authored-by: ModoX <moardox@gmail.com>
This commit is contained in:
Aqua Deus
2023-07-24 17:35:59 +02:00
committed by GitHub
parent 3cfc27f5ca
commit ed871f1eab
7 changed files with 1014 additions and 0 deletions

View File

@@ -0,0 +1,218 @@
/*
* 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 "Conversation.h"
#include "InstanceScript.h"
#include "MotionMaster.h"
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "Unit.h"
#include "aberrus_the_shadowed_crucible.h"
enum AberrusEvents
{
EVENT_SABELLIAN_MOVE = 1,
EVENT_SABELLIAN_MOVE_HOME_POS,
EVENT_KAZZARA_INTRO,
EVENT_KAZZARA_INTRO_DONE
};
enum AberrusPaths
{
PATH_SARKARETH = (202416 * 10) << 3,
PATH_WINGLORD_DEZRAN = (202610 * 10) << 3,
PATH_ZSKARN = (202637 * 10) << 3
};
enum AberrusSpells
{
SPELL_ABERRUS_ENTRANCE_RP_CONVERSATION_1 = 400785, // Sabellian and Wrathion
SPELL_ABERRUS_ENTRANCE_RP_CONVERSATION_2 = 403340, // Sabellian and Sarkareth
};
enum AberrusMisc
{
// Sabellian intro
CONVO_ACTOR_IDX_SABELLIAN = 0,
CONVO_SABELLIAN_INTRO_LINE_01 = 56690,
CONVO_SABELLIAN_INTRO_LINE_02 = 56692,
// Kazzara intro
CONVO_ACTOR_IDX_WINGLORD_DEZRAN = 0,
CONVO_ACTOR_IDX_ZSKARN = 1,
CONVO_ACTOR_IDX_SARKARETH = 2,
CONVO_SARKARETH_LAST_LINE = 57821
};
Position const SabellianIntroConvoMovePosition = { 2250.6372f, 2482.3003f, 711.9592f };
// Id 26 - Areatrigger
struct at_aberrus_sabellian_conversation_intro : AreaTriggerAI
{
at_aberrus_sabellian_conversation_intro(AreaTrigger* areatrigger) : AreaTriggerAI(areatrigger) { }
void OnUnitEnter(Unit* unit) override
{
Player* player = unit->ToPlayer();
if (!player)
return;
Creature* sabellian = unit->FindNearestCreature(NPC_SABELLIAN_AT_ABERRUS_ENTRANCE, 50.0f);
if (!sabellian)
return;
sabellian->CastSpell(nullptr, SPELL_ABERRUS_ENTRANCE_RP_CONVERSATION_1);
at->Remove();
}
};
// Id 27 - Areatrigger
struct at_aberrus_sarkareth_conversation_intro : AreaTriggerAI
{
at_aberrus_sarkareth_conversation_intro(AreaTrigger* areatrigger) : AreaTriggerAI(areatrigger) { }
void OnUnitEnter(Unit* unit) override
{
Player* player = unit->ToPlayer();
if (!player)
return;
Creature* sabellian = unit->FindNearestCreature(NPC_SABELLIAN_AT_ABERRUS_ENTRANCE, 50.0f);
if (!sabellian)
return;
sabellian->CastSpell(nullptr, SPELL_ABERRUS_ENTRANCE_RP_CONVERSATION_2);
at->Remove();
}
};
// 20800 - Conversation
class conversation_aberrus_sabellian_intro : public ConversationScript
{
public:
conversation_aberrus_sabellian_intro() : ConversationScript("conversation_aberrus_sabellian_intro") { }
void OnConversationStart(Conversation* conversation) override
{
if (Milliseconds const* sabellianMoveStartTime = conversation->GetLineStartTime(DEFAULT_LOCALE, CONVO_SABELLIAN_INTRO_LINE_01))
_events.ScheduleEvent(EVENT_SABELLIAN_MOVE, *sabellianMoveStartTime);
if (Milliseconds const* sabellianHomeMoveStartTime = conversation->GetLineStartTime(DEFAULT_LOCALE, CONVO_SABELLIAN_INTRO_LINE_02))
_events.ScheduleEvent(EVENT_SABELLIAN_MOVE_HOME_POS, *sabellianHomeMoveStartTime + Seconds(2));
}
void OnConversationUpdate(Conversation* conversation, uint32 diff) override
{
_events.Update(diff);
switch (_events.ExecuteEvent())
{
case EVENT_SABELLIAN_MOVE:
{
Creature* sabellian = conversation->GetActorCreature(CONVO_ACTOR_IDX_SABELLIAN);
if (!sabellian)
break;
sabellian->SetWalk(true);
sabellian->GetMotionMaster()->MovePoint(0, SabellianIntroConvoMovePosition);
break;
}
case EVENT_SABELLIAN_MOVE_HOME_POS:
{
Creature* sabellian = conversation->GetActorCreature(CONVO_ACTOR_IDX_SABELLIAN);
if (!sabellian)
break;
sabellian->SetWalk(true);
sabellian->GetMotionMaster()->MovePoint(0, sabellian->ToCreature()->GetHomePosition(), false, sabellian->ToCreature()->GetHomePosition().GetOrientation());
break;
}
default:
break;
}
}
private:
EventMap _events;
};
// 20985 - Conversation
class conversation_aberrus_kazzara_intro : public ConversationScript
{
public:
conversation_aberrus_kazzara_intro() : ConversationScript("conversation_aberrus_kazzara_intro") { }
void OnConversationStart(Conversation* conversation) override
{
_events.ScheduleEvent(EVENT_KAZZARA_INTRO, conversation->GetLineEndTime(DEFAULT_LOCALE, CONVO_SARKARETH_LAST_LINE));
}
void OnConversationUpdate(Conversation* conversation, uint32 diff) override
{
_events.Update(diff);
switch (_events.ExecuteEvent())
{
case EVENT_KAZZARA_INTRO:
{
Creature* winglordDezran = conversation->GetActorCreature(CONVO_ACTOR_IDX_WINGLORD_DEZRAN);
Creature* zskarn = conversation->GetActorCreature(CONVO_ACTOR_IDX_ZSKARN);
Creature* sarkareth = conversation->GetActorCreature(CONVO_ACTOR_IDX_SARKARETH);
if (!winglordDezran || !zskarn || !sarkareth)
return;
sarkareth->GetMotionMaster()->MovePath(PATH_SARKARETH, false);
sarkareth->DespawnOrUnsummon(45s);
winglordDezran->GetMotionMaster()->MovePath(PATH_WINGLORD_DEZRAN, false);
winglordDezran->DespawnOrUnsummon(45s);
zskarn->GetMotionMaster()->MovePath(PATH_ZSKARN, false);
zskarn->DespawnOrUnsummon(45s, Seconds::max()); // override respawn time to prevent instant respawn due to CREATURE_FLAG_EXTRA_DUNGEON_BOSS
if (InstanceScript* instance = conversation->GetInstanceScript())
{
instance->SetData(DATA_KAZZARA_INTRO_DONE, 1);
if (Creature* kazzara = instance->GetCreature(DATA_KAZZARA_THE_HELLFORGED))
kazzara->AI()->DoAction(ACTION_START_KAZZARA_INTRO);
}
break;
}
default:
break;
}
}
private:
EventMap _events;
};
void AddSC_aberrus_the_shadowed_crucible()
{
RegisterAreaTriggerAI(at_aberrus_sabellian_conversation_intro);
RegisterAreaTriggerAI(at_aberrus_sarkareth_conversation_intro);
new conversation_aberrus_sabellian_intro();
new conversation_aberrus_kazzara_intro();
}

View File

@@ -0,0 +1,92 @@
/*
* 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_ABERRUS_THE_SHADOWED_CRUCIBLE_H_
#define DEF_ABERRUS_THE_SHADOWED_CRUCIBLE_H_
#include "CreatureAIImpl.h"
#define ATSCScriptName "instance_aberrus_the_shadowed_crucible"
#define DataHeader "Aberrus"
uint32 const EncounterCount = 9;
enum AberrusDataTypes
{
// Encounters
DATA_KAZZARA_THE_HELLFORGED = 0,
DATA_THE_AMALGAMATION_CHAMBER = 1,
DATA_THE_FORGOTTEN_EXPERIMENTS = 2,
DATA_ASSAULT_OF_THE_ZAQALI = 3,
DATA_RASHOK_THE_ELDER = 4,
DATA_ZSKARN_THE_VIGILANT_STEWARD = 5,
DATA_MAGMORAX = 6,
DATA_ECHO_OF_NELTHARION = 7,
DATA_SCALECOMMANDER_SARKARETH = 8,
// Additional Data
DATA_KAZZARA_GATE,
// Misc
DATA_KAZZARA_INTRO_DONE
};
enum AberrusCreatureIds
{
// Bosses
BOSS_KAZZARA_THE_HELLFORGED = 201261,
BOSS_ETERNAL_BLAZE = 201773,
BOSS_ESSENCE_OF_SHADOW = 201774,
BOSS_SHADOWFLAME_AMALGAMATION = 201934,
BOSS_NELDRIS = 200912,
BOSS_THADRION = 200913,
BOSS_RIONTHUS = 200918,
BOSS_WARLORD_KAGNI = 199659,
BOSS_RASHOK_THE_ELDER = 201320,
BOSS_ZSKARN_THE_VIGILANT_STEWARD = 202637,
BOSS_MAGMORAX = 201579,
BOSS_ECHO_OF_NELTHARION = 204223,
BOSS_SCALECOMMANDER_SARKARETH = 205319,
// Misc
NPC_SABELLIAN_AT_ABERRUS_ENTRANCE = 201575
};
enum AberrusGameObjectIds
{
GO_KAZZARA_DOOR = 398742,
GO_KAZZARA_GATE = 397996,
GO_INVISIBLE_DOOR = 398588
};
enum AberrusSharedActions
{
ACTION_START_KAZZARA_INTRO = 0,
};
template <class AI, class T>
inline AI* GetAberrusTheShadowedCrucibleAI(T* obj)
{
return GetInstanceAI<AI>(obj, ATSCScriptName);
}
#define RegisterAberrusTheShadowedCrucibleCreatureAI(ai_name) RegisterCreatureAIWithFactory(ai_name, GetAberrusTheShadowedCrucibleAI)
#endif

View File

@@ -0,0 +1,102 @@
/*
* 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 "CellImpl.h"
#include "GameObject.h"
#include "GridNotifiersImpl.h"
#include "InstanceScript.h"
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "aberrus_the_shadowed_crucible.h"
enum KazzaraSpells
{
// Sundered NPCs
SPELL_FEAR = 220540,
// Kazzara
SPELL_DREAD_LANDING = 411872,
SPELL_KAZZARA_INTRO = 410541
};
// 201261 - Kazzara the Hellforged
struct boss_kazzara_the_hellforged : public BossAI
{
boss_kazzara_the_hellforged(Creature* creature) : BossAI(creature, DATA_KAZZARA_THE_HELLFORGED) { }
void JustAppeared() override
{
if (!instance->GetData(DATA_KAZZARA_INTRO_DONE))
{
me->SetUninteractible(true);
me->SetImmuneToAll(true);
me->SetVisible(false);
}
}
void DoAction(int32 actionId) override
{
switch (actionId)
{
case ACTION_START_KAZZARA_INTRO:
{
if (GameObject* gate = instance->GetGameObject(DATA_KAZZARA_GATE))
{
gate->SetFlag(GO_FLAG_IN_USE);
gate->SetGoState(GO_STATE_READY);
}
me->SetVisible(true);
DoCast(SPELL_DREAD_LANDING);
DoCast(SPELL_KAZZARA_INTRO);
scheduler.Schedule(1s + 500ms, [this](TaskContext /*context*/)
{
std::vector<Creature*> sunderedMobs;
GetCreatureListWithOptionsInGrid(sunderedMobs, me, 50.0f, FindCreatureOptions().SetStringId("sundered_mob"));
for (Creature* sunderedMob : sunderedMobs)
{
if (!sunderedMob->IsAlive() || sunderedMob->IsInCombat())
continue;
sunderedMob->CastSpell(nullptr, SPELL_FEAR, false);
}
});
scheduler.Schedule(12s, [this](TaskContext /*context*/)
{
me->SetUninteractible(false);
me->SetImmuneToAll(false);
});
break;
}
default:
break;
}
}
void UpdateAI(uint32 diff) override
{
scheduler.Update(diff);
}
};
void AddSC_boss_kazzara_the_hellforged()
{
RegisterAberrusTheShadowedCrucibleCreatureAI(boss_kazzara_the_hellforged);
}

View File

@@ -0,0 +1,151 @@
/*
* 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 "InstanceScript.h"
#include "ScriptMgr.h"
#include "Unit.h"
#include "aberrus_the_shadowed_crucible.h"
ObjectData const creatureData[] =
{
{ BOSS_KAZZARA_THE_HELLFORGED, DATA_KAZZARA_THE_HELLFORGED },
{ BOSS_SHADOWFLAME_AMALGAMATION, DATA_THE_AMALGAMATION_CHAMBER },
{ BOSS_RIONTHUS, DATA_THE_FORGOTTEN_EXPERIMENTS },
{ BOSS_WARLORD_KAGNI, DATA_ASSAULT_OF_THE_ZAQALI },
{ BOSS_RASHOK_THE_ELDER, DATA_RASHOK_THE_ELDER },
{ BOSS_ZSKARN_THE_VIGILANT_STEWARD, DATA_ZSKARN_THE_VIGILANT_STEWARD },
{ BOSS_MAGMORAX, DATA_MAGMORAX },
{ BOSS_ECHO_OF_NELTHARION, DATA_ECHO_OF_NELTHARION },
{ BOSS_SCALECOMMANDER_SARKARETH, DATA_SCALECOMMANDER_SARKARETH },
{ 0, 0 } // END
};
DoorData const doorData[] =
{
{ GO_KAZZARA_DOOR, DATA_KAZZARA_THE_HELLFORGED, DOOR_TYPE_ROOM },
{ 0, 0, DOOR_TYPE_ROOM } // END
};
ObjectData const objectData[] =
{
{ GO_KAZZARA_GATE, DATA_KAZZARA_GATE },
{ 0, 0 } // END
};
DungeonEncounterData const encounters[] =
{
{ DATA_KAZZARA_THE_HELLFORGED, {{ 2688 }} },
{ DATA_THE_AMALGAMATION_CHAMBER, {{ 2687 }} },
{ DATA_THE_FORGOTTEN_EXPERIMENTS, {{ 2693 }} },
{ DATA_ASSAULT_OF_THE_ZAQALI, {{ 2682 }} },
{ DATA_RASHOK_THE_ELDER, {{ 2680 }} },
{ DATA_ZSKARN_THE_VIGILANT_STEWARD, {{ 2689 }} },
{ DATA_MAGMORAX, {{ 2683 }} },
{ DATA_ECHO_OF_NELTHARION, {{ 2684 }} },
{ DATA_SCALECOMMANDER_SARKARETH, {{ 2685 }} }
};
enum AberrusInstanceCreatureIds
{
NPC_SCALECOMMANDER_SARKARETH_AT_KAZZARA = 202416
};
enum AberrusInstanceSpells
{
SPELL_ABERRUS_ENTRANCE_RP_CONVERSATION_3 = 403409 // Winglord Dezran, Sarkareth and Zskarn (Kazzara Summon)
};
class instance_aberrus_the_shadowed_crucible : public InstanceMapScript
{
public:
instance_aberrus_the_shadowed_crucible() : InstanceMapScript(ATSCScriptName, 2569) { }
struct instance_aberrus_the_shadowed_crucible_InstanceMapScript: public InstanceScript
{
instance_aberrus_the_shadowed_crucible_InstanceMapScript(InstanceMap* map) : InstanceScript(map)
{
SetHeaders(DataHeader);
SetBossNumber(EncounterCount);
LoadObjectData(creatureData, objectData);
LoadDoorData(doorData);
LoadDungeonEncounterData(encounters);
_kazzaraIntroDone = false;
_deadSunderedMobs = 0;
}
uint32 GetData(uint32 dataId) const override
{
switch (dataId)
{
case DATA_KAZZARA_INTRO_DONE:
return _kazzaraIntroDone ? 1 : 0;
default:
break;
}
return 0;
}
void SetData(uint32 dataId, uint32 /*value*/) override
{
switch (dataId)
{
case DATA_KAZZARA_INTRO_DONE:
_kazzaraIntroDone = true; // no need to pass value, it will never reset to false
break;
default:
break;
}
}
void OnUnitDeath(Unit* unit) override
{
Creature* creature = unit->ToCreature();
if (!creature)
return;
if (creature->HasStringId("sundered_mob"))
{
if (_deadSunderedMobs >= 6)
return;
_deadSunderedMobs++;
if (_deadSunderedMobs >= 6)
{
Creature* sarkareth = creature->FindNearestCreature(NPC_SCALECOMMANDER_SARKARETH_AT_KAZZARA, 300.0f);
if (!sarkareth)
return;
sarkareth->CastSpell(nullptr, SPELL_ABERRUS_ENTRANCE_RP_CONVERSATION_3);
}
}
}
private:
uint8 _deadSunderedMobs;
bool _kazzaraIntroDone;
};
InstanceScript* GetInstanceScript(InstanceMap* map) const override
{
return new instance_aberrus_the_shadowed_crucible_InstanceMapScript(map);
}
};
void AddSC_instance_aberrus_the_shadowed_crucible()
{
new instance_aberrus_the_shadowed_crucible();
}

View File

@@ -26,6 +26,11 @@ void AddSC_ruby_life_pools();
void AddSC_instance_azure_vault();
void AddSC_boss_leymor();
// Aberrus the Shadowed Crucible
void AddSC_instance_aberrus_the_shadowed_crucible();
void AddSC_aberrus_the_shadowed_crucible();
void AddSC_boss_kazzara_the_hellforged();
// The name of this function should match:
// void Add${NameOfDirectory}Scripts()
void AddDragonIslesScripts()
@@ -39,4 +44,9 @@ void AddDragonIslesScripts()
// Azure Vault
AddSC_instance_azure_vault();
AddSC_boss_leymor();
// Aberrus the Shadowed Crucible
AddSC_instance_aberrus_the_shadowed_crucible();
AddSC_aberrus_the_shadowed_crucible();
AddSC_boss_kazzara_the_hellforged();
}