Files
mod-individual-progression/src/vanillaScripts/instance_molten_core.cpp
2025-09-20 12:39:58 +02:00

522 lines
17 KiB
C++

/*
* This file is part of the AzerothCore 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 Affero General Public License as published by the
* Free Software Foundation; either version 3 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 Affero 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 "ScriptedCreature.h"
#include "GameObjectAI.h"
#include "TemporarySummon.h"
#include "Cell.h"
#include "CellImpl.h"
#include "GridNotifiers.h"
#include "GridNotifiersImpl.h"
#include "ObjectDefines.h"
#include "ObjectMgr.h"
#include "molten_core.h"
#include "ProgressionSystem.h"
MinionData const minionData[] =
{
{ NPC_FIRESWORN, DATA_GARR },
{ NPC_FLAMEWALKER, DATA_GEHENNAS },
{ NPC_FLAMEWALKER_PROTECTOR, DATA_LUCIFRON },
{ NPC_FLAMEWALKER_PRIEST, DATA_SULFURON },
{ NPC_FLAMEWALKER_HEALER, DATA_MAJORDOMO_EXECUTUS },
{ NPC_FLAMEWALKER_ELITE, DATA_MAJORDOMO_EXECUTUS },
{ 0, 0 } // END
};
struct MCBossObject
{
uint32 bossId;
uint32 runeId;
uint32 circleId;
};
constexpr uint8 MAX_MC_LINKED_BOSS_OBJ = 7;
MCBossObject const linkedBossObjData[MAX_MC_LINKED_BOSS_OBJ]=
{
{ DATA_MAGMADAR, GO_RUNE_KRESS, GO_CIRCLE_MAGMADAR },
{ DATA_GEHENNAS, GO_RUNE_MOHN, GO_CIRCLE_GEHENNAS },
{ DATA_GARR, GO_RUNE_BLAZ, GO_CIRCLE_GARR },
{ DATA_SHAZZRAH, GO_RUNE_MAZJ, GO_CIRCLE_SHAZZRAH },
{ DATA_GEDDON, GO_RUNE_ZETH, GO_CIRCLE_GEDDON },
{ DATA_GOLEMAGG, GO_RUNE_THERI, GO_CIRCLE_GOLEMAGG },
{ DATA_SULFURON, GO_RUNE_KORO, GO_CIRCLE_SULFURON },
};
constexpr uint8 SAY_SPAWN = 1;
class instance_molten_core_60_1_A : public InstanceMapScript
{
public:
instance_molten_core_60_1_A() : InstanceMapScript(MCScriptName, 409) {}
struct instance_molten_core_InstanceMapScript : public InstanceScript
{
instance_molten_core_InstanceMapScript(Map* map) : InstanceScript(map)
{
SetBossNumber(MAX_ENCOUNTER);
LoadMinionData(minionData);
}
void OnPlayerEnter(Player* /*player*/) override
{
if (CheckMajordomoExecutus())
{
SummonMajordomoExecutus();
}
}
void OnCreatureCreate(Creature* creature) override
{
switch (creature->GetEntry())
{
case NPC_GOLEMAGG_THE_INCINERATOR:
{
_golemaggGUID = creature->GetGUID();
break;
}
case NPC_CORE_RAGER:
{
_golemaggMinionsGUIDS.insert(creature->GetGUID());
break;
}
case NPC_MAJORDOMO_EXECUTUS:
{
_majordomoExecutusGUID = creature->GetGUID();
break;
}
case NPC_GARR:
{
_garrGUID = creature->GetGUID();
break;
}
case NPC_RAGNAROS:
{
_ragnarosGUID = creature->GetGUID();
break;
}
case NPC_FIRESWORN:
case NPC_FLAMEWALKER:
case NPC_FLAMEWALKER_PROTECTOR:
case NPC_FLAMEWALKER_PRIEST:
case NPC_FLAMEWALKER_HEALER:
case NPC_FLAMEWALKER_ELITE:
{
AddMinion(creature, true);
break;
}
}
}
void OnCreatureRemove(Creature* creature) override
{
switch (creature->GetEntry())
{
case NPC_FIRESWORN:
{
AddMinion(creature, false);
break;
}
case NPC_FLAMEWALKER:
case NPC_FLAMEWALKER_PROTECTOR:
case NPC_FLAMEWALKER_PRIEST:
case NPC_FLAMEWALKER_HEALER:
case NPC_FLAMEWALKER_ELITE:
{
AddMinion(creature, false);
break;
}
}
}
void OnGameObjectCreate(GameObject* go) override
{
switch (go->GetEntry())
{
case GO_CACHE_OF_THE_FIRELORD:
{
_cacheOfTheFirelordGUID = go->GetGUID();
break;
}
case GO_CIRCLE_GEDDON:
case GO_CIRCLE_GARR:
case GO_CIRCLE_GEHENNAS:
case GO_CIRCLE_GOLEMAGG:
case GO_CIRCLE_MAGMADAR:
case GO_CIRCLE_SHAZZRAH:
case GO_CIRCLE_SULFURON:
{
for (uint8 i = 0; i < MAX_MC_LINKED_BOSS_OBJ; ++i)
{
if (linkedBossObjData[i].circleId != go->GetEntry())
{
continue;
}
if (GetBossState(linkedBossObjData[i].bossId) == DONE)
{
go->DespawnOrUnsummon();
}
else
{
_circlesGUIDs[linkedBossObjData[i].bossId] = go->GetGUID();
}
}
break;
}
case GO_RUNE_KRESS:
case GO_RUNE_MOHN:
case GO_RUNE_BLAZ:
case GO_RUNE_MAZJ:
case GO_RUNE_ZETH:
case GO_RUNE_THERI:
case GO_RUNE_KORO:
{
for (uint8 i = 0; i < MAX_MC_LINKED_BOSS_OBJ; ++i)
{
if (linkedBossObjData[i].runeId != go->GetEntry())
{
continue;
}
if (GetBossState(linkedBossObjData[i].bossId) == DONE)
{
go->SetGoState(GO_STATE_ACTIVE);
_runeStatus[go->GetEntry()] = true;
}
else
{
_runesGUIDs[linkedBossObjData[i].bossId] = go->GetGUID();
_runeStatus[go->GetEntry()] = false;
}
}
break;
}
case GO_LAVA_STEAM:
{
_lavaSteamGUID = go->GetGUID();
break;
}
case GO_LAVA_SPLASH:
{
_lavaSplashGUID = go->GetGUID();
break;
}
case GO_LAVA_BURST:
{
if (Creature* ragnaros = instance->GetCreature(_ragnarosGUID))
{
ragnaros->AI()->SetGUID(go->GetGUID(), GO_LAVA_BURST);
}
break;
}
}
}
ObjectGuid GetGuidData(uint32 type) const override
{
switch (type)
{
case DATA_GOLEMAGG:
return _golemaggGUID;
case DATA_MAJORDOMO_EXECUTUS:
return _majordomoExecutusGUID;
case DATA_GARR:
return _garrGUID;
case DATA_LAVA_STEAM:
return _lavaSteamGUID;
case DATA_LAVA_SPLASH:
return _lavaSplashGUID;
case DATA_RAGNAROS:
return _ragnarosGUID;
}
return ObjectGuid::Empty;
}
bool SetBossState(uint32 bossId, EncounterState state) override
{
if (!InstanceScript::SetBossState(bossId, state))
{
return false;
}
if (bossId == DATA_MAJORDOMO_EXECUTUS && state == DONE)
{
DoRespawnGameObject(_cacheOfTheFirelordGUID, 7 * DAY);
}
else if (bossId == DATA_GOLEMAGG)
{
switch (state)
{
case NOT_STARTED:
case FAIL:
{
if (!_golemaggMinionsGUIDS.empty())
{
for (ObjectGuid const& minionGuid : _golemaggMinionsGUIDS)
{
Creature* minion = instance->GetCreature(minionGuid);
if (minion && minion->isDead())
{
minion->Respawn();
}
}
}
break;
}
case IN_PROGRESS:
{
if (!_golemaggMinionsGUIDS.empty())
{
for (ObjectGuid const& minionGuid : _golemaggMinionsGUIDS)
{
if (Creature* minion = instance->GetCreature(minionGuid))
{
minion->AI()->DoZoneInCombat(nullptr, 150.0f);
}
}
}
break;
}
case DONE:
{
if (!_golemaggMinionsGUIDS.empty())
{
for (ObjectGuid const& minionGuid : _golemaggMinionsGUIDS)
{
if (Creature* minion = instance->GetCreature(minionGuid))
{
minion->CastSpell(minion, SPELL_CORE_RAGER_QUIET_SUICIDE, true);
}
}
_golemaggMinionsGUIDS.clear();
}
break;
}
default:
break;
}
}
// Perform needed checks for Majordomu
if (bossId < DATA_MAJORDOMO_EXECUTUS && state == DONE)
{
if (GameObject* rune = instance->GetGameObject(_runesGUIDs[bossId]))
{
if (sConfigMgr->GetOption<int>("IndividualProgression.MoltenCore.ManualRuneHandling", 1) == 1)
{
rune->SetGoState(GO_STATE_ACTIVE);
rune->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
}
else
{
if (GameObject* circle = instance->GetGameObject(_circlesGUIDs[bossId]))
{
circle->DespawnOrUnsummon();
_circlesGUIDs[bossId].Clear();
}
rune->SetGoState(GO_STATE_ACTIVE);
if (CheckMajordomoExecutus())
{
SummonMajordomoExecutus();
}
}
_runesGUIDs[bossId].Clear();
}
}
return true;
}
void SetData(uint32 index, uint32 data) override
{
if (index == DATA_RUNE_STATUS)
{
_runeStatus[data] = true;
}
}
void DoAction(int32 action) override
{
if (action == ACTION_RESET_GOLEMAGG_ENCOUNTER)
{
if (Creature* golemagg = instance->GetCreature(_golemaggGUID))
{
golemagg->AI()->EnterEvadeMode();
}
if (!_golemaggMinionsGUIDS.empty())
{
for (ObjectGuid const& minionGuid : _golemaggMinionsGUIDS)
{
if (Creature* minion = instance->GetCreature(minionGuid))
{
minion->AI()->EnterEvadeMode();
}
}
}
}
else if (action == ACTION_CHECK_RUNES)
{
if (CheckMajordomoExecutus())
{
SummonMajordomoExecutus();
}
}
}
void SummonMajordomoExecutus()
{
if (instance->GetCreature(_majordomoExecutusGUID))
{
return;
}
if (GetBossState(DATA_MAJORDOMO_EXECUTUS) != DONE)
{
if (Creature* creature = instance->SummonCreature(NPC_MAJORDOMO_EXECUTUS, MajordomoSummonPos))
{
creature->AI()->Talk(SAY_SPAWN);
}
}
else
{
instance->SummonCreature(NPC_MAJORDOMO_EXECUTUS, MajordomoRagnaros);
}
}
bool CheckMajordomoExecutus() const
{
if (GetBossState(DATA_RAGNAROS) == DONE)
{
return false;
}
for (uint8 i = 0; i < DATA_MAJORDOMO_EXECUTUS; ++i)
{
if (i == DATA_LUCIFRON)
{
continue;
}
if (GetBossState(i) != DONE)
{
return false;
}
}
// Prevent spawning if Ragnaros is present
if (instance->GetCreature(_ragnarosGUID))
{
return false;
}
if (sConfigMgr->GetOption<int>("IndividualProgression.MoltenCore.ManualRuneHandling", 1) == 1)
{
return CheckFirelordRunes();
}
else
{
return true;
}
}
bool CheckFirelordRunes() const
{
for (auto const& status : _runeStatus)
{
if (!status.second)
{
return false;
}
}
return true;
}
private:
std::unordered_map<uint32 /*bossid*/, ObjectGuid /*circleGUID*/> _circlesGUIDs;
std::unordered_map<uint32/*bossid*/, ObjectGuid/*runeGUID*/> _runesGUIDs;
std::unordered_map<uint32 /*bossid*/, bool /*status*/> _runeStatus;
// Golemagg encounter related
ObjectGuid _golemaggGUID;
GuidSet _golemaggMinionsGUIDS;
// Ragnaros encounter related
ObjectGuid _ragnarosGUID;
ObjectGuid _lavaSteamGUID;
ObjectGuid _lavaSplashGUID;
ObjectGuid _majordomoExecutusGUID;
ObjectGuid _cacheOfTheFirelordGUID;
ObjectGuid _garrGUID;
ObjectGuid _magmadarGUID;
};
InstanceScript* GetInstanceScript(InstanceMap* map) const override
{
return new instance_molten_core_InstanceMapScript(map);
}
};
constexpr uint32 SPELL_AQUAL_QUINTESSENCE = 21358;
class go_firelord_rune : public GameObjectScript
{
public:
go_firelord_rune() : GameObjectScript("go_firelord_rune") { }
bool OnGossipHello(Player* player, GameObject* go) override
{
go->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
if (GameObject* circle = go->GetLinkedTrap())
{
circle->DespawnOrUnsummon();
}
if (InstanceScript* instance = go->GetInstanceScript())
{
instance->SetData(DATA_RUNE_STATUS, go->GetEntry());
instance->DoAction(ACTION_CHECK_RUNES);
}
if (uint32 cooldown = player->GetSpellCooldownDelay(SPELL_AQUAL_QUINTESSENCE))
{
int32 cooldownredux = sConfigMgr->GetOption<int>("IndividualProgression.MoltenCore.AqualEssenceCooldownReduction", 0);
player->ModifySpellCooldown(SPELL_AQUAL_QUINTESSENCE, -(cooldownredux * MINUTE * IN_MILLISECONDS));
}
return true;
}
};
void AddSC_instance_molten_core_60_1_A()
{
new instance_molten_core_60_1_A();
new go_firelord_rune();
}