fix(Scripts/ZulAman): Fix Sacrifice timers not updating after latest … (#20490)

This commit is contained in:
Andrew
2024-11-10 08:41:26 -03:00
committed by GitHub
parent d73ebe2e38
commit 8904a13304
3 changed files with 429 additions and 806 deletions

View File

@@ -15,13 +15,6 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* ScriptData
SDName: instance_zulaman
SD%Complete: 80
SDComment:
SDCategory: Zul'Aman
EndScriptData */
#include "InstanceMapScript.h"
#include "InstanceScript.h"
#include "Player.h"
@@ -41,34 +34,40 @@ enum Misc
struct SHostageInfo
{
uint32 npc, go; // FIXME go Not used
float x, y, z, o;
Position pos;
};
static SHostageInfo HostageInfo[] =
{
{23790, 186648, -57, 1343, 40.77f, 3.2f}, // bear
{23999, 187021, 400, 1414, 74.36f, 3.3f}, // eagle
{24001, 186672, -35, 1134, 18.71f, 1.9f}, // dragonhawk
{24024, 186667, 413, 1117, 6.32f, 3.1f} // lynx
{23790, 186648, { -57.0f, 1343.0f, 40.77f, 3.2f } }, // bear
{23999, 187021, { 400.0f, 1414.0f, 74.36f, 3.3f } }, // eagle
{24001, 186672, { -35.0f, 1134.0f, 18.71f, 1.9f } }, // dragonhawk
{24024, 186667, { 413.0f, 1117.0f, 6.32f, 3.1f } } // lynx
};
Position const HarrisonJonesLoc = {120.687f, 1674.0f, 42.0217f, 1.59044f};
DoorData const doorData[] =
{
{ GO_ZULJIN_FIREWALL, DATA_ZULJIN, DOOR_TYPE_ROOM },
{ 0, 0, DOOR_TYPE_ROOM } // END
{ GO_ZULJIN_FIREWALL, DATA_ZULJIN, DOOR_TYPE_ROOM },
{ GO_DOOR_HALAZZI, DATA_HALAZZI, DOOR_TYPE_ROOM },
{ GO_DOOR_AKILZON, DATA_AKILZON, DOOR_TYPE_ROOM },
{ GO_GATE_ZULJIN, DATA_HEXLORD, DOOR_TYPE_PASSAGE },
{ 0, 0, DOOR_TYPE_ROOM } // END
};
ObjectData const creatureData[] =
{
{ NPC_SPIRIT_LYNX, DATA_SPIRIT_LYNX },
{ 0, 0 }
{ NPC_SPIRIT_LYNX, DATA_SPIRIT_LYNX },
{ 0, 0 }
};
ObjectData const gameObjectData[] =
{
{ 0, 0 }
{ GO_STRANGE_GONG, DATA_STRANGE_GONG },
{ GO_MASSIVE_GATE, DATA_MASSIVE_GATE },
{ GO_GATE_HEXLORD, DATA_HEXLORD_GATE },
{ 0, 0 }
};
BossBoundaryData const boundaries =
@@ -79,304 +78,163 @@ BossBoundaryData const boundaries =
class instance_zulaman : public InstanceMapScript
{
public:
instance_zulaman()
: InstanceMapScript("instance_zulaman", 568)
{
}
instance_zulaman() : InstanceMapScript("instance_zulaman", 568) { }
struct instance_zulaman_InstanceMapScript : public InstanceScript
{
instance_zulaman_InstanceMapScript(Map* map) : InstanceScript(map) {}
ObjectGuid HarkorsSatchelGUID;
ObjectGuid TanzarsTrunkGUID;
ObjectGuid AshlisBagGUID;
ObjectGuid KrazsPackageGUID;
ObjectGuid StrangeGongGUID;
ObjectGuid HexLordGateGUID;
ObjectGuid ZulJinGateGUID;
ObjectGuid MassiveGateGUID;
ObjectGuid AkilzonDoorGUID;
ObjectGuid HalazziDoorGUID;
uint32 QuestTimer;
uint16 BossKilled;
uint16 QuestMinute;
uint16 ChestLooted;
uint32 m_auiEncounter[MAX_ENCOUNTER];
uint32 RandVendor[RAND_VENDOR];
void Initialize() override
{
SetHeaders(DataHeader);
LoadObjectData(creatureData, gameObjectData);
memset(&m_auiEncounter, 0, sizeof(m_auiEncounter));
SetBossNumber(MAX_ENCOUNTER);
SetPersistentDataCount(PersistentDataCount);
LoadObjectData(creatureData, gameObjectData);
LoadBossBoundaries(boundaries);
LoadDoorData(doorData);
QuestTimer = 0;
QuestMinute = 0;
BossKilled = 0;
ChestLooted = 0;
for (uint8 i = 0; i < RAND_VENDOR; ++i)
RandVendor[i] = NOT_STARTED;
}
m_auiEncounter[DATA_GONGEVENT] = NOT_STARTED;
void OnPlayerEnter(Player* /*player*/) override
{
if (!scheduler.IsGroupScheduled(GROUP_TIMED_RUN))
DoAction(ACTION_START_TIMED_RUN);
}
void OnGameObjectCreate(GameObject* go) override
{
switch (go->GetEntry())
{
case GO_DOOR_HALAZZI:
HalazziDoorGUID = go->GetGUID();
break;
case GO_GATE_ZULJIN:
ZulJinGateGUID = go->GetGUID();
break;
case GO_GATE_HEXLORD:
HexLordGateGUID = go->GetGUID();
break;
case GO_MASSIVE_GATE:
MassiveGateGUID = go->GetGUID();
break;
case GO_DOOR_AKILZON:
AkilzonDoorGUID = go->GetGUID();
break;
case GO_HARKORS_SATCHEL:
HarkorsSatchelGUID = go->GetGUID();
break;
case GO_TANZARS_TRUNK:
TanzarsTrunkGUID = go->GetGUID();
break;
case GO_ASHLIS_BAG:
AshlisBagGUID = go->GetGUID();
break;
case GO_KRAZS_PACKAGE:
KrazsPackageGUID = go->GetGUID();
break;
case GO_STRANGE_GONG:
StrangeGongGUID = go->GetGUID();
break;
default:
break;
}
CheckInstanceStatus();
if (go->GetEntry() == GO_GATE_HEXLORD)
CheckInstanceStatus();
InstanceScript::OnGameObjectCreate(go);
}
void SummonHostage(uint8 num)
{
if (!QuestMinute)
if (!GetPersistentData(DATA_TIMED_RUN))
return;
Map::PlayerList const& PlayerList = instance->GetPlayers();
if (PlayerList.IsEmpty())
return;
instance->SummonCreature(HostageInfo[num].npc, HostageInfo[num].pos);
}
Map::PlayerList::const_iterator i = PlayerList.begin();
if (Player* i_pl = i->GetSource())
void DoAction(int32 actionId) override
{
if (actionId == ACTION_START_TIMED_RUN)
{
if (Unit* Hostage = i_pl->SummonCreature(HostageInfo[num].npc, HostageInfo[num].x, HostageInfo[num].y, HostageInfo[num].z, HostageInfo[num].o, TEMPSUMMON_DEAD_DESPAWN, 0))
if (uint32 timer = GetPersistentData(DATA_TIMED_RUN))
{
Hostage->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
Hostage->SetNpcFlag(UNIT_NPC_FLAG_GOSSIP);
DoUpdateWorldState(WORLDSTATE_SHOW_TIMER, 1);
DoUpdateWorldState(WORLDSTATE_TIME_TO_SACRIFICE, timer);
}
scheduler.Schedule(1min, GROUP_TIMED_RUN, [this](TaskContext context)
{
if (uint32 timer = GetPersistentData(DATA_TIMED_RUN))
{
--timer;
DoUpdateWorldState(WORLDSTATE_SHOW_TIMER, 1);
DoUpdateWorldState(WORLDSTATE_TIME_TO_SACRIFICE, timer);
StorePersistentData(DATA_TIMED_RUN, timer);
context.Repeat();
}
else
DoUpdateWorldState(WORLDSTATE_SHOW_TIMER, 0);
});
}
}
void CheckInstanceStatus()
{
if (BossKilled >= DATA_HALAZZI)
HandleGameObject(HexLordGateGUID, true);
if (BossKilled >= DATA_HEXLORD)
HandleGameObject(ZulJinGateGUID, true);
}
std::string GetSaveData() override
{
OUT_SAVE_INST_DATA;
std::ostringstream ss;
ss << "S " << BossKilled << ' ' << ChestLooted << ' ' << QuestMinute;
OUT_SAVE_INST_DATA_COMPLETE;
return ss.str();
}
void Load(const char* load) override
{
if (!load)
return;
std::istringstream ss(load);
char dataHead; // S
uint16 data1, data2, data3;
ss >> dataHead >> data1 >> data2 >> data3;
if (dataHead == 'S')
{
BossKilled = data1;
ChestLooted = data2;
QuestMinute = data3;
}
else
{
LOG_ERROR("misc", "Zul'aman: corrupted save data.");
}
if (AllBossesDone({ DATA_NALORAKK, DATA_AKILZON, DATA_JANALAI, DATA_HALAZZI }))
HandleGameObject(ObjectGuid::Empty, true, GetGameObject(DATA_HEXLORD_GATE));
}
void SetData(uint32 type, uint32 data) override
{
if (type == TYPE_RAND_VENDOR_1)
RandVendor[0] = data;
else if (type == TYPE_RAND_VENDOR_2)
RandVendor[1] = data;
}
bool SetBossState(uint32 type, EncounterState state) override
{
if (!InstanceScript::SetBossState(type, state))
return false;
switch (type)
{
case DATA_GONGEVENT:
m_auiEncounter[DATA_GONGEVENT] = data;
if (data == IN_PROGRESS)
SaveToDB();
else if (data == DONE)
QuestMinute = 21;
break;
case DATA_NALORAKK:
m_auiEncounter[DATA_NALORAKK] = data;
if (data == DONE)
if (state == DONE)
{
if (QuestMinute)
if (uint32 timer = GetPersistentData(DATA_TIMED_RUN))
{
QuestMinute += 15;
DoUpdateWorldState(WORLDSTATE_TIME_TO_SACRIFICE, QuestMinute);
StorePersistentData(DATA_TIMED_RUN, timer += 15);
DoUpdateWorldState(WORLDSTATE_TIME_TO_SACRIFICE, timer);
}
SummonHostage(0);
SaveToDB();
}
break;
case DATA_AKILZON:
m_auiEncounter[DATA_AKILZON] = data;
HandleGameObject(AkilzonDoorGUID, data != IN_PROGRESS);
if (data == DONE)
if (state == DONE)
{
if (QuestMinute)
if (uint32 timer = GetPersistentData(DATA_TIMED_RUN))
{
QuestMinute += 10;
DoUpdateWorldState(WORLDSTATE_TIME_TO_SACRIFICE, QuestMinute);
StorePersistentData(DATA_TIMED_RUN, timer += 10);
DoUpdateWorldState(WORLDSTATE_TIME_TO_SACRIFICE, timer);
}
SummonHostage(1);
SaveToDB();
}
break;
case DATA_JANALAI:
m_auiEncounter[DATA_JANALAI] = data;
if (data == DONE)
if (state == DONE)
SummonHostage(2);
SaveToDB();
break;
case DATA_HALAZZI:
m_auiEncounter[DATA_HALAZZI] = data;
HandleGameObject(HalazziDoorGUID, data != IN_PROGRESS);
if (data == DONE) SummonHostage(3);
SaveToDB();
if (state == DONE)
SummonHostage(3);
break;
case DATA_HEXLORD:
m_auiEncounter[DATA_HEXLORD] = data;
if (data == IN_PROGRESS)
HandleGameObject(HexLordGateGUID, false);
else if (data == NOT_STARTED)
if (state == IN_PROGRESS)
HandleGameObject(ObjectGuid::Empty, false, GetGameObject(DATA_HEXLORD_GATE));
else if (state == NOT_STARTED)
CheckInstanceStatus();
SaveToDB();
break;
case DATA_CHESTLOOTED:
++ChestLooted;
SaveToDB();
break;
case TYPE_RAND_VENDOR_1:
RandVendor[0] = data;
break;
case TYPE_RAND_VENDOR_2:
RandVendor[1] = data;
break;
}
if (data == DONE)
if (state == DONE)
{
++BossKilled;
if (QuestMinute && BossKilled >= DATA_HALAZZI)
if (GetPersistentData(DATA_TIMED_RUN) && AllBossesDone({ DATA_NALORAKK, DATA_AKILZON, DATA_JANALAI, DATA_HALAZZI }))
{
QuestMinute = 0;
StorePersistentData(DATA_TIMED_RUN, 0);
DoUpdateWorldState(WORLDSTATE_SHOW_TIMER, 0);
}
CheckInstanceStatus();
SaveToDB();
}
return true;
}
uint32 GetData(uint32 type) const override
{
switch (type)
{
case DATA_GONGEVENT:
return m_auiEncounter[DATA_GONGEVENT];
case DATA_NALORAKK:
return m_auiEncounter[DATA_NALORAKK];
case DATA_AKILZON:
return m_auiEncounter[DATA_AKILZON];
case DATA_JANALAI:
return m_auiEncounter[DATA_JANALAI];
case DATA_HALAZZI:
return m_auiEncounter[DATA_HALAZZI];
case DATA_HEXLORD:
return m_auiEncounter[DATA_HEXLORD];
case DATA_ZULJIN:
return m_auiEncounter[DATA_ZULJIN];
case DATA_CHESTLOOTED:
return ChestLooted;
case TYPE_RAND_VENDOR_1:
return RandVendor[0];
case TYPE_RAND_VENDOR_2:
return RandVendor[1];
default:
return 0;
}
if (type == TYPE_RAND_VENDOR_1)
return RandVendor[0];
else if (type == TYPE_RAND_VENDOR_2)
return RandVendor[1];
return 0;
}
void Update(uint32 diff) override
{
if (QuestMinute)
{
if (QuestTimer <= diff)
{
QuestMinute--;
SaveToDB();
QuestTimer += 60000;
if (QuestMinute)
{
DoUpdateWorldState(WORLDSTATE_SHOW_TIMER, 1);
DoUpdateWorldState(WORLDSTATE_TIME_TO_SACRIFICE, QuestMinute);
}
else DoUpdateWorldState(WORLDSTATE_SHOW_TIMER, 0);
}
QuestTimer -= diff;
}
scheduler.Update(diff);
}
ObjectGuid GetGuidData(uint32 type) const override
{
switch (type)
{
case GO_STRANGE_GONG:
return StrangeGongGUID;
case GO_MASSIVE_GATE:
return MassiveGateGUID;
}
return ObjectGuid::Empty;
}
private:
uint32 RandVendor[RAND_VENDOR];
};
InstanceScript* GetInstanceScript(InstanceMap* map) const override

View File

@@ -63,384 +63,177 @@ enum ForestFrog
NPC_BRENNAN = 24453,
NPC_HOLLEE = 24455,
// Says
SAY_MANNUTH_0 = 0,
SAY_MANNUTH_1 = 1,
SAY_MANNUTH_2 = 2,
SAY_MANNUTH_3 = 3,
// Adarrah is spawned elsewhere.
// So her text 0 isn't used in this instance.
SAY_THANKS_FREED = 0,
SAY_CHEST_SPAWN = 1,
SAY_CHEST_TALK = 2,
SAY_GOODBYE = 3,
SAY_DEEZ_0 = 0,
SAY_DEEZ_1 = 1,
SAY_DEEZ_2 = 2,
SAY_DEEZ_3 = 3,
SAY_GALATHRYN_0 = 0,
SAY_GALATHRYN_1 = 1,
SAY_GALATHRYN_2 = 2,
SAY_GALATHRYN_3 = 3,
SAY_ADARRAH_1 = 1,
SAY_ADARRAH_2 = 2,
SAY_ADARRAH_3 = 3,
SAY_ADARRAH_4 = 4,
SAY_DARWEN_0 = 0,
SAY_DARWEN_1 = 1,
SAY_DARWEN_2 = 2,
SAY_DARWEN_3 = 3,
SAY_FUDGERICK_0 = 0,
SAY_FUDGERICK_1 = 1,
SAY_FUDGERICK_2 = 2,
SAY_FUDGERICK_3 = 3,
SAY_GUNTER_0 = 0,
SAY_GUNTER_1 = 1,
SAY_GUNTER_2 = 2,
SAY_KYREN_0 = 0,
SAY_KYREN_1 = 1,
SAY_KYREN_2 = 2,
SAY_MITZI_0 = 0,
SAY_MITZI_1 = 1,
SAY_MITZI_2 = 2,
SAY_MITZI_3 = 3,
SAY_CHRISTIAN_0 = 0,
SAY_CHRISTIAN_1 = 1,
SAY_CHRISTIAN_2 = 2,
SAY_CHRISTIAN_3 = 3,
SAY_BRENNAN_0 = 0,
SAY_BRENNAN_1 = 1,
SAY_BRENNAN_2 = 2,
SAY_BRENNAN_3 = 3,
SAY_HOLLEE_0 = 0,
SAY_HOLLEE_1 = 1,
SAY_HOLLEE_2 = 2,
SAY_HOLLEE_3 = 3,
POINT_DESPAWN = 1
POINT_DESPAWN = 1,
};
class npc_forest_frog : public CreatureScript
struct npc_forest_frog : public ScriptedAI
{
public:
npc_forest_frog() : CreatureScript("npc_forest_frog") { }
struct npc_forest_frogAI : public ScriptedAI
npc_forest_frog(Creature* creature) : ScriptedAI(creature)
{
npc_forest_frogAI(Creature* creature) : ScriptedAI(creature)
instance = creature->GetInstanceScript();
}
void JustEngagedWith(Unit* /*who*/) override { }
void MovementInform(uint32 type, uint32 data) override
{
if (type == POINT_MOTION_TYPE && data == POINT_DESPAWN)
me->DespawnOrUnsummon(1000);
}
void UpdateAI(uint32 diff) override
{
events.Update(diff);
if (eventTimer)
{
instance = creature->GetInstanceScript();
Player* player = ObjectAccessor::GetPlayer(me->GetMap(), PlayerGUID);
switch (events.ExecuteEvent())
{
case 1:
if (me->GetEntry() == NPC_ADARRAH)
Talk(SAY_THANKS_FREED + 1, player);
else
Talk(SAY_THANKS_FREED, player);
eventTimer = 2;
events.ScheduleEvent(eventTimer, urand(4000, 5000));
break;
case 2:
if (me->GetEntry() != NPC_GUNTER && me->GetEntry() != NPC_KYREN) // vendors don't kneel?
me->SetStandState(UNIT_STAND_STATE_KNEEL);
switch (me->GetEntry())
{
case NPC_MANNUTH:
case NPC_DEEZ:
case NPC_GALATHRYN:
DoCastSelf(SPELL_SUMMON_AMANI_CHARM_CHEST_2, true);
Talk(SAY_CHEST_SPAWN, player);
break;
case NPC_ADARRAH:
DoCastSelf(SPELL_SUMMON_AMANI_CHARM_CHEST_2, true);
Talk(SAY_CHEST_SPAWN + 1, player);
break;
case NPC_DARWEN:
case NPC_FUDGERICK:
DoCastSelf(SPELL_SUMMON_MONEY_BAG, true);
me->LoadEquipment(0, true);
Talk(SAY_CHEST_SPAWN, player);
break;
case NPC_KYREN:
case NPC_GUNTER:
Talk(SAY_CHEST_SPAWN, player);
break;
case NPC_MITZI:
case NPC_CHRISTIAN:
case NPC_BRENNAN:
case NPC_HOLLEE:
DoCastSelf(SPELL_SUMMON_AMANI_CHARM_CHEST_1, true);
Talk(SAY_CHEST_SPAWN, player);
break;
}
eventTimer = 3;
events.ScheduleEvent(eventTimer, urand(6000, 7000));
break;
case 3:
me->SetStandState(EMOTE_ONESHOT_NONE);
if (me->GetEntry() == NPC_ADARRAH)
Talk(SAY_CHEST_TALK + 1, player);
else
Talk(SAY_CHEST_TALK);
eventTimer = 4;
if (me->GetEntry() == NPC_GUNTER || me->GetEntry() == NPC_KYREN)
events.ScheduleEvent(eventTimer, 5 * MINUTE * IN_MILLISECONDS); // vendors wait for 5 minutes before running away and despawning
else
events.ScheduleEvent(eventTimer, 6000);
break;
case 4:
me->HandleEmoteCommand(EMOTE_ONESHOT_WAVE);
if (me->GetEntry() == NPC_ADARRAH)
Talk(SAY_GOODBYE + 1, player);
else
Talk(SAY_GOODBYE);
eventTimer = 5;
events.ScheduleEvent(eventTimer, 2000);
break;
case 5:
if (me->GetEntry() == NPC_ADARRAH)
DoCastSelf(SPELL_STEALTH_, true);
if (me->GetPositionY() > 1290.0f)
me->GetMotionMaster()->MovePoint(POINT_DESPAWN, 118.2742f, 1400.657f, -9.118711f);
else
me->GetMotionMaster()->MovePoint(POINT_DESPAWN, 114.3155f, 1244.244f, -20.97606f);
eventTimer = 0;
break;
}
}
}
void DoSpawnRandom()
{
auto const& entries =
{
NPC_MANNUTH, NPC_DEEZ, NPC_GALATHRYN, NPC_ADARRAH, NPC_FUDGERICK, NPC_DARWEN, NPC_MITZI,
NPC_CHRISTIAN, NPC_BRENNAN, NPC_HOLLEE
};
uint32 cEntry = Acore::Containers::SelectRandomContainerElement(entries);
if (!instance->GetData(TYPE_RAND_VENDOR_1) && roll_chance_i(10))
{
cEntry = NPC_GUNTER;
instance->SetData(TYPE_RAND_VENDOR_1, DONE);
}
else if (!instance->GetData(TYPE_RAND_VENDOR_2) && roll_chance_i(10))
{
cEntry = NPC_KYREN;
instance->SetData(TYPE_RAND_VENDOR_2, DONE);
}
// start generic rp
eventTimer = 1;
events.ScheduleEvent(eventTimer, 3000);
me->UpdateEntry(cEntry);
}
void SpellHit(Unit* caster, SpellInfo const* spell) override
{
if (spell->Id == SPELL_REMOVE_AMANI_CURSE && caster->IsPlayer() && me->GetEntry() == NPC_FOREST_FROG)
{
me->GetMotionMaster()->MoveIdle();
me->SetFacingToObject(caster);
PlayerGUID = caster->GetGUID();
if (roll_chance_i(2))
{
DoCast(caster, SPELL_PUSH_MOJO, true);
me->GetMotionMaster()->MovePoint(POINT_DESPAWN, caster->GetPosition());
}
else
DoSpawnRandom();
}
}
private:
InstanceScript* instance;
EventMap events;
uint8 eventTimer;
ObjectGuid PlayerGUID;
void Reset() override { }
void JustEngagedWith(Unit* /*who*/) override { }
void MovementInform(uint32 type, uint32 data) override
{
if (type == POINT_MOTION_TYPE && data == POINT_DESPAWN)
me->DespawnOrUnsummon(1000);
}
void UpdateAI(uint32 diff) override
{
events.Update(diff);
if (eventTimer)
{
Player* player = ObjectAccessor::GetPlayer(me->GetMap(), PlayerGUID);
switch (events.ExecuteEvent())
{
case 1:
switch (me->GetEntry())
{
case NPC_MANNUTH:
Talk(SAY_MANNUTH_0, player);
break;
case NPC_DEEZ:
Talk(SAY_DEEZ_0, player);
break;
case NPC_GALATHRYN:
Talk(SAY_GALATHRYN_0, player);
break;
case NPC_ADARRAH:
Talk(SAY_ADARRAH_1, player);
break;
case NPC_DARWEN:
Talk(SAY_DARWEN_0, player);
break;
case NPC_FUDGERICK:
Talk(SAY_FUDGERICK_0, player);
break;
case NPC_GUNTER:
Talk(SAY_GUNTER_0, player);
break;
case NPC_KYREN:
Talk(SAY_KYREN_0, player);
break;
case NPC_MITZI:
Talk(SAY_MITZI_0, player);
break;
case NPC_CHRISTIAN:
Talk(SAY_CHRISTIAN_0, player);
break;
case NPC_BRENNAN:
Talk(SAY_BRENNAN_0, player);
break;
case NPC_HOLLEE:
Talk(SAY_HOLLEE_0, player);
break;
}
eventTimer = 2;
events.ScheduleEvent(eventTimer, urand(4000, 5000));
break;
case 2:
if (me->GetEntry() != NPC_GUNTER && me->GetEntry() != NPC_KYREN) // vendors don't kneel?
me->SetStandState(UNIT_STAND_STATE_KNEEL);
switch (me->GetEntry())
{
case NPC_MANNUTH:
DoCast(me, SPELL_SUMMON_AMANI_CHARM_CHEST_2, true);
Talk(SAY_MANNUTH_1, player);
break;
case NPC_DEEZ:
DoCast(me, SPELL_SUMMON_AMANI_CHARM_CHEST_2, true);
Talk(SAY_DEEZ_1, player);
break;
case NPC_GALATHRYN:
DoCast(me, SPELL_SUMMON_AMANI_CHARM_CHEST_2, true);
Talk(SAY_GALATHRYN_1, player);
break;
case NPC_ADARRAH:
DoCast(me, SPELL_SUMMON_AMANI_CHARM_CHEST_2, true);
Talk(SAY_ADARRAH_2, player);
break;
case NPC_DARWEN:
DoCast(me, SPELL_SUMMON_MONEY_BAG, true);
me->LoadEquipment(0, true);
Talk(SAY_DARWEN_1, player);
break;
case NPC_FUDGERICK:
DoCast(me, SPELL_SUMMON_MONEY_BAG, true);
me->LoadEquipment(0, true);
Talk(SAY_FUDGERICK_1, player);
break;
case NPC_GUNTER:
Talk(SAY_GUNTER_1, player);
break;
case NPC_KYREN:
Talk(SAY_KYREN_1, player);
break;
case NPC_MITZI:
DoCast(me, SPELL_SUMMON_AMANI_CHARM_CHEST_1, true);
Talk(SAY_MITZI_1, player);
break;
case NPC_CHRISTIAN:
DoCast(me, SPELL_SUMMON_AMANI_CHARM_CHEST_1, true);
Talk(SAY_CHRISTIAN_1, player);
break;
case NPC_BRENNAN:
DoCast(me, SPELL_SUMMON_AMANI_CHARM_CHEST_1, true);
Talk(SAY_BRENNAN_1, player);
break;
case NPC_HOLLEE:
DoCast(me, SPELL_SUMMON_AMANI_CHARM_CHEST_1, true);
Talk(SAY_HOLLEE_1, player);
break;
}
eventTimer = 3;
events.ScheduleEvent(eventTimer, urand(6000, 7000));
break;
case 3:
me->SetStandState(EMOTE_ONESHOT_NONE);
switch (me->GetEntry())
{
case NPC_MANNUTH:
Talk(SAY_MANNUTH_2, player);
break;
case NPC_DEEZ:
Talk(SAY_DEEZ_2, player);
break;
case NPC_GALATHRYN:
Talk(SAY_GALATHRYN_2, player);
break;
case NPC_ADARRAH:
Talk(SAY_ADARRAH_3, player);
break;
case NPC_DARWEN:
Talk(SAY_DARWEN_2, player);
break;
case NPC_FUDGERICK:
Talk(SAY_FUDGERICK_2, player);
break;
case NPC_GUNTER:
Talk(SAY_GUNTER_2, player);
break;
case NPC_KYREN:
Talk(SAY_KYREN_2, player);
break;
case NPC_MITZI:
Talk(SAY_MITZI_2, player);
break;
case NPC_CHRISTIAN:
Talk(SAY_CHRISTIAN_2, player);
break;
case NPC_BRENNAN:
Talk(SAY_BRENNAN_2, player);
break;
case NPC_HOLLEE:
Talk(SAY_HOLLEE_2, player);
break;
}
eventTimer = 4;
if (me->GetEntry() == NPC_GUNTER || me->GetEntry() == NPC_KYREN)
events.ScheduleEvent(eventTimer, 5 * MINUTE * IN_MILLISECONDS); // vendors wait for 5 minutes before running away and despawning
else
events.ScheduleEvent(eventTimer, 6000);
break;
case 4:
me->HandleEmoteCommand(EMOTE_ONESHOT_WAVE);
switch (me->GetEntry())
{
case NPC_MANNUTH:
Talk(SAY_MANNUTH_3, player);
break;
case NPC_DEEZ:
Talk(SAY_DEEZ_3, player);
break;
case NPC_GALATHRYN:
Talk(SAY_GALATHRYN_3, player);
break;
case NPC_ADARRAH:
Talk(SAY_ADARRAH_4, player);
break;
case NPC_DARWEN:
Talk(SAY_DARWEN_3, player);
break;
case NPC_FUDGERICK:
Talk(SAY_FUDGERICK_3, player);
break;
case NPC_MITZI:
Talk(SAY_MITZI_3, player);
break;
case NPC_CHRISTIAN:
Talk(SAY_CHRISTIAN_3, player);
break;
case NPC_BRENNAN:
Talk(SAY_BRENNAN_3, player);
break;
case NPC_HOLLEE:
Talk(SAY_HOLLEE_3, player);
break;
}
eventTimer = 5;
events.ScheduleEvent(eventTimer, 2000);
break;
case 5:
switch (me->GetEntry())
{
case NPC_ADARRAH:
DoCast(me, SPELL_STEALTH_, true);
break;
}
if (me->GetPositionY() > 1290.0f)
me->GetMotionMaster()->MovePoint(POINT_DESPAWN, 118.2742f, 1400.657f, -9.118711f);
else
me->GetMotionMaster()->MovePoint(POINT_DESPAWN, 114.3155f, 1244.244f, -20.97606f);
eventTimer = 0;
break;
}
}
}
void DoSpawnRandom()
{
if (instance)
{
uint32 cEntry = NPC_MANNUTH;
switch (urand(0, 9))
{
case 1:
cEntry = NPC_DEEZ;
break;
case 2:
cEntry = NPC_GALATHRYN;
break;
case 3:
cEntry = NPC_ADARRAH;
break;
case 4:
cEntry = NPC_FUDGERICK;
break;
case 5:
cEntry = NPC_DARWEN;
break;
case 6:
cEntry = NPC_MITZI;
break;
case 7:
cEntry = NPC_CHRISTIAN;
break;
case 8:
cEntry = NPC_BRENNAN;
break;
case 9:
cEntry = NPC_HOLLEE;
break;
}
if (!instance->GetData(TYPE_RAND_VENDOR_1) && roll_chance_i(10))
{
cEntry = NPC_GUNTER;
instance->SetData(TYPE_RAND_VENDOR_1, DONE);
}
else if (!instance->GetData(TYPE_RAND_VENDOR_2) && roll_chance_i(10))
{
cEntry = NPC_KYREN;
instance->SetData(TYPE_RAND_VENDOR_2, DONE);
}
// start generic rp
eventTimer = 1;
events.ScheduleEvent(eventTimer, 3000);
me->UpdateEntry(cEntry);
}
}
void SpellHit(Unit* caster, SpellInfo const* spell) override
{
if (spell->Id == SPELL_REMOVE_AMANI_CURSE && caster->IsPlayer() && me->GetEntry() == NPC_FOREST_FROG)
{
me->GetMotionMaster()->MoveIdle();
me->SetFacingToObject(caster);
PlayerGUID = caster->GetGUID();
if (roll_chance_i(2))
{
DoCast(caster, SPELL_PUSH_MOJO, true);
me->GetMotionMaster()->MovePoint(POINT_DESPAWN, caster->GetPositionX(), caster->GetPositionY(), caster->GetPositionZ());
}
else
DoSpawnRandom();
}
}
};
CreatureAI* GetAI(Creature* creature) const override
{
return GetZulAmanAI<npc_forest_frogAI>(creature);
}
};
/*######
@@ -467,8 +260,6 @@ public:
bool IsLoot;
ObjectGuid PlayerGUID;
void Reset() override { }
void JustEngagedWith(Unit* /*who*/) override { }
void JustDied(Unit* /*killer*/) override
@@ -508,21 +299,14 @@ public:
creature->RemoveNpcFlag(UNIT_NPC_FLAG_GOSSIP);
InstanceScript* instance = creature->GetInstanceScript();
if (instance)
float x, y, z;
creature->GetPosition(x, y, z);
for (uint8 i = 0; i < 4; ++i)
{
//uint8 progress = instance->GetData(DATA_CHESTLOOTED);
instance->SetData(DATA_CHESTLOOTED, 0);
float x, y, z;
creature->GetPosition(x, y, z);
uint32 entry = creature->GetEntry();
for (uint8 i = 0; i < 4; ++i)
if (HostageEntry[i] == creature->GetEntry())
{
if (HostageEntry[i] == entry)
{
creature->SummonGameObject(ChestEntry[i], x - 2, y, z, 0, 0, 0, 0, 0, 0);
break;
}
creature->SummonGameObject(ChestEntry[i], x - 2, y, z, 0, 0, 0, 0, 0, 0);
break;
}
}
@@ -591,201 +375,172 @@ enum Weapons
WEAPON_SPEAR = 13631
};
class npc_harrison_jones : public CreatureScript
struct npc_harrison_jones : public ScriptedAI
{
public:
npc_harrison_jones() : CreatureScript("npc_harrison_jones")
npc_harrison_jones(Creature* creature) : ScriptedAI(creature)
{
_instance = creature->GetInstanceScript();
}
struct npc_harrison_jonesAI : public ScriptedAI
void Reset() override
{
npc_harrison_jonesAI(Creature* creature) : ScriptedAI(creature)
_gongEvent = 0;
_gongTimer = 0;
uiTargetGUID.Clear();
}
void JustEngagedWith(Unit* /*who*/) override { }
void sGossipSelect(Player* player, uint32 sender, uint32 action) override
{
if (me->GetCreatureTemplate()->GossipMenuId == sender && !action)
{
instance = creature->GetInstanceScript();
CloseGossipMenuFor(player);
me->SetFacingToObject(player);
me->RemoveNpcFlag(UNIT_NPC_FLAG_GOSSIP);
Talk(SAY_HARRISON_0);
_gongEvent = GONG_EVENT_1;
_gongTimer = 4000;
}
}
InstanceScript* instance;
void SpellHit(Unit*, SpellInfo const* spell) override
{
if (spell->Id == SPELL_COSMETIC_SPEAR_THROW)
{
me->RemoveAllAuras();
me->SetEntry(NPC_HARRISON_JONES_2);
me->SetDisplayId(MODEL_HARRISON_JONES_2);
me->SetTarget();
me->SetByteValue(UNIT_FIELD_BYTES_1, UNIT_BYTES_1_OFFSET_STAND_STATE, UNIT_STAND_STATE_DEAD);
me->SetDynamicFlag(UNIT_DYNFLAG_DEAD);
_instance->StorePersistentData(DATA_TIMED_RUN, 21);
_instance->DoAction(ACTION_START_TIMED_RUN);
}
}
void UpdateAI(uint32 diff) override
{
if (_gongEvent)
{
if (_gongTimer <= diff)
{
switch (_gongEvent)
{
case GONG_EVENT_1:
me->GetMotionMaster()->MovePath(HARRISON_MOVE_1, false);
_gongEvent = GONG_EVENT_2;
_gongTimer = 12000;
break;
case GONG_EVENT_2:
me->SetFacingTo(6.235659f);
Talk(SAY_HARRISON_1);
DoCastSelf(SPELL_BANGING_THE_GONG);
me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 0, uint32(WEAPON_MACE));
me->SetSheath(SHEATH_STATE_MELEE);
_gongEvent = GONG_EVENT_3;
_gongTimer = 4000;
break;
case GONG_EVENT_3:
if (GameObject* gong = _instance->GetGameObject(DATA_STRANGE_GONG))
gong->RemoveGameObjectFlag(GO_FLAG_NOT_SELECTABLE);
_gongEvent = GONG_EVENT_4;
_gongTimer = 105000;
break;
case GONG_EVENT_4:
me->RemoveAura(SPELL_BANGING_THE_GONG);
if (GameObject* gong = _instance->GetGameObject(DATA_STRANGE_GONG))
gong->SetGameObjectFlag(GO_FLAG_NOT_SELECTABLE);
// Players are Now Saved to instance at SPECIAL (Player should be notified?)
me->GetMotionMaster()->MovePath(HARRISON_MOVE_2, false);
_gongEvent = GONG_EVENT_5;
_gongTimer = 5000;
break;
case GONG_EVENT_5:
me->SetEntry(NPC_HARRISON_JONES_1);
me->SetDisplayId(MODEL_HARRISON_JONES_1);
Talk(SAY_HARRISON_2);
_gongTimer = 12000;
_gongEvent = GONG_EVENT_6;
break;
case GONG_EVENT_6:
me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_USE_STANDING);
Talk(SAY_HARRISON_3);
_gongTimer = 7000;
_gongEvent = GONG_EVENT_7;
break;
case GONG_EVENT_7:
if (!uiTargetGUID)
{
std::list<Creature*> targetList;
GetCreatureListWithEntryInGrid(targetList, me, NPC_AMANISHI_GUARDIAN, 26.0f);
if (!targetList.empty())
{
for (auto const& creature : targetList)
{
if (creature)
{
creature->SetImmuneToPC(true);
creature->SetReactState(REACT_PASSIVE);
if (creature->GetPositionX() > 120)
{
creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 0, uint32(WEAPON_SPEAR));
creature->AI()->SetData(0, 1);
}
else
creature->AI()->SetData(0, 2);
}
}
}
}
if (GameObject* gate = _instance->GetGameObject(DATA_MASSIVE_GATE))
gate->SetGoState(GO_STATE_ACTIVE);
_gongTimer = 2000;
_gongEvent = GONG_EVENT_8;
break;
case GONG_EVENT_8:
DoCastSelf(SPELL_STEALTH);
me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 0, uint32(0));
me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE);
me->GetMotionMaster()->MovePath(HARRISON_MOVE_3, false);
_gongTimer = 1000;
_gongEvent = 0;
break;
case GONG_EVENT_9:
me->GetMotionMaster()->MovePoint(0, 120.687f, 1674.0f, 42.0217f);
_gongTimer = 12000;
_gongEvent = GONG_EVENT_10;
break;
case GONG_EVENT_10:
me->SetFacingTo(1.59044f);
_gongEvent = 11;
_gongTimer = 6000;
break;
case GONG_EVENT_11:
me->SetNpcFlag(UNIT_NPC_FLAG_GOSSIP);
_gongEvent = 0;
_gongTimer = 1000;
break;
}
}
else
_gongTimer -= diff;
}
}
private:
InstanceScript* _instance;
uint8 _gongEvent;
uint32 _gongTimer;
ObjectGuid uiTargetGUID;
void Reset() override
{
_gongEvent = 0;
_gongTimer = 0;
uiTargetGUID.Clear();
}
void JustEngagedWith(Unit* /*who*/) override { }
void sGossipSelect(Player* player, uint32 sender, uint32 action) override
{
if (me->GetCreatureTemplate()->GossipMenuId == sender && !action)
{
CloseGossipMenuFor(player);
me->SetFacingToObject(player);
me->RemoveNpcFlag(UNIT_NPC_FLAG_GOSSIP);
Talk(SAY_HARRISON_0);
_gongEvent = GONG_EVENT_1;
_gongTimer = 4000;
}
}
void SpellHit(Unit*, SpellInfo const* spell) override
{
if (spell->Id == SPELL_COSMETIC_SPEAR_THROW)
{
me->RemoveAllAuras();
me->SetEntry(NPC_HARRISON_JONES_2);
me->SetDisplayId(MODEL_HARRISON_JONES_2);
me->SetTarget();
me->SetByteValue(UNIT_FIELD_BYTES_1, UNIT_BYTES_1_OFFSET_STAND_STATE, UNIT_STAND_STATE_DEAD);
me->SetDynamicFlag(UNIT_DYNFLAG_DEAD);
instance->SetData(DATA_GONGEVENT, DONE);
}
}
void UpdateAI(uint32 diff) override
{
if (_gongEvent)
{
if (_gongTimer <= diff)
{
switch (_gongEvent)
{
case GONG_EVENT_1:
me->GetMotionMaster()->MovePath(HARRISON_MOVE_1, false);
_gongEvent = GONG_EVENT_2;
_gongTimer = 12000;
break;
case GONG_EVENT_2:
me->SetFacingTo(6.235659f);
Talk(SAY_HARRISON_1);
DoCast(me, SPELL_BANGING_THE_GONG);
me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 0, uint32(WEAPON_MACE));
me->SetSheath(SHEATH_STATE_MELEE);
_gongEvent = GONG_EVENT_3;
_gongTimer = 4000;
break;
case GONG_EVENT_3:
if (GameObject* gong = me->GetMap()->GetGameObject(instance->GetGuidData(GO_STRANGE_GONG)))
gong->RemoveGameObjectFlag(GO_FLAG_NOT_SELECTABLE);
_gongEvent = GONG_EVENT_4;
_gongTimer = 105000;
break;
case GONG_EVENT_4:
me->RemoveAura(SPELL_BANGING_THE_GONG);
if (GameObject* gong = me->GetMap()->GetGameObject(instance->GetGuidData(GO_STRANGE_GONG)))
gong->SetGameObjectFlag(GO_FLAG_NOT_SELECTABLE);
// trigger or gong will need to be scripted to set IN_PROGRESS after enough hits.
// This is temp workaround.
instance->SetData(DATA_GONGEVENT, IN_PROGRESS); // to be removed.
if (instance->GetData(DATA_GONGEVENT) == IN_PROGRESS)
{
// Players are Now Saved to instance at SPECIAL (Player should be notified?)
me->GetMotionMaster()->MovePath(HARRISON_MOVE_2, false);
_gongEvent = GONG_EVENT_5;
_gongTimer = 5000;
}
else
{
_gongTimer = 1000;
_gongEvent = GONG_EVENT_9;
}
break;
case GONG_EVENT_5:
me->SetEntry(NPC_HARRISON_JONES_1);
me->SetDisplayId(MODEL_HARRISON_JONES_1);
Talk(SAY_HARRISON_2);
_gongTimer = 12000;
_gongEvent = GONG_EVENT_6;
break;
case GONG_EVENT_6:
me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_USE_STANDING);
Talk(SAY_HARRISON_3);
_gongTimer = 7000;
_gongEvent = GONG_EVENT_7;
break;
case GONG_EVENT_7:
if (!uiTargetGUID)
{
std::list<Creature*> targetList;
GetCreatureListWithEntryInGrid(targetList, me, NPC_AMANISHI_GUARDIAN, 26.0f);
if (!targetList.empty())
{
for (std::list<Creature*>::const_iterator itr = targetList.begin(); itr != targetList.end(); ++itr)
{
if (Creature* ptarget = *itr)
{
if (ptarget->GetPositionX() > 120)
{
ptarget->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 0, uint32(WEAPON_SPEAR));
ptarget->SetImmuneToPC(true);
ptarget->SetReactState(REACT_PASSIVE);
ptarget->AI()->SetData(0, 1);
}
else
{
ptarget->SetImmuneToPC(true);
ptarget->SetReactState(REACT_PASSIVE);
ptarget->AI()->SetData(0, 2);
}
}
}
}
}
if (GameObject* gate = me->GetMap()->GetGameObject(instance->GetGuidData(GO_MASSIVE_GATE)))
gate->SetGoState(GO_STATE_ACTIVE);
_gongTimer = 2000;
_gongEvent = GONG_EVENT_8;
break;
case GONG_EVENT_8:
DoCast(me, SPELL_STEALTH);
me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 0, uint32(0));
me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE);
me->GetMotionMaster()->MovePath(HARRISON_MOVE_3, false);
_gongTimer = 1000;
_gongEvent = 0;
break;
case GONG_EVENT_9:
me->GetMotionMaster()->MovePoint(0, 120.687f, 1674.0f, 42.0217f);
_gongTimer = 12000;
_gongEvent = GONG_EVENT_10;
break;
case GONG_EVENT_10:
me->SetFacingTo(1.59044f);
_gongEvent = 11;
_gongTimer = 6000;
break;
case GONG_EVENT_11:
me->SetNpcFlag(UNIT_NPC_FLAG_GOSSIP);
instance->SetData(DATA_GONGEVENT, NOT_STARTED);
_gongEvent = 0;
_gongTimer = 1000;
break;
}
}
else
_gongTimer -= diff;
}
}
};
CreatureAI* GetAI(Creature* creature) const override
{
return GetZulAmanAI<npc_harrison_jonesAI>(creature);
}
};
void AddSC_zulaman()
{
new npc_forest_frog();
RegisterZulAmanCreatureAI(npc_forest_frog);
new npc_zulaman_hostage();
new npc_harrison_jones();
RegisterZulAmanCreatureAI(npc_harrison_jones);
}

View File

@@ -25,18 +25,19 @@
enum DataTypes
{
DATA_GONGEVENT = 0,
DATA_NALORAKK = 1,
DATA_AKILZON = 2,
DATA_JANALAI = 3,
DATA_HALAZZI = 4,
DATA_HEXLORD = 5,
DATA_ZULJIN = 6,
MAX_ENCOUNTER = 7,
DATA_SPIRIT_LYNX = 8,
DATA_CHESTLOOTED = 9,
TYPE_RAND_VENDOR_1 = 10,
TYPE_RAND_VENDOR_2 = 11
DATA_NALORAKK = 0,
DATA_AKILZON = 1,
DATA_JANALAI = 2,
DATA_HALAZZI = 3,
DATA_HEXLORD = 4,
DATA_ZULJIN = 5,
MAX_ENCOUNTER = 6,
DATA_SPIRIT_LYNX = 7,
TYPE_RAND_VENDOR_1 = 8,
TYPE_RAND_VENDOR_2 = 9,
DATA_STRANGE_GONG = 10,
DATA_MASSIVE_GATE = 11,
DATA_HEXLORD_GATE = 12
};
enum CreatureIds
@@ -69,6 +70,15 @@ enum GameobjectIds
GO_STRANGE_GONG = 187359
};
enum MiscIds
{
DATA_TIMED_RUN = 0,
ACTION_START_TIMED_RUN = 0,
GROUP_TIMED_RUN = 1
};
uint32 constexpr PersistentDataCount = 1;
template <class AI, class T>
inline AI* GetZulAmanAI(T* obj)
{