Scripts/Vortex Pinnacle: implemented Slipstreams and shortcuts

This commit is contained in:
Ovahlord
2023-12-23 17:03:59 +01:00
parent e05541665b
commit 44921878f1
5 changed files with 396 additions and 6 deletions

View File

@@ -0,0 +1,89 @@
UPDATE `creature_template` SET `npcflag`= 0, `VehicleId`= 1111, `ScriptName`= 'npc_vp_slipstream' WHERE `entry`= 45455;
UPDATE `creature_template` SET `unit_flags`= 0x2000000, `flags_extra`= 0x80,`ScriptName`= 'npc_vp_slipstream_landing_zone' WHERE `entry`= 45504;
DELETE FROM `creature_template_addon` WHERE `entry`= 45455;
INSERT INTO `creature_template_addon` (`entry`, `SheathState`, `visibilityDistanceType`, `auras`) VALUES
(45455, 1, 5, '85021');
DELETE FROM `creature_template_movement` WHERE `CreatureId` IN (45455, 45504);
INSERT INTO `creature_template_movement` (`CreatureId`, `Ground`, `Flight`, `Rooted`) VALUES
(45455, 0, 1, 0),
(45504, 0, 1, 0);
DELETE FROM `npc_spellclick_spells` WHERE `npc_entry` = 45455;
INSERT INTO `npc_spellclick_spells` (`npc_entry`, `spell_id`, `cast_flags`, `user_type`) VALUES
(45455, 84965, 1, 0);
DELETE FROM `creature` WHERE `guid` IN (368211, 368210);
DELETE FROM `creature_addon` WHERE `guid` IN (368211, 368210);
SET @CGUID := 3000463;
DELETE FROM `creature` WHERE `guid` BETWEEN @CGUID+0 AND @CGUID+12;
INSERT INTO `creature` (`guid`, `id`, `map`, `zoneId`, `areaId`, `spawnDifficulties`, `PhaseId`, `PhaseGroup`, `modelid`, `equipment_id`, `position_x`, `position_y`, `position_z`, `orientation`, `spawntimesecs`, `wander_distance`, `currentwaypoint`, `curhealth`, `curmana`, `MovementType`, `npcflag`, `unit_flags`, `StringId`, `VerifiedBuild`) VALUES
-- Spawned after Grandvizier Ertan died
(@CGUID+0, 45455, 657, 0, 0, '1,2,24', 169, 0, 0, 0, -775.517, -70.9323, 640.3123, 0, 7200, 0, 0, 0, 0, 0, NULL, NULL, 'vp_slipstream_ertan_1', 15595), -- Slipstream
(@CGUID+1, 45455, 657, 0, 0, '1,2,24', 169, 0, 0, 0, -310.4583, -29.74479, 625.0833, 0, 7200, 0, 0, 0, 0, 0, NULL, NULL, 'vp_slipstream_entrance_1', 15595), -- Slipstream
(@CGUID+2, 45455, 657, 0, 0, '1,2,24', 169, 0, 0, 0, -848.227, -68.724, 654.2203, 0, 7200, 0, 0, 0, 0, 0, NULL, NULL, 'vp_slipstream_ertan_2',15595), -- Slipstream
(@CGUID+3, 45455, 657, 0, 0, '1,2,24', 169, 0, 0, 0, -844.885, -205.135, 660.7083, 0, 7200, 0, 0, 0, 0, 0, NULL, NULL, 'vp_slipstream_ertan_3', 15595), -- Slipstream
(@CGUID+4, 45504, 657, 0, 0, '1,2,24', 169, 0, 0, 0, -906.08, -176.514, 664.5053, 2.86234, 7200, 0, 0, 0, 0, 0, NULL, NULL, 'vp_slipstream_landing_zone_1', 15595), -- Slipstream Landing Zone
-- Spawned after Altairus died
(@CGUID+5, 45455, 657, 0, 0, '1,2,24', 169, 0, 0, 0, -1229.64, 412.26, 641.2933, 0, 7200, 0, 0, 0, 0, 0, NULL, NULL, 'vp_slipstream_altairus_5', 15595), -- Slipstream
(@CGUID+6, 45455, 657, 0, 0, '1,2,24', 169, 0, 0, 0, -1245.21, 230.986, 690.6083, 0, 7200, 0, 0, 0, 0, 0, NULL, NULL, 'vp_slipstream_altairus_3', 15595), -- Slipstream
(@CGUID+7, 45455, 657, 0, 0, '1,2,24', 169, 0, 0, 0, -1190.88, 125.203, 737.6243, 0, 7200, 0, 0, 0, 0, 0, NULL, NULL, 'vp_slipstream_altairus_1', 15595), -- Slipstream
(@CGUID+8, 45455, 657, 0, 0, '1,2,24', 169, 0, 0, 0, -382.441, 42.31597, 625.0833, 0, 7200, 0, 0, 0, 0, 0, NULL, NULL, 'vp_slipstream_entrance_2', 15595), -- Slipstream
(@CGUID+9, 45455, 657, 0, 0, '1,2,24', 169, 0, 0, 0, -1138.55, 178.524, 711.4943, 0, 7200, 0, 0, 0, 0, 0, NULL, NULL, 'vp_slipstream_altairus_2', 15595), -- Slipstream
(@CGUID+10, 45455, 657, 0, 0, '1,2,24', 169, 0, 0, 0, -1282.07, 344.856, 660.9873, 0, 7200, 0, 0, 0, 0, 0, NULL, NULL, 'vp_slipstream_altairus_4', 15595), -- Slipstream
(@CGUID+11, 45504, 657, 0, 0, '1,2,24', 169, 0, 0, 0, -1193.67, 472.835, 634.8653, 0.5061455, 7200, 0, 0, 0, 0, 0, NULL, NULL, 'vp_slipstream_landing_zone_2', 15595), -- Slipstream Landing Zone
-- Spawned after Asaad died
(@CGUID+12, 45455, 657, 0, 0, '1,2,24', 169, 0, 0, 0, -746.9566, 529.1406, 644.8316, 0, 7200, 0, 0, 0, 0, 0, NULL, NULL, 'vp_slipstream_back_to_entrance', 15595); -- Slipstream
DELETE FROM `spawn_group_template` WHERE `groupId` IN (1038, 1039, 1040);
INSERT INTO `spawn_group_template` (`groupId`, `groupName`, `groupFlags`) VALUES
(1038, 'The Vortex Pinnacle - Grandvizier Ertan Slipstreams', 4),
(1039, 'The Vortex Pinnacle - Altairus Slipstreams', 4),
(1040, 'The Vortex Pinnacle - Asaad Slipstreams', 4);
SET @SPAWNGROUP := 1038;
DELETE FROM `spawn_group` WHERE `groupId`= @SPAWNGROUP;
INSERT INTO `spawn_group` (`groupId`, `spawnType`, `spawnId`) VALUES
(@SPAWNGROUP, 0, @CGUID+0),
(@SPAWNGROUP, 0, @CGUID+1),
(@SPAWNGROUP, 0, @CGUID+2),
(@SPAWNGROUP, 0, @CGUID+3),
(@SPAWNGROUP, 0, @CGUID+4);
SET @SPAWNGROUP := 1039;
DELETE FROM `spawn_group` WHERE `groupId`= @SPAWNGROUP;
INSERT INTO `spawn_group` (`groupId`, `spawnType`, `spawnId`) VALUES
(@SPAWNGROUP, 0, @CGUID+5),
(@SPAWNGROUP, 0, @CGUID+6),
(@SPAWNGROUP, 0, @CGUID+7),
(@SPAWNGROUP, 0, @CGUID+8),
(@SPAWNGROUP, 0, @CGUID+9),
(@SPAWNGROUP, 0, @CGUID+10),
(@SPAWNGROUP, 0, @CGUID+11);
SET @SPAWNGROUP := 1040;
DELETE FROM `spawn_group` WHERE `groupId`= @SPAWNGROUP;
INSERT INTO `spawn_group` (`groupId`, `spawnType`, `spawnId`) VALUES
(@SPAWNGROUP, 0, @CGUID+12);
DELETE FROM `instance_spawn_groups` WHERE `spawnGroupId` IN (1038, 1039, 1040);
INSERT INTO `instance_spawn_groups` (`instanceMapId`, `bossStateId`, `bossStates`, `spawnGroupId`, `flags`) VALUES
(657, 0, 8, 1038, 1), -- Enable group when Grandvizier Ertan is DONE
(657, 1, 8, 1039, 1), -- Enable group when Alairus is DONE
(657, 2, 8, 1040, 1); -- Enable group when Asaad is DONE
DELETE FROM `spell_script_names` WHERE `ScriptName` IN ('spell_vp_slipstream', 'spell_vp_slipstream_shortcut');
INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES
(84978, 'spell_vp_slipstream'),
(84989, 'spell_vp_slipstream'),
(85395, 'spell_vp_slipstream'),
(85396, 'spell_vp_slipstream'),
(85017, 'spell_vp_slipstream'),
(89499, 'spell_vp_slipstream_shortcut'),
(89501, 'spell_vp_slipstream_shortcut');
DELETE FROM `spell_script_names` WHERE `spell_id`= 79737;
INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES
(79737, 'spell_gen_eject_all_passengers');

View File

@@ -17,6 +17,7 @@
#include "ScriptMgr.h"
#include "vortex_pinnacle.h"
#include "Creature.h"
#include "InstanceScript.h"
ObjectData const creatureData[] =
@@ -34,6 +35,10 @@ DungeonEncounterData const encounters[] =
{ BOSS_ASAAD, {{ 1042 }} }
};
// These StringIds must be set in DB to properly identify the first and second landing zone for the entrance shortcut teleporters
constexpr std::string_view SlipStreamLandingZoneStringId1 = "vp_slipstream_landing_zone_1";
constexpr std::string_view SlipStreamLandingZoneStringId2 = "vp_slipstream_landing_zone_2";
class instance_vortex_pinnacle : public InstanceMapScript
{
public:
@@ -48,6 +53,40 @@ public:
LoadObjectData(creatureData, nullptr);
LoadDungeonEncounterData(encounters);
}
void OnCreatureCreate(Creature* creature) override
{
InstanceScript::OnCreatureCreate(creature);
switch (creature->GetEntry())
{
case NPC_SLIPSTREAM_LANDING_ZONE:
if (creature->HasStringId(SlipStreamLandingZoneStringId1))
AddObject(creature, DATA_SLIPSTREAM_LANDING_ZONE_1, true);
else if (creature->HasStringId(SlipStreamLandingZoneStringId2))
AddObject(creature, DATA_SLIPSTREAM_LANDING_ZONE_2, true);
break;
default:
break;
}
}
void OnCreatureRemove(Creature* creature) override
{
InstanceScript::OnCreatureRemove(creature);
switch (creature->GetEntry())
{
case NPC_SLIPSTREAM_LANDING_ZONE:
if (creature->HasStringId(SlipStreamLandingZoneStringId1))
AddObject(creature, DATA_SLIPSTREAM_LANDING_ZONE_1, false);
else if (creature->HasStringId(SlipStreamLandingZoneStringId2))
AddObject(creature, DATA_SLIPSTREAM_LANDING_ZONE_2, false);
break;
default:
break;
}
}
};
InstanceScript* GetInstanceScript(InstanceMap* map) const override

View File

@@ -0,0 +1,253 @@
/*
* 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/>.
*/
#include "vortex_pinnacle.h"
#include "Creature.h"
#include "DB2Structure.h"
#include "EventMap.h"
#include "InstanceScript.h"
#include "ObjectAccessor.h"
#include "PassiveAI.h"
#include "Player.h"
#include "ScriptMgr.h"
#include "SpellInfo.h"
#include "SpellScript.h"
#include "Vehicle.h"
enum VPVehicleIds
{
VEHICLE_ID_SLIPSTREAM_ENTRANCE_1 = 1305,
VEHICLE_ID_SLIPSTREAM_ENTRANCE_2 = 1306,
VEHICLE_ID_SLIPSTREAM_1 = 1111,
VEHICLE_ID_SLIPSTREAM_2 = 1112,
VEHICLE_ID_SLIPSTREAM_3 = 1113,
VEHICLE_ID_SLIPSTREAM_4 = 1149,
VEHICLE_ID_SLIPSTREAM_5 = 1150,
VEHICLE_ID_SLIPSTREAM_BACK_TO_ENTRANCE = 1551
};
enum VPSlipstreamSpells
{
// Spells
SPELL_SLIPSTREAM_ENTER = 84965,
SPELL_SLIPSTREAM_FIRST = 84980,
SPELL_SLIPSTREAM_SECOND = 84988,
SPELL_SLIPSTREAM_THIRD = 85394,
SPELL_SLIPSTREAM_FOURTH = 85397,
SPELL_SLIPSTREAM_LAST = 85016,
SPELL_SLIPSTREAM_ASAAD = 95911,
SPELL_SLIPSTREAM_SHORTCUT_ALTAIRUS = 89498,
SPELL_SLIPSTREAM_SHORTCUT_ALTAIRUS_TELEPORT = 89499,
SPELL_SLIPSTREAM_SHORTCUT_ASAAD = 89500,
SPELL_SLIPSTREAM_SHORTCUT_ASAAD_TELEPORT = 89501,
SPELL_GENERIC_EJECT_ALL_PASSENGERS = 79737
};
struct SlipstreamInfo
{
SlipstreamInfo(std::string_view const& stringId, std::string_view const& targetStringId, uint32 vehicleId, bool spellClick, uint32 chainSpellId) :
StringId(stringId), TargetStringId(targetStringId), VehicleId(vehicleId), SpellClick(spellClick), ChainSpellId(chainSpellId) { }
std::string_view StringId;
std::string_view TargetStringId;
uint32 VehicleId;
bool SpellClick;
uint32 ChainSpellId;
};
static std::array<SlipstreamInfo const, 11> const SlipstreamData =
{
// Sequence for Grandvizier Ertan's Slipstreams
SlipstreamInfo("vp_slipstream_ertan_1", "vp_slipstream_ertan_2", VEHICLE_ID_SLIPSTREAM_1, true, SPELL_SLIPSTREAM_FIRST),
SlipstreamInfo("vp_slipstream_ertan_2", "vp_slipstream_ertan_3", VEHICLE_ID_SLIPSTREAM_2, false, SPELL_SLIPSTREAM_SECOND),
SlipstreamInfo("vp_slipstream_ertan_3", "vp_slipstream_landing_zone_1", VEHICLE_ID_SLIPSTREAM_3, false, SPELL_SLIPSTREAM_LAST),
// Sequence for Altairus' Slipstreams
SlipstreamInfo("vp_slipstream_altairus_1", "vp_slipstream_altairus_2", VEHICLE_ID_SLIPSTREAM_1, true, SPELL_SLIPSTREAM_FIRST),
SlipstreamInfo("vp_slipstream_altairus_2", "vp_slipstream_altairus_3", VEHICLE_ID_SLIPSTREAM_2, false, SPELL_SLIPSTREAM_SECOND),
SlipstreamInfo("vp_slipstream_altairus_3", "vp_slipstream_altairus_4", VEHICLE_ID_SLIPSTREAM_3, false, SPELL_SLIPSTREAM_THIRD),
SlipstreamInfo("vp_slipstream_altairus_4", "vp_slipstream_altairus_5", VEHICLE_ID_SLIPSTREAM_4, false, SPELL_SLIPSTREAM_FOURTH),
SlipstreamInfo("vp_slipstream_altairus_5", "vp_slipstream_landing_zone_2", VEHICLE_ID_SLIPSTREAM_5, false, SPELL_SLIPSTREAM_LAST),
// Shortcuts
SlipstreamInfo("vp_slipstream_entrance_1", "", VEHICLE_ID_SLIPSTREAM_ENTRANCE_1, true, SPELL_SLIPSTREAM_SHORTCUT_ALTAIRUS),
SlipstreamInfo("vp_slipstream_entrance_2", "", VEHICLE_ID_SLIPSTREAM_ENTRANCE_2, true, SPELL_SLIPSTREAM_SHORTCUT_ASAAD),
SlipstreamInfo("vp_slipstream_back_to_entrance", "", VEHICLE_ID_SLIPSTREAM_BACK_TO_ENTRANCE, true, SPELL_SLIPSTREAM_ASAAD)
};
struct npc_vp_slipstream : public NullCreatureAI
{
npc_vp_slipstream(Creature* creature) : NullCreatureAI(creature) { }
// This is a bit hacky but we have to set the vehicleId before the npc is being sent out via UpdateObject to prevent client visuals from breaking
void InitializeAI() override
{
for (SlipstreamInfo const& slipstreamInfo : SlipstreamData)
{
if (!me->HasStringId(slipstreamInfo.StringId))
continue;
Vehicle const* vehicle = me->GetVehicleKit();
// Uninstall the existing vehicle kit when the vehicleId mismatches
if (vehicle && vehicle->GetVehicleInfo()->ID != slipstreamInfo.VehicleId)
{
me->RemoveVehicleKit(true);
vehicle = nullptr;
}
if (!vehicle)
me->CreateVehicleKit(slipstreamInfo.VehicleId, me->GetEntry(), true);
if (slipstreamInfo.SpellClick)
{
me->SetNpcFlag(UNIT_NPC_FLAG_SPELLCLICK);
me->RemoveUnitFlag(UNIT_FLAG_UNINTERACTIBLE);
}
break;
}
}
void PassengerBoarded(Unit* who, int8 /*seatId*/, bool apply) override
{
if (!apply || !who->IsPlayer())
return;
for (SlipstreamInfo const& slipstreamInfo : SlipstreamData)
{
if (!me->HasStringId(slipstreamInfo.StringId))
continue;
// The cast of the chain spell is slightly delayed
me->m_Events.AddEventAtOffset([caster = me, playerGuid = who->GetGUID(), chainSpellId = slipstreamInfo.ChainSpellId]()
{
if (Player* player = ObjectAccessor::FindPlayer(playerGuid))
if (player->IsOnVehicle(caster))
caster->CastSpell(player, chainSpellId);
}, 500ms);
break;
}
}
};
static constexpr uint32 const EVENT_EJECT_ALL_PASSENGERS = 1;
struct npc_vp_slipstream_landing_zone : public NullCreatureAI
{
npc_vp_slipstream_landing_zone(Creature* creature) : NullCreatureAI(creature) { }
void PassengerBoarded(Unit* /*who*/, int8 /*seatId*/, bool apply) override
{
if (!apply)
return;
// Every time a player enters the landing zone vehicle before it can eject passengers, it will delay its cast
_events.RescheduleEvent(EVENT_EJECT_ALL_PASSENGERS, 2s);
}
void UpdateAI(uint32 diff) override
{
_events.Update(diff);
if (_events.ExecuteEvent())
DoCastSelf(SPELL_GENERIC_EJECT_ALL_PASSENGERS);
}
private:
EventMap _events;
};
// 84978, 84989, 85395, 85396, 85017 - Slipstream
class spell_vp_slipstream : public SpellScript
{
bool Load() override
{
Creature const* vehicle = GetCaster()->GetVehicleCreatureBase();
if (!vehicle)
return false;
for (SlipstreamInfo const& slipstreamInfo : SlipstreamData)
{
if (!vehicle->HasStringId(slipstreamInfo.StringId))
continue;
_targetStringId = slipstreamInfo.TargetStringId;
return true;
}
return false;
}
void SelectNextSlipstream(WorldObject*& target)
{
target = GetCaster()->FindNearestCreatureWithOptions(200.f, { .StringId = _targetStringId });
}
void Register() override
{
OnObjectTargetSelect += SpellObjectTargetSelectFn(spell_vp_slipstream::SelectNextSlipstream, EFFECT_0, TARGET_UNIT_NEARBY_ENTRY);
}
private:
std::string_view _targetStringId;
};
// 89499, 89501 - Slipstream
class spell_vp_slipstream_shortcut : public SpellScript
{
bool Load() override
{
_instance = GetCaster()->GetInstanceScript();
return _instance != nullptr;
}
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_SLIPSTREAM_SHORTCUT_ALTAIRUS_TELEPORT, SPELL_SLIPSTREAM_SHORTCUT_ASAAD_TELEPORT });
}
// The distance between the shortcut Slipstreams and the Slipstream Landing Platforms is beyond our grid searching limit, we have to manually select the target
void SetDestination(SpellDestination& target)
{
switch (GetSpellInfo()->Id)
{
case SPELL_SLIPSTREAM_SHORTCUT_ALTAIRUS_TELEPORT:
if (Creature* landingZone = _instance->GetCreature(DATA_SLIPSTREAM_LANDING_ZONE_1))
target.Relocate(landingZone->GetPosition());
break;
case SPELL_SLIPSTREAM_SHORTCUT_ASAAD_TELEPORT:
if (Creature* landingZone = _instance->GetCreature(DATA_SLIPSTREAM_LANDING_ZONE_2))
target.Relocate(landingZone->GetPosition());
break;
default:
break;
}
}
void Register() override
{
OnDestinationTargetSelect += SpellDestinationTargetSelectFn(spell_vp_slipstream_shortcut::SetDestination, EFFECT_0, TARGET_DEST_NEARBY_ENTRY);
}
private:
InstanceScript* _instance;
};
void AddSC_vortex_pinnacle()
{
RegisterVortexPinnacleCreatureAI(npc_vp_slipstream);
RegisterVortexPinnacleCreatureAI(npc_vp_slipstream_landing_zone);
RegisterSpellScript(spell_vp_slipstream);
RegisterSpellScript(spell_vp_slipstream_shortcut);
}

View File

@@ -25,20 +25,27 @@ constexpr char const* VPScriptName = "instance_vortex_pinnacle";
constexpr uint32 const EncounterCount = 3;
enum TotFWDataTypes
enum VPDataTypes
{
// Encounters
BOSS_GRAND_VIZIER_ERTAN = 0,
BOSS_ALTAIRUS = 1,
BOSS_ASAAD = 2
BOSS_ASAAD = 2,
// Shortcuts
DATA_SLIPSTREAM_LANDING_ZONE_1,
DATA_SLIPSTREAM_LANDING_ZONE_2
};
enum TotFWCreatureIds
enum VPreatureIds
{
// Bosses
NPC_GRAND_VIZIER_ERTAN = 43878,
NPC_ALTAIRUS = 43873,
NPC_ASAAD = 43875
NPC_GRAND_VIZIER_ERTAN = 43878,
NPC_ALTAIRUS = 43873,
NPC_ASAAD = 43875,
// Shortcuts
NPC_SLIPSTREAM_LANDING_ZONE = 45504
};
template <class AI, class T>

View File

@@ -111,6 +111,7 @@ void AddSC_boss_lockmaw();
void AddSC_instance_lost_city_of_the_tolvir();
// The Vortex Pinnacle
void AddSC_instance_vortex_pinnacle();
void AddSC_vortex_pinnacle();
// Wailing caverns
void AddSC_wailing_caverns();
void AddSC_instance_wailing_caverns();
@@ -248,6 +249,7 @@ void AddKalimdorScripts()
AddSC_instance_lost_city_of_the_tolvir();
// The Vortex Pinnacle
AddSC_instance_vortex_pinnacle();
AddSC_vortex_pinnacle();
// Wailing caverns
AddSC_wailing_caverns();
AddSC_instance_wailing_caverns();