diff --git a/data/sql/updates/pending_db_world/rev_1661383096159773400.sql b/data/sql/updates/pending_db_world/rev_1661383096159773400.sql new file mode 100644 index 000000000..c29b76d26 --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1661383096159773400.sql @@ -0,0 +1,3 @@ +-- +DELETE FROM `creature_addon` WHERE `guid` IN (144680, 144679); +DELETE FROM `creature` WHERE `id1` = 15428; diff --git a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_ossirian.cpp b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_ossirian.cpp index 426d844bf..91258c5c1 100644 --- a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_ossirian.cpp +++ b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_ossirian.cpp @@ -15,6 +15,7 @@ * with this program. If not, see . */ +#include "GameObjectAI.h" #include "MiscPackets.h" #include "Opcodes.h" #include "Player.h" @@ -43,6 +44,7 @@ enum Spells SPELL_SAND_STORM = 25160, SPELL_SUMMON_CRYSTAL = 25192, SPELL_SUMMON_SMALL_OBSIDIAN_CHUNK = 27627, // Server-side + SPELL_SPEED_BURST = 25184, // Server-side // Crystal SPELL_FIRE_WEAKNESS = 25177, @@ -54,7 +56,8 @@ enum Spells enum Actions { - ACTION_TRIGGER_WEAKNESS = 1 + ACTION_TRIGGER_WEAKNESS = 1, + ACTION_DESPAWN_TRIGGER = 2 }; enum Events @@ -65,6 +68,11 @@ enum Events EVENT_SPEEDUP = 4 }; +enum Misc +{ + GUID_TRIGGER_PAIR = 1, +}; + uint8 const NUM_CRYSTALS = 12; Position CrystalCoordinates[NUM_CRYSTALS] = { @@ -82,6 +90,12 @@ Position CrystalCoordinates[NUM_CRYSTALS] = { -9367.1699218750f, 1780.89001464844f, 85.6390991210937f, 1.90241003036499f } }; +Position VortexPositions[2] = +{ + { -9524.06f, 1881.9224f, 85.64029f, 0.0f }, + { -9228.479, 1925.3331f, 85.64147f, 0.0f } +}; + uint8 const NUM_WEAKNESS = 5; uint32 const spellWeakness[NUM_WEAKNESS] = { SPELL_FIRE_WEAKNESS, SPELL_FROST_WEAKNESS, SPELL_NATURE_WEAKNESS, SPELL_ARCANE_WEAKNESS, SPELL_SHADOW_WEAKNESS }; @@ -96,21 +110,6 @@ struct boss_ossirian : public BossAI void InitializeAI() override { Reset(); - - if (Creature* trigger = me->GetMap()->SummonCreature(NPC_OSSIRIAN_TRIGGER, CrystalCoordinates[0])) - { - _triggerGUID[0] = trigger->GetGUID(); - if (GameObject* crystal = trigger->SummonGameObject(GO_OSSIRIAN_CRYSTAL, - CrystalCoordinates[0].GetPositionX(), - CrystalCoordinates[0].GetPositionY(), - CrystalCoordinates[0].GetPositionZ(), - 0, 0, 0, 0, 0, uint32(-1))) - { - _crystalGUID[0] = crystal->GetGUID(); - crystal->SetOwnerGUID(ObjectGuid::Empty); - crystal->RemoveGameObjectFlag(GO_FLAG_IN_USE); - } - } } void Reset() override @@ -119,88 +118,46 @@ struct boss_ossirian : public BossAI _crystalIterator = urand(1, NUM_CRYSTALS - 1); - for (uint8 i = 1; i < NUM_CRYSTALS; ++i) + if (!ObjectAccessor::GetGameObject(*me, _firstCrystalGUID)) { - _triggerGUID[i].Clear(); - _crystalGUID[i].Clear(); - } - } - - void JustReachedHome() override - { - if (me->IsVisible()) - { - Creature* trigger = me->GetMap()->GetCreature(_triggerGUID[0]); - if (trigger) + if (Creature* trigger = me->GetMap()->SummonCreature(NPC_OSSIRIAN_TRIGGER, CrystalCoordinates[0])) { - trigger->DespawnOrUnsummon(); - if (GameObject* crystal = me->GetMap()->GetGameObject(_crystalGUID[0])) - crystal->Delete(); - } - - trigger = me->GetMap()->SummonCreature(NPC_OSSIRIAN_TRIGGER, CrystalCoordinates[0]); - if (trigger) - { - _triggerGUID[0] = trigger->GetGUID(); - if (GameObject* crystal = trigger->SummonGameObject(GO_OSSIRIAN_CRYSTAL, + if (GameObject* crystal = me->SummonGameObject(GO_OSSIRIAN_CRYSTAL, CrystalCoordinates[0].GetPositionX(), CrystalCoordinates[0].GetPositionY(), CrystalCoordinates[0].GetPositionZ(), 0, 0, 0, 0, 0, uint32(-1))) { - _crystalGUID[0] = crystal->GetGUID(); + _firstCrystalGUID = crystal->GetGUID(); crystal->SetOwnerGUID(ObjectGuid::Empty); crystal->RemoveGameObjectFlag(GO_FLAG_IN_USE); + crystal->AI()->SetGUID(trigger->GetGUID(), GUID_TRIGGER_PAIR); } } } } - void SpellHit(Unit* caster, SpellInfo const* spell) override + void JustSummoned(Creature* creature) override + { + summons.Summon(creature); + } + + void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override { for (uint32 weakness : spellWeakness) { if (spell->Id == weakness) { me->RemoveAurasDueToSpell(SPELL_STRENGHT_OF_OSSIRIAN); - - for (uint8 i = 1; i < NUM_CRYSTALS; ++i) - { - if (caster->GetGUID() == _triggerGUID[i]) - { - if (Creature* creatureCaster = caster->ToCreature()) - { - creatureCaster->DespawnOrUnsummon(); - } - - break; - } - } } } } void SetGUID(ObjectGuid guid, int32 action) override { - if (action == ACTION_TRIGGER_WEAKNESS) + if (action == ACTION_TRIGGER_WEAKNESS && guid != _firstCrystalGUID) { - for (uint8 i = 0; i < NUM_CRYSTALS; ++i) - { - if (_crystalGUID[i] == guid) - { - if (Creature* trigger = me->GetMap()->GetCreature(_triggerGUID[i])) - { - if (!trigger->HasUnitState(UNIT_STATE_CASTING)) - { - trigger->CastSpell(trigger, spellWeakness[urand(0, 4)], false); - } - } - - SpawnNextCrystal(); - - break; - } - } + SpawnNextCrystal(); } } @@ -208,7 +165,6 @@ struct boss_ossirian : public BossAI { BossAI::EnterCombat(who); events.Reset(); - me->SetSpeedRate(MOVE_RUN, 1.0f); events.ScheduleEvent(EVENT_SPEEDUP, 10s); events.ScheduleEvent(EVENT_SILENCE, 30s); events.ScheduleEvent(EVENT_CYCLONE, 20s); @@ -224,15 +180,29 @@ struct boss_ossirian : public BossAI map->SendToPlayers(weather.Write()); SpawnNextCrystal(3); + + std::list pathIds = { 1446800, 1446790 }; + + for (Position pos : VortexPositions) + { + if (Creature* vortex = me->SummonCreature(NPC_SAND_VORTEX, pos)) + { + vortex->GetMotionMaster()->MovePath(pathIds.front(), true); + pathIds.reverse(); + } + } } void SummonedCreatureDespawn(Creature* summon) override { summons.Despawn(summon); - if (GameObject* crystal = GetClosestGameObjectWithEntry(summon, GO_OSSIRIAN_CRYSTAL, 5.0f)) + if (summon->GetEntry() == NPC_OSSIRIAN_TRIGGER) { - crystal->Delete(); + if (GameObject* crystal = GetClosestGameObjectWithEntry(summon, GO_OSSIRIAN_CRYSTAL, 5.0f)) + { + crystal->Delete(); + } } } @@ -250,17 +220,16 @@ struct boss_ossirian : public BossAI if (Creature* trigger = me->SummonCreature(NPC_OSSIRIAN_TRIGGER, CrystalCoordinates[_crystalIterator])) { - _triggerGUID[i] = trigger->GetGUID(); if (GameObject* crystal = trigger->SummonGameObject(GO_OSSIRIAN_CRYSTAL, CrystalCoordinates[_crystalIterator].GetPositionX(), CrystalCoordinates[_crystalIterator].GetPositionY(), CrystalCoordinates[_crystalIterator].GetPositionZ(), 0, 0, 0, 0, 0, uint32(-1))) { - _crystalGUID[i] = crystal->GetGUID(); ++_crystalIterator; crystal->SetOwnerGUID(ObjectGuid::Empty); crystal->RemoveGameObjectFlag(GO_FLAG_IN_USE); + crystal->AI()->SetGUID(trigger->GetGUID(), GUID_TRIGGER_PAIR); } } } @@ -311,7 +280,7 @@ struct boss_ossirian : public BossAI switch (eventId) { case EVENT_SPEEDUP: - me->SetSpeedRate(MOVE_RUN, 2.2f); + DoCastSelf(SPELL_SPEED_BURST); break; case EVENT_SILENCE: DoCastAOE(SPELL_CURSE_OF_TONGUES); @@ -333,9 +302,8 @@ struct boss_ossirian : public BossAI } protected: - std::array _triggerGUID; - std::array _crystalGUID; uint8 _crystalIterator; + ObjectGuid _firstCrystalGUID; bool _saidIntro; }; @@ -344,18 +312,61 @@ class go_ossirian_crystal : public GameObjectScript public: go_ossirian_crystal() : GameObjectScript("go_ossirian_crystal") { } - bool OnGossipHello(Player* player, GameObject* go) override + struct go_ossirian_crystalAI : public GameObjectAI { - InstanceScript* instance = player->GetInstanceScript(); - if (!instance) - return true; + go_ossirian_crystalAI(GameObject* go) : GameObjectAI(go), _instance(go->GetInstanceScript()) { } - Creature* ossirian = instance->GetCreature(DATA_OSSIRIAN); - if (!ossirian) - return true; + void SetGUID(ObjectGuid guid, int32 type) override + { + if (type == GUID_TRIGGER_PAIR) + { + _triggerGUID = guid; + } + } - ossirian->AI()->SetGUID(go->GetGUID(), ACTION_TRIGGER_WEAKNESS); - return false; + bool GossipHello(Player* /*player*/, bool reportUse) override + { + if (reportUse) + { + if (!_instance) + return true; + + Creature* ossirian = _instance->GetCreature(DATA_OSSIRIAN); + if (!ossirian) + return true; + + if (Creature* trigger = ObjectAccessor::GetCreature(*me, _triggerGUID)) + { + if (!trigger->HasUnitState(UNIT_STATE_CASTING)) + { + ossirian->AI()->SetGUID(me->GetGUID(), ACTION_TRIGGER_WEAKNESS); + trigger->CastSpell(trigger, spellWeakness[urand(0, 4)], false); + } + } + } + + return false; + } + + void DoAction(int32 action) override + { + if (action == ACTION_DESPAWN_TRIGGER) + { + if (Creature* trigger = ObjectAccessor::GetCreature(*me, _triggerGUID)) + { + trigger->DespawnOrUnsummon(); + } + } + } + + private: + InstanceScript* _instance; + ObjectGuid _triggerGUID; + }; + + GameObjectAI* GetAI(GameObject* go) const override + { + return new go_ossirian_crystalAI(go); } }; diff --git a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/instance_ruins_of_ahnqiraj.cpp b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/instance_ruins_of_ahnqiraj.cpp index c60e67710..fc897bc6a 100644 --- a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/instance_ruins_of_ahnqiraj.cpp +++ b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/instance_ruins_of_ahnqiraj.cpp @@ -110,10 +110,6 @@ public: case NPC_OSSIRIAN: _ossirianGUID = creature->GetGUID(); break; - case NPC_SAND_VORTEX: - _sandVortexes.push_back(creature->GetGUID()); - creature->SetVisible(false); - break; case NPC_ANDOROV: _andorovGUID = creature->GetGUID(); break; @@ -225,31 +221,6 @@ public: _paralyzedGUID = data; } - bool SetBossState(uint32 type, EncounterState state) override - { - if (!InstanceScript::SetBossState(type, state)) - return false; - - switch (type) - { - case DATA_OSSIRIAN: - { - for (ObjectGuid const& guid : _sandVortexes) - { - if (Creature* sandVortex = instance->GetCreature(guid)) - { - sandVortex->SetVisible(state == IN_PROGRESS); - } - } - break; - default: - break; - } - } - - return true; - } - ObjectGuid GetGuidData(uint32 type) const override { switch (type) @@ -376,7 +347,6 @@ public: ObjectGuid _ossirianGUID; ObjectGuid _paralyzedGUID; ObjectGuid _andorovGUID; - GuidVector _sandVortexes; uint32 _rajaxWaveCounter; uint8 _buruPhase; TaskScheduler _scheduler;