From 91f5d16d6e6f2712d760aa28071053ce5f47b54e Mon Sep 17 00:00:00 2001 From: _daanieL Date: Wed, 12 Jun 2024 12:04:37 +0200 Subject: [PATCH] rework the arcatraz intro script, using spawn_group and worldstates (#677) * Add a better handling for Arcatraz Intro 1 Protean Nightmare respawns as long the Arcatraz Defenders are alive 9 Protean Horrors respawn as long both Arcatraz Warden groups are alive All handled via database now * correct worldstates * changes code requested in comments * Prevent xp/rep farm exploit * tab --- .../tempest_keep/arcatraz/arcatraz.cpp | 113 +++++++----------- .../outland/tempest_keep/arcatraz/arcatraz.h | 32 ++--- src/game/World/WorldStateDefines.h | 4 + 3 files changed, 65 insertions(+), 84 deletions(-) diff --git a/src/game/AI/ScriptDevAI/scripts/outland/tempest_keep/arcatraz/arcatraz.cpp b/src/game/AI/ScriptDevAI/scripts/outland/tempest_keep/arcatraz/arcatraz.cpp index a7c6d609432..f2673b25546 100644 --- a/src/game/AI/ScriptDevAI/scripts/outland/tempest_keep/arcatraz/arcatraz.cpp +++ b/src/game/AI/ScriptDevAI/scripts/outland/tempest_keep/arcatraz/arcatraz.cpp @@ -90,30 +90,19 @@ static const DialogueEntry aArcatrazDialogue[] = }; instance_arcatraz::instance_arcatraz(Map* map) : ScriptedInstance(map), DialogueHelper(aArcatrazDialogue), - m_resetDelayTimer(0), - m_entranceEventTimer(0), - m_killedWarders(0), - m_killedDefenders(0) + m_resetDelayTimer(0), m_WardenGroup(false) { Initialize(); } void instance_arcatraz::Initialize() { + instance->GetVariableManager().SetVariable(WORLD_STATE_PROTEAN_HORROR, 1); + instance->GetVariableManager().SetVariable(WORLD_STATE_PROTEAN_NIGHTMARE, 1); memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); InitializeDialogueHelper(this); } -void instance_arcatraz::OnPlayerEnter(Player* /*player*/) -{ - // Check encounter states - if (GetData(TYPE_ENTRANCE) == DONE || GetData(TYPE_ENTRANCE) == IN_PROGRESS) - return; - - SetData(TYPE_ENTRANCE, IN_PROGRESS); - m_entranceEventTimer = 1000; -} - void instance_arcatraz::OnObjectCreate(GameObject* go) { switch (go->GetEntry()) @@ -171,12 +160,52 @@ void instance_arcatraz::OnCreatureCreate(Creature* creature) break; } } +void instance_arcatraz::OnCreatureRespawn(Creature* creature) +{ + switch (creature->GetEntry()) + { + case NPC_PROTEAN_NIGHTMARE: + case NPC_PROTEAN_HORROR: + if (creature->HasStringId(STRING_ID_ENTRANCE_GROUP)) + { + creature->SetNoXP(true); + creature->SetNoLoot(true); + creature->SetNoReputation(true); + } + break; + } +} + +// Intro Handling +// When both Arcatraz Warder spawn_groups are dead, Protean Horror stop spawning +// When Arcatraz Defender spawn_group is dead, Protean Nightmare stop spawning +void instance_arcatraz::OnCreatureGroupDespawn(CreatureGroup* pGroup, Creature* /*pCreature*/) +{ + if (pGroup->GetGroupId() == SPAWN_GROUP_WARDEN_01) + { + if (m_WardenGroup) + instance->GetVariableManager().SetVariable(WORLD_STATE_PROTEAN_HORROR, 0); + else + m_WardenGroup = true; + } + + if (pGroup->GetGroupId() == SPAWN_GROUP_WARDEN_02) + { + if (m_WardenGroup) + + instance->GetVariableManager().SetVariable(WORLD_STATE_PROTEAN_HORROR, 0); + else + m_WardenGroup = true; + } + + if (pGroup->GetGroupId() == SPAWN_GROUP_DEFENDER) + instance->GetVariableManager().SetVariable(WORLD_STATE_PROTEAN_NIGHTMARE, 0); +} void instance_arcatraz::SetData(uint32 type, uint32 data) { switch (type) { - case TYPE_ENTRANCE: case TYPE_ZEREKETH: m_auiEncounter[type] = data; break; @@ -429,31 +458,6 @@ void instance_arcatraz::JustDidDialogueStep(int32 dialogueEntry) } } -void instance_arcatraz::OnCreatureDeath(Creature* creature) -{ - switch (creature->GetEntry()) - { - case NPC_ARCATRAZ_WARDER: - ++m_killedWarders; - break; - case NPC_ARCATRAZ_DEFENDER: - ++m_killedDefenders; - break; - case NPC_PROTEAN_NIGHTMARE: - case NPC_PROTEAN_HORROR: - // intro Protean spawn corpses should despawn after about 5 seconds - creature->ForcedDespawn(5000); - break; - } - - // Stop the intro spawns when the wardens are killed - if (m_killedDefenders == MAX_DEFENDERS && m_killedWarders == MAX_WARDERS) - { - SetData(TYPE_ENTRANCE, DONE); - m_entranceEventTimer = 0; - } -} - void instance_arcatraz::Update(uint32 diff) { DialogueUpdate(diff); @@ -469,35 +473,6 @@ void instance_arcatraz::Update(uint32 diff) else m_resetDelayTimer -= diff; } - - if (m_entranceEventTimer) - { - if (m_entranceEventTimer <= diff) - { - Player* player = GetPlayerInMap(); - if (!player) - return; - - uint32 entry = urand(0, 10) ? NPC_PROTEAN_HORROR : NPC_PROTEAN_NIGHTMARE; - - // Protean Horrors stop spawning once 4 warders are killed - // Protean Nightmares stop spawning once 3 defenders are killed - if ((entry == NPC_PROTEAN_HORROR && m_killedWarders == MAX_WARDERS) || (entry == NPC_PROTEAN_NIGHTMARE && m_killedDefenders == MAX_DEFENDERS)) - { - m_entranceEventTimer = urand(0, 10) ? urand(2000, 3500) : urand(5000, 7000); - return; - } - - // Summon and move the intro creatures into combat positions - if (Creature* pTemp = player->SummonCreature(entry, aEntranceSpawnLoc[0], aEntranceSpawnLoc[1], aEntranceSpawnLoc[2], aEntranceSpawnLoc[3], TEMPSPAWN_TIMED_OOC_OR_DEAD_DESPAWN, 30000)) - { - pTemp->GetMotionMaster()->MoveWaypoint(1); - } - m_entranceEventTimer = urand(0, 10) ? urand(2000, 3500) : urand(5000, 7000); - } - else - m_entranceEventTimer -= diff; - } } void AddSC_instance_arcatraz() diff --git a/src/game/AI/ScriptDevAI/scripts/outland/tempest_keep/arcatraz/arcatraz.h b/src/game/AI/ScriptDevAI/scripts/outland/tempest_keep/arcatraz/arcatraz.h index 565bf0e1276..42b96b8e5cf 100644 --- a/src/game/AI/ScriptDevAI/scripts/outland/tempest_keep/arcatraz/arcatraz.h +++ b/src/game/AI/ScriptDevAI/scripts/outland/tempest_keep/arcatraz/arcatraz.h @@ -5,13 +5,12 @@ #ifndef DEF_ARCATRAZ_H #define DEF_ARCATRAZ_H +#include "World/WorldStateDefines.h" + enum { MAX_ENCOUNTER = 10, - MAX_WARDERS = 4, - MAX_DEFENDERS = 3, - TYPE_ENTRANCE = 0, TYPE_ZEREKETH = 1, TYPE_DALLIAH = 2, TYPE_SOCCOTHRATES = 3, @@ -22,6 +21,10 @@ enum TYPE_WARDEN_4 = 8, // Handled with ACID (20910 - Twilight Drakonaar, 20911 - Blackwing Drakonaar) TYPE_WARDEN_5 = 9, + // intro event related + NPC_PROTEAN_NIGHTMARE = 20864, + NPC_PROTEAN_HORROR = 20865, + NPC_DALLIAH = 20885, NPC_SOCCOTHRATES = 20886, NPC_WRATH_SCRYER_FELFIRE = 20978, @@ -32,12 +35,6 @@ enum NPC_PRISON_GAMMA_POD = 21439, NPC_PRISON_BOSS_POD = 21440, - // intro event related - NPC_PROTEAN_NIGHTMARE = 20864, - NPC_PROTEAN_HORROR = 20865, - NPC_ARCATRAZ_WARDER = 20859, - NPC_ARCATRAZ_DEFENDER = 20857, - // Harbinger Skyriss event related (trash mobs are scripted in ACID) NPC_BLAZING_TRICKSTER = 20905, // phase 1 NPC_PHASE_HUNTER = 20906, @@ -58,8 +55,15 @@ enum GO_POD_OMEGA = 183965, // Pod fifth boss wave SPELL_TARGET_OMEGA = 36852, // Visual spell used by Mellichar + + // Intro related + SPAWN_GROUP_WARDEN_01 = 5520001, // Both Warden groups have to be dead to prevent Protean Horror to respawn + SPAWN_GROUP_WARDEN_02 = 5520002, // + SPAWN_GROUP_DEFENDER = 5520003, // SpawnGroup that handles Protean Nightmare respawn }; +const std::string STRING_ID_ENTRANCE_GROUP = "ARCATRAZ_ENTRANCE_GROUP"; // StringID assigned to entrance group to prevent rep/xp farm abuse + struct SpawnLocation { float m_fX, m_fY, m_fZ, m_fO; @@ -77,7 +81,6 @@ static const SpawnLocation aSummonPosition[5] = static const float aDalliahStartPos[4] = {118.6038f, 96.84682f, 22.44115f, 1.012f}; static const float aSoccotharesStartPos[4] = {122.1035f, 192.7203f, 22.44115f, 5.235f}; -static const float aEntranceSpawnLoc[4] = {173.471f, -0.138f, -10.101f, 3.123f}; class instance_arcatraz : public ScriptedInstance, private DialogueHelper { @@ -86,10 +89,10 @@ class instance_arcatraz : public ScriptedInstance, private DialogueHelper void Initialize() override; - void OnPlayerEnter(Player* player) override; void OnObjectCreate(GameObject* go) override; void OnCreatureCreate(Creature* creature) override; - void OnCreatureDeath(Creature* creature) override; + void OnCreatureGroupDespawn(CreatureGroup* pGroup, Creature* pCreature) override; + void OnCreatureRespawn(Creature* creature) override; void SetData(uint32 type, uint32 data) override; uint32 GetData(uint32 type) const override; @@ -106,9 +109,8 @@ class instance_arcatraz : public ScriptedInstance, private DialogueHelper std::string m_strInstData; uint32 m_resetDelayTimer; - uint32 m_entranceEventTimer; - uint8 m_killedWarders; - uint8 m_killedDefenders; + + bool m_WardenGroup; GuidVector m_skyrissEventMobsGuids; }; diff --git a/src/game/World/WorldStateDefines.h b/src/game/World/WorldStateDefines.h index c10d46c0acb..02147c3eb38 100644 --- a/src/game/World/WorldStateDefines.h +++ b/src/game/World/WorldStateDefines.h @@ -352,6 +352,10 @@ enum WorldStateID : int32 WORLD_STATE_LEGIONNAIRE_003 = 5400003, // Spawns Legionnaire 04 and 05 groups WORLD_STATE_CUSTOM_SPAWN_WAVES = 5400004, // Spawns initial waves at gauntlet of flame + // The Arcatraz + WORLD_STATE_PROTEAN_HORROR = 5520001, // Prevents that Protean Horrors respawn + WORLD_STATE_PROTEAN_NIGHTMARE = 5520002, // Prevents that Protean Nightmare respawn + // Wotlk };