fix(Scripts/ZulFarrak): Moved Sergeant Bly's script from DB to C++ (#7855)

This commit is contained in:
UltraNix
2021-09-21 12:36:51 +02:00
committed by GitHub
parent d065f52615
commit 048025ceba
5 changed files with 1127 additions and 24 deletions

View File

@@ -9,10 +9,87 @@
#include "TemporarySummon.h"
#include "zulfarrak.h"
enum Misc
{
// Paths
PATH_ADDS = 81553,
SAY_BLY_FORWARD = 2
};
struct PyramidEventData
{
uint8 waveID = 0;
uint32 creatureID = 0;
Position pos;
};
uint32 const pyramidSpawnTotal = 54;
/* list of wave spawns: 0 = wave ID, 1 = creature id, 2 = x, 3 = y
no z coordinat b/c they're all the same */
static PyramidEventData pyramidSpawns[pyramidSpawnTotal] =
{
{ 1, NPC_SANDFURY_CRETIN, { 1894.64f, 1206.29f } },
{ 1, NPC_SANDFURY_SLAVE, { 1890.08f, 1218.68f } },
{ 1, NPC_SANDFURY_ACOLYTE, { 1883.76f, 1222.30f } },
{ 1, NPC_SANDFURY_CRETIN, { 1874.18f, 1221.24f } },
{ 1, NPC_SANDFURY_SLAVE, { 1892.28f, 1225.49f } },
{ 1, NPC_SANDFURY_DRUDGE, { 1889.94f, 1212.21f } },
{ 1, NPC_SANDFURY_SLAVE, { 1879.02f, 1223.06f } },
{ 1, NPC_SANDFURY_CRETIN, { 1874.45f, 1204.44f } },
{ 1, NPC_SANDFURY_ACOLYTE, { 1898.23f, 1217.97f } },
{ 1, NPC_SANDFURY_SLAVE, { 1882.07f, 1225.70f } },
{ 1, NPC_SANDFURY_ZEALOT, { 1896.46f, 1205.62f } },
{ 1, NPC_SANDFURY_SLAVE, { 1886.97f, 1225.86f } },
{ 1, NPC_SANDFURY_SLAVE, { 1894.72f, 1221.91f } },
{ 1, NPC_SANDFURY_SLAVE, { 1883.50f, 1218.25f } },
{ 1, NPC_SANDFURY_SLAVE, { 1886.93f, 1221.40f } },
{ 1, NPC_SANDFURY_ACOLYTE, { 1889.82f, 1222.51f } },
{ 1, NPC_SANDFURY_DRUDGE, { 1893.07f, 1215.26f } },
{ 1, NPC_SANDFURY_DRUDGE, { 1878.57f, 1214.16f } },
{ 1, NPC_SANDFURY_DRUDGE, { 1883.74f, 1212.35f } },
{ 1, NPC_SANDFURY_ZEALOT, { 1877.00f, 1207.27f } },
{ 1, NPC_SANDFURY_ZEALOT, { 1873.63f, 1204.65f } },
{ 1, NPC_SANDFURY_ACOLYTE, { 1877.40f, 1216.41f } },
{ 1, NPC_SANDFURY_ZEALOT, { 1899.63f, 1202.52f } },
{ 2, NPC_SANDFURY_CRETIN, { 1902.83f, 1223.41f } },
{ 2, NPC_SANDFURY_ACOLYTE, { 1889.82f, 1222.51f } },
{ 2, NPC_SANDFURY_SLAVE, { 1883.50f, 1218.25f } },
{ 2, NPC_SANDFURY_DRUDGE, { 1883.74f, 1212.35f } },
{ 2, NPC_SANDFURY_ZEALOT, { 1877.00f, 1207.27f } },
{ 2, NPC_SANDFURY_SLAVE, { 1890.08f, 1218.68f } },
{ 2, NPC_SANDFURY_CRETIN, { 1894.64f, 1206.29f } },
{ 2, NPC_SANDFURY_ACOLYTE, { 1877.40f, 1216.41f } },
{ 2, NPC_SANDFURY_SLAVE, { 1892.28f, 1225.49f } },
{ 2, NPC_SANDFURY_DRUDGE, { 1893.07f, 1215.26f } },
{ 2, NPC_SANDFURY_ZEALOT, { 1896.46f, 1205.62f } },
{ 2, NPC_SANDFURY_CRETIN, { 1874.45f, 1204.44f } },
{ 2, NPC_SANDFURY_CRETIN, { 1874.18f, 1221.24f } },
{ 2, NPC_SANDFURY_SLAVE, { 1879.02f, 1223.06f } },
{ 2, NPC_SANDFURY_ACOLYTE, { 1898.23f, 1217.97f } },
{ 2, NPC_SANDFURY_SLAVE, { 1882.07f, 1225.70f } },
{ 2, NPC_SANDFURY_ZEALOT, { 1873.63f, 1204.65f } },
{ 2, NPC_SANDFURY_SLAVE, { 1886.97f, 1225.86f } },
{ 2, NPC_SANDFURY_DRUDGE, { 1878.57f, 1214.16f } },
{ 2, NPC_SANDFURY_SLAVE, { 1894.72f, 1221.91f } },
{ 2, NPC_SANDFURY_SLAVE, { 1886.93f, 1221.40f } },
{ 2, NPC_SANDFURY_ACOLYTE, { 1883.76f, 1222.30f } },
{ 2, NPC_SANDFURY_DRUDGE, { 1889.94f, 1212.21f } },
{ 2, NPC_SANDFURY_ZEALOT, { 1899.63f, 1202.52f } },
{ 3, NPC_SANDFURY_DRUDGE, { 1878.57f, 1214.16f } },
{ 3, NPC_SANDFURY_SLAVE, { 1894.72f, 1221.91f } },
{ 3, NPC_SANDFURY_SLAVE, { 1886.93f, 1221.40f } },
{ 3, NPC_SANDFURY_ACOLYTE, { 1883.76f, 1222.30f } },
{ 3, NPC_SANDFURY_DRUDGE, { 1889.94f, 1212.21f } },
{ 3, NPC_SHADOWPRIEST_SEZZZIZ, { 1886.30f, 1199.65f } },
{ 3, NPC_NEKRUM_GUTCHEWER, { 1881.06f, 1199.70f } }
};
class instance_zulfarrak : public InstanceMapScript
{
public:
instance_zulfarrak() : InstanceMapScript("instance_zulfarrak", 209) { }
instance_zulfarrak() : InstanceMapScript(ZFScriptName, 209) {}
InstanceScript* GetInstanceScript(InstanceMap* map) const override
{
@@ -23,44 +100,337 @@ public:
{
instance_zulfarrak_InstanceMapScript(Map* map) : InstanceScript(map) { }
ObjectGuid EndDoorGUID;
ObjectGuid BlyGUID;
ObjectGuid WeegliGUID;
ObjectGuid OroGUID;
ObjectGuid RavenGUID;
ObjectGuid MurtaGUID;
ObjectGuid ShadowpriestGUID;
GuidList addsAtBase;
GuidList movedadds;
uint32 GahzrillaSummoned;
uint32 PyramidPhase;
uint32 major_wave_Timer;
uint32 minor_wave_Timer;
uint32 addGroupSize;
uint32 waypoint;
void Initialize() override
{
_pyramidEventProgress = NOT_STARTED;
_gahzrillaSummoned = NOT_STARTED;
GahzrillaSummoned = NOT_STARTED;
PyramidPhase = 0;
major_wave_Timer = 0;
minor_wave_Timer = 0;
addGroupSize = 0;
waypoint = 0;
}
void OnCreatureCreate(Creature* creature) override
{
switch (creature->GetEntry())
{
case NPC_BLY:
BlyGUID = creature->GetGUID();
creature->SetReactState(REACT_PASSIVE); // starts out passive (in a cage)
break;
case NPC_RAVEN:
RavenGUID = creature->GetGUID();
creature->SetReactState(REACT_PASSIVE);// starts out passive (in a cage)
break;
case NPC_ORO:
OroGUID = creature->GetGUID();
creature->SetReactState(REACT_PASSIVE);// starts out passive (in a cage)
break;
case NPC_WEEGLI:
WeegliGUID = creature->GetGUID();
creature->SetReactState(REACT_PASSIVE);// starts out passive (in a cage)
break;
case NPC_MURTA:
MurtaGUID = creature->GetGUID();
creature->SetReactState(REACT_PASSIVE);// starts out passive (in a cage)
break;
case NPC_SHADOWPRIEST_SEZZZIZ:
ShadowpriestGUID = creature->GetGUID();
break;
default:
break;
}
}
void OnGameObjectCreate(GameObject* gameobject) override
{
if (gameobject->GetEntry() == GO_END_DOOR && _pyramidEventProgress == DONE)
gameobject->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE);
switch (gameobject->GetEntry())
{
case GO_END_DOOR:
EndDoorGUID = gameobject->GetGUID();
if (PyramidPhase == PYRAMID_DONE)
{
HandleGameObject(gameobject->GetGUID(), true, gameobject);
}
break;
default:
break;
}
}
uint32 GetData(uint32 type) const override
void OnUnitDeath(Unit* unit) override
{
if (type == TYPE_PYRAMID_EVENT)
return _pyramidEventProgress;
return 0;
if (unit->GetEntry() == NPC_BLY)
{
PyramidPhase = PYRAMID_DONE;
SaveToDB();
}
}
void SetData(uint32 type, uint32 data) override
{
switch (type)
{
case TYPE_PYRAMID_EVENT:
_pyramidEventProgress = data;
case DATA_PYRAMID:
PyramidPhase = data;
break;
case TYPE_GAHZRILLA:
_gahzrillaSummoned = data;
case DATA_GAHZRILLA:
GahzrillaSummoned = data;
break;
default:
break;
}
SaveToDB();
}
uint32 GetData(uint32 type) const override
{
switch (type)
{
case DATA_PYRAMID:
return PyramidPhase;
case DATA_GAHZRILLA:
return GahzrillaSummoned;
}
return 0;
}
ObjectGuid GetGuidData(uint32 data) const override
{
switch (data)
{
case NPC_BLY:
return BlyGUID;
case NPC_RAVEN:
return RavenGUID;
case NPC_ORO:
return OroGUID;
case NPC_WEEGLI:
return WeegliGUID;
case NPC_MURTA:
return MurtaGUID;
case NPC_SHADOWPRIEST_SEZZZIZ:
return ShadowpriestGUID;
case GO_END_DOOR:
return EndDoorGUID;
}
return ObjectGuid::Empty;
}
void Update(uint32 diff) override
{
switch (PyramidPhase)
{
case PYRAMID_NOT_STARTED:
case PYRAMID_KILLED_ALL_TROLLS:
case PYRAMID_MOVED_DOWNSTAIRS:
case PYRAMID_DESTROY_GATES:
case PYRAMID_GATES_DESTROYED:
case PYRAMID_DONE:
break;
case PYRAMID_ARRIVED_AT_STAIR:
SpawnPyramidWave(1);
SetData(DATA_PYRAMID, PYRAMID_WAVE_1);
major_wave_Timer = 2 * MINUTE * IN_MILLISECONDS;
minor_wave_Timer = 0;
addGroupSize = 2;
break;
case PYRAMID_WAVE_1:
if (IsWaveAllDead())
{
SetData(DATA_PYRAMID, PYRAMID_PRE_WAVE_2);
major_wave_Timer = 10 * IN_MILLISECONDS; //give players a few seconds before wave 2 starts to rebuff
}
else
{
if (minor_wave_Timer <= diff)
{
SendAddsUpStairs(addGroupSize++);
minor_wave_Timer = 10 * IN_MILLISECONDS;
}
else
{
minor_wave_Timer -= diff;
}
}
break;
case PYRAMID_PRE_WAVE_2:
if (major_wave_Timer <= diff)
{
// beginning 2nd wave!
SpawnPyramidWave(2);
SetData(DATA_PYRAMID, PYRAMID_WAVE_2);
minor_wave_Timer = 0;
addGroupSize = 2;
}
else
{
major_wave_Timer -= diff;
}
break;
case PYRAMID_WAVE_2:
if (IsWaveAllDead())
{
SpawnPyramidWave(3);
SetData(DATA_PYRAMID, PYRAMID_PRE_WAVE_3);
major_wave_Timer = 5 * IN_MILLISECONDS; //give NPCs time to return to their home spots
}
else
{
if (minor_wave_Timer <= diff)
{
SendAddsUpStairs(addGroupSize++);
minor_wave_Timer = 10 * IN_MILLISECONDS;
}
else
{
minor_wave_Timer -= diff;
}
}
break;
case PYRAMID_PRE_WAVE_3:
if (major_wave_Timer <= diff)
{
// move NPCs to bottom of stair
MoveNPCIfAlive(NPC_BLY, 1887.92f, 1228.179f, 9.98f, 4.78f);
MoveNPCIfAlive(NPC_MURTA, 1891.57f, 1228.68f, 9.69f, 4.78f);
MoveNPCIfAlive(NPC_ORO, 1897.23f, 1228.34f, 9.43f, 4.78f);
MoveNPCIfAlive(NPC_RAVEN, 1883.68f, 1227.95f, 9.543f, 4.78f);
MoveNPCIfAlive(NPC_WEEGLI, 1878.02f, 1227.65f, 9.485f, 4.78f);
SetData(DATA_PYRAMID, PYRAMID_WAVE_3);
if (Creature* sergeantBlye = instance->GetCreature(BlyGUID))
{
sergeantBlye->AI()->Talk(SAY_BLY_FORWARD);
}
}
else
{
major_wave_Timer -= diff;
}
break;
case PYRAMID_WAVE_3:
if (IsWaveAllDead()) // move NPCS to their final positions
{
SetData(DATA_PYRAMID, PYRAMID_KILLED_ALL_TROLLS);
MoveNPCIfAlive(NPC_BLY, 1883.82f, 1200.83f, 8.87f, 1.32f);
MoveNPCIfAlive(NPC_MURTA, 1891.83f, 1201.45f, 8.87f, 1.32f);
MoveNPCIfAlive(NPC_ORO, 1894.50f, 1204.40f, 8.87f, 1.32f);
MoveNPCIfAlive(NPC_RAVEN, 1874.11f, 1206.17f, 8.87f, 1.32f);
MoveNPCIfAlive(NPC_WEEGLI, 1877.52f, 1199.63f, 8.87f, 1.32f);
}
break;
default:
break;
};
}
void MoveNPCIfAlive(uint32 entry, float x, float y, float z, float o)
{
if (Creature* npc = instance->GetCreature(GetGuidData(entry)))
{
if (npc->IsAlive())
{
npc->SetWalk(true);
npc->GetMotionMaster()->MovePoint(1, { x, y, z, o } );
npc->SetHomePosition(x, y, z, o);
}
}
}
void SpawnPyramidWave(uint32 wave)
{
for (uint32 i = 0; i < pyramidSpawnTotal; i++)
{
if (pyramidSpawns[i].waveID == wave)
{
float orientation = 4.78f;
if (pyramidSpawns[i].creatureID == NPC_SHADOWPRIEST_SEZZZIZ || pyramidSpawns[i].creatureID == NPC_NEKRUM_GUTCHEWER)
{
orientation = 1.32f;
}
Position pos = { pyramidSpawns[i].pos.GetPositionX(), pyramidSpawns[i].pos.GetPositionY(), 8.87f, orientation };
if (TempSummon* ts = instance->SummonCreature(pyramidSpawns[i].creatureID, pos))
{
addsAtBase.push_back(ts->GetGUID());
if (pyramidSpawns[i].creatureID != NPC_SHADOWPRIEST_SEZZZIZ && pyramidSpawns[i].creatureID != NPC_NEKRUM_GUTCHEWER)
{
ts->GetMotionMaster()->MoveRandom(10);
}
}
}
}
}
bool IsWaveAllDead()
{
for (GuidList::iterator itr = addsAtBase.begin(); itr != addsAtBase.end(); ++itr)
{
if (Creature* add = instance->GetCreature((*itr)))
{
if (add->IsAlive())
{
return false;
}
}
}
for (GuidList::iterator itr = movedadds.begin(); itr != movedadds.end(); ++itr)
{
if (Creature* add = instance->GetCreature(((*itr))))
{
if (add->IsAlive())
{
return false;
}
}
}
return true;
}
void SendAddsUpStairs(uint32 count)
{
//pop a add from list, send him up the stairs...
for (uint32 addCount = 0; addCount < count && !addsAtBase.empty(); addCount++)
{
if (Creature* add = instance->GetCreature(*addsAtBase.begin()))
{
add->GetMotionMaster()->MovePath(PATH_ADDS, false);
movedadds.push_back(add->GetGUID());
}
addsAtBase.erase(addsAtBase.begin());
}
}
std::string GetSaveData() override
{
std::ostringstream saveStream;
saveStream << "Z F " << _pyramidEventProgress << ' ' << _gahzrillaSummoned;
saveStream << "Z F " << PyramidPhase << ' ' << GahzrillaSummoned;
return saveStream.str();
}
@@ -75,14 +445,10 @@ public:
if (dataHead1 == 'Z' && dataHead2 == 'F')
{
loadStream >> _pyramidEventProgress;
loadStream >> _gahzrillaSummoned;
loadStream >> PyramidPhase;
loadStream >> GahzrillaSummoned;
}
}
private:
uint32 _pyramidEventProgress;
uint32 _gahzrillaSummoned;
};
};

View File

@@ -0,0 +1,674 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it and/or modify it under version 2 of the License, or (at your option), any later version.
* Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/>
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
*/
/* ScriptData
SDName: Zulfarrak
SD%Complete: 50
SDComment: Consider it temporary, no instance script made for this instance yet.
SDCategory: Zul'Farrak
EndScriptData */
/* ContentData
npc_sergeant_bly
npc_weegli_blastfuse
EndContentData */
#include "ScriptMgr.h"
#include "ScriptSystem.h"
#include "GameObject.h"
#include "GameObjectAI.h"
#include "InstanceScript.h"
#include "MotionMaster.h"
#include "ObjectAccessor.h"
#include "Player.h"
#include "ScriptedCreature.h"
#include "ScriptedGossip.h"
#include "zulfarrak.h"
#include "Cell.h"
#include "CellImpl.h"
#include "GridNotifiers.h"
#include "GridNotifiersImpl.h"
/*######
## npc_sergeant_bly
######*/
enum blySays
{
SAY_1 = 0,
SAY_2 = 1
};
enum blySpells
{
SPELL_SHIELD_BASH = 11972,
SPELL_REVENGE = 12170
};
#define GOSSIP_BLY "That's it! I'm tired of helping you out. It's time we settled things on the battlefield!"
class npc_sergeant_bly : public CreatureScript
{
public:
npc_sergeant_bly() : CreatureScript("npc_sergeant_bly") { }
struct npc_sergeant_blyAI : public ScriptedAI
{
npc_sergeant_blyAI(Creature* creature) : ScriptedAI(creature)
{
instance = creature->GetInstanceScript();
}
void InitializeAI() override
{
startedFight = false;
me->setFaction(35);
postGossipStep = 0;
Text_Timer = 0;
me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
}
InstanceScript* instance;
bool startedFight;
uint32 postGossipStep;
uint32 Text_Timer;
uint32 ShieldBash_Timer;
uint32 Revenge_Timer; //this is wrong, spell should never be used unless me->GetVictim() dodge, parry or block attack. Trinity support required.
ObjectGuid PlayerGUID;
void Reset() override
{
ShieldBash_Timer = 5000;
Revenge_Timer = 8000;
}
void MovementInform(uint32 type, uint32 /*id*/) override
{
if (type != POINT_MOTION_TYPE)
{
return;
}
if (instance->GetData(DATA_PYRAMID) == PYRAMID_WAVE_3)
{
if (Creature* shadowpriest = ObjectAccessor::GetCreature(*me, instance->GetGuidData(NPC_SHADOWPRIEST_SEZZZIZ)))
{
AttackStart(shadowpriest);
shadowpriest->CallAssistance();
}
}
}
void UpdateAI(uint32 diff) override
{
if (postGossipStep > 0 && postGossipStep < 4)
{
if (Text_Timer <= diff)
{
switch (postGossipStep)
{
case 1:
//weegli doesn't fight - he goes & blows up the door
if (Creature* pWeegli = ObjectAccessor::GetCreature(*me, instance->GetGuidData(NPC_WEEGLI)))
{
pWeegli->AI()->DoAction(0);
}
Talk(SAY_1);
Text_Timer = 5000;
break;
case 2:
Talk(SAY_2);
Text_Timer = 5000;
break;
case 3:
me->setFaction(14);
Player* target = ObjectAccessor::GetPlayer(*me, PlayerGUID);
switchFactionIfAlive(NPC_RAVEN, target);
switchFactionIfAlive(NPC_ORO, target);
switchFactionIfAlive(NPC_MURTA, target);
if (target)
{
AttackStart(target);
}
}
postGossipStep++;
}
else
{
Text_Timer -= diff;
}
}
if (!UpdateVictim())
{
return;
}
if (ShieldBash_Timer <= diff)
{
DoCastVictim(SPELL_SHIELD_BASH);
ShieldBash_Timer = 15000;
}
else
{
ShieldBash_Timer -= diff;
}
if (Revenge_Timer <= diff)
{
DoCastVictim(SPELL_REVENGE);
Revenge_Timer = 10000;
}
else
{
Revenge_Timer -= diff;
}
DoMeleeAttackIfReady();
}
void DoAction(int32 /*param*/) override
{
postGossipStep = 1;
Text_Timer = 0;
}
void switchFactionIfAlive(uint32 entry, Player* target)
{
if (Creature* crew = ObjectAccessor::GetCreature(*me, instance->GetGuidData(entry)))
{
if (crew->IsAlive())
{
crew->setFaction(14);
if (target)
{
crew->AI()->AttackStart(target);
}
}
}
}
void sGossipSelect(Player* player, uint32 /*menuId*/, uint32 gossipListId) override
{
uint32 const action = player->PlayerTalkClass->GetGossipOptionAction(gossipListId);
ClearGossipMenuFor(player);
if (action == GOSSIP_ACTION_INFO_DEF + 1)
{
CloseGossipMenuFor(player);
PlayerGUID = player->GetGUID();
DoAction(0);
}
}
void sGossipHello(Player* player) override
{
if (instance->GetData(DATA_PYRAMID) >= PYRAMID_DESTROY_GATES && !startedFight)
{
startedFight = true;
AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_BLY, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
SendGossipMenuFor(player, 1517, me->GetGUID());
}
else
{
if (instance->GetData(DATA_PYRAMID) == PYRAMID_NOT_STARTED)
{
SendGossipMenuFor(player, 1515, me->GetGUID());
}
else
{
SendGossipMenuFor(player, 1516, me->GetGUID());
}
}
}
};
CreatureAI* GetAI(Creature* creature) const override
{
return GetZulFarrakAI<npc_sergeant_blyAI>(creature);
}
};
/*######
+## go_troll_cage
+######*/
class go_troll_cage : public GameObjectScript
{
public:
go_troll_cage() : GameObjectScript("go_troll_cage") { }
struct go_troll_cageAI : public GameObjectAI
{
go_troll_cageAI(GameObject* go) : GameObjectAI(go), instance(go->GetInstanceScript()) { }
InstanceScript* instance;
bool GossipHello(Player* /*player*/, bool reportUse) override
{
if (reportUse)
{
return true;
}
instance->SetData(DATA_PYRAMID, PYRAMID_CAGES_OPEN);
//set bly & co to aggressive & start moving to top of stairs
initBlyCrewMember(NPC_BLY, 1884.99f, 1263, 41.52f);
initBlyCrewMember(NPC_RAVEN, 1882.5f, 1263, 41.52f);
initBlyCrewMember(NPC_ORO, 1886.47f, 1270.68f, 41.68f);
initBlyCrewMember(NPC_WEEGLI, 1890, 1263, 41.52f);
initBlyCrewMember(NPC_MURTA, 1891.19f, 1272.03f, 41.60f);
return false;
}
private:
void initBlyCrewMember(uint32 entry, float x, float y, float z)
{
if (Creature* crew = ObjectAccessor::GetCreature(*go, instance->GetGuidData(entry)))
{
crew->SetReactState(REACT_AGGRESSIVE);
crew->SetWalk(true);
crew->SetHomePosition(x, y, z, 4.78f);
crew->GetMotionMaster()->MovePoint(1, { x, y, z, 4.78f });
crew->setFaction(FACTION_ESCORT_N_NEUTRAL_ACTIVE);
switch (entry)
{
case NPC_BLY:
case NPC_WEEGLI:
crew->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
break;
default:
break;
}
}
}
};
GameObjectAI* GetAI(GameObject* go) const override
{
return GetZulFarrakAI<go_troll_cageAI>(go);
}
};
/*######
## npc_weegli_blastfuse
######*/
enum weegliSpells
{
SPELL_BOMB = 8858,
SPELL_GOBLIN_LAND_MINE = 21688,
SPELL_SHOOT = 6660,
SPELL_WEEGLIS_BARREL = 10772
};
enum weegliSays
{
SAY_WEEGLI_OHNO = 0,
SAY_WEEGLI_OK_I_GO = 1,
SAY_WEEGLI_OUT_OF_HERE = 2
};
#define GOSSIP_WEEGLI "Will you blow up that door now?"
class npc_weegli_blastfuse : public CreatureScript
{
public:
npc_weegli_blastfuse() : CreatureScript("npc_weegli_blastfuse") { }
struct npc_weegli_blastfuseAI : public ScriptedAI
{
npc_weegli_blastfuseAI(Creature* creature) : ScriptedAI(creature)
{
instance = creature->GetInstanceScript();
destroyingDoor = false;
outroTimer = 2000;
outroStage = 0;
}
uint32 Bomb_Timer;
uint32 LandMine_Timer;
uint32 outroTimer;
uint8 outroStage;
bool destroyingDoor;
InstanceScript* instance;
void InitializeAI() override
{
me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
Reset();
}
void Reset() override
{
Bomb_Timer = 10000;
LandMine_Timer = 30000;
}
void AttackStart(Unit* victim) override
{
AttackStartCaster(victim, 10);//keep back & toss bombs/shoot
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
{
if (destroyingDoor)
{
if (outroTimer <= diff)
{
switch (outroStage)
{
case 0:
DoCastSelf(SPELL_WEEGLIS_BARREL);
outroTimer = 2000;
++outroStage;
break;
case 1:
me->GetMotionMaster()->MovePoint(2, 1871.18f, 1100.f, 8.88f);
Talk(SAY_WEEGLI_OUT_OF_HERE);
me->DespawnOrUnsummon(8000);
instance->SetData(DATA_PYRAMID, PYRAMID_GATES_DESTROYED);
destroyingDoor = false;
break;
}
}
else
{
outroTimer -= diff;
}
}
return;
}
if (Bomb_Timer <= diff)
{
DoCastVictim(SPELL_BOMB);
Bomb_Timer = 10000;
}
else
{
Bomb_Timer -= diff;
}
if (LandMine_Timer <= diff)
{
DoCastSelf(SPELL_GOBLIN_LAND_MINE);
LandMine_Timer = 30000;
}
else
{
LandMine_Timer -= diff;
}
if (me->isAttackReady() && !me->IsWithinMeleeRange(me->GetVictim()))
{
DoCastVictim(SPELL_SHOOT);
me->SetSheath(SHEATH_STATE_RANGED);
}
else
{
me->SetSheath(SHEATH_STATE_MELEE);
DoMeleeAttackIfReady();
}
}
void JustReachedHome() override
{
if (instance->GetData(DATA_PYRAMID) == PYRAMID_CAGES_OPEN)
{
instance->SetData(DATA_PYRAMID, PYRAMID_ARRIVED_AT_STAIR);
Talk(SAY_WEEGLI_OHNO);
}
else if (instance->GetData(DATA_PYRAMID) == PYRAMID_KILLED_ALL_TROLLS)
{
instance->SetData(DATA_PYRAMID, PYRAMID_MOVED_DOWNSTAIRS);
me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
}
else if (instance->GetData(DATA_PYRAMID) == PYRAMID_DESTROY_GATES)
{
destroyingDoor = true;
}
}
void MovementInform(uint32 type, uint32 /*id*/) override
{
if (type != POINT_MOTION_TYPE)
{
return;
}
if (instance->GetData(DATA_PYRAMID) == PYRAMID_CAGES_OPEN)
{
instance->SetData(DATA_PYRAMID, PYRAMID_ARRIVED_AT_STAIR);
Talk(SAY_WEEGLI_OHNO);
}
else if (instance->GetData(DATA_PYRAMID) == PYRAMID_KILLED_ALL_TROLLS)
{
instance->SetData(DATA_PYRAMID, PYRAMID_MOVED_DOWNSTAIRS);
me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
}
else if (instance->GetData(DATA_PYRAMID) == PYRAMID_DESTROY_GATES)
{
destroyingDoor = true;
}
}
void DestroyDoor()
{
if (me->IsAlive())
{
me->setFaction(35);
me->SetWalk(false);
me->GetMotionMaster()->MovePoint(0, { 1858.57f, 1146.35f, 14.745f, 3.85f });
me->SetHomePosition(1858.57f, 1146.35f, 14.745f, 3.85f);
Talk(SAY_WEEGLI_OK_I_GO);
instance->SetData(DATA_PYRAMID, PYRAMID_DESTROY_GATES);
if (Creature* sergeantBly = ObjectAccessor::GetCreature(*me, instance->GetGuidData(NPC_BLY)))
{
sergeantBly->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
}
}
}
void sGossipSelect(Player* player, uint32 /*menuId*/, uint32 gossipListId) override
{
uint32 const action = player->PlayerTalkClass->GetGossipOptionAction(gossipListId);
ClearGossipMenuFor(player);
if (action == GOSSIP_ACTION_INFO_DEF + 1)
{
CloseGossipMenuFor(player);
//here we make him run to door, set the charge and run away off to nowhere
DestroyDoor();
}
}
void sGossipHello(Player* player) override
{
switch (instance->GetData(DATA_PYRAMID))
{
case PYRAMID_MOVED_DOWNSTAIRS:
AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_WEEGLI, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
SendGossipMenuFor(player, 1514, me->GetGUID()); //if event can proceed to end
break;
case PYRAMID_NOT_STARTED:
SendGossipMenuFor(player, 1511, me->GetGUID()); //if event not started
break;
default:
SendGossipMenuFor(player, 1513, me->GetGUID()); //if event are in progress
}
}
};
CreatureAI* GetAI(Creature* creature) const override
{
return GetZulFarrakAI<npc_weegli_blastfuseAI>(creature);
}
};
enum ShadowPriestSezzizEnum
{
SPELL_SHADOW_BOLT = 15537,
SPELL_PSYCHIC_SCREEM = 13704,
SPELL_RENEW = 8362,
SPELL_HEAL = 12039
};
std::array<std::vector<std::pair<uint32, Position>>, 4> shadowpriestSezzizAdds =
{ {
{ { NPC_SANDFURY_ZEALOT, { 1874.12f, 1198.90f, 8.87f } }, { NPC_SANDFURY_ACOLYTE, { 1874.12f, 1198.90f, 8.87f } } },
{ { NPC_SANDFURY_ACOLYTE, { 895.26f, 1199.09f, 8.87f } }, { NPC_SANDFURY_ACOLYTE, { 895.26f, 1199.088f, 8.87f } } },
{ { NPC_SANDFURY_ZEALOT, { 1874.12f, 1198.90f, 8.87f } }, { NPC_SANDFURY_ACOLYTE, { 895.26f, 1199.09f, 8.87f } }, { NPC_SANDFURY_ACOLYTE, { 895.26f, 1199.09f, 8.87f } } },
{ { NPC_SANDFURY_ZEALOT, { 895.26f, 1199.09f, 8.87f } }, { NPC_SANDFURY_ZEALOT, { 1874.12f, 1198.90f, 8.87f } }, { NPC_SANDFURY_ACOLYTE, { 1874.12f, 1198.90f } }, { NPC_SANDFURY_ACOLYTE, { 895.26f, 1199.09f, 8.87f } } }
} };
class npc_shadowpriest_sezziz : public CreatureScript
{
public:
npc_shadowpriest_sezziz() : CreatureScript("npc_shadowpriest_sezziz") {}
struct npc_shadowpriest_sezzizAI : public ScriptedAI
{
npc_shadowpriest_sezzizAI(Creature* creature) : ScriptedAI(creature) { }
void Reset() override
{
_shadowBoltTimer = urand(0, 1 * IN_MILLISECONDS);
_physicScreemTimer = urand(1 * IN_MILLISECONDS, 16 * IN_MILLISECONDS);
_missingHPForRenewTimer = urand(10 * IN_MILLISECONDS, 15 * IN_MILLISECONDS);
_missingHPForHealTimer = urand(7 * IN_MILLISECONDS, 10 * IN_MILLISECONDS);
_summonAddsTimer = 12 * IN_MILLISECONDS;
_summmonAddsCount = 0;
}
void AttackStart(Unit* victim) override
{
ScriptedAI::AttackStartCaster(victim, 40.f);
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
{
return;
}
if (me->HasUnitState(UNIT_STATE_CASTING))
{
return;
}
if (_summonAddsTimer <= diff)
{
for (auto itr : shadowpriestSezzizAdds[_summmonAddsCount])
{
if (Creature* add = me->SummonCreature(itr.first, itr.second, TEMPSUMMON_DEAD_DESPAWN, 10 * IN_MILLISECONDS))
{
add->AI()->AttackStart(me->GetVictim());
}
}
if (++_summmonAddsCount >= 4)
{
_summmonAddsCount = 0;
}
_summonAddsTimer = urand(10 * IN_MILLISECONDS, 14 * IN_MILLISECONDS);
}
else
{
_summonAddsTimer -= diff;
}
if (_missingHPForHealTimer <= diff)
{
Unit* unit = nullptr;
Acore::MostHPMissingInRange u_check(me, 40.f, 1500);
Acore::UnitLastSearcher<Acore::MostHPMissingInRange> searcher(me, unit, u_check);
Cell::VisitGridObjects(me, searcher, 40.f);
if (unit)
{
DoCast(unit, SPELL_HEAL);
}
_missingHPForHealTimer = urand(7 * IN_MILLISECONDS, 10 * IN_MILLISECONDS);
}
else
{
_missingHPForHealTimer -= diff;
}
if (_missingHPForRenewTimer <= diff)
{
Unit* unit = nullptr;
Acore::MostHPMissingInRange u_check(me, 40.f, 700);
Acore::UnitLastSearcher<Acore::MostHPMissingInRange> searcher(me, unit, u_check);
Cell::VisitGridObjects(me, searcher, 40.f);
if (unit)
{
DoCast(unit, SPELL_RENEW);
}
_missingHPForRenewTimer = urand(10 * IN_MILLISECONDS, 15 * IN_MILLISECONDS);
}
else
{
_missingHPForRenewTimer -= diff;
}
if (_physicScreemTimer <= diff)
{
DoCastVictim(SPELL_PSYCHIC_SCREEM);
_physicScreemTimer = urand(22 * IN_MILLISECONDS, 30 * IN_MILLISECONDS);
}
else
{
_physicScreemTimer -= diff;
}
if (_shadowBoltTimer <= diff)
{
DoCastVictim(SPELL_SHADOW_BOLT);
_shadowBoltTimer = urand(3 * IN_MILLISECONDS, 4 * IN_MILLISECONDS);
}
else
{
_shadowBoltTimer -= diff;
}
}
private:
uint32 _shadowBoltTimer;
uint32 _physicScreemTimer;
uint32 _missingHPForRenewTimer;
uint32 _missingHPForHealTimer;
uint32 _summonAddsTimer;
uint8 _summmonAddsCount;
};
CreatureAI* GetAI(Creature* creature) const override
{
return GetZulFarrakAI<npc_shadowpriest_sezzizAI>(creature);
}
};
void AddSC_zulfarrak()
{
new npc_sergeant_bly();
new npc_weegli_blastfuse();
new npc_shadowpriest_sezziz();
new go_troll_cage();
}

View File

@@ -5,15 +5,61 @@
#ifndef DEF_ZULFARRACK_H
#define DEF_ZULFARRACK_H
#include "CreatureAIImpl.h"
#include "CellImpl.h"
#include "SpellScript.h"
enum ZulFarrakData
{
TYPE_PYRAMID_EVENT = 0,
TYPE_GAHZRILLA = 1,
#define ZFScriptName "instance_zulfarrak"
enum ZulFarrakCreatures
{
NPC_SANDFURY_CRETIN = 7789,
NPC_SANDFURY_SLAVE = 7787,
NPC_SANDFURY_ACOLYTE = 8876,
NPC_SANDFURY_DRUDGE = 7788,
NPC_SANDFURY_ZEALOT = 8877,
NPC_SHADOWPRIEST_SEZZZIZ = 7275,
NPC_NEKRUM_GUTCHEWER = 7796,
NPC_BLY = 7604,
NPC_RAVEN = 7605,
NPC_ORO = 7606,
NPC_WEEGLI = 7607,
NPC_MURTA = 7608
};
enum ZulFarrakGameobjects
{
GO_END_DOOR = 146084
};
enum ZulFarrakData
{
DATA_PYRAMID = 0,
DATA_GAHZRILLA = 1
};
enum ZFPyramidPhases
{
PYRAMID_NOT_STARTED, //default
PYRAMID_CAGES_OPEN, //happens in GO hello for cages
PYRAMID_ARRIVED_AT_STAIR, //happens in Weegli's movementinform
PYRAMID_WAVE_1,
PYRAMID_PRE_WAVE_2,
PYRAMID_WAVE_2,
PYRAMID_PRE_WAVE_3,
PYRAMID_WAVE_3,
PYRAMID_KILLED_ALL_TROLLS,
PYRAMID_MOVED_DOWNSTAIRS,
PYRAMID_DESTROY_GATES,
PYRAMID_GATES_DESTROYED,
PYRAMID_DONE
};
template <class AI, class T>
inline AI* GetZulFarrakAI(T* obj)
{
return GetInstanceAI<AI>(obj, ZFScriptName);
}
#endif

View File

@@ -57,6 +57,7 @@ void AddSC_boss_ouro();
void AddSC_npc_anubisath_sentinel();
void AddSC_instance_temple_of_ahnqiraj();
void AddSC_instance_wailing_caverns(); //Wailing caverns
void AddSC_zulfarrak();
void AddSC_instance_zulfarrak(); //Zul'Farrak instance script
void AddSC_ashenvale();
void AddSC_azshara();
@@ -137,6 +138,7 @@ void AddKalimdorScripts()
AddSC_npc_anubisath_sentinel();
AddSC_instance_temple_of_ahnqiraj();
AddSC_instance_wailing_caverns(); //Wailing caverns
AddSC_zulfarrak();
AddSC_instance_zulfarrak(); //Zul'Farrak instance script
AddSC_ashenvale();
AddSC_azshara();