/*
* 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 .
*/
/* Script Data Start
SDName: Gnomeregan
SDAuthor: Manuel
SD%Complete: 90%
SDComment: Some visual effects are not implemented.
Script Data End */
#include "ScriptMgr.h"
#include "GameObject.h"
#include "gnomeregan.h"
#include "InstanceScript.h"
#include "Map.h"
#include "ObjectAccessor.h"
#include "Player.h"
#include "ScriptedEscortAI.h"
#include "ScriptedGossip.h"
#include "TemporarySummon.h"
enum BlastmasterEmi
{
SAY_BLASTMASTER_0 = 0,
SAY_BLASTMASTER_1 = 1,
SAY_BLASTMASTER_2 = 2,
SAY_BLASTMASTER_3 = 3,
SAY_BLASTMASTER_4 = 4,
SAY_BLASTMASTER_5 = 5,
SAY_BLASTMASTER_6 = 6,
SAY_BLASTMASTER_7 = 7,
SAY_BLASTMASTER_8 = 8,
SAY_BLASTMASTER_9 = 9,
SAY_BLASTMASTER_10 = 10,
SAY_BLASTMASTER_11 = 11,
SAY_BLASTMASTER_12 = 12,
SAY_BLASTMASTER_13 = 13,
SAY_BLASTMASTER_14 = 14,
SAY_BLASTMASTER_15 = 15,
SAY_BLASTMASTER_16 = 16,
SAY_BLASTMASTER_17 = 17,
SAY_BLASTMASTER_18 = 18,
SAY_BLASTMASTER_19 = 19,
SAY_GRUBBIS = 0,
PATH_ESCORT_BLASTMASTER_EMI = 63986,
};
const Position SpawnPosition[] =
{
{-557.630f, -114.514f, -152.209f, 0.641f},
{-555.263f, -113.802f, -152.737f, 0.311f},
{-552.154f, -112.476f, -153.349f, 0.621f},
{-548.692f, -111.089f, -154.090f, 0.621f},
{-546.905f, -108.340f, -154.877f, 0.729f},
{-547.736f, -105.154f, -155.176f, 0.372f},
{-547.274f, -114.109f, -153.952f, 0.735f},
{-552.534f, -110.012f, -153.577f, 0.747f},
{-550.708f, -116.436f, -153.103f, 0.679f},
{-554.030f, -115.983f, -152.635f, 0.695f},
{-494.595f, -87.516f, -149.116f, 3.344f},
{-493.349f, -90.845f, -148.882f, 3.717f},
{-491.995f, -87.619f, -148.197f, 3.230f},
{-490.732f, -90.739f, -148.091f, 3.230f},
{-490.554f, -89.114f, -148.055f, 3.230f},
{-495.240f, -90.808f, -149.493f, 3.238f},
{-494.195f, -89.553f, -149.131f, 3.254f},
{-511.3304f, -139.9622f, -152.4761f, 0.7504908f},
{-510.6754f, -139.4371f, -152.6167f, 3.33359f},
{-511.8976f, -139.3562f, -152.4785f, 3.961899f}
};
class npc_blastmaster_emi_shortfuse : public CreatureScript
{
public:
npc_blastmaster_emi_shortfuse() : CreatureScript("npc_blastmaster_emi_shortfuse") { }
CreatureAI* GetAI(Creature* creature) const override
{
return GetGnomereganAI(creature);
}
struct npc_blastmaster_emi_shortfuseAI : public EscortAI
{
npc_blastmaster_emi_shortfuseAI(Creature* creature) : EscortAI(creature)
{
instance = creature->GetInstanceScript();
creature->RestoreFaction();
Initialize();
}
void Initialize()
{
uiTimer = 0;
uiPhase = 0;
}
InstanceScript* instance;
uint8 uiPhase;
uint32 uiTimer;
GuidList SummonList;
GuidList GoSummonList;
void Reset() override
{
if (!HasEscortState(STATE_ESCORT_ESCORTING))
{
Initialize();
RestoreAll();
SummonList.clear();
GoSummonList.clear();
}
}
bool OnGossipSelect(Player* player, uint32 /*menuId*/, uint32 gossipListId) override
{
if (gossipListId == 0)
{
LoadPath(PATH_ESCORT_BLASTMASTER_EMI);
Start(true, player->GetGUID());
me->SetFaction(player->GetFaction());
SetData(1, 0);
player->PlayerTalkClass->SendCloseGossip();
}
return false;
}
void NextStep(uint32 uiTimerStep, bool bNextStep = true, uint8 uiPhaseStep = 0)
{
uiTimer = uiTimerStep;
if (bNextStep)
++uiPhase;
else
uiPhase = uiPhaseStep;
}
void CaveDestruction(bool isRight)
{
if (GoSummonList.empty())
return;
for (GuidList::const_iterator itr = GoSummonList.begin(); itr != GoSummonList.end(); ++itr)
{
if (GameObject* go = ObjectAccessor::GetGameObject(*me, *itr))
{
if (Creature* trigger = go->SummonTrigger(go->GetPositionX(), go->GetPositionY(), go->GetPositionZ(), 0, 1ms))
{
//visual effects are not working!
trigger->CastSpell(trigger, 11542, true);
trigger->CastSpell(trigger, 35470, true);
}
go->RemoveFromWorld();
//go->CastSpell(me, 12158); makes all die?!
}
}
if (GameObject* go = ObjectAccessor::GetGameObject(*me, instance->GetGuidData(isRight ? DATA_GO_CAVE_IN_RIGHT : DATA_GO_CAVE_IN_LEFT)))
instance->HandleGameObject(ObjectGuid::Empty, false, go);
}
void SetInFace(bool isRight)
{
if (GameObject* go = ObjectAccessor::GetGameObject(*me, instance->GetGuidData(isRight ? DATA_GO_CAVE_IN_RIGHT : DATA_GO_CAVE_IN_LEFT)))
me->SetFacingToObject(go);
}
void RestoreAll()
{
if (GameObject* go = ObjectAccessor::GetGameObject(*me, instance->GetGuidData(DATA_GO_CAVE_IN_RIGHT)))
instance->HandleGameObject(ObjectGuid::Empty, false, go);
if (GameObject* go = ObjectAccessor::GetGameObject(*me, instance->GetGuidData(DATA_GO_CAVE_IN_LEFT)))
instance->HandleGameObject(ObjectGuid::Empty, false, go);
if (!GoSummonList.empty())
for (GuidList::const_iterator itr = GoSummonList.begin(); itr != GoSummonList.end(); ++itr)
{
if (GameObject* go = ObjectAccessor::GetGameObject(*me, *itr))
go->RemoveFromWorld();
}
if (!SummonList.empty())
for (GuidList::const_iterator itr = SummonList.begin(); itr != SummonList.end(); ++itr)
{
if (Creature* summon = ObjectAccessor::GetCreature(*me, *itr))
{
summon->DespawnOrUnsummon();
}
}
}
void AggroAllPlayers(Creature* temp)
{
Map::PlayerList const& PlList = me->GetMap()->GetPlayers();
for (Map::PlayerList::const_iterator i = PlList.begin(); i != PlList.end(); ++i)
{
if (Player* player = i->GetSource())
{
if (player->IsGameMaster())
continue;
if (player->IsAlive())
AddThreat(player, 0.0f, temp);
}
}
}
void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
{
//just in case
if (GetPlayerForEscort())
if (me->GetFaction() != GetPlayerForEscort()->GetFaction())
me->SetFaction(GetPlayerForEscort()->GetFaction());
switch (waypointId)
{
case 3:
SetEscortPaused(true);
NextStep(2000, false, 3);
break;
case 7:
SetEscortPaused(true);
NextStep(2000, false, 4);
break;
case 9:
NextStep(1000, false, 8);
break;
case 10:
NextStep(25000, false, 10);
break;
case 11:
SetEscortPaused(true);
SetInFace(true);
NextStep(1000, false, 11);
break;
case 12:
NextStep(25000, false, 18);
break;
case 13:
Summon(6);
NextStep(25000, false, 19);
break;
case 14:
SetInFace(false);
Talk(SAY_BLASTMASTER_17);
SetEscortPaused(true);
NextStep(5000, false, 20);
break;
}
}
void SetData(uint32 uiI, uint32 uiValue) override
{
switch (uiI)
{
case 1:
SetEscortPaused(true);
Talk(SAY_BLASTMASTER_0);
NextStep(2000, true);
break;
case 2:
switch (uiValue)
{
case 1:
instance->SetBossState(DATA_BLASTMASTER_EVENT, IN_PROGRESS);
break;
case 2:
instance->SetBossState(DATA_BLASTMASTER_EVENT, DONE);
NextStep(5000, false, 22);
break;
}
break;
}
}
void Summon(uint8 uiCase)
{
switch (uiCase)
{
case 1:
me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[0], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30min);
me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[1], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30min);
me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[2], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30min);
me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[3], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30min);
me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[4], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30min);
me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[5], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30min);
me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[6], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30min);
me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[7], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30min);
me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[8], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30min);
me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[9], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30min);
break;
case 2:
if (GameObject* go = me->SummonGameObject(183410, -533.140f, -105.322f, -156.016f, 0.f, QuaternionData(), 1s))
{
GoSummonList.push_back(go->GetGUID());
go->SetFlag(GO_FLAG_NOT_SELECTABLE); //We can't use it!
}
Summon(3);
break;
case 3:
me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[0], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30min);
me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[1], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30min);
me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[2], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30min);
me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[3], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30min);
Talk(SAY_BLASTMASTER_7);
break;
case 4:
if (GameObject* go = me->SummonGameObject(183410, -542.199f, -96.854f, -155.790f, 0.f, QuaternionData(), 1s))
{
GoSummonList.push_back(go->GetGUID());
go->SetFlag(GO_FLAG_NOT_SELECTABLE);
}
break;
case 5:
me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[10], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30min);
me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[11], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30min);
me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[12], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30min);
me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[13], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30min);
me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[14], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30min);
break;
case 6:
if (GameObject* go = me->SummonGameObject(183410, -507.820f, -103.333f, -151.353f, 0.f, QuaternionData(), 1s))
{
GoSummonList.push_back(go->GetGUID());
go->SetFlag(GO_FLAG_NOT_SELECTABLE); //We can't use it!
Summon(5);
}
break;
case 7:
if (GameObject* go = me->SummonGameObject(183410, -511.829f, -86.249f, -151.431f, 0.f, QuaternionData(), 1s))
{
GoSummonList.push_back(go->GetGUID());
go->SetFlag(GO_FLAG_NOT_SELECTABLE); //We can't use it!
}
break;
case 8:
if (Creature* grubbis = me->SummonCreature(NPC_GRUBBIS, SpawnPosition[15], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30min))
grubbis->AI()->Talk(SAY_GRUBBIS);
me->SummonCreature(NPC_CHOMPER, SpawnPosition[16], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30min);
break;
case 9:
me->SummonGameObject(GO_RED_ROCKET, SpawnPosition[17], QuaternionData::fromEulerAnglesZYX(SpawnPosition[17].GetOrientation(), 0.0f, 0.0f), 2h);
me->SummonGameObject(GO_RED_ROCKET, SpawnPosition[18], QuaternionData::fromEulerAnglesZYX(SpawnPosition[18].GetOrientation(), 0.0f, 0.0f), 2h);
me->SummonGameObject(GO_RED_ROCKET, SpawnPosition[19], QuaternionData::fromEulerAnglesZYX(SpawnPosition[19].GetOrientation(), 0.0f, 0.0f), 2h);
break;
}
}
void UpdateEscortAI(uint32 uiDiff) override
{
if (uiPhase)
{
if (uiTimer <= uiDiff)
{
switch (uiPhase)
{
case 1:
Talk(SAY_BLASTMASTER_1);
NextStep(2000, true);
break;
case 2:
SetEscortPaused(false);
NextStep(0, false, 0);
break;
case 3:
Talk(SAY_BLASTMASTER_2);
SetEscortPaused(false);
NextStep(0, false, 0);
break;
case 4:
Talk(SAY_BLASTMASTER_3);
NextStep(3000, true);
break;
case 5:
Talk(SAY_BLASTMASTER_4);
NextStep(3000, true);
break;
case 6:
SetInFace(true);
Talk(SAY_BLASTMASTER_5);
Summon(1);
if (GameObject* go = ObjectAccessor::GetGameObject(*me, instance->GetGuidData(DATA_GO_CAVE_IN_RIGHT)))
instance->HandleGameObject(ObjectGuid::Empty, true, go);
NextStep(3000, true);
break;
case 7:
Talk(SAY_BLASTMASTER_6);
SetEscortPaused(false);
NextStep(0, false, 0);
break;
case 8:
me->HandleEmoteCommand(EMOTE_STATE_USE_STANDING);
NextStep(25000, true);
break;
case 9:
Summon(2);
NextStep(0, false);
break;
case 10:
Summon(4);
Talk(SAY_BLASTMASTER_8);
NextStep(0, false);
break;
case 11:
Talk(SAY_BLASTMASTER_9);
NextStep(5000, true);
break;
case 12:
Talk(SAY_BLASTMASTER_10);
NextStep(5000, true);
break;
case 13:
Talk(SAY_BLASTMASTER_11);
CaveDestruction(true);
NextStep(8000, true);
break;
case 14:
Talk(SAY_BLASTMASTER_12);
NextStep(8500, true);
break;
case 15:
Talk(SAY_BLASTMASTER_13);
NextStep(2000, true);
break;
case 16:
Talk(SAY_BLASTMASTER_14);
SetInFace(false);
if (GameObject* go = ObjectAccessor::GetGameObject(*me, instance->GetGuidData(DATA_GO_CAVE_IN_LEFT)))
instance->HandleGameObject(ObjectGuid::Empty, true, go);
NextStep(2000, true);
break;
case 17:
SetEscortPaused(false);
Talk(SAY_BLASTMASTER_15);
Summon(5);
NextStep(0, false);
break;
case 18:
Summon(6);
NextStep(0, false);
break;
case 19:
SetInFace(false);
Summon(7);
Talk(SAY_BLASTMASTER_16);
NextStep(0, false);
break;
case 20:
Talk(SAY_BLASTMASTER_18);
NextStep(2000, true);
break;
case 21:
Summon(8);
NextStep(0, false);
break;
case 22:
CaveDestruction(false);
Talk(SAY_BLASTMASTER_11);
NextStep(3000, true);
break;
case 23:
Summon(9);
Talk(SAY_BLASTMASTER_19);
NextStep(0, false);
break;
}
} else uiTimer -= uiDiff;
}
UpdateVictim();
}
void JustSummoned(Creature* summon) override
{
SummonList.push_back(summon->GetGUID());
AggroAllPlayers(summon);
}
};
};
class boss_grubbis : public CreatureScript
{
public:
boss_grubbis() : CreatureScript("boss_grubbis") { }
CreatureAI* GetAI(Creature* creature) const override
{
return GetGnomereganAI(creature);
}
struct boss_grubbisAI : public ScriptedAI
{
boss_grubbisAI(Creature* creature) : ScriptedAI(creature)
{
SetDataSummoner();
}
void SetDataSummoner()
{
if (!me->IsSummon())
return;
if (Unit* summon = me->ToTempSummon()->GetSummonerUnit())
if (Creature* creature = summon->ToCreature())
creature->AI()->SetData(2, 1);
}
void JustDied(Unit* /*killer*/) override
{
if (!me->IsSummon())
return;
if (Unit* summoner = me->ToTempSummon()->GetSummonerUnit())
if (Creature* creature = summoner->ToCreature())
creature->AI()->SetData(2, 2);
}
};
};
void AddSC_gnomeregan()
{
new npc_blastmaster_emi_shortfuse();
new boss_grubbis();
}