Scripts/Diremaul - Dire Maul crystal and forcefield fix (#25332)

* Scripts/Diremaul
Diremaul Crystal and Forcefield fix

* Apply suggestions from code review

Apply suggestions

Co-authored-by: MaxtorCoder <warsongkiller.s8@gmail.com>

* Fix stuff

* _private member

* use std array instead of c-arrays and standartized guid container namings

* Process feedback

* finalize

* blubb

* small changes

* whoops

* Process feedback

* Missing include

* Process feedback

* Apply suggestions from code review

Co-authored-by: Giacomo Pozzoni <giacomopoz@gmail.com>

* remove unused field

Co-authored-by: MaxtorCoder <warsongkiller.s8@gmail.com>
Co-authored-by: Ovah <dreadkiller@gmx.de>
Co-authored-by: Giacomo Pozzoni <giacomopoz@gmail.com>
(cherry picked from commit 26002c530f)
This commit is contained in:
Jinnaix
2021-01-10 16:38:41 +01:00
committed by Shauren
parent 6b242eee13
commit 53eebf39f3
2 changed files with 272 additions and 2 deletions

View File

@@ -0,0 +1,60 @@
/*
* 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_DIREMAUL_H
#define DEF_DIREMAUL_H
#include "CreatureAIImpl.h"
#define DiremaulScriptName "instance_diremaul"
#define DataHeader "DM"
enum DMDataTypes
{
DATA_CRYSTAL_01 = 17,
DATA_CRYSTAL_02 = 18,
DATA_CRYSTAL_03 = 19,
DATA_CRYSTAL_04 = 20,
DATA_CRYSTAL_05 = 21,
DATA_FORCEFIELD = 22
};
enum DMCreatureIds
{
NPC_IMMOLTHAR = 11496,
NPC_TORTHELDRIN = 11486,
NPC_ARCANE_ABERRATION = 11480,
NPC_MANA_REMNANT = 11483
};
enum DMGameobjectIds
{
GO_FORCEFIELD = 179503,
GO_CRYSTAL_01 = 177259,
GO_CRYSTAL_02 = 177257,
GO_CRYSTAL_03 = 177258,
GO_CRYSTAL_04 = 179504,
GO_CRYSTAL_05 = 179505
};
template <class AI, class T>
inline AI* GetDiremaulAI(T* obj)
{
return GetInstanceAI<AI>(obj, DiremaulScriptName);
}
#endif

View File

@@ -22,8 +22,12 @@ Without it, the party doing random dungeon won't get satchel of spoils and
gets instead the deserter debuff.
*/
#include "ScriptMgr.h"
#include "GameObject.h"
#include "InstanceScript.h"
#include "Map.h"
#include "ScriptedCreature.h"
#include "ScriptMgr.h"
#include "diremaul.h"
// Bosses (East)
// 0 - Pusillin
@@ -39,6 +43,12 @@ gets instead the deserter debuff.
// 8 - Illyanna Ravenoak
// 9 - Immol'thar
// 10 - Prince Tortheldrin
// 17 - CRYSTAL_01
// 18 - CRYSTAL_02
// 19 - CRYSTAL_03
// 20 - CRYSTAL_04
// 21 - CRYSTAL_05
// 22 - FORCEFIELD
// North
// 11 - Guard Mol'dar
@@ -48,7 +58,15 @@ gets instead the deserter debuff.
// 15 - Captain Kromcrush
// 16 - King Gordok
uint8 const EncounterCount = 17;
uint8 const EncounterCount = 23;
uint32 const CrystalMobs[2] = { NPC_ARCANE_ABERRATION, NPC_MANA_REMNANT };
enum Events
{
EVENT_CRYSTAL_CREATURE_STORE = 1,
EVENT_CRYSTAL_CREATURE_CHECK = 2
};
class instance_dire_maul : public InstanceMapScript
{
@@ -59,8 +77,200 @@ public:
{
instance_dire_maul_InstanceMapScript(InstanceMap* map) : InstanceScript(map)
{
SetHeaders(DataHeader);
SetBossNumber(EncounterCount);
}
void OnCreatureCreate(Creature* creature) override
{
switch (creature->GetEntry())
{
case NPC_IMMOLTHAR:
_immoGUID = creature->GetGUID();
// we make Immolthar non attackable, otherwise players with pets can pull him out of the forcefield
// TODO: this change isnt correct but since of today (13.09.2020) mmaps dont support doors
if (GetBossState(DATA_FORCEFIELD) != DONE)
creature->AddUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
break;
default:
break;
}
}
void OnGameObjectCreate(GameObject* go) override
{
InstanceScript::OnGameObjectCreate(go);
switch (go->GetEntry())
{
case GO_CRYSTAL_01:
_crystalGUIDs[0] = go->GetGUID();
break;
case GO_CRYSTAL_02:
_crystalGUIDs[1] = go->GetGUID();
break;
case GO_CRYSTAL_03:
_crystalGUIDs[2] = go->GetGUID();
break;
case GO_CRYSTAL_04:
_crystalGUIDs[3] = go->GetGUID();
break;
case GO_CRYSTAL_05:
_crystalGUIDs[4] = go->GetGUID();
break;
case GO_FORCEFIELD:
_forcefieldGUID = go->GetGUID();
if (GetBossState(DATA_FORCEFIELD) != DONE)
_events.ScheduleEvent(EVENT_CRYSTAL_CREATURE_STORE, 1s);
break;
default:
break;
}
}
ObjectGuid GetGuidData(uint32 type) const override
{
switch (type)
{
case GO_CRYSTAL_01:
return _crystalGUIDs[0];
case GO_CRYSTAL_02:
return _crystalGUIDs[1];
case GO_CRYSTAL_03:
return _crystalGUIDs[2];
case GO_CRYSTAL_04:
return _crystalGUIDs[3];
case GO_CRYSTAL_05:
return _crystalGUIDs[4];
case GO_FORCEFIELD:
return _forcefieldGUID;
case NPC_IMMOLTHAR:
return _immoGUID;
default:
break;
}
return ObjectGuid::Empty;
}
void Update(uint32 diff) override
{
_events.Update(diff);
while (uint32 eventId = _events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_CRYSTAL_CREATURE_STORE:
CrystalCreatureStore();
_events.ScheduleEvent(EVENT_CRYSTAL_CREATURE_CHECK, 3s);
break;
case EVENT_CRYSTAL_CREATURE_CHECK:
CrystalCreatureCheck();
if ((GetBossState(DATA_FORCEFIELD) != DONE))
_events.ScheduleEvent(EVENT_CRYSTAL_CREATURE_CHECK, 1s);
break;
default:
break;
}
}
}
void CrystalCreatureStore()
{
for (uint8 i = 0; i < 5; ++i) // we store creatures in a list for all 5 crystals
{
uint8 creatureCount = 0;
if (GameObject* crystal = instance->GetGameObject(_crystalGUIDs[i]))
{
for (uint8 j = 0; j < 2; ++j) // once per creature type from CrystalMobs
{
std::list<Creature*> creatureList;
GetCreatureListWithEntryInGrid(creatureList, crystal, CrystalMobs[j], 30.0f);
for (std::list<Creature*>::iterator itr = creatureList.begin(); itr != creatureList.end(); ++itr)
{
_crystalCreatureGUIDs[i][creatureCount] = (*itr)->GetGUID();
++creatureCount;
}
}
}
}
}
void CrystalCreatureCheck()
{
for (uint8 i = 0; i < _crystalGUIDs.size(); ++i)
{
bool _mobAlive = false;
GameObject* go = instance->GetGameObject(_crystalGUIDs[i]);
if (!go)
continue;
if (go->GetGoState() == GO_STATE_READY)
{
for (uint8 j = 0; j < _crystalCreatureGUIDs[i].size(); ++j)
{
Creature* mob = instance->GetCreature(_crystalCreatureGUIDs[i][j]);
if (mob && mob->IsAlive())
{
_mobAlive = true;
break;
}
}
}
if (!_mobAlive && go->GetGoState() == GO_STATE_READY) // if all stored creatures are dead and go state is ready
{
HandleGameObject(ObjectGuid::Empty, false, go);
switch (go->GetEntry())
{
case GO_CRYSTAL_01:
SetBossState(DATA_CRYSTAL_01, DONE);
go->SetGoState(GO_STATE_ACTIVE);
break;
case GO_CRYSTAL_02:
SetBossState(DATA_CRYSTAL_02, DONE);
go->SetGoState(GO_STATE_ACTIVE);
break;
case GO_CRYSTAL_03:
SetBossState(DATA_CRYSTAL_03, DONE);
go->SetGoState(GO_STATE_ACTIVE);
break;
case GO_CRYSTAL_04:
SetBossState(DATA_CRYSTAL_04, DONE);
go->SetGoState(GO_STATE_ACTIVE);
break;
case GO_CRYSTAL_05:
SetBossState(DATA_CRYSTAL_05, DONE);
go->SetGoState(GO_STATE_ACTIVE);
break;
default:
break;
}
}
}
if (GetBossState(DATA_CRYSTAL_01) == DONE && GetBossState(DATA_CRYSTAL_02) == DONE && GetBossState(DATA_CRYSTAL_03) == DONE &&
GetBossState(DATA_CRYSTAL_04) == DONE && GetBossState(DATA_CRYSTAL_05) == DONE)
{
// if all crystals are done, we set encounter forcefield to done
SetBossState(DATA_FORCEFIELD, DONE);
// activate forcefield to make it disappear
if (GameObject* ffield = instance->GetGameObject(_forcefieldGUID))
ffield->SetGoState(GO_STATE_ACTIVE);
// remove previously set non attackable flag
if (Creature* immo = instance->GetCreature(_immoGUID))
immo->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
}
}
protected:
EventMap _events;
std::array<ObjectGuid, 5> _crystalGUIDs;
std::array<std::array<ObjectGuid, 4>, 5> _crystalCreatureGUIDs; // 5 different Crystals, maximum of 4 Creatures
ObjectGuid _forcefieldGUID;
ObjectGuid _immoGUID;
};
InstanceScript* GetInstanceScript(InstanceMap* map) const override