From e548805017ed5477b3e85b0a49ffb828ff9ba947 Mon Sep 17 00:00:00 2001 From: ZhengPeiRu21 <98835050+ZhengPeiRu21@users.noreply.github.com> Date: Wed, 13 Jul 2022 14:46:14 -0600 Subject: [PATCH 001/130] fix(Core): Fix indexing in UpdatePlayerSetting (#12375) * fix(Core): Fix indexing in UpdatePlayerSetting * Fix integer signing --- src/server/game/Entities/Player/PlayerSettings.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/server/game/Entities/Player/PlayerSettings.cpp b/src/server/game/Entities/Player/PlayerSettings.cpp index 46130b115..f81bfe9a9 100644 --- a/src/server/game/Entities/Player/PlayerSettings.cpp +++ b/src/server/game/Entities/Player/PlayerSettings.cpp @@ -108,12 +108,11 @@ void Player::_SavePlayerSettings(CharacterDatabaseTransaction trans) void Player::UpdatePlayerSetting(std::string source, uint8 index, uint32 value) { auto itr = m_charSettingsMap.find(source); + uint8 size = index + 1; if (itr == m_charSettingsMap.end()) { // Settings not found, initialize a new entry. - uint8 size = index ? index : index + 1; - PlayerSettingVector setting; setting.resize(size); @@ -129,6 +128,10 @@ void Player::UpdatePlayerSetting(std::string source, uint8 index, uint32 value) } else { + if (size > itr->second.size()) + { + itr->second.resize(size); + } itr->second[index].value = value; } } From 57327aa362f0702ea8878cc961206bfcc243bf5e Mon Sep 17 00:00:00 2001 From: Eddy Vega <61223313+Si1ker@users.noreply.github.com> Date: Wed, 13 Jul 2022 14:51:50 -0600 Subject: [PATCH 002/130] fix(DB/creature template): Adjust Whitewhisker/Irondeep NPCs in Alterac Valley (#12309) --- .../updates/pending_db_world/rev_1657055583659435900.sql | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 data/sql/updates/pending_db_world/rev_1657055583659435900.sql diff --git a/data/sql/updates/pending_db_world/rev_1657055583659435900.sql b/data/sql/updates/pending_db_world/rev_1657055583659435900.sql new file mode 100644 index 000000000..10d5ece89 --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1657055583659435900.sql @@ -0,0 +1,7 @@ +-- + +UPDATE `creature_template` SET `exp`=0, `ManaModifier`=1 WHERE `entry`=11657; +UPDATE `creature_template` SET `unit_flags`=`unit_flags`|512 WHERE `entry`=11677; +UPDATE `creature_template` SET `minlevel`=53, `maxlevel`=54 WHERE `entry`=11600; +UPDATE `creature_template` SET `lootid`=0,`mingold`=0, `maxgold`=0 WHERE `entry` IN (10987,11600,11602,11604,11605,10982,11603); + From 02fa20b6380b991634198de9a295abac11152d60 Mon Sep 17 00:00:00 2001 From: AzerothCoreBot Date: Wed, 13 Jul 2022 20:54:01 +0000 Subject: [PATCH 003/130] chore(DB): import pending files Referenced commit(s): 57327aa362f0702ea8878cc961206bfcc243bf5e --- .../rev_1657055583659435900.sql => db_world/2022_07_13_00.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/rev_1657055583659435900.sql => db_world/2022_07_13_00.sql} (89%) diff --git a/data/sql/updates/pending_db_world/rev_1657055583659435900.sql b/data/sql/updates/db_world/2022_07_13_00.sql similarity index 89% rename from data/sql/updates/pending_db_world/rev_1657055583659435900.sql rename to data/sql/updates/db_world/2022_07_13_00.sql index 10d5ece89..9b485f276 100644 --- a/data/sql/updates/pending_db_world/rev_1657055583659435900.sql +++ b/data/sql/updates/db_world/2022_07_13_00.sql @@ -1,3 +1,4 @@ +-- DB update 2022_07_12_01 -> 2022_07_13_00 -- UPDATE `creature_template` SET `exp`=0, `ManaModifier`=1 WHERE `entry`=11657; From cc52712ac12e3d6a16aabcbd13807924c64aeb1e Mon Sep 17 00:00:00 2001 From: IntelligentQuantum Date: Fri, 15 Jul 2022 18:41:49 +0430 Subject: [PATCH 004/130] refactor(Core/AI): factory functions cleanup (#11779) --- src/common/Dynamic/FactoryHolder.h | 25 ++- src/common/Dynamic/ObjectRegistry.h | 75 +++------ src/server/game/AI/CoreAI/CombatAI.cpp | 10 +- src/server/game/AI/CoreAI/CombatAI.h | 10 +- src/server/game/AI/CoreAI/GameObjectAI.cpp | 13 +- src/server/game/AI/CoreAI/GameObjectAI.h | 4 +- src/server/game/AI/CoreAI/GuardAI.cpp | 4 +- src/server/game/AI/CoreAI/GuardAI.h | 2 +- src/server/game/AI/CoreAI/PassiveAI.cpp | 27 ++++ src/server/game/AI/CoreAI/PassiveAI.h | 9 +- src/server/game/AI/CoreAI/PetAI.cpp | 9 +- src/server/game/AI/CoreAI/PetAI.h | 2 +- src/server/game/AI/CoreAI/ReactorAI.cpp | 2 +- src/server/game/AI/CoreAI/ReactorAI.h | 2 +- src/server/game/AI/CoreAI/TotemAI.cpp | 2 +- src/server/game/AI/CoreAI/TotemAI.h | 2 +- src/server/game/AI/CreatureAI.h | 2 +- src/server/game/AI/CreatureAIFactory.h | 58 ++----- src/server/game/AI/CreatureAIRegistry.cpp | 9 +- src/server/game/AI/CreatureAISelector.cpp | 152 +++++++----------- src/server/game/AI/CreatureAISelector.h | 7 +- src/server/game/AI/GameObjectAIFactory.h | 51 ++++++ src/server/game/AI/SmartScripts/SmartAI.cpp | 14 -- src/server/game/AI/SmartScripts/SmartAI.h | 4 +- .../game/Entities/Creature/Creature.cpp | 4 +- src/server/game/Entities/Creature/Creature.h | 2 +- .../game/Entities/GameObject/GameObject.cpp | 2 +- .../game/Entities/GameObject/GameObject.h | 2 +- src/server/game/Movement/MotionMaster.cpp | 22 ++- .../game/Movement/MovementGenerator.cpp | 7 + src/server/game/Movement/MovementGenerator.h | 25 ++- .../game/Movement/MovementGeneratorImpl.h | 29 ---- .../IdleMovementGenerator.cpp | 2 - .../IdleMovementGenerator.h | 2 - src/tools/mmaps_generator/MapBuilder.cpp | 4 + 35 files changed, 285 insertions(+), 311 deletions(-) create mode 100644 src/server/game/AI/GameObjectAIFactory.h delete mode 100644 src/server/game/Movement/MovementGeneratorImpl.h diff --git a/src/common/Dynamic/FactoryHolder.h b/src/common/Dynamic/FactoryHolder.h index c1f1055b0..093f6e4f3 100644 --- a/src/common/Dynamic/FactoryHolder.h +++ b/src/common/Dynamic/FactoryHolder.h @@ -19,33 +19,29 @@ #define ACORE_FACTORY_HOLDER #include "Define.h" -#include "Dynamic/TypeList.h" #include "ObjectRegistry.h" +#include "TypeList.h" -/* - * FactoryHolder holds a factory object of a specific type +/** FactoryHolder holds a factory object of a specific type */ -template +template class FactoryHolder { public: - typedef ObjectRegistry, Key > FactoryHolderRegistry; + typedef ObjectRegistry, Key> FactoryHolderRegistry; - FactoryHolder(Key k) : i_key(k) { } + explicit FactoryHolder(Key const& k) : _key(k) { } virtual ~FactoryHolder() { } - inline Key key() const { return i_key; } - void RegisterSelf(void) { FactoryHolderRegistry::instance()->InsertItem(this, i_key); } - void DeregisterSelf(void) { FactoryHolderRegistry::instance()->RemoveItem(this, false); } + void RegisterSelf() { FactoryHolderRegistry::instance()->InsertItem(this, _key); } /// Abstract Factory create method - virtual T* Create(void* data = nullptr) const = 0; + virtual T* Create(O* object = nullptr) const = 0; private: - Key i_key; + Key const _key; }; -/* - * Permissible is a classic way of letting the object decide +/** Permissible is a classic way of letting the object decide * whether how good they handle things. This is not retricted * to factory selectors. */ @@ -54,7 +50,6 @@ class Permissible { public: virtual ~Permissible() { } - virtual int Permit(const T*) const = 0; + virtual int32 Permit(T const*) const = 0; }; - #endif diff --git a/src/common/Dynamic/ObjectRegistry.h b/src/common/Dynamic/ObjectRegistry.h index 7cc2c9abc..d72fd7b3a 100644 --- a/src/common/Dynamic/ObjectRegistry.h +++ b/src/common/Dynamic/ObjectRegistry.h @@ -23,20 +23,23 @@ #include #include #include +#include /** ObjectRegistry holds all registry item of the same type */ template -class ObjectRegistry +class ObjectRegistry final { public: - typedef std::map RegistryMapType; + typedef std::map> RegistryMapType; /// Returns a registry item - const T* GetRegistryItem(Key key) const + T const* GetRegistryItem(Key const& key) const { - typename RegistryMapType::const_iterator iter = i_registeredObjects.find(key); - return ( iter == i_registeredObjects.end() ? nullptr : iter->second ); + auto itr = _registeredObjects.find(key); + if (itr == _registeredObjects.end()) + return nullptr; + return itr->second.get(); } static ObjectRegistry* instance() @@ -46,72 +49,34 @@ public: } /// Inserts a registry item - bool InsertItem(T* obj, Key key, bool override = false) + bool InsertItem(T* obj, Key const& key, bool force = false) { - typename RegistryMapType::iterator iter = i_registeredObjects.find(key); - if ( iter != i_registeredObjects.end() ) + auto itr = _registeredObjects.find(key); + if (itr != _registeredObjects.end()) { - if ( !override ) + if (!force) { return false; } - delete iter->second; - i_registeredObjects.erase(iter); + _registeredObjects.erase(itr); } - i_registeredObjects[key] = obj; + _registeredObjects.emplace(std::piecewise_construct, std::forward_as_tuple(key), std::forward_as_tuple(obj)); return true; } - /// Removes a registry item - void RemoveItem(Key key, bool delete_object = true) - { - typename RegistryMapType::iterator iter = i_registeredObjects.find(key); - if ( iter != i_registeredObjects.end() ) - { - if ( delete_object ) - { - delete iter->second; - } - i_registeredObjects.erase(iter); - } - } - - /// Returns true if registry contains an item - bool HasItem(Key key) const - { - return (i_registeredObjects.find(key) != i_registeredObjects.end()); - } - - /// Inefficiently return a vector of registered items - unsigned int GetRegisteredItems(std::vector& l) const - { - unsigned int sz = l.size(); - l.resize(sz + i_registeredObjects.size()); - for (typename RegistryMapType::const_iterator iter = i_registeredObjects.begin(); iter != i_registeredObjects.end(); ++iter) - { - l[sz++] = iter->first; - } - return i_registeredObjects.size(); - } - /// Return the map of registered items RegistryMapType const& GetRegisteredItems() const { - return i_registeredObjects; + return _registeredObjects; } - ObjectRegistry() { } - ~ObjectRegistry() - { - for (typename RegistryMapType::iterator iter = i_registeredObjects.begin(); iter != i_registeredObjects.end(); ++iter) - { - delete iter->second; - } - i_registeredObjects.clear(); - } private: - RegistryMapType i_registeredObjects; + RegistryMapType _registeredObjects; + + // non instanceable, only static + ObjectRegistry() { } + ~ObjectRegistry() { } }; #endif diff --git a/src/server/game/AI/CoreAI/CombatAI.cpp b/src/server/game/AI/CoreAI/CombatAI.cpp index 336733978..18c7a2382 100644 --- a/src/server/game/AI/CoreAI/CombatAI.cpp +++ b/src/server/game/AI/CoreAI/CombatAI.cpp @@ -26,7 +26,7 @@ // AggressorAI ///////////////// -int AggressorAI::Permissible(Creature const* creature) +int32 AggressorAI::Permissible(Creature const* creature) { // have some hostile factions, it will be selected by IsHostileTo check at MoveInLineOfSight if (!creature->IsCivilian() && !creature->IsNeutralToAll()) @@ -320,3 +320,11 @@ void VehicleAI::CheckConditions(uint32 diff) else m_ConditionsTimer -= diff; } + +int32 VehicleAI::Permissible(Creature const* creature) +{ + if (creature->IsVehicle()) + return PERMIT_BASE_SPECIAL; + + return PERMIT_BASE_NO; +} diff --git a/src/server/game/AI/CoreAI/CombatAI.h b/src/server/game/AI/CoreAI/CombatAI.h index 39c016bc9..6f5825385 100644 --- a/src/server/game/AI/CoreAI/CombatAI.h +++ b/src/server/game/AI/CoreAI/CombatAI.h @@ -31,7 +31,7 @@ public: explicit AggressorAI(Creature* c) : CreatureAI(c) {} void UpdateAI(uint32) override; - static int Permissible(Creature const*); + static int32 Permissible(Creature const* creature); }; typedef std::vector SpellVct; @@ -47,7 +47,7 @@ public: void JustDied(Unit* killer) override; void UpdateAI(uint32 diff) override; - static int Permissible(Creature const* /*creature*/) { return PERMIT_BASE_NO; } + static int32 Permissible(Creature const* /*creature*/) { return PERMIT_BASE_NO; } protected: EventMap events; @@ -73,7 +73,7 @@ public: void AttackStart(Unit* who) override; void UpdateAI(uint32 diff) override; - static int Permissible(Creature const* /*creature*/) { return PERMIT_BASE_NO; } + static int32 Permissible(Creature const* /*creature*/) { return PERMIT_BASE_NO; } protected: float m_minRange; @@ -87,7 +87,7 @@ public: void AttackStart(Unit* who) override; void UpdateAI(uint32 diff) override; - static int Permissible(Creature const* /*creature*/) { return PERMIT_BASE_NO; } + static int32 Permissible(Creature const* /*creature*/) { return PERMIT_BASE_NO; } protected: float m_minRange; @@ -105,7 +105,7 @@ public: void AttackStart(Unit*) override {} void OnCharmed(bool apply) override; - static int Permissible(Creature const* /*creature*/) { return PERMIT_BASE_NO; } + static int32 Permissible(Creature const* creature); private: void LoadConditions(); diff --git a/src/server/game/AI/CoreAI/GameObjectAI.cpp b/src/server/game/AI/CoreAI/GameObjectAI.cpp index 4594ce83a..ca5267331 100644 --- a/src/server/game/AI/CoreAI/GameObjectAI.cpp +++ b/src/server/game/AI/CoreAI/GameObjectAI.cpp @@ -17,12 +17,15 @@ #include "GameObjectAI.h" -//GameObjectAI::GameObjectAI(GameObject* g) : go(g) {} -int GameObjectAI::Permissible(GameObject const* go) +int32 GameObjectAI::Permissible(GameObject const* /*go*/) { - if (go->GetAIName() == "GameObjectAI") - return PERMIT_BASE_SPECIAL; return PERMIT_BASE_NO; } -NullGameObjectAI::NullGameObjectAI(GameObject* g) : GameObjectAI(g) {} +NullGameObjectAI::NullGameObjectAI(GameObject* go) : GameObjectAI(go) { } + +int32 NullGameObjectAI::Permissible(GameObject const* /*go*/) +{ + return PERMIT_BASE_IDLE; +} + diff --git a/src/server/game/AI/CoreAI/GameObjectAI.h b/src/server/game/AI/CoreAI/GameObjectAI.h index 1bf62bceb..3a2731105 100644 --- a/src/server/game/AI/CoreAI/GameObjectAI.h +++ b/src/server/game/AI/CoreAI/GameObjectAI.h @@ -49,7 +49,7 @@ public: virtual void SetGUID(ObjectGuid /*guid*/, int32 /*id = 0 */) {} virtual ObjectGuid GetGUID(int32 /*id = 0 */) const { return ObjectGuid::Empty; } - static int Permissible(GameObject const* go); + static int32 Permissible(GameObject const* go); virtual bool GossipHello(Player* /*player*/, bool /*reportUse*/) { return false; } virtual bool GossipSelect(Player* /*player*/, uint32 /*sender*/, uint32 /*action*/) { return false; } @@ -76,6 +76,6 @@ public: void UpdateAI(uint32 /*diff*/) override {} - static int Permissible(GameObject const* /*go*/) { return PERMIT_BASE_IDLE; } + static int32 Permissible(GameObject const* go); }; #endif diff --git a/src/server/game/AI/CoreAI/GuardAI.cpp b/src/server/game/AI/CoreAI/GuardAI.cpp index 0253eb007..86c6fc1f0 100644 --- a/src/server/game/AI/CoreAI/GuardAI.cpp +++ b/src/server/game/AI/CoreAI/GuardAI.cpp @@ -19,10 +19,10 @@ #include "CreatureAIImpl.h" #include "Player.h" -int GuardAI::Permissible(Creature const* creature) +int32 GuardAI::Permissible(Creature const* creature) { if (creature->IsGuard()) - return PERMIT_BASE_SPECIAL; + return PERMIT_BASE_PROACTIVE; return PERMIT_BASE_NO; } diff --git a/src/server/game/AI/CoreAI/GuardAI.h b/src/server/game/AI/CoreAI/GuardAI.h index c48b93a9f..d8c7c9310 100644 --- a/src/server/game/AI/CoreAI/GuardAI.h +++ b/src/server/game/AI/CoreAI/GuardAI.h @@ -27,7 +27,7 @@ class GuardAI : public ScriptedAI public: explicit GuardAI(Creature* creature); - static int Permissible(Creature const* creature); + static int32 Permissible(Creature const* creature); void Reset() override; void EnterEvadeMode(EvadeReason /*why*/) override; diff --git a/src/server/game/AI/CoreAI/PassiveAI.cpp b/src/server/game/AI/CoreAI/PassiveAI.cpp index 1a576f47e..d1ac8350f 100644 --- a/src/server/game/AI/CoreAI/PassiveAI.cpp +++ b/src/server/game/AI/CoreAI/PassiveAI.cpp @@ -23,6 +23,17 @@ PassiveAI::PassiveAI(Creature* c) : CreatureAI(c) { me->SetReactState(REACT_PASS PossessedAI::PossessedAI(Creature* c) : CreatureAI(c) { me->SetReactState(REACT_PASSIVE); } NullCreatureAI::NullCreatureAI(Creature* c) : CreatureAI(c) { me->SetReactState(REACT_PASSIVE); } +int32 NullCreatureAI::Permissible(Creature const* creature) +{ + if (creature->HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK)) + return PERMIT_BASE_PROACTIVE + 50; + + if (creature->IsTrigger()) + return PERMIT_BASE_REACTIVE; + + return PERMIT_BASE_IDLE; +} + void PassiveAI::UpdateAI(uint32) { if (me->IsInCombat() && me->getAttackers().empty()) @@ -84,8 +95,24 @@ void CritterAI::UpdateAI(uint32 diff) } } +int32 CritterAI::Permissible(Creature const* creature) +{ + if (creature->IsCritter() && !creature->HasUnitTypeMask(UNIT_MASK_GUARDIAN)) + return PERMIT_BASE_PROACTIVE; + + return PERMIT_BASE_NO; +} + void TriggerAI::IsSummonedBy(Unit* summoner) { if (me->m_spells[0]) me->CastSpell(me, me->m_spells[0], false, 0, 0, summoner ? summoner->GetGUID() : ObjectGuid::Empty); } + +int32 TriggerAI::Permissible(Creature const* creature) +{ + if (creature->IsTrigger() && creature->m_spells[0]) + return PERMIT_BASE_SPECIAL; + + return PERMIT_BASE_NO; +} diff --git a/src/server/game/AI/CoreAI/PassiveAI.h b/src/server/game/AI/CoreAI/PassiveAI.h index 9f17a5935..79046100e 100644 --- a/src/server/game/AI/CoreAI/PassiveAI.h +++ b/src/server/game/AI/CoreAI/PassiveAI.h @@ -30,7 +30,7 @@ public: void AttackStart(Unit*) override {} void UpdateAI(uint32) override; - static int Permissible(Creature const*) { return PERMIT_BASE_IDLE; } + static int32 Permissible(Creature const* /*creature*/) { return PERMIT_BASE_NO; } }; class PossessedAI : public CreatureAI @@ -46,7 +46,7 @@ public: void JustDied(Unit*) override; void KilledUnit(Unit* victim) override; - static int Permissible(Creature const*) { return PERMIT_BASE_IDLE; } + static int32 Permissible(Creature const* /*creature*/) { return PERMIT_BASE_NO; } }; class NullCreatureAI : public CreatureAI @@ -60,7 +60,7 @@ public: void EnterEvadeMode(EvadeReason /*why*/) override {} void OnCharmed(bool /*apply*/) override {} - static int Permissible(Creature const*) { return PERMIT_BASE_IDLE; } + static int32 Permissible(Creature const* creature); }; class CritterAI : public PassiveAI @@ -72,6 +72,7 @@ public: void EnterEvadeMode(EvadeReason why) override; void UpdateAI(uint32) override; + static int32 Permissible(Creature const* creature); // Xinef: Added private: uint32 _combatTimer; @@ -82,6 +83,8 @@ class TriggerAI : public NullCreatureAI public: explicit TriggerAI(Creature* c) : NullCreatureAI(c) {} void IsSummonedBy(Unit* summoner) override; + + static int32 Permissible(Creature const* creature); }; #endif diff --git a/src/server/game/AI/CoreAI/PetAI.cpp b/src/server/game/AI/CoreAI/PetAI.cpp index fe71ffadc..3ed00426f 100644 --- a/src/server/game/AI/CoreAI/PetAI.cpp +++ b/src/server/game/AI/CoreAI/PetAI.cpp @@ -28,11 +28,18 @@ #include "SpellMgr.h" #include "Util.h" -int PetAI::Permissible(Creature const* creature) +int32 PetAI::Permissible(Creature const* creature) { if (creature->IsPet()) return PERMIT_BASE_SPECIAL; + if (creature->HasUnitTypeMask(UNIT_MASK_CONTROLABLE_GUARDIAN)) + { + if (reinterpret_cast(creature)->GetOwner()->GetTypeId() == TYPEID_PLAYER) + return PERMIT_BASE_PROACTIVE; + return PERMIT_BASE_REACTIVE; + } + return PERMIT_BASE_NO; } diff --git a/src/server/game/AI/CoreAI/PetAI.h b/src/server/game/AI/CoreAI/PetAI.h index bf7685289..7db553adb 100644 --- a/src/server/game/AI/CoreAI/PetAI.h +++ b/src/server/game/AI/CoreAI/PetAI.h @@ -49,7 +49,7 @@ public: explicit PetAI(Creature* c); void UpdateAI(uint32) override; - static int Permissible(Creature const*); + static int32 Permissible(Creature const* creature); void KilledUnit(Unit* /*victim*/) override; void AttackStart(Unit* target) override; diff --git a/src/server/game/AI/CoreAI/ReactorAI.cpp b/src/server/game/AI/CoreAI/ReactorAI.cpp index 37165d7f1..e50356f34 100644 --- a/src/server/game/AI/CoreAI/ReactorAI.cpp +++ b/src/server/game/AI/CoreAI/ReactorAI.cpp @@ -19,7 +19,7 @@ #include "CreatureAIImpl.h" #include "Errors.h" -int ReactorAI::Permissible(Creature const* creature) +int32 ReactorAI::Permissible(Creature const* creature) { if (creature->IsCivilian() || creature->IsNeutralToAll()) return PERMIT_BASE_REACTIVE; diff --git a/src/server/game/AI/CoreAI/ReactorAI.h b/src/server/game/AI/CoreAI/ReactorAI.h index fb65eb0fc..b6a203189 100644 --- a/src/server/game/AI/CoreAI/ReactorAI.h +++ b/src/server/game/AI/CoreAI/ReactorAI.h @@ -30,6 +30,6 @@ public: void MoveInLineOfSight(Unit*) override {} void UpdateAI(uint32 diff) override; - static int Permissible(Creature const*); + static int32 Permissible(Creature const* creature); }; #endif diff --git a/src/server/game/AI/CoreAI/TotemAI.cpp b/src/server/game/AI/CoreAI/TotemAI.cpp index 77560df6b..d12232f27 100644 --- a/src/server/game/AI/CoreAI/TotemAI.cpp +++ b/src/server/game/AI/CoreAI/TotemAI.cpp @@ -25,7 +25,7 @@ #include "SpellMgr.h" #include "Totem.h" -int TotemAI::Permissible(Creature const* creature) +int32 TotemAI::Permissible(Creature const* creature) { if (creature->IsTotem()) return PERMIT_BASE_PROACTIVE; diff --git a/src/server/game/AI/CoreAI/TotemAI.h b/src/server/game/AI/CoreAI/TotemAI.h index 837d5e0fd..36639a006 100644 --- a/src/server/game/AI/CoreAI/TotemAI.h +++ b/src/server/game/AI/CoreAI/TotemAI.h @@ -38,7 +38,7 @@ public: void DoAction(int32 param) override; void UpdateAI(uint32 diff) override; - static int Permissible(Creature const* creature); + static int32 Permissible(Creature const* creature); private: ObjectGuid i_victimGuid; diff --git a/src/server/game/AI/CreatureAI.h b/src/server/game/AI/CreatureAI.h index b03e25578..a85638975 100644 --- a/src/server/game/AI/CreatureAI.h +++ b/src/server/game/AI/CreatureAI.h @@ -222,7 +222,7 @@ private: bool m_MoveInLineOfSight_locked; }; -enum Permitions +enum Permitions : int32 { PERMIT_BASE_NO = -1, PERMIT_BASE_IDLE = 1, diff --git a/src/server/game/AI/CreatureAIFactory.h b/src/server/game/AI/CreatureAIFactory.h index 233d4c165..6ae188a7b 100644 --- a/src/server/game/AI/CreatureAIFactory.h +++ b/src/server/game/AI/CreatureAIFactory.h @@ -19,60 +19,32 @@ #define ACORE_CREATUREAIFACTORY_H #include "FactoryHolder.h" -#include "GameObjectAI.h" #include "ObjectRegistry.h" -struct SelectableAI : public FactoryHolder, public Permissible +typedef FactoryHolder CreatureAICreator; + +struct SelectableAI : public CreatureAICreator, public Permissible { - SelectableAI(const char* id) : FactoryHolder(id) {} + SelectableAI(std::string const& name) : CreatureAICreator(name), Permissible() { } }; template struct CreatureAIFactory : public SelectableAI { - CreatureAIFactory(const char* name) : SelectableAI(name) {} + CreatureAIFactory(std::string const& name) : SelectableAI(name) { } - CreatureAI* Create(void*) const; + inline CreatureAI* Create(Creature* c) const override + { + return new REAL_AI(c); + } - int Permit(Creature const* c) const { return REAL_AI::Permissible(c); } + int32 Permit(Creature const* c) const override + { + return REAL_AI::Permissible(c); + } }; -template -inline CreatureAI* -CreatureAIFactory::Create(void* data) const -{ - Creature* creature = reinterpret_cast(data); - return (new REAL_AI(creature)); -} - -typedef FactoryHolder CreatureAICreator; -typedef FactoryHolder::FactoryHolderRegistry CreatureAIRegistry; - -//GO -struct SelectableGameObjectAI : public FactoryHolder, public Permissible -{ - SelectableGameObjectAI(const char* id) : FactoryHolder(id) {} -}; - -template -struct GameObjectAIFactory : public SelectableGameObjectAI -{ - GameObjectAIFactory(const char* name) : SelectableGameObjectAI(name) {} - - GameObjectAI* Create(void*) const; - - int Permit(GameObject const* g) const { return REAL_GO_AI::Permissible(g); } -}; - -template -inline GameObjectAI* -GameObjectAIFactory::Create(void* data) const -{ - GameObject* go = reinterpret_cast(data); - return (new REAL_GO_AI(go)); -} - -typedef FactoryHolder GameObjectAICreator; -typedef FactoryHolder::FactoryHolderRegistry GameObjectAIRegistry; +typedef CreatureAICreator::FactoryHolderRegistry CreatureAIRegistry; +#define sCreatureAIRegistry CreatureAIRegistry::instance() #endif diff --git a/src/server/game/AI/CreatureAIRegistry.cpp b/src/server/game/AI/CreatureAIRegistry.cpp index f3d29e5be..4e1f6fdc5 100644 --- a/src/server/game/AI/CreatureAIRegistry.cpp +++ b/src/server/game/AI/CreatureAIRegistry.cpp @@ -19,7 +19,7 @@ #include "CombatAI.h" #include "CreatureAIFactory.h" #include "GuardAI.h" -#include "MovementGeneratorImpl.h" +#include "MovementGenerator.h" #include "PassiveAI.h" #include "PetAI.h" #include "RandomMovementGenerator.h" @@ -27,6 +27,7 @@ #include "SmartAI.h" #include "TotemAI.h" #include "WaypointMovementGenerator.h" +#include "GameObjectAIFactory.h" namespace AIRegistry { @@ -47,10 +48,12 @@ namespace AIRegistry (new CreatureAIFactory("VehicleAI"))->RegisterSelf(); (new CreatureAIFactory("SmartAI"))->RegisterSelf(); + (new GameObjectAIFactory("NullGameObjectAI"))->RegisterSelf(); (new GameObjectAIFactory("GameObjectAI"))->RegisterSelf(); (new GameObjectAIFactory("SmartGameObjectAI"))->RegisterSelf(); - (new MovementGeneratorFactory >(RANDOM_MOTION_TYPE))->RegisterSelf(); - (new MovementGeneratorFactory >(WAYPOINT_MOTION_TYPE))->RegisterSelf(); + (new IdleMovementFactory())->RegisterSelf(); + (new MovementGeneratorFactory>(RANDOM_MOTION_TYPE))->RegisterSelf(); + (new MovementGeneratorFactory>(WAYPOINT_MOTION_TYPE))->RegisterSelf(); } } diff --git a/src/server/game/AI/CreatureAISelector.cpp b/src/server/game/AI/CreatureAISelector.cpp index a9ed9832c..d4c1e71a1 100644 --- a/src/server/game/AI/CreatureAISelector.cpp +++ b/src/server/game/AI/CreatureAISelector.cpp @@ -15,132 +15,102 @@ * with this program. If not, see . */ -#include "CreatureAISelector.h" #include "Creature.h" +#include "CreatureAISelector.h" #include "CreatureAIFactory.h" + #include "MovementGenerator.h" -#include "PassiveAI.h" -#include "Pet.h" + +#include "GameObject.h" +#include "GameObjectAIFactory.h" + #include "ScriptMgr.h" -#include "TemporarySummon.h" namespace FactorySelector { - CreatureAI* selectAI(Creature* creature) + template + struct PermissibleOrderPred { - const CreatureAICreator* ai_factory = nullptr; - CreatureAIRegistry& ai_registry(*CreatureAIRegistry::instance()); + public: + PermissibleOrderPred(T const* obj) : _obj(obj) { } - // xinef: if we have controlable guardian, define petai for players as they can steer him, otherwise db / normal ai - // xinef: dont remember why i changed this qq commented out as may break some quests - if (creature->IsPet()/* || (creature->HasUnitTypeMask(UNIT_MASK_CONTROLABLE_GUARDIAN) && ((Guardian*)creature)->GetOwner()->GetTypeId() == TYPEID_PLAYER)*/) - ai_factory = ai_registry.GetRegistryItem("PetAI"); + template + bool operator()(Value const& left, Value const& right) const + { + Permissible const* leftPermit = ASSERT_NOTNULL(dynamic_cast const*>(left.second.get())); + Permissible const* rightPermit = ASSERT_NOTNULL(dynamic_cast const*>(right.second.get())); - //scriptname in db + return leftPermit->Permit(_obj) < rightPermit->Permit(_obj); + } + + private: + T const* const _obj; + }; + + CreatureAI* SelectAI(Creature* creature) + { + CreatureAICreator const* ai_factory = nullptr; + + // scriptname in db if (!ai_factory) if (CreatureAI* scriptedAI = sScriptMgr->GetCreatureAI(creature)) return scriptedAI; // AIname in db - std::string ainame = creature->GetAIName(); - if (!ai_factory && !ainame.empty()) - ai_factory = ai_registry.GetRegistryItem(ainame); - - // select by NPC flags - if (!ai_factory) - { - if (creature->IsVehicle()) - ai_factory = ai_registry.GetRegistryItem("VehicleAI"); - else if (creature->HasUnitTypeMask(UNIT_MASK_CONTROLABLE_GUARDIAN) && ((Guardian*)creature)->GetOwner()->GetTypeId() == TYPEID_PLAYER) - ai_factory = ai_registry.GetRegistryItem("PetAI"); - else if (creature->HasNpcFlag(UNIT_NPC_FLAG_SPELLCLICK)) - ai_factory = ai_registry.GetRegistryItem("NullCreatureAI"); - else if (creature->IsGuard()) - ai_factory = ai_registry.GetRegistryItem("GuardAI"); - else if (creature->HasUnitTypeMask(UNIT_MASK_CONTROLABLE_GUARDIAN)) - ai_factory = ai_registry.GetRegistryItem("PetAI"); - else if (creature->IsTotem()) - ai_factory = ai_registry.GetRegistryItem("TotemAI"); - else if (creature->IsTrigger()) - { - if (creature->m_spells[0]) - ai_factory = ai_registry.GetRegistryItem("TriggerAI"); - else - ai_factory = ai_registry.GetRegistryItem("NullCreatureAI"); - } - else if (creature->IsCritter() && !creature->HasUnitTypeMask(UNIT_MASK_GUARDIAN)) - ai_factory = ai_registry.GetRegistryItem("CritterAI"); - } + std::string const& aiName = creature->GetAIName(); + if (!ai_factory && !aiName.empty()) + ai_factory = sCreatureAIRegistry->GetRegistryItem(aiName); // select by permit check if (!ai_factory) { - int best_val = -1; - typedef CreatureAIRegistry::RegistryMapType RMT; - RMT const& l = ai_registry.GetRegisteredItems(); - for (RMT::const_iterator iter = l.begin(); iter != l.end(); ++iter) - { - const CreatureAICreator* factory = iter->second; - const SelectableAI* p = dynamic_cast(factory); - ASSERT(p); - int val = p->Permit(creature); - if (val > best_val) - { - best_val = val; - ai_factory = p; - } - } + CreatureAIRegistry::RegistryMapType const& items = sCreatureAIRegistry->GetRegisteredItems(); + auto itr = std::max_element(items.begin(), items.end(), PermissibleOrderPred(creature)); + if (itr != items.end()) + ai_factory = itr->second.get(); } - // select NullCreatureAI if not another cases - ainame = (!ai_factory) ? "NullCreatureAI" : ai_factory->key(); - LOG_DEBUG("scripts.ai", "Creature {} used AI is {}.", creature->GetGUID().ToString(), ainame); - return (!ai_factory ? new NullCreatureAI(creature) : ai_factory->Create(creature)); + if (!ai_factory) + ai_factory = sCreatureAIRegistry->GetRegistryItem("NullCreatureAI"); + + return ASSERT_NOTNULL(ai_factory)->Create(creature); } - MovementGenerator* selectMovementGenerator(Creature* creature) + MovementGenerator* SelectMovementGenerator(Unit* unit) { - MovementGeneratorRegistry& mv_registry(*MovementGeneratorRegistry::instance()); - ASSERT(creature->GetCreatureTemplate()); - const MovementGeneratorCreator* mv_factory = mv_registry.GetRegistryItem(creature->GetDefaultMovementType()); + MovementGeneratorType type = IDLE_MOTION_TYPE; + if (unit->GetTypeId() == TYPEID_UNIT) + type = unit->ToCreature()->GetDefaultMovementType(); - /* if (mv_factory == nullptr) - { - int best_val = -1; - std::vector l; - mv_registry.GetRegisteredItems(l); - for (std::vector::iterator iter = l.begin(); iter != l.end(); ++iter) - { - const MovementGeneratorCreator *factory = mv_registry.GetRegistryItem((*iter).c_str()); - const SelectableMovement *p = dynamic_cast(factory); - ASSERT(p != nullptr); - int val = p->Permit(creature); - if (val > best_val) - { - best_val = val; - mv_factory = p; - } - } - }*/ - - return (!mv_factory ? nullptr : mv_factory->Create(creature)); + MovementGeneratorCreator const* mv_factory = sMovementGeneratorRegistry->GetRegistryItem(type); + return ASSERT_NOTNULL(mv_factory)->Create(unit); } GameObjectAI* SelectGameObjectAI(GameObject* go) { - const GameObjectAICreator* ai_factory = nullptr; - GameObjectAIRegistry& ai_registry(*GameObjectAIRegistry::instance()); + GameObjectAICreator const* ai_factory = nullptr; + // scriptname in db if (GameObjectAI* scriptedAI = sScriptMgr->GetGameObjectAI(go)) return scriptedAI; - ai_factory = ai_registry.GetRegistryItem(go->GetAIName()); + // AIname in db + std::string const& aiName = go->GetAIName(); + if (!ai_factory && !aiName.empty()) + ai_factory = sGameObjectAIRegistry->GetRegistryItem(aiName); - //future goAI types go here + // select by permit check + if (!ai_factory) + { + GameObjectAIRegistry::RegistryMapType const& items = sGameObjectAIRegistry->GetRegisteredItems(); + auto itr = std::max_element(items.begin(), items.end(), PermissibleOrderPred(go)); + if (itr != items.end()) + ai_factory = itr->second.get(); + } - std::string ainame = (!ai_factory || go->GetScriptId()) ? "NullGameObjectAI" : ai_factory->key(); - LOG_DEBUG("scripts.ai", "GameObject {} used AI is {}.", go->GetGUID().ToString(), ainame); + if (!ai_factory) + ai_factory = sGameObjectAIRegistry->GetRegistryItem("NullGameObjectAI"); - return (!ai_factory ? new NullGameObjectAI(go) : ai_factory->Create(go)); + return ASSERT_NOTNULL(ai_factory)->Create(go); } } diff --git a/src/server/game/AI/CreatureAISelector.h b/src/server/game/AI/CreatureAISelector.h index 936587e12..a5df78f81 100644 --- a/src/server/game/AI/CreatureAISelector.h +++ b/src/server/game/AI/CreatureAISelector.h @@ -21,13 +21,14 @@ class CreatureAI; class Creature; class MovementGenerator; +class Unit; class GameObjectAI; class GameObject; namespace FactorySelector { - CreatureAI* selectAI(Creature*); - MovementGenerator* selectMovementGenerator(Creature*); - GameObjectAI* SelectGameObjectAI(GameObject*); + AC_GAME_API CreatureAI* SelectAI(Creature* creature); + AC_GAME_API MovementGenerator* SelectMovementGenerator(Unit* unit); + AC_GAME_API GameObjectAI* SelectGameObjectAI(GameObject* go); } #endif diff --git a/src/server/game/AI/GameObjectAIFactory.h b/src/server/game/AI/GameObjectAIFactory.h new file mode 100644 index 000000000..bfebd358b --- /dev/null +++ b/src/server/game/AI/GameObjectAIFactory.h @@ -0,0 +1,51 @@ +/* + * This file is part of the AzerothCore 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 Affero General Public License as published by the + * Free Software Foundation; either version 3 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 Affero 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 . + */ + +#ifndef ACORE_GAMEOBJECTAIFACTORY_H +#define ACORE_GAMEOBJECTAIFACTORY_H + +#include "ObjectRegistry.h" +#include "FactoryHolder.h" + +typedef FactoryHolder GameObjectAICreator; + +struct SelectableGameObjectAI : public GameObjectAICreator, public Permissible +{ + SelectableGameObjectAI(std::string const& name) : GameObjectAICreator(name), Permissible() { } +}; + +template +struct GameObjectAIFactory : public SelectableGameObjectAI +{ + GameObjectAIFactory(std::string const& name) : SelectableGameObjectAI(name) { } + + GameObjectAI* Create(GameObject* go) const override + { + return new REAL_GO_AI(go); + } + + int32 Permit(GameObject const* go) const override + { + return REAL_GO_AI::Permissible(go); + } +}; + +typedef GameObjectAICreator::FactoryHolderRegistry GameObjectAIRegistry; + +#define sGameObjectAIRegistry GameObjectAIRegistry::instance() + +#endif diff --git a/src/server/game/AI/SmartScripts/SmartAI.cpp b/src/server/game/AI/SmartScripts/SmartAI.cpp index 612981260..34a6111d4 100644 --- a/src/server/game/AI/SmartScripts/SmartAI.cpp +++ b/src/server/game/AI/SmartScripts/SmartAI.cpp @@ -763,13 +763,6 @@ void SmartAI::JustRespawned() mFollowArrivedAlive = true; } -int SmartAI::Permissible(Creature const* creature) -{ - if (creature->GetAIName() == "SmartAI") - return PERMIT_BASE_SPECIAL; - return PERMIT_BASE_NO; -} - void SmartAI::JustReachedHome() { GetScript()->OnReset(); @@ -1133,13 +1126,6 @@ void SmartGameObjectAI::SummonedCreatureDies(Creature* summon, Unit* /*killer*/) GetScript()->ProcessEventsFor(SMART_EVENT_SUMMONED_UNIT_DIES, summon); } -int SmartGameObjectAI::Permissible(GameObject const* g) -{ - if (g->GetAIName() == "SmartGameObjectAI") - return PERMIT_BASE_SPECIAL; - return PERMIT_BASE_NO; -} - void SmartGameObjectAI::UpdateAI(uint32 diff) { GetScript()->OnUpdate(diff); diff --git a/src/server/game/AI/SmartScripts/SmartAI.h b/src/server/game/AI/SmartScripts/SmartAI.h index 7bc589ec5..38b07a19b 100644 --- a/src/server/game/AI/SmartScripts/SmartAI.h +++ b/src/server/game/AI/SmartScripts/SmartAI.h @@ -164,7 +164,7 @@ public: ObjectGuid GetGUID(int32 id = 0) const override; //core related - static int32 Permissible(Creature const*); + static int32 Permissible(Creature const* /*creature*/) { return PERMIT_BASE_NO; } // Called at movepoint reached void MovepointReached(uint32 id); @@ -259,7 +259,7 @@ public: void InitializeAI() override; void Reset() override; SmartScript* GetScript() { return &mScript; } - static int32 Permissible(GameObject const* g); + static int32 Permissible(GameObject const* /*go*/) { return PERMIT_BASE_NO; } bool GossipHello(Player* player, bool reportUse) override; bool GossipSelect(Player* player, uint32 sender, uint32 action) override; diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index 6af1be441..ecacbf3b3 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -1020,7 +1020,7 @@ bool Creature::AIM_Initialize(CreatureAI* ai) // Xinef: called in add to world //Motion_Initialize(); - i_AI = ai ? ai : FactorySelector::selectAI(this); + i_AI = ai ? ai : FactorySelector::SelectAI(this); delete oldAI; IsAIEnabled = true; i_AI->InitializeAI(); @@ -2860,7 +2860,7 @@ uint8 Creature::getLevelForTarget(WorldObject const* target) const return uint8(level); } -std::string Creature::GetAIName() const +std::string const& Creature::GetAIName() const { return sObjectMgr->GetCreatureTemplate(GetEntry())->AIName; } diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h index e404dcc83..b1fd4eea4 100644 --- a/src/server/game/Entities/Creature/Creature.h +++ b/src/server/game/Entities/Creature/Creature.h @@ -198,7 +198,7 @@ public: void SetDetectionDistance(float dist){ m_detectionDistance = dist; } [[nodiscard]] CreatureAddon const* GetCreatureAddon() const; - [[nodiscard]] std::string GetAIName() const; + [[nodiscard]] std::string const& GetAIName() const; [[nodiscard]] std::string GetScriptName() const; [[nodiscard]] uint32 GetScriptId() const; diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp index be992f4fe..2a75ff688 100644 --- a/src/server/game/Entities/GameObject/GameObject.cpp +++ b/src/server/game/Entities/GameObject/GameObject.cpp @@ -96,7 +96,7 @@ bool GameObject::AIM_Initialize() return true; } -std::string GameObject::GetAIName() const +std::string const& GameObject::GetAIName() const { return sObjectMgr->GetGameObjectTemplate(GetEntry())->AIName; } diff --git a/src/server/game/Entities/GameObject/GameObject.h b/src/server/game/Entities/GameObject/GameObject.h index bd8500f97..a13a1be39 100644 --- a/src/server/game/Entities/GameObject/GameObject.h +++ b/src/server/game/Entities/GameObject/GameObject.h @@ -1000,7 +1000,7 @@ public: [[nodiscard]] virtual uint32 GetScriptId() const; [[nodiscard]] GameObjectAI* AI() const { return m_AI; } - [[nodiscard]] std::string GetAIName() const; + [[nodiscard]] std::string const& GetAIName() const; void SetDisplayId(uint32 displayid); [[nodiscard]] uint32 GetDisplayId() const { return GetUInt32Value(GAMEOBJECT_DISPLAYID); } diff --git a/src/server/game/Movement/MotionMaster.cpp b/src/server/game/Movement/MotionMaster.cpp index 6d2cdcb95..fe8075ddb 100644 --- a/src/server/game/Movement/MotionMaster.cpp +++ b/src/server/game/Movement/MotionMaster.cpp @@ -32,6 +32,11 @@ #include "TargetedMovementGenerator.h" #include "WaypointMovementGenerator.h" +inline MovementGenerator* GetIdleMovementGenerator() +{ + return sMovementGeneratorRegistry->GetRegistryItem(IDLE_MOTION_TYPE)->Create(); +} + // ---- ChaseRange ---- // ChaseRange::ChaseRange(float range) : MinRange(range > CONTACT_DISTANCE ? 0 : range - CONTACT_DISTANCE), MinTolerance(range), MaxRange(range + CONTACT_DISTANCE), MaxTolerance(range) { } @@ -59,9 +64,9 @@ bool ChaseAngle::IsAngleOkay(float relativeAngle) const return (std::min(diff, float(2 * M_PI) - diff) <= Tolerance); } -inline bool isStatic(MovementGenerator* mv) +inline bool isStatic(MovementGenerator* movement) { - return (mv == &si_idleMovement); + return (movement == GetIdleMovementGenerator()); } void MotionMaster::Initialize() @@ -80,16 +85,7 @@ void MotionMaster::Initialize() // set new default movement generator void MotionMaster::InitDefault() { - // Xinef: Do not allow to initialize any motion generator for dead creatures - if (_owner->GetTypeId() == TYPEID_UNIT && _owner->IsAlive()) - { - MovementGenerator* movement = FactorySelector::selectMovementGenerator(_owner->ToCreature()); - Mutate(!movement ? &si_idleMovement : movement, MOTION_SLOT_IDLE); - } - else - { - Mutate(&si_idleMovement, MOTION_SLOT_IDLE); - } + Mutate(FactorySelector::SelectMovementGenerator(_owner), MOTION_SLOT_IDLE); } MotionMaster::~MotionMaster() @@ -236,7 +232,7 @@ void MotionMaster::MoveIdle() { //! Should be preceded by MovementExpired or Clear if there's an overlying movementgenerator active if (empty() || !isStatic(top())) - Mutate(&si_idleMovement, MOTION_SLOT_IDLE); + Mutate(GetIdleMovementGenerator(), MOTION_SLOT_IDLE); } void MotionMaster::MoveRandom(float wanderDistance) diff --git a/src/server/game/Movement/MovementGenerator.cpp b/src/server/game/Movement/MovementGenerator.cpp index 3e80ab121..a14578b26 100644 --- a/src/server/game/Movement/MovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerator.cpp @@ -16,7 +16,14 @@ */ #include "MovementGenerator.h" +#include "IdleMovementGenerator.h" MovementGenerator::~MovementGenerator() { } + +MovementGenerator* IdleMovementFactory::Create(Unit* /*object*/) const +{ + static IdleMovementGenerator instance; + return &instance; +} diff --git a/src/server/game/Movement/MovementGenerator.h b/src/server/game/Movement/MovementGenerator.h index 5ea148e2c..2f317ec48 100644 --- a/src/server/game/Movement/MovementGenerator.h +++ b/src/server/game/Movement/MovementGenerator.h @@ -82,19 +82,28 @@ public: } }; -struct SelectableMovement : public FactoryHolder +typedef FactoryHolder MovementGeneratorCreator; + +template +struct MovementGeneratorFactory : public MovementGeneratorCreator { - SelectableMovement(MovementGeneratorType mgt) : FactoryHolder(mgt) {} + MovementGeneratorFactory(MovementGeneratorType movementGeneratorType) : MovementGeneratorCreator(movementGeneratorType) { } + + MovementGenerator* Create(Unit* /*object*/) const + { + return new Movement(); + } }; -template -struct MovementGeneratorFactory : public SelectableMovement +struct IdleMovementFactory : public MovementGeneratorCreator { - MovementGeneratorFactory(MovementGeneratorType mgt) : SelectableMovement(mgt) {} + IdleMovementFactory() : MovementGeneratorCreator(IDLE_MOTION_TYPE) { } - MovementGenerator* Create(void*) const; + MovementGenerator* Create(Unit* object) const override; }; -typedef FactoryHolder MovementGeneratorCreator; -typedef FactoryHolder::FactoryHolderRegistry MovementGeneratorRegistry; +typedef MovementGeneratorCreator::FactoryHolderRegistry MovementGeneratorRegistry; + +#define sMovementGeneratorRegistry MovementGeneratorRegistry::instance() + #endif diff --git a/src/server/game/Movement/MovementGeneratorImpl.h b/src/server/game/Movement/MovementGeneratorImpl.h deleted file mode 100644 index d566fbbcb..000000000 --- a/src/server/game/Movement/MovementGeneratorImpl.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * This file is part of the AzerothCore 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 Affero General Public License as published by the - * Free Software Foundation; either version 3 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 Affero 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 . - */ - -#ifndef ACORE_MOVEMENTGENERATOR_IMPL_H -#define ACORE_MOVEMENTGENERATOR_IMPL_H - -#include "MovementGenerator.h" - -template -inline MovementGenerator* -MovementGeneratorFactory::Create(void* /*data*/) const -{ - return (new MOVEMENT_GEN()); -} -#endif diff --git a/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.cpp index da3058c76..5f64daef3 100644 --- a/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.cpp @@ -19,8 +19,6 @@ #include "Creature.h" #include "CreatureAI.h" -IdleMovementGenerator si_idleMovement; - // StopMoving is needed to make unit stop if its last movement generator expires // But it should not be sent otherwise there are many redundent packets void IdleMovementGenerator::Initialize(Unit* owner) diff --git a/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.h b/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.h index b1571f66d..293862bdd 100644 --- a/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.h +++ b/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.h @@ -30,8 +30,6 @@ public: MovementGeneratorType GetMovementGeneratorType() override { return IDLE_MOTION_TYPE; } }; -extern IdleMovementGenerator si_idleMovement; - class RotateMovementGenerator : public MovementGenerator { public: diff --git a/src/tools/mmaps_generator/MapBuilder.cpp b/src/tools/mmaps_generator/MapBuilder.cpp index 3ca17f2ed..c2e846396 100644 --- a/src/tools/mmaps_generator/MapBuilder.cpp +++ b/src/tools/mmaps_generator/MapBuilder.cpp @@ -16,10 +16,14 @@ */ #include "MapBuilder.h" +#include "IntermediateValues.h" #include "MapDefines.h" #include "MapTree.h" #include "ModelInstance.h" #include "PathCommon.h" +#include "StringFormat.h" +#include "VMapFactory.h" +#include "VMapMgr2.h" #include #include #include From 6ac7dfa26f40c133495e9cd178275a3a7e0af72e Mon Sep 17 00:00:00 2001 From: IntelligentQuantum Date: Mon, 18 Jul 2022 13:45:57 +0430 Subject: [PATCH 005/130] refactor(Core/SmartScripts): GetTargets returns ObjectList instead of ObjectList* (#11950) --- src/server/game/AI/SmartScripts/SmartAI.cpp | 19 +- .../game/AI/SmartScripts/SmartScript.cpp | 5536 +++++++---------- src/server/game/AI/SmartScripts/SmartScript.h | 52 +- .../game/AI/SmartScripts/SmartScriptMgr.cpp | 90 +- .../game/AI/SmartScripts/SmartScriptMgr.h | 117 +- 5 files changed, 2505 insertions(+), 3309 deletions(-) diff --git a/src/server/game/AI/SmartScripts/SmartAI.cpp b/src/server/game/AI/SmartScripts/SmartAI.cpp index 34a6111d4..0b4541985 100644 --- a/src/server/game/AI/SmartScripts/SmartAI.cpp +++ b/src/server/game/AI/SmartScripts/SmartAI.cpp @@ -297,12 +297,12 @@ void SmartAI::EndPath(bool fail) mEscortNPCFlags = 0; } - ObjectList* targets = GetScript()->GetTargetList(SMART_ESCORT_TARGETS); + ObjectVector const* targets = GetScript()->GetStoredTargetVector(SMART_ESCORT_TARGETS); if (targets && mEscortQuestID) { if (targets->size() == 1 && GetScript()->IsPlayer((*targets->begin()))) { - Player* player = (*targets->begin())->ToPlayer(); + Player* player = targets->front()->ToPlayer(); if (Group* group = player->GetGroup()) { for (GroupReference* groupRef = group->GetFirstMember(); groupRef != nullptr; groupRef = groupRef->next()) @@ -327,11 +327,11 @@ void SmartAI::EndPath(bool fail) } else { - for (ObjectList::iterator iter = targets->begin(); iter != targets->end(); ++iter) + for (WorldObject* target : *targets) { - if (GetScript()->IsPlayer((*iter))) + if (GetScript()->IsPlayer(target)) { - Player* player = (*iter)->ToPlayer(); + Player* player = target->ToPlayer(); if (!fail && player->IsAtGroupRewardDistance(me) && !player->HasCorpse()) player->AreaExploredOrEventHappens(mEscortQuestID); else if (fail && player->GetQuestStatus(mEscortQuestID) == QUEST_STATUS_INCOMPLETE) @@ -535,8 +535,7 @@ void SmartAI::UpdateAI(uint32 diff) bool SmartAI::IsEscortInvokerInRange() { - ObjectList* targets = GetScript()->GetTargetList(SMART_ESCORT_TARGETS); - if (targets) + if (ObjectVector const* targets = GetScript()->GetStoredTargetVector(SMART_ESCORT_TARGETS)) { float checkDist = me->GetInstanceScript() ? SMART_ESCORT_MAX_PLAYER_DIST * 2 : SMART_ESCORT_MAX_PLAYER_DIST; if (targets->size() == 1 && GetScript()->IsPlayer((*targets->begin()))) @@ -558,11 +557,11 @@ bool SmartAI::IsEscortInvokerInRange() } else { - for (ObjectList::iterator iter = targets->begin(); iter != targets->end(); ++iter) + for (WorldObject* target : *targets) { - if (GetScript()->IsPlayer((*iter))) + if (GetScript()->IsPlayer(target)) { - if (me->GetDistance((*iter)->ToPlayer()) <= checkDist) + if (me->GetDistance(target->ToPlayer()) <= checkDist) return true; } } diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp index d1da549cf..5c304cfab 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.cpp +++ b/src/server/game/AI/SmartScripts/SmartScript.cpp @@ -44,7 +44,6 @@ SmartScript::SmartScript() trigger = nullptr; mEventPhase = 0; mPathId = 0; - mTargetStorage = new ObjectListMap(); mTextTimer = 0; mLastTextID = 0; mUseTextTimer = false; @@ -66,11 +65,7 @@ SmartScript::SmartScript() SmartScript::~SmartScript() { - for (ObjectListMap::iterator itr = mTargetStorage->begin(); itr != mTargetStorage->end(); ++itr) - delete itr->second; - delete mTargetStorage; - mCounterList.clear(); } void SmartScript::OnReset() @@ -135,1759 +130,1456 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u bool isControlled = e.action.moveToPos.controlled > 0; + ObjectVector targets; + GetTargets(targets, e, unit); + switch (e.GetActionType()) { case SMART_ACTION_TALK: + { + Creature* talker = e.target.type == 0 ? me : nullptr; + Unit* talkTarget = nullptr; + + for (WorldObject* target : targets) { - ObjectList* targets = GetTargets(e, unit); - Creature* talker = e.target.type == 0 ? me : nullptr; - Unit* talkTarget = nullptr; - if (targets) + if (IsCreature((target)) && !target->ToCreature()->IsPet()) // Prevented sending text to pets. { - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) + if (e.action.talk.useTalkTarget) { - if (IsCreature((*itr)) && !(*itr)->ToCreature()->IsPet()) // Prevented sending text to pets. - { - if (e.action.talk.useTalkTarget) - { - talker = me; - talkTarget = (*itr)->ToCreature(); - } - else - talker = (*itr)->ToCreature(); - break; - } - else if (IsPlayer((*itr))) - { - talker = me; // xinef: added - talkTarget = (*itr)->ToPlayer(); - break; - } + talker = me; + talkTarget = target->ToCreature(); } - - delete targets; - } - - if (!talkTarget) - talkTarget = GetLastInvoker(); - - if (!talker) + else + talker = target->ToCreature(); break; - - if (!sCreatureTextMgr->TextExist(talker->GetEntry(), uint8(e.action.talk.textGroupID))) + } + else if (IsPlayer((target))) { - LOG_ERROR("sql.sql", "SmartScript::ProcessAction: SMART_ACTION_TALK: EntryOrGuid {} SourceType {} EventType {} TargetType {} using non-existent Text id {} for talker {}, ignored.", e.entryOrGuid, e.GetScriptType(), e.GetEventType(), e.GetTargetType(), e.action.talk.textGroupID, talker->GetEntry()); + talker = me; // xinef: added + talkTarget = target->ToPlayer(); break; } + } - mTalkerEntry = talker->GetEntry(); - mLastTextID = e.action.talk.textGroupID; - mTextTimer = e.action.talk.duration; - mUseTextTimer = true; - sCreatureTextMgr->SendChat(talker, uint8(e.action.talk.textGroupID), talkTarget); - LOG_DEBUG("sql.sql", "SmartScript::ProcessAction: SMART_ACTION_TALK: talker: {} ({}), textId: {}", talker->GetName(), talker->GetGUID().ToString(), mLastTextID); + if (!talkTarget) + talkTarget = GetLastInvoker(); + + if (!talker) + break; + + if (!sCreatureTextMgr->TextExist(talker->GetEntry(), uint8(e.action.talk.textGroupID))) + { + LOG_ERROR("sql.sql", "SmartScript::ProcessAction: SMART_ACTION_TALK: EntryOrGuid {} SourceType {} EventType {} TargetType {} using non-existent Text id {} for talker {}, ignored.", e.entryOrGuid, e.GetScriptType(), e.GetEventType(), e.GetTargetType(), e.action.talk.textGroupID, talker->GetEntry()); break; } + + mTalkerEntry = talker->GetEntry(); + mLastTextID = e.action.talk.textGroupID; + mTextTimer = e.action.talk.duration; + mUseTextTimer = true; + sCreatureTextMgr->SendChat(talker, uint8(e.action.talk.textGroupID), talkTarget); + LOG_DEBUG("sql.sql", "SmartScript::ProcessAction: SMART_ACTION_TALK: talker: {} ({}), textId: {}", talker->GetName(), talker->GetGUID().ToString(), mLastTextID); + break; + } case SMART_ACTION_SIMPLE_TALK: + { + for (WorldObject* target : targets) { - ObjectList* targets = GetTargets(e, unit); - if (targets) + if (IsCreature(target)) + sCreatureTextMgr->SendChat(target->ToCreature(), uint8(e.action.simpleTalk.textGroupID), IsPlayer(GetLastInvoker()) ? GetLastInvoker() : 0); + else if (IsPlayer(target) && me) { - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - { - if (IsCreature(*itr)) - sCreatureTextMgr->SendChat((*itr)->ToCreature(), uint8(e.action.simpleTalk.textGroupID), IsPlayer(GetLastInvoker()) ? GetLastInvoker() : 0); - else if (IsPlayer(*itr) && me) - { - Unit* templastInvoker = GetLastInvoker(); - sCreatureTextMgr->SendChat(me, uint8(e.action.simpleTalk.textGroupID), IsPlayer(templastInvoker) ? templastInvoker : 0, CHAT_MSG_ADDON, LANG_ADDON, TEXT_RANGE_NORMAL, 0, TEAM_NEUTRAL, false, (*itr)->ToPlayer()); - } - - LOG_DEBUG("sql.sql", "SmartScript::ProcessAction:: SMART_ACTION_SIMPLE_TALK: talker: {} ({}), textGroupId: {}", - (*itr)->GetName(), (*itr)->GetGUID().ToString(), uint8(e.action.simpleTalk.textGroupID)); - } - - delete targets; + Unit* templastInvoker = GetLastInvoker(); + sCreatureTextMgr->SendChat(me, uint8(e.action.simpleTalk.textGroupID), IsPlayer(templastInvoker) ? templastInvoker : 0, CHAT_MSG_ADDON, LANG_ADDON, TEXT_RANGE_NORMAL, 0, TEAM_NEUTRAL, false, target->ToPlayer()); } - break; + + LOG_DEBUG("sql.sql", "SmartScript::ProcessAction:: SMART_ACTION_SIMPLE_TALK: talker: {} ({}), textGroupId: {}", + target->GetName(), target->GetGUID().ToString(), uint8(e.action.simpleTalk.textGroupID)); } + break; + } case SMART_ACTION_PLAY_EMOTE: + { + for (WorldObject* target : targets) { - ObjectList* targets = GetTargets(e, unit); - if (targets) + if (IsUnit(target)) { - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - { - if (IsUnit(*itr)) - { - (*itr)->ToUnit()->HandleEmoteCommand(e.action.emote.emote); - LOG_DEBUG("sql.sql", "SmartScript::ProcessAction:: SMART_ACTION_PLAY_EMOTE: target: {} ({}), emote: {}", - (*itr)->GetName(), (*itr)->GetGUID().ToString(), e.action.emote.emote); - } - } - - delete targets; + target->ToUnit()->HandleEmoteCommand(e.action.emote.emote); + LOG_DEBUG("sql.sql", "SmartScript::ProcessAction:: SMART_ACTION_PLAY_EMOTE: target: {} ({}), emote: {}", + target->GetName(), target->GetGUID().ToString(), e.action.emote.emote); } - break; } + break; + } case SMART_ACTION_SOUND: + { + for (WorldObject* target : targets) { - ObjectList* targets = GetTargets(e, unit); - if (targets) + if (IsUnit(target)) { - for (auto& target : *targets) - { - if (IsUnit(target)) - { - if (e.action.sound.distance == 1) - target->PlayDistanceSound(e.action.sound.sound, e.action.sound.onlySelf ? target->ToPlayer() : nullptr); - else - target->PlayDirectSound(e.action.sound.sound, e.action.sound.onlySelf ? target->ToPlayer() : nullptr); - LOG_DEBUG("sql.sql", "SmartScript::ProcessAction:: SMART_ACTION_SOUND: target: {} ({}), sound: {}, onlyself: {}", - target->GetName(), target->GetGUID().ToString(), e.action.sound.sound, e.action.sound.onlySelf); - } - } - - delete targets; + if (e.action.sound.distance == 1) + target->PlayDistanceSound(e.action.sound.sound, e.action.sound.onlySelf ? target->ToPlayer() : nullptr); + else + target->PlayDirectSound(e.action.sound.sound, e.action.sound.onlySelf ? target->ToPlayer() : nullptr); + LOG_DEBUG("sql.sql", "SmartScript::ProcessAction:: SMART_ACTION_SOUND: target: {} ({}), sound: {}, onlyself: {}", + target->GetName(), target->GetGUID().ToString(), e.action.sound.sound, e.action.sound.onlySelf); } + } + break; + } + case SMART_ACTION_RANDOM_SOUND: + { + uint32 sounds[4]; + sounds[0] = e.action.randomSound.sound1; + sounds[1] = e.action.randomSound.sound2; + sounds[2] = e.action.randomSound.sound3; + sounds[3] = e.action.randomSound.sound4; + uint32 temp[4]; + uint32 count = 0; + for (unsigned int sound : sounds) + { + if (sound) + { + temp[count] = sound; + ++count; + } + } + + if (count == 0) + { break; } - case SMART_ACTION_RANDOM_SOUND: - { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - uint32 sounds[4]; - sounds[0] = e.action.randomSound.sound1; - sounds[1] = e.action.randomSound.sound2; - sounds[2] = e.action.randomSound.sound3; - sounds[3] = e.action.randomSound.sound4; - uint32 temp[4]; - uint32 count = 0; - for (uint8 i = 0; i < 4; i++) + for (WorldObject* target : targets) + { + if (IsUnit(target)) { - if (sounds[i]) + uint32 sound = temp[urand(0, count - 1)]; + target->PlayDirectSound(sound, e.action.randomSound.onlySelf ? target->ToPlayer() : nullptr); + LOG_DEBUG("sql.sql", "SmartScript::ProcessAction:: SMART_ACTION_RANDOM_SOUND: target: {} ({}), sound: {}, onlyself: {}", + target->GetName(), target->GetGUID().ToString(), sound, e.action.randomSound.onlySelf); + } + } + + break; + } + case SMART_ACTION_MUSIC: + { + ObjectVector targets; + + if (e.action.music.type > 0) + { + if (me && me->FindMap()) + { + Map::PlayerList const& players = me->GetMap()->GetPlayers(); + + if (!players.IsEmpty()) { - temp[count] = sounds[i]; - ++count; + for (Map::PlayerList::const_iterator i = players.begin(); i != players.end(); ++i) + if (Player* player = i->GetSource()) + { + if (player->GetZoneId() == me->GetZoneId()) + { + if (e.action.music.type > 1) + { + if (player->GetAreaId() == me->GetAreaId()) + targets.push_back(player); + } + else + targets.push_back(player); + } + } } } + } + else + GetTargets(targets, e); - if (count == 0) - { - delete targets; - break; - } - - for (auto& target : *targets) + if (!targets.empty()) + { + for (WorldObject* target : targets) { if (IsUnit(target)) { - uint32 sound = temp[urand(0, count - 1)]; - if (e.action.randomSound.distance == 1) - target->PlayDistanceSound(sound, e.action.randomSound.onlySelf ? target->ToPlayer() : nullptr); - else - target->PlayDirectSound(sound, e.action.randomSound.onlySelf ? target->ToPlayer() : nullptr); - LOG_DEBUG("sql.sql", "SmartScript::ProcessAction:: SMART_ACTION_RANDOM_SOUND: target: {} ({}), sound: {}, onlyself: {}", - target->GetName(), target->GetGUID().ToString(), sound, e.action.randomSound.onlySelf); + target->SendPlayMusic(e.action.music.sound, e.action.music.onlySelf > 0); + LOG_DEBUG("sql.sql", "SmartScript::ProcessAction:: SMART_ACTION_MUSIC: target: {} ({}), sound: {}, onlySelf: {}, type: {}", + target->GetName(), target->GetGUID().ToString(), e.action.music.sound, e.action.music.onlySelf, e.action.music.type); } } - - delete targets; - break; - } - case SMART_ACTION_MUSIC: - { - ObjectList* targets = nullptr; - - if (e.action.music.type > 0) - { - if (me && me->FindMap()) - { - Map::PlayerList const& players = me->GetMap()->GetPlayers(); - targets = new ObjectList(); - - if (!players.IsEmpty()) - { - for (Map::PlayerList::const_iterator i = players.begin(); i != players.end(); ++i) - if (Player* player = i->GetSource()) - { - if (player->GetZoneId() == me->GetZoneId()) - { - if (e.action.music.type > 1) - { - if (player->GetAreaId() == me->GetAreaId()) - targets->push_back(player); - } - else - targets->push_back(player); - } - } - } - } - } - else - targets = GetTargets(e, unit); - - if (targets) - { - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - { - if (IsUnit(*itr)) - { - (*itr)->SendPlayMusic(e.action.music.sound, e.action.music.onlySelf > 0); - LOG_DEBUG("sql.sql", "SmartScript::ProcessAction:: SMART_ACTION_MUSIC: target: {} ({}), sound: {}, onlySelf: {}, type: {}", - (*itr)->GetName(), (*itr)->GetGUID().ToString(), e.action.music.sound, e.action.music.onlySelf, e.action.music.type); - } - } - - delete targets; - } - break; } + break; + } case SMART_ACTION_RANDOM_MUSIC: + { + ObjectVector targets; + + if (e.action.randomMusic.type > 0) { - ObjectList* targets = nullptr; - - if (e.action.randomMusic.type > 0) + if (me && me->FindMap()) { - if (me && me->FindMap()) - { - Map::PlayerList const& players = me->GetMap()->GetPlayers(); - targets = new ObjectList(); + Map::PlayerList const& players = me->GetMap()->GetPlayers(); - if (!players.IsEmpty()) - { - for (Map::PlayerList::const_iterator i = players.begin(); i != players.end(); ++i) - if (Player* player = i->GetSource()) + if (!players.IsEmpty()) + { + for (Map::PlayerList::const_iterator i = players.begin(); i != players.end(); ++i) + if (Player* player = i->GetSource()) + { + if (player->GetZoneId() == me->GetZoneId()) { - if (player->GetZoneId() == me->GetZoneId()) + if (e.action.randomMusic.type > 1) { - if (e.action.randomMusic.type > 1) - { - if (player->GetAreaId() == me->GetAreaId()) - targets->push_back(player); - } - else - targets->push_back(player); + if (player->GetAreaId() == me->GetAreaId()) + targets.push_back(player); } + else + targets.push_back(player); } - } + } } } - else - targets = GetTargets(e, unit); + } + else + GetTargets(targets, e); - if (!targets) - break; + if (targets.empty()) + break; - uint32 sounds[4]; - sounds[0] = e.action.randomMusic.sound1; - sounds[1] = e.action.randomMusic.sound2; - sounds[2] = e.action.randomMusic.sound3; - sounds[3] = e.action.randomMusic.sound4; - uint32 temp[4]; - uint32 count = 0; - for (uint8 i = 0; i < 4; i++) + uint32 sounds[4]; + sounds[0] = e.action.randomMusic.sound1; + sounds[1] = e.action.randomMusic.sound2; + sounds[2] = e.action.randomMusic.sound3; + sounds[3] = e.action.randomMusic.sound4; + uint32 temp[4]; + uint32 count = 0; + for (unsigned int sound : sounds) + { + if (sound) { - if (sounds[i]) - { - temp[count] = sounds[i]; - ++count; - } + temp[count] = sound; + ++count; } + } - if (count == 0) - { - delete targets; - break; - } - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - { - if (IsUnit(*itr)) - { - uint32 sound = temp[urand(0, count - 1)]; - (*itr)->SendPlayMusic(sound, e.action.randomMusic.onlySelf > 0); - LOG_DEBUG("sql.sql", "SmartScript::ProcessAction:: SMART_ACTION_RANDOM_MUSIC: target: {} ({}), sound: {}, onlyself: {}, type: {}", - (*itr)->GetName(), (*itr)->GetGUID().ToString(), sound, e.action.randomMusic.onlySelf, e.action.randomMusic.type); - } - } - - delete targets; + if (count == 0) + { break; } + + for (WorldObject* target : targets) + { + if (IsUnit(target)) + { + uint32 sound = temp[urand(0, count - 1)]; + target->SendPlayMusic(sound, e.action.randomMusic.onlySelf > 0); + LOG_DEBUG("sql.sql", "SmartScript::ProcessAction:: SMART_ACTION_RANDOM_MUSIC: target: {} ({}), sound: {}, onlyself: {}, type: {}", + target->GetName(), target->GetGUID().ToString(), sound, e.action.randomMusic.onlySelf, e.action.randomMusic.type); + } + } + + break; + } case SMART_ACTION_SET_FACTION: + { + for (WorldObject* target : targets) { - ObjectList* targets = GetTargets(e, unit); - if (targets) + if (IsCreature(target)) { - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) + if (e.action.faction.factionID) { - if (IsCreature(*itr)) + target->ToCreature()->SetFaction(e.action.faction.factionID); + LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_SET_FACTION: Creature entry {}, GuidLow {} set faction to {}", + target->GetEntry(), target->GetGUID().ToString(), e.action.faction.factionID); + } + else + { + if (CreatureTemplate const* ci = sObjectMgr->GetCreatureTemplate(target->ToCreature()->GetEntry())) { - if (e.action.faction.factionID) + if (target->ToCreature()->GetFaction() != ci->faction) { - (*itr)->ToCreature()->SetFaction(e.action.faction.factionID); - LOG_DEBUG("sql.sql", "SmartScript::ProcessAction:: SMART_ACTION_SET_FACTION: Creature entry {} ({}) set faction to {}", - (*itr)->GetEntry(), (*itr)->GetGUID().ToString(), e.action.faction.factionID); + target->ToCreature()->SetFaction(ci->faction); + LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_SET_FACTION: Creature entry {}, GuidLow {} set faction to {}", + target->GetEntry(), target->GetGUID().ToString(), ci->faction); } - else + } + } + } + } + break; + } + case SMART_ACTION_MORPH_TO_ENTRY_OR_MODEL: + { + for (WorldObject* target : targets) + { + if (!IsCreature(target)) + continue; + + if (e.action.morphOrMount.creature || e.action.morphOrMount.model) + { + //set model based on entry from creature_template + if (e.action.morphOrMount.creature) + { + if (CreatureTemplate const* ci = sObjectMgr->GetCreatureTemplate(e.action.morphOrMount.creature)) + { + uint32 displayId = ObjectMgr::ChooseDisplayId(ci); + target->ToCreature()->SetDisplayId(displayId); + LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_MORPH_TO_ENTRY_OR_MODEL: Creature entry {}, GuidLow {} set displayid to {}", + target->GetEntry(), target->GetGUID().ToString(), displayId); + } + } + //if no param1, then use value from param2 (modelId) + else + { + target->ToCreature()->SetDisplayId(e.action.morphOrMount.model); + LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_MORPH_TO_ENTRY_OR_MODEL: Creature entry {}, GuidLow {} set displayid to {}", + target->GetEntry(), target->GetGUID().ToString(), e.action.morphOrMount.model); + } + } + else + { + target->ToCreature()->DeMorph(); + LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_MORPH_TO_ENTRY_OR_MODEL: Creature entry {}, GuidLow {} demorphs.", + target->GetEntry(), target->GetGUID().ToString()); + } + } + break; + } + case SMART_ACTION_FAIL_QUEST: + { + for (WorldObject* target : targets) + { + if (IsPlayer(target)) + { + target->ToPlayer()->FailQuest(e.action.quest.quest); + LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_FAIL_QUEST: Player guidLow {} fails quest {}", + target->GetGUID().ToString(), e.action.quest.quest); + } + } + break; + } + case SMART_ACTION_OFFER_QUEST: + { + for (WorldObject* target : targets) + { + if (Player* player = target->ToPlayer()) + { + if (Quest const* q = sObjectMgr->GetQuestTemplate(e.action.questOffer.questID)) + { + if (me && e.action.questOffer.directAdd == 0) + { + if (player->CanTakeQuest(q, true)) { - if (CreatureTemplate const* ci = sObjectMgr->GetCreatureTemplate((*itr)->ToCreature()->GetEntry())) + if (WorldSession* session = player->GetSession()) { - if ((*itr)->ToCreature()->GetFaction() != ci->faction) - { - (*itr)->ToCreature()->SetFaction(ci->faction); - LOG_DEBUG("sql.sql", "SmartScript::ProcessAction:: SMART_ACTION_SET_FACTION: Creature entry {} ({}) set faction to {}", - (*itr)->GetEntry(), (*itr)->GetGUID().ToString(), ci->faction); - } + PlayerMenu menu(session); + menu.SendQuestGiverQuestDetails(q, me->GetGUID(), true); + LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_OFFER_QUEST: Player guidLow {} - offering quest {}", + player->GetGUID().ToString(), e.action.questOffer.questID); } } } - } - - delete targets; - } - break; - } - case SMART_ACTION_MORPH_TO_ENTRY_OR_MODEL: - { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - { - if (!IsCreature(*itr)) - continue; - - if (e.action.morphOrMount.creature || e.action.morphOrMount.model) - { - //set model based on entry from creature_template - if (e.action.morphOrMount.creature) - { - if (CreatureTemplate const* ci = sObjectMgr->GetCreatureTemplate(e.action.morphOrMount.creature)) - { - uint32 displayId = ObjectMgr::ChooseDisplayId(ci); - (*itr)->ToCreature()->SetDisplayId(displayId); - LOG_DEBUG("sql.sql", "SmartScript::ProcessAction:: SMART_ACTION_MORPH_TO_ENTRY_OR_MODEL: Creature entry {} ({}) set displayid to {}", - (*itr)->GetEntry(), (*itr)->GetGUID().ToString(), displayId); - } - } - //if no param1, then use value from param2 (modelId) else { - (*itr)->ToCreature()->SetDisplayId(e.action.morphOrMount.model); - LOG_DEBUG("sql.sql", "SmartScript::ProcessAction:: SMART_ACTION_MORPH_TO_ENTRY_OR_MODEL: Creature entry {} ({}) set displayid to {}", - (*itr)->GetEntry(), (*itr)->GetGUID().ToString(), e.action.morphOrMount.model); - } - } - else - { - (*itr)->ToCreature()->DeMorph(); - LOG_DEBUG("sql.sql", "SmartScript::ProcessAction:: SMART_ACTION_MORPH_TO_ENTRY_OR_MODEL: Creature entry {} ({}) demorphs.", - (*itr)->GetEntry(), (*itr)->GetGUID().ToString()); - } - } - - delete targets; - break; - } - case SMART_ACTION_FAIL_QUEST: - { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - { - if (IsPlayer(*itr)) - { - (*itr)->ToPlayer()->FailQuest(e.action.quest.quest); - LOG_DEBUG("sql.sql", "SmartScript::ProcessAction:: SMART_ACTION_FAIL_QUEST: Player {} fails quest {}", - (*itr)->GetGUID().ToString(), e.action.quest.quest); - } - } - - delete targets; - break; - } - case SMART_ACTION_OFFER_QUEST: - { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - { - if (Player* pTarget = (*itr)->ToPlayer()) - { - if (Quest const* q = sObjectMgr->GetQuestTemplate(e.action.questOffer.questID)) - { - if (me && e.action.questOffer.directAdd == 0) - { - if (pTarget->CanTakeQuest(q, true)) - if (WorldSession* session = pTarget->GetSession()) - { - PlayerMenu menu(session); - menu.SendQuestGiverQuestDetails(q, me->GetGUID(), true); - LOG_DEBUG("sql.sql", "SmartScript::ProcessAction:: SMART_ACTION_OFFER_QUEST: Player {}- offering quest {}", - (*itr)->GetGUID().ToString(), e.action.questOffer.questID); - } - } - else - { - (*itr)->ToPlayer()->AddQuestAndCheckCompletion(q, nullptr); - LOG_DEBUG("sql.sql", "SmartScript::ProcessAction:: SMART_ACTION_OFFER_QUEST: Player {} - quest {} added", - (*itr)->GetGUID().ToString(), e.action.questOffer.questID); - } + player->AddQuestAndCheckCompletion(q, nullptr); + LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_OFFER_QUEST: Player guidLow {} - quest {} added", + player->GetGUID().ToString(), e.action.questOffer.questID); } } } - - delete targets; - break; } + break; + } case SMART_ACTION_SET_REACT_STATE: + { + for (WorldObject* target : targets) { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; + if (!IsCreature(target)) + continue; - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - { - if (!IsCreature(*itr)) - continue; - - (*itr)->ToCreature()->SetReactState(ReactStates(e.action.react.state)); - } - - delete targets; - break; + target->ToCreature()->SetReactState(ReactStates(e.action.react.state)); } + break; + } case SMART_ACTION_RANDOM_EMOTE: + { + std::vector emotes; + std::copy_if(e.action.randomEmote.emotes.begin(), e.action.randomEmote.emotes.end(), + std::back_inserter(emotes), [](uint32 emote) { return emote != 0; }); + + for (WorldObject* target : targets) { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - uint32 emotes[SMART_ACTION_PARAM_COUNT]; - emotes[0] = e.action.randomEmote.emote1; - emotes[1] = e.action.randomEmote.emote2; - emotes[2] = e.action.randomEmote.emote3; - emotes[3] = e.action.randomEmote.emote4; - emotes[4] = e.action.randomEmote.emote5; - emotes[5] = e.action.randomEmote.emote6; - uint32 temp[SMART_ACTION_PARAM_COUNT]; - uint32 count = 0; - for (uint8 i = 0; i < SMART_ACTION_PARAM_COUNT; i++) + if (IsUnit(target)) { - if (emotes[i]) - { - temp[count] = emotes[i]; - ++count; - } + uint32 emote = Acore::Containers::SelectRandomContainerElement(emotes); + target->ToUnit()->HandleEmoteCommand(emote); + LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_RANDOM_EMOTE: Creature guidLow {} handle random emote {}", + target->GetGUID().ToString(), emote); } - - if (count == 0) - { - delete targets; - break; - } - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - { - if (IsUnit(*itr)) - { - uint32 emote = temp[urand(0, count - 1)]; - (*itr)->ToUnit()->HandleEmoteCommand(emote); - LOG_DEBUG("sql.sql", "SmartScript::ProcessAction:: SMART_ACTION_RANDOM_EMOTE: Creature {} handle random emote {}", - (*itr)->GetGUID().ToString(), emote); - } - } - - delete targets; - break; } + break; + } case SMART_ACTION_THREAT_ALL_PCT: - { - if (!me) - break; - - ThreatContainer::StorageType threatList = me->GetThreatMgr().getThreatList(); - for (ThreatContainer::StorageType::const_iterator i = threatList.begin(); i != threatList.end(); ++i) - { - if (Unit* target = ObjectAccessor::GetUnit(*me, (*i)->getUnitGuid())) - { - me->GetThreatMgr().modifyThreatPercent(target, e.action.threatPCT.threatINC ? (int32)e.action.threatPCT.threatINC : -(int32)e.action.threatPCT.threatDEC); - LOG_DEBUG("sql.sql", "SmartScript::ProcessAction:: SMART_ACTION_THREAT_ALL_PCT: Creature {} modify threat for unit {}, value {}", - me->GetGUID().ToString(), target->GetGUID().ToString(), e.action.threatPCT.threatINC ? (int32)e.action.threatPCT.threatINC : -(int32)e.action.threatPCT.threatDEC); - } - } + { + if (!me) break; + + ThreatContainer::StorageType threatList = me->GetThreatMgr().getThreatList(); + for (ThreatContainer::StorageType::const_iterator i = threatList.begin(); i != threatList.end(); ++i) + { + if (Unit* target = ObjectAccessor::GetUnit(*me, (*i)->getUnitGuid())) + { + me->GetThreatMgr().modifyThreatPercent(target, e.action.threatPCT.threatINC ? (int32)e.action.threatPCT.threatINC : -(int32)e.action.threatPCT.threatDEC); + LOG_DEBUG("sql.sql", "SmartScript::ProcessAction:: SMART_ACTION_THREAT_ALL_PCT: Creature {} modify threat for unit {}, value {}", + me->GetGUID().ToString(), target->GetGUID().ToString(), e.action.threatPCT.threatINC ? (int32)e.action.threatPCT.threatINC : -(int32)e.action.threatPCT.threatDEC); + } } + break; + } case SMART_ACTION_THREAT_SINGLE_PCT: - { - if (!me) - break; - - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - { - if (IsUnit(*itr)) - { - me->GetThreatMgr().modifyThreatPercent((*itr)->ToUnit(), e.action.threatPCT.threatINC ? (int32)e.action.threatPCT.threatINC : -(int32)e.action.threatPCT.threatDEC); - LOG_DEBUG("sql.sql", "SmartScript::ProcessAction:: SMART_ACTION_THREAT_SINGLE_PCT: Creature {} modify threat for unit {}, value {}", - me->GetGUID().ToString(), (*itr)->GetGUID().ToString(), e.action.threatPCT.threatINC ? (int32)e.action.threatPCT.threatINC : -(int32)e.action.threatPCT.threatDEC); - } - } - - delete targets; + { + if (!me) break; + + for (WorldObject* target : targets) + { + if (IsUnit(target)) + { + me->GetThreatMgr().modifyThreatPercent(target->ToUnit(), e.action.threatPCT.threatINC ? (int32)e.action.threatPCT.threatINC : -(int32)e.action.threatPCT.threatDEC); + LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_THREAT_SINGLE_PCT: Creature guidLow {} modify threat for unit {}, value %i", + me->GetGUID().ToString(), target->GetGUID().ToString(), e.action.threatPCT.threatINC ? (int32)e.action.threatPCT.threatINC : -(int32)e.action.threatPCT.threatDEC); + } } + break; + } case SMART_ACTION_CALL_AREAEXPLOREDOREVENTHAPPENS: + { + for (WorldObject* target : targets) { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; + // Special handling for vehicles + if (IsUnit(target)) + if (Vehicle* vehicle = target->ToUnit()->GetVehicleKit()) + for (auto & Seat : vehicle->Seats) + if (Player* player = ObjectAccessor::GetPlayer(*target, Seat.second.Passenger.Guid)) + player->AreaExploredOrEventHappens(e.action.quest.quest); - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) + if (IsPlayer(target)) { - // Special handling for vehicles - if (IsUnit(*itr)) - { - if (Vehicle* vehicle = (*itr)->ToUnit()->GetVehicleKit()) - for (SeatMap::iterator it = vehicle->Seats.begin(); it != vehicle->Seats.end(); ++it) - if (Player* player = ObjectAccessor::GetPlayer(*(*itr), it->second.Passenger.Guid)) - player->AreaExploredOrEventHappens(e.action.quest.quest); + target->ToPlayer()->AreaExploredOrEventHappens(e.action.quest.quest); - if (Player* player = (*itr)->ToUnit()->GetCharmerOrOwnerPlayerOrPlayerItself()) - { - player->GroupEventHappens(e.action.quest.quest, GetBaseObject()); - LOG_DEBUG("sql.sql", "SmartScript::ProcessAction:: SMART_ACTION_CALL_AREAEXPLOREDOREVENTHAPPENS: Player {} credited quest {}", - (*itr)->GetGUID().ToString(), e.action.quest.quest); - } - } + LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_CALL_AREAEXPLOREDOREVENTHAPPENS: Player guidLow {} credited quest {}", + target->GetGUID().ToString(), e.action.quest.quest); } - - delete targets; - break; } + break; + } case SMART_ACTION_CAST: + { + if (targets.empty()) + break; + + Unit* caster = me; + // Areatrigger Cast! + if (e.GetScriptType() == SMART_SCRIPT_TYPE_AREATRIGGER) + caster = unit->SummonTrigger(unit->GetPositionX(), unit->GetPositionY(), unit->GetPositionZ(), unit->GetOrientation(), 5000); + + if (e.action.cast.targetsLimit > 0 && targets.size() > e.action.cast.targetsLimit) + Acore::Containers::RandomResize(targets, e.action.cast.targetsLimit); + + for (WorldObject* target : targets) { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - Unit* caster = me; - // Areatrigger Cast! - if (e.GetScriptType() == SMART_SCRIPT_TYPE_AREATRIGGER) - caster = unit->SummonTrigger(unit->GetPositionX(), unit->GetPositionY(), unit->GetPositionZ(), unit->GetOrientation(), 5000); - - if (e.action.cast.targetsLimit > 0 && targets->size() > e.action.cast.targetsLimit) - Acore::Containers::RandomResize(*targets, e.action.cast.targetsLimit); - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) + // may be nullptr + if (go) { - if (go) - { - // Xinef: may be nullptr! - go->CastSpell((*itr)->ToUnit(), e.action.cast.spell); - } - - if (!IsUnit(*itr)) - continue; - - if (caster && caster != me) // Areatrigger cast - { - caster->CastSpell((*itr)->ToUnit(), e.action.cast.spell, (e.action.cast.flags & SMARTCAST_TRIGGERED)); - } - else if (me && (!(e.action.cast.flags & SMARTCAST_AURA_NOT_PRESENT) || !(*itr)->ToUnit()->HasAura(e.action.cast.spell))) - { - if (e.action.cast.flags & SMARTCAST_INTERRUPT_PREVIOUS) - me->InterruptNonMeleeSpells(false); - - // Xinef: flag usable only if caster has max dist set - if ((e.action.cast.flags & SMARTCAST_COMBAT_MOVE) && GetCasterMaxDist() > 0.0f && me->GetMaxPower(GetCasterPowerType()) > 0) - { - // Xinef: check mana case only and operate movement accordingly, LoS and range is checked in targetet movement generator - SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(e.action.cast.spell); - int32 currentPower = me->GetPower(GetCasterPowerType()); - - if ((spellInfo && (currentPower < spellInfo->CalcPowerCost(me, spellInfo->GetSchoolMask()) || me->IsSpellProhibited(spellInfo->GetSchoolMask()))) || me->HasUnitFlag(UNIT_FLAG_SILENCED)) - { - SetCasterActualDist(0); - CAST_AI(SmartAI, me->AI())->SetForcedCombatMove(0); - } - else if (GetCasterActualDist() == 0.0f && me->GetPowerPct(GetCasterPowerType()) > 30.0f) - { - RestoreCasterMaxDist(); - CAST_AI(SmartAI, me->AI())->SetForcedCombatMove(GetCasterActualDist()); - } - } - - me->CastSpell((*itr)->ToUnit(), e.action.cast.spell, (e.action.cast.flags & SMARTCAST_TRIGGERED)); - } + go->CastSpell(target->ToUnit(), e.action.cast.spell); } - delete targets; - break; + if (!IsUnit(target)) + continue; + + if (caster && caster != me) // Areatrigger cast + { + caster->CastSpell(target->ToUnit(), e.action.cast.spell, (e.action.cast.flags & SMARTCAST_TRIGGERED)); + } + else if (me && (!(e.action.cast.flags & SMARTCAST_AURA_NOT_PRESENT) || !target->ToUnit()->HasAura(e.action.cast.spell))) + { + if (e.action.cast.flags & SMARTCAST_INTERRUPT_PREVIOUS) + me->InterruptNonMeleeSpells(false); + + // Xinef: flag usable only if caster has max dist set + if ((e.action.cast.flags & SMARTCAST_COMBAT_MOVE) && GetCasterMaxDist() > 0.0f && me->GetMaxPower(GetCasterPowerType()) > 0) + { + // Xinef: check mana case only and operate movement accordingly, LoS and range is checked in targetet movement generator + SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(e.action.cast.spell); + int32 currentPower = me->GetPower(GetCasterPowerType()); + + if ((spellInfo && (currentPower < spellInfo->CalcPowerCost(me, spellInfo->GetSchoolMask()) || me->IsSpellProhibited(spellInfo->GetSchoolMask()))) || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED)) + { + SetCasterActualDist(0); + CAST_AI(SmartAI, me->AI())->SetForcedCombatMove(0); + } + else if (GetCasterActualDist() == 0.0f && me->GetPowerPct(GetCasterPowerType()) > 30.0f) + { + RestoreCasterMaxDist(); + CAST_AI(SmartAI, me->AI())->SetForcedCombatMove(GetCasterActualDist()); + } + } + + me->CastSpell(target->ToUnit(), e.action.cast.spell, (e.action.cast.flags & SMARTCAST_TRIGGERED)); + } } + + break; + } case SMART_ACTION_INVOKER_CAST: - { - Unit* tempLastInvoker = GetLastInvoker(unit); // xinef: can be used for area triggers cast - if (!tempLastInvoker) - break; - - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - if (e.action.cast.targetsLimit > 0 && targets->size() > e.action.cast.targetsLimit) - Acore::Containers::RandomResize(*targets, e.action.cast.targetsLimit); - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - { - if (!IsUnit(*itr)) - continue; - - if (!(e.action.cast.flags & SMARTCAST_AURA_NOT_PRESENT) || !(*itr)->ToUnit()->HasAura(e.action.cast.spell)) - { - if (e.action.cast.flags & SMARTCAST_INTERRUPT_PREVIOUS) - tempLastInvoker->InterruptNonMeleeSpells(false); - - tempLastInvoker->CastSpell((*itr)->ToUnit(), e.action.cast.spell, (e.action.cast.flags & SMARTCAST_TRIGGERED)); - } - } - - delete targets; + { + Unit* tempLastInvoker = GetLastInvoker(unit); // xinef: can be used for area triggers cast + if (!tempLastInvoker) break; + + if (targets.empty()) + break; + + if (e.action.cast.targetsLimit > 0 && targets.size() > e.action.cast.targetsLimit) + Acore::Containers::RandomResize(targets, e.action.cast.targetsLimit); + + for (WorldObject* target : targets) + { + if (!IsUnit(target)) + continue; + + if (!(e.action.cast.flags & SMARTCAST_AURA_NOT_PRESENT) || !target->ToUnit()->HasAura(e.action.cast.spell)) + { + if (e.action.cast.flags & SMARTCAST_INTERRUPT_PREVIOUS) + tempLastInvoker->InterruptNonMeleeSpells(false); + + tempLastInvoker->CastSpell(target->ToUnit(), e.action.cast.spell, (e.action.cast.flags & SMARTCAST_TRIGGERED)); + } } + + break; + } case SMART_ACTION_ADD_AURA: + { + for (WorldObject* target : targets) { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) + if (IsUnit(target)) { - if (IsUnit(*itr)) - { - (*itr)->ToUnit()->AddAura(e.action.addAura.spell, (*itr)->ToUnit()); - LOG_DEBUG("sql.sql", "SmartScript::ProcessAction:: SMART_ACTION_ADD_AURA: Adding aura {} to unit {}", - e.action.addAura.spell, (*itr)->GetGUID().ToString()); - } + target->ToUnit()->AddAura(e.action.cast.spell, target->ToUnit()); + LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_ADD_AURA: Adding aura {} to unit {}", + e.action.cast.spell, target->GetGUID().ToString()); } - - delete targets; - break; } + break; + } case SMART_ACTION_ACTIVATE_GOBJECT: + { + for (WorldObject* target : targets) { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) + if (IsGameObject(target)) { - if (IsGameObject(*itr)) + GameObject* go = target->ToGameObject(); + + // Activate + if (go->GetGoType() != GAMEOBJECT_TYPE_DOOR) { - GameObject* go = (*itr)->ToGameObject(); - - // Activate - if (go->GetGoType() != GAMEOBJECT_TYPE_DOOR) - { - go->SetLootState(GO_READY); - } - - go->UseDoorOrButton(0, !!e.action.activateObject.alternative, unit); - LOG_DEBUG("sql.sql", "SmartScript::ProcessAction:: SMART_ACTION_ACTIVATE_GOBJECT. Gameobject {} activated", go->GetGUID().ToString()); + go->SetLootState(GO_READY); } - } - delete targets; - break; + go->UseDoorOrButton(0, !!e.action.activateObject.alternative, unit); + LOG_DEBUG("sql.sql", "SmartScript::ProcessAction:: SMART_ACTION_ACTIVATE_GOBJECT. Gameobject {} activated", go->GetGUID().ToString()); + } } + + break; + } case SMART_ACTION_RESET_GOBJECT: + { + for (WorldObject* target : targets) { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) + if (IsGameObject(target)) { - if (IsGameObject(*itr)) - { - (*itr)->ToGameObject()->ResetDoorOrButton(); - LOG_DEBUG("sql.sql", "SmartScript::ProcessAction:: SMART_ACTION_RESET_GOBJECT. Gameobject {} reset", - (*itr)->GetGUID().ToString()); - } + target->ToGameObject()->ResetDoorOrButton(); + LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_RESET_GOBJECT. Gameobject {} (entry: {}) reset", + target->GetGUID().ToString(), target->GetEntry()); } - - delete targets; - break; } + break; + } case SMART_ACTION_SET_EMOTE_STATE: + { + for (WorldObject* target : targets) { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) + if (IsUnit(target)) { - if (IsUnit(*itr)) - { - (*itr)->ToUnit()->SetUInt32Value(UNIT_NPC_EMOTESTATE, e.action.emote.emote); - LOG_DEBUG("sql.sql", "SmartScript::ProcessAction:: SMART_ACTION_SET_EMOTE_STATE. Unit {} set emotestate to {}", - (*itr)->GetGUID().ToString(), e.action.emote.emote); - } + target->ToUnit()->SetUInt32Value(UNIT_NPC_EMOTESTATE, e.action.emote.emote); + LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_SET_EMOTE_STATE. Unit {} set emotestate to {}", + target->GetGUID().ToString(), e.action.emote.emote); } - - delete targets; - break; } + break; + } case SMART_ACTION_SET_UNIT_FLAG: + { + for (WorldObject* target : targets) { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) + if (IsUnit(target)) { - if (IsUnit(*itr)) + if (!e.action.unitFlag.type) { - if (!e.action.unitFlag.type) - { - (*itr)->ToUnit()->SetUnitFlag(UnitFlags(e.action.unitFlag.flag)); - LOG_DEBUG("sql.sql", "SmartScript::ProcessAction:: SMART_ACTION_SET_UNIT_FLAG. Unit {} added flag {} to UNIT_FIELD_FLAGS", - (*itr)->GetGUID().ToString(), e.action.unitFlag.flag); - } - else - { - (*itr)->ToUnit()->SetUnitFlag2(UnitFlags2(e.action.unitFlag.flag)); - LOG_DEBUG("sql.sql", "SmartScript::ProcessAction:: SMART_ACTION_SET_UNIT_FLAG. Unit {} added flag {} to UNIT_FIELD_FLAGS_2", - (*itr)->GetGUID().ToString(), e.action.unitFlag.flag); - } + target->ToUnit()->SetFlag(UNIT_FIELD_FLAGS, e.action.unitFlag.flag); + LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_SET_UNIT_FLAG. Unit {} added flag {} to UNIT_FIELD_FLAGS", + target->GetGUID().ToString(), e.action.unitFlag.flag); + } + else + { + target->ToUnit()->SetFlag(UNIT_FIELD_FLAGS_2, e.action.unitFlag.flag); + LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_SET_UNIT_FLAG. Unit {} added flag {} to UNIT_FIELD_FLAGS_2", + target->GetGUID().ToString(), e.action.unitFlag.flag); } } - - delete targets; - break; } + break; + } case SMART_ACTION_REMOVE_UNIT_FLAG: + { + for (WorldObject* target : targets) { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) + if (IsUnit(target)) { - if (IsUnit(*itr)) + if (!e.action.unitFlag.type) { - if (!e.action.unitFlag.type) - { - (*itr)->ToUnit()->RemoveUnitFlag(UnitFlags(e.action.unitFlag.flag)); - LOG_DEBUG("sql.sql", "SmartScript::ProcessAction:: SMART_ACTION_REMOVE_UNIT_FLAG. Unit {} removed flag {} to UNIT_FIELD_FLAGS", - (*itr)->GetGUID().ToString(), e.action.unitFlag.flag); - } - else - { - (*itr)->ToUnit()->RemoveUnitFlag2(UnitFlags2(e.action.unitFlag.flag)); - LOG_DEBUG("sql.sql", "SmartScript::ProcessAction:: SMART_ACTION_REMOVE_UNIT_FLAG. Unit {} removed flag {} to UNIT_FIELD_FLAGS_2", - (*itr)->GetGUID().ToString(), e.action.unitFlag.flag); - } + target->ToUnit()->RemoveFlag(UNIT_FIELD_FLAGS, e.action.unitFlag.flag); + LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_REMOVE_UNIT_FLAG. Unit {} removed flag {} to UNIT_FIELD_FLAGS", + target->GetGUID().ToString(), e.action.unitFlag.flag); + } + else + { + target->ToUnit()->RemoveFlag(UNIT_FIELD_FLAGS_2, e.action.unitFlag.flag); + LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_REMOVE_UNIT_FLAG. Unit {} removed flag {} to UNIT_FIELD_FLAGS_2", + target->GetGUID().ToString(), e.action.unitFlag.flag); } } - - delete targets; - break; } + break; + } case SMART_ACTION_AUTO_ATTACK: - { - if (!IsSmart()) - break; - - CAST_AI(SmartAI, me->AI())->SetAutoAttack(e.action.autoAttack.attack); - LOG_DEBUG("sql.sql", "SmartScript::ProcessAction:: SMART_ACTION_AUTO_ATTACK: Creature: {} bool on = {}", - me->GetGUID().ToString(), e.action.autoAttack.attack); + { + if (!IsSmart()) break; - } + + CAST_AI(SmartAI, me->AI())->SetAutoAttack(e.action.autoAttack.attack); + LOG_DEBUG("sql.sql", "SmartScript::ProcessAction:: SMART_ACTION_AUTO_ATTACK: Creature: {} bool on = {}", + me->GetGUID().ToString(), e.action.autoAttack.attack); + break; + } case SMART_ACTION_ALLOW_COMBAT_MOVEMENT: - { - if (!IsSmart()) - break; - - // Xinef: Fix Combat Movement - bool move = e.action.combatMove.move; - if (move && GetMaxCombatDist() && e.GetEventType() == SMART_EVENT_MANA_PCT) - { - SetActualCombatDist(0); - CAST_AI(SmartAI, me->AI())->SetForcedCombatMove(0); - } - else - CAST_AI(SmartAI, me->AI())->SetCombatMove(move); - LOG_DEBUG("sql.sql", "SmartScript::ProcessAction:: SMART_ACTION_ALLOW_COMBAT_MOVEMENT: Creature {} bool on = {}", - me->GetGUID().ToString(), e.action.combatMove.move); + { + if (!IsSmart()) break; + + // Xinef: Fix Combat Movement + bool move = e.action.combatMove.move; + if (move && GetMaxCombatDist() && e.GetEventType() == SMART_EVENT_MANA_PCT) + { + SetActualCombatDist(0); + CAST_AI(SmartAI, me->AI())->SetForcedCombatMove(0); } + else + CAST_AI(SmartAI, me->AI())->SetCombatMove(move); + LOG_DEBUG("sql.sql", "SmartScript::ProcessAction:: SMART_ACTION_ALLOW_COMBAT_MOVEMENT: Creature {} bool on = {}", + me->GetGUID().ToString(), e.action.combatMove.move); + break; + } case SMART_ACTION_SET_EVENT_PHASE: - { - if (!GetBaseObject()) - break; - - SetPhase(e.action.setEventPhase.phase); - LOG_DEBUG("sql.sql", "SmartScript::ProcessAction:: SMART_ACTION_SET_EVENT_PHASE: Creature {} set event phase {}", - GetBaseObject()->GetGUID().ToString(), e.action.setEventPhase.phase); + { + if (!GetBaseObject()) break; - } + + SetPhase(e.action.setEventPhase.phase); + LOG_DEBUG("sql.sql", "SmartScript::ProcessAction:: SMART_ACTION_SET_EVENT_PHASE: Creature {} set event phase {}", + GetBaseObject()->GetGUID().ToString(), e.action.setEventPhase.phase); + break; + } case SMART_ACTION_INC_EVENT_PHASE: - { - if (!GetBaseObject()) - break; - - IncPhase(e.action.incEventPhase.inc); - DecPhase(e.action.incEventPhase.dec); - LOG_DEBUG("sql.sql", "SmartScript::ProcessAction:: SMART_ACTION_INC_EVENT_PHASE: Creature {} inc event phase by {}, " - "decrease by {}", GetBaseObject()->GetGUID().ToString(), e.action.incEventPhase.inc, e.action.incEventPhase.dec); + { + if (!GetBaseObject()) break; - } + + IncPhase(e.action.incEventPhase.inc); + DecPhase(e.action.incEventPhase.dec); + LOG_DEBUG("sql.sql", "SmartScript::ProcessAction:: SMART_ACTION_INC_EVENT_PHASE: Creature {} inc event phase by {}, " + "decrease by {}", GetBaseObject()->GetGUID().ToString(), e.action.incEventPhase.inc, e.action.incEventPhase.dec); + break; + } case SMART_ACTION_EVADE: - { - if (!GetBaseObject()) - break; - - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - if (IsCreature((*itr))) - if ((*itr)->ToCreature()->IsAIEnabled) - (*itr)->ToCreature()->AI()->EnterEvadeMode(); - - delete targets; + { + if (!GetBaseObject()) break; - } + + for (WorldObject* target : targets) + if (IsCreature(target)) + if (target->ToCreature()->IsAIEnabled) + target->ToCreature()->AI()->EnterEvadeMode(); + + break; + } case SMART_ACTION_FLEE_FOR_ASSIST: - { - // Xinef: do not allow to flee without control (stun, fear etc) - if (!me || me->HasUnitState(UNIT_STATE_LOST_CONTROL) || me->GetSpeed(MOVE_RUN) < 0.1f) - break; - - me->DoFleeToGetAssistance(); - if (e.action.flee.withEmote) - { - Acore::BroadcastTextBuilder builder(me, CHAT_MSG_MONSTER_EMOTE, BROADCAST_TEXT_FLEE_FOR_ASSIST, me->getGender()); - sCreatureTextMgr->SendChatPacket(me, builder, CHAT_MSG_MONSTER_EMOTE); - } - LOG_DEBUG("sql.sql", "SmartScript::ProcessAction:: SMART_ACTION_FLEE_FOR_ASSIST: Creature {} DoFleeToGetAssistance", me->GetGUID().ToString()); + { + // Xinef: do not allow to flee without control (stun, fear etc) + if (!me || me->HasUnitState(UNIT_STATE_LOST_CONTROL) || me->GetSpeed(MOVE_RUN) < 0.1f) break; + + me->DoFleeToGetAssistance(); + if (e.action.flee.withEmote) + { + Acore::BroadcastTextBuilder builder(me, CHAT_MSG_MONSTER_EMOTE, BROADCAST_TEXT_FLEE_FOR_ASSIST, me->getGender()); + sCreatureTextMgr->SendChatPacket(me, builder, CHAT_MSG_MONSTER_EMOTE); } + LOG_DEBUG("sql.sql", "SmartScript::ProcessAction:: SMART_ACTION_FLEE_FOR_ASSIST: Creature {} DoFleeToGetAssistance", me->GetGUID().ToString()); + break; + } case SMART_ACTION_COMBAT_STOP: - { - if (!me) - break; - - me->CombatStop(true); + { + if (!me) break; - } + + me->CombatStop(true); + break; + } case SMART_ACTION_CALL_GROUPEVENTHAPPENS: - { - if (!GetBaseObject()) - break; - - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - { - if (IsUnit((*itr))) - { - if (Player* player = (*itr)->ToUnit()->GetCharmerOrOwnerPlayerOrPlayerItself()) - player->GroupEventHappens(e.action.quest.quest, GetBaseObject()); - LOG_DEBUG("sql.sql", "SmartScript::ProcessAction: SMART_ACTION_CALL_GROUPEVENTHAPPENS: Player {}, group credit for quest {}", - (*itr)->GetGUID().ToString(), e.action.quest.quest); - } - } - - delete targets; + { + if (!unit) break; - } - case SMART_ACTION_REMOVEAURASFROMSPELL: + + // If invoker was pet or charm + Player* player = unit->GetCharmerOrOwnerPlayerOrPlayerItself(); + if (player && GetBaseObject()) { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; + player->GroupEventHappens(e.action.quest.quest, GetBaseObject()); + LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction: SMART_ACTION_CALL_GROUPEVENTHAPPENS: Player {}, group credit for quest {}", + unit->GetGUID().ToString(), e.action.quest.quest); + } - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) + // Special handling for vehicles + if (Vehicle* vehicle = unit->GetVehicleKit()) + for (auto & Seat : vehicle->Seats) + if (Player* player = ObjectAccessor::GetPlayer(*unit, Seat.second.Passenger.Guid)) + player->GroupEventHappens(e.action.quest.quest, GetBaseObject()); + break; + } + case SMART_ACTION_REMOVEAURASFROMSPELL: + { + for (WorldObject* target : targets) + { + if (!IsUnit(target)) + continue; + + if (e.action.removeAura.spell) { - if (!IsUnit((*itr))) - continue; - - if (e.action.removeAura.spell) + if (e.action.removeAura.charges) { - if (e.action.removeAura.charges) - { - if (Aura* aur = (*itr)->ToUnit()->GetAura(e.action.removeAura.spell)) - aur->ModCharges(-static_cast(e.action.removeAura.charges), AURA_REMOVE_BY_EXPIRE); - } - else - (*itr)->ToUnit()->RemoveAurasDueToSpell(e.action.removeAura.spell); + if (Aura* aur = target->ToUnit()->GetAura(e.action.removeAura.spell)) + aur->ModCharges(-static_cast(e.action.removeAura.charges), AURA_REMOVE_BY_EXPIRE); } else - (*itr)->ToUnit()->RemoveAllAuras(); - - LOG_DEBUG("sql.sql", "SmartScript::ProcessAction: SMART_ACTION_REMOVEAURASFROMSPELL: Unit {}, spell {}", - (*itr)->GetGUID().ToString(), e.action.removeAura.spell); - } - - delete targets; - break; - } - case SMART_ACTION_FOLLOW: - { - if (!IsSmart()) - break; - - ObjectList* targets = GetTargets(e, unit); - if (!targets) - { - CAST_AI(SmartAI, me->AI())->StopFollow(false); - break; - } - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - { - if (IsUnit((*itr))) - { - float angle = e.action.follow.angle > 6 ? (e.action.follow.angle * M_PI / 180.0f) : e.action.follow.angle; - CAST_AI(SmartAI, me->AI())->SetFollow((*itr)->ToUnit(), float(int32(e.action.follow.dist)) + 0.1f, angle, e.action.follow.credit, e.action.follow.entry, e.action.follow.creditType, e.action.follow.aliveState); - LOG_DEBUG("sql.sql", "SmartScript::ProcessAction: SMART_ACTION_FOLLOW: Creature {} following target {}", - me->GetGUID().ToString(), (*itr)->GetGUID().ToString()); - break; - } - } - - delete targets; - break; - } - case SMART_ACTION_RANDOM_PHASE: - { - if (!GetBaseObject()) - break; - - uint32 phases[SMART_ACTION_PARAM_COUNT]; - phases[0] = e.action.randomPhase.phase1; - phases[1] = e.action.randomPhase.phase2; - phases[2] = e.action.randomPhase.phase3; - phases[3] = e.action.randomPhase.phase4; - phases[4] = e.action.randomPhase.phase5; - phases[5] = e.action.randomPhase.phase6; - uint32 temp[SMART_ACTION_PARAM_COUNT]; - uint32 count = 0; - for (uint8 i = 0; i < SMART_ACTION_PARAM_COUNT; i++) - { - if (phases[i] > 0) - { - temp[count] = phases[i]; - ++count; - } - } - - if (count == 0) - break; - - uint32 phase = temp[urand(0, count - 1)]; - SetPhase(phase); - LOG_DEBUG("sql.sql", "SmartScript::ProcessAction: SMART_ACTION_RANDOM_PHASE: Creature {} sets event phase to {}", - GetBaseObject()->GetGUID().ToString(), phase); - break; - } - case SMART_ACTION_RANDOM_PHASE_RANGE: - { - if (!GetBaseObject()) - break; - - uint32 phase = urand(e.action.randomPhaseRange.phaseMin, e.action.randomPhaseRange.phaseMax); - SetPhase(phase); - LOG_DEBUG("sql.sql", "SmartScript::ProcessAction: SMART_ACTION_RANDOM_PHASE_RANGE: Creature {} sets event phase to {}", - GetBaseObject()->GetGUID().ToString(), phase); - break; - } - case SMART_ACTION_CALL_KILLEDMONSTER: - { - if (trigger && IsPlayer(unit)) - { - unit->ToPlayer()->RewardPlayerAndGroupAtEvent(e.action.killedMonster.creature, unit); - LOG_DEBUG("sql.sql", "SmartScript::ProcessAction: SMART_ACTION_CALL_KILLEDMONSTER: (trigger == true) Player {}, Killcredit: {}", - unit->GetGUID().ToString(), e.action.killedMonster.creature); - } - else if (e.target.type == SMART_TARGET_NONE || e.target.type == SMART_TARGET_SELF) // Loot recipient and his group members - { - if (!me) - break; - - if (Player* player = me->GetLootRecipient()) - { - player->RewardPlayerAndGroupAtEvent(e.action.killedMonster.creature, player); - LOG_DEBUG("sql.sql", "SmartScript::ProcessAction: SMART_ACTION_CALL_KILLEDMONSTER: Player {}, Killcredit: {}", - player->GetGUID().ToString(), e.action.killedMonster.creature); - } - } - else // Specific target type - { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - { - if (!IsUnit(*itr)) - continue; - - Player* player = (*itr)->ToUnit()->GetCharmerOrOwnerPlayerOrPlayerItself(); - if (!player) - continue; - - player->RewardPlayerAndGroupAtEvent(e.action.killedMonster.creature, player); - LOG_DEBUG("sql.sql", "SmartScript::ProcessAction: SMART_ACTION_CALL_KILLEDMONSTER: Player {}, Killcredit: {}", - (*itr)->GetGUID().ToString(), e.action.killedMonster.creature); - } - - delete targets; - } - break; - } - case SMART_ACTION_SET_INST_DATA: - { - WorldObject* obj = GetBaseObject(); - if (!obj) - obj = unit; - - if (!obj) - break; - - InstanceScript* instance = obj->GetInstanceScript(); - if (!instance) - { - LOG_ERROR("scripts.ai.sai", "SmartScript: Event {} attempt to set instance data without instance script. EntryOrGuid {}", e.GetEventType(), e.entryOrGuid); - break; - } - - switch (e.action.setInstanceData.type) - { - case 0: - { - instance->SetData(e.action.setInstanceData.field, e.action.setInstanceData.data); - LOG_DEBUG("scripts.ai.sai", "SmartScript::ProcessAction: SMART_ACTION_SET_INST_DATA: Field: {}, data: {}", e.action.setInstanceData.field, e.action.setInstanceData.data); - } break; - case 1: - { - instance->SetBossState(e.action.setInstanceData.field, static_cast(e.action.setInstanceData.data)); - LOG_DEBUG("scripts.ai.sai", "SmartScript::ProcessAction: SMART_ACTION_SET_INST_DATA: SetBossState BossId: {}, State: {} ({})", e.action.setInstanceData.field, e.action.setInstanceData.data, InstanceScript::GetBossStateName(e.action.setInstanceData.data)); - } break; - default: - { - break; - } - } - break; - } - case SMART_ACTION_SET_INST_DATA64: - { - WorldObject* obj = GetBaseObject(); - if (!obj) - obj = unit; - - if (!obj) - break; - - InstanceScript* instance = obj->GetInstanceScript(); - if (!instance) - { - LOG_ERROR("sql.sql", "SmartScript: Event {} attempt to set instance data without instance script. EntryOrGuid {}", e.GetEventType(), e.entryOrGuid); - break; - } - - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - instance->SetGuidData(e.action.setInstanceData64.field, targets->front()->GetGUID()); - LOG_DEBUG("sql.sql", "SmartScript::ProcessAction: SMART_ACTION_SET_INST_DATA64: Field: {}, data: {}", e.action.setInstanceData64.field, targets->front()->GetGUID().GetRawValue()); - delete targets; - break; - } - case SMART_ACTION_UPDATE_TEMPLATE: - { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - if (IsCreature(*itr)) - (*itr)->ToCreature()->UpdateEntry(e.action.updateTemplate.creature, nullptr, e.action.updateTemplate.updateLevel != 0); - - delete targets; - break; - } - case SMART_ACTION_DIE: - { - if (me && !me->isDead()) - { - Unit::Kill(me, me); - LOG_DEBUG("sql.sql", "SmartScript::ProcessAction: SMART_ACTION_DIE: Creature {}", me->GetGUID().ToString()); - } - break; - } - case SMART_ACTION_SET_IN_COMBAT_WITH_ZONE: - { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - if (!me->GetMap()->IsDungeon()) - { - ObjectList* units = GetWorldObjectsInDist((float)e.action.combatZone.range); - if (!units->empty() && GetBaseObject()) - for (ObjectList::const_iterator itr = units->begin(); itr != units->end(); ++itr) - if (IsPlayer(*itr) && !(*itr)->ToPlayer()->isDead()) - { - me->SetInCombatWith((*itr)->ToPlayer()); - (*itr)->ToPlayer()->SetInCombatWith(me); - me->AddThreat((*itr)->ToPlayer(), 0.0f); - } + target->ToUnit()->RemoveAurasDueToSpell(e.action.removeAura.spell); } else - { - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - if (IsCreature(*itr)) - (*itr)->ToCreature()->SetInCombatWithZone(); - } + target->ToUnit()->RemoveAllAuras(); - delete targets; + LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction: SMART_ACTION_REMOVEAURASFROMSPELL: Unit {}, spell {}", + target->GetGUID().ToString(), e.action.removeAura.spell); + } + break; + } + case SMART_ACTION_FOLLOW: + { + if (!IsSmart()) + break; + + if (targets.empty()) + { + CAST_AI(SmartAI, me->AI())->StopFollow(false); break; } - case SMART_ACTION_CALL_FOR_HELP: + + for (WorldObject* target : targets) { - ObjectList* targets = GetTargets(e, unit); - if (!targets) + if (IsUnit(target)) + { + float angle = e.action.follow.angle > 6 ? (e.action.follow.angle * M_PI / 180.0f) : e.action.follow.angle; + CAST_AI(SmartAI, me->AI())->SetFollow(target->ToUnit(), float(e.action.follow.dist) + 0.1f, angle, e.action.follow.credit, e.action.follow.entry, e.action.follow.creditType); + LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction: SMART_ACTION_FOLLOW: Creature {} following target {}", + me->GetGUID().ToString(), target->GetGUID().ToString()); + break; + } + } + break; + } + case SMART_ACTION_RANDOM_PHASE: + { + if (!GetBaseObject()) + break; + + std::vector phases; + std::copy_if(e.action.randomPhase.phases.begin(), e.action.randomPhase.phases.end(), + std::back_inserter(phases), [](uint32 phase) { return phase != 0; }); + + uint32 phase = Acore::Containers::SelectRandomContainerElement(phases); + SetPhase(phase); + LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction: SMART_ACTION_RANDOM_PHASE: Creature {} sets event phase to {}", + GetBaseObject()->GetGUID().ToString(), phase); + break; + } + case SMART_ACTION_RANDOM_PHASE_RANGE: + { + if (!GetBaseObject()) + break; + + uint32 phase = urand(e.action.randomPhaseRange.phaseMin, e.action.randomPhaseRange.phaseMax); + SetPhase(phase); + LOG_DEBUG("sql.sql", "SmartScript::ProcessAction: SMART_ACTION_RANDOM_PHASE_RANGE: Creature {} sets event phase to {}", + GetBaseObject()->GetGUID().ToString(), phase); + break; + } + case SMART_ACTION_CALL_KILLEDMONSTER: + { + if (trigger && IsPlayer(unit)) + { + unit->ToPlayer()->RewardPlayerAndGroupAtEvent(e.action.killedMonster.creature, unit); + LOG_DEBUG("sql.sql", "SmartScript::ProcessAction: SMART_ACTION_CALL_KILLEDMONSTER: (trigger == true) Player {}, Killcredit: {}", + unit->GetGUID().ToString(), e.action.killedMonster.creature); + } + else if (e.target.type == SMART_TARGET_NONE || e.target.type == SMART_TARGET_SELF) // Loot recipient and his group members + { + if (!me) break; - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) + if (Player* player = me->GetLootRecipient()) { - if (IsCreature(*itr)) - { - (*itr)->ToCreature()->CallForHelp((float)e.action.callHelp.range, e.GetEventType() == SMART_EVENT_AGGRO ? unit : nullptr); - if (e.action.callHelp.withEmote) - { - Acore::BroadcastTextBuilder builder(*itr, CHAT_MSG_MONSTER_EMOTE, BROADCAST_TEXT_CALL_FOR_HELP, LANG_UNIVERSAL, nullptr); - sCreatureTextMgr->SendChatPacket(*itr, builder, CHAT_MSG_MONSTER_EMOTE); - } - } + player->RewardPlayerAndGroupAtEvent(e.action.killedMonster.creature, player); + LOG_DEBUG("sql.sql", "SmartScript::ProcessAction: SMART_ACTION_CALL_KILLEDMONSTER: Player {}, Killcredit: {}", + player->GetGUID().ToString(), e.action.killedMonster.creature); } - - delete targets; - break; } - case SMART_ACTION_SET_SHEATH: + else // Specific target type { - if (me) + for (WorldObject* target : targets) { - me->SetSheath(SheathState(e.action.setSheath.sheath)); - LOG_DEBUG("sql.sql", "SmartScript::ProcessAction: SMART_ACTION_SET_SHEATH: Creature {}, State: {}", - me->GetGUID().ToString(), e.action.setSheath.sheath); - } - break; - } - case SMART_ACTION_FORCE_DESPAWN: - { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - { - Milliseconds despawnDelay(e.action.forceDespawn.delay); - - // Wait at least one world update tick before despawn, so it doesn't break linked actions. - if (despawnDelay <= 0ms) - { - despawnDelay = 1ms; - } - - Seconds forceRespawnTimer(e.action.forceDespawn.forceRespawnTimer); - if (Creature* creature = (*itr)->ToCreature()) - { - creature->DespawnOrUnsummon(despawnDelay, forceRespawnTimer); - } - else if (GameObject* go = (*itr)->ToGameObject()) - { - go->DespawnOrUnsummon(despawnDelay, forceRespawnTimer); - } - } - - delete targets; - break; - } - case SMART_ACTION_SET_INGAME_PHASE_MASK: - { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - { - if (IsUnit(*itr)) - (*itr)->ToUnit()->SetPhaseMask(e.action.ingamePhaseMask.mask, true); - else if (IsGameObject(*itr)) - (*itr)->ToGameObject()->SetPhaseMask(e.action.ingamePhaseMask.mask, true); - } - - delete targets; - break; - } - case SMART_ACTION_MOUNT_TO_ENTRY_OR_MODEL: - { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - { - if (!IsUnit(*itr)) + if (!IsUnit(target)) continue; - if (e.action.morphOrMount.creature || e.action.morphOrMount.model) - { - if (e.action.morphOrMount.creature > 0) + Player* player = target->ToUnit()->GetCharmerOrOwnerPlayerOrPlayerItself(); + if (!player) + continue; + + player->RewardPlayerAndGroupAtEvent(e.action.killedMonster.creature, player); + LOG_DEBUG("sql.sql", "SmartScript::ProcessAction: SMART_ACTION_CALL_KILLEDMONSTER: Player {}, Killcredit: {}", + target->GetGUID().ToString(), e.action.killedMonster.creature); + } + } + break; + } + case SMART_ACTION_SET_INST_DATA: + { + WorldObject* obj = GetBaseObject(); + if (!obj) + obj = unit; + + if (!obj) + break; + + InstanceScript* instance = obj->GetInstanceScript(); + if (!instance) + { + LOG_ERROR("scripts.ai.sai", "SmartScript: Event {} attempt to set instance data without instance script. EntryOrGuid {}", e.GetEventType(), e.entryOrGuid); + break; + } + + switch (e.action.setInstanceData.type) + { + case 0: + { + instance->SetData(e.action.setInstanceData.field, e.action.setInstanceData.data); + LOG_DEBUG("scripts.ai.sai", "SmartScript::ProcessAction: SMART_ACTION_SET_INST_DATA: Field: {}, data: {}", e.action.setInstanceData.field, e.action.setInstanceData.data); + } break; + case 1: + { + instance->SetBossState(e.action.setInstanceData.field, static_cast(e.action.setInstanceData.data)); + LOG_DEBUG("scripts.ai.sai", "SmartScript::ProcessAction: SMART_ACTION_SET_INST_DATA: SetBossState BossId: {}, State: {} ({})", e.action.setInstanceData.field, e.action.setInstanceData.data, InstanceScript::GetBossStateName(e.action.setInstanceData.data)); + } break; + default: + { + break; + } + } + break; + } + case SMART_ACTION_SET_INST_DATA64: + { + WorldObject* obj = GetBaseObject(); + if (!obj) + obj = unit; + + if (!obj) + break; + + InstanceScript* instance = obj->GetInstanceScript(); + if (!instance) + { + LOG_ERROR("sql.sql", "SmartScript: Event {} attempt to set instance data without instance script. EntryOrGuid {}", e.GetEventType(), e.entryOrGuid); + break; + } + + if (targets.empty()) + break; + + instance->SetGuidData(e.action.setInstanceData64.field, targets.front()->GetGUID()); + LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction: SMART_ACTION_SET_INST_DATA64: Field: {}, data: {}", + e.action.setInstanceData64.field, targets.front()->GetGUID().ToString()); + break; + } + case SMART_ACTION_UPDATE_TEMPLATE: + { + for (WorldObject* target : targets) + if (IsCreature(target)) + target->ToCreature()->UpdateEntry(e.action.updateTemplate.creature, target->ToCreature()->GetCreatureData(), e.action.updateTemplate.updateLevel != 0); + break; + } + case SMART_ACTION_DIE: + { + if (me && !me->isDead()) + { + Unit::Kill(me, me); + LOG_DEBUG("sql.sql", "SmartScript::ProcessAction: SMART_ACTION_DIE: Creature {}", me->GetGUID().ToString()); + } + break; + } + case SMART_ACTION_SET_IN_COMBAT_WITH_ZONE: + { + if (targets.empty()) + break; + + if (!me->GetMap()->IsDungeon()) + { + ObjectVector units; + GetWorldObjectsInDist(units, static_cast(e.target.unitRange.maxDist)); + + if (!units.empty() && GetBaseObject()) + for (WorldObject* unit : units) + if (IsPlayer(unit) && !unit->ToPlayer()->isDead()) { - if (CreatureTemplate const* cInfo = sObjectMgr->GetCreatureTemplate(e.action.morphOrMount.creature)) - (*itr)->ToUnit()->Mount(ObjectMgr::ChooseDisplayId(cInfo)); + me->SetInCombatWith(unit->ToPlayer()); + unit->ToPlayer()->SetInCombatWith(me); + me->AddThreat(unit->ToPlayer(), 0.0f); } - else - (*itr)->ToUnit()->Mount(e.action.morphOrMount.model); + } + else + { + for (WorldObject* target : targets) + { + if (IsCreature(target)) + { + target->ToCreature()->SetInCombatWithZone(); + LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction: SMART_ACTION_SET_IN_COMBAT_WITH_ZONE: Creature {}, target: {}", + me->GetGUID().ToString(), target->GetGUID().ToString()); + } + } + } + + break; + } + case SMART_ACTION_CALL_FOR_HELP: + { + for (WorldObject* target : targets) + { + if (IsCreature(target)) + { + target->ToCreature()->CallForHelp(float(e.action.callHelp.range)); + if (e.action.callHelp.withEmote) + { + Acore::BroadcastTextBuilder builder(target, CHAT_MSG_MONSTER_EMOTE, BROADCAST_TEXT_CALL_FOR_HELP, LANG_UNIVERSAL, nullptr); + sCreatureTextMgr->SendChatPacket(target, builder, CHAT_MSG_MONSTER_EMOTE); + } + LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction: SMART_ACTION_CALL_FOR_HELP: Creature {}, target: {}", + me->GetGUID().ToString(), target->GetGUID().ToString()); + } + } + break; + } + case SMART_ACTION_SET_SHEATH: + { + if (me) + { + me->SetSheath(SheathState(e.action.setSheath.sheath)); + LOG_DEBUG("sql.sql", "SmartScript::ProcessAction: SMART_ACTION_SET_SHEATH: Creature {}, State: {}", + me->GetGUID().ToString(), e.action.setSheath.sheath); + } + break; + } + case SMART_ACTION_FORCE_DESPAWN: + { + for (WorldObject* target : targets) + { + Milliseconds despawnDelay(e.action.forceDespawn.delay); + + // Wait at least one world update tick before despawn, so it doesn't break linked actions. + if (despawnDelay <= 0ms) + { + despawnDelay = 1ms; + } + + Seconds forceRespawnTimer(e.action.forceDespawn.forceRespawnTimer); + if (Creature* creature = target->ToCreature()) + { + creature->DespawnOrUnsummon(despawnDelay, forceRespawnTimer); + } + else if (GameObject* go = target->ToGameObject()) + { + go->DespawnOrUnsummon(despawnDelay, forceRespawnTimer); + } + } + + break; + } + case SMART_ACTION_SET_INGAME_PHASE_MASK: + { + for (WorldObject* target : targets) + { + if (IsUnit(target)) + target->ToUnit()->SetPhaseMask(e.action.ingamePhaseMask.mask, true); + else if (IsGameObject(target)) + target->ToGameObject()->SetPhaseMask(e.action.ingamePhaseMask.mask, true); + } + break; + } + case SMART_ACTION_MOUNT_TO_ENTRY_OR_MODEL: + { + for (WorldObject* target : targets) + { + if (!IsUnit(target)) + continue; + + if (e.action.morphOrMount.creature || e.action.morphOrMount.model) + { + if (e.action.morphOrMount.creature > 0) + { + if (CreatureTemplate const* cInfo = sObjectMgr->GetCreatureTemplate(e.action.morphOrMount.creature)) + target->ToUnit()->Mount(ObjectMgr::ChooseDisplayId(cInfo)); } else - (*itr)->ToUnit()->Dismount(); + target->ToUnit()->Mount(e.action.morphOrMount.model); } - - delete targets; - break; + else + target->ToUnit()->Dismount(); } + break; + } case SMART_ACTION_SET_INVINCIBILITY_HP_LEVEL: + { + for (WorldObject* target : targets) { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) + if (IsCreature(target)) { - if (IsCreature(*itr)) - { - SmartAI* ai = CAST_AI(SmartAI, (*itr)->ToCreature()->AI()); - if (!ai) - continue; + SmartAI* ai = CAST_AI(SmartAI, target->ToCreature()->AI()); + if (!ai) + continue; - if (e.action.invincHP.percent) - ai->SetInvincibilityHpLevel((*itr)->ToCreature()->CountPctFromMaxHealth(e.action.invincHP.percent)); - else - ai->SetInvincibilityHpLevel(e.action.invincHP.minHP); - } + if (e.action.invincHP.percent) + ai->SetInvincibilityHpLevel(target->ToCreature()->CountPctFromMaxHealth(e.action.invincHP.percent)); + else + ai->SetInvincibilityHpLevel(e.action.invincHP.minHP); } - - delete targets; - break; } + break; + } case SMART_ACTION_SET_DATA: + { + for (WorldObject* target : targets) { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - { - if (IsCreature(*itr)) - (*itr)->ToCreature()->AI()->SetData(e.action.setData.field, e.action.setData.data); - else if (IsGameObject(*itr)) - (*itr)->ToGameObject()->AI()->SetData(e.action.setData.field, e.action.setData.data); - } - - delete targets; - break; + if (IsCreature(target)) + target->ToCreature()->AI()->SetData(e.action.setData.field, e.action.setData.data); + else if (IsGameObject(target)) + target->ToGameObject()->AI()->SetData(e.action.setData.field, e.action.setData.data); } + break; + } case SMART_ACTION_MOVE_FORWARD: - { - if (!me) - break; - - float x, y, z; - me->GetClosePoint(x, y, z, me->GetObjectSize() / 3, (float)e.action.moveRandom.distance); - me->GetMotionMaster()->MovePoint(SMART_RANDOM_POINT, x, y, z); + { + if (!me) break; - } + + float x, y, z; + me->GetClosePoint(x, y, z, me->GetObjectSize() / 3, (float)e.action.moveRandom.distance); + me->GetMotionMaster()->MovePoint(SMART_RANDOM_POINT, x, y, z); + break; + } case SMART_ACTION_RISE_UP: - { - if (!me) - break; - - me->GetMotionMaster()->MovePoint(SMART_RANDOM_POINT, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ() + (float)e.action.moveRandom.distance); + { + if (!me) break; - } + + me->GetMotionMaster()->MovePoint(SMART_RANDOM_POINT, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ() + (float)e.action.moveRandom.distance); + break; + } case SMART_ACTION_SET_VISIBILITY: - { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; + { + for (WorldObject* target : targets) + if (IsUnit(target)) + target->ToUnit()->SetVisible(!!e.action.visibility.state); - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - if (IsUnit(*itr)) - (*itr)->ToUnit()->SetVisible(!!e.action.visibility.state); - - delete targets; - break; - } + break; + } case SMART_ACTION_SET_ACTIVE: - { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - (*itr)->setActive(!!e.action.setActive.state); - - delete targets; - break; - } + { + for (WorldObject* target : targets) + target->setActive(!!e.action.setActive.state); + break; + } case SMART_ACTION_ATTACK_START: - { - if (!me) - break; - - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - // xinef: attack random target - if (Unit* target = Acore::Containers::SelectRandomContainerElement(*targets)->ToUnit()) - me->AI()->AttackStart(target); - - delete targets; + { + if (!me) break; - } + + if (targets.empty()) + break; + + // attack random target + if (Unit* target = Acore::Containers::SelectRandomContainerElement(targets)->ToUnit()) + me->AI()->AttackStart(target); + break; + } case SMART_ACTION_ATTACK_STOP: - { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - { - break; - } + { + for (WorldObject* target : targets) + if (Unit* unitTarget = target->ToUnit()) + unitTarget->AttackStop(); + break; + } + case SMART_ACTION_SUMMON_CREATURE: + { + WorldObject* summoner = GetBaseObject() ? GetBaseObject() : unit; + if (!summoner) + break; - for (auto const& target : *targets) + if (e.GetTargetType() == SMART_TARGET_RANDOM_POINT) + { + float range = (float)e.target.randomPoint.range; + Position randomPoint; + Position srcPos = { e.target.x, e.target.y, e.target.z, e.target.o }; + for (uint32 i = 0; i < e.target.randomPoint.amount; i++) { - if (Unit* unitTarget = target->ToUnit()) + if (e.target.randomPoint.self > 0) + randomPoint = me->GetRandomPoint(me->GetPosition(), range); + else + randomPoint = me->GetRandomPoint(srcPos, range); + if (Creature* summon = summoner->SummonCreature(e.action.summonCreature.creature, randomPoint, (TempSummonType)e.action.summonCreature.type, e.action.summonCreature.duration)) { - unitTarget->AttackStop(); + if (unit && e.action.summonCreature.attackInvoker) + summon->AI()->AttackStart(unit); + else if (me && e.action.summonCreature.attackScriptOwner) + summon->AI()->AttackStart(me); } } - - delete targets; break; } - case SMART_ACTION_SUMMON_CREATURE: + + float x, y, z, o; + for (WorldObject* target : targets) { - ObjectList* targets = GetTargets(e, unit); - WorldObject* summoner = GetBaseObject() ? GetBaseObject() : unit; - if (!summoner) - break; - - if (e.GetTargetType() == SMART_TARGET_RANDOM_POINT) + target->GetPosition(x, y, z, o); + x += e.target.x; + y += e.target.y; + z += e.target.z; + o += e.target.o; + if (Creature* summon = summoner->SummonCreature(e.action.summonCreature.creature, x, y, z, o, (TempSummonType)e.action.summonCreature.type, e.action.summonCreature.duration)) { - float range = (float)e.target.randomPoint.range; - Position randomPoint; - Position srcPos = { e.target.x, e.target.y, e.target.z, e.target.o }; - for (uint32 i = 0; i < e.target.randomPoint.amount; i++) - { - if (e.target.randomPoint.self > 0) - randomPoint = me->GetRandomPoint(me->GetPosition(), range); - else - randomPoint = me->GetRandomPoint(srcPos, range); - if (Creature* summon = summoner->SummonCreature(e.action.summonCreature.creature, randomPoint, (TempSummonType)e.action.summonCreature.type, e.action.summonCreature.duration)) - { - if (unit && e.action.summonCreature.attackInvoker) - summon->AI()->AttackStart(unit); - else if (me && e.action.summonCreature.attackScriptOwner) - summon->AI()->AttackStart(me); - } - } - break; - } - - if (targets) - { - float x, y, z, o; - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - { - (*itr)->GetPosition(x, y, z, o); - x += e.target.x; - y += e.target.y; - z += e.target.z; - o += e.target.o; - if (Creature* summon = summoner->SummonCreature(e.action.summonCreature.creature, x, y, z, o, (TempSummonType)e.action.summonCreature.type, e.action.summonCreature.duration)) - { - if (e.action.summonCreature.attackInvoker == 2) // pussywizard: proper attackInvoker implementation - summon->AI()->AttackStart(unit); - else if (e.action.summonCreature.attackInvoker) - summon->AI()->AttackStart((*itr)->ToUnit()); - else if (me && e.action.summonCreature.attackScriptOwner) - summon->AI()->AttackStart(me); - } - } - - delete targets; - } - - if (e.GetTargetType() != SMART_TARGET_POSITION) - break; - - if (Creature* summon = summoner->SummonCreature(e.action.summonCreature.creature, e.target.x, e.target.y, e.target.z, e.target.o, (TempSummonType)e.action.summonCreature.type, e.action.summonCreature.duration)) - { - if (unit && e.action.summonCreature.attackInvoker) + if (e.action.summonCreature.attackInvoker == 2) // pussywizard: proper attackInvoker implementation summon->AI()->AttackStart(unit); + else if (e.action.summonCreature.attackInvoker) + summon->AI()->AttackStart(target->ToUnit()); else if (me && e.action.summonCreature.attackScriptOwner) summon->AI()->AttackStart(me); } - break; } + + if (e.GetTargetType() != SMART_TARGET_POSITION) + break; + + if (Creature* summon = summoner->SummonCreature(e.action.summonCreature.creature, e.target.x, e.target.y, e.target.z, e.target.o, (TempSummonType)e.action.summonCreature.type, e.action.summonCreature.duration)) + { + if (unit && e.action.summonCreature.attackInvoker) + summon->AI()->AttackStart(unit); + else if (me && e.action.summonCreature.attackScriptOwner) + summon->AI()->AttackStart(me); + } + break; + } case SMART_ACTION_SUMMON_GO: - { - if (!GetBaseObject()) - break; - - ObjectList* targets = GetTargets(e, unit); - if (targets) - { - float x, y, z, o; - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - { - // xinef: allow gameobjects to summon gameobjects! - //if(!IsUnit((*itr))) - // continue; - - (*itr)->GetPosition(x, y, z, o); - x += e.target.x; - y += e.target.y; - z += e.target.z; - o += e.target.o; - if (!e.action.summonGO.targetsummon) - GetBaseObject()->SummonGameObject(e.action.summonGO.entry, x, y, z, o, 0, 0, 0, 0, e.action.summonGO.despawnTime, GOSummonType(e.action.summonGO.summonType)); - else - (*itr)->SummonGameObject(e.action.summonGO.entry, GetBaseObject()->GetPositionX(), GetBaseObject()->GetPositionY(), GetBaseObject()->GetPositionZ(), GetBaseObject()->GetOrientation(), 0, 0, 0, 0, e.action.summonGO.despawnTime); - } - - delete targets; - } - - if (e.GetTargetType() != SMART_TARGET_POSITION) - break; - - GetBaseObject()->SummonGameObject(e.action.summonGO.entry, e.target.x, e.target.y, e.target.z, e.target.o, 0, 0, 0, 0, e.action.summonGO.despawnTime, GOSummonType(e.action.summonGO.summonType)); + { + if (!GetBaseObject()) break; + + if (!targets.empty()) + { + float x, y, z, o; + for (WorldObject* target : targets) + { + // xinef: allow gameobjects to summon gameobjects! + //if(!IsUnit((*itr))) + // continue; + + target->GetPosition(x, y, z, o); + x += e.target.x; + y += e.target.y; + z += e.target.z; + o += e.target.o; + if (!e.action.summonGO.targetsummon) + GetBaseObject()->SummonGameObject(e.action.summonGO.entry, x, y, z, o, 0, 0, 0, 0, e.action.summonGO.despawnTime); + else + target->SummonGameObject(e.action.summonGO.entry, GetBaseObject()->GetPositionX(), GetBaseObject()->GetPositionY(), GetBaseObject()->GetPositionZ(), GetBaseObject()->GetOrientation(), 0, 0, 0, 0, e.action.summonGO.despawnTime); + } } + + if (e.GetTargetType() != SMART_TARGET_POSITION) + break; + + GetBaseObject()->SummonGameObject(e.action.summonGO.entry, e.target.x, e.target.y, e.target.z, e.target.o, 0, 0, 0, 0, e.action.summonGO.despawnTime); + break; + } case SMART_ACTION_KILL_UNIT: + { + for (WorldObject* target : targets) { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; + if (!IsUnit(target)) + continue; - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - { - if (!IsUnit(*itr)) - continue; - - Unit::Kill((*itr)->ToUnit(), (*itr)->ToUnit()); - } - - delete targets; - break; + Unit::Kill(target->ToUnit(), target->ToUnit()); } + + break; + } case SMART_ACTION_INSTALL_AI_TEMPLATE: - { - InstallTemplate(e); - break; - } + { + InstallTemplate(e); + break; + } case SMART_ACTION_ADD_ITEM: + { + for (WorldObject* target : targets) { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; + if (!IsPlayer(target)) + continue; - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - { - if (!IsPlayer(*itr)) - continue; - - (*itr)->ToPlayer()->AddItem(e.action.item.entry, e.action.item.count); - } - - delete targets; - break; + target->ToPlayer()->AddItem(e.action.item.entry, e.action.item.count); } + break; + } case SMART_ACTION_REMOVE_ITEM: + { + for (WorldObject* target : targets) { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; + if (!IsPlayer(target)) + continue; - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - { - if (!IsPlayer(*itr)) - continue; - - (*itr)->ToPlayer()->DestroyItemCount(e.action.item.entry, e.action.item.count, true); - } - - delete targets; - break; + target->ToPlayer()->DestroyItemCount(e.action.item.entry, e.action.item.count, true); } + break; + } case SMART_ACTION_STORE_TARGET_LIST: - { - ObjectList* targets = GetTargets(e, unit); - StoreTargetList(targets, e.action.storeTargets.id); - break; - } + { + StoreTargetList(targets, e.action.storeTargets.id); + break; + } case SMART_ACTION_TELEPORT: + { + for (WorldObject* target : targets) { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - { - if (IsPlayer(*itr)) - (*itr)->ToPlayer()->TeleportTo(e.action.teleport.mapID, e.target.x, e.target.y, e.target.z, e.target.o); - else if (IsUnit(*itr)) - (*itr)->ToUnit()->NearTeleportTo(e.target.x, e.target.y, e.target.z, e.target.o); - } - - delete targets; - break; + if (IsPlayer(target)) + target->ToPlayer()->TeleportTo(e.action.teleport.mapID, e.target.x, e.target.y, e.target.z, e.target.o); + else if (IsCreature(target)) + target->ToCreature()->NearTeleportTo(e.target.x, e.target.y, e.target.z, e.target.o); } + break; + } case SMART_ACTION_SET_FLY: - { - if (!IsSmart()) - break; - - CAST_AI(SmartAI, me->AI())->SetFly(e.action.setFly.fly); - // Xinef: Set speed if any - if (e.action.setFly.speed) - me->SetSpeed(MOVE_RUN, float(e.action.setFly.speed / 100.0f), true); - - // Xinef: this wil be executed only if state is different - me->SetDisableGravity(e.action.setFly.disableGravity); + { + if (!IsSmart()) break; - } + + CAST_AI(SmartAI, me->AI())->SetFly(e.action.setFly.fly); + // Xinef: Set speed if any + if (e.action.setFly.speed) + me->SetSpeed(MOVE_RUN, float(e.action.setFly.speed / 100.0f), true); + + // Xinef: this wil be executed only if state is different + me->SetDisableGravity(e.action.setFly.disableGravity); + break; + } case SMART_ACTION_SET_RUN: + { + for (WorldObject* target : targets) { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) + if (IsCreature(target)) { - if (IsCreature(*itr)) - { - if (IsSmart((*itr)->ToCreature())) - CAST_AI(SmartAI, (*itr)->ToCreature()->AI())->SetRun(e.action.setRun.run); - else - (*itr)->ToCreature()->SetWalk(e.action.setRun.run ? false : true); // Xinef: reversed - } + if (IsSmart(target->ToCreature())) + CAST_AI(SmartAI, target->ToCreature()->AI())->SetRun(e.action.setRun.run); + else + target->ToCreature()->SetWalk(e.action.setRun.run ? false : true); // Xinef: reversed } - - delete targets; - break; } + + break; + } case SMART_ACTION_SET_SWIM: - { - if (!IsSmart()) - break; - - CAST_AI(SmartAI, me->AI())->SetSwim(e.action.setSwim.swim); + { + if (!IsSmart()) break; - } + + CAST_AI(SmartAI, me->AI())->SetSwim(e.action.setSwim.swim); + break; + } case SMART_ACTION_SET_COUNTER: + { + if (!targets.empty()) { - if (ObjectList* targets = GetTargets(e, unit)) + for (WorldObject* target : targets) { - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) + if (IsCreature(target)) { - if (IsCreature(*itr)) - { - if (SmartAI* ai = CAST_AI(SmartAI, (*itr)->ToCreature()->AI())) - ai->GetScript()->StoreCounter(e.action.setCounter.counterId, e.action.setCounter.value, e.action.setCounter.reset, e.action.setCounter.subtract); - else - LOG_ERROR("scripts.ai.sai", "SmartScript: Action target for SMART_ACTION_SET_COUNTER is not using SmartAI, skipping"); - } - else if (IsGameObject(*itr)) - { - if (SmartGameObjectAI* ai = CAST_AI(SmartGameObjectAI, (*itr)->ToGameObject()->AI())) - ai->GetScript()->StoreCounter(e.action.setCounter.counterId, e.action.setCounter.value, e.action.setCounter.reset, e.action.setCounter.subtract); - else - LOG_ERROR("scripts.ai.sai", "SmartScript: Action target for SMART_ACTION_SET_COUNTER is not using SmartGameObjectAI, skipping"); - } + if (SmartAI* ai = CAST_AI(SmartAI, target->ToCreature()->AI())) + ai->GetScript()->StoreCounter(e.action.setCounter.counterId, e.action.setCounter.value, e.action.setCounter.reset, e.action.setCounter.subtract); + else + LOG_ERROR("sql.sql", "SmartScript: Action target for SMART_ACTION_SET_COUNTER is not using SmartAI, skipping"); + } + else if (IsGameObject(target)) + { + if (SmartGameObjectAI* ai = CAST_AI(SmartGameObjectAI, target->ToGameObject()->AI())) + ai->GetScript()->StoreCounter(e.action.setCounter.counterId, e.action.setCounter.value, e.action.setCounter.reset, e.action.setCounter.subtract); + else + LOG_ERROR("sql.sql", "SmartScript: Action target for SMART_ACTION_SET_COUNTER is not using SmartGameObjectAI, skipping"); } - delete targets; } - else - { - StoreCounter(e.action.setCounter.counterId, e.action.setCounter.value, e.action.setCounter.reset, e.action.setCounter.subtract); - } - break; } + else + StoreCounter(e.action.setCounter.counterId, e.action.setCounter.value, e.action.setCounter.reset, e.action.setCounter.subtract); + break; + } case SMART_ACTION_WP_START: - { - if (!IsSmart()) - break; - - bool run = e.action.wpStart.run; - uint32 entry = e.action.wpStart.pathID; - bool repeat = e.action.wpStart.repeat; - - // Xinef: ensure that SMART_ESCORT_TARGETS contains at least one player reference - bool stored = false; - ObjectList* targets = GetTargets(e, unit); - if (targets) - { - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - { - if (IsPlayer(*itr)) - { - stored = true; - StoreTargetList(targets, SMART_ESCORT_TARGETS); - break; - } - } - if (!stored) - delete targets; - } - if (e.action.wpStart.reactState <= REACT_AGGRESSIVE) - { - me->SetReactState((ReactStates) e.action.wpStart.reactState); - } - CAST_AI(SmartAI, me->AI())->StartPath(run, entry, repeat, unit); - - uint32 quest = e.action.wpStart.quest; - uint32 DespawnTime = e.action.wpStart.despawnTime; - CAST_AI(SmartAI, me->AI())->mEscortQuestID = quest; - CAST_AI(SmartAI, me->AI())->SetDespawnTime(DespawnTime); + { + if (!IsSmart()) break; + + bool run = e.action.wpStart.run != 0; + uint32 entry = e.action.wpStart.pathID; + bool repeat = e.action.wpStart.repeat != 0; + + for (WorldObject* target : targets) + { + if (IsPlayer(target)) + { + StoreTargetList(targets, SMART_ESCORT_TARGETS); + break; + } } + + me->SetReactState((ReactStates)e.action.wpStart.reactState); + CAST_AI(SmartAI, me->AI())->StartPath(run, entry, repeat, unit); + + uint32 quest = e.action.wpStart.quest; + uint32 DespawnTime = e.action.wpStart.despawnTime; + CAST_AI(SmartAI, me->AI())->mEscortQuestID = quest; + CAST_AI(SmartAI, me->AI())->SetDespawnTime(DespawnTime); + break; + } case SMART_ACTION_WP_PAUSE: - { - if (!IsSmart()) - break; - - uint32 delay = e.action.wpPause.delay; - CAST_AI(SmartAI, me->AI())->PausePath(delay, e.GetEventType() == SMART_EVENT_WAYPOINT_REACHED ? false : true); + { + if (!IsSmart()) break; - } + + uint32 delay = e.action.wpPause.delay; + CAST_AI(SmartAI, me->AI())->PausePath(delay, e.GetEventType() == SMART_EVENT_WAYPOINT_REACHED ? false : true); + break; + } case SMART_ACTION_WP_STOP: - { - if (!IsSmart()) - break; - - uint32 DespawnTime = e.action.wpStop.despawnTime; - uint32 quest = e.action.wpStop.quest; - bool fail = e.action.wpStop.fail; - CAST_AI(SmartAI, me->AI())->StopPath(DespawnTime, quest, fail); + { + if (!IsSmart()) break; - } + + uint32 DespawnTime = e.action.wpStop.despawnTime; + uint32 quest = e.action.wpStop.quest; + bool fail = e.action.wpStop.fail; + CAST_AI(SmartAI, me->AI())->StopPath(DespawnTime, quest, fail); + break; + } case SMART_ACTION_WP_RESUME: - { - if (!IsSmart()) - break; - - CAST_AI(SmartAI, me->AI())->SetWPPauseTimer(0); + { + if (!IsSmart()) break; - } + + CAST_AI(SmartAI, me->AI())->SetWPPauseTimer(0); + break; + } case SMART_ACTION_SET_ORIENTATION: + { + if (!me) + break; + + if (e.action.orientation.random > 0) { - if (!me) - break; - - if (e.action.orientation.random > 0) - { - float randomOri = frand(0.0f, 2 * M_PI); - me->SetFacingTo(randomOri); - if (e.action.orientation.quickChange) - me->SetOrientation(randomOri); - break; - } - - if (e.GetTargetType() == SMART_TARGET_SELF) - { - me->SetFacingTo((me->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT) && me->GetTransGUID() ? me->GetTransportHomePosition() : me->GetHomePosition()).GetOrientation()); - if (e.action.orientation.quickChange) - me->SetOrientation((me->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT) && me->GetTransGUID() ? me->GetTransportHomePosition() : me->GetHomePosition()).GetOrientation()); - } - else if (e.GetTargetType() == SMART_TARGET_POSITION) - { - me->SetFacingTo(e.target.o); - if (e.action.orientation.quickChange) - me->SetOrientation(e.target.o); - } - else if (ObjectList* targets = GetTargets(e, unit)) - { - if (!targets->empty()) - { - me->SetFacingToObject(*targets->begin()); - if (e.action.orientation.quickChange) - me->SetInFront(*targets->begin()); - } - - delete targets; - } - + float randomOri = frand(0.0f, 2 * M_PI); + me->SetFacingTo(randomOri); + if (e.action.orientation.quickChange) + me->SetOrientation(randomOri); break; } + + if (e.GetTargetType() == SMART_TARGET_SELF) + { + me->SetFacingTo((me->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT) && me->GetTransGUID() ? me->GetTransportHomePosition() : me->GetHomePosition()).GetOrientation()); + if (e.action.orientation.quickChange) + me->SetOrientation((me->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT) && me->GetTransGUID() ? me->GetTransportHomePosition() : me->GetHomePosition()).GetOrientation()); + } + else if (e.GetTargetType() == SMART_TARGET_POSITION) + { + me->SetFacingTo(e.target.o); + if (e.action.orientation.quickChange) + me->SetOrientation(e.target.o); + } + else if (!targets.empty()) + { + me->SetFacingToObject(*targets.begin()); + if (e.action.orientation.quickChange) + me->SetInFront(*targets.begin()); + } + + break; + } case SMART_ACTION_PLAYMOVIE: + { + for (WorldObject* target : targets) { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; + if (!IsPlayer(target)) + continue; - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - { - if (!IsPlayer(*itr)) - continue; - - (*itr)->ToPlayer()->SendMovieStart(e.action.movie.entry); - } - - delete targets; - break; + target->ToPlayer()->SendMovieStart(e.action.movie.entry); } + break; + } case SMART_ACTION_MOVE_TO_POS: + { + if (!IsSmart()) + break; + + WorldObject* target = nullptr; + + if (e.GetTargetType() == SMART_TARGET_RANDOM_POINT) { - if (!IsSmart()) - break; - - WorldObject* target = nullptr; - - if (e.GetTargetType() == SMART_TARGET_RANDOM_POINT) + if (me) { - if (me) - { - float range = (float)e.target.randomPoint.range; - Position srcPos = { e.target.x, e.target.y, e.target.z, e.target.o }; - Position randomPoint = me->GetRandomPoint(srcPos, range); - me->GetMotionMaster()->MovePoint( + float range = (float)e.target.randomPoint.range; + Position srcPos = { e.target.x, e.target.y, e.target.z, e.target.o }; + Position randomPoint = me->GetRandomPoint(srcPos, range); + me->GetMotionMaster()->MovePoint( e.action.moveToPos.pointId, randomPoint.m_positionX, randomPoint.m_positionY, @@ -1895,174 +1587,141 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u true, true, isControlled ? MOTION_SLOT_CONTROLLED : MOTION_SLOT_ACTIVE - ); - } - - break; + ); } - /*if (e.GetTargetType() == SMART_TARGET_CREATURE_RANGE || e.GetTargetType() == SMART_TARGET_CREATURE_GUID || - e.GetTargetType() == SMART_TARGET_CREATURE_DISTANCE || e.GetTargetType() == SMART_TARGET_GAMEOBJECT_RANGE || - e.GetTargetType() == SMART_TARGET_GAMEOBJECT_GUID || e.GetTargetType() == SMART_TARGET_GAMEOBJECT_DISTANCE || - e.GetTargetType() == SMART_TARGET_CLOSEST_CREATURE || e.GetTargetType() == SMART_TARGET_CLOSEST_GAMEOBJECT || - e.GetTargetType() == SMART_TARGET_OWNER_OR_SUMMONER || e.GetTargetType() == SMART_TARGET_ACTION_INVOKER || - e.GetTargetType() == SMART_TARGET_CLOSEST_ENEMY || e.GetTargetType() == SMART_TARGET_CLOSEST_FRIENDLY || - e.GetTargetType() == SMART_TARGET_SELF || e.GetTargetType() == SMART_TARGET_STORED) // Xinef: bieda i rozpierdol TC)*/ - { - if (ObjectList* targets = GetTargets(e, unit)) - { - // xinef: we want to move to random element - target = Acore::Containers::SelectRandomContainerElement(*targets); - delete targets; - } - } - - if (!target) - { - G3D::Vector3 dest(e.target.x, e.target.y, e.target.z); - if (e.action.moveToPos.transport) - if (TransportBase* trans = me->GetDirectTransport()) - trans->CalculatePassengerPosition(dest.x, dest.y, dest.z); - - me->GetMotionMaster()->MovePoint(e.action.moveToPos.pointId, dest.x, dest.y, dest.z, true, true, - isControlled ? MOTION_SLOT_CONTROLLED : MOTION_SLOT_ACTIVE, e.target.o); - } - else // Xinef: we can use dest.x, dest.y, dest.z to make offset - { - float x, y, z; - target->GetPosition(x, y, z); - if (e.action.moveToPos.ContactDistance > 0) - target->GetContactPoint(me, x, y, z, e.action.moveToPos.ContactDistance); - me->GetMotionMaster()->MovePoint(e.action.moveToPos.pointId, x + e.target.x, y + e.target.y, z + e.target.z, true, true, isControlled ? MOTION_SLOT_CONTROLLED : MOTION_SLOT_ACTIVE); - } break; } + + /*if (e.GetTargetType() == SMART_TARGET_CREATURE_RANGE || e.GetTargetType() == SMART_TARGET_CREATURE_GUID || + e.GetTargetType() == SMART_TARGET_CREATURE_DISTANCE || e.GetTargetType() == SMART_TARGET_GAMEOBJECT_RANGE || + e.GetTargetType() == SMART_TARGET_GAMEOBJECT_GUID || e.GetTargetType() == SMART_TARGET_GAMEOBJECT_DISTANCE || + e.GetTargetType() == SMART_TARGET_CLOSEST_CREATURE || e.GetTargetType() == SMART_TARGET_CLOSEST_GAMEOBJECT || + e.GetTargetType() == SMART_TARGET_OWNER_OR_SUMMONER || e.GetTargetType() == SMART_TARGET_ACTION_INVOKER || + e.GetTargetType() == SMART_TARGET_CLOSEST_ENEMY || e.GetTargetType() == SMART_TARGET_CLOSEST_FRIENDLY || + e.GetTargetType() == SMART_TARGET_SELF || e.GetTargetType() == SMART_TARGET_STORED) // Xinef: bieda i rozpierdol TC)*/ + { + // we want to move to random element + if (!targets.empty()) + target = Acore::Containers::SelectRandomContainerElement(targets); + } + + if (!target) + { + G3D::Vector3 dest(e.target.x, e.target.y, e.target.z); + if (e.action.moveToPos.transport) + if (TransportBase* trans = me->GetDirectTransport()) + trans->CalculatePassengerPosition(dest.x, dest.y, dest.z); + + me->GetMotionMaster()->MovePoint(e.action.moveToPos.pointId, dest.x, dest.y, dest.z, true, true, + isControlled ? MOTION_SLOT_CONTROLLED : MOTION_SLOT_ACTIVE, e.target.o); + } + else // Xinef: we can use dest.x, dest.y, dest.z to make offset + { + float x, y, z; + target->GetPosition(x, y, z); + if (e.action.moveToPos.ContactDistance > 0) + target->GetContactPoint(me, x, y, z, e.action.moveToPos.ContactDistance); + me->GetMotionMaster()->MovePoint(e.action.moveToPos.pointId, x + e.target.x, y + e.target.y, z + e.target.z, true, true, isControlled ? MOTION_SLOT_CONTROLLED : MOTION_SLOT_ACTIVE); + } + break; + } case SMART_ACTION_MOVE_TO_POS_TARGET: + { + for (WorldObject* target : targets) { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - return; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) + if (IsCreature(target)) { - if (IsCreature(*itr)) - { - Creature* target = (*itr)->ToCreature(); - target->GetMotionMaster()->MovePoint(e.action.moveToPos.pointId, e.target.x, e.target.y, e.target.z, true, true, isControlled ? MOTION_SLOT_CONTROLLED : MOTION_SLOT_ACTIVE); - } + Creature* ctarget = target->ToCreature(); + ctarget->GetMotionMaster()->MovePoint(e.action.moveToPos.pointId, e.target.x, e.target.y, e.target.z, true, true, isControlled ? MOTION_SLOT_CONTROLLED : MOTION_SLOT_ACTIVE); } - - delete targets; - break; } + + break; + } case SMART_ACTION_RESPAWN_TARGET: + { + for (WorldObject* target : targets) { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) + if (IsCreature(target)) + target->ToCreature()->Respawn(); + else if (IsGameObject(target)) { - if (IsCreature(*itr)) - (*itr)->ToCreature()->Respawn(e.action.RespawnTarget.goRespawnTime); - else if (IsGameObject(*itr)) - { - // Xinef: do not modify respawndelay of already spawned gameobjects QQ - if ((*itr)->ToGameObject()->isSpawnedByDefault()) - (*itr)->ToGameObject()->Respawn(); - else - (*itr)->ToGameObject()->SetRespawnTime(e.action.RespawnTarget.goRespawnTime); - } + // do not modify respawndelay of already spawned gameobjects + if (target->ToGameObject()->isSpawnedByDefault()) + target->ToGameObject()->Respawn(); + else + target->ToGameObject()->SetRespawnTime(e.action.RespawnTarget.goRespawnTime); } - - delete targets; - break; } + break; + } case SMART_ACTION_CLOSE_GOSSIP: - { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - if (IsPlayer(*itr)) - (*itr)->ToPlayer()->PlayerTalkClass->SendCloseGossip(); - - delete targets; - break; - } + { + for (WorldObject* target : targets) + if (IsPlayer(target)) + target->ToPlayer()->PlayerTalkClass->SendCloseGossip(); + break; + } case SMART_ACTION_EQUIP: + { + for (WorldObject* target : targets) { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) + if (Creature* npc = target->ToCreature()) { - if (Creature* npc = (*itr)->ToCreature()) + std::array slot; + if (int8 equipId = static_cast(e.action.equip.entry)) { - uint32 slot[3]; - int8 equipId = (int8)e.action.equip.entry; - if (equipId) + EquipmentInfo const* eInfo = sObjectMgr->GetEquipmentInfo(npc->GetEntry(), equipId); + if (!eInfo) { - EquipmentInfo const* einfo = sObjectMgr->GetEquipmentInfo(npc->GetEntry(), equipId); - if (!einfo) - { - LOG_ERROR("scripts.ai.sai", "SmartScript: SMART_ACTION_EQUIP uses non-existent equipment info id {} for creature {}", equipId, npc->GetEntry()); - break; - } - npc->SetCurrentEquipmentId(equipId); - slot[0] = einfo->ItemEntry[0]; - slot[1] = einfo->ItemEntry[1]; - slot[2] = einfo->ItemEntry[2]; + LOG_ERROR("sql.sql", "SmartScript: SMART_ACTION_EQUIP uses non-existent equipment info id {} for creature {}", equipId, npc->GetEntry()); + break; } - else - { - slot[0] = e.action.equip.slot1; - slot[1] = e.action.equip.slot2; - slot[2] = e.action.equip.slot3; - } - if (!e.action.equip.mask || (e.action.equip.mask & 1)) - npc->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 0, slot[0]); - if (!e.action.equip.mask || (e.action.equip.mask & 2)) - npc->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 1, slot[1]); - if (!e.action.equip.mask || (e.action.equip.mask & 4)) - npc->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 2, slot[2]); + + npc->SetCurrentEquipmentId(equipId); + + std::copy(std::begin(eInfo->ItemEntry), std::end(eInfo->ItemEntry), std::begin(slot)); } + else + std::copy(std::begin(e.action.equip.slots), std::end(e.action.equip.slots), std::begin(slot)); + + for (uint32 i = 0; i < MAX_EQUIPMENT_ITEMS; ++i) + if (!e.action.equip.mask || (e.action.equip.mask & (1 << i))) + npc->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + i, slot[i]); } - - delete targets; - break; } + break; + } case SMART_ACTION_CREATE_TIMED_EVENT: - { - SmartEvent ne = SmartEvent(); - ne.type = (SMART_EVENT)SMART_EVENT_UPDATE; - ne.event_chance = e.action.timeEvent.chance; - if (!ne.event_chance) ne.event_chance = 100; + { + SmartEvent ne = SmartEvent(); + ne.type = (SMART_EVENT)SMART_EVENT_UPDATE; + ne.event_chance = e.action.timeEvent.chance; + if (!ne.event_chance) ne.event_chance = 100; - ne.minMaxRepeat.min = e.action.timeEvent.min; - ne.minMaxRepeat.max = e.action.timeEvent.max; - ne.minMaxRepeat.repeatMin = e.action.timeEvent.repeatMin; - ne.minMaxRepeat.repeatMax = e.action.timeEvent.repeatMax; + ne.minMaxRepeat.min = e.action.timeEvent.min; + ne.minMaxRepeat.max = e.action.timeEvent.max; + ne.minMaxRepeat.repeatMin = e.action.timeEvent.repeatMin; + ne.minMaxRepeat.repeatMax = e.action.timeEvent.repeatMax; - ne.event_flags = 0; - if (!ne.minMaxRepeat.repeatMin && !ne.minMaxRepeat.repeatMax) - ne.event_flags |= SMART_EVENT_FLAG_NOT_REPEATABLE; + ne.event_flags = 0; + if (!ne.minMaxRepeat.repeatMin && !ne.minMaxRepeat.repeatMax) + ne.event_flags |= SMART_EVENT_FLAG_NOT_REPEATABLE; - SmartAction ac = SmartAction(); - ac.type = (SMART_ACTION)SMART_ACTION_TRIGGER_TIMED_EVENT; - ac.timeEvent.id = e.action.timeEvent.id; + SmartAction ac = SmartAction(); + ac.type = (SMART_ACTION)SMART_ACTION_TRIGGER_TIMED_EVENT; + ac.timeEvent.id = e.action.timeEvent.id; - SmartScriptHolder ev = SmartScriptHolder(); - ev.event = ne; - ev.event_id = e.action.timeEvent.id; - ev.target = e.target; - ev.action = ac; - InitTimer(ev); - mStoredEvents.push_back(ev); - break; - } + SmartScriptHolder ev = SmartScriptHolder(); + ev.event = ne; + ev.event_id = e.action.timeEvent.id; + ev.target = e.target; + ev.action = ac; + InitTimer(ev); + mStoredEvents.push_back(ev); + break; + } case SMART_ACTION_TRIGGER_TIMED_EVENT: ProcessEventsFor((SMART_EVENT)SMART_EVENT_TIMED_EVENT_TRIGGERED, nullptr, e.action.timeEvent.id); @@ -2074,38 +1733,33 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u mRemIDs.push_back(e.action.timeEvent.id); break; case SMART_ACTION_OVERRIDE_SCRIPT_BASE_OBJECT: + { + for (WorldObject* target : targets) { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::iterator itr = targets->begin(); itr != targets->end(); ++itr) + if (IsCreature(target)) { - if (IsCreature(*itr)) - { - if (!meOrigGUID) - meOrigGUID = me ? me->GetGUID() : ObjectGuid::Empty; - if (!goOrigGUID) - goOrigGUID = go ? go->GetGUID() : ObjectGuid::Empty; - go = nullptr; - me = (*itr)->ToCreature(); - break; - } - else if (IsGameObject(*itr)) - { - if (!meOrigGUID) - meOrigGUID = me ? me->GetGUID() : ObjectGuid::Empty; - if (!goOrigGUID) - goOrigGUID = go ? go->GetGUID() : ObjectGuid::Empty; - go = (*itr)->ToGameObject(); - me = nullptr; - break; - } + if (!meOrigGUID) + meOrigGUID = me ? me->GetGUID() : ObjectGuid::Empty; + if (!goOrigGUID) + goOrigGUID = go ? go->GetGUID() : ObjectGuid::Empty; + go = nullptr; + me = target->ToCreature(); + break; + } + else if (IsGameObject(target)) + { + if (!meOrigGUID) + meOrigGUID = me ? me->GetGUID() : ObjectGuid::Empty; + if (!goOrigGUID) + goOrigGUID = go ? go->GetGUID() : ObjectGuid::Empty; + go = target->ToGameObject(); + me = nullptr; + break; } - - delete targets; - break; } + + break; + } case SMART_ACTION_RESET_SCRIPT_BASE_OBJECT: ResetBaseObject(); break; @@ -2113,1291 +1767,911 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u OnReset(); break; case SMART_ACTION_SET_RANGED_MOVEMENT: - { - if (!IsSmart()) - break; - - float attackDistance = float(e.action.setRangedMovement.distance); - float attackAngle = float(e.action.setRangedMovement.angle) / 180.0f * M_PI; - - ObjectList* targets = GetTargets(e, unit); - if (targets) - { - for (ObjectList::iterator itr = targets->begin(); itr != targets->end(); ++itr) - if (Creature* target = (*itr)->ToCreature()) - if (IsSmart(target) && target->GetVictim()) - if (CAST_AI(SmartAI, target->AI())->CanCombatMove()) - target->GetMotionMaster()->MoveChase(target->GetVictim(), attackDistance, attackAngle); - - delete targets; - } + { + if (!IsSmart()) break; - } + + float attackDistance = float(e.action.setRangedMovement.distance); + float attackAngle = float(e.action.setRangedMovement.angle) / 180.0f * float(M_PI); + + for (WorldObject* target : targets) + if (Creature* creature = target->ToCreature()) + if (IsSmart(creature) && creature->GetVictim()) + if (CAST_AI(SmartAI, creature->AI())->CanCombatMove()) + creature->GetMotionMaster()->MoveChase(creature->GetVictim(), attackDistance, attackAngle); + + break; + } case SMART_ACTION_CALL_TIMED_ACTIONLIST: + { + if (e.GetTargetType() == SMART_TARGET_NONE) { - if (e.GetTargetType() == SMART_TARGET_NONE) - { - LOG_ERROR("sql.sql", "SmartScript: Entry {} SourceType {} Event {} Action {} is using TARGET_NONE(0) for Script9 target. Please correct target_type in database.", e.entryOrGuid, e.GetScriptType(), e.GetEventType(), e.GetActionType()); - break; - } - - if (ObjectList* targets = GetTargets(e, unit)) - { - for (ObjectList::iterator itr = targets->begin(); itr != targets->end(); ++itr) - { - if (Creature* target = (*itr)->ToCreature()) - { - if (IsSmart(target)) - CAST_AI(SmartAI, target->AI())->SetScript9(e, e.action.timedActionList.id, GetLastInvoker()); - } - else if (GameObject* goTarget = (*itr)->ToGameObject()) - { - if (IsSmartGO(goTarget)) - CAST_AI(SmartGameObjectAI, goTarget->AI())->SetScript9(e, e.action.timedActionList.id, GetLastInvoker()); - } - } - - delete targets; - } + LOG_ERROR("sql.sql", "SmartScript: Entry {} SourceType {} Event {} Action {} is using TARGET_NONE(0) for Script9 target. Please correct target_type in database.", e.entryOrGuid, e.GetScriptType(), e.GetEventType(), e.GetActionType()); break; } + + for (WorldObject* target : targets) + { + if (Creature* creature = target->ToCreature()) + { + if (IsSmart(creature)) + CAST_AI(SmartAI, creature->AI())->SetScript9(e, e.action.timedActionList.id, GetLastInvoker()); + } + else if (GameObject* go = target->ToGameObject()) + { + if (IsSmartGO(go)) + CAST_AI(SmartGameObjectAI, go->AI())->SetScript9(e, e.action.timedActionList.id, GetLastInvoker()); + } + } + break; + } case SMART_ACTION_SET_NPC_FLAG: - { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - if (IsCreature(*itr)) - (*itr)->ToUnit()->ReplaceAllNpcFlags(NPCFlags(e.action.flag.flag)); - - delete targets; - break; - } + { + for (WorldObject* target : targets) + if (IsCreature(target)) + target->ToUnit()->SetUInt32Value(UNIT_NPC_FLAGS, e.action.unitFlag.flag); + break; + } case SMART_ACTION_ADD_NPC_FLAG: - { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - if (IsCreature(*itr)) - (*itr)->ToUnit()->SetNpcFlag(NPCFlags(e.action.flag.flag)); - - delete targets; - break; - } + { + for (WorldObject* target : targets) + if (IsCreature(target)) + target->ToUnit()->SetFlag(UNIT_NPC_FLAGS, e.action.unitFlag.flag); + break; + } case SMART_ACTION_REMOVE_NPC_FLAG: - { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - if (IsCreature(*itr)) - (*itr)->ToUnit()->RemoveNpcFlag(NPCFlags(e.action.flag.flag)); - - delete targets; - break; - } + { + for (WorldObject* target : targets) + if (IsCreature(target)) + target->ToUnit()->RemoveFlag(UNIT_NPC_FLAGS, e.action.unitFlag.flag); + break; + } case SMART_ACTION_CROSS_CAST: + { + if (targets.empty()) + break; + + ObjectVector casters; + GetTargets(casters, CreateSmartEvent(SMART_EVENT_UPDATE_IC, 0, 0, 0, 0, 0, 0, SMART_ACTION_NONE, 0, 0, 0, 0, 0, 0, (SMARTAI_TARGETS)e.action.crossCast.targetType, e.action.crossCast.targetParam1, e.action.crossCast.targetParam2, e.action.crossCast.targetParam3, 0, 0), unit); + + for (WorldObject* caster : casters) { - ObjectList* casters = GetTargets(CreateSmartEvent(SMART_EVENT_UPDATE_IC, 0, 0, 0, 0, 0, 0, SMART_ACTION_NONE, 0, 0, 0, 0, 0, 0, (SMARTAI_TARGETS)e.action.crossCast.targetType, e.action.crossCast.targetParam1, e.action.crossCast.targetParam2, e.action.crossCast.targetParam3, 0, 0), unit); - if (!casters) - break; + if (!IsUnit(caster)) + continue; - ObjectList* targets = GetTargets(e, unit); - if (!targets) - { - delete casters; // casters already validated, delete now - break; - } + Unit* casterUnit = caster->ToUnit(); - for (ObjectList::const_iterator itr = casters->begin(); itr != casters->end(); ++itr) + bool interruptedSpell = false; + + for (WorldObject* target : targets) { - if (!IsUnit(*itr)) + if (!IsUnit(target)) continue; - bool interruptedSpell = false; - - for (ObjectList::const_iterator it = targets->begin(); it != targets->end(); ++it) + if (!(e.action.crossCast.flags & SMARTCAST_AURA_NOT_PRESENT) || !target->ToUnit()->HasAura(e.action.crossCast.spell)) { - if (!IsUnit(*it)) - continue; - - if (!(e.action.cast.flags & SMARTCAST_AURA_NOT_PRESENT) || !(*it)->ToUnit()->HasAura(e.action.cast.spell)) + if (!interruptedSpell && e.action.crossCast.flags & SMARTCAST_INTERRUPT_PREVIOUS) { - if (!interruptedSpell && e.action.cast.flags & SMARTCAST_INTERRUPT_PREVIOUS) - { - (*itr)->ToUnit()->InterruptNonMeleeSpells(false); - interruptedSpell = true; - } - - (*itr)->ToUnit()->CastSpell((*it)->ToUnit(), e.action.cast.spell, (e.action.cast.flags & SMARTCAST_TRIGGERED)); + casterUnit->InterruptNonMeleeSpells(false); + interruptedSpell = true; } - else - LOG_DEBUG("sql.sql", "Spell {} not casted because it has flag SMARTCAST_AURA_NOT_PRESENT and the target {} already has the aura", - e.action.cast.spell, (*it)->GetGUID().ToString()); + + casterUnit->CastSpell(target->ToUnit(), e.action.crossCast.spell, (e.action.crossCast.flags & SMARTCAST_TRIGGERED) != 0); } - } - - delete targets; - delete casters; - break; - } - case SMART_ACTION_CALL_RANDOM_TIMED_ACTIONLIST: - { - uint32 actions[SMART_ACTION_PARAM_COUNT]; - actions[0] = e.action.randTimedActionList.entry1; - actions[1] = e.action.randTimedActionList.entry2; - actions[2] = e.action.randTimedActionList.entry3; - actions[3] = e.action.randTimedActionList.entry4; - actions[4] = e.action.randTimedActionList.entry5; - actions[5] = e.action.randTimedActionList.entry6; - uint32 temp[SMART_ACTION_PARAM_COUNT]; - uint32 count = 0; - for (uint8 i = 0; i < SMART_ACTION_PARAM_COUNT; i++) - { - if (actions[i] > 0) - { - temp[count] = actions[i]; - ++count; - } - } - - if (count == 0) - break; - - uint32 id = temp[urand(0, count - 1)]; - if (e.GetTargetType() == SMART_TARGET_NONE) - { - LOG_ERROR("sql.sql", "SmartScript: Entry {} SourceType {} Event {} Action {} is using TARGET_NONE(0) for Script9 target. Please correct target_type in database.", e.entryOrGuid, e.GetScriptType(), e.GetEventType(), e.GetActionType()); - break; - } - - ObjectList* targets = GetTargets(e, unit); - if (targets) - { - for (ObjectList::iterator itr = targets->begin(); itr != targets->end(); ++itr) - { - if (Creature* target = (*itr)->ToCreature()) - { - if (IsSmart(target)) - CAST_AI(SmartAI, target->AI())->SetScript9(e, id, GetLastInvoker()); - } - else if (GameObject* goTarget = (*itr)->ToGameObject()) - { - if (IsSmartGO(goTarget)) - CAST_AI(SmartGameObjectAI, goTarget->AI())->SetScript9(e, id, GetLastInvoker()); - } - } - - delete targets; - } - break; - } - case SMART_ACTION_CALL_RANDOM_RANGE_TIMED_ACTIONLIST: - { - uint32 id = urand(e.action.randRangeTimedActionList.idMin, e.action.randRangeTimedActionList.idMax); - if (e.GetTargetType() == SMART_TARGET_NONE) - { - LOG_ERROR("sql.sql", "SmartScript: Entry {} SourceType {} Event {} Action {} is using TARGET_NONE(0) for Script9 target. Please correct target_type in database.", e.entryOrGuid, e.GetScriptType(), e.GetEventType(), e.GetActionType()); - break; - } - - ObjectList* targets = GetTargets(e, unit); - if (targets) - { - for (ObjectList::iterator itr = targets->begin(); itr != targets->end(); ++itr) - { - if (Creature* target = (*itr)->ToCreature()) - { - if (IsSmart(target)) - CAST_AI(SmartAI, target->AI())->SetScript9(e, id, GetLastInvoker()); - } - else if (GameObject* goTarget = (*itr)->ToGameObject()) - { - if (IsSmartGO(goTarget)) - CAST_AI(SmartGameObjectAI, goTarget->AI())->SetScript9(e, id, GetLastInvoker()); - } - } - - delete targets; - } - break; - } - case SMART_ACTION_ACTIVATE_TAXI: - { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - if (IsPlayer(*itr)) - (*itr)->ToPlayer()->ActivateTaxiPathTo(e.action.taxi.id); - - delete targets; - break; - } - case SMART_ACTION_RANDOM_MOVE: - { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - bool foundTarget = false; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - { - if (IsCreature((*itr))) - { - foundTarget = true; - - if (e.action.moveRandom.distance) - (*itr)->ToCreature()->GetMotionMaster()->MoveRandom((float)e.action.moveRandom.distance); - else - (*itr)->ToCreature()->GetMotionMaster()->MoveIdle(); - } - } - - if (!foundTarget && me && IsCreature(me)) - { - if (e.action.moveRandom.distance) - me->GetMotionMaster()->MoveRandom((float)e.action.moveRandom.distance); else - me->GetMotionMaster()->MoveIdle(); + LOG_DEBUG("scripts.ai", "Spell {} not cast because it has flag SMARTCAST_AURA_NOT_PRESENT and the target ({}) already has the aura", e.action.crossCast.spell, target->GetGUID().ToString()); } + } + break; + } + case SMART_ACTION_CALL_RANDOM_TIMED_ACTIONLIST: + { + std::vector actionLists; + std::copy_if(e.action.randTimedActionList.actionLists.begin(), e.action.randTimedActionList.actionLists.end(), + std::back_inserter(actionLists), [](uint32 actionList) { return actionList != 0; }); - delete targets; + uint32 id = Acore::Containers::SelectRandomContainerElement(actionLists); + if (e.GetTargetType() == SMART_TARGET_NONE) + { + LOG_ERROR("sql.sql", "SmartScript: Entry {} SourceType {} Event {} Action {} is using TARGET_NONE(0) for Script9 target. Please correct target_type in database.", e.entryOrGuid, e.GetScriptType(), e.GetEventType(), e.GetActionType()); break; } - case SMART_ACTION_SET_UNIT_FIELD_BYTES_1: + + for (WorldObject* target : targets) { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - if (IsUnit(*itr)) - (*itr)->ToUnit()->SetByteFlag(UNIT_FIELD_BYTES_1, e.action.setunitByte.type, e.action.setunitByte.byte1); - - delete targets; - break; - } - case SMART_ACTION_REMOVE_UNIT_FIELD_BYTES_1: - { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - if (IsUnit(*itr)) - (*itr)->ToUnit()->RemoveByteFlag(UNIT_FIELD_BYTES_1, e.action.delunitByte.type, e.action.delunitByte.byte1); - - delete targets; - break; - } - case SMART_ACTION_INTERRUPT_SPELL: - { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - if (IsUnit(*itr)) - (*itr)->ToUnit()->InterruptNonMeleeSpells(e.action.interruptSpellCasting.withDelayed, e.action.interruptSpellCasting.spell_id, e.action.interruptSpellCasting.withInstant); - - delete targets; - break; - } - case SMART_ACTION_SEND_GO_CUSTOM_ANIM: - { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - if (IsGameObject(*itr)) - (*itr)->ToGameObject()->SendCustomAnim(e.action.sendGoCustomAnim.anim); - - delete targets; - break; - } - case SMART_ACTION_SET_DYNAMIC_FLAG: - { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - if (IsUnit(*itr)) - (*itr)->ToUnit()->ReplaceAllDynamicFlags(e.action.flag.flag); - - delete targets; - break; - } - case SMART_ACTION_ADD_DYNAMIC_FLAG: - { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - if (IsUnit(*itr)) - (*itr)->ToUnit()->SetDynamicFlag(e.action.flag.flag); - - delete targets; - break; - } - case SMART_ACTION_REMOVE_DYNAMIC_FLAG: - { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - if (IsUnit(*itr)) - (*itr)->ToUnit()->RemoveDynamicFlag(e.action.flag.flag); - - delete targets; - break; - } - case SMART_ACTION_JUMP_TO_POS: - { - if (e.GetTargetType() == SMART_TARGET_RANDOM_POINT) + if (Creature* creature = target->ToCreature()) { - if (me) - { - float range = (float)e.target.randomPoint.range; - Position srcPos = { e.target.x, e.target.y, e.target.z, e.target.o }; - Position randomPoint = me->GetRandomPoint(srcPos, range); - me->GetMotionMaster()->MoveJump(randomPoint, (float)e.action.jump.speedxy, (float)e.action.jump.speedz); - } - - break; + if (IsSmart(creature)) + CAST_AI(SmartAI, creature->AI())->SetScript9(e, id, GetLastInvoker()); } - - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - // xinef: my implementation - if (e.action.jump.selfJump) + else if (GameObject* go = target->ToGameObject()) { - if (WorldObject* target = Acore::Containers::SelectRandomContainerElement(*targets)) - if (me) - me->GetMotionMaster()->MoveJump(target->GetPositionX() + e.target.x, target->GetPositionY() + e.target.y, target->GetPositionZ() + e.target.z, (float)e.action.jump.speedxy, (float)e.action.jump.speedz); + if (IsSmartGO(go)) + CAST_AI(SmartGameObjectAI, go->AI())->SetScript9(e, id, GetLastInvoker()); } + } + break; + } + case SMART_ACTION_CALL_RANDOM_RANGE_TIMED_ACTIONLIST: + { + uint32 id = urand(e.action.randTimedActionList.actionLists[0], e.action.randTimedActionList.actionLists[1]); + if (e.GetTargetType() == SMART_TARGET_NONE) + { + LOG_ERROR("sql.sql", "SmartScript: Entry {} SourceType {} Event {} Action {} is using TARGET_NONE(0) for Script9 target. Please correct target_type in database.", e.entryOrGuid, e.GetScriptType(), e.GetEventType(), e.GetActionType()); + break; + } + + for (WorldObject* target : targets) + { + if (Creature* creature = target->ToCreature()) + { + if (IsSmart(creature)) + CAST_AI(SmartAI, creature->AI())->SetScript9(e, id, GetLastInvoker()); + } + else if (GameObject* go = target->ToGameObject()) + { + if (IsSmartGO(go)) + CAST_AI(SmartGameObjectAI, go->AI())->SetScript9(e, id, GetLastInvoker()); + } + } + break; + } + case SMART_ACTION_ACTIVATE_TAXI: + { + for (WorldObject* target : targets) + if (IsPlayer(target)) + target->ToPlayer()->ActivateTaxiPathTo(e.action.taxi.id); + break; + } + case SMART_ACTION_RANDOM_MOVE: + { + bool foundTarget = false; + + for (WorldObject* target : targets) + { + if (IsCreature((target))) + { + foundTarget = true; + + if (e.action.moveRandom.distance) + target->ToCreature()->GetMotionMaster()->MoveRandom(float(e.action.moveRandom.distance)); + else + target->ToCreature()->GetMotionMaster()->MoveIdle(); + } + } + + if (!foundTarget && me && IsCreature(me)) + { + if (e.action.moveRandom.distance) + me->GetMotionMaster()->MoveRandom(float(e.action.moveRandom.distance)); else + me->GetMotionMaster()->MoveIdle(); + } + break; + } + case SMART_ACTION_SET_UNIT_FIELD_BYTES_1: + { + for (WorldObject* target : targets) + if (IsUnit(target)) + target->ToUnit()->SetByteFlag(UNIT_FIELD_BYTES_1, e.action.setunitByte.type, e.action.setunitByte.byte1); + break; + } + case SMART_ACTION_REMOVE_UNIT_FIELD_BYTES_1: + { + for (WorldObject* target : targets) + if (IsUnit(target)) + target->ToUnit()->RemoveByteFlag(UNIT_FIELD_BYTES_1, e.action.delunitByte.type, e.action.delunitByte.byte1); + break; + } + case SMART_ACTION_INTERRUPT_SPELL: + { + for (WorldObject* target : targets) + if (IsUnit(target)) + target->ToUnit()->InterruptNonMeleeSpells(e.action.interruptSpellCasting.withDelayed != 0, e.action.interruptSpellCasting.spell_id, e.action.interruptSpellCasting.withInstant != 0); + break; + } + case SMART_ACTION_SEND_GO_CUSTOM_ANIM: + { + for (WorldObject* target : targets) + if (IsGameObject(target)) + target->ToGameObject()->SendCustomAnim(e.action.sendGoCustomAnim.anim); + break; + } + case SMART_ACTION_SET_DYNAMIC_FLAG: + { + for (WorldObject* target : targets) + if (IsUnit(target)) + target->ToUnit()->SetUInt32Value(UNIT_DYNAMIC_FLAGS, e.action.unitFlag.flag); + break; + } + case SMART_ACTION_ADD_DYNAMIC_FLAG: + { + for (WorldObject* target : targets) + if (IsUnit(target)) + target->ToUnit()->SetFlag(UNIT_DYNAMIC_FLAGS, e.action.unitFlag.flag); + break; + } + case SMART_ACTION_REMOVE_DYNAMIC_FLAG: + { + for (WorldObject* target : targets) + if (IsUnit(target)) + target->ToUnit()->RemoveFlag(UNIT_DYNAMIC_FLAGS, e.action.unitFlag.flag); + break; + } + case SMART_ACTION_JUMP_TO_POS: + { + if (e.GetTargetType() == SMART_TARGET_RANDOM_POINT) + { + if (me) { - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - if (WorldObject* obj = (*itr)) - { - if (Creature* creature = obj->ToCreature()) - creature->GetMotionMaster()->MoveJump(e.target.x, e.target.y, e.target.z, (float)e.action.jump.speedxy, (float)e.action.jump.speedz); - } + float range = (float)e.target.randomPoint.range; + Position srcPos = { e.target.x, e.target.y, e.target.z, e.target.o }; + Position randomPoint = me->GetRandomPoint(srcPos, range); + me->GetMotionMaster()->MoveJump(randomPoint, (float)e.action.jump.speedxy, (float)e.action.jump.speedz); } - delete targets; break; } + + if (targets.empty()) + break; + + // xinef: my implementation + if (e.action.jump.selfJump) + { + if (WorldObject* target = Acore::Containers::SelectRandomContainerElement(targets)) + if (me) + me->GetMotionMaster()->MoveJump(target->GetPositionX() + e.target.x, target->GetPositionY() + e.target.y, target->GetPositionZ() + e.target.z, (float)e.action.jump.speedxy, (float)e.action.jump.speedz); + } + else + { + for (WorldObject* target : targets) + if (WorldObject* obj = (target)) + { + if (Creature* creature = obj->ToCreature()) + creature->GetMotionMaster()->MoveJump(e.target.x, e.target.y, e.target.z, (float)e.action.jump.speedxy, (float)e.action.jump.speedz); + } + } + + break; + } case SMART_ACTION_GO_SET_LOOT_STATE: - { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - if (IsGameObject(*itr)) - (*itr)->ToGameObject()->SetLootState((LootState)e.action.setGoLootState.state); - - delete targets; - break; - } + { + for (WorldObject* target : targets) + if (IsGameObject(target)) + target->ToGameObject()->SetLootState((LootState)e.action.setGoLootState.state); + break; + } case SMART_ACTION_GO_SET_GO_STATE: - { - ObjectList* targets = GetTargets(e, unit); - - if (!targets) - { - break; - } - - for (auto const& target : *targets) - { - if (IsGameObject(target)) - { - target->ToGameObject()->SetGoState((GOState)e.action.goState.state); - } - } - - delete targets; - break; - } + { + for (WorldObject* target : targets) + if (IsGameObject(target)) + target->ToGameObject()->SetGoState((GOState)e.action.goState.state); + break; + } case SMART_ACTION_SEND_TARGET_TO_TARGET: - { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - ObjectList* storedTargets = GetTargetList(e.action.sendTargetToTarget.id); - if (!storedTargets) - { - delete targets; - break; - } - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - { - if (IsCreature(*itr)) - { - if (SmartAI* ai = CAST_AI(SmartAI, (*itr)->ToCreature()->AI())) - ai->GetScript()->StoreTargetList(new ObjectList(*storedTargets), e.action.sendTargetToTarget.id); // store a copy of target list - else - LOG_ERROR("sql.sql", "SmartScript: Action target for SMART_ACTION_SEND_TARGET_TO_TARGET is not using SmartAI, skipping"); - } - else if (IsGameObject(*itr)) - { - if (SmartGameObjectAI* ai = CAST_AI(SmartGameObjectAI, (*itr)->ToGameObject()->AI())) - ai->GetScript()->StoreTargetList(new ObjectList(*storedTargets), e.action.sendTargetToTarget.id); // store a copy of target list - else - LOG_ERROR("sql.sql", "SmartScript: Action target for SMART_ACTION_SEND_TARGET_TO_TARGET is not using SmartGameObjectAI, skipping"); - } - } - - delete targets; + { + ObjectVector const* storedTargets = GetStoredTargetVector(e.action.sendTargetToTarget.id); + if (!storedTargets) break; + + for (WorldObject* target : targets) + { + if (IsCreature(target)) + { + if (SmartAI* ai = CAST_AI(SmartAI, target->ToCreature()->AI())) + ai->GetScript()->StoreTargetList(ObjectVector(*storedTargets), e.action.sendTargetToTarget.id); // store a copy of target list + else + LOG_ERROR("sql.sql", "SmartScript: Action target for SMART_ACTION_SEND_TARGET_TO_TARGET is not using SmartAI, skipping"); + } + else if (IsGameObject(target)) + { + if (SmartGameObjectAI* ai = CAST_AI(SmartGameObjectAI, target->ToGameObject()->AI())) + ai->GetScript()->StoreTargetList(ObjectVector(*storedTargets), e.action.sendTargetToTarget.id); // store a copy of target list + else + LOG_ERROR("sql.sql", "SmartScript: Action target for SMART_ACTION_SEND_TARGET_TO_TARGET is not using SmartGameObjectAI, skipping"); + } } + break; + } case SMART_ACTION_SEND_GOSSIP_MENU: - { - if (!GetBaseObject()) - break; - - LOG_DEBUG("sql.sql", "SmartScript::ProcessAction:: SMART_ACTION_SEND_GOSSIP_MENU: gossipMenuId {}, gossipNpcTextId {}", - e.action.sendGossipMenu.gossipMenuId, e.action.sendGossipMenu.gossipNpcTextId); - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - if (Player* player = (*itr)->ToPlayer()) - { - if (e.action.sendGossipMenu.gossipMenuId) - player->PrepareGossipMenu(GetBaseObject(), e.action.sendGossipMenu.gossipMenuId, true); - else - ClearGossipMenuFor(player); - - SendGossipMenuFor(player, e.action.sendGossipMenu.gossipNpcTextId, GetBaseObject()->GetGUID()); - } - - delete targets; + { + if (!GetBaseObject()) break; - } + + LOG_DEBUG("sql.sql", "SmartScript::ProcessAction:: SMART_ACTION_SEND_GOSSIP_MENU: gossipMenuId {}, gossipNpcTextId {}", + e.action.sendGossipMenu.gossipMenuId, e.action.sendGossipMenu.gossipNpcTextId); + + for (WorldObject* target : targets) + if (Player* player = target->ToPlayer()) + { + if (e.action.sendGossipMenu.gossipMenuId) + player->PrepareGossipMenu(GetBaseObject(), e.action.sendGossipMenu.gossipMenuId, true); + else + ClearGossipMenuFor(player); + + SendGossipMenuFor(player, e.action.sendGossipMenu.gossipNpcTextId, GetBaseObject()->GetGUID()); + } + + break; + } case SMART_ACTION_SET_HOME_POS: + { + if (!targets.empty()) { - ObjectList* targets = GetTargets(e, unit); - if (targets) + float x, y, z, o; + for (WorldObject* target : targets) + if (IsCreature(target)) + { + if (e.action.setHomePos.spawnPos) + { + target->ToCreature()->GetRespawnPosition(x, y, z, &o); + target->ToCreature()->SetHomePosition(x, y, z, o); + } + else + target->ToCreature()->SetHomePosition(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), target->GetOrientation()); + } + } + else if (me && e.GetTargetType() == SMART_TARGET_POSITION) + { + if (e.action.setHomePos.spawnPos) { float x, y, z, o; - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - if (IsCreature(*itr)) - { - if (e.action.setHomePos.spawnPos) - { - (*itr)->ToCreature()->GetRespawnPosition(x, y, z, &o); - (*itr)->ToCreature()->SetHomePosition(x, y, z, o); - } - else - (*itr)->ToCreature()->SetHomePosition((*itr)->GetPositionX(), (*itr)->GetPositionY(), (*itr)->GetPositionZ(), (*itr)->GetOrientation()); - } - delete targets; + me->GetRespawnPosition(x, y, z, &o); + me->SetHomePosition(x, y, z, o); } - else if (me && e.GetTargetType() == SMART_TARGET_POSITION) - { - if (e.action.setHomePos.spawnPos) - { - float x, y, z, o; - me->GetRespawnPosition(x, y, z, &o); - me->SetHomePosition(x, y, z, o); - } - else - me->SetHomePosition(e.target.x, e.target.y, e.target.z, e.target.o); - } - break; + else + me->SetHomePosition(e.target.x, e.target.y, e.target.z, e.target.o); } - /*{ - ObjectList* movers = GetTargets(CreateSmartEvent(SMART_EVENT_UPDATE_IC, 0, 0, 0, 0, 0, SMART_ACTION_NONE, 0, 0, 0, 0, 0, 0, (SMARTAI_TARGETS)e.action.sethome.targetType, e.action.sethome.targetParam1, e.action.sethome.targetParam2, e.action.sethome.targetParam3, 0), unit); - if (!movers) - break; - - if (e.GetTargetType() == SMART_TARGET_POSITION) - { - for (ObjectList::const_iterator itr = movers->begin(); itr != movers->end(); ++itr) - if (IsCreature(*itr)) - (*itr)->ToCreature()->SetHomePosition(e.target.x, e.target.y, e.target.z, e.target.o); + break; } - else if (ObjectList* targets = GetTargets(e, unit)) - { - if (WorldObject* target = targets->front()) - for (ObjectList::const_iterator itr = movers->begin(); itr != movers->end(); ++itr) - if (IsCreature(*itr)) - (*itr)->ToCreature()->SetHomePosition(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), target->GetOrientation()); - - delete targets; - } - - delete movers; - break; - }*/ case SMART_ACTION_SET_HEALTH_REGEN: - { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; + { + for (WorldObject* target : targets) + if (IsCreature(target)) + target->ToCreature()->SetRegeneratingHealth(e.action.setHealthRegen.regenHealth); - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - if (IsCreature(*itr)) - (*itr)->ToCreature()->SetRegeneratingHealth(e.action.setHealthRegen.regenHealth); - - delete targets; - break; - } + break; + } case SMART_ACTION_SET_ROOT: - { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - if (IsCreature(*itr)) - (*itr)->ToCreature()->SetControlled(e.action.setRoot.root, UNIT_STATE_ROOT); - - delete targets; - break; - } + { + for (WorldObject* target : targets) + if (IsCreature(target)) + target->ToCreature()->SetControlled(e.action.setRoot.root != 0, UNIT_STATE_ROOT); + break; + } case SMART_ACTION_SET_GO_FLAG: - { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - if (IsGameObject(*itr)) - (*itr)->ToGameObject()->ReplaceAllGameObjectFlags((GameObjectFlags)e.action.goFlag.flag); - - delete targets; - break; - } + { + for (WorldObject* target : targets) + if (IsGameObject(target)) + target->ToGameObject()->SetUInt32Value(GAMEOBJECT_FLAGS, e.action.goFlag.flag); + break; + } case SMART_ACTION_ADD_GO_FLAG: - { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - if (IsGameObject(*itr)) - (*itr)->ToGameObject()->SetGameObjectFlag((GameObjectFlags)e.action.goFlag.flag); - - delete targets; - break; - } + { + for (WorldObject* target : targets) + if (IsGameObject(target)) + target->ToGameObject()->SetFlag(GAMEOBJECT_FLAGS, e.action.goFlag.flag); + break; + } case SMART_ACTION_REMOVE_GO_FLAG: + { + for (WorldObject* target : targets) + if (IsGameObject(target)) + target->ToGameObject()->RemoveFlag(GAMEOBJECT_FLAGS, e.action.goFlag.flag); + break; + } + case SMART_ACTION_SUMMON_CREATURE_GROUP: + { + std::list summonList; + GetBaseObject()->SummonCreatureGroup(e.action.creatureGroup.group, &summonList); + + for (std::list::const_iterator itr = summonList.begin(); itr != summonList.end(); ++itr) { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - if (IsGameObject(*itr)) - (*itr)->ToGameObject()->RemoveGameObjectFlag((GameObjectFlags)e.action.goFlag.flag); - - delete targets; - break; + if (unit && e.action.creatureGroup.attackInvoker) + (*itr)->AI()->AttackStart(unit); + else if (me && e.action.creatureGroup.attackScriptOwner) + (*itr)->AI()->AttackStart(me); } - case SMART_ACTION_SUMMON_CREATURE_GROUP: - { - std::list summonList; - GetBaseObject()->SummonCreatureGroup(e.action.creatureGroup.group, &summonList); - for (std::list::const_iterator itr = summonList.begin(); itr != summonList.end(); ++itr) - { - if (unit && e.action.creatureGroup.attackInvoker) - (*itr)->AI()->AttackStart(unit); - else if (me && e.action.creatureGroup.attackScriptOwner) - (*itr)->AI()->AttackStart(me); - } - - break; - } + break; + } case SMART_ACTION_SET_POWER: - { - ObjectList* targets = GetTargets(e, unit); - - if (targets) - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - if (IsUnit(*itr)) - (*itr)->ToUnit()->SetPower(Powers(e.action.power.powerType), e.action.power.newPower); - - delete targets; - break; - } + { + for (WorldObject* target : targets) + if (IsUnit(target)) + target->ToUnit()->SetPower(Powers(e.action.power.powerType), e.action.power.newPower); + break; + } case SMART_ACTION_ADD_POWER: - { - ObjectList* targets = GetTargets(e, unit); - - if (targets) - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - if (IsUnit(*itr)) - (*itr)->ToUnit()->SetPower(Powers(e.action.power.powerType), (*itr)->ToUnit()->GetPower(Powers(e.action.power.powerType)) + e.action.power.newPower); - - delete targets; - break; - } + { + for (WorldObject* target : targets) + if (IsUnit(target)) + target->ToUnit()->SetPower(Powers(e.action.power.powerType), target->ToUnit()->GetPower(Powers(e.action.power.powerType)) + e.action.power.newPower); + break; + } case SMART_ACTION_REMOVE_POWER: - { - ObjectList* targets = GetTargets(e, unit); - - if (targets) - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - if (IsUnit(*itr)) - (*itr)->ToUnit()->SetPower(Powers(e.action.power.powerType), (*itr)->ToUnit()->GetPower(Powers(e.action.power.powerType)) - e.action.power.newPower); - - delete targets; - break; - } + { + for (WorldObject* target : targets) + if (IsUnit(target)) + target->ToUnit()->SetPower(Powers(e.action.power.powerType), target->ToUnit()->GetPower(Powers(e.action.power.powerType)) - e.action.power.newPower); + break; + } case SMART_ACTION_GAME_EVENT_STOP: + { + uint32 eventId = e.action.gameEventStop.id; + if (!sGameEventMgr->IsActiveEvent(eventId)) { - uint32 eventId = e.action.gameEventStop.id; - if (!sGameEventMgr->IsActiveEvent(eventId)) - { - LOG_ERROR("scripts.ai.sai", "SmartScript::ProcessAction: At case SMART_ACTION_GAME_EVENT_STOP, inactive event (id: {})", eventId); - break; - } - sGameEventMgr->StopEvent(eventId, true); + LOG_ERROR("scripts.ai.sai", "SmartScript::ProcessAction: At case SMART_ACTION_GAME_EVENT_STOP, inactive event (id: {})", eventId); break; } + sGameEventMgr->StopEvent(eventId, true); + break; + } case SMART_ACTION_GAME_EVENT_START: + { + uint32 eventId = e.action.gameEventStart.id; + if (sGameEventMgr->IsActiveEvent(eventId)) { - uint32 eventId = e.action.gameEventStart.id; - if (sGameEventMgr->IsActiveEvent(eventId)) - { - LOG_ERROR("scripts.ai.sai", "SmartScript::ProcessAction: At case SMART_ACTION_GAME_EVENT_START, already activated event (id: {})", eventId); - break; - } - sGameEventMgr->StartEvent(eventId, true); + LOG_ERROR("scripts.ai.sai", "SmartScript::ProcessAction: At case SMART_ACTION_GAME_EVENT_START, already activated event (id: {})", eventId); break; } + sGameEventMgr->StartEvent(eventId, true); + break; + } case SMART_ACTION_START_CLOSEST_WAYPOINT: + { + std::vector waypoints; + std::copy_if(e.action.closestWaypointFromList.wps.begin(), e.action.closestWaypointFromList.wps.end(), + std::back_inserter(waypoints), [](uint32 wp) { return wp != 0; }); + + float distanceToClosest = std::numeric_limits::max(); + WayPoint* closestWp = nullptr; + + for (WorldObject* target : targets) { - uint32 waypoints[SMART_ACTION_PARAM_COUNT]; - waypoints[0] = e.action.closestWaypointFromList.wp1; - waypoints[1] = e.action.closestWaypointFromList.wp2; - waypoints[2] = e.action.closestWaypointFromList.wp3; - waypoints[3] = e.action.closestWaypointFromList.wp4; - waypoints[4] = e.action.closestWaypointFromList.wp5; - waypoints[5] = e.action.closestWaypointFromList.wp6; - float distanceToClosest = std::numeric_limits::max(); - WayPoint* closestWp = nullptr; - - ObjectList* targets = GetTargets(e, unit); - if (targets) + if (Creature* creature = target->ToCreature()) { - for (ObjectList::iterator itr = targets->begin(); itr != targets->end(); ++itr) + if (IsSmart(creature)) { - if (Creature* target = (*itr)->ToCreature()) + for (uint32 wp : waypoints) { - if (IsSmart(target)) + WPPath* path = sSmartWaypointMgr->GetPath(wp); + if (!path || path->empty()) + continue; + + auto itrWp = path->find(0); + if (itrWp != path->end()) { - for (uint8 i = 0; i < SMART_ACTION_PARAM_COUNT; i++) + if (WayPoint* wp = itrWp->second) { - if (!waypoints[i]) - continue; - - WPPath* path = sSmartWaypointMgr->GetPath(waypoints[i]); - - if (!path || path->empty()) - continue; - - WPPath::const_iterator itrWp = path->find(0); - - if (itrWp != path->end()) + float distToThisPath = creature->GetDistance(wp->x, wp->y, wp->z); + if (distToThisPath < distanceToClosest) { - if (WayPoint* wp = itrWp->second) - { - float distToThisPath = target->GetDistance(wp->x, wp->y, wp->z); - - if (distToThisPath < distanceToClosest) - { - distanceToClosest = distToThisPath; - closestWp = wp; - } - } + distanceToClosest = distToThisPath; + closestWp = wp; } } - - if (closestWp) - CAST_AI(SmartAI, target->AI())->StartPath(false, closestWp->id, true); } } - } - delete targets; + if (closestWp) + CAST_AI(SmartAI, creature->AI())->StartPath(false, closestWp->id, true); + } } - break; } + break; + } case SMART_ACTION_SET_GO_STATE: - { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; + { + for (WorldObject* target : targets) + if (IsGameObject(target)) + target->ToGameObject()->SetGoState((GOState)e.action.goState.state); - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - if (IsGameObject(*itr)) - (*itr)->ToGameObject()->SetGoState((GOState)e.action.goState.state); - - delete targets; - break; - } + break; + } case SMART_ACTION_EXIT_VEHICLE: - { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; + { + for (WorldObject* target : targets) + if (IsUnit(target)) + target->ToUnit()->ExitVehicle(); - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - if (IsUnit(*itr)) - (*itr)->ToUnit()->ExitVehicle(); - - delete targets; - break; - } + break; + } case SMART_ACTION_SET_UNIT_MOVEMENT_FLAGS: - { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; + { + for (WorldObject* target : targets) + if (IsUnit(target)) + { + target->ToUnit()->SetUnitMovementFlags(e.action.movementFlag.flag); + target->ToUnit()->SendMovementFlagUpdate(); + } - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - if (IsUnit(*itr)) - { - (*itr)->ToUnit()->SetUnitMovementFlags(e.action.movementFlag.flag); - (*itr)->ToUnit()->SendMovementFlagUpdate(); - } - - delete targets; - break; - } + break; + } case SMART_ACTION_SET_COMBAT_DISTANCE: - { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; + { + for (WorldObject* target : targets) + if (IsCreature(target)) + target->ToCreature()->m_CombatDistance = e.action.combatDistance.dist; - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - if (IsCreature(*itr)) - (*itr)->ToCreature()->m_CombatDistance = e.action.combatDistance.dist; - - delete targets; - break; - } + break; + } case SMART_ACTION_SET_CASTER_COMBAT_DIST: - { - if (e.action.casterDistance.reset) - RestoreCasterMaxDist(); - else - SetCasterActualDist(e.action.casterDistance.dist); + { + if (e.action.casterDistance.reset) + RestoreCasterMaxDist(); + else + SetCasterActualDist(e.action.casterDistance.dist); - if (me->GetVictim() && me->GetMotionMaster()->GetCurrentMovementGeneratorType() == CHASE_MOTION_TYPE) - me->GetMotionMaster()->MoveChase(me->GetVictim(), GetCasterActualDist()); - break; - } + if (me->GetVictim() && me->GetMotionMaster()->GetCurrentMovementGeneratorType() == CHASE_MOTION_TYPE) + me->GetMotionMaster()->MoveChase(me->GetVictim(), GetCasterActualDist()); + break; + } case SMART_ACTION_SET_SIGHT_DIST: - { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - if (IsCreature(*itr)) - (*itr)->ToCreature()->m_SightDistance = e.action.sightDistance.dist; - - delete targets; - break; - } + { + for (WorldObject* const target : targets) + if (IsCreature(target)) + target->ToCreature()->m_SightDistance = e.action.sightDistance.dist; + break; + } case SMART_ACTION_FLEE: - { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - if (IsCreature(*itr)) - (*itr)->ToCreature()->GetMotionMaster()->MoveFleeing(me, e.action.flee.withEmote); - - delete targets; - break; - } + { + for (WorldObject* const target : targets) + if (IsCreature(target)) + target->ToCreature()->GetMotionMaster()->MoveFleeing(me, e.action.flee.withEmote); + break; + } case SMART_ACTION_ADD_THREAT: - { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - if (IsUnit(*itr)) - me->AddThreat((*itr)->ToUnit(), (float)e.action.threat.threatINC - (float)e.action.threat.threatDEC); - - delete targets; - break; - } + { + for (WorldObject* const target : targets) + if (IsUnit(target)) + me->AddThreat(target->ToUnit(), float(e.action.threatPCT.threatINC) - float(e.action.threatPCT.threatDEC)); + break; + } case SMART_ACTION_LOAD_EQUIPMENT: - { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - if (IsCreature(*itr)) - (*itr)->ToCreature()->LoadEquipment(e.action.loadEquipment.id, e.action.loadEquipment.force); - - delete targets; - break; - } + { + for (WorldObject* const target : targets) + if (IsCreature(target)) + target->ToCreature()->LoadEquipment(e.action.loadEquipment.id, e.action.loadEquipment.force != 0); + break; + } case SMART_ACTION_TRIGGER_RANDOM_TIMED_EVENT: - { - uint32 eventId = urand(e.action.randomTimedEvent.minId, e.action.randomTimedEvent.maxId); - ProcessEventsFor((SMART_EVENT)SMART_EVENT_TIMED_EVENT_TRIGGERED, nullptr, eventId); - break; - } + { + uint32 eventId = urand(e.action.randomTimedEvent.minId, e.action.randomTimedEvent.maxId); + ProcessEventsFor((SMART_EVENT)SMART_EVENT_TIMED_EVENT_TRIGGERED, nullptr, eventId); + break; + } case SMART_ACTION_SET_HOVER: - { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - if (IsUnit(*itr)) - (*itr)->ToUnit()->SetHover(e.action.setHover.state); - - delete targets; - break; - } + { + for (WorldObject* target : targets) + if (IsUnit(target)) + target->ToUnit()->SetHover(e.action.setHover.state); + break; + } case SMART_ACTION_ADD_IMMUNITY: - { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; + { + for (WorldObject* target : targets) + if (IsUnit(target)) + target->ToUnit()->ApplySpellImmune(e.action.immunity.id, e.action.immunity.type, e.action.immunity.value, true); - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - if (IsUnit(*itr)) - (*itr)->ToUnit()->ApplySpellImmune(e.action.immunity.id, e.action.immunity.type, e.action.immunity.value, true); - - delete targets; - break; - } + break; + } case SMART_ACTION_REMOVE_IMMUNITY: - { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - if (IsUnit(*itr)) - (*itr)->ToUnit()->ApplySpellImmune(e.action.immunity.id, e.action.immunity.type, e.action.immunity.value, false); - - delete targets; - break; - } + { + for (WorldObject* target : targets) + if (IsUnit(target)) + target->ToUnit()->ApplySpellImmune(e.action.immunity.id, e.action.immunity.type, e.action.immunity.value, false); + break; + } case SMART_ACTION_FALL: - { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; + { + for (WorldObject* target : targets) + if (IsUnit(target)) + target->ToUnit()->GetMotionMaster()->MoveFall(); - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - if (IsUnit(*itr)) - (*itr)->ToUnit()->GetMotionMaster()->MoveFall(); - - delete targets; - break; - } + break; + } case SMART_ACTION_SET_EVENT_FLAG_RESET: - { - SetPhaseReset(e.action.setActive.state); - break; - } + { + SetPhaseReset(e.action.setActive.state); + break; + } case SMART_ACTION_REMOVE_ALL_GAMEOBJECTS: - { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - if (IsUnit(*itr)) - (*itr)->ToUnit()->RemoveAllGameObjects(); - - delete targets; - break; - } + { + for (WorldObject* const target : targets) + if (IsUnit(target)) + target->ToUnit()->RemoveAllGameObjects(); + break; + } case SMART_ACTION_STOP_MOTION: + { + for (WorldObject* const target : targets) { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - if (IsUnit(*itr)) - { - if (e.action.stopMotion.stopMovement) - (*itr)->ToUnit()->StopMoving(); - if (e.action.stopMotion.movementExpired) - (*itr)->ToUnit()->GetMotionMaster()->MovementExpired(); - } - - delete targets; - break; + if (IsUnit(target)) + { + if (e.action.stopMotion.stopMovement) + target->ToUnit()->StopMoving(); + if (e.action.stopMotion.movementExpired) + target->ToUnit()->GetMotionMaster()->MovementExpired(); + } } + break; + } case SMART_ACTION_NO_ENVIRONMENT_UPDATE: - { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; + { + for (WorldObject* target : targets) + if (IsUnit(target)) + target->ToUnit()->AddUnitState(UNIT_STATE_NO_ENVIRONMENT_UPD); - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - if (IsUnit(*itr)) - (*itr)->ToUnit()->AddUnitState(UNIT_STATE_NO_ENVIRONMENT_UPD); - - delete targets; - break; - } + break; + } case SMART_ACTION_ZONE_UNDER_ATTACK: - { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - if (IsUnit(*itr)) - if (Player* player = (*itr)->ToUnit()->GetCharmerOrOwnerPlayerOrPlayerItself()) - { - me->SendZoneUnderAttackMessage(player); - break; - } - - delete targets; - break; - } - case SMART_ACTION_LOAD_GRID: - { - if (me && me->FindMap()) - me->FindMap()->LoadGrid(e.target.x, e.target.y); - break; - } - case SMART_ACTION_PLAYER_TALK: - { - ObjectList* targets = GetTargets(e, unit); - char const* text = sObjectMgr->GetAcoreString(e.action.playerTalk.textId, DEFAULT_LOCALE); - - if (targets) - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - if (IsPlayer(*itr)) - !e.action.playerTalk.flag ? (*itr)->ToPlayer()->Say(text, LANG_UNIVERSAL) : (*itr)->ToPlayer()->Yell(text, LANG_UNIVERSAL); - - delete targets; - break; - } - case SMART_ACTION_CUSTOM_CAST: - { - if (!me) - break; - - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - { - if (IsUnit(*itr)) - { - if (e.action.castCustom.flags & SMARTCAST_INTERRUPT_PREVIOUS) - me->InterruptNonMeleeSpells(false); - - if (e.action.castCustom.flags & SMARTCAST_COMBAT_MOVE) - { - // If cast flag SMARTCAST_COMBAT_MOVE is set combat movement will not be allowed - // unless target is outside spell range, out of mana, or LOS. - - bool _allowMove = false; - SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(e.action.castCustom.spell); // AssertSpellInfo? - int32 mana = me->GetPower(POWER_MANA); - - if (me->GetDistance((*itr)->ToUnit()) > spellInfo->GetMaxRange(true) || - me->GetDistance((*itr)->ToUnit()) < spellInfo->GetMinRange(true) || - !me->IsWithinLOSInMap((*itr)->ToUnit()) || - mana < spellInfo->CalcPowerCost(me, spellInfo->GetSchoolMask())) - _allowMove = true; - - CAST_AI(SmartAI, me->AI())->SetCombatMove(_allowMove); - } - - if (!(e.action.castCustom.flags & SMARTCAST_AURA_NOT_PRESENT) || !(*itr)->ToUnit()->HasAura(e.action.castCustom.spell)) - { - CustomSpellValues values; - if (e.action.castCustom.bp1) - values.AddSpellMod(SPELLVALUE_BASE_POINT0, e.action.castCustom.bp1); - if (e.action.castCustom.bp2) - values.AddSpellMod(SPELLVALUE_BASE_POINT1, e.action.castCustom.bp2); - if (e.action.castCustom.bp3) - values.AddSpellMod(SPELLVALUE_BASE_POINT2, e.action.castCustom.bp3); - me->CastCustomSpell(e.action.castCustom.spell, values, (*itr)->ToUnit(), (e.action.castCustom.flags & SMARTCAST_TRIGGERED) ? TRIGGERED_FULL_MASK : TRIGGERED_NONE); - } - } - } - delete targets; - break; - } - case SMART_ACTION_VORTEX_SUMMON: - { - if (!me) - break; - - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - TempSummonType summon_type = (e.action.summonVortex.summonDuration > 0) ? TEMPSUMMON_TIMED_DESPAWN : TEMPSUMMON_CORPSE_DESPAWN; - - float a = static_cast(e.action.summonVortex.a); - float k = static_cast(e.action.summonVortex.k) / 1000.0f; - float r_max = static_cast(e.action.summonVortex.r_max); - float delta_phi = M_PI * static_cast(e.action.summonVortex.phi_delta) / 180.0f; - - // r(phi) = a * e ^ (k * phi) - // r(phi + delta_phi) = a * e ^ (k * (phi + delta_phi)) - // r(phi + delta_phi) = a * e ^ (k * phi) * e ^ (k * delta_phi) - // r(phi + delta_phi) = r(phi) * e ^ (k * delta_phi) - float factor = std::exp(k * delta_phi); - - // r(0) = a * e ^ (k * 0) = a * e ^ 0 = a * 1 = a - float summonRadius = a; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - { - // Offset by orientation, should not count into radius calculation, - // but is needed for vortex direction (polar coordinates) - float phi = (*itr)->GetOrientation(); - - do - { - Position summonPosition(**itr); - summonPosition.RelocatePolarOffset(phi, summonRadius); - - me->SummonCreature(e.action.summonVortex.summonEntry, summonPosition, summon_type, e.action.summonVortex.summonDuration); - - phi += delta_phi; - summonRadius *= factor; - } while (summonRadius <= r_max); - } - - delete targets; - break; - } - case SMART_ACTION_CONE_SUMMON: - { - if (!me) - break; - - TempSummonType spawnType = (e.action.coneSummon.summonDuration > 0) ? TEMPSUMMON_TIMED_DESPAWN : TEMPSUMMON_CORPSE_DESPAWN; - - float distInARow = static_cast(e.action.coneSummon.distanceBetweenSummons); - float coneAngle = static_cast(e.action.coneSummon.coneAngle) * M_PI / 180.0f; - - for (uint32 radius = 0; radius <= e.action.coneSummon.coneLength; radius += e.action.coneSummon.distanceBetweenRings) - { - float deltaAngle = 0.0f; - if (radius > 0) - deltaAngle = distInARow / radius; - - uint32 count = 1; - if (deltaAngle > 0) - count += coneAngle / deltaAngle; - - float currentAngle = -static_cast(count) * deltaAngle / 2.0f; - - if (e.GetTargetType() == SMART_TARGET_SELF || e.GetTargetType() == SMART_TARGET_NONE) - currentAngle += G3D::fuzzyGt(e.target.o, 0.0f) ? (e.target.o - me->GetOrientation()) : 0.0f; - else if (ObjectList* targets = GetTargets(e, unit)) - { - currentAngle += (me->GetAngle(targets->front()) - me->GetOrientation()); - delete targets; - } - - for (uint32 index = 0; index < count; ++index) - { - Position spawnPosition(*me); - spawnPosition.RelocatePolarOffset(currentAngle, radius); - currentAngle += deltaAngle; - - me->SummonCreature(e.action.coneSummon.summonEntry, spawnPosition, spawnType, e.action.coneSummon.summonDuration); - } - } - - break; - } - case SMART_ACTION_CU_ENCOUNTER_START: - { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - { - if (Player* playerTarget = (*itr)->ToPlayer()) - { - playerTarget->RemoveArenaSpellCooldowns(); - playerTarget->RemoveAurasDueToSpell(57724); // Spell Shaman Debuff - Sated (Heroism) - playerTarget->RemoveAurasDueToSpell(57723); // Spell Shaman Debuff - Exhaustion (Bloodlust) - playerTarget->RemoveAurasDueToSpell(2825); // Bloodlust - playerTarget->RemoveAurasDueToSpell(32182); // Heroism - } - } - - delete targets; - break; - } - case SMART_ACTION_DO_ACTION: - { - int32 const actionId = e.action.doAction.isNegative ? -e.action.doAction.actionId : e.action.doAction.actionId; - if (!e.action.doAction.instanceTarget) - { - ObjectList* targets = GetTargets(e, unit); - if (!targets) + { + for (WorldObject* target : targets) + if (IsUnit(target)) + if (Player* player = target->ToUnit()->GetCharmerOrOwnerPlayerOrPlayerItself()) { + me->SendZoneUnderAttackMessage(player); break; } - for (WorldObject* objTarget : *targets) + break; + } + case SMART_ACTION_LOAD_GRID: + { + if (me && me->FindMap()) + me->FindMap()->LoadGrid(e.target.x, e.target.y); + break; + } + case SMART_ACTION_PLAYER_TALK: + { + char const* text = sObjectMgr->GetAcoreString(e.action.playerTalk.textId, DEFAULT_LOCALE); + + if (!targets.empty()) + for (WorldObject* target : targets) + if (IsPlayer(target)) + !e.action.playerTalk.flag ? target->ToPlayer()->Say(text, LANG_UNIVERSAL) : target->ToPlayer()->Yell(text, LANG_UNIVERSAL); + + break; + } + case SMART_ACTION_CUSTOM_CAST: + { + if (!me) + break; + + for (WorldObject* target : targets) + { + if (IsUnit(target)) + { + if (e.action.castCustom.flags & SMARTCAST_INTERRUPT_PREVIOUS) + me->InterruptNonMeleeSpells(false); + + if (e.action.castCustom.flags & SMARTCAST_COMBAT_MOVE) { - if (Creature const* unitTarget = objTarget->ToCreature()) - { - if (unitTarget->IsAIEnabled) - { - unitTarget->AI()->DoAction(actionId); - } - } - else if (GameObject const* gobjTarget = objTarget->ToGameObject()) - { - gobjTarget->AI()->DoAction(actionId); - } + // If cast flag SMARTCAST_COMBAT_MOVE is set combat movement will not be allowed + // unless target is outside spell range, out of mana, or LOS. + + bool _allowMove = false; + SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(e.action.castCustom.spell); // AssertSpellInfo? + int32 mana = me->GetPower(POWER_MANA); + + if (me->GetDistance(target->ToUnit()) > spellInfo->GetMaxRange(true) || + me->GetDistance(target->ToUnit()) < spellInfo->GetMinRange(true) || + !me->IsWithinLOSInMap(target->ToUnit()) || + mana < spellInfo->CalcPowerCost(me, spellInfo->GetSchoolMask())) + _allowMove = true; + + CAST_AI(SmartAI, me->AI())->SetCombatMove(_allowMove); } - delete targets; - } - else - { - InstanceScript* instanceScript = nullptr; - if (WorldObject* baseObj = GetBaseObject()) + if (!(e.action.castCustom.flags & SMARTCAST_AURA_NOT_PRESENT) || !target->ToUnit()->HasAura(e.action.castCustom.spell)) { - instanceScript = baseObj->GetInstanceScript(); + CustomSpellValues values; + if (e.action.castCustom.bp1) + values.AddSpellMod(SPELLVALUE_BASE_POINT0, e.action.castCustom.bp1); + if (e.action.castCustom.bp2) + values.AddSpellMod(SPELLVALUE_BASE_POINT1, e.action.castCustom.bp2); + if (e.action.castCustom.bp3) + values.AddSpellMod(SPELLVALUE_BASE_POINT2, e.action.castCustom.bp3); + me->CastCustomSpell(e.action.castCustom.spell, values, target->ToUnit(), (e.action.castCustom.flags & SMARTCAST_TRIGGERED) ? TRIGGERED_FULL_MASK : TRIGGERED_NONE); } + } + } + break; + } + case SMART_ACTION_VORTEX_SUMMON: + { + if (!me) + break; + + if (targets.empty()) + break; + + TempSummonType summon_type = (e.action.summonVortex.summonDuration > 0) ? TEMPSUMMON_TIMED_DESPAWN : TEMPSUMMON_CORPSE_DESPAWN; + + float a = static_cast(e.action.summonVortex.a); + float k = static_cast(e.action.summonVortex.k) / 1000.0f; + float r_max = static_cast(e.action.summonVortex.r_max); + float delta_phi = M_PI * static_cast(e.action.summonVortex.phi_delta) / 180.0f; + + // r(phi) = a * e ^ (k * phi) + // r(phi + delta_phi) = a * e ^ (k * (phi + delta_phi)) + // r(phi + delta_phi) = a * e ^ (k * phi) * e ^ (k * delta_phi) + // r(phi + delta_phi) = r(phi) * e ^ (k * delta_phi) + float factor = std::exp(k * delta_phi); + + // r(0) = a * e ^ (k * 0) = a * e ^ 0 = a * 1 = a + float summonRadius = a; + + for (WorldObject* target : targets) + { + // Offset by orientation, should not count into radius calculation, + // but is needed for vortex direction (polar coordinates) + float phi = target->GetOrientation(); + + do + { + Position summonPosition(*target); + summonPosition.RelocatePolarOffset(phi, summonRadius); + + me->SummonCreature(e.action.summonVortex.summonEntry, summonPosition, summon_type, e.action.summonVortex.summonDuration); + + phi += delta_phi; + summonRadius *= factor; + } while (summonRadius <= r_max); + } + + break; + } + case SMART_ACTION_CONE_SUMMON: + { + if (!me) + break; + + TempSummonType spawnType = (e.action.coneSummon.summonDuration > 0) ? TEMPSUMMON_TIMED_DESPAWN : TEMPSUMMON_CORPSE_DESPAWN; + + float distInARow = static_cast(e.action.coneSummon.distanceBetweenSummons); + float coneAngle = static_cast(e.action.coneSummon.coneAngle) * M_PI / 180.0f; + + for (uint32 radius = 0; radius <= e.action.coneSummon.coneLength; radius += e.action.coneSummon.distanceBetweenRings) + { + float deltaAngle = 0.0f; + if (radius > 0) + deltaAngle = distInARow / radius; + + uint32 count = 1; + if (deltaAngle > 0) + count += coneAngle / deltaAngle; + + float currentAngle = -static_cast(count) * deltaAngle / 2.0f; + + if (e.GetTargetType() == SMART_TARGET_SELF || e.GetTargetType() == SMART_TARGET_NONE) + currentAngle += G3D::fuzzyGt(e.target.o, 0.0f) ? (e.target.o - me->GetOrientation()) : 0.0f; + else if (!targets.empty()) + { + currentAngle += (me->GetAngle(targets.front()) - me->GetOrientation()); + } + + for (uint32 index = 0; index < count; ++index) + { + Position spawnPosition(*me); + spawnPosition.RelocatePolarOffset(currentAngle, radius); + currentAngle += deltaAngle; + + me->SummonCreature(e.action.coneSummon.summonEntry, spawnPosition, spawnType, e.action.coneSummon.summonDuration); + } + } + + break; + } + case SMART_ACTION_CU_ENCOUNTER_START: + { + for (WorldObject* target : targets) + { + if (Player* playerTarget = target->ToPlayer()) + { + playerTarget->RemoveArenaSpellCooldowns(); + playerTarget->RemoveAurasDueToSpell(57724); // Spell Shaman Debuff - Sated (Heroism) + playerTarget->RemoveAurasDueToSpell(57723); // Spell Shaman Debuff - Exhaustion (Bloodlust) + playerTarget->RemoveAurasDueToSpell(2825); // Bloodlust + playerTarget->RemoveAurasDueToSpell(32182); // Heroism + } + } + + break; + } + case SMART_ACTION_DO_ACTION: + { + int32 const actionId = e.action.doAction.isNegative ? -e.action.doAction.actionId : e.action.doAction.actionId; + if (!e.action.doAction.instanceTarget) + { + if (targets.empty()) + break; + + for (WorldObject* objTarget : targets) + { + if (Creature const* unitTarget = objTarget->ToCreature()) + { + if (unitTarget->IsAIEnabled) + { + unitTarget->AI()->DoAction(actionId); + } + } + else if (GameObject const* gobjTarget = objTarget->ToGameObject()) + { + gobjTarget->AI()->DoAction(actionId); + } + } + + } + else + { + InstanceScript* instanceScript = nullptr; + if (WorldObject* baseObj = GetBaseObject()) + { + instanceScript = baseObj->GetInstanceScript(); + } // Action is triggered by AreaTrigger - else if (trigger && IsPlayer(unit)) - { - instanceScript = unit->GetInstanceScript(); - } - - if (instanceScript) - { - instanceScript->DoAction(actionId); - } + else if (trigger && IsPlayer(unit)) + { + instanceScript = unit->GetInstanceScript(); + } + + if (instanceScript) + { + instanceScript->DoAction(actionId); } - break; } + break; + } case SMART_ACTION_DISABLE_EVADE: - { - if (!IsSmart()) - break; - - CAST_AI(SmartAI, me->AI())->SetEvadeDisabled(e.action.disableEvade.disable != 0); + { + if (!IsSmart()) break; - } + + CAST_AI(SmartAI, me->AI())->SetEvadeDisabled(e.action.disableEvade.disable != 0); + break; + } case SMART_ACTION_SET_CORPSE_DELAY: + { + for (WorldObject* const target : targets) { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - { - break; - } - - for (auto const& target : *targets) - { - if (IsCreature(target)) - { - target->ToCreature()->SetCorpseDelay(e.action.corpseDelay.timer); - } - } - - delete targets; - break; + if (IsCreature(target)) + target->ToCreature()->SetCorpseDelay(e.action.corpseDelay.timer); } + break; + } case SMART_ACTION_SET_HEALTH_PCT: - { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - { - break; - } - - for (auto const& target : *targets) - { - if (Unit* targetUnit = target->ToUnit()) - { - targetUnit->SetHealth(targetUnit->CountPctFromMaxHealth(e.action.setHealthPct.percent)); - } - } - - delete targets; - break; - } + { + for (WorldObject* target : targets) + if (Unit* targetUnit = target->ToUnit()) + targetUnit->SetHealth(targetUnit->CountPctFromMaxHealth(e.action.setHealthPct.percent)); + break; + } case SMART_ACTION_SET_MOVEMENT_SPEED: - { - uint32 speedInteger = e.action.movementSpeed.speedInteger; - uint32 speedFraction = e.action.movementSpeed.speedFraction; - float speed = float(speedInteger) + float(speedFraction) / std::pow(10, std::floor(std::log10(float(speedFraction ? speedFraction : 1)) + 1)); + { + uint32 speedInteger = e.action.movementSpeed.speedInteger; + uint32 speedFraction = e.action.movementSpeed.speedFraction; + float speed = float(speedInteger) + float(speedFraction) / std::pow(10, std::floor(std::log10(float(speedFraction ? speedFraction : 1)) + 1)); - ObjectList* targets = GetTargets(e, unit); - if (!targets) - { - break; - } + for (WorldObject* target : targets) + if (IsCreature(target)) + target->ToCreature()->SetSpeed(UnitMoveType(e.action.movementSpeed.movementType), speed); - for (auto const& target : *targets) - { - if (IsCreature(target)) - { - me->SetSpeed(UnitMoveType(e.action.movementSpeed.movementType), speed); - } - } - - delete targets; - break; - } + break; + } case SMART_ACTION_PLAY_CINEMATIC: + { + for (WorldObject* target : targets) { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - { - break; - } + if (!IsPlayer(target)) + continue; - for (auto const& target : *targets) - { - if (!IsPlayer(target)) - continue; - - target->ToPlayer()->SendCinematicStart(e.action.cinematic.entry); - } - break; + target->ToPlayer()->SendCinematicStart(e.action.cinematic.entry); } + break; + } default: LOG_ERROR("sql.sql", "SmartScript::ProcessAction: Entry {} SourceType {}, Event {}, Unhandled Action type {}", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType()); break; @@ -3432,7 +2706,7 @@ void SmartScript::InstallTemplate(SmartScriptHolder const& e) { if (!GetBaseObject()) return; - if (mTemplate) + if (mTemplate != SMARTAI_TEMPLATE_BASIC) { LOG_ERROR("sql.sql", "SmartScript::InstallTemplate: Entry {} SourceType {} AI Template can not be set more then once, skipped.", e.entryOrGuid, e.GetScriptType()); return; @@ -3539,7 +2813,7 @@ SmartScriptHolder SmartScript::CreateSmartEvent(SMART_EVENT e, uint32 event_flag return script; } -ObjectList* SmartScript::GetTargets(SmartScriptHolder const& e, Unit* invoker /*= nullptr*/) +void SmartScript::GetTargets(ObjectVector& targets, SmartScriptHolder const& e, Unit* invoker /*= nullptr*/) const { Unit* scriptTrigger = nullptr; if (invoker) @@ -3549,16 +2823,16 @@ ObjectList* SmartScript::GetTargets(SmartScriptHolder const& e, Unit* invoker /* WorldObject* baseObject = GetBaseObject(); - ObjectList* l = new ObjectList(); switch (e.GetTargetType()) { case SMART_TARGET_SELF: if (baseObject) - l->push_back(baseObject); + targets.push_back(baseObject); break; case SMART_TARGET_VICTIM: - if (me && me->GetVictim()) - l->push_back(me->GetVictim()); + if (me) + if (Unit* victim = me->GetVictim()) + targets.push_back(victim); break; case SMART_TARGET_HOSTILE_SECOND_AGGRO: if (me) @@ -3566,10 +2840,10 @@ ObjectList* SmartScript::GetTargets(SmartScriptHolder const& e, Unit* invoker /* if (e.target.hostileRandom.powerType) { if (Unit* u = me->AI()->SelectTarget(SelectTargetMethod::MaxThreat, 1, PowerUsersSelector(me, Powers(e.target.hostileRandom.powerType - 1), (float)e.target.hostileRandom.maxDist, e.target.hostileRandom.playerOnly))) - l->push_back(u); + targets.push_back(u); } else if (Unit* u = me->AI()->SelectTarget(SelectTargetMethod::MaxThreat, 1, (float)e.target.hostileRandom.maxDist, e.target.hostileRandom.playerOnly)) - l->push_back(u); + targets.push_back(u); } break; case SMART_TARGET_HOSTILE_LAST_AGGRO: @@ -3578,10 +2852,10 @@ ObjectList* SmartScript::GetTargets(SmartScriptHolder const& e, Unit* invoker /* if (e.target.hostileRandom.powerType) { if (Unit* u = me->AI()->SelectTarget(SelectTargetMethod::MinThreat, 0, PowerUsersSelector(me, Powers(e.target.hostileRandom.powerType - 1), (float)e.target.hostileRandom.maxDist, e.target.hostileRandom.playerOnly))) - l->push_back(u); + targets.push_back(u); } else if (Unit* u = me->AI()->SelectTarget(SelectTargetMethod::MinThreat, 0, (float)e.target.hostileRandom.maxDist, e.target.hostileRandom.playerOnly)) - l->push_back(u); + targets.push_back(u); } break; case SMART_TARGET_HOSTILE_RANDOM: @@ -3590,10 +2864,10 @@ ObjectList* SmartScript::GetTargets(SmartScriptHolder const& e, Unit* invoker /* if (e.target.hostileRandom.powerType) { if (Unit* u = me->AI()->SelectTarget(SelectTargetMethod::Random, 0, PowerUsersSelector(me, Powers(e.target.hostileRandom.powerType - 1), (float)e.target.hostileRandom.maxDist, e.target.hostileRandom.playerOnly))) - l->push_back(u); + targets.push_back(u); } else if (Unit* u = me->AI()->SelectTarget(SelectTargetMethod::Random, 0, (float)e.target.hostileRandom.maxDist, e.target.hostileRandom.playerOnly)) - l->push_back(u); + targets.push_back(u); } break; case SMART_TARGET_HOSTILE_RANDOM_NOT_TOP: @@ -3602,26 +2876,26 @@ ObjectList* SmartScript::GetTargets(SmartScriptHolder const& e, Unit* invoker /* if (e.target.hostileRandom.powerType) { if (Unit* u = me->AI()->SelectTarget(SelectTargetMethod::Random, 1, PowerUsersSelector(me, Powers(e.target.hostileRandom.powerType - 1), (float)e.target.hostileRandom.maxDist, e.target.hostileRandom.playerOnly))) - l->push_back(u); + targets.push_back(u); } else if (Unit* u = me->AI()->SelectTarget(SelectTargetMethod::Random, 1, (float)e.target.hostileRandom.maxDist, e.target.hostileRandom.playerOnly)) - l->push_back(u); + targets.push_back(u); } break; case SMART_TARGET_FARTHEST: if (me) { if (Unit* u = me->AI()->SelectTarget(SelectTargetMethod::MinDistance, 0, FarthestTargetSelector(me, e.target.farthest.maxDist, e.target.farthest.playerOnly, e.target.farthest.isInLos))) - l->push_back(u); + targets.push_back(u); } break; case SMART_TARGET_ACTION_INVOKER: if (scriptTrigger) - l->push_back(scriptTrigger); + targets.push_back(scriptTrigger); break; case SMART_TARGET_ACTION_INVOKER_VEHICLE: if (scriptTrigger && scriptTrigger->GetVehicle() && scriptTrigger->GetVehicle()->GetBase()) - l->push_back(scriptTrigger->GetVehicle()->GetBase()); + targets.push_back(scriptTrigger->GetVehicle()->GetBase()); break; case SMART_TARGET_INVOKER_PARTY: if (scriptTrigger) @@ -3633,394 +2907,360 @@ ObjectList* SmartScript::GetTargets(SmartScriptHolder const& e, Unit* invoker /* for (GroupReference* groupRef = group->GetFirstMember(); groupRef != nullptr; groupRef = groupRef->next()) if (Player* member = groupRef->GetSource()) if (member->IsInMap(player)) - l->push_back(member); + targets.push_back(member); } // We still add the player to the list if there is no group. If we do // this even if there is a group (thus the else-check), it will add the // same player to the list twice. We don't want that to happen. else - l->push_back(scriptTrigger); + targets.push_back(scriptTrigger); } } break; case SMART_TARGET_CREATURE_RANGE: + { + ObjectVector units; + GetWorldObjectsInDist(units, static_cast(e.target.unitRange.maxDist)); + + for (WorldObject* unit : units) { - // will always return a valid pointer, even if empty list - ObjectList* units = GetWorldObjectsInDist((float)e.target.unitRange.maxDist); - for (ObjectList::const_iterator itr = units->begin(); itr != units->end(); ++itr) + if (!IsCreature(unit)) + continue; + + if (me && me->GetGUID() == unit->GetGUID()) + continue; + + // check alive state - 1 alive, 2 dead, 0 both + if (uint32 state = e.target.unitRange.livingState) { - if (!IsCreature(*itr)) + if (unit->ToCreature()->IsAlive() && state == 2) continue; - - if (me && me->GetGUID() == (*itr)->GetGUID()) + if (!unit->ToCreature()->IsAlive() && state == 1) continue; - - // check alive state - 1 alive, 2 dead, 0 both - if (uint32 state = e.target.unitRange.livingState) - { - if ((*itr)->ToCreature()->IsAlive() && state == 2) - continue; - if (!(*itr)->ToCreature()->IsAlive() && state == 1) - continue; - } - - if (((e.target.unitRange.creature && (*itr)->ToCreature()->GetEntry() == e.target.unitRange.creature) || !e.target.unitRange.creature) && baseObject->IsInRange(*itr, (float)e.target.unitRange.minDist, (float)e.target.unitRange.maxDist)) - l->push_back(*itr); } - delete units; - break; + if (((e.target.unitRange.creature && unit->ToCreature()->GetEntry() == e.target.unitRange.creature) || !e.target.unitRange.creature) && baseObject->IsInRange(unit, (float)e.target.unitRange.minDist, (float)e.target.unitRange.maxDist)) + targets.push_back(unit); } + + break; + } case SMART_TARGET_CREATURE_DISTANCE: + { + ObjectVector units; + GetWorldObjectsInDist(units, static_cast(e.target.unitDistance.dist)); + + for (WorldObject* unit : units) { - // will always return a valid pointer, even if empty list - ObjectList* units = GetWorldObjectsInDist((float)e.target.unitDistance.dist); - for (ObjectList::const_iterator itr = units->begin(); itr != units->end(); ++itr) + if (!IsCreature(unit)) + continue; + + if (me && me->GetGUID() == unit->GetGUID()) + continue; + + // check alive state - 1 alive, 2 dead, 0 both + if (uint32 state = e.target.unitDistance.livingState) { - if (!IsCreature(*itr)) + if (unit->ToCreature()->IsAlive() && state == 2) continue; - - if (me && me->GetGUID() == (*itr)->GetGUID()) + if (!unit->ToCreature()->IsAlive() && state == 1) continue; - - // check alive state - 1 alive, 2 dead, 0 both - if (uint32 state = e.target.unitDistance.livingState) - { - if ((*itr)->ToCreature()->IsAlive() && state == 2) - continue; - if (!(*itr)->ToCreature()->IsAlive() && state == 1) - continue; - } - - if ((e.target.unitDistance.creature && (*itr)->ToCreature()->GetEntry() == e.target.unitDistance.creature) || !e.target.unitDistance.creature) - l->push_back(*itr); } - delete units; - break; + if ((e.target.unitDistance.creature && unit->ToCreature()->GetEntry() == e.target.unitDistance.creature) || !e.target.unitDistance.creature) + targets.push_back(unit); } + + break; + } case SMART_TARGET_GAMEOBJECT_DISTANCE: + { + ObjectVector units; + GetWorldObjectsInDist(units, static_cast(e.target.goDistance.dist)); + + for (WorldObject* unit : units) { - // will always return a valid pointer, even if empty list - ObjectList* units = GetWorldObjectsInDist((float)e.target.goDistance.dist); - for (ObjectList::const_iterator itr = units->begin(); itr != units->end(); ++itr) - { - if (!IsGameObject(*itr)) - continue; + if (!IsGameObject(unit)) + continue; - if (go && go->GetGUID() == (*itr)->GetGUID()) - continue; + if (go && go->GetGUID() == unit->GetGUID()) + continue; - if ((e.target.goDistance.entry && (*itr)->ToGameObject()->GetEntry() == e.target.goDistance.entry) || !e.target.goDistance.entry) - l->push_back(*itr); - } - - delete units; - break; + if ((e.target.goDistance.entry && unit->ToGameObject()->GetEntry() == e.target.goDistance.entry) || !e.target.goDistance.entry) + targets.push_back(unit); } + + break; + } case SMART_TARGET_GAMEOBJECT_RANGE: + { + ObjectVector units; + GetWorldObjectsInDist(units, static_cast(e.target.goRange.maxDist)); + + for (WorldObject* unit : units) { - // will always return a valid pointer, even if empty list - ObjectList* units = GetWorldObjectsInDist((float)e.target.goRange.maxDist); - for (ObjectList::const_iterator itr = units->begin(); itr != units->end(); ++itr) - { - if (!IsGameObject(*itr)) - continue; + if (!IsGameObject(unit)) + continue; - if (go && go->GetGUID() == (*itr)->GetGUID()) - continue; + if (go && go->GetGUID() == unit->GetGUID()) + continue; - if (((e.target.goRange.entry && IsGameObject(*itr) && (*itr)->ToGameObject()->GetEntry() == e.target.goRange.entry) || !e.target.goRange.entry) && baseObject->IsInRange((*itr), (float)e.target.goRange.minDist, (float)e.target.goRange.maxDist)) - l->push_back(*itr); - } - - delete units; - break; + if (((e.target.goRange.entry && IsGameObject(unit) && unit->ToGameObject()->GetEntry() == e.target.goRange.entry) || !e.target.goRange.entry) && baseObject->IsInRange((unit), (float)e.target.goRange.minDist, (float)e.target.goRange.maxDist)) + targets.push_back(unit); } + + break; + } case SMART_TARGET_CREATURE_GUID: + { + if (!scriptTrigger && !baseObject) { - if (!scriptTrigger && !baseObject) - { - LOG_ERROR("scripts.ai.sai", "SMART_TARGET_CREATURE_GUID can not be used without invoker"); - break; - } - - Creature* target = FindCreatureNear(scriptTrigger ? scriptTrigger : GetBaseObject(), e.target.unitGUID.dbGuid); - if (target && (!e.target.unitGUID.entry || target->GetEntry() == e.target.unitGUID.entry)) - l->push_back(target); + LOG_ERROR("scripts.ai.sai", "SMART_TARGET_CREATURE_GUID can not be used without invoker"); break; } + + Creature* target = FindCreatureNear(scriptTrigger ? scriptTrigger : GetBaseObject(), e.target.unitGUID.dbGuid); + if (target && (!e.target.unitGUID.entry || target->GetEntry() == e.target.unitGUID.entry)) + targets.push_back(target); + break; + } case SMART_TARGET_GAMEOBJECT_GUID: + { + if (!scriptTrigger && !GetBaseObject()) { - if (!scriptTrigger && !GetBaseObject()) - { - LOG_ERROR("scripts.ai.sai", "SMART_TARGET_GAMEOBJECT_GUID can not be used without invoker"); - break; - } - - GameObject* target = FindGameObjectNear(scriptTrigger ? scriptTrigger : GetBaseObject(), e.target.goGUID.dbGuid); - if (target && (!e.target.goGUID.entry || target->GetEntry() == e.target.goGUID.entry)) - l->push_back(target); + LOG_ERROR("scripts.ai.sai", "SMART_TARGET_GAMEOBJECT_GUID can not be used without invoker"); break; } + + GameObject* target = FindGameObjectNear(scriptTrigger ? scriptTrigger : GetBaseObject(), e.target.goGUID.dbGuid); + if (target && (!e.target.goGUID.entry || target->GetEntry() == e.target.goGUID.entry)) + targets.push_back(target); + break; + } case SMART_TARGET_PLAYER_RANGE: - { - // will always return a valid pointer, even if empty list - ObjectList* units = GetWorldObjectsInDist((float)e.target.playerRange.maxDist); - if (!units->empty() && GetBaseObject()) - { - for (ObjectList::const_iterator itr = units->begin(); itr != units->end(); ++itr) - if (IsPlayer(*itr) && GetBaseObject()->IsInRange(*itr, (float)e.target.playerRange.minDist, (float)e.target.playerRange.maxDist) && (*itr)->ToPlayer()->IsAlive() && !(*itr)->ToPlayer()->IsGameMaster()) - l->push_back(*itr); + { + ObjectVector units; + GetWorldObjectsInDist(units, static_cast(e.target.playerRange.maxDist)); - // If Orientation is also set and we didnt find targets, try it with all the range - if (l->empty() && e.target.o > 0) - for (ObjectList::const_iterator itr = units->begin(); itr != units->end(); ++itr) - if (IsPlayer(*itr) && baseObject->IsInRange(*itr, 0.0f, float(e.target.playerRange.maxDist)) && (*itr)->ToPlayer()->IsAlive() && !(*itr)->ToPlayer()->IsGameMaster()) - l->push_back(*itr); - - if (e.target.playerRange.maxCount > 0) - Acore::Containers::RandomResize(*l, e.target.playerRange.maxCount); - } - - delete units; - break; - } + if (!units.empty() && baseObject) + for (WorldObject* unit : units) + if (IsPlayer(unit) && baseObject->IsInRange(unit, float(e.target.playerRange.minDist), float(e.target.playerRange.maxDist))) + targets.push_back(unit); + break; + } case SMART_TARGET_PLAYER_DISTANCE: - { - // will always return a valid pointer, even if empty list - ObjectList* units = GetWorldObjectsInDist((float)e.target.playerDistance.dist); - for (ObjectList::const_iterator itr = units->begin(); itr != units->end(); ++itr) - if (IsPlayer(*itr)) - l->push_back(*itr); + { + ObjectVector units; + GetWorldObjectsInDist(units, static_cast(e.target.playerDistance.dist)); - delete units; - break; - } + for (WorldObject* unit : units) + if (IsPlayer(unit)) + targets.push_back(unit); + break; + } case SMART_TARGET_STORED: - { - ObjectListMap::iterator itr = mTargetStorage->find(e.target.stored.id); - if (itr != mTargetStorage->end()) - { - ObjectList* objectList = itr->second->GetObjectList(); - l->assign(objectList->begin(), objectList->end()); - } - - // xinef: return l, what if list is empty? will return empty list instead of null pointer - break; - } + { + if (ObjectVector const* stored = GetStoredTargetVector(e.target.stored.id)) + targets.assign(stored->begin(), stored->end()); + break; + } case SMART_TARGET_CLOSEST_CREATURE: - { - Creature* target = GetClosestCreatureWithEntry(GetBaseObject(), e.target.unitClosest.entry, (float)(e.target.unitClosest.dist ? e.target.unitClosest.dist : 100), !e.target.unitClosest.dead); - if (target) - l->push_back(target); - break; - } + { + Creature* target = GetClosestCreatureWithEntry(GetBaseObject(), e.target.unitClosest.entry, (float)(e.target.unitClosest.dist ? e.target.unitClosest.dist : 100), !e.target.unitClosest.dead); + if (target) + targets.push_back(target); + break; + } case SMART_TARGET_CLOSEST_GAMEOBJECT: - { - GameObject* target = GetClosestGameObjectWithEntry(GetBaseObject(), e.target.goClosest.entry, (float)(e.target.goClosest.dist ? e.target.goClosest.dist : 100), e.target.goClosest.onlySpawned); - if (target) - l->push_back(target); - break; - } + { + GameObject* target = GetClosestGameObjectWithEntry(GetBaseObject(), e.target.goClosest.entry, (float)(e.target.goClosest.dist ? e.target.goClosest.dist : 100), e.target.goClosest.onlySpawned); + if (target) + targets.push_back(target); + break; + } case SMART_TARGET_CLOSEST_PLAYER: + { + if (WorldObject* obj = GetBaseObject()) { - if (WorldObject* obj = GetBaseObject()) - { - Player* target = obj->SelectNearestPlayer((float)e.target.playerDistance.dist); - if (target) - l->push_back(target); - } - break; + Player* target = obj->SelectNearestPlayer((float)e.target.playerDistance.dist); + if (target) + targets.push_back(target); } + break; + } case SMART_TARGET_OWNER_OR_SUMMONER: - /* - * Owners/Summoners should be WorldObjects. This allows to have other objects - * such as gameobjects to execute SmartScripts using this type of target. - * Otherwise, only Units like creatures can summon other creatures. - */ + /* + * Owners/Summoners should be WorldObjects. This allows to have other objects + * such as gameobjects to execute SmartScripts using this type of target. + * Otherwise, only Units like creatures can summon other creatures. + */ + { + if (me) { - if (me) + if (WorldObject* owner = ObjectAccessor::GetWorldObject(*me, me->GetCharmerOrOwnerGUID())) { - if (WorldObject* owner = ObjectAccessor::GetWorldObject(*me, me->GetCharmerOrOwnerGUID())) - { - l->push_back(owner); - } - else if (me->IsSummon() && me->ToTempSummon()->GetSummonerUnit()) - { - l->push_back(me->ToTempSummon()->GetSummonerUnit()); - } + targets.push_back(owner); } - else if (go) - { - if (WorldObject* owner = ObjectAccessor::GetWorldObject(*go, go->GetOwnerGUID())) - { - l->push_back(owner); - } - } - - // xinef: Get owner of owner - if (e.target.owner.useCharmerOrOwner && !l->empty()) - { - if (Unit* owner = l->front()->ToUnit()) - { - l->clear(); - - if (Unit* base = ObjectAccessor::GetUnit(*owner, owner->GetCharmerOrOwnerGUID())) - { - l->push_back(base); - } - } - } - break; } + else if (go) + { + if (WorldObject* owner = ObjectAccessor::GetWorldObject(*go, go->GetOwnerGUID())) + { + targets.push_back(owner); + } + } + + // xinef: Get owner of owner + if (e.target.owner.useCharmerOrOwner && !targets.empty()) + { + if (Unit* owner = targets.front()->ToUnit()) + { + targets.clear(); + + if (Unit* base = ObjectAccessor::GetUnit(*owner, owner->GetCharmerOrOwnerGUID())) + { + targets.push_back(base); + } + } + } + break; + } case SMART_TARGET_THREAT_LIST: + { + if (me) { - if (me) - { - ThreatContainer::StorageType threatList = me->GetThreatMgr().getThreatList(); - for (ThreatContainer::StorageType::const_iterator i = threatList.begin(); i != threatList.end(); ++i) - if (Unit* temp = ObjectAccessor::GetUnit(*me, (*i)->getUnitGuid())) - // Xinef: added distance check - if (e.target.threatList.maxDist == 0 || me->IsWithinCombatRange(temp, (float)e.target.threatList.maxDist)) - l->push_back(temp); - } - break; + ThreatContainer::StorageType threatList = me->GetThreatMgr().getThreatList(); + for (ThreatContainer::StorageType::const_iterator i = threatList.begin(); i != threatList.end(); ++i) + if (Unit* temp = ObjectAccessor::GetUnit(*me, (*i)->getUnitGuid())) + // Xinef: added distance check + if (e.target.threatList.maxDist == 0 || me->IsWithinCombatRange(temp, (float)e.target.threatList.maxDist)) + targets.push_back(temp); } + break; + } case SMART_TARGET_CLOSEST_ENEMY: - { - if (me) - if (Unit* target = me->SelectNearestTarget(e.target.closestAttackable.maxDist, e.target.closestAttackable.playerOnly)) - l->push_back(target); + { + if (me) + if (Unit* target = me->SelectNearestTarget(e.target.closestAttackable.maxDist, e.target.closestAttackable.playerOnly)) + targets.push_back(target); - break; - } + break; + } case SMART_TARGET_CLOSEST_FRIENDLY: - { - if (me) - if (Unit* target = DoFindClosestFriendlyInRange(e.target.closestFriendly.maxDist, e.target.closestFriendly.playerOnly)) - l->push_back(target); + { + if (me) + if (Unit* target = DoFindClosestFriendlyInRange(e.target.closestFriendly.maxDist, e.target.closestFriendly.playerOnly)) + targets.push_back(target); - break; - } + break; + } case SMART_TARGET_PLAYER_WITH_AURA: - { - // will always return a valid pointer, even if empty list - ObjectList* units = GetWorldObjectsInDist(e.target.z ? e.target.z : float(e.target.playerWithAura.distMax)); - for (ObjectList::const_iterator itr = units->begin(); itr != units->end(); ++itr) - if (IsPlayer(*itr) && (*itr)->ToPlayer()->IsAlive() && !(*itr)->ToPlayer()->IsGameMaster()) - if (GetBaseObject()->IsInRange(*itr, (float)e.target.playerWithAura.distMin, (float)e.target.playerWithAura.distMax)) - if (bool(e.target.playerWithAura.negation) != (*itr)->ToPlayer()->HasAura(e.target.playerWithAura.spellId)) - l->push_back(*itr); + { + ObjectVector units; + GetWorldObjectsInDist(units, static_cast(e.target.playerDistance.dist)); - if (e.target.o > 0) - Acore::Containers::RandomResize(*l, e.target.o); + for (WorldObject* unit : units) + if (IsPlayer(unit) && unit->ToPlayer()->IsAlive() && !unit->ToPlayer()->IsGameMaster()) + if (GetBaseObject()->IsInRange(unit, (float)e.target.playerWithAura.distMin, (float)e.target.playerWithAura.distMax)) + if (bool(e.target.playerWithAura.negation) != unit->ToPlayer()->HasAura(e.target.playerWithAura.spellId)) + targets.push_back(unit); - delete units; - break; - } + if (e.target.o > 0) + Acore::Containers::RandomResize(targets, e.target.o); + + break; + } case SMART_TARGET_ROLE_SELECTION: - { - // will always return a valid pointer, even if empty list - ObjectList* units = GetWorldObjectsInDist(float(e.target.roleSelection.maxDist)); - // 1 = Tanks, 2 = Healer, 4 = Damage - uint32 roleMask = e.target.roleSelection.roleMask; - for (ObjectList::const_iterator itr = units->begin(); itr != units->end(); ++itr) - if (Player* targetPlayer = (*itr)->ToPlayer()) - if (targetPlayer->IsAlive() && !targetPlayer->IsGameMaster()) + { + ObjectVector units; + GetWorldObjectsInDist(units, static_cast(e.target.playerDistance.dist)); + // 1 = Tanks, 2 = Healer, 4 = Damage + uint32 roleMask = e.target.roleSelection.roleMask; + for (WorldObject* unit : units) + if (Player* targetPlayer = unit->ToPlayer()) + if (targetPlayer->IsAlive() && !targetPlayer->IsGameMaster()) + { + if (roleMask & SMART_TARGET_ROLE_FLAG_TANKS) { - if (roleMask & SMART_TARGET_ROLE_FLAG_TANKS) + if (targetPlayer->HasTankSpec()) { - if (targetPlayer->HasTankSpec()) - { - l->push_back(*itr); - continue; - } - } - if (roleMask & SMART_TARGET_ROLE_FLAG_HEALERS) - { - if (targetPlayer->HasHealSpec()) - { - l->push_back(*itr); - continue; - } - } - if (roleMask & SMART_TARGET_ROLE_FLAG_DAMAGERS) - { - if (targetPlayer->HasCasterSpec() || targetPlayer->HasMeleeSpec()) - { - l->push_back(*itr); - continue; - } + targets.push_back(unit); + continue; } } + if (roleMask & SMART_TARGET_ROLE_FLAG_HEALERS) + { + if (targetPlayer->HasHealSpec()) + { + targets.push_back(unit); + continue; + } + } + if (roleMask & SMART_TARGET_ROLE_FLAG_DAMAGERS) + { + if (targetPlayer->HasCasterSpec() || targetPlayer->HasMeleeSpec()) + { + targets.push_back(unit); + continue; + } + } + } - if (e.target.roleSelection.resize > 0) - Acore::Containers::RandomResize(*l, e.target.roleSelection.resize); + if (e.target.roleSelection.resize > 0) + Acore::Containers::RandomResize(targets, e.target.roleSelection.resize); - delete units; - break; - } + break; + } case SMART_TARGET_VEHICLE_PASSENGER: + { + if (me && me->IsVehicle()) { - if (me && me->IsVehicle()) + if (Unit* target = me->GetVehicleKit()->GetPassenger(e.target.vehicle.seatMask)) { - if (Unit* target = me->GetVehicleKit()->GetPassenger(e.target.vehicle.seatMask)) - { - l->push_back(target); - } + targets.push_back(target); } - break; } + break; + } case SMART_TARGET_LOOT_RECIPIENTS: + { + if (me) { - if (me) + if (Group* lootGroup = me->GetLootRecipientGroup()) { - if (Group* lootGroup = me->GetLootRecipientGroup()) + for (GroupReference* it = lootGroup->GetFirstMember(); it != nullptr; it = it->next()) { - for (GroupReference* it = lootGroup->GetFirstMember(); it != nullptr; it = it->next()) + if (Player* recipient = it->GetSource()) { - if (Player* recipient = it->GetSource()) - { - l->push_back(recipient); - } - } - } - else - { - if (Player* recipient = me->GetLootRecipient()) - { - l->push_back(recipient); + targets.push_back(recipient); } } } + else + { + if (Player* recipient = me->GetLootRecipient()) + { + targets.push_back(recipient); + } + } } + } case SMART_TARGET_NONE: case SMART_TARGET_POSITION: default: break; } - - if (l->empty()) - { - delete l; - l = nullptr; - } - - return l; } -ObjectList* SmartScript::GetWorldObjectsInDist(float dist) +void SmartScript::GetWorldObjectsInDist(ObjectVector& targets, float dist) const { - ObjectList* targets = new ObjectList(); WorldObject* obj = GetBaseObject(); - if (obj) - { - Acore::AllWorldObjectsInRange u_check(obj, dist); - Acore::WorldObjectListSearcher searcher(obj, *targets, u_check); - Cell::VisitAllObjects(obj, searcher, dist); - } - return targets; + if (!obj) + return; + + Acore::AllWorldObjectsInRange u_check(obj, dist); + Acore::WorldObjectListSearcher searcher(obj, targets, u_check); + Cell::VisitAllObjects(obj, searcher, dist); } void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, uint32 var1, bool bvar, SpellInfo const* spell, GameObject* gob) @@ -4142,26 +3382,26 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui if (!me || !me->IsEngaged()) return; - std::list pList; - DoFindFriendlyCC(pList, (float)e.event.friendlyCC.radius); - if (pList.empty()) + std::vector creatures; + DoFindFriendlyCC(creatures, float(e.event.friendlyCC.radius)); + if (creatures.empty()) { // Xinef: if there are at least two same npcs, they will perform the same action immediately even if this is useless... RecalcTimer(e, 1000, 3000); return; } - ProcessTimedAction(e, e.event.friendlyCC.repeatMin, e.event.friendlyCC.repeatMax, Acore::Containers::SelectRandomContainerElement(pList)); + ProcessTimedAction(e, e.event.friendlyCC.repeatMin, e.event.friendlyCC.repeatMax, Acore::Containers::SelectRandomContainerElement(creatures)); break; } case SMART_EVENT_FRIENDLY_MISSING_BUFF: { - std::list pList; - DoFindFriendlyMissingBuff(pList, (float)e.event.missingBuff.radius, e.event.missingBuff.spell); + std::vector creatures; + DoFindFriendlyMissingBuff(creatures, float(e.event.missingBuff.radius), e.event.missingBuff.spell); - if (pList.empty()) + if (creatures.empty()) return; - ProcessTimedAction(e, e.event.missingBuff.repeatMin, e.event.missingBuff.repeatMax, Acore::Containers::SelectRandomContainerElement(pList)); + ProcessTimedAction(e, e.event.missingBuff.repeatMin, e.event.missingBuff.repeatMax, Acore::Containers::SelectRandomContainerElement(creatures)); break; } case SMART_EVENT_HAS_AURA: @@ -4510,7 +3750,7 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui if (!me || !me->IsEngaged()) return; - Unit* target = nullptr; + ObjectVector targets; switch (e.GetTargetType()) { case SMART_TARGET_CREATURE_RANGE: @@ -4521,10 +3761,9 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui case SMART_TARGET_PLAYER_RANGE: case SMART_TARGET_PLAYER_DISTANCE: { - ObjectList* targets = GetTargets(e); - if (!targets) + if (targets.empty()) return; - for (WorldObject* target : *targets) + for (WorldObject* target : targets) { if (IsUnit(target) && me->IsFriendlyTo(target->ToUnit()) && target->ToUnit()->IsAlive() && target->ToUnit()->IsInCombat()) { @@ -4539,21 +3778,20 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui } } - delete targets; break; } case SMART_TARGET_SELF: case SMART_TARGET_ACTION_INVOKER: - target = DoSelectLowestHpPercentFriendly((float)e.event.friendlyHealthPct.radius, e.event.friendlyHealthPct.minHpPct, e.event.friendlyHealthPct.maxHpPct); + DoSelectLowestHpPercentFriendly((float)e.event.friendlyHealthPct.radius, e.event.friendlyHealthPct.minHpPct, e.event.friendlyHealthPct.maxHpPct); break; default: return; } - if (!target) + if (targets.empty()) return; - ProcessTimedAction(e, e.event.friendlyHealthPct.repeatMin, e.event.friendlyHealthPct.repeatMax, target); + ProcessTimedAction(e, e.event.friendlyHealthPct.repeatMin, e.event.friendlyHealthPct.repeatMax); break; } case SMART_EVENT_DISTANCE_CREATURE: @@ -4625,33 +3863,37 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui ProcessTimedAction(e, e.event.counter.cooldownMin, e.event.counter.cooldownMax); break; case SMART_EVENT_NEAR_PLAYERS: - { - float range = (float)e.event.nearPlayer.radius; - ObjectList* units = GetWorldObjectsInDist(range); - if (!units->empty()) - { - units->remove_if([](WorldObject * unit) { return unit->GetTypeId() != TYPEID_PLAYER; }); + { + ObjectVector units; + GetWorldObjectsInDist(units, static_cast(e.event.nearPlayer.radius)); - if (units->size() >= e.event.nearPlayer.minCount) - ProcessAction(e, unit); - } - RecalcTimer(e, e.event.nearPlayer.checkTimer, e.event.nearPlayer.checkTimer); - break; + if (!units.empty()) + { + if (unit->GetTypeId() != TYPEID_PLAYER) + return; + + if (units.size() >= e.event.nearPlayer.minCount) + ProcessAction(e, unit); } + RecalcTimer(e, e.event.nearPlayer.checkTimer, e.event.nearPlayer.checkTimer); + break; + } case SMART_EVENT_NEAR_PLAYERS_NEGATION: - { - float range = (float)e.event.nearPlayerNegation.radius; - ObjectList* units = GetWorldObjectsInDist(range); - if (!units->empty()) - { - units->remove_if([](WorldObject * unit) { return unit->GetTypeId() != TYPEID_PLAYER; }); + { + ObjectVector units; + GetWorldObjectsInDist(units, static_cast(e.event.nearPlayerNegation.radius)); - if (units->size() < e.event.nearPlayerNegation.minCount) - ProcessAction(e, unit); - } - RecalcTimer(e, e.event.nearPlayerNegation.checkTimer, e.event.nearPlayerNegation.checkTimer); - break; + if (!units.empty()) + { + if (unit->GetTypeId() != TYPEID_PLAYER) + return; + + if (units.size() < e.event.nearPlayerNegation.minCount) + ProcessAction(e, unit); } + RecalcTimer(e, e.event.nearPlayerNegation.checkTimer, e.event.nearPlayerNegation.checkTimer); + break; + } default: LOG_ERROR("sql.sql", "SmartScript::ProcessEvent: Unhandled Event type {}", e.GetEventType()); break; @@ -5030,7 +4272,7 @@ uint32 SmartScript::DoChat(int8 id, ObjectGuid whisperGuid) }*/ // SmartScript end -Unit* SmartScript::DoSelectLowestHpFriendly(float range, uint32 MinHPDiff) +Unit* SmartScript::DoSelectLowestHpFriendly(float range, uint32 MinHPDiff) const { if (!me) return nullptr; @@ -5057,27 +4299,27 @@ Unit* SmartScript::DoSelectLowestHpPercentFriendly(float range, uint32 minHpPct, return unit; } -void SmartScript::DoFindFriendlyCC(std::list& _list, float range) +void SmartScript::DoFindFriendlyCC(std::vector& creatures, float range) const { if (!me) return; Acore::FriendlyCCedInRange u_check(me, range); - Acore::CreatureListSearcher searcher(me, _list, u_check); + Acore::CreatureListSearcher searcher(me, creatures, u_check); Cell::VisitGridObjects(me, searcher, range); } -void SmartScript::DoFindFriendlyMissingBuff(std::list& list, float range, uint32 spellid) +void SmartScript::DoFindFriendlyMissingBuff(std::vector& creatures, float range, uint32 spellid) const { if (!me) return; Acore::FriendlyMissingBuffInRange u_check(me, range, spellid); - Acore::CreatureListSearcher searcher(me, list, u_check); + Acore::CreatureListSearcher searcher(me, creatures, u_check); Cell::VisitGridObjects(me, searcher, range); } -Unit* SmartScript::DoFindClosestFriendlyInRange(float range, bool playerOnly) +Unit* SmartScript::DoFindClosestFriendlyInRange(float range, bool playerOnly) const { if (!me) return nullptr; @@ -5124,7 +4366,7 @@ void SmartScript::SetScript9(SmartScriptHolder& e, uint32 entry) } } -Unit* SmartScript::GetLastInvoker(Unit* invoker) +Unit* SmartScript::GetLastInvoker(Unit* invoker) const { // Xinef: Look for invoker only on map of base object... Prevents multithreaded crashes if (GetBaseObject()) diff --git a/src/server/game/AI/SmartScripts/SmartScript.h b/src/server/game/AI/SmartScripts/SmartScript.h index cd564b72b..4cf33a56e 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.h +++ b/src/server/game/AI/SmartScripts/SmartScript.h @@ -39,19 +39,19 @@ public: void ProcessEventsFor(SMART_EVENT e, Unit* unit = nullptr, uint32 var0 = 0, uint32 var1 = 0, bool bvar = false, SpellInfo const* spell = nullptr, GameObject* gob = nullptr); void ProcessEvent(SmartScriptHolder& e, Unit* unit = nullptr, uint32 var0 = 0, uint32 var1 = 0, bool bvar = false, SpellInfo const* spell = nullptr, GameObject* gob = nullptr); bool CheckTimer(SmartScriptHolder const& e) const; - void RecalcTimer(SmartScriptHolder& e, uint32 min, uint32 max); + static void RecalcTimer(SmartScriptHolder& e, uint32 min, uint32 max); void UpdateTimer(SmartScriptHolder& e, uint32 const diff); - void InitTimer(SmartScriptHolder& e); + static void InitTimer(SmartScriptHolder& e); void ProcessAction(SmartScriptHolder& e, Unit* unit = nullptr, uint32 var0 = 0, uint32 var1 = 0, bool bvar = false, SpellInfo const* spell = nullptr, GameObject* gob = nullptr); void ProcessTimedAction(SmartScriptHolder& e, uint32 const& min, uint32 const& max, Unit* unit = nullptr, uint32 var0 = 0, uint32 var1 = 0, bool bvar = false, SpellInfo const* spell = nullptr, GameObject* gob = nullptr); - ObjectList* GetTargets(SmartScriptHolder const& e, Unit* invoker = nullptr); - ObjectList* GetWorldObjectsInDist(float dist); + void GetTargets(ObjectVector& targets, SmartScriptHolder const& e, Unit* invoker = nullptr) const; + void GetWorldObjectsInDist(ObjectVector& objects, float dist) const; void InstallTemplate(SmartScriptHolder const& e); - SmartScriptHolder CreateSmartEvent(SMART_EVENT e, uint32 event_flags, uint32 event_param1, uint32 event_param2, uint32 event_param3, uint32 event_param4, uint32 event_param5, SMART_ACTION action, uint32 action_param1, uint32 action_param2, uint32 action_param3, uint32 action_param4, uint32 action_param5, uint32 action_param6, SMARTAI_TARGETS t, uint32 target_param1, uint32 target_param2, uint32 target_param3, uint32 target_param4, uint32 phaseMask); + static SmartScriptHolder CreateSmartEvent(SMART_EVENT e, uint32 event_flags, uint32 event_param1, uint32 event_param2, uint32 event_param3, uint32 event_param4, uint32 event_param5, SMART_ACTION action, uint32 action_param1, uint32 action_param2, uint32 action_param3, uint32 action_param4, uint32 action_param5, uint32 action_param6, SMARTAI_TARGETS t, uint32 target_param1, uint32 target_param2, uint32 target_param3, uint32 target_param4, uint32 phaseMask); void AddEvent(SMART_EVENT e, uint32 event_flags, uint32 event_param1, uint32 event_param2, uint32 event_param3, uint32 event_param4, uint32 event_param5, SMART_ACTION action, uint32 action_param1, uint32 action_param2, uint32 action_param3, uint32 action_param4, uint32 action_param5, uint32 action_param6, SMARTAI_TARGETS t, uint32 target_param1, uint32 target_param2, uint32 target_param3, uint32 target_param4, uint32 phaseMask); void SetPathId(uint32 id) { mPathId = id; } uint32 GetPathId() const { return mPathId; } - WorldObject* GetBaseObject() + WorldObject* GetBaseObject() const { WorldObject* obj = nullptr; if (me) @@ -70,27 +70,17 @@ public: void OnUpdate(const uint32 diff); void OnMoveInLineOfSight(Unit* who); - Unit* DoSelectLowestHpFriendly(float range, uint32 MinHPDiff); + Unit* DoSelectLowestHpFriendly(float range, uint32 MinHPDiff) const; Unit* DoSelectLowestHpPercentFriendly(float range, uint32 minHpPct, uint32 maxHpPct) const; - void DoFindFriendlyCC(std::list& _list, float range); - void DoFindFriendlyMissingBuff(std::list& list, float range, uint32 spellid); - Unit* DoFindClosestFriendlyInRange(float range, bool playerOnly); + void DoFindFriendlyCC(std::vector& creatures, float range) const; + void DoFindFriendlyMissingBuff(std::vector& creatures, float range, uint32 spellid) const; + Unit* DoFindClosestFriendlyInRange(float range, bool playerOnly) const; - void StoreTargetList(ObjectList* targets, uint32 id) + void StoreTargetList(ObjectVector const& targets, uint32 id) { - if (!targets) - return; - - if (mTargetStorage->find(id) != mTargetStorage->end()) - { - // check if already stored - if ((*mTargetStorage)[id]->Equals(targets)) - return; - - delete (*mTargetStorage)[id]; - } - - (*mTargetStorage)[id] = new ObjectGuidList(targets, GetBaseObject()); + // insert or replace + _storedTargets.erase(id); + _storedTargets.emplace(id, ObjectGuidVector(GetBaseObject(), targets)); } bool IsSmart(Creature* c = nullptr) @@ -122,11 +112,11 @@ public: return smart; } - ObjectList* GetTargetList(uint32 id) + ObjectVector const* GetStoredTargetVector(uint32 id) const { - ObjectListMap::iterator itr = mTargetStorage->find(id); - if (itr != mTargetStorage->end()) - return (*itr).second->GetObjectList(); + auto itr = _storedTargets.find(id); + if (itr != _storedTargets.end()) + return itr->second.GetObjectVector(); return nullptr; } @@ -187,8 +177,6 @@ public: return creatureItr != bounds.second ? creatureItr->second : bounds.first->second; } - ObjectListMap* mTargetStorage; - void OnReset(); void ResetBaseObject() { @@ -223,7 +211,7 @@ public: //TIMED_ACTIONLIST (script type 9 aka script9) void SetScript9(SmartScriptHolder& e, uint32 entry); - Unit* GetLastInvoker(Unit* invoker = nullptr); + Unit* GetLastInvoker(Unit* invoker = nullptr) const; ObjectGuid mLastInvoker; typedef std::unordered_map CounterMap; CounterMap mCounterList; @@ -284,6 +272,8 @@ private: // Xinef: misc bool _allowPhaseReset; + ObjectVectorMap _storedTargets; + SMARTAI_TEMPLATE mTemplate; void InstallEvents(); diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp index 82292262d..0f5d71a8b 100644 --- a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp +++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp @@ -1358,24 +1358,39 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e) break; } case SMART_ACTION_RANDOM_EMOTE: - if (e.action.randomEmote.emote1 && !IsEmoteValid(e, e.action.randomEmote.emote1)) - return false; + { + if (std::all_of(e.action.randomEmote.emotes.begin(), e.action.randomEmote.emotes.end(), [](uint32 emote) { return emote == 0; })) + { + LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} does not have any non-zero emote", + e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType()); + return false; + } - if (e.action.randomEmote.emote2 && !IsEmoteValid(e, e.action.randomEmote.emote2)) - return false; - - if (e.action.randomEmote.emote3 && !IsEmoteValid(e, e.action.randomEmote.emote3)) - return false; - - if (e.action.randomEmote.emote4 && !IsEmoteValid(e, e.action.randomEmote.emote4)) - return false; - - if (e.action.randomEmote.emote5 && !IsEmoteValid(e, e.action.randomEmote.emote5)) - return false; - - if (e.action.randomEmote.emote6 && !IsEmoteValid(e, e.action.randomEmote.emote6)) - return false; - break; + for (uint32 emote : e.action.randomEmote.emotes) + if (emote && !IsEmoteValid(e, emote)) + return false; + break; + } + case SMART_ACTION_CALL_RANDOM_TIMED_ACTIONLIST: + { + if (std::all_of(e.action.randTimedActionList.actionLists.begin(), e.action.randTimedActionList.actionLists.end(), [](uint32 actionList) { return actionList == 0; })) + { + LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} does not have any non-zero action list", + e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType()); + return false; + } + break; + } + case SMART_ACTION_START_CLOSEST_WAYPOINT: + { + if (std::all_of(e.action.closestWaypointFromList.wps.begin(), e.action.closestWaypointFromList.wps.end(), [](uint32 wp) { return wp == 0; })) + { + LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} does not have any non-zero waypoint id", + e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType()); + return false; + } + break; + } case SMART_ACTION_CAST: case SMART_ACTION_INVOKER_CAST: if (!IsSpellValid(e, e.action.cast.spell)) @@ -1434,36 +1449,29 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e) break; case SMART_ACTION_RANDOM_PHASE: { - if (e.action.randomPhase.phase1 >= SMART_EVENT_PHASE_MAX || - e.action.randomPhase.phase2 >= SMART_EVENT_PHASE_MAX || - e.action.randomPhase.phase3 >= SMART_EVENT_PHASE_MAX || - e.action.randomPhase.phase4 >= SMART_EVENT_PHASE_MAX || - e.action.randomPhase.phase5 >= SMART_EVENT_PHASE_MAX || - e.action.randomPhase.phase6 >= SMART_EVENT_PHASE_MAX) - { - LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} attempts to set invalid phase, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType()); - return false; - } - if (e.action.randomPhase.phase1 == 0 && - e.action.randomPhase.phase2 == 0 && - e.action.randomPhase.phase3 == 0 && - e.action.randomPhase.phase4 == 0 && - e.action.randomPhase.phase5 == 0 && - e.action.randomPhase.phase6 == 0) + if (std::all_of(e.action.randomPhase.phases.begin(), e.action.randomPhase.phases.end(), [](uint32 phase) { return phase == 0; })) + { + LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} does not have any non-zero phase", + e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType()); + return false; + } + + if (std::any_of(e.action.randomPhase.phases.begin(), e.action.randomPhase.phases.end(), [](uint32 phase) { return phase >= SMART_EVENT_PHASE_MAX; })) { LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} attempts to set invalid phase, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType()); return false; } + break; } - break; case SMART_ACTION_RANDOM_PHASE_RANGE: //PhaseMin, PhaseMax { if (e.action.randomPhaseRange.phaseMin >= SMART_EVENT_PHASE_MAX || - e.action.randomPhaseRange.phaseMax >= SMART_EVENT_PHASE_MAX) + e.action.randomPhaseRange.phaseMax >= SMART_EVENT_PHASE_MAX) { LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} attempts to set invalid phase, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType()); return false; } + if (!IsMinMaxValid(e, e.action.randomPhaseRange.phaseMin, e.action.randomPhaseRange.phaseMax)) return false; break; @@ -1570,7 +1578,7 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e) } case SMART_ACTION_CALL_RANDOM_RANGE_TIMED_ACTIONLIST: { - if (!IsMinMaxValid(e, e.action.randRangeTimedActionList.idMin, e.action.randRangeTimedActionList.idMax)) + if (!IsMinMaxValid(e, e.action.randTimedActionList.actionLists[0], e.action.randTimedActionList.actionLists[1])) return false; break; } @@ -1625,12 +1633,10 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e) { if (e.GetScriptType() == SMART_SCRIPT_TYPE_CREATURE) { - int8 equipId = (int8)e.action.equip.entry; - - if (equipId) + if (int8 equipId = static_cast(e.action.equip.entry)) { - EquipmentInfo const* einfo = sObjectMgr->GetEquipmentInfo(e.entryOrGuid, equipId); - if (!einfo) + EquipmentInfo const* eInfo = sObjectMgr->GetEquipmentInfo(e.entryOrGuid, equipId); + if (!eInfo) { LOG_ERROR("scripts.ai.sai", "SmartScript: SMART_ACTION_EQUIP uses non-existent equipment info id {} for creature {}, skipped.", equipId, e.entryOrGuid); return false; @@ -1783,7 +1789,6 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e) case SMART_ACTION_MOVE_TO_POS: case SMART_ACTION_EVADE: case SMART_ACTION_SET_ACTIVE: - case SMART_ACTION_START_CLOSEST_WAYPOINT: case SMART_ACTION_FOLLOW: case SMART_ACTION_SET_ORIENTATION: case SMART_ACTION_STORE_TARGET_LIST: @@ -1818,7 +1823,6 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e) case SMART_ACTION_SET_NPC_FLAG: case SMART_ACTION_ADD_NPC_FLAG: case SMART_ACTION_REMOVE_NPC_FLAG: - case SMART_ACTION_CALL_RANDOM_TIMED_ACTIONLIST: case SMART_ACTION_RANDOM_MOVE: case SMART_ACTION_SET_UNIT_FIELD_BYTES_1: case SMART_ACTION_REMOVE_UNIT_FIELD_BYTES_1: diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.h b/src/server/game/AI/SmartScripts/SmartScriptMgr.h index c8f3f2609..1c3f500ec 100644 --- a/src/server/game/AI/SmartScripts/SmartScriptMgr.h +++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.h @@ -49,6 +49,16 @@ struct WayPoint uint32 delay; }; +enum eSmartAI +{ + SMART_EVENT_PARAM_COUNT = 4, + SMART_ACTION_PARAM_COUNT = 6, + SMART_SUMMON_COUNTER = 0xFFFFFF, + SMART_ESCORT_LAST_OOC_POINT = 0xFFFFFF, + SMART_RANDOM_POINT = 0xFFFFFE, + SMART_ESCORT_TARGETS = 0xFFFFFF +}; + enum SMART_EVENT_PHASE { SMART_EVENT_PHASE_ALWAYS = 0, @@ -758,12 +768,7 @@ struct SmartAction struct { - uint32 emote1; - uint32 emote2; - uint32 emote3; - uint32 emote4; - uint32 emote5; - uint32 emote6; + std::array emotes; } randomEmote; struct @@ -858,12 +863,7 @@ struct SmartAction struct { - uint32 phase1; - uint32 phase2; - uint32 phase3; - uint32 phase4; - uint32 phase5; - uint32 phase6; + std::array phases; } randomPhase; struct @@ -1049,9 +1049,7 @@ struct SmartAction { uint32 entry; uint32 mask; - uint32 slot1; - uint32 slot2; - uint32 slot3; + std::array slots; } equip; struct @@ -1086,12 +1084,7 @@ struct SmartAction struct { - uint32 entry1; - uint32 entry2; - uint32 entry3; - uint32 entry4; - uint32 entry5; - uint32 entry6; + std::array actionLists; } randTimedActionList; struct @@ -1209,12 +1202,7 @@ struct SmartAction struct { - uint32 wp1; - uint32 wp2; - uint32 wp3; - uint32 wp4; - uint32 wp5; - uint32 wp6; + std::array wps; } closestWaypointFromList; struct @@ -1584,16 +1572,6 @@ enum SmartTargetRoleFlags SMART_TARGET_ROLE_FLAG_DAMAGERS = 0x004 }; -enum eSmartAI -{ - SMART_EVENT_PARAM_COUNT = 4, - SMART_ACTION_PARAM_COUNT = 6, - SMART_SUMMON_COUNTER = 0xFFFFFF, - SMART_ESCORT_LAST_OOC_POINT = 0xFFFFFF, - SMART_RANDOM_POINT = 0xFFFFFE, - SMART_ESCORT_TARGETS = 0xFFFFFF -}; - enum SmartScriptType { SMART_SCRIPT_TYPE_CREATURE = 0, //done @@ -1802,60 +1780,43 @@ public: typedef std::unordered_map WPPath; -typedef std::list ObjectList; +typedef std::vector ObjectVector; -class ObjectGuidList +class ObjectGuidVector { - ObjectList* m_objectList; - GuidList* m_guidList; - WorldObject* m_baseObject; - public: - ObjectGuidList(ObjectList* objectList, WorldObject* baseObject) + ObjectGuidVector(WorldObject* baseObject, ObjectVector const& objectVector) : _baseObject(baseObject), _objectVector(objectVector) { - ASSERT(objectList); - m_objectList = objectList; - m_baseObject = baseObject; - m_guidList = new GuidList(); - - for (ObjectList::iterator itr = objectList->begin(); itr != objectList->end(); ++itr) - { - m_guidList->push_back((*itr)->GetGUID()); - } + _guidVector.reserve(_objectVector.size()); + for (WorldObject* obj : _objectVector) + _guidVector.push_back(obj->GetGUID()); } - ObjectList* GetObjectList() + ObjectVector const* GetObjectVector() const { - if (m_baseObject) - { - //sanitize list using m_guidList - m_objectList->clear(); - - for (GuidList::iterator itr = m_guidList->begin(); itr != m_guidList->end(); ++itr) - { - if (WorldObject* obj = ObjectAccessor::GetWorldObject(*m_baseObject, *itr)) - m_objectList->push_back(obj); - //else - // LOG_DEBUG("scripts.ai", "SmartScript::mTargetStorage stores a guid to an invalid object: {}", (*itr).ToString()); - } - } - - return m_objectList; + UpdateObjects(); + return &_objectVector; } - bool Equals(ObjectList* objectList) - { - return m_objectList == objectList; - } + ~ObjectGuidVector() { } - ~ObjectGuidList() +private: + WorldObject* const _baseObject; + mutable ObjectVector _objectVector; + + GuidVector _guidVector; + + //sanitize vector using _guidVector + void UpdateObjects() const { - delete m_objectList; - delete m_guidList; + _objectVector.clear(); + + for (ObjectGuid const& guid : _guidVector) + if (WorldObject* obj = ObjectAccessor::GetWorldObject(*_baseObject, guid)) + _objectVector.push_back(obj); } }; - -typedef std::unordered_map ObjectListMap; +typedef std::unordered_map ObjectVectorMap; class SmartWaypointMgr { From a782eb0a6d8aa9c69f3a4073f8c907068728dd4e Mon Sep 17 00:00:00 2001 From: temperrr Date: Mon, 18 Jul 2022 20:20:14 +0200 Subject: [PATCH 006/130] fix(DB/Creature): Rookery Whelps should not give XP. (#12426) --- data/sql/updates/pending_db_world/rookerywhelpsxp.sql | 1 + 1 file changed, 1 insertion(+) create mode 100644 data/sql/updates/pending_db_world/rookerywhelpsxp.sql diff --git a/data/sql/updates/pending_db_world/rookerywhelpsxp.sql b/data/sql/updates/pending_db_world/rookerywhelpsxp.sql new file mode 100644 index 000000000..8bcbe2b49 --- /dev/null +++ b/data/sql/updates/pending_db_world/rookerywhelpsxp.sql @@ -0,0 +1 @@ +UPDATE `creature_template` SET `flags_extra` = `flags_extra` |64 WHERE (`entry` = 10161); From 8882be570ce9bb88850c901643faedd0096c9596 Mon Sep 17 00:00:00 2001 From: Gultask <100873791+Gultask@users.noreply.github.com> Date: Mon, 18 Jul 2022 15:20:54 -0300 Subject: [PATCH 007/130] fix(DB/Loot): Cuergo's Hidden Treasure (9265) (#12283) --- data/sql/updates/pending_db_world/cuergo.sql | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 data/sql/updates/pending_db_world/cuergo.sql diff --git a/data/sql/updates/pending_db_world/cuergo.sql b/data/sql/updates/pending_db_world/cuergo.sql new file mode 100644 index 000000000..e17abd620 --- /dev/null +++ b/data/sql/updates/pending_db_world/cuergo.sql @@ -0,0 +1,5 @@ +-- +DELETE FROM `item_loot_template` WHERE (`Entry` = 9265) AND (`Item` IN (9360, 9361)); +INSERT INTO `item_loot_template` (`Entry`, `Item`, `Reference`, `Chance`, `QuestRequired`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`, `Comment`) VALUES +(9265, 9360, 0, 92, 0, 1, 1, 1, 1, 'Cuergo\'s Hidden Treasure - Cuergo\'s Gold'), +(9265, 9361, 0, 0, 0, 1, 1, 1, 1, 'Cuergo\'s Hidden Treasure - Cuergo\'s Gold with worm'); From 2a199fdaef07987efe61ce70b81c72b76324273d Mon Sep 17 00:00:00 2001 From: AzerothCoreBot Date: Mon, 18 Jul 2022 18:23:10 +0000 Subject: [PATCH 008/130] chore(DB): import pending files Referenced commit(s): 8882be570ce9bb88850c901643faedd0096c9596 --- .../{pending_db_world/cuergo.sql => db_world/2022_07_18_00.sql} | 1 + .../rookerywhelpsxp.sql => db_world/2022_07_18_01.sql} | 1 + 2 files changed, 2 insertions(+) rename data/sql/updates/{pending_db_world/cuergo.sql => db_world/2022_07_18_00.sql} (90%) rename data/sql/updates/{pending_db_world/rookerywhelpsxp.sql => db_world/2022_07_18_01.sql} (67%) diff --git a/data/sql/updates/pending_db_world/cuergo.sql b/data/sql/updates/db_world/2022_07_18_00.sql similarity index 90% rename from data/sql/updates/pending_db_world/cuergo.sql rename to data/sql/updates/db_world/2022_07_18_00.sql index e17abd620..27f250d95 100644 --- a/data/sql/updates/pending_db_world/cuergo.sql +++ b/data/sql/updates/db_world/2022_07_18_00.sql @@ -1,3 +1,4 @@ +-- DB update 2022_07_13_00 -> 2022_07_18_00 -- DELETE FROM `item_loot_template` WHERE (`Entry` = 9265) AND (`Item` IN (9360, 9361)); INSERT INTO `item_loot_template` (`Entry`, `Item`, `Reference`, `Chance`, `QuestRequired`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`, `Comment`) VALUES diff --git a/data/sql/updates/pending_db_world/rookerywhelpsxp.sql b/data/sql/updates/db_world/2022_07_18_01.sql similarity index 67% rename from data/sql/updates/pending_db_world/rookerywhelpsxp.sql rename to data/sql/updates/db_world/2022_07_18_01.sql index 8bcbe2b49..836f13116 100644 --- a/data/sql/updates/pending_db_world/rookerywhelpsxp.sql +++ b/data/sql/updates/db_world/2022_07_18_01.sql @@ -1 +1,2 @@ +-- DB update 2022_07_18_00 -> 2022_07_18_01 UPDATE `creature_template` SET `flags_extra` = `flags_extra` |64 WHERE (`entry` = 10161); From 9aeb23636803c681efa8d25451639e2f7b7a2f0c Mon Sep 17 00:00:00 2001 From: UltraNix <80540499+UltraNix@users.noreply.github.com> Date: Tue, 19 Jul 2022 16:52:49 +0200 Subject: [PATCH 009/130] fix(Scripts/ZulGurub): Corrected timers on Arlokk. (#12397) Fixes #12366 Co-authored-by: Maelthyr --- .../updates/pending_db_world/rev_1657971514916176000.sql | 2 ++ src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp | 6 +++--- 2 files changed, 5 insertions(+), 3 deletions(-) create mode 100644 data/sql/updates/pending_db_world/rev_1657971514916176000.sql diff --git a/data/sql/updates/pending_db_world/rev_1657971514916176000.sql b/data/sql/updates/pending_db_world/rev_1657971514916176000.sql new file mode 100644 index 000000000..c5f309323 --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1657971514916176000.sql @@ -0,0 +1,2 @@ +-- +UPDATE `spell_dbc` SET `DurationIndex`=21 WHERE `ID`=24235; diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp index 77877043f..5c33f4a82 100644 --- a/src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp +++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp @@ -122,7 +122,7 @@ public: events.ScheduleEvent(EVENT_GOUGE, urand(12000, 15000), 0, PHASE_ONE); events.ScheduleEvent(EVENT_SUMMON_PROWLERS, 6000, 0, PHASE_ALL); events.ScheduleEvent(EVENT_MARK_OF_ARLOKK, urand(9000, 11000), 0, PHASE_ALL); - events.ScheduleEvent(EVENT_TRANSFORM, urand(15000, 20000), 0, PHASE_ONE); + events.ScheduleEvent(EVENT_TRANSFORM, 30000, 0, PHASE_ONE); Talk(SAY_AGGRO); // Sets up list of Panther spawners to cast on @@ -259,7 +259,7 @@ public: me->RemoveAura(SPELL_SUPER_INVIS); me->RemoveAura(SPELL_VANISH); events.ScheduleEvent(EVENT_RAVAGE, urand(10000, 14000), 0, PHASE_TWO); - events.ScheduleEvent(EVENT_TRANSFORM_BACK, urand(15000, 18000), 0, PHASE_TWO); + events.ScheduleEvent(EVENT_TRANSFORM_BACK, urand(30000, 40000), 0, PHASE_TWO); events.SetPhase(PHASE_TWO); me->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, 35.0f, true); // hack break; @@ -276,7 +276,7 @@ public: me->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, 35.0f, false); // hack events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, urand(4000, 7000), 0, PHASE_ONE); events.ScheduleEvent(EVENT_GOUGE, urand(12000, 15000), 0, PHASE_ONE); - events.ScheduleEvent(EVENT_TRANSFORM, urand(16000, 20000), 0, PHASE_ONE); + events.ScheduleEvent(EVENT_TRANSFORM, 30000, 0, PHASE_ONE); events.SetPhase(PHASE_ONE); break; } From 2d6679d1e581bcac78b2aa30142997c9b96e1246 Mon Sep 17 00:00:00 2001 From: AzerothCoreBot Date: Tue, 19 Jul 2022 14:54:54 +0000 Subject: [PATCH 010/130] chore(DB): import pending files Referenced commit(s): 9aeb23636803c681efa8d25451639e2f7b7a2f0c --- .../rev_1657971514916176000.sql => db_world/2022_07_19_00.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/rev_1657971514916176000.sql => db_world/2022_07_19_00.sql} (58%) diff --git a/data/sql/updates/pending_db_world/rev_1657971514916176000.sql b/data/sql/updates/db_world/2022_07_19_00.sql similarity index 58% rename from data/sql/updates/pending_db_world/rev_1657971514916176000.sql rename to data/sql/updates/db_world/2022_07_19_00.sql index c5f309323..575bdf287 100644 --- a/data/sql/updates/pending_db_world/rev_1657971514916176000.sql +++ b/data/sql/updates/db_world/2022_07_19_00.sql @@ -1,2 +1,3 @@ +-- DB update 2022_07_18_01 -> 2022_07_19_00 -- UPDATE `spell_dbc` SET `DurationIndex`=21 WHERE `ID`=24235; From 700dfde2afa5803c46f53293a49baa4c228fc601 Mon Sep 17 00:00:00 2001 From: UltraNix <80540499+UltraNix@users.noreply.github.com> Date: Tue, 19 Jul 2022 16:59:02 +0200 Subject: [PATCH 011/130] =?UTF-8?q?fix(Scripts/ZulGurub):=20Threat=20cause?= =?UTF-8?q?d=20by=20`SPELL=5FAURA=5FDAMAGE=5FSHIELD`=20au=E2=80=A6=20(#123?= =?UTF-8?q?98)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ...ras should not count to Threating Gaze Charge mechanic. Fixes #12379 --- src/server/scripts/EasternKingdoms/ZulGurub/boss_mandokir.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_mandokir.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_mandokir.cpp index 018b64b64..ccf460440 100644 --- a/src/server/scripts/EasternKingdoms/ZulGurub/boss_mandokir.cpp +++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_mandokir.cpp @@ -286,7 +286,7 @@ public: if (_chargeTarget.first == hatedUnit->GetGUID()) { // Do not count DOTs/HOTs - if (!threatSpell || !threatSpell->HasAttribute(SPELL_ATTR0_CU_NO_INITIAL_THREAT)) + if (!(threatSpell && (threatSpell->HasAura(SPELL_AURA_DAMAGE_SHIELD) || threatSpell->HasAttribute(SPELL_ATTR0_CU_NO_INITIAL_THREAT)))) { _chargeTarget.second += threat; } From 1078ad720c8e3cb1f9dc51d53911854f5d348eab Mon Sep 17 00:00:00 2001 From: UltraNix <80540499+UltraNix@users.noreply.github.com> Date: Tue, 19 Jul 2022 17:11:44 +0200 Subject: [PATCH 012/130] fix(Scripts/ZulGurub): Improvements to Jindo the Hexxer (#12395) --- .../rev_1657968102568754700.sql | 2 + .../EasternKingdoms/ZulGurub/boss_jindo.cpp | 43 ++++++++++++++----- 2 files changed, 34 insertions(+), 11 deletions(-) create mode 100644 data/sql/updates/pending_db_world/rev_1657968102568754700.sql diff --git a/data/sql/updates/pending_db_world/rev_1657968102568754700.sql b/data/sql/updates/pending_db_world/rev_1657968102568754700.sql new file mode 100644 index 000000000..9f15023c0 --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1657968102568754700.sql @@ -0,0 +1,2 @@ +-- +UPDATE `creature_template` SET `ScriptName`='npc_brain_wash_totem' WHERE `entry`=15112; diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_jindo.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_jindo.cpp index d4aa84a18..6d85c47d8 100644 --- a/src/server/scripts/EasternKingdoms/ZulGurub/boss_jindo.cpp +++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_jindo.cpp @@ -68,6 +68,9 @@ struct boss_jindo : public BossAI events.ScheduleEvent(EVENT_TELEPORT, 5000); Talk(SAY_AGGRO); + + me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_NONE); + _scheduler.CancelAll(); } void JustSummoned(Creature* summon) override @@ -76,14 +79,15 @@ struct boss_jindo : public BossAI switch (summon->GetEntry()) { - case NPC_BRAIN_WASH_TOTEM: - if (Unit* target = SelectTarget(SelectTargetMethod::Random, 1)) - { - summon->CastSpell(target, summon->m_spells[0], true); - } - break; - default: - break; + case NPC_BRAIN_WASH_TOTEM: + summon->SetReactState(REACT_PASSIVE); + if (Unit* target = SelectTarget(SelectTargetMethod::Random, me->GetThreatMgr().getThreatList().size() > 1 ? 1 : 0)) + { + summon->CastSpell(target, summon->m_spells[0], true); + } + break; + default: + break; } } @@ -91,20 +95,22 @@ struct boss_jindo : public BossAI { if (_EnterEvadeMode(evadeReason)) { - me->AddUnitState(UNIT_STATE_EVADE); Reset(); me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_DANCE); - me->m_Events.AddEventAtOffset([&]() + _scheduler.Schedule(4s, [this](TaskContext /*context*/) { me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_NONE); + me->AddUnitState(UNIT_STATE_EVADE); me->GetMotionMaster()->MoveTargetedHome(); - }, 4s); + }); } } void UpdateAI(uint32 diff) override { + _scheduler.Update(diff); + if (!UpdateVictim()) return; @@ -153,6 +159,9 @@ struct boss_jindo : public BossAI return true; } + +private: + TaskScheduler _scheduler; }; //Healing Ward @@ -282,11 +291,23 @@ class spell_delusions_of_jindo : public SpellScript } }; +struct npc_brain_wash_totem : public ScriptedAI +{ + npc_brain_wash_totem(Creature* creature) : ScriptedAI(creature) + { + } + + void EnterEvadeMode(EvadeReason /*evadeReason*/) override + { + } +}; + void AddSC_boss_jindo() { RegisterZulGurubCreatureAI(boss_jindo); RegisterZulGurubCreatureAI(npc_healing_ward); RegisterZulGurubCreatureAI(npc_shade_of_jindo); + RegisterZulGurubCreatureAI(npc_brain_wash_totem); RegisterSpellScript(spell_random_aggro); RegisterSpellScript(spell_delusions_of_jindo); } From fbee3bbec054520d2d3a64bb26881e45dce901c7 Mon Sep 17 00:00:00 2001 From: AzerothCoreBot Date: Tue, 19 Jul 2022 15:13:54 +0000 Subject: [PATCH 013/130] chore(DB): import pending files Referenced commit(s): 1078ad720c8e3cb1f9dc51d53911854f5d348eab --- .../rev_1657968102568754700.sql => db_world/2022_07_19_01.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/rev_1657968102568754700.sql => db_world/2022_07_19_01.sql} (67%) diff --git a/data/sql/updates/pending_db_world/rev_1657968102568754700.sql b/data/sql/updates/db_world/2022_07_19_01.sql similarity index 67% rename from data/sql/updates/pending_db_world/rev_1657968102568754700.sql rename to data/sql/updates/db_world/2022_07_19_01.sql index 9f15023c0..2aa01de06 100644 --- a/data/sql/updates/pending_db_world/rev_1657968102568754700.sql +++ b/data/sql/updates/db_world/2022_07_19_01.sql @@ -1,2 +1,3 @@ +-- DB update 2022_07_19_00 -> 2022_07_19_01 -- UPDATE `creature_template` SET `ScriptName`='npc_brain_wash_totem' WHERE `entry`=15112; From 9b6da94510d626619ac5e3c129e97fe253715aef Mon Sep 17 00:00:00 2001 From: Nefertumm Date: Tue, 19 Jul 2022 14:31:03 -0300 Subject: [PATCH 014/130] fix(Core/AI): more AI factory checks (#12402) Co-authored-by: ariel- Co-authored-by: Treeston Co-authored-by: Aokromes --- .../rev_1657988086857948400.sql | 7 ++ src/common/Dynamic/ObjectRegistry.h | 6 ++ src/common/Utilities/Timer.h | 4 +- src/server/game/AI/CoreAI/CombatAI.cpp | 2 +- src/server/game/AI/CoreAI/PetAI.cpp | 3 - src/server/game/AI/CreatureAISelector.cpp | 87 +++++++++---------- src/server/game/Entities/Player/Player.cpp | 5 ++ src/server/game/Globals/ObjectMgr.cpp | 17 ++++ src/server/game/World/World.cpp | 6 +- 9 files changed, 82 insertions(+), 55 deletions(-) create mode 100644 data/sql/updates/pending_db_world/rev_1657988086857948400.sql diff --git a/data/sql/updates/pending_db_world/rev_1657988086857948400.sql b/data/sql/updates/pending_db_world/rev_1657988086857948400.sql new file mode 100644 index 000000000..82e38de8d --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1657988086857948400.sql @@ -0,0 +1,7 @@ +-- +UPDATE `creature` SET `MovementType` = 1, `wander_distance` = 5 WHERE `guid` IN (51879,51914); +UPDATE `creature` SET `MovementType` = 0 WHERE `guid` = 132313; + +UPDATE `creature_template` SET `AIName` = 'NullCreatureAI' WHERE `AIName` IN ('NullCreatureAi', 'NullAI'); +UPDATE `creature_template` SET `AIName` = 'AggressorAI' WHERE `AIName` = 'AgressorAI'; +UPDATE `creature_template` SET `AIName` = '' WHERE `AIName` = 'OutdoorPvPObjectiveAI'; diff --git a/src/common/Dynamic/ObjectRegistry.h b/src/common/Dynamic/ObjectRegistry.h index d72fd7b3a..ba9bccd39 100644 --- a/src/common/Dynamic/ObjectRegistry.h +++ b/src/common/Dynamic/ObjectRegistry.h @@ -65,6 +65,12 @@ public: return true; } + /// Returns true if registry contains an item + bool HasItem(Key const& key) const + { + return (_registeredObjects.count(key) > 0); + } + /// Return the map of registered items RegistryMapType const& GetRegisteredItems() const { diff --git a/src/common/Utilities/Timer.h b/src/common/Utilities/Timer.h index 505b23827..e8d392439 100644 --- a/src/common/Utilities/Timer.h +++ b/src/common/Utilities/Timer.h @@ -231,7 +231,7 @@ private: struct TimeTrackerSmall { public: - TimeTrackerSmall(uint32 expiry = 0) + TimeTrackerSmall(int32 expiry = 0) : i_expiryTime(expiry) { } @@ -246,7 +246,7 @@ public: return i_expiryTime <= 0; } - void Reset(uint32 interval) + void Reset(int32 interval) { i_expiryTime = interval; } diff --git a/src/server/game/AI/CoreAI/CombatAI.cpp b/src/server/game/AI/CoreAI/CombatAI.cpp index 18c7a2382..c038d5b98 100644 --- a/src/server/game/AI/CoreAI/CombatAI.cpp +++ b/src/server/game/AI/CoreAI/CombatAI.cpp @@ -30,7 +30,7 @@ int32 AggressorAI::Permissible(Creature const* creature) { // have some hostile factions, it will be selected by IsHostileTo check at MoveInLineOfSight if (!creature->IsCivilian() && !creature->IsNeutralToAll()) - return PERMIT_BASE_PROACTIVE; + return PERMIT_BASE_REACTIVE; return PERMIT_BASE_NO; } diff --git a/src/server/game/AI/CoreAI/PetAI.cpp b/src/server/game/AI/CoreAI/PetAI.cpp index 3ed00426f..a60083a67 100644 --- a/src/server/game/AI/CoreAI/PetAI.cpp +++ b/src/server/game/AI/CoreAI/PetAI.cpp @@ -30,9 +30,6 @@ int32 PetAI::Permissible(Creature const* creature) { - if (creature->IsPet()) - return PERMIT_BASE_SPECIAL; - if (creature->HasUnitTypeMask(UNIT_MASK_CONTROLABLE_GUARDIAN)) { if (reinterpret_cast(creature)->GetOwner()->GetTypeId() == TYPEID_PLAYER) diff --git a/src/server/game/AI/CreatureAISelector.cpp b/src/server/game/AI/CreatureAISelector.cpp index d4c1e71a1..c4436b840 100644 --- a/src/server/game/AI/CreatureAISelector.cpp +++ b/src/server/game/AI/CreatureAISelector.cpp @@ -28,6 +28,13 @@ namespace FactorySelector { + template + inline int32 GetPermitFor(T const* obj, Value const& value) + { + Permissible const* const p = ASSERT_NOTNULL(dynamic_cast const*>(value.second.get())); + return p->Permit(obj); + } + template struct PermissibleOrderPred { @@ -37,50 +44,57 @@ namespace FactorySelector template bool operator()(Value const& left, Value const& right) const { - Permissible const* leftPermit = ASSERT_NOTNULL(dynamic_cast const*>(left.second.get())); - Permissible const* rightPermit = ASSERT_NOTNULL(dynamic_cast const*>(right.second.get())); - - return leftPermit->Permit(_obj) < rightPermit->Permit(_obj); + return GetPermitFor(_obj, left) < GetPermitFor(_obj, right); } private: T const* const _obj; }; - CreatureAI* SelectAI(Creature* creature) + template + inline FactoryHolder const* SelectFactory(T* obj) { - CreatureAICreator const* ai_factory = nullptr; + static_assert(std::is_same::value || std::is_same::value, "Invalid template parameter"); + static_assert(std::is_same::value == std::is_same::value, "Incompatible AI for type"); + static_assert(std::is_same::value == std::is_same::value, "Incompatible AI for type"); - // scriptname in db - if (!ai_factory) - if (CreatureAI* scriptedAI = sScriptMgr->GetCreatureAI(creature)) - return scriptedAI; + using AIRegistry = typename FactoryHolder::FactoryHolderRegistry; - // AIname in db - std::string const& aiName = creature->GetAIName(); - if (!ai_factory && !aiName.empty()) - ai_factory = sCreatureAIRegistry->GetRegistryItem(aiName); + // AIName in db + std::string const& aiName = obj->GetAIName(); + if (!aiName.empty()) + return AIRegistry::instance()->GetRegistryItem(aiName); // select by permit check - if (!ai_factory) - { - CreatureAIRegistry::RegistryMapType const& items = sCreatureAIRegistry->GetRegisteredItems(); - auto itr = std::max_element(items.begin(), items.end(), PermissibleOrderPred(creature)); - if (itr != items.end()) - ai_factory = itr->second.get(); - } + typename AIRegistry::RegistryMapType const& items = AIRegistry::instance()->GetRegisteredItems(); + auto itr = std::max_element(items.begin(), items.end(), PermissibleOrderPred(obj)); + if (itr != items.end() && GetPermitFor(obj, *itr) >= 0) + return itr->second.get(); - if (!ai_factory) - ai_factory = sCreatureAIRegistry->GetRegistryItem("NullCreatureAI"); + // should _never_ happen, Null AI types defined as PERMIT_BASE_IDLE, it must've been found + ABORT(); + return nullptr; + } - return ASSERT_NOTNULL(ai_factory)->Create(creature); + CreatureAI* SelectAI(Creature* creature) + { + // special pet case, if a tamed creature uses AIName (example SmartAI) we need to override it + if (creature->IsPet()) + return ASSERT_NOTNULL(sCreatureAIRegistry->GetRegistryItem("PetAI"))->Create(creature); + + // scriptname in db + if (CreatureAI* scriptedAI = sScriptMgr->GetCreatureAI(creature)) + return scriptedAI; + + return SelectFactory(creature)->Create(creature); } MovementGenerator* SelectMovementGenerator(Unit* unit) { MovementGeneratorType type = IDLE_MOTION_TYPE; - if (unit->GetTypeId() == TYPEID_UNIT) - type = unit->ToCreature()->GetDefaultMovementType(); + if (Creature* creature = unit->ToCreature()) + if (!creature->GetCharmerOrOwnerPlayerOrPlayerItself()) + type = creature->GetDefaultMovementType(); MovementGeneratorCreator const* mv_factory = sMovementGeneratorRegistry->GetRegistryItem(type); return ASSERT_NOTNULL(mv_factory)->Create(unit); @@ -88,29 +102,10 @@ namespace FactorySelector GameObjectAI* SelectGameObjectAI(GameObject* go) { - GameObjectAICreator const* ai_factory = nullptr; - // scriptname in db if (GameObjectAI* scriptedAI = sScriptMgr->GetGameObjectAI(go)) return scriptedAI; - // AIname in db - std::string const& aiName = go->GetAIName(); - if (!ai_factory && !aiName.empty()) - ai_factory = sGameObjectAIRegistry->GetRegistryItem(aiName); - - // select by permit check - if (!ai_factory) - { - GameObjectAIRegistry::RegistryMapType const& items = sGameObjectAIRegistry->GetRegisteredItems(); - auto itr = std::max_element(items.begin(), items.end(), PermissibleOrderPred(go)); - if (itr != items.end()) - ai_factory = itr->second.get(); - } - - if (!ai_factory) - ai_factory = sGameObjectAIRegistry->GetRegistryItem("NullGameObjectAI"); - - return ASSERT_NOTNULL(ai_factory)->Create(go); + return SelectFactory(go)->Create(go); } } diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 2c8fe1dfb..25d9425b9 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -12561,8 +12561,13 @@ void Player::SetMover(Unit* target) LOG_INFO("misc", "Player::SetMover (B2) - {}, {}, {}, {}, {}, {}, {}, {}", target->GetGUID().ToString(), target->GetMapId(), target->GetInstanceId(), target->FindMap()->GetId(), target->IsInWorld() ? 1 : 0, target->IsDuringRemoveFromWorld() ? 1 : 0, (target->ToPlayer() && target->ToPlayer()->IsBeingTeleported() ? 1 : 0), target->isBeingLoaded() ? 1 : 0); } m_mover->m_movedByPlayer = nullptr; + if (m_mover->GetTypeId() == TYPEID_UNIT) + m_mover->GetMotionMaster()->Initialize(); + m_mover = target; m_mover->m_movedByPlayer = this; + if (m_mover->GetTypeId() == TYPEID_UNIT) + m_mover->GetMotionMaster()->Initialize(); } uint32 Player::GetCorpseReclaimDelay(bool pvp) const diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index 568597c34..ca63485ba 100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -22,10 +22,12 @@ #include "CharacterCache.h" #include "Chat.h" #include "Common.h" +#include "CreatureAIFactory.h" #include "Config.h" #include "Containers.h" #include "DatabaseEnv.h" #include "DisableMgr.h" +#include "GameObjectAIFactory.h" #include "GameEventMgr.h" #include "GameTime.h" #include "GossipDef.h" @@ -979,6 +981,12 @@ void ObjectMgr::CheckCreatureTemplate(CreatureTemplate const* cInfo) ok = true; } + if (!cInfo->AIName.empty() && !sCreatureAIRegistry->HasItem(cInfo->AIName)) + { + LOG_ERROR("sql.sql", "Creature (Entry: {}) has non-registered `AIName` '{}' set, removing", cInfo->Entry, cInfo->AIName); + const_cast(cInfo)->AIName.clear(); + } + FactionTemplateEntry const* factionTemplate = sFactionTemplateStore.LookupEntry(cInfo->faction); if (!factionTemplate) LOG_ERROR("sql.sql", "Creature (Entry: {}) has non-existing faction template ({}).", cInfo->Entry, cInfo->faction); @@ -2162,6 +2170,11 @@ void ObjectMgr::LoadCreatures() LOG_ERROR("sql.sql", "Table `creature` have creature (SpawnId: {} Entries: {}, {}, {}) with a `creature_template`.`flags_extra` in one or more entries including CREATURE_FLAG_EXTRA_INSTANCE_BIND but creature are not in instance.", spawnId, data.id1, data.id2, data.id3); } + if (data.movementType >= MAX_DB_MOTION_TYPE) + { + LOG_ERROR("sql.sql", "Table `creature` has creature (SpawnId: {} Entries: {}, {}, {}) with wrong movement generator type ({}), ignored and set to IDLE.", spawnId, data.id1, data.id2, data.id3, data.movementType); + data.movementType = IDLE_MOTION_TYPE; + } if (data.wander_distance < 0.0f) { LOG_ERROR("sql.sql", "Table `creature` have creature (SpawnId: {} Entries: {}, {}, {}) with `wander_distance`< 0, set to 0.", spawnId, data.id1, data.id2, data.id3); @@ -7040,6 +7053,10 @@ void ObjectMgr::LoadGameObjectTemplate() got.IsForQuests = false; // Checks + if (!got.AIName.empty() && !sGameObjectAIRegistry->HasItem(got.AIName)) + { + LOG_ERROR("sql.sql", "GameObject (Entry: {}) has non-registered `AIName` '{}' set, removing", got.entry, got.AIName); + } switch (got.type) { diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index 8e64e7b49..9702172a0 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -1567,6 +1567,9 @@ void World::SetInitialWorldSettings() LOG_INFO("server.loading", "Initializing PlayerDump tables..."); PlayerDump::InitializeTables(); + ///- Initilize static helper structures + AIRegistry::Initialize(); + LOG_INFO("server.loading", "Loading SpellInfo store..."); sSpellMgr->LoadSpellInfoStore(); @@ -2035,9 +2038,6 @@ void World::SetInitialWorldSettings() mail_expire_check_timer = GameTime::GetGameTime() + 6h; - ///- Initilize static helper structures - AIRegistry::Initialize(); - ///- Initialize MapMgr LOG_INFO("server.loading", "Starting Map System"); LOG_INFO("server.loading", " "); From 1c8d562f012656ede5a961f7a53313b2cf208acc Mon Sep 17 00:00:00 2001 From: AzerothCoreBot Date: Tue, 19 Jul 2022 17:33:19 +0000 Subject: [PATCH 015/130] chore(DB): import pending files Referenced commit(s): 9b6da94510d626619ac5e3c129e97fe253715aef --- .../rev_1657988086857948400.sql => db_world/2022_07_19_02.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/rev_1657988086857948400.sql => db_world/2022_07_19_02.sql} (90%) diff --git a/data/sql/updates/pending_db_world/rev_1657988086857948400.sql b/data/sql/updates/db_world/2022_07_19_02.sql similarity index 90% rename from data/sql/updates/pending_db_world/rev_1657988086857948400.sql rename to data/sql/updates/db_world/2022_07_19_02.sql index 82e38de8d..1a0b09097 100644 --- a/data/sql/updates/pending_db_world/rev_1657988086857948400.sql +++ b/data/sql/updates/db_world/2022_07_19_02.sql @@ -1,3 +1,4 @@ +-- DB update 2022_07_19_01 -> 2022_07_19_02 -- UPDATE `creature` SET `MovementType` = 1, `wander_distance` = 5 WHERE `guid` IN (51879,51914); UPDATE `creature` SET `MovementType` = 0 WHERE `guid` = 132313; From 1066bc76b17fe76b5cd7ab6321a3579834ee1072 Mon Sep 17 00:00:00 2001 From: UltraNix <80540499+UltraNix@users.noreply.github.com> Date: Tue, 19 Jul 2022 23:02:45 +0200 Subject: [PATCH 016/130] =?UTF-8?q?fix(Core/Spells):=20Upon=20using=20char?= =?UTF-8?q?ge=20warrior=20should=20start=20auto=20attacki=E2=80=A6=20(#124?= =?UTF-8?q?08)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ...ng the targeted enemy once you reach them. --- .../Movement/MovementGenerators/PointMovementGenerator.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp index 6e8f80065..5e06523fa 100644 --- a/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp @@ -41,7 +41,7 @@ void PointMovementGenerator::DoInitialize(T* unit) unit->StopMoving(); unit->AddUnitState(UNIT_STATE_ROAMING | UNIT_STATE_ROAMING_MOVE); - if (id == EVENT_CHARGE) + if (id == EVENT_CHARGE || id == EVENT_CHARGE_PREPATH) { unit->AddUnitState(UNIT_STATE_CHARGING); } @@ -158,7 +158,7 @@ template void PointMovementGenerator::DoFinalize(T* unit) { unit->ClearUnitState(UNIT_STATE_ROAMING | UNIT_STATE_ROAMING_MOVE); - if (id == EVENT_CHARGE) + if (id == EVENT_CHARGE || id == EVENT_CHARGE_PREPATH) { unit->ClearUnitState(UNIT_STATE_CHARGING); @@ -182,7 +182,7 @@ void PointMovementGenerator::DoReset(T* unit) unit->StopMoving(); unit->AddUnitState(UNIT_STATE_ROAMING | UNIT_STATE_ROAMING_MOVE); - if (id == EVENT_CHARGE) + if (id == EVENT_CHARGE || id == EVENT_CHARGE_PREPATH) { unit->AddUnitState(UNIT_STATE_CHARGING); } From 79f34b2b311804f06a1dc764f00dc63370ec6320 Mon Sep 17 00:00:00 2001 From: UltraNix <80540499+UltraNix@users.noreply.github.com> Date: Tue, 19 Jul 2022 23:25:01 +0200 Subject: [PATCH 017/130] =?UTF-8?q?fix(DB/Spells):=20Zandalarian=20Hero=20?= =?UTF-8?q?Charm=20trinket=20should=20drop=20off=20stacks=E2=80=A6=20(#124?= =?UTF-8?q?06)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit … only on cast. --- data/sql/updates/pending_db_world/rev_1658046606233879000.sql | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 data/sql/updates/pending_db_world/rev_1658046606233879000.sql diff --git a/data/sql/updates/pending_db_world/rev_1658046606233879000.sql b/data/sql/updates/pending_db_world/rev_1658046606233879000.sql new file mode 100644 index 000000000..044822329 --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1658046606233879000.sql @@ -0,0 +1,2 @@ +-- +UPDATE `spell_proc_event` SET `procPhase`=1 WHERE `entry`=24658; From 12689237b81d16adb366a48f84f84e6eceb583bb Mon Sep 17 00:00:00 2001 From: AzerothCoreBot Date: Tue, 19 Jul 2022 21:27:03 +0000 Subject: [PATCH 018/130] chore(DB): import pending files Referenced commit(s): 79f34b2b311804f06a1dc764f00dc63370ec6320 --- .../rev_1658046606233879000.sql => db_world/2022_07_19_03.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/rev_1658046606233879000.sql => db_world/2022_07_19_03.sql} (60%) diff --git a/data/sql/updates/pending_db_world/rev_1658046606233879000.sql b/data/sql/updates/db_world/2022_07_19_03.sql similarity index 60% rename from data/sql/updates/pending_db_world/rev_1658046606233879000.sql rename to data/sql/updates/db_world/2022_07_19_03.sql index 044822329..d95649125 100644 --- a/data/sql/updates/pending_db_world/rev_1658046606233879000.sql +++ b/data/sql/updates/db_world/2022_07_19_03.sql @@ -1,2 +1,3 @@ +-- DB update 2022_07_19_02 -> 2022_07_19_03 -- UPDATE `spell_proc_event` SET `procPhase`=1 WHERE `entry`=24658; From dc3025249ce5099d9f7eb8bbebb030e72a6c64d2 Mon Sep 17 00:00:00 2001 From: neifion-00000000 <91289495+neifion-00000000@users.noreply.github.com> Date: Tue, 19 Jul 2022 17:24:53 -0500 Subject: [PATCH 019/130] fix(db/creature): ZG entrance creature improvement, part 2 (#12371) --- .../rev_1657669676037619800.sql | 283 ++++++++++++++++++ 1 file changed, 283 insertions(+) create mode 100644 data/sql/updates/pending_db_world/rev_1657669676037619800.sql diff --git a/data/sql/updates/pending_db_world/rev_1657669676037619800.sql b/data/sql/updates/pending_db_world/rev_1657669676037619800.sql new file mode 100644 index 000000000..dd280d96f --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1657669676037619800.sql @@ -0,0 +1,283 @@ +-- +/* Maintenance on ZG Entranceway mobs part 2 Pooling */ +DELETE FROM `creature` WHERE `guid` IN (49116, 49117, 49118, 49119); +DELETE FROM `creature_addon` WHERE `guid` IN (49116, 49117, 49118, 49119); +DELETE FROM `waypoint_data` WHERE `id` IN (49116, 49117, 49118, 49119); + +/* 20 Pools of V( (Themselves Pooled) to represent every possibility; this is the only way I know how to represent every possibility I am open to other suggestions; 72 snakes + +INSERT INTO `creature` (`guid`, `id1`, `id2`, `id3`, `map`, `zoneId`, `areaId`, `spawnMask`, `phaseMask`, `equipment_id`, `position_x`, `position_y`, `position_z`, `orientation`, `spawntimesecs`, `wander_distance`, `currentwaypoint`, `curhealth`, `curmana`, `MovementType`, `npcflag`, `unit_flags`, `dynamicflags`, `ScriptName`, `VerifiedBuild`) VALUES +(@GUID+, 0, 0, 0, 309, 0, 0, 1, 1, 0, -11884.3, -1379.01, 66.4316, 3.36848, 7200, 3, 0, 15260, 0, 1, 0, 0, 0, '', 0), -- Empty Occasionally 1 slot, front facing exit +(@GUID+, 0, 0, 0, 309, 0, 0, 1, 1, 0, -11896.4, -1365.13, 69.8727, 2.42601, 7200, 3, 0, 15260, 0, 1, 0, 0, 0, '', 0), -- Empty Occasionally 2 slot left facing exit +(@GUID+, 0, 0, 0, 309, 0, 0, 1, 1, 0, -11885, -1368.42, 68.8007, 5.53269, 7200, 3, 0, 15260, 0, 1, 0, 0, 0, '', 0), -- 3 slot center slot +(@GUID+, 0, 0, 0, 309, 0, 0, 1, 1, 0, -11878.2, -1368.68, 69.7661, 3.90954, 7200, 3, 0, 15260, 0, 1, 0, 0, 0, '', 0); -- 4 slot right slot + +@POOL+0 Master Pool of all of the following Pools + +8 Pools are 6.25% to create a 50% chance of 3 mobs spawning, let E1 and E2 represent empty xyz slots that have been witnessed empty + +@POOL+1 E1 A@GUID+0 S@GUID+1 X@GUID+2 +@POOL+2 E1 A@GUID+3 X@GUID+4 S@GUID+5 +@POOL+3 E1 S@GUID+6 A@GUID+7 X@GUID+8 +@POOL+4 E1 S@GUID+9 X@GUID+10 A@GUID+11 +@POOL+5 A@GUID+12 E2 S@GUID+13 X@GUID+14 +@POOL+6 A@GUID+15 E2 X@GUID+16 S@GUID+17 +@POOL+7 S@GUID+18 E2 A@GUID+19 X@GUID+20 +@POOL+8 S@GUID+21 E2 X@GUID+22 A@GUID+23 + +11 Pools of 4.16% and 1 of 4.24% to create a 50% chance of 4 mobs spawning 1-3 of each type +@POOL+9 A@GUID+24 S@GUID+25 X@GUID+26 X@GUID+27 +@POOL+10 A@GUID+28 X@GUID+29 S@GUID+30 X@GUID+31 +@POOL+11 A@GUID+32 X@GUID+33 X@GUID+34 S@GUID+35 +@POOL+12 S@GUID+36 A@GUID+37 X@GUID+38 X@GUID+39 +@POOL+13 S@GUID+40 X@GUID+41 A@GUID+42 X@GUID+43 +@POOL+14 S@GUID+44 X@GUID+45 X@GUID+46 A@GUID+47 +@POOL+15 X@GUID+48 A@GUID+49 S@GUID+50 X@GUID+51 +@POOL+16 X@GUID+52 A@GUID+53 X@GUID+54 S@GUID+55 +@POOL+17 X@GUID+56 S@GUID+57 A@GUID+58 X@GUID+59 +@POOL+18 X@GUID+60 S@GUID+61 X@GUID+62 A@GUID+63 +@POOL+19 X@GUID+64 X@GUID+65 A@GUID+66 S@GUID+67 +@POOL+20 X@GUID+68 X@GUID+69 S@GUID+70 A@GUID+71 */ + +SET @GUID :=86939; +DELETE FROM `creature` WHERE `guid` BETWEEN @GUID+0 AND @GUID+71; +INSERT INTO `creature` (`guid`, `id1`, `id2`, `id3`, `map`, `zoneId`, `areaId`, `spawnMask`, `phaseMask`, `equipment_id`, `position_x`, `position_y`, `position_z`, `orientation`, `spawntimesecs`, `wander_distance`, `currentwaypoint`, `curhealth`, `curmana`, `MovementType`, `npcflag`, `unit_flags`, `dynamicflags`, `ScriptName`, `VerifiedBuild`) VALUES +-- 3 Packs +-- @POOL+1 E1 11372, 0, 0,@GUID+0 11371, 0, 0,@GUID+1 11371, 11372, 0,@GUID+2 +(@GUID+0, 11372, 0, 0, 309, 0, 0, 1, 1, 0, -11896.4, -1365.13, 69.8727, 2.42601, 7200, 3, 0, 15260, 0, 1, 0, 0, 0, '', 0), -- 2 +(@GUID+1, 11371, 0, 0, 309, 0, 0, 1, 1, 0, -11885, -1368.42, 68.8007, 5.53269, 7200, 3, 0, 15260, 0, 1, 0, 0, 0, '', 0), -- 3 +(@GUID+2, 11371, 11372, 0, 309, 0, 0, 1, 1, 0, -11878.2, -1368.68, 69.7661, 3.90954, 7200, 3, 0, 15260, 0, 1, 0, 0, 0, '', 0), -- 4 +-- @POOL+2 E1 11372, 0, 0,@GUID+3 11371, 11372, 0,@GUID+4 11371, 0, 0,@GUID+5 +(@GUID+3, 11372, 0, 0, 309, 0, 0, 1, 1, 0, -11896.4, -1365.13, 69.8727, 2.42601, 7200, 3, 0, 15260, 0, 1, 0, 0, 0, '', 0), -- 2 +(@GUID+4, 11371, 11372, 0, 309, 0, 0, 1, 1, 0, -11885, -1368.42, 68.8007, 5.53269, 7200, 3, 0, 15260, 0, 1, 0, 0, 0, '', 0), -- 3 +(@GUID+5, 11371, 0, 0, 309, 0, 0, 1, 1, 0, -11878.2, -1368.68, 69.7661, 3.90954, 7200, 3, 0, 15260, 0, 1, 0, 0, 0, '', 0), -- 4 +-- @POOL+3 E1 11371, 0, 0,@GUID+6 11372, 0, 0,@GUID+7 11371, 11372, 0,@GUID+8 +(@GUID+6, 11371, 0, 0, 309, 0, 0, 1, 1, 0, -11896.4, -1365.13, 69.8727, 2.42601, 7200, 3, 0, 15260, 0, 1, 0, 0, 0, '', 0), -- 2 +(@GUID+7, 11372, 0, 0, 309, 0, 0, 1, 1, 0, -11885, -1368.42, 68.8007, 5.53269, 7200, 3, 0, 15260, 0, 1, 0, 0, 0, '', 0), -- 3 +(@GUID+8, 11371, 11372, 0, 309, 0, 0, 1, 1, 0, -11878.2, -1368.68, 69.7661, 3.90954, 7200, 3, 0, 15260, 0, 1, 0, 0, 0, '', 0), -- 4 +-- @POOL+4 E1 11371, 0, 0,@GUID+9 11371, 11372, 0,@GUID+10 11372, 0, 0,@GUID+11 +(@GUID+9, 11371, 0, 0, 309, 0, 0, 1, 1, 0, -11896.4, -1365.13, 69.8727, 2.42601, 7200, 3, 0, 15260, 0, 1, 0, 0, 0, '', 0), -- 2 +(@GUID+10, 11371, 11372, 0, 309, 0, 0, 1, 1, 0, -11885, -1368.42, 68.8007, 5.53269, 7200, 3, 0, 15260, 0, 1, 0, 0, 0, '', 0), -- 3 +(@GUID+11, 11372, 0, 0, 309, 0, 0, 1, 1, 0, -11878.2, -1368.68, 69.7661, 3.90954, 7200, 3, 0, 15260, 0, 1, 0, 0, 0, '', 0), -- 4 +-- @POOL+5 11372, 0, 0,@GUID+12 E2 11371, 0, 0,@GUID+13 11371, 11372, 0,@GUID+14 +(@GUID+12, 11372, 0, 0, 309, 0, 0, 1, 1, 0, -11884.3, -1379.01, 66.4316, 3.36848, 7200, 3, 0, 15260, 0, 1, 0, 0, 0, '', 0), -- 1 +(@GUID+13, 11371, 0, 0, 309, 0, 0, 1, 1, 0, -11885, -1368.42, 68.8007, 5.53269, 7200, 3, 0, 15260, 0, 1, 0, 0, 0, '', 0), -- 3 +(@GUID+14, 11371, 11372, 0, 309, 0, 0, 1, 1, 0, -11878.2, -1368.68, 69.7661, 3.90954, 7200, 3, 0, 15260, 0, 1, 0, 0, 0, '', 0), -- 4 +-- @POOL+6 11372, 0, 0,@GUID+15 E2 11371, 11372, 0,@GUID+16 11371, 0, 0,@GUID+17 +(@GUID+15, 11372, 0, 0, 309, 0, 0, 1, 1, 0, -11884.3, -1379.01, 66.4316, 3.36848, 7200, 3, 0, 15260, 0, 1, 0, 0, 0, '', 0), -- 1 +(@GUID+16, 11371, 11372, 0, 309, 0, 0, 1, 1, 0, -11885, -1368.42, 68.8007, 5.53269, 7200, 3, 0, 15260, 0, 1, 0, 0, 0, '', 0), -- 3 +(@GUID+17, 11371, 0, 0, 309, 0, 0, 1, 1, 0, -11878.2, -1368.68, 69.7661, 3.90954, 7200, 3, 0, 15260, 0, 1, 0, 0, 0, '', 0), -- 4 +-- @POOL+7 11371, 0, 0,@GUID+18 E2 11372, 0, 0,@GUID+19 11371, 11372, 0,@GUID+20 +(@GUID+18, 11371, 0, 0, 309, 0, 0, 1, 1, 0, -11884.3, -1379.01, 66.4316, 3.36848, 7200, 3, 0, 15260, 0, 1, 0, 0, 0, '', 0), -- 1 +(@GUID+19, 11372, 0, 0, 309, 0, 0, 1, 1, 0, -11885, -1368.42, 68.8007, 5.53269, 7200, 3, 0, 15260, 0, 1, 0, 0, 0, '', 0), -- 3 +(@GUID+20, 11371, 11372, 0, 309, 0, 0, 1, 1, 0, -11878.2, -1368.68, 69.7661, 3.90954, 7200, 3, 0, 15260, 0, 1, 0, 0, 0, '', 0), -- 4 +-- @POOL+8 11371, 0, 0,@GUID+21 E2 11371, 11372, 0,@GUID+22 11372, 0, 0,@GUID+23 +(@GUID+21, 11371, 0, 0, 309, 0, 0, 1, 1, 0, -11884.3, -1379.01, 66.4316, 3.36848, 7200, 3, 0, 15260, 0, 1, 0, 0, 0, '', 0), -- 1 +(@GUID+22, 11371, 11372, 0, 309, 0, 0, 1, 1, 0, -11885, -1368.42, 68.8007, 5.53269, 7200, 3, 0, 15260, 0, 1, 0, 0, 0, '', 0), -- 3 +(@GUID+23, 11372, 0, 0, 309, 0, 0, 1, 1, 0, -11878.2, -1368.68, 69.7661, 3.90954, 7200, 3, 0, 15260, 0, 1, 0, 0, 0, '', 0), -- 4 +-- 4 Packs +-- @POOL+9 11372, 0, 0,@GUID+24 11371, 0, 0,@GUID+25 11371, 11372, 0,@GUID+26 11371, 11372, 0,@GUID+27 +(@GUID+24, 11372, 0, 0, 309, 0, 0, 1, 1, 0, -11884.3, -1379.01, 66.4316, 3.36848, 7200, 3, 0, 15260, 0, 1, 0, 0, 0, '', 0), -- 1 +(@GUID+25, 11371, 0, 0, 309, 0, 0, 1, 1, 0, -11896.4, -1365.13, 69.8727, 2.42601, 7200, 3, 0, 15260, 0, 1, 0, 0, 0, '', 0), -- 2 +(@GUID+26, 11371, 11372, 0, 309, 0, 0, 1, 1, 0, -11885, -1368.42, 68.8007, 5.53269, 7200, 3, 0, 15260, 0, 1, 0, 0, 0, '', 0), -- 3 +(@GUID+27, 11371, 11372, 0, 309, 0, 0, 1, 1, 0, -11878.2, -1368.68, 69.7661, 3.90954, 7200, 3, 0, 15260, 0, 1, 0, 0, 0, '', 0), -- 4 +-- @POOL+10 11372, 0, 0,@GUID+28 11371, 11372, 0,@GUID+29 11371, 0, 0,@GUID+30 11371, 11372, 0,@GUID+31 +(@GUID+28, 11372, 0, 0, 309, 0, 0, 1, 1, 0, -11884.3, -1379.01, 66.4316, 3.36848, 7200, 3, 0, 15260, 0, 1, 0, 0, 0, '', 0), -- 1 +(@GUID+29, 11371, 11372, 0, 309, 0, 0, 1, 1, 0, -11896.4, -1365.13, 69.8727, 2.42601, 7200, 3, 0, 15260, 0, 1, 0, 0, 0, '', 0), -- 2 +(@GUID+30, 11371, 0, 0, 309, 0, 0, 1, 1, 0, -11885, -1368.42, 68.8007, 5.53269, 7200, 3, 0, 15260, 0, 1, 0, 0, 0, '', 0), -- 3 +(@GUID+31, 11371, 11372, 0, 309, 0, 0, 1, 1, 0, -11878.2, -1368.68, 69.7661, 3.90954, 7200, 3, 0, 15260, 0, 1, 0, 0, 0, '', 0), -- 4 +-- @POOL+11 11372, 0, 0,@GUID+32 11371, 11372, 0,@GUID+33 11371, 11372, 0,@GUID+34 11371, 0, 0,@GUID+35 +(@GUID+32, 11372, 0, 0, 309, 0, 0, 1, 1, 0, -11884.3, -1379.01, 66.4316, 3.36848, 7200, 3, 0, 15260, 0, 1, 0, 0, 0, '', 0), -- 1 +(@GUID+33, 11371, 11372, 0, 309, 0, 0, 1, 1, 0, -11896.4, -1365.13, 69.8727, 2.42601, 7200, 3, 0, 15260, 0, 1, 0, 0, 0, '', 0), -- 2 +(@GUID+34, 11371, 11372, 0, 309, 0, 0, 1, 1, 0, -11885, -1368.42, 68.8007, 5.53269, 7200, 3, 0, 15260, 0, 1, 0, 0, 0, '', 0), -- 3 +(@GUID+35, 11371, 0, 0, 309, 0, 0, 1, 1, 0, -11878.2, -1368.68, 69.7661, 3.90954, 7200, 3, 0, 15260, 0, 1, 0, 0, 0, '', 0), -- 4 +-- @POOL+12 11371, 0, 0,@GUID+36 11372, 0, 0,@GUID+37 11371, 11372, 0,@GUID+38 11371, 11372, 0,@GUID+39 +(@GUID+36, 11371, 0, 0, 309, 0, 0, 1, 1, 0, -11884.3, -1379.01, 66.4316, 3.36848, 7200, 3, 0, 15260, 0, 1, 0, 0, 0, '', 0), -- 1 +(@GUID+37, 11372, 0, 0, 309, 0, 0, 1, 1, 0, -11896.4, -1365.13, 69.8727, 2.42601, 7200, 3, 0, 15260, 0, 1, 0, 0, 0, '', 0), -- 2 +(@GUID+38, 11371, 11372, 0, 309, 0, 0, 1, 1, 0, -11885, -1368.42, 68.8007, 5.53269, 7200, 3, 0, 15260, 0, 1, 0, 0, 0, '', 0), -- 3 +(@GUID+39, 11371, 11372, 0, 309, 0, 0, 1, 1, 0, -11878.2, -1368.68, 69.7661, 3.90954, 7200, 3, 0, 15260, 0, 1, 0, 0, 0, '', 0), -- 4 +-- @POOL+13 11371, 0, 0,@GUID+40 11371, 11372, 0,@GUID+41 11372, 0, 0,@GUID+42 11371, 11372, 0,@GUID+43 +(@GUID+40, 11371, 0, 0, 309, 0, 0, 1, 1, 0, -11884.3, -1379.01, 66.4316, 3.36848, 7200, 3, 0, 15260, 0, 1, 0, 0, 0, '', 0), -- 1 +(@GUID+41, 11371, 11372, 0, 309, 0, 0, 1, 1, 0, -11896.4, -1365.13, 69.8727, 2.42601, 7200, 3, 0, 15260, 0, 1, 0, 0, 0, '', 0), -- 2 +(@GUID+42, 11372, 0, 0, 309, 0, 0, 1, 1, 0, -11885, -1368.42, 68.8007, 5.53269, 7200, 3, 0, 15260, 0, 1, 0, 0, 0, '', 0), -- 3 +(@GUID+43, 11371, 11372, 0, 309, 0, 0, 1, 1, 0, -11878.2, -1368.68, 69.7661, 3.90954, 7200, 3, 0, 15260, 0, 1, 0, 0, 0, '', 0), -- 4 +-- @POOL+14 11371, 0, 0,@GUID+44 11371, 11372, 0,@GUID+45 11371, 11372, 0,@GUID+46 11372, 0, 0,@GUID+47 +(@GUID+44, 11371, 0, 0, 309, 0, 0, 1, 1, 0, -11884.3, -1379.01, 66.4316, 3.36848, 7200, 3, 0, 15260, 0, 1, 0, 0, 0, '', 0), -- 1 +(@GUID+45, 11371, 11372, 0, 309, 0, 0, 1, 1, 0, -11896.4, -1365.13, 69.8727, 2.42601, 7200, 3, 0, 15260, 0, 1, 0, 0, 0, '', 0), -- 2 +(@GUID+46, 11371, 11372, 0, 309, 0, 0, 1, 1, 0, -11885, -1368.42, 68.8007, 5.53269, 7200, 3, 0, 15260, 0, 1, 0, 0, 0, '', 0), -- 3 +(@GUID+47, 11372, 0, 0, 309, 0, 0, 1, 1, 0, -11878.2, -1368.68, 69.7661, 3.90954, 7200, 3, 0, 15260, 0, 1, 0, 0, 0, '', 0), -- 4 +-- @POOL+15 11371, 11372, 0,@GUID+48 11372, 0, 0,@GUID+49 11371, 0, 0,@GUID+50 11371, 11372, 0,@GUID+51 +(@GUID+48, 11371, 11372, 0, 309, 0, 0, 1, 1, 0, -11884.3, -1379.01, 66.4316, 3.36848, 7200, 3, 0, 15260, 0, 1, 0, 0, 0, '', 0), -- 1 +(@GUID+49, 11372, 0, 0, 309, 0, 0, 1, 1, 0, -11896.4, -1365.13, 69.8727, 2.42601, 7200, 3, 0, 15260, 0, 1, 0, 0, 0, '', 0), -- 2 +(@GUID+50, 11371, 0, 0, 309, 0, 0, 1, 1, 0, -11885, -1368.42, 68.8007, 5.53269, 7200, 3, 0, 15260, 0, 1, 0, 0, 0, '', 0), -- 3 +(@GUID+51, 11371, 11372, 0, 309, 0, 0, 1, 1, 0, -11878.2, -1368.68, 69.7661, 3.90954, 7200, 3, 0, 15260, 0, 1, 0, 0, 0, '', 0), -- 4 +-- @POOL+16 11371, 11372, 0,@GUID+52 11372, 0, 0,@GUID+53 11371, 11372, 0,@GUID+54 11371, 0, 0,@GUID+55 +(@GUID+52, 11371, 11372, 0, 309, 0, 0, 1, 1, 0, -11884.3, -1379.01, 66.4316, 3.36848, 7200, 3, 0, 15260, 0, 1, 0, 0, 0, '', 0), -- 1 +(@GUID+53, 11372, 0, 0, 309, 0, 0, 1, 1, 0, -11896.4, -1365.13, 69.8727, 2.42601, 7200, 3, 0, 15260, 0, 1, 0, 0, 0, '', 0), -- 2 +(@GUID+54, 11371, 11372, 0, 309, 0, 0, 1, 1, 0, -11885, -1368.42, 68.8007, 5.53269, 7200, 3, 0, 15260, 0, 1, 0, 0, 0, '', 0), -- 3 +(@GUID+55, 11371, 0, 0, 309, 0, 0, 1, 1, 0, -11878.2, -1368.68, 69.7661, 3.90954, 7200, 3, 0, 15260, 0, 1, 0, 0, 0, '', 0), -- 4 +-- @POOL+17 11371, 11372, 0,@GUID+56 11371, 0, 0,@GUID+57 11372, 0, 0,@GUID+58 11371, 11372, 0,@GUID+59 +(@GUID+56, 11371, 11372, 0, 309, 0, 0, 1, 1, 0, -11884.3, -1379.01, 66.4316, 3.36848, 7200, 3, 0, 15260, 0, 1, 0, 0, 0, '', 0), -- 1 +(@GUID+57, 11371, 0, 0, 309, 0, 0, 1, 1, 0, -11896.4, -1365.13, 69.8727, 2.42601, 7200, 3, 0, 15260, 0, 1, 0, 0, 0, '', 0), -- 2 +(@GUID+58, 11372, 0, 0, 309, 0, 0, 1, 1, 0, -11885, -1368.42, 68.8007, 5.53269, 7200, 3, 0, 15260, 0, 1, 0, 0, 0, '', 0), -- 3 +(@GUID+59, 11371, 11372, 0, 309, 0, 0, 1, 1, 0, -11878.2, -1368.68, 69.7661, 3.90954, 7200, 3, 0, 15260, 0, 1, 0, 0, 0, '', 0), -- 4 +-- @POOL+18 11371, 11372, 0,@GUID+60 11371, 0, 0,@GUID+61 11371, 11372, 0,@GUID+62 11372, 0, 0,@GUID+63 +(@GUID+60, 11371, 11372, 0, 309, 0, 0, 1, 1, 0, -11884.3, -1379.01, 66.4316, 3.36848, 7200, 3, 0, 15260, 0, 1, 0, 0, 0, '', 0), -- 1 +(@GUID+61, 11371, 0, 0, 309, 0, 0, 1, 1, 0, -11896.4, -1365.13, 69.8727, 2.42601, 7200, 3, 0, 15260, 0, 1, 0, 0, 0, '', 0), -- 2 +(@GUID+62, 11371, 11372, 0, 309, 0, 0, 1, 1, 0, -11885, -1368.42, 68.8007, 5.53269, 7200, 3, 0, 15260, 0, 1, 0, 0, 0, '', 0), -- 3 +(@GUID+63, 11372, 0, 0, 309, 0, 0, 1, 1, 0, -11878.2, -1368.68, 69.7661, 3.90954, 7200, 3, 0, 15260, 0, 1, 0, 0, 0, '', 0), -- 4 +-- @POOL+19 11371, 11372, 0,@GUID+64 11371, 11372, 0,@GUID+65 11372, 0, 0,@GUID+66 11371, 0, 0,@GUID+67 +(@GUID+64, 11371, 11372, 0, 309, 0, 0, 1, 1, 0, -11884.3, -1379.01, 66.4316, 3.36848, 7200, 3, 0, 15260, 0, 1, 0, 0, 0, '', 0), -- 1 +(@GUID+65, 11371, 11372, 0, 309, 0, 0, 1, 1, 0, -11896.4, -1365.13, 69.8727, 2.42601, 7200, 3, 0, 15260, 0, 1, 0, 0, 0, '', 0), -- 2 +(@GUID+66, 11372, 0, 0, 309, 0, 0, 1, 1, 0, -11885, -1368.42, 68.8007, 5.53269, 7200, 3, 0, 15260, 0, 1, 0, 0, 0, '', 0), -- 3 +(@GUID+67, 11371, 0, 0, 309, 0, 0, 1, 1, 0, -11878.2, -1368.68, 69.7661, 3.90954, 7200, 3, 0, 15260, 0, 1, 0, 0, 0, '', 0), -- 4 +-- @POOL+20 11371, 11372, 0,@GUID+68 11371, 11372, 0,@GUID+69 11371, 0, 0,@GUID+70 11372, 0, 0,@GUID+71 +(@GUID+68, 11371, 11372, 0, 309, 0, 0, 1, 1, 0, -11884.3, -1379.01, 66.4316, 3.36848, 7200, 3, 0, 15260, 0, 1, 0, 0, 0, '', 0), -- 1 +(@GUID+69, 11371, 11372, 0, 309, 0, 0, 1, 1, 0, -11896.4, -1365.13, 69.8727, 2.42601, 7200, 3, 0, 15260, 0, 1, 0, 0, 0, '', 0), -- 2 +(@GUID+70, 11371, 0, 0, 309, 0, 0, 1, 1, 0, -11885, -1368.42, 68.8007, 5.53269, 7200, 3, 0, 15260, 0, 1, 0, 0, 0, '', 0), -- 3 +(@GUID+71, 11372, 0, 0, 309, 0, 0, 1, 1, 0, -11878.2, -1368.68, 69.7661, 3.90954, 7200, 3, 0, 15260, 0, 1, 0, 0, 0, '', 0); -- 4 + +SET @POOL :=448; +DELETE FROM `pool_template` WHERE `entry` BETWEEN @POOL+0 AND @POOL+20; +DELETE FROM `pool_creature` WHERE `guid` BETWEEN @GUID+0 AND @GUID+71; + +INSERT INTO `pool_template` (`entry`, `max_limit`, `description`) VALUES +(@POOL+0, 1, 'ZG Entrance Snake 3-4 Pack Pool of Pools'), +(@POOL+1, 3, 'ZG Entrance Snake as 3 Pack 1/8'), +(@POOL+2, 3, 'ZG Entrance Snake as 3 Pack 2/8'), +(@POOL+3, 3, 'ZG Entrance Snake as 3 Pack 3/8'), +(@POOL+4, 3, 'ZG Entrance Snake as 3 Pack 4/8'), +(@POOL+5, 3, 'ZG Entrance Snake as 3 Pack 5/8'), +(@POOL+6, 3, 'ZG Entrance Snake as 3 Pack 6/8'), +(@POOL+7, 3, 'ZG Entrance Snake as 3 Pack 7/8'), +(@POOL+8, 3, 'ZG Entrance Snake as 3 Pack 8/8'), +(@POOL+9, 4, 'ZG Entrance Snake as 4 Pack 1/12'), +(@POOL+10, 4, 'ZG Entrance Snake as 4 Pack 2/12'), +(@POOL+11, 4, 'ZG Entrance Snake as 4 Pack 3/12'), +(@POOL+12, 4, 'ZG Entrance Snake as 4 Pack 4/12'), +(@POOL+13, 4, 'ZG Entrance Snake as 4 Pack 5/12'), +(@POOL+14, 4, 'ZG Entrance Snake as 4 Pack 6/12'), +(@POOL+15, 4, 'ZG Entrance Snake as 4 Pack 7/12'), +(@POOL+16, 4, 'ZG Entrance Snake as 4 Pack 8/12'), +(@POOL+17, 4, 'ZG Entrance Snake as 4 Pack 9/12'), +(@POOL+18, 4, 'ZG Entrance Snake as 4 Pack 10/12'), +(@POOL+19, 4, 'ZG Entrance Snake as 4 Pack 11/12'), +(@POOL+20, 4, 'ZG Entrance Snake as 4 Pack 12/12'); + +DELETE FROM `pool_pool` WHERE `pool_id` BETWEEN @POOL+0 AND @POOL+20; +DELETE FROM `pool_pool` WHERE `mother_pool` BETWEEN @POOL+0 AND @POOL+20; +INSERT INTO `pool_pool` (`pool_id`, `mother_pool`, `chance`, `description`) VALUES +(@POOL+1, @POOL+0, 6, 'ZG Entrance Snake as 3 Pack 1/8'), +(@POOL+2, @POOL+0, 6, 'ZG Entrance Snake as 3 Pack 2/8'), +(@POOL+3, @POOL+0, 6, 'ZG Entrance Snake as 3 Pack 3/8'), +(@POOL+4, @POOL+0, 7, 'ZG Entrance Snake as 3 Pack 4/8'), +(@POOL+5, @POOL+0, 6, 'ZG Entrance Snake as 3 Pack 5/8'), +(@POOL+6, @POOL+0, 6, 'ZG Entrance Snake as 3 Pack 6/8'), +(@POOL+7, @POOL+0, 6, 'ZG Entrance Snake as 3 Pack 7/8'), +(@POOL+8, @POOL+0, 7, 'ZG Entrance Snake as 3 Pack 8/8'), +(@POOL+9, @POOL+0, 5, 'ZG Entrance Snake as 4 Pack 1/12'), +(@POOL+10, @POOL+0, 4, 'ZG Entrance Snake as 4 Pack 2/12'), +(@POOL+11, @POOL+0, 4, 'ZG Entrance Snake as 4 Pack 3/12'), +(@POOL+12, @POOL+0, 4, 'ZG Entrance Snake as 4 Pack 4/12'), +(@POOL+13, @POOL+0, 4, 'ZG Entrance Snake as 4 Pack 5/12'), +(@POOL+14, @POOL+0, 5, 'ZG Entrance Snake as 4 Pack 6/12'), +(@POOL+15, @POOL+0, 4, 'ZG Entrance Snake as 4 Pack 7/12'), +(@POOL+16, @POOL+0, 4, 'ZG Entrance Snake as 4 Pack 8/12'), +(@POOL+17, @POOL+0, 4, 'ZG Entrance Snake as 4 Pack 9/12'), +(@POOL+18, @POOL+0, 4, 'ZG Entrance Snake as 4 Pack 10/12'), +(@POOL+19, @POOL+0, 4, 'ZG Entrance Snake as 4 Pack 11/12'), +(@POOL+20, @POOL+0, 4, 'ZG Entrance Snake as 4 Pack 12/12'); + +INSERT INTO `pool_creature` (`guid`, `pool_entry`, `description`) VALUES +-- @POOL+1 E1 A@GUID+0 S@GUID+1 X@GUID+2 +(@GUID+0, @POOL+1, 'ZG Entrance Snake as 3 Pack 1/8 Adder'), +(@GUID+1, @POOL+1, 'ZG Entrance Snake as 3 Pack 1/8 Serpent'), +(@GUID+2, @POOL+1, 'ZG Entrance Snake as 3 Pack 1/8 Xsnake'), +-- @POOL+2 E1 A@GUID+3 X@GUID+4 S@GUID+5 +(@GUID+3, @POOL+2, 'ZG Entrance Snake as 3 Pack 2/8 Adder'), +(@GUID+4, @POOL+2, 'ZG Entrance Snake as 3 Pack 2/8 Xsnake'), +(@GUID+5, @POOL+2, 'ZG Entrance Snake as 3 Pack 2/8 Serpent'), +-- @POOL+3 E1 S@GUID+6 A@GUID+7 X@GUID+8 +(@GUID+6, @POOL+3, 'ZG Entrance Snake as 3 Pack 3/8 Serpent'), +(@GUID+7, @POOL+3, 'ZG Entrance Snake as 3 Pack 3/8 Adder'), +(@GUID+8, @POOL+3, 'ZG Entrance Snake as 3 Pack 3/8 Xsnake'), +-- @POOL+4 E1 S@GUID+9 X@GUID+10 A@GUID+11 +(@GUID+9, @POOL+4, 'ZG Entrance Snake as 3 Pack 4/8 Serpent'), +(@GUID+10, @POOL+4, 'ZG Entrance Snake as 3 Pack 4/8 Xsnake'), +(@GUID+11, @POOL+4, 'ZG Entrance Snake as 3 Pack 4/8 Adder'), +-- @POOL+5 A@GUID+12 E2 S@GUID+13 X@GUID+14 +(@GUID+12, @POOL+5, 'ZG Entrance Snake as 3 Pack 5/8 Adder'), +(@GUID+13, @POOL+5, 'ZG Entrance Snake as 3 Pack 5/8 Serpent'), +(@GUID+14, @POOL+5, 'ZG Entrance Snake as 3 Pack 5/8 Xsnake'), +-- @POOL+6 A@GUID+15 E2 X@GUID+16 S@GUID+17 +(@GUID+15, @POOL+6, 'ZG Entrance Snake as 3 Pack 6/8 Adder'), +(@GUID+16, @POOL+6, 'ZG Entrance Snake as 3 Pack 6/8 Xsnake'), +(@GUID+17, @POOL+6, 'ZG Entrance Snake as 3 Pack 6/8 Serpent'), +-- @POOL+7 S@GUID+18 E2 A@GUID+19 X@GUID+20 +(@GUID+18, @POOL+7, 'ZG Entrance Snake as 3 Pack 7/8 Serpent'), +(@GUID+19, @POOL+7, 'ZG Entrance Snake as 3 Pack 7/8 Adder'), +(@GUID+20, @POOL+7, 'ZG Entrance Snake as 3 Pack 7/8 Xsnake'), +-- @POOL+8 S@GUID+21 E2 X@GUID+22 A@GUID+23 +(@GUID+21, @POOL+8, 'ZG Entrance Snake as 3 Pack 8/8 Serpent'), +(@GUID+22, @POOL+8, 'ZG Entrance Snake as 3 Pack 8/8 Xsnake'), +(@GUID+23, @POOL+8, 'ZG Entrance Snake as 3 Pack 8/8 Adder'), +-- @POOL+9 A@GUID+24 S@GUID+25 X@GUID+26 X@GUID+27 +(@GUID+24, @POOL+9, 'ZG Entrance Snake as 4 Pack 1/12 Adder'), +(@GUID+25, @POOL+9, 'ZG Entrance Snake as 4 Pack 1/12 Serpent'), +(@GUID+26, @POOL+9, 'ZG Entrance Snake as 4 Pack 1/12 Xsnake'), +(@GUID+27, @POOL+9, 'ZG Entrance Snake as 4 Pack 1/12 Xsnake'), +-- @POOL+10 A@GUID+28 X@GUID+29 S@GUID+30 X@GUID+31 +(@GUID+28, @POOL+10, 'ZG Entrance Snake as 4 Pack 2/12 Adder'), +(@GUID+29, @POOL+10, 'ZG Entrance Snake as 4 Pack 2/12 Xsnake'), +(@GUID+30, @POOL+10, 'ZG Entrance Snake as 4 Pack 2/12 Serpent'), +(@GUID+31, @POOL+10, 'ZG Entrance Snake as 4 Pack 2/12 Xsnake'), +-- @POOL+11 A@GUID+32 X@GUID+33 X@GUID+34 S@GUID+35 +(@GUID+32, @POOL+11, 'ZG Entrance Snake as 4 Pack 3/12 Adder'), +(@GUID+33, @POOL+11, 'ZG Entrance Snake as 4 Pack 3/12 Xsnake'), +(@GUID+34, @POOL+11, 'ZG Entrance Snake as 4 Pack 3/12 Xsnake'), +(@GUID+35, @POOL+11, 'ZG Entrance Snake as 4 Pack 3/12 Serpent'), +-- @POOL+12 S@GUID+36 A@GUID+37 X@GUID+38 X@GUID+39 +(@GUID+36, @POOL+12, 'ZG Entrance Snake as 4 Pack 4/12 Serpent'), +(@GUID+37, @POOL+12, 'ZG Entrance Snake as 4 Pack 4/12 Adder'), +(@GUID+38, @POOL+12, 'ZG Entrance Snake as 4 Pack 4/12 Xsnake'), +(@GUID+39, @POOL+12, 'ZG Entrance Snake as 4 Pack 4/12 Xsnake'), +-- @POOL+13 S@GUID+40 X@GUID+41 A@GUID+42 X@GUID+43 +(@GUID+40, @POOL+13, 'ZG Entrance Snake as 4 Pack 5/12 Serpent'), +(@GUID+41, @POOL+13, 'ZG Entrance Snake as 4 Pack 5/12 Xsnake'), +(@GUID+42, @POOL+13, 'ZG Entrance Snake as 4 Pack 5/12 Adder'), +(@GUID+43, @POOL+13, 'ZG Entrance Snake as 4 Pack 5/12 Xsnake'), +-- @POOL+14 S@GUID+44 X@GUID+45 X@GUID+46 A@GUID+47 +(@GUID+44, @POOL+14, 'ZG Entrance Snake as 4 Pack 6/12 Serpent'), +(@GUID+45, @POOL+14, 'ZG Entrance Snake as 4 Pack 6/12 Xsnake'), +(@GUID+46, @POOL+14, 'ZG Entrance Snake as 4 Pack 6/12 Xsnake'), +(@GUID+47, @POOL+14, 'ZG Entrance Snake as 4 Pack 6/12 Adder'), +-- @POOL+15 X@GUID+48 A@GUID+49 S@GUID+50 X@GUID+51 +(@GUID+48, @POOL+15, 'ZG Entrance Snake as 4 Pack 7/12 Xsnake'), +(@GUID+49, @POOL+15, 'ZG Entrance Snake as 4 Pack 7/12 Adder'), +(@GUID+50, @POOL+15, 'ZG Entrance Snake as 4 Pack 7/12 Serpent'), +(@GUID+51, @POOL+15, 'ZG Entrance Snake as 4 Pack 7/12 Xsnake'), +-- @POOL+16 X@GUID+52 A@GUID+53 X@GUID+54 S@GUID+55 +(@GUID+52, @POOL+16, 'ZG Entrance Snake as 4 Pack 8/12 Xsnake'), +(@GUID+53, @POOL+16, 'ZG Entrance Snake as 4 Pack 8/12 Adder'), +(@GUID+54, @POOL+16, 'ZG Entrance Snake as 4 Pack 8/12 Xsnake'), +(@GUID+55, @POOL+16, 'ZG Entrance Snake as 4 Pack 8/12 Serpent'), +-- @POOL+17 X@GUID+56 S@GUID+57 A@GUID+58 X@GUID+59 +(@GUID+56, @POOL+17, 'ZG Entrance Snake as 4 Pack 9/12 Xsnake'), +(@GUID+57, @POOL+17, 'ZG Entrance Snake as 4 Pack 9/12 Serpent'), +(@GUID+58, @POOL+17, 'ZG Entrance Snake as 4 Pack 9/12 Adder'), +(@GUID+59, @POOL+17, 'ZG Entrance Snake as 4 Pack 9/12 Xsnake'), +-- @POOL+18 X@GUID+60 S@GUID+61 X@GUID+62 A@GUID+63 +(@GUID+60, @POOL+18, 'ZG Entrance Snake as 4 Pack 10/12 Xsnake'), +(@GUID+61, @POOL+18, 'ZG Entrance Snake as 4 Pack 10/12 Serpent'), +(@GUID+62, @POOL+18, 'ZG Entrance Snake as 4 Pack 10/12 Xsnake'), +(@GUID+63, @POOL+18, 'ZG Entrance Snake as 4 Pack 10/12 Adder'), +-- @POOL+19 X@GUID+64 X@GUID+65 A@GUID+66 S@GUID+67 +(@GUID+64, @POOL+19, 'ZG Entrance Snake as 4 Pack 11/12 Xsnake'), +(@GUID+65, @POOL+19, 'ZG Entrance Snake as 4 Pack 11/12 Xsnake'), +(@GUID+66, @POOL+19, 'ZG Entrance Snake as 4 Pack 11/12 Adder'), +(@GUID+67, @POOL+19, 'ZG Entrance Snake as 4 Pack 11/12 Serpent'), +-- @POOL+20 X@GUID+68 X@GUID+69 S@GUID+70 A@GUID+71 +(@GUID+68, @POOL+20, 'ZG Entrance Snake as 4 Pack 12/12 Xsnake'), +(@GUID+69, @POOL+20, 'ZG Entrance Snake as 4 Pack 12/12 Xsnake'), +(@GUID+70, @POOL+20, 'ZG Entrance Snake as 4 Pack 12/12 Serpent'), +(@GUID+71, @POOL+20, 'ZG Entrance Snake as 4 Pack 12/12 Adder'); From 206497cb26e4438cacccffb1e193f426e215b716 Mon Sep 17 00:00:00 2001 From: AzerothCoreBot Date: Tue, 19 Jul 2022 22:26:59 +0000 Subject: [PATCH 020/130] chore(DB): import pending files Referenced commit(s): dc3025249ce5099d9f7eb8bbebb030e72a6c64d2 --- .../rev_1657669676037619800.sql => db_world/2022_07_19_04.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/rev_1657669676037619800.sql => db_world/2022_07_19_04.sql} (99%) diff --git a/data/sql/updates/pending_db_world/rev_1657669676037619800.sql b/data/sql/updates/db_world/2022_07_19_04.sql similarity index 99% rename from data/sql/updates/pending_db_world/rev_1657669676037619800.sql rename to data/sql/updates/db_world/2022_07_19_04.sql index dd280d96f..89f553a4f 100644 --- a/data/sql/updates/pending_db_world/rev_1657669676037619800.sql +++ b/data/sql/updates/db_world/2022_07_19_04.sql @@ -1,3 +1,4 @@ +-- DB update 2022_07_19_03 -> 2022_07_19_04 -- /* Maintenance on ZG Entranceway mobs part 2 Pooling */ DELETE FROM `creature` WHERE `guid` IN (49116, 49117, 49118, 49119); From e3754ede1f94f8ee05149b2dff8c99ea2855fe9f Mon Sep 17 00:00:00 2001 From: Gultask <100873791+Gultask@users.noreply.github.com> Date: Tue, 19 Jul 2022 23:43:11 -0300 Subject: [PATCH 021/130] fix(DB/Pathing): Add missing waypoints to Somnus (12900) (#12321) --- .../pending_db_world/somnus_waypoints.sql | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 data/sql/updates/pending_db_world/somnus_waypoints.sql diff --git a/data/sql/updates/pending_db_world/somnus_waypoints.sql b/data/sql/updates/pending_db_world/somnus_waypoints.sql new file mode 100644 index 000000000..d9307ec2e --- /dev/null +++ b/data/sql/updates/pending_db_world/somnus_waypoints.sql @@ -0,0 +1,53 @@ +-- +SET @NPC := 42880; +SET @PATH := @NPC * 10; + +UPDATE `creature` SET `position_x`=-10661, `position_y`=-3924.57, `position_z`=18.8015, `orientation`=5.83672, `MovementType`='2' WHERE `guid`=@NPC; + +DELETE FROM `creature_addon` WHERE `guid` = @NPC; +INSERT INTO `creature_addon` (`guid`, `path_id`) VALUES (@NPC, @PATH); + +DELETE FROM `waypoint_data` WHERE `id` = @PATH; +INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`) VALUES +(@PATH, 1, -10641.5, -3982.49, 19.943), +(@PATH, 2, -10591, -3982.21, 21.4646), +(@PATH, 3, -10574.5, -3995.66, 18.5265), +(@PATH, 4, -10556.4, -4008.31, 19.5063), +(@PATH, 5, -10541.2, -4012.2, 22.3642), +(@PATH, 6, -10510.2, -4016.9, 18.3724), +(@PATH, 7, -10482.4, -4010.78, 18.9192), +(@PATH, 8, -10475.6, -4003.55, 19.5199), +(@PATH, 9, -10460.1, -3998.53, 18.5604), +(@PATH, 10, -10434, -4005, 18.5093), +(@PATH, 11, -10408.6, -4010.32, 18.2372), +(@PATH, 12, -10387.1, -3999.93, 19.7943), +(@PATH, 13, -10363.4, -3997.07, 19.3136), +(@PATH, 14, -10343.3, -4003.71, 20.5207), +(@PATH, 15, -10328.6, -4013.14, 18.4205), +(@PATH, 16, -10335.8, -4029.01, 19.4894), +(@PATH, 17, -10325.5, -4054.12, 19.7849), +(@PATH, 18, -10315.2, -4078.22, 22.4922), +(@PATH, 19, -10296, -4123.39, 23.2141), +(@PATH, 20, -10301, -4143.57, 19.8863), +(@PATH, 21, -10322.1, -4159.15, 18.3385), +(@PATH, 22, -10357.8, -4178.26, 20.1807), +(@PATH, 23, -10379.9, -4192.31, 22.7909), +(@PATH, 24, -10419, -4192.8, 19.1422), +(@PATH, 25, -10441.2, -4184.96, 18.6967), +(@PATH, 26, -10480, -4193.1, 18.9901), +(@PATH, 27, -10495, -4205.67, 19.6285), +(@PATH, 28, -10511.9, -4209.93, 19.0212), +(@PATH, 29, -10547.4, -4199.08, 18.7961), +(@PATH, 30, -10564.6, -4187.57, 19.3169), +(@PATH, 31, -10581, -4203.9, 20.3609), +(@PATH, 32, -10594, -4205.64, 21.6639), +(@PATH, 33, -10620.6, -4211.36, 23.3686), +(@PATH, 34, -10673.5, -4191.09, 22.867), +(@PATH, 35, -10710.4, -4172.44, 21.8668), +(@PATH, 36, -10723.1, -4139.99, 18.6405), +(@PATH, 37, -10745.3, -4114.88, 19.7025), +(@PATH, 38, -10749.3, -4070.5, 20.6484), +(@PATH, 39, -10756.1, -4048.57, 22.868), +(@PATH, 40, -10742.5, -4002.81, 20.3069), +(@PATH, 41, -10701.2, -3956.85, 23.3119), +(@PATH, 42, -10662.1, -3926.38, 19.4344); From fe635c0f662fdff81dc42021c439746e31ee3d13 Mon Sep 17 00:00:00 2001 From: AzerothCoreBot Date: Wed, 20 Jul 2022 02:45:46 +0000 Subject: [PATCH 022/130] chore(DB): import pending files Referenced commit(s): e3754ede1f94f8ee05149b2dff8c99ea2855fe9f --- .../somnus_waypoints.sql => db_world/2022_07_20_00.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/somnus_waypoints.sql => db_world/2022_07_20_00.sql} (98%) diff --git a/data/sql/updates/pending_db_world/somnus_waypoints.sql b/data/sql/updates/db_world/2022_07_20_00.sql similarity index 98% rename from data/sql/updates/pending_db_world/somnus_waypoints.sql rename to data/sql/updates/db_world/2022_07_20_00.sql index d9307ec2e..d7d767069 100644 --- a/data/sql/updates/pending_db_world/somnus_waypoints.sql +++ b/data/sql/updates/db_world/2022_07_20_00.sql @@ -1,3 +1,4 @@ +-- DB update 2022_07_19_04 -> 2022_07_20_00 -- SET @NPC := 42880; SET @PATH := @NPC * 10; From c705475d25692f70d32da07e19edc428f1e8e50c Mon Sep 17 00:00:00 2001 From: schell244 Date: Wed, 20 Jul 2022 04:47:28 +0200 Subject: [PATCH 023/130] fix(DB/Event): Shadowfang Keep: link objects and npcs to event (#12404) --- .../rev_1657989497144859400.sql | 226 ++++++++++++++++++ 1 file changed, 226 insertions(+) create mode 100644 data/sql/updates/pending_db_world/rev_1657989497144859400.sql diff --git a/data/sql/updates/pending_db_world/rev_1657989497144859400.sql b/data/sql/updates/pending_db_world/rev_1657989497144859400.sql new file mode 100644 index 000000000..2f0f8dade --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1657989497144859400.sql @@ -0,0 +1,226 @@ +-- +SET @EVENT := 8; + +DELETE FROM `game_event_creature` WHERE `eventEntry` = @EVENT AND `guid` IN +(146602, + 146609, + 146618, + 146619, + 146621); + +INSERT INTO `game_event_creature` (`eventEntry`, `guid`) VALUES +(@EVENT, 146602), +(@EVENT, 146609), +(@EVENT, 146618), +(@EVENT, 146619), +(@EVENT, 146621); + +DELETE FROM `game_event_gameobject` WHERE `eventEntry` = @EVENT AND `guid` IN +(9780, + 9754, + 9782, + 9751, + 9766, + 9756, + 9747, + 9749, + 9809, + 9774, + 9746, + 9748, + 9802, + 9808, + 9752, + 9760, + 9792, + 9762, + 9778, + 9757, + 9770, + 9793, + 9758, + 9769, + 9830, + 9828, + 9761, + 9779, + 9791, + 9773, + 9768, + 9833, + 9759, + 9800, + 9804, + 9801, + 9787, + 9783, + 9798, + 9772, + 9794, + 9781, + 9790, + 9795, + 9813, + 9753, + 9811, + 9805, + 9785, + 9807, + 9797, + 9799, + 9810, + 9784, + 9771, + 9796, + 9743, + 9803, + 9786, + 9777, + 9767, + 9765, + 9789, + 9763, + 242252, + 242257, + 242259, + 242267, + 242253, + 242254, + 242275, + 242274, + 242273, + 242271, + 242263, + 242272, + 242276, + 242270, + 242265, + 242255, + 242306, + 242307, + 242302, + 242301, + 242304, + 242303, + 242300, + 242299, + 242305, + 242266, + 242264, + 242282, + 242258, + 242261, + 242284, + 242283, + 242256, + 242260, + 242278, + 242277, + 242279, + 242280, + 242281); + +INSERT INTO `game_event_gameobject` (`eventEntry`, `guid`) VALUES +(@EVENT, 9780), +(@EVENT, 9754), +(@EVENT, 9782), +(@EVENT, 9751), +(@EVENT, 9766), +(@EVENT, 9756), +(@EVENT, 9747), +(@EVENT, 9749), +(@EVENT, 9809), +(@EVENT, 9774), +(@EVENT, 9746), +(@EVENT, 9748), +(@EVENT, 9802), +(@EVENT, 9808), +(@EVENT, 9752), +(@EVENT, 9760), +(@EVENT, 9792), +(@EVENT, 9762), +(@EVENT, 9778), +(@EVENT, 9757), +(@EVENT, 9770), +(@EVENT, 9793), +(@EVENT, 9758), +(@EVENT, 9769), +(@EVENT, 9830), +(@EVENT, 9828), +(@EVENT, 9761), +(@EVENT, 9779), +(@EVENT, 9791), +(@EVENT, 9773), +(@EVENT, 9768), +(@EVENT, 9833), +(@EVENT, 9759), +(@EVENT, 9800), +(@EVENT, 9804), +(@EVENT, 9801), +(@EVENT, 9787), +(@EVENT, 9783), +(@EVENT, 9798), +(@EVENT, 9772), +(@EVENT, 9794), +(@EVENT, 9781), +(@EVENT, 9790), +(@EVENT, 9795), +(@EVENT, 9813), +(@EVENT, 9753), +(@EVENT, 9811), +(@EVENT, 9805), +(@EVENT, 9785), +(@EVENT, 9807), +(@EVENT, 9797), +(@EVENT, 9799), +(@EVENT, 9810), +(@EVENT, 9784), +(@EVENT, 9771), +(@EVENT, 9796), +(@EVENT, 9743), +(@EVENT, 9803), +(@EVENT, 9786), +(@EVENT, 9777), +(@EVENT, 9767), +(@EVENT, 9765), +(@EVENT, 9789), +(@EVENT, 9763), +(@EVENT, 242252), +(@EVENT, 242257), +(@EVENT, 242259), +(@EVENT, 242267), +(@EVENT, 242253), +(@EVENT, 242254), +(@EVENT, 242275), +(@EVENT, 242274), +(@EVENT, 242273), +(@EVENT, 242271), +(@EVENT, 242263), +(@EVENT, 242272), +(@EVENT, 242276), +(@EVENT, 242270), +(@EVENT, 242265), +(@EVENT, 242255), +(@EVENT, 242306), +(@EVENT, 242307), +(@EVENT, 242302), +(@EVENT, 242301), +(@EVENT, 242304), +(@EVENT, 242303), +(@EVENT, 242300), +(@EVENT, 242299), +(@EVENT, 242305), +(@EVENT, 242266), +(@EVENT, 242264), +(@EVENT, 242282), +(@EVENT, 242258), +(@EVENT, 242261), +(@EVENT, 242284), +(@EVENT, 242283), +(@EVENT, 242256), +(@EVENT, 242260), +(@EVENT, 242278), +(@EVENT, 242277), +(@EVENT, 242279), +(@EVENT, 242280), +(@EVENT, 242281); From dd2b08e8cfbfa57bea36783137735653df163946 Mon Sep 17 00:00:00 2001 From: AzerothCoreBot Date: Wed, 20 Jul 2022 02:49:26 +0000 Subject: [PATCH 024/130] chore(DB): import pending files Referenced commit(s): c705475d25692f70d32da07e19edc428f1e8e50c --- .../rev_1657989497144859400.sql => db_world/2022_07_20_01.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/rev_1657989497144859400.sql => db_world/2022_07_20_01.sql} (98%) diff --git a/data/sql/updates/pending_db_world/rev_1657989497144859400.sql b/data/sql/updates/db_world/2022_07_20_01.sql similarity index 98% rename from data/sql/updates/pending_db_world/rev_1657989497144859400.sql rename to data/sql/updates/db_world/2022_07_20_01.sql index 2f0f8dade..03e742122 100644 --- a/data/sql/updates/pending_db_world/rev_1657989497144859400.sql +++ b/data/sql/updates/db_world/2022_07_20_01.sql @@ -1,3 +1,4 @@ +-- DB update 2022_07_20_00 -> 2022_07_20_01 -- SET @EVENT := 8; From 37cc3ffa70f80e3f6297ceb7f6890152766ca42f Mon Sep 17 00:00:00 2001 From: Gultask <100873791+Gultask@users.noreply.github.com> Date: Tue, 19 Jul 2022 23:51:17 -0300 Subject: [PATCH 025/130] fix(DB/Creature): Rocklance waypoints and formation. (#12322) --- .../updates/pending_db_world/rocklance.sql | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 data/sql/updates/pending_db_world/rocklance.sql diff --git a/data/sql/updates/pending_db_world/rocklance.sql b/data/sql/updates/pending_db_world/rocklance.sql new file mode 100644 index 000000000..c87add070 --- /dev/null +++ b/data/sql/updates/pending_db_world/rocklance.sql @@ -0,0 +1,56 @@ +-- Rocklance +SET @NPC := 20720; +SET @PATH := @NPC * 10; + +UPDATE `creature` SET `position_x`=-1199.35, `position_y`=-3100.46, `position_z`=94.7484, `orientation`=2.7918, `MovementType`='2' WHERE `guid`=@NPC; + +DELETE FROM `creature_addon` WHERE `guid` = @NPC; +INSERT INTO `creature_addon` (`guid`, `path_id`) VALUES (@NPC, @PATH); + +DELETE FROM `waypoint_data` WHERE `id` = @PATH; +INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`) VALUES +(@PATH, 1, -1201.63, -3099.24, 94.8781), +(@PATH, 2, -1219.21, -3099.76, 95.241), +(@PATH, 3, -1272.76, -3089.53, 93.8928), +(@PATH, 4, -1315.08, -3106.5, 91.7995), +(@PATH, 5, -1330.48, -3095.55, 92.4438), +(@PATH, 6, -1341.49, -3060.61, 92.6899), +(@PATH, 7, -1354.4, -3030.3, 93.3309), +(@PATH, 8, -1386.31, -3005.86, 93.1475), +(@PATH, 9, -1430.19, -2974.08, 93.1218), +(@PATH, 10, -1436.49, -2943.46, 91.668), +(@PATH, 11, -1436.75, -2920.35, 92.5429), +(@PATH, 12, -1410.03, -2893.52, 93.1282), +(@PATH, 13, -1388.5, -2866.72, 94.5754), +(@PATH, 14, -1360.27, -2850.79, 94.705), +(@PATH, 15, -1332.8, -2857.77, 93.5965), +(@PATH, 16, -1288.33, -2870.37, 93.0108), +(@PATH, 17, -1265.32, -2850.79, 94.069), +(@PATH, 18, -1239.87, -2834.24, 94.41), +(@PATH, 19, -1219.09, -2834.03, 93.9937), +(@PATH, 20, -1194.71, -2865.09, 93.5771), +(@PATH, 21, -1170.2, -2886.21, 94.3522), +(@PATH, 22, -1146.43, -2925.68, 93.1956), +(@PATH, 23, -1123.57, -2957.35, 92.8819), +(@PATH, 24, -1114.24, -2966.51, 92.4826), +(@PATH, 25, -1111.46, -3018.12, 94.8292), +(@PATH, 26, -1101.72, -3047.27, 93.4784), +(@PATH, 27, -1123.65, -3070.33, 91.8408), +(@PATH, 28, -1147.38, -3076.85, 92.3126), +(@PATH, 29, -1177.95, -3082.89, 92.8266); + +DELETE FROM `creature_formations` WHERE `leaderGUID` = @NPC; +INSERT INTO `creature_formations` (`leaderGUID`, `memberGUID`, `dist`, `angle`, `groupAI`) VALUES (@NPC, @NPC, 0, 0, 512); +INSERT INTO `creature_formations` (`leaderGUID`, `memberGUID`, `dist`, `angle`, `groupAI`) VALUES (@NPC, 20588, 3, 215, 512); +INSERT INTO `creature_formations` (`leaderGUID`, `memberGUID`, `dist`, `angle`, `groupAI`) VALUES (@NPC, 14007, 3, 135, 512); + +UPDATE `creature` SET `spawntimesecs`=25000 WHERE `guid`=14007; +UPDATE `creature` SET `spawntimesecs`=25000 WHERE `guid`=20588; +UPDATE `creature` SET `spawntimesecs`=19800 WHERE `guid`=@NPC; + +UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 5841; + +DELETE FROM `smart_scripts` WHERE (`entryorguid` = 5841) AND (`source_type` = 0) AND (`id` IN (3, 4)); +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(5841, 0, 3, 0, 11, 0, 100, 0, 0, 0, 0, 0, 0, 70, 500, 0, 0, 0, 0, 0, 10, 14007, 0, 0, 0, 0, 0, 0, 0, 'Rocklance - On Respawn - Respawn Formation Member 14007'), +(5841, 0, 4, 0, 11, 0, 100, 0, 0, 0, 0, 0, 0, 70, 500, 0, 0, 0, 0, 0, 10, 20588, 0, 0, 0, 0, 0, 0, 0, 'Rocklance - On Respawn - Respawn Formation Member 20588'); From 9a2a6992ff236ba4f471f457337373c906d82b7b Mon Sep 17 00:00:00 2001 From: AzerothCoreBot Date: Wed, 20 Jul 2022 02:53:15 +0000 Subject: [PATCH 026/130] chore(DB): import pending files Referenced commit(s): 37cc3ffa70f80e3f6297ceb7f6890152766ca42f --- .../rocklance.sql => db_world/2022_07_20_02.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/rocklance.sql => db_world/2022_07_20_02.sql} (98%) diff --git a/data/sql/updates/pending_db_world/rocklance.sql b/data/sql/updates/db_world/2022_07_20_02.sql similarity index 98% rename from data/sql/updates/pending_db_world/rocklance.sql rename to data/sql/updates/db_world/2022_07_20_02.sql index c87add070..e21a1e744 100644 --- a/data/sql/updates/pending_db_world/rocklance.sql +++ b/data/sql/updates/db_world/2022_07_20_02.sql @@ -1,3 +1,4 @@ +-- DB update 2022_07_20_01 -> 2022_07_20_02 -- Rocklance SET @NPC := 20720; SET @PATH := @NPC * 10; From b7353ce9b297d644afb59e24ad3d1e29a99c96d3 Mon Sep 17 00:00:00 2001 From: neifion-00000000 <91289495+neifion-00000000@users.noreply.github.com> Date: Tue, 19 Jul 2022 23:04:23 -0500 Subject: [PATCH 027/130] feat(Core/Commands): Introduce .npc guid (#12440) --- .../rev_1658266226251855400.sql | 3 ++ src/server/scripts/Commands/cs_npc.cpp | 31 +++++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 data/sql/updates/pending_db_world/rev_1658266226251855400.sql diff --git a/data/sql/updates/pending_db_world/rev_1658266226251855400.sql b/data/sql/updates/pending_db_world/rev_1658266226251855400.sql new file mode 100644 index 000000000..cb1b6a970 --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1658266226251855400.sql @@ -0,0 +1,3 @@ +-- +DELETE FROM `command` WHERE `name` = 'npc guid'; +INSERT INTO `command` (`name`, `security`, `help`) VALUES ('npc guid', 1, 'Syntax: .npc guid\r\n\r\nDisplays GUID, faction, NPC flags, Entry ID, Model ID for selected creature.'); diff --git a/src/server/scripts/Commands/cs_npc.cpp b/src/server/scripts/Commands/cs_npc.cpp index d722a5478..83c5fbeb0 100644 --- a/src/server/scripts/Commands/cs_npc.cpp +++ b/src/server/scripts/Commands/cs_npc.cpp @@ -186,6 +186,7 @@ public: static ChatCommandTable npcCommandTable = { { "info", HandleNpcInfoCommand, SEC_GAMEMASTER, Console::No }, + { "guid", HandleNpcGuidCommand, SEC_GAMEMASTER, Console::No }, { "near", HandleNpcNearCommand, SEC_GAMEMASTER, Console::No }, { "move", HandleNpcMoveCommand, SEC_GAMEMASTER, Console::No }, { "playemote", HandleNpcPlayEmoteCommand, SEC_GAMEMASTER, Console::No }, @@ -651,6 +652,36 @@ public: return true; } + static bool HandleNpcGuidCommand(ChatHandler* handler) + { + Creature* target = handler->getSelectedCreature(); + + if (!target) + { + handler->SendSysMessage(LANG_SELECT_CREATURE); + handler->SetSentErrorMessage(true); + return false; + } + + uint32 faction = target->GetFaction(); + uint32 npcflags = target->GetNpcFlags(); + uint32 displayid = target->GetDisplayId(); + uint32 nativeid = target->GetNativeDisplayId(); + uint32 entry = target->GetEntry(); + uint32 id1 = 0; + uint32 id2 = 0; + uint32 id3 = 0; + if (CreatureData const* cData = target->GetCreatureData()) + { + id1 = cData->id1; + id2 = cData->id2; + id3 = cData->id3; + } + + handler->PSendSysMessage(LANG_NPCINFO_CHAR, target->GetSpawnId(), target->GetGUID().GetCounter(), entry, id1, id2, id3, displayid, nativeid, faction, npcflags); + + return true; + } static bool HandleNpcNearCommand(ChatHandler* handler, Optional dist) { From 93f4aaa999345f7a8e1764163b4b70690d8d48c5 Mon Sep 17 00:00:00 2001 From: AzerothCoreBot Date: Wed, 20 Jul 2022 04:06:21 +0000 Subject: [PATCH 028/130] chore(DB): import pending files Referenced commit(s): b7353ce9b297d644afb59e24ad3d1e29a99c96d3 --- .../rev_1658266226251855400.sql => db_world/2022_07_20_03.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/rev_1658266226251855400.sql => db_world/2022_07_20_03.sql} (84%) diff --git a/data/sql/updates/pending_db_world/rev_1658266226251855400.sql b/data/sql/updates/db_world/2022_07_20_03.sql similarity index 84% rename from data/sql/updates/pending_db_world/rev_1658266226251855400.sql rename to data/sql/updates/db_world/2022_07_20_03.sql index cb1b6a970..9f7d1d737 100644 --- a/data/sql/updates/pending_db_world/rev_1658266226251855400.sql +++ b/data/sql/updates/db_world/2022_07_20_03.sql @@ -1,3 +1,4 @@ +-- DB update 2022_07_20_02 -> 2022_07_20_03 -- DELETE FROM `command` WHERE `name` = 'npc guid'; INSERT INTO `command` (`name`, `security`, `help`) VALUES ('npc guid', 1, 'Syntax: .npc guid\r\n\r\nDisplays GUID, faction, NPC flags, Entry ID, Model ID for selected creature.'); From 6cef730514710fef96f2eb51361cc051ced9c6c4 Mon Sep 17 00:00:00 2001 From: temperrr Date: Wed, 20 Jul 2022 15:23:24 +0200 Subject: [PATCH 029/130] fix(DB/SAI): Cauldron Lord Razarch smartscripts (#12453) --- data/sql/updates/pending_db_world/cauldronlordrazarch.sql | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 data/sql/updates/pending_db_world/cauldronlordrazarch.sql diff --git a/data/sql/updates/pending_db_world/cauldronlordrazarch.sql b/data/sql/updates/pending_db_world/cauldronlordrazarch.sql new file mode 100644 index 000000000..d25235bc5 --- /dev/null +++ b/data/sql/updates/pending_db_world/cauldronlordrazarch.sql @@ -0,0 +1,8 @@ +UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 11076; + +DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 11076); +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(11076, 0, 0, 0, 0, 0, 100, 0, 0, 0, 3400, 4800, 0, 11, 12471, 64, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Cauldron Lord Razarch - In Combat - Cast \'Shadow Bolt\''), +(11076, 0, 1, 0, 0, 0, 100, 0, 11000, 15000, 20000, 25000, 0, 11, 17204, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Cauldron Lord Razarch - In Combat - Cast \'Summon Skeleton\''), +(11076, 0, 2, 0, 2, 0, 100, 0, 0, 50, 14000, 18000, 0, 11, 17173, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Cauldron Lord Razarch - Between 0-50% Health - Cast \'Drain Life\''), +(11076, 0, 3, 0, 4, 0, 100, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'Cauldron Lord Razarch - On Aggro - Say Line 0'); From 15eb6386aa86766d853bd706d4fb6a6323bf930a Mon Sep 17 00:00:00 2001 From: temperrr Date: Wed, 20 Jul 2022 15:25:15 +0200 Subject: [PATCH 030/130] =?UTF-8?q?fix(DB/SAI):=20Skeletal=20terror=20shou?= =?UTF-8?q?ld=20not=20cast=20Altered=20C=E2=80=A6=20(#12451)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fix(SmartScripts/Creature): Skeletal terror should not cast Altered Cauldron Toxin. --- data/sql/updates/pending_db_world/skeletalterror.sql | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 data/sql/updates/pending_db_world/skeletalterror.sql diff --git a/data/sql/updates/pending_db_world/skeletalterror.sql b/data/sql/updates/pending_db_world/skeletalterror.sql new file mode 100644 index 000000000..88dec0b90 --- /dev/null +++ b/data/sql/updates/pending_db_world/skeletalterror.sql @@ -0,0 +1,5 @@ +UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 1785; + +DELETE FROM `smart_scripts` WHERE (`entryorguid` = 1785) AND (`source_type` = 0) AND (`id` IN (0, 1)); +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(1785, 0, 0, 0, 2, 0, 100, 1, 5, 30, 0, 0, 0, 11, 12542, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Skeletal Terror - Between 5-30% Health - Cast \'Fear\' (No Repeat)'); From 44183bc376c1d25c01df46426d618ec9a6a39cae Mon Sep 17 00:00:00 2001 From: AzerothCoreBot Date: Wed, 20 Jul 2022 13:27:28 +0000 Subject: [PATCH 031/130] chore(DB): import pending files Referenced commit(s): 15eb6386aa86766d853bd706d4fb6a6323bf930a --- .../cauldronlordrazarch.sql => db_world/2022_07_20_04.sql} | 1 + .../skeletalterror.sql => db_world/2022_07_20_05.sql} | 1 + 2 files changed, 2 insertions(+) rename data/sql/updates/{pending_db_world/cauldronlordrazarch.sql => db_world/2022_07_20_04.sql} (96%) rename data/sql/updates/{pending_db_world/skeletalterror.sql => db_world/2022_07_20_05.sql} (94%) diff --git a/data/sql/updates/pending_db_world/cauldronlordrazarch.sql b/data/sql/updates/db_world/2022_07_20_04.sql similarity index 96% rename from data/sql/updates/pending_db_world/cauldronlordrazarch.sql rename to data/sql/updates/db_world/2022_07_20_04.sql index d25235bc5..06edb512f 100644 --- a/data/sql/updates/pending_db_world/cauldronlordrazarch.sql +++ b/data/sql/updates/db_world/2022_07_20_04.sql @@ -1,3 +1,4 @@ +-- DB update 2022_07_20_03 -> 2022_07_20_04 UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 11076; DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 11076); diff --git a/data/sql/updates/pending_db_world/skeletalterror.sql b/data/sql/updates/db_world/2022_07_20_05.sql similarity index 94% rename from data/sql/updates/pending_db_world/skeletalterror.sql rename to data/sql/updates/db_world/2022_07_20_05.sql index 88dec0b90..fa2a74941 100644 --- a/data/sql/updates/pending_db_world/skeletalterror.sql +++ b/data/sql/updates/db_world/2022_07_20_05.sql @@ -1,3 +1,4 @@ +-- DB update 2022_07_20_04 -> 2022_07_20_05 UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 1785; DELETE FROM `smart_scripts` WHERE (`entryorguid` = 1785) AND (`source_type` = 0) AND (`id` IN (0, 1)); From 153871e918aefc35919b3443ddca777d78345824 Mon Sep 17 00:00:00 2001 From: UltraNix <80540499+UltraNix@users.noreply.github.com> Date: Wed, 20 Jul 2022 15:31:43 +0200 Subject: [PATCH 032/130] fix(DB/Quest): Boiling Point. (#12407) Fixes #10313 --- data/sql/updates/pending_db_world/rev_1658048928200692800.sql | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 data/sql/updates/pending_db_world/rev_1658048928200692800.sql diff --git a/data/sql/updates/pending_db_world/rev_1658048928200692800.sql b/data/sql/updates/pending_db_world/rev_1658048928200692800.sql new file mode 100644 index 000000000..75d1b0697 --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1658048928200692800.sql @@ -0,0 +1,3 @@ +-- +UPDATE `smart_scripts` SET `target_type`=24 WHERE `entryorguid`=25416 AND `source_type`=0 AND `id`=4; +UPDATE `smart_scripts` SET `target_type`=24 WHERE `entryorguid`=25418 AND `source_type`=0 AND `id`=4; From 0b24dddb34a9cd67318134b989328276e5a5bbf8 Mon Sep 17 00:00:00 2001 From: ZhengPeiRu21 <98835050+ZhengPeiRu21@users.noreply.github.com> Date: Wed, 20 Jul 2022 07:32:47 -0600 Subject: [PATCH 033/130] fix(DB/Creature): Remorseful Highborne (#12374) --- .../rev_1657733841180289000.sql | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 data/sql/updates/pending_db_world/rev_1657733841180289000.sql diff --git a/data/sql/updates/pending_db_world/rev_1657733841180289000.sql b/data/sql/updates/pending_db_world/rev_1657733841180289000.sql new file mode 100644 index 000000000..650e291fc --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1657733841180289000.sql @@ -0,0 +1,27 @@ +-- Remorseful Highborne --> Add gossip texts (Credit: https://github.com/Haeniken/FairyCore/commit/25260b92a6c5163643248deeae7247a3bac6cbb7) +UPDATE `creature_template` SET `gossip_menu_id`=3803, `npcflag` = `npcflag` | 1 WHERE `entry`=10684; + +DELETE FROM `gossip_menu` WHERE `MenuID`=3803; +INSERT INTO `gossip_menu` (`MenuID`, `TextID`) VALUES +(3803,4635), +(3803,4636); + +DELETE FROM `npc_text` WHERE `ID`=4636; +INSERT INTO `npc_text` (`ID`, `text0_0`, `text0_1`, `BroadcastTextID0`, `lang0`, `Probability0`) VALUES +(4636,'',"I will not forrrget what you have done...$B$BPleassse, leave meee...",7309,0,1); + +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=14 AND `SourceGroup`=3803; +INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES +(14,3803,4636,0,0,8,0,5248,0,0,0,0,0,'',"Remorseful Highborne - Show Gossip Menu Text 4636 if Quest 5248 is rewarded"); + +-- Remorseful Highborne --> Add texts on quest finished +DELETE FROM `creature_text` WHERE `CreatureID`=10684; +INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES +(10684,0,0,"Highborne spirits! Be at peace! The Crystal of Zin-Malor is whole once again!",14,0,100,0,0,0,6505,0,"Remorseful Highborne"), +(10684,0,1,"Cursed spirits! Let go of the past! The Crystal of Zin-Malor no longer binds you!",14,0,100,0,0,0,6506,0,"Remorseful Highborne"), +(10684,0,2,"Spirits of the Highborne! You may now rest! The curse of the crystal releases you!",14,0,100,0,0,0,6507,0,"Remorseful Highborne"); + +UPDATE `creature_template` SET `AIName`="SmartAI" WHERE `entry`=10684; +DELETE FROM `smart_scripts` WHERE `entryorguid`=10684 AND `source_type`=0; +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(10684,0,0,0,20,0,100,0,5248,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"Remorseful Highborne - On Quest \'Tormented by the Past\' Finished - Say Line 0"); From 4ddaccd73930ffed6c78f58b3c11b5a6de72c849 Mon Sep 17 00:00:00 2001 From: AzerothCoreBot Date: Wed, 20 Jul 2022 13:35:01 +0000 Subject: [PATCH 034/130] chore(DB): import pending files Referenced commit(s): 0b24dddb34a9cd67318134b989328276e5a5bbf8 --- .../rev_1657733841180289000.sql => db_world/2022_07_20_06.sql} | 1 + .../rev_1658048928200692800.sql => db_world/2022_07_20_07.sql} | 1 + 2 files changed, 2 insertions(+) rename data/sql/updates/{pending_db_world/rev_1657733841180289000.sql => db_world/2022_07_20_06.sql} (98%) rename data/sql/updates/{pending_db_world/rev_1658048928200692800.sql => db_world/2022_07_20_07.sql} (82%) diff --git a/data/sql/updates/pending_db_world/rev_1657733841180289000.sql b/data/sql/updates/db_world/2022_07_20_06.sql similarity index 98% rename from data/sql/updates/pending_db_world/rev_1657733841180289000.sql rename to data/sql/updates/db_world/2022_07_20_06.sql index 650e291fc..06fe8042c 100644 --- a/data/sql/updates/pending_db_world/rev_1657733841180289000.sql +++ b/data/sql/updates/db_world/2022_07_20_06.sql @@ -1,3 +1,4 @@ +-- DB update 2022_07_20_05 -> 2022_07_20_06 -- Remorseful Highborne --> Add gossip texts (Credit: https://github.com/Haeniken/FairyCore/commit/25260b92a6c5163643248deeae7247a3bac6cbb7) UPDATE `creature_template` SET `gossip_menu_id`=3803, `npcflag` = `npcflag` | 1 WHERE `entry`=10684; diff --git a/data/sql/updates/pending_db_world/rev_1658048928200692800.sql b/data/sql/updates/db_world/2022_07_20_07.sql similarity index 82% rename from data/sql/updates/pending_db_world/rev_1658048928200692800.sql rename to data/sql/updates/db_world/2022_07_20_07.sql index 75d1b0697..d3a039af4 100644 --- a/data/sql/updates/pending_db_world/rev_1658048928200692800.sql +++ b/data/sql/updates/db_world/2022_07_20_07.sql @@ -1,3 +1,4 @@ +-- DB update 2022_07_20_06 -> 2022_07_20_07 -- UPDATE `smart_scripts` SET `target_type`=24 WHERE `entryorguid`=25416 AND `source_type`=0 AND `id`=4; UPDATE `smart_scripts` SET `target_type`=24 WHERE `entryorguid`=25418 AND `source_type`=0 AND `id`=4; From 758eee999e0599fb98feb6101363024bada740c4 Mon Sep 17 00:00:00 2001 From: temperrr Date: Wed, 20 Jul 2022 15:41:17 +0200 Subject: [PATCH 035/130] fix(DB/SAI): Skeletal Horror should cast Terrify at top threat target (#12452) fix(SmartScript/Creature) --- data/sql/updates/pending_db_world/skeletalhorror.sql | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 data/sql/updates/pending_db_world/skeletalhorror.sql diff --git a/data/sql/updates/pending_db_world/skeletalhorror.sql b/data/sql/updates/pending_db_world/skeletalhorror.sql new file mode 100644 index 000000000..49a18e354 --- /dev/null +++ b/data/sql/updates/pending_db_world/skeletalhorror.sql @@ -0,0 +1,5 @@ +UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 202; + +DELETE FROM `smart_scripts` WHERE (`entryorguid` = 202) AND (`source_type` = 0) AND (`id` IN (0)); +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(202, 0, 0, 0, 0, 0, 100, 0, 5000, 8000, 9000, 13000, 0, 11, 7399, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Skeletal Horror - In Combat - Cast \'Terrify\' (No Repeat)'); From 123b7166e8303071c707346cd51ffb759a71979d Mon Sep 17 00:00:00 2001 From: AzerothCoreBot Date: Wed, 20 Jul 2022 13:43:36 +0000 Subject: [PATCH 036/130] chore(DB): import pending files Referenced commit(s): 758eee999e0599fb98feb6101363024bada740c4 --- .../skeletalhorror.sql => db_world/2022_07_20_08.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/skeletalhorror.sql => db_world/2022_07_20_08.sql} (94%) diff --git a/data/sql/updates/pending_db_world/skeletalhorror.sql b/data/sql/updates/db_world/2022_07_20_08.sql similarity index 94% rename from data/sql/updates/pending_db_world/skeletalhorror.sql rename to data/sql/updates/db_world/2022_07_20_08.sql index 49a18e354..68e6beea2 100644 --- a/data/sql/updates/pending_db_world/skeletalhorror.sql +++ b/data/sql/updates/db_world/2022_07_20_08.sql @@ -1,3 +1,4 @@ +-- DB update 2022_07_20_07 -> 2022_07_20_08 UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 202; DELETE FROM `smart_scripts` WHERE (`entryorguid` = 202) AND (`source_type` = 0) AND (`id` IN (0)); From b77fbf61da8a47d3715a7f7620c884a288636bb9 Mon Sep 17 00:00:00 2001 From: Maelthyr <100411212+Maelthyrr@users.noreply.github.com> Date: Wed, 20 Jul 2022 15:45:41 +0200 Subject: [PATCH 037/130] fix(Scripts/ZulGurub): Adjust Arlokk timers (#12458) follow up https://github.com/azerothcore/azerothcore-wotlk/commit/9aeb23636803c681efa8d25451639e2f7b7a2f0c --- src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp index 5c33f4a82..0b8af4541 100644 --- a/src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp +++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp @@ -249,7 +249,7 @@ public: case EVENT_VANISH_2: DoCastSelf(SPELL_VANISH); DoCastSelf(SPELL_SUPER_INVIS); - events.ScheduleEvent(EVENT_VISIBLE, urand(7000, 10000), 0, PHASE_ONE); + events.ScheduleEvent(EVENT_VISIBLE, urand(41000, 47000), 0, PHASE_ONE); break; case EVENT_VISIBLE: me->SetReactState(REACT_AGGRESSIVE); From 43d5876dd6bde901e4e0c8f6065984033649abd6 Mon Sep 17 00:00:00 2001 From: Skjalf <47818697+Nyeriah@users.noreply.github.com> Date: Wed, 20 Jul 2022 10:51:21 -0300 Subject: [PATCH 038/130] =?UTF-8?q?fix(Scripts\TempleOfAhnQiraj):=20Fix=20?= =?UTF-8?q?Skeram=20images=20not=20spawning=20if=20he's=E2=80=A6=20(#12428?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../scripts/Kalimdor/TempleOfAhnQiraj/boss_skeram.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_skeram.cpp b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_skeram.cpp index f0ffe9d79..5944c9e95 100644 --- a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_skeram.cpp +++ b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_skeram.cpp @@ -58,6 +58,7 @@ public: void Reset() override { + _Reset(); _flag = 0; _hpct = 75.0f; me->SetVisible(true); @@ -96,9 +97,6 @@ public: if (_flag & (1 << 7)) _flag = 0; - if (Unit* Target = SelectTarget(SelectTargetMethod::Random)) - creature->AI()->AttackStart(Target); - float ImageHealthPct; if (me->GetHealthPct() < 25.0f) @@ -110,12 +108,16 @@ public: creature->SetMaxHealth(me->GetMaxHealth() * ImageHealthPct); creature->SetHealth(creature->GetMaxHealth() * (me->GetHealthPct() / 100.0f)); + BossAI::JustSummoned(creature); } void JustDied(Unit* /*killer*/) override { if (!me->IsSummon()) + { + _JustDied(); Talk(SAY_DEATH); + } else me->RemoveCorpse(); } @@ -169,7 +171,7 @@ public: if (!me->IsSummon() && me->GetHealthPct() < _hpct) { - DoCast(me, SPELL_SUMMON_IMAGES); + DoCast(me, SPELL_SUMMON_IMAGES, true); Talk(SAY_SPLIT); _hpct -= 25.0f; me->SetVisible(false); From 42c3474ad899da99bcf2d713edcfe63bf13c67be Mon Sep 17 00:00:00 2001 From: temperrr Date: Wed, 20 Jul 2022 17:57:23 +0200 Subject: [PATCH 039/130] =?UTF-8?q?fix(DB/SAI):=20Flamewaker=20Protector?= =?UTF-8?q?=20should=20not=20cast=20domi=E2=80=A6=20(#12454)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fix(SmartScripts/Creature): Flamewaker Protector should not cast dominate mind on main target. --- data/sql/updates/pending_db_world/flamewakerprotector.sql | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 data/sql/updates/pending_db_world/flamewakerprotector.sql diff --git a/data/sql/updates/pending_db_world/flamewakerprotector.sql b/data/sql/updates/pending_db_world/flamewakerprotector.sql new file mode 100644 index 000000000..4af545cd1 --- /dev/null +++ b/data/sql/updates/pending_db_world/flamewakerprotector.sql @@ -0,0 +1,6 @@ +UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 12119; + +DELETE FROM `smart_scripts` WHERE (`entryorguid` = 12119) AND (`source_type` = 0) AND (`id` IN (0, 1)); +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(12119, 0, 0, 0, 0, 0, 100, 0, 5000, 5000, 6500, 6500, 0, 11, 20604, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 'Flamewaker Protector - In Combat - Cast \'Dominate Mind\''), +(12119, 0, 1, 0, 0, 0, 100, 0, 5000, 10000, 7000, 7000, 0, 11, 20605, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Flamewaker Protector - In Combat - Cast \'Cleave\''); From 619a6526bdfde997e4a7b120fe40441c8f474fcc Mon Sep 17 00:00:00 2001 From: neifion-00000000 <91289495+neifion-00000000@users.noreply.github.com> Date: Wed, 20 Jul 2022 10:58:19 -0500 Subject: [PATCH 040/130] fix(DB/Creature): ZG Before Bats Area Improvements (#12442) * fix(DB/creature): ZG Before Bats Area Improvements Update a few creature positions Add a few extra ids Remove movement from croc mobs until proper movement can be added. Adjust movement type on bat pack. * Order matters here * nitpicks sorry :P --- .../rev_1658282918588821000.sql | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 data/sql/updates/pending_db_world/rev_1658282918588821000.sql diff --git a/data/sql/updates/pending_db_world/rev_1658282918588821000.sql b/data/sql/updates/pending_db_world/rev_1658282918588821000.sql new file mode 100644 index 000000000..ddc0d7884 --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1658282918588821000.sql @@ -0,0 +1,21 @@ +-- +/* Snakes */ +UPDATE `creature` SET `id1`=11371 WHERE `guid` IN (49096, 49097); +UPDATE `creature` SET `id2`=11372 WHERE `guid` IN (49096, 49097); + +/* Priest can be Axe thrower */ +UPDATE `creature` SET `id2`=11350 WHERE `guid`=49754; + +/* Crocs movement is a scripted action that occurs about every 30 seconds, and all crocs do it--not normal random movement */ +UPDATE `creature` SET `wander_distance`=0, `MovementType`=0 WHERE `id1`=15043; + +/* Reposition a Snake */ +/* Reposition two Trolls */ +DELETE FROM `creature` WHERE `guid` IN (49121, 49122, 49097); +INSERT INTO `creature` (`guid`, `id1`, `id2`, `id3`, `map`, `zoneId`, `areaId`, `spawnMask`, `phaseMask`, `equipment_id`, `position_x`, `position_y`, `position_z`, `orientation`, `spawntimesecs`, `wander_distance`, `currentwaypoint`, `curhealth`, `curmana`, `MovementType`, `npcflag`, `unit_flags`, `dynamicflags`, `ScriptName`, `VerifiedBuild`) VALUES +(49097, 11371, 11372, 0, 309, 0, 0, 1, 1, 0, -11959.5, -1547.96, 40.6727, 3.1776, 7200, 0, 0, 15260, 0, 0, 0, 0, 0, '', 0), +(49121, 11351, 0, 0, 309, 0, 0, 1, 1, 1, -12008.5, -1484.79, 79.1498, 4.87654, 7200, 0, 0, 21364, 0, 0, 0, 0, 0, '', 0), +(49122, 11831, 0, 0, 309, 0, 0, 1, 1, 1, -12004.5, -1483.46, 79.5746, 4.71553, 7200, 0, 0, 24420, 12170, 0, 0, 0, 0, '', 0); + +/* Movetype and wander distance corrections for Snakes and Bats/Bat Riders */ +UPDATE `creature` SET `wander_distance`=2, `MovementType`=1 WHERE `guid` IN (49096, 49097, 49190, 49191, 49192, 49193); From b7bd70625d4648645fbd45358271a0557f33f307 Mon Sep 17 00:00:00 2001 From: AzerothCoreBot Date: Wed, 20 Jul 2022 16:00:26 +0000 Subject: [PATCH 041/130] chore(DB): import pending files Referenced commit(s): 619a6526bdfde997e4a7b120fe40441c8f474fcc --- .../flamewakerprotector.sql => db_world/2022_07_20_09.sql} | 1 + .../rev_1658282918588821000.sql => db_world/2022_07_20_10.sql} | 1 + 2 files changed, 2 insertions(+) rename data/sql/updates/{pending_db_world/flamewakerprotector.sql => db_world/2022_07_20_09.sql} (95%) rename data/sql/updates/{pending_db_world/rev_1658282918588821000.sql => db_world/2022_07_20_10.sql} (97%) diff --git a/data/sql/updates/pending_db_world/flamewakerprotector.sql b/data/sql/updates/db_world/2022_07_20_09.sql similarity index 95% rename from data/sql/updates/pending_db_world/flamewakerprotector.sql rename to data/sql/updates/db_world/2022_07_20_09.sql index 4af545cd1..2685bc2f1 100644 --- a/data/sql/updates/pending_db_world/flamewakerprotector.sql +++ b/data/sql/updates/db_world/2022_07_20_09.sql @@ -1,3 +1,4 @@ +-- DB update 2022_07_20_08 -> 2022_07_20_09 UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 12119; DELETE FROM `smart_scripts` WHERE (`entryorguid` = 12119) AND (`source_type` = 0) AND (`id` IN (0, 1)); diff --git a/data/sql/updates/pending_db_world/rev_1658282918588821000.sql b/data/sql/updates/db_world/2022_07_20_10.sql similarity index 97% rename from data/sql/updates/pending_db_world/rev_1658282918588821000.sql rename to data/sql/updates/db_world/2022_07_20_10.sql index ddc0d7884..8fe12a4d2 100644 --- a/data/sql/updates/pending_db_world/rev_1658282918588821000.sql +++ b/data/sql/updates/db_world/2022_07_20_10.sql @@ -1,3 +1,4 @@ +-- DB update 2022_07_20_09 -> 2022_07_20_10 -- /* Snakes */ UPDATE `creature` SET `id1`=11371 WHERE `guid` IN (49096, 49097); From 565e39ac55d45943a15d961c47abb04904a34c0e Mon Sep 17 00:00:00 2001 From: Skjalf <47818697+Nyeriah@users.noreply.github.com> Date: Wed, 20 Jul 2022 13:49:39 -0300 Subject: [PATCH 042/130] fix(Scripts\Spells): Consume (AQ) (#12448) --- .../rev_1658293185077751500.sql | 5 ++ src/server/scripts/Spells/spell_generic.cpp | 51 +++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 data/sql/updates/pending_db_world/rev_1658293185077751500.sql diff --git a/data/sql/updates/pending_db_world/rev_1658293185077751500.sql b/data/sql/updates/pending_db_world/rev_1658293185077751500.sql new file mode 100644 index 000000000..63dbb7fb1 --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1658293185077751500.sql @@ -0,0 +1,5 @@ +-- +DELETE FROM `spell_script_names` WHERE `spell_id` = 25371 AND `ScriptName` = 'spell_consume_aq20'; +INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES (25371, 'spell_consume_aq20'); +DELETE FROM `spell_script_names` WHERE `spell_id` = 25373 AND `ScriptName` = 'spell_gen_10pct_count_pct_from_max_hp'; +INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES (25373, 'spell_gen_10pct_count_pct_from_max_hp'); diff --git a/src/server/scripts/Spells/spell_generic.cpp b/src/server/scripts/Spells/spell_generic.cpp index 51d16c953..9b4af72b0 100644 --- a/src/server/scripts/Spells/spell_generic.cpp +++ b/src/server/scripts/Spells/spell_generic.cpp @@ -4472,6 +4472,55 @@ class spell_gen_remove_impairing_auras : public SpellScript } }; +enum AQSpells +{ + SPELL_CONSUME_LEECH_AQ20 = 25373, + SPELL_CONSUME_LEECH_HEAL_AQ20 = 25378 +}; + +class spell_gen_consume : public AuraScript +{ + PrepareAuraScript(spell_gen_consume); + +public: + spell_gen_consume(uint32 spellId1, uint32 spellId2) : AuraScript(), _spellId1(spellId1), _spellId2(spellId2) { } + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo({ _spellId1, _spellId2 }); + } + + void HandleProc(AuraEffect* /*aurEff*/) + { + if (Unit* caster = GetCaster()) + { + caster->CastSpell(GetUnitOwner(), _spellId1, true); + } + } + + void AfterRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + // Final heal only on duration end + if (GetTargetApplication() && GetTargetApplication()->GetRemoveMode() == AURA_REMOVE_BY_DEATH) + { + if (Unit* caster = GetCaster()) + { + caster->CastSpell(caster, _spellId2, true); + } + } + } + + void Register() override + { + AfterEffectRemove += AuraEffectRemoveFn(spell_gen_consume::AfterRemove, EFFECT_1, SPELL_AURA_MOD_STUN, AURA_EFFECT_HANDLE_REAL); + OnEffectUpdatePeriodic += AuraEffectUpdatePeriodicFn(spell_gen_consume::HandleProc, EFFECT_2, SPELL_AURA_PERIODIC_TRIGGER_SPELL); + } + +private: + uint32 _spellId1; + uint32 _spellId2; +}; + void AddSC_generic_spell_scripts() { RegisterSpellScript(spell_silithyst); @@ -4569,6 +4618,7 @@ void AddSC_generic_spell_scripts() RegisterSpellScript(spell_gen_teleporting); RegisterSpellScript(spell_gen_ds_flush_knockback); RegisterSpellScriptWithArgs(spell_gen_count_pct_from_max_hp, "spell_gen_default_count_pct_from_max_hp"); + RegisterSpellScriptWithArgs(spell_gen_count_pct_from_max_hp, "spell_gen_10pct_count_pct_from_max_hp", 10); RegisterSpellScriptWithArgs(spell_gen_count_pct_from_max_hp, "spell_gen_50pct_count_pct_from_max_hp", 50); RegisterSpellScriptWithArgs(spell_gen_count_pct_from_max_hp, "spell_gen_100pct_count_pct_from_max_hp", 100); RegisterSpellScript(spell_gen_despawn_self); @@ -4605,4 +4655,5 @@ void AddSC_generic_spell_scripts() RegisterSpellScript(spell_gen_holiday_buff_food); RegisterSpellScript(spell_gen_arcane_charge); RegisterSpellScript(spell_gen_remove_impairing_auras); + RegisterSpellScriptWithArgs(spell_gen_consume, "spell_consume_aq20", SPELL_CONSUME_LEECH_AQ20, SPELL_CONSUME_LEECH_HEAL_AQ20); } From 96b48a78bb9fd3f5b4702a924a710735bb0b1882 Mon Sep 17 00:00:00 2001 From: AzerothCoreBot Date: Wed, 20 Jul 2022 16:51:52 +0000 Subject: [PATCH 043/130] chore(DB): import pending files Referenced commit(s): 565e39ac55d45943a15d961c47abb04904a34c0e --- .../rev_1658293185077751500.sql => db_world/2022_07_20_11.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/rev_1658293185077751500.sql => db_world/2022_07_20_11.sql} (90%) diff --git a/data/sql/updates/pending_db_world/rev_1658293185077751500.sql b/data/sql/updates/db_world/2022_07_20_11.sql similarity index 90% rename from data/sql/updates/pending_db_world/rev_1658293185077751500.sql rename to data/sql/updates/db_world/2022_07_20_11.sql index 63dbb7fb1..bd38538ac 100644 --- a/data/sql/updates/pending_db_world/rev_1658293185077751500.sql +++ b/data/sql/updates/db_world/2022_07_20_11.sql @@ -1,3 +1,4 @@ +-- DB update 2022_07_20_10 -> 2022_07_20_11 -- DELETE FROM `spell_script_names` WHERE `spell_id` = 25371 AND `ScriptName` = 'spell_consume_aq20'; INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES (25371, 'spell_consume_aq20'); From fba89eb35974bd622ee9481f872f5534c05ec14b Mon Sep 17 00:00:00 2001 From: Skjalf <47818697+Nyeriah@users.noreply.github.com> Date: Wed, 20 Jul 2022 14:00:31 -0300 Subject: [PATCH 044/130] fix(Scripts/TempleOfAhnQiraj): Correct Fankriss Mortal Wound spell ID (#12443) --- .../TempleOfAhnQiraj/boss_fankriss.cpp | 192 +++++++----------- 1 file changed, 69 insertions(+), 123 deletions(-) diff --git a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_fankriss.cpp b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_fankriss.cpp index e7fd78ea6..fdd08243b 100644 --- a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_fankriss.cpp +++ b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_fankriss.cpp @@ -24,6 +24,7 @@ EndScriptData */ #include "ScriptMgr.h" #include "ScriptedCreature.h" +#include "TaskScheduler.h" #include "temple_of_ahnqiraj.h" #define SOUND_SENTENCE_YOU 8588 @@ -34,7 +35,7 @@ EndScriptData */ enum Spells { - SPELL_MORTAL_WOUND = 28467, + SPELL_MORTAL_WOUND = 25646, SPELL_ROOT = 28858, // Enrage for his spawns @@ -55,28 +56,8 @@ public: { boss_fankrissAI(Creature* creature) : ScriptedAI(creature) { } - uint32 MortalWound_Timer; - uint32 SpawnHatchlings_Timer; - uint32 SpawnSpawns_Timer; - int Rand; - float RandX; - float RandY; - - Creature* Hatchling; - Creature* Spawn; - - void Reset() override + void SummonSpawn() { - MortalWound_Timer = urand(10000, 15000); - SpawnHatchlings_Timer = urand(6000, 12000); - SpawnSpawns_Timer = urand(15000, 45000); - } - - void SummonSpawn(Unit* victim) - { - if (!victim) - return; - Rand = 10 + (rand() % 10); switch (rand() % 2) { @@ -99,13 +80,68 @@ public: break; } Rand = 0; - Spawn = DoSpawnCreature(15630, RandX, RandY, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); - if (Spawn) - Spawn->AI()->AttackStart(victim); + DoSpawnCreature(15630, RandX, RandY, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); } void EnterCombat(Unit* /*who*/) override { + _scheduler.CancelAll(); + + _scheduler.Schedule(4s, 8s, [this](TaskContext context) { + DoCastVictim(SPELL_MORTAL_WOUND); + context.Repeat(); + }).Schedule(15s, 45s, [this](TaskContext context) { + switch (urand(0, 2)) + { + case 0: + SummonSpawn(); + break; + case 1: + SummonSpawn(); + SummonSpawn(); + break; + case 2: + SummonSpawn(); + SummonSpawn(); + SummonSpawn(); + break; + } + context.Repeat(30s, 60s); + }).Schedule(15s, 45s, [this](TaskContext context) { + if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true)) + { + DoCast(target, SPELL_ROOT); + + if (DoGetThreat(target)) + DoModifyThreatPercent(target, -100); + + switch (urand(0, 2)) + { + case 0: + DoTeleportPlayer(target, -8106.0142f, 1289.2900f, -74.419533f, 5.112f); + me->SummonCreature(15962, target->GetPositionX() - 3, target->GetPositionY() - 3, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + me->SummonCreature(15962, target->GetPositionX() - 3, target->GetPositionY() + 3, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + me->SummonCreature(15962, target->GetPositionX() - 5, target->GetPositionY() - 5, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + me->SummonCreature(15962, target->GetPositionX() - 5, target->GetPositionY() + 5, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + break; + case 1: + DoTeleportPlayer(target, -7990.135354f, 1155.1907f, -78.849319f, 2.608f); + me->SummonCreature(15962, target->GetPositionX() - 3, target->GetPositionY() - 3, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + me->SummonCreature(15962, target->GetPositionX() - 3, target->GetPositionY() + 3, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + me->SummonCreature(15962, target->GetPositionX() - 5, target->GetPositionY() - 5, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + me->SummonCreature(15962, target->GetPositionX() - 5, target->GetPositionY() + 5, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + break; + case 2: + DoTeleportPlayer(target, -8159.7753f, 1127.9064f, -76.868660f, 0.675f); + me->SummonCreature(15962, target->GetPositionX() - 3, target->GetPositionY() - 3, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + me->SummonCreature(15962, target->GetPositionX() - 3, target->GetPositionY() + 3, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + me->SummonCreature(15962, target->GetPositionX() - 5, target->GetPositionY() - 5, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + me->SummonCreature(15962, target->GetPositionX() - 5, target->GetPositionY() + 5, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + break; + } + } + context.Repeat(45s, 60s); + }); } void UpdateAI(uint32 diff) override @@ -114,105 +150,15 @@ public: if (!UpdateVictim()) return; - //MortalWound_Timer - if (MortalWound_Timer <= diff) - { - DoCastVictim(SPELL_MORTAL_WOUND); - MortalWound_Timer = urand(10000, 20000); - } - else MortalWound_Timer -= diff; - - //Summon 1-3 Spawns of Fankriss at random time. - if (SpawnSpawns_Timer <= diff) - { - switch (urand(0, 2)) - { - case 0: - SummonSpawn(SelectTarget(SelectTargetMethod::Random, 0)); - break; - case 1: - SummonSpawn(SelectTarget(SelectTargetMethod::Random, 0)); - SummonSpawn(SelectTarget(SelectTargetMethod::Random, 0)); - break; - case 2: - SummonSpawn(SelectTarget(SelectTargetMethod::Random, 0)); - SummonSpawn(SelectTarget(SelectTargetMethod::Random, 0)); - SummonSpawn(SelectTarget(SelectTargetMethod::Random, 0)); - break; - } - SpawnSpawns_Timer = urand(30000, 60000); - } - else SpawnSpawns_Timer -= diff; - - // Teleporting Random Target to one of the three tunnels and spawn 4 hatchlings near the gamer. - //We will only telport if fankriss has more than 3% of hp so teleported gamers can always loot. - if (HealthAbovePct(3)) - { - if (SpawnHatchlings_Timer <= diff) - { - if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true)) - { - DoCast(target, SPELL_ROOT); - - if (DoGetThreat(target)) - DoModifyThreatPercent(target, -100); - - switch (urand(0, 2)) - { - case 0: - DoTeleportPlayer(target, -8106.0142f, 1289.2900f, -74.419533f, 5.112f); - Hatchling = me->SummonCreature(15962, target->GetPositionX() - 3, target->GetPositionY() - 3, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - if (Hatchling) - Hatchling->AI()->AttackStart(target); - Hatchling = me->SummonCreature(15962, target->GetPositionX() - 3, target->GetPositionY() + 3, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - if (Hatchling) - Hatchling->AI()->AttackStart(target); - Hatchling = me->SummonCreature(15962, target->GetPositionX() - 5, target->GetPositionY() - 5, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - if (Hatchling) - Hatchling->AI()->AttackStart(target); - Hatchling = me->SummonCreature(15962, target->GetPositionX() - 5, target->GetPositionY() + 5, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - if (Hatchling) - Hatchling->AI()->AttackStart(target); - break; - case 1: - DoTeleportPlayer(target, -7990.135354f, 1155.1907f, -78.849319f, 2.608f); - Hatchling = me->SummonCreature(15962, target->GetPositionX() - 3, target->GetPositionY() - 3, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - if (Hatchling) - Hatchling->AI()->AttackStart(target); - Hatchling = me->SummonCreature(15962, target->GetPositionX() - 3, target->GetPositionY() + 3, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - if (Hatchling) - Hatchling->AI()->AttackStart(target); - Hatchling = me->SummonCreature(15962, target->GetPositionX() - 5, target->GetPositionY() - 5, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - if (Hatchling) - Hatchling->AI()->AttackStart(target); - Hatchling = me->SummonCreature(15962, target->GetPositionX() - 5, target->GetPositionY() + 5, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - if (Hatchling) - Hatchling->AI()->AttackStart(target); - break; - case 2: - DoTeleportPlayer(target, -8159.7753f, 1127.9064f, -76.868660f, 0.675f); - Hatchling = me->SummonCreature(15962, target->GetPositionX() - 3, target->GetPositionY() - 3, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - if (Hatchling) - Hatchling->AI()->AttackStart(target); - Hatchling = me->SummonCreature(15962, target->GetPositionX() - 3, target->GetPositionY() + 3, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - if (Hatchling) - Hatchling->AI()->AttackStart(target); - Hatchling = me->SummonCreature(15962, target->GetPositionX() - 5, target->GetPositionY() - 5, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - if (Hatchling) - Hatchling->AI()->AttackStart(target); - Hatchling = me->SummonCreature(15962, target->GetPositionX() - 5, target->GetPositionY() + 5, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - if (Hatchling) - Hatchling->AI()->AttackStart(target); - break; - } - } - SpawnHatchlings_Timer = urand(45000, 60000); - } - else SpawnHatchlings_Timer -= diff; - } - - DoMeleeAttackIfReady(); + _scheduler.Update(diff, + std::bind(&ScriptedAI::DoMeleeAttackIfReady, this)); } + + private: + TaskScheduler _scheduler; + int Rand; + float RandX; + float RandY; }; }; From 5c3656a6422a4dd99c43c0709f34f30e7b130ef0 Mon Sep 17 00:00:00 2001 From: Skjalf <47818697+Nyeriah@users.noreply.github.com> Date: Wed, 20 Jul 2022 14:00:48 -0300 Subject: [PATCH 045/130] =?UTF-8?q?fix(Scripts\TempleOfAnhQiraj):=20Fix=20?= =?UTF-8?q?Huhuran`s=20Wyvern=20Sting=20dealing=20no=20=E2=80=A6=20(#12445?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ...damage when dispelled --- .../rev_1658289715488941700.sql | 3 ++ .../TempleOfAhnQiraj/boss_huhuran.cpp | 31 ++++++++++++++----- 2 files changed, 27 insertions(+), 7 deletions(-) create mode 100644 data/sql/updates/pending_db_world/rev_1658289715488941700.sql diff --git a/data/sql/updates/pending_db_world/rev_1658289715488941700.sql b/data/sql/updates/pending_db_world/rev_1658289715488941700.sql new file mode 100644 index 000000000..c6301315d --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1658289715488941700.sql @@ -0,0 +1,3 @@ +-- +DELETE FROM `spell_script_names` WHERE `spell_id` = 26180 AND `ScriptName` = 'spell_huhuran_wyvern_sting'; +INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES (26180, 'spell_huhuran_wyvern_sting'); diff --git a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_huhuran.cpp b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_huhuran.cpp index 3b5be7146..bdd58744e 100644 --- a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_huhuran.cpp +++ b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_huhuran.cpp @@ -24,6 +24,7 @@ EndScriptData */ #include "ScriptMgr.h" #include "ScriptedCreature.h" +#include "SpellScript.h" #include "temple_of_ahnqiraj.h" enum Huhuran @@ -36,7 +37,8 @@ enum Huhuran SPELL_POISONBOLT = 26052, SPELL_NOXIOUSPOISON = 26053, SPELL_WYVERNSTING = 26180, - SPELL_ACIDSPIT = 26050 + SPELL_ACIDSPIT = 26050, + SPELL_WYVERN_STING_DAMAGE = 26233 }; class boss_huhuran : public CreatureScript @@ -76,10 +78,6 @@ public: Berserk = false; } - void EnterCombat(Unit* /*who*/) override - { - } - void UpdateAI(uint32 diff) override { //Return since we have no target @@ -100,8 +98,7 @@ public: // Wyvern Timer if (Wyvern_Timer <= diff) { - if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0)) - DoCast(target, SPELL_WYVERNSTING); + DoCastAOE(SPELL_WYVERNSTING); Wyvern_Timer = urand(15000, 32000); } else Wyvern_Timer -= diff; @@ -155,7 +152,27 @@ public: }; }; +// 26180 - Wyvern Sting +class spell_huhuran_wyvern_sting : public AuraScript +{ + PrepareAuraScript(spell_huhuran_wyvern_sting); + + void HandleRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + if (Unit* caster = GetCaster()) + { + caster->CastCustomSpell(SPELL_WYVERN_STING_DAMAGE, SPELLVALUE_BASE_POINT0, 3000, GetUnitOwner(), true); + } + } + + void Register() override + { + AfterEffectRemove += AuraEffectRemoveFn(spell_huhuran_wyvern_sting::HandleRemove, EFFECT_0, SPELL_AURA_MOD_STUN, AURA_EFFECT_HANDLE_REAL); + } +}; + void AddSC_boss_huhuran() { new boss_huhuran(); + RegisterSpellScript(spell_huhuran_wyvern_sting); } From d42a74a9a5e8a741596e91b40b0616006156056d Mon Sep 17 00:00:00 2001 From: Skjalf <47818697+Nyeriah@users.noreply.github.com> Date: Wed, 20 Jul 2022 14:01:18 -0300 Subject: [PATCH 046/130] =?UTF-8?q?fix(Scripts\TempleOfAhnQiraj):=20C'thun?= =?UTF-8?q?=20should=20aggro=20as=20soon=20as=20you=20eit=E2=80=A6=20(#124?= =?UTF-8?q?29)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../scripts/Kalimdor/TempleOfAhnQiraj/boss_cthun.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_cthun.cpp b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_cthun.cpp index cffb86012..c262aafe2 100644 --- a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_cthun.cpp +++ b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_cthun.cpp @@ -195,6 +195,18 @@ public: instance->SetData(DATA_CTHUN_PHASE, PHASE_EYE_GREEN_BEAM); } + void MoveInLineOfSight(Unit* who) override + { + if (who->GetTypeId() == TYPEID_PLAYER && !me->IsInCombat()) + { + // Z checks are necessary here because AQ maps do funky stuff. + if (me->IsWithinLOSInMap(who) && me->IsWithinDist2d(who, 50.0f) && who->GetPositionZ() > 100.0f) + { + AttackStart(who); + } + } + } + void DoAction(int32 action) override { if (action == ACTION_SPAWN_EYE_TENTACLES) From 47f66c556cbb81dcd48aa4873a86e1aceaa9be8c Mon Sep 17 00:00:00 2001 From: AzerothCoreBot Date: Wed, 20 Jul 2022 17:03:35 +0000 Subject: [PATCH 047/130] chore(DB): import pending files Referenced commit(s): d42a74a9a5e8a741596e91b40b0616006156056d --- .../rev_1658289715488941700.sql => db_world/2022_07_20_12.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/rev_1658289715488941700.sql => db_world/2022_07_20_12.sql} (83%) diff --git a/data/sql/updates/pending_db_world/rev_1658289715488941700.sql b/data/sql/updates/db_world/2022_07_20_12.sql similarity index 83% rename from data/sql/updates/pending_db_world/rev_1658289715488941700.sql rename to data/sql/updates/db_world/2022_07_20_12.sql index c6301315d..04a2d8320 100644 --- a/data/sql/updates/pending_db_world/rev_1658289715488941700.sql +++ b/data/sql/updates/db_world/2022_07_20_12.sql @@ -1,3 +1,4 @@ +-- DB update 2022_07_20_11 -> 2022_07_20_12 -- DELETE FROM `spell_script_names` WHERE `spell_id` = 26180 AND `ScriptName` = 'spell_huhuran_wyvern_sting'; INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES (26180, 'spell_huhuran_wyvern_sting'); From 565e123cadfdb9f8cee0d69007b46b12676242f3 Mon Sep 17 00:00:00 2001 From: mpfans Date: Thu, 21 Jul 2022 01:05:41 +0800 Subject: [PATCH 048/130] fix(DB/Quest): Slim Pickings (#12359) --- data/sql/updates/pending_db_world/rev_1657531199046334193.sql | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 data/sql/updates/pending_db_world/rev_1657531199046334193.sql diff --git a/data/sql/updates/pending_db_world/rev_1657531199046334193.sql b/data/sql/updates/pending_db_world/rev_1657531199046334193.sql new file mode 100644 index 000000000..ecab6fdd0 --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1657531199046334193.sql @@ -0,0 +1,2 @@ +-- fix Slim Pickings quest +UPDATE `creature_template` SET `npcflag`=`npcflag`|1 WHERE `entry` = 26809; From 36824f6aa738a802d90f6dc1b2c4bc0d2d5c5185 Mon Sep 17 00:00:00 2001 From: AzerothCoreBot Date: Wed, 20 Jul 2022 17:07:59 +0000 Subject: [PATCH 049/130] chore(DB): import pending files Referenced commit(s): 565e123cadfdb9f8cee0d69007b46b12676242f3 --- .../rev_1657531199046334193.sql => db_world/2022_07_20_13.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/rev_1657531199046334193.sql => db_world/2022_07_20_13.sql} (70%) diff --git a/data/sql/updates/pending_db_world/rev_1657531199046334193.sql b/data/sql/updates/db_world/2022_07_20_13.sql similarity index 70% rename from data/sql/updates/pending_db_world/rev_1657531199046334193.sql rename to data/sql/updates/db_world/2022_07_20_13.sql index ecab6fdd0..bc91b0b86 100644 --- a/data/sql/updates/pending_db_world/rev_1657531199046334193.sql +++ b/data/sql/updates/db_world/2022_07_20_13.sql @@ -1,2 +1,3 @@ +-- DB update 2022_07_20_12 -> 2022_07_20_13 -- fix Slim Pickings quest UPDATE `creature_template` SET `npcflag`=`npcflag`|1 WHERE `entry` = 26809; From e8f271ca25122e6835d788dc6a058f1b1261744a Mon Sep 17 00:00:00 2001 From: Eddy Vega <61223313+Si1ker@users.noreply.github.com> Date: Wed, 20 Jul 2022 11:09:09 -0600 Subject: [PATCH 050/130] fix(Scripts/RuinsOfAhnQiraj): Improve Kurinnaxx (#12136) --- .../rev_1655863615360060800.sql | 5 +++ .../RuinsOfAhnQiraj/boss_kurinnaxx.cpp | 34 +++++++------------ 2 files changed, 18 insertions(+), 21 deletions(-) create mode 100644 data/sql/updates/pending_db_world/rev_1655863615360060800.sql diff --git a/data/sql/updates/pending_db_world/rev_1655863615360060800.sql b/data/sql/updates/pending_db_world/rev_1655863615360060800.sql new file mode 100644 index 000000000..c7565f42e --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1655863615360060800.sql @@ -0,0 +1,5 @@ +-- +DELETE FROM `creature_addon` WHERE `guid`=144632; +INSERT INTO `creature_addon` (`guid`, `auras`) VALUES +(144632, '8876'); -- Triggers SPELL_THRASH = 3391 + diff --git a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_kurinnaxx.cpp b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_kurinnaxx.cpp index 6d4ab62d5..510624a28 100644 --- a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_kurinnaxx.cpp +++ b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_kurinnaxx.cpp @@ -26,7 +26,6 @@ enum Spells SPELL_SANDTRAP = 25648, SPELL_ENRAGE = 26527, SPELL_SUMMON_PLAYER = 26446, - SPELL_TRASH = 3391, // Should perhaps be triggered by an aura? Couldn't find any though SPELL_WIDE_SLASH = 25814 }; @@ -34,13 +33,12 @@ enum Events { EVENT_MORTAL_WOUND = 1, EVENT_SANDTRAP = 2, - EVENT_TRASH = 3, - EVENT_WIDE_SLASH = 4 + EVENT_WIDE_SLASH = 3 }; enum Texts { - SAY_KURINAXX_DEATH = 5, // Yelled by Ossirian the Unscarred + SAY_KURINAXX_DEATH = 5 // Yell by 'Ossirian the Unscarred' }; class boss_kurinnaxx : public CreatureScript @@ -50,25 +48,22 @@ public: struct boss_kurinnaxxAI : public BossAI { - boss_kurinnaxxAI(Creature* creature) : BossAI(creature, DATA_KURINNAXX) - { - } + boss_kurinnaxxAI(Creature* creature) : BossAI(creature, DATA_KURINNAXX) {} void Reset() override { _Reset(); _enraged = false; - events.ScheduleEvent(EVENT_MORTAL_WOUND, 8000); + events.ScheduleEvent(EVENT_MORTAL_WOUND, urand(8000, 10000)); events.ScheduleEvent(EVENT_SANDTRAP, urand(5000, 15000)); - events.ScheduleEvent(EVENT_TRASH, 1000); - events.ScheduleEvent(EVENT_WIDE_SLASH, 11000); + events.ScheduleEvent(EVENT_WIDE_SLASH, urand(10000, 15000)); } void DamageTaken(Unit*, uint32& /*damage*/, DamageEffectType, SpellSchoolMask) override { if (!_enraged && HealthBelowPct(30)) { - DoCast(me, SPELL_ENRAGE); + DoCastSelf(SPELL_ENRAGE); _enraged = true; } } @@ -77,7 +72,9 @@ public: { _JustDied(); if (Creature* Ossirian = me->GetMap()->GetCreature(instance->GetGuidData(DATA_OSSIRIAN))) + { sCreatureTextMgr->SendChat(Ossirian, SAY_KURINAXX_DEATH, nullptr, CHAT_MSG_ADDON, LANG_ADDON, TEXT_RANGE_ZONE); + } } void UpdateAI(uint32 diff) override @@ -96,28 +93,23 @@ public: { case EVENT_MORTAL_WOUND: DoCastVictim(SPELL_MORTALWOUND); - events.ScheduleEvent(EVENT_MORTAL_WOUND, 8000); + events.ScheduleEvent(EVENT_MORTAL_WOUND, urand(8000, 10000)); break; case EVENT_SANDTRAP: if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100, true)) + { target->CastSpell(target, SPELL_SANDTRAP, true); - else if (Unit* victim = me->GetVictim()) - victim->CastSpell(victim, SPELL_SANDTRAP, true); + } events.ScheduleEvent(EVENT_SANDTRAP, urand(5000, 15000)); break; case EVENT_WIDE_SLASH: - DoCast(me, SPELL_WIDE_SLASH); - events.ScheduleEvent(EVENT_WIDE_SLASH, 11000); - break; - case EVENT_TRASH: - DoCast(me, SPELL_TRASH); - events.ScheduleEvent(EVENT_WIDE_SLASH, 16000); + DoCastSelf(SPELL_WIDE_SLASH); + events.ScheduleEvent(EVENT_WIDE_SLASH, urand(12000, 15000)); break; default: break; } } - DoMeleeAttackIfReady(); } private: From d9065adae8eb3ab12421372d45196b38a156a142 Mon Sep 17 00:00:00 2001 From: AzerothCoreBot Date: Wed, 20 Jul 2022 17:11:19 +0000 Subject: [PATCH 051/130] chore(DB): import pending files Referenced commit(s): e8f271ca25122e6835d788dc6a058f1b1261744a --- .../rev_1655863615360060800.sql => db_world/2022_07_20_14.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/rev_1655863615360060800.sql => db_world/2022_07_20_14.sql} (78%) diff --git a/data/sql/updates/pending_db_world/rev_1655863615360060800.sql b/data/sql/updates/db_world/2022_07_20_14.sql similarity index 78% rename from data/sql/updates/pending_db_world/rev_1655863615360060800.sql rename to data/sql/updates/db_world/2022_07_20_14.sql index c7565f42e..d7262e839 100644 --- a/data/sql/updates/pending_db_world/rev_1655863615360060800.sql +++ b/data/sql/updates/db_world/2022_07_20_14.sql @@ -1,3 +1,4 @@ +-- DB update 2022_07_20_13 -> 2022_07_20_14 -- DELETE FROM `creature_addon` WHERE `guid`=144632; INSERT INTO `creature_addon` (`guid`, `auras`) VALUES From bcdeaa416a06d0cd0201b7bcbff3c8b94a385da2 Mon Sep 17 00:00:00 2001 From: temperrr Date: Wed, 20 Jul 2022 19:19:06 +0200 Subject: [PATCH 052/130] fix(DB/SAI): AQ20 Trash scripts (#12444) --- .../updates/pending_db_world/aq20trash.sql | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 data/sql/updates/pending_db_world/aq20trash.sql diff --git a/data/sql/updates/pending_db_world/aq20trash.sql b/data/sql/updates/pending_db_world/aq20trash.sql new file mode 100644 index 000000000..08b76a4ac --- /dev/null +++ b/data/sql/updates/pending_db_world/aq20trash.sql @@ -0,0 +1,46 @@ +-- +UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` IN (15325, 15343, 15320, 15335, 15336, 15319, 15461, 15462, 15505); + +DELETE FROM `smart_scripts` WHERE `entryorguid`IN (15325, 15343, 15320, 15335, 15336, 15319, 15461, 15462, 15505); +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +-- swarmguard +(15343, 0, 0, 0, 9, 0, 100, 0, 0, 5, 8000, 12000, 0, 11, 25174, 3, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 'Qiraji Swarmguard - Within 0-5 Range - Cast \'Sundering Cleave\''), + +-- hive wasp +(15325, 0, 0, 0, 9, 0, 100, 0, 0, 40, 5000, 7000, 0, 11, 25185, 4, 32, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 'Hive\'Zara Wasp - Within 0-40 Range - Cast \'Itch\''), + +-- hive soldier +(15320, 0, 0, 0, 0, 0, 100, 0, 1000, 3000, 19000, 23000, 0, 11, 22857, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Hive\'Zara Soldier - In Combat - Cast \'Retaliation\''), +(15320, 0, 1, 0, 9, 0, 100, 0, 0, 30, 5000, 7000, 0, 11, 25497, 1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Hive\'Zara Soldier - Within 0-30 Range - Cast \'Venom Spit\''), + +-- flesh hunter +(15335, 0, 0, 0, 11, 0, 100, 0, 0, 0, 0, 0, 0, 11, 8876, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Flesh Hunter - On Respawn - Cast \'Thrash\''), +(15335, 0, 1, 0, 4, 0, 100, 0, 0, 0, 0, 0, 0, 22, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Flesh Hunter - On Aggro - Set Event Phase 1'), +(15335, 0, 2, 0, 9, 0, 100, 0, 0, 45, 5000, 7000, 0, 11, 25424, 4, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Flesh Hunter - Within 0-45 Range - Cast \'Poison Bolt\''), +(15335, 0, 3, 0, 24, 2, 100, 0, 25371, 1, 5000, 5000, 0, 22, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Flesh Hunter - On Target Buffed With \'Consume\' - Set Event Phase 2 (Phase 2)'), +(15335, 0, 4, 0, 28, 0, 100, 0, 5000, 5000, 0, 0, 0, 22, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Flesh Hunter - On Passenger Removed - Set Event Phase 1'), +(15335, 0, 5, 0, 9, 1, 100, 0, 0, 10, 21000, 24000, 0, 11, 25371, 1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Flesh Hunter - Within 0-10 Range - Cast \'Consume\' (Phase 1)'), +(15335, 0, 6, 0, 7, 0, 100, 0, 0, 0, 0, 0, 0, 22, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Flesh Hunter - On Evade - Set Event Phase 1'), + +-- tail lasher +(15336, 0, 0, 0, 4, 0, 100, 0, 0, 0, 0, 0, 0, 22, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Hive\'Zara Tail Lasher - On Aggro - Set Event Phase 1'), +(15336, 0, 1, 0, 9, 1, 100, 0, 0, 5, 6000, 9000, 0, 11, 25645, 1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Hive\'Zara Tail Lasher - Within 0-5 Range - Cast \'Poison\' (Phase 1)'), +(15336, 0, 2, 0, 24, 1, 100, 0, 25645, 5, 5000, 5000, 0, 22, 2, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Hive\'Zara Tail Lasher - On Target Buffed With \'Poison\' - Set Event Phase 2 (Phase 1)'), +(15336, 0, 3, 0, 24, 2, 100, 0, 25645, 1, 5000, 5000, 0, 22, 1, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Hive\'Zara Tail Lasher - On Target Buffed With \'Poison\' - Set Event Phase 1 (Phase 2)'), +(15336, 0, 4, 0, 9, 0, 100, 0, 0, 30, 7000, 10000, 0, 11, 25654, 4, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Hive\'Zara Tail Lasher - Within 0-30 Range - Cast \'Tail Lash\''), +(15336, 0, 5, 0, 7, 0, 100, 0, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'Hive\'Zara Tail Lasher - On Evade - Set Event Phase 0'), + +-- hive collector +(15319, 0, 0, 0, 9, 0, 100, 0, 0, 30, 10000, 16000, 0, 11, 12252, 1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Hive\'Zara Collector - Within 0-30 Range - Cast \'Web Spray\''), +(15319, 0, 1, 0, 0, 0, 100, 0, 7000, 11000, 12000, 15000, 0, 11, 3589, 4, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Hive\'Zara Collector - In Combat - Cast \'Deafening Screech\''), + +-- shrieker scarab +(15461, 0, 0, 0, 9, 0, 100, 0, 0, 40, 14000, 18000, 0, 11, 22886, 1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Shrieker Scarab - Within 0-40 Range - Cast \'Berserker Charge\''), +(15461, 0, 1, 0, 0, 0, 100, 0, 5000, 9000, 10000, 15000, 0, 11, 26379, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Shrieker Scarab - In Combat - Cast \'Piercing Shriek\''), + +-- spitting scarab +(15462, 0, 0, 0, 9, 0, 100, 0, 0, 40, 14000, 18000, 0, 11, 22886, 1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Spitting Scarab - Within 0-40 Range - Cast \'Berserker Charge\''), +(15462, 0, 1, 0, 0, 0, 100, 0, 5000, 9000, 4000, 6000, 0, 11, 24334, 4, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Spitting Scarab - In Combat - Cast \'Acid Spit\''), + +-- canal frenzy +(15505, 0, 0, 0, 9, 0, 100, 0, 0, 5, 5000, 8000, 0, 11, 12097, 4, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Canal Frenzy - Within 0-5 Range - Cast \'Pierce Armor\''); From 757375f982429c60b17e9b1f559ed86cb22abbc4 Mon Sep 17 00:00:00 2001 From: AzerothCoreBot Date: Wed, 20 Jul 2022 17:21:17 +0000 Subject: [PATCH 053/130] chore(DB): import pending files Referenced commit(s): bcdeaa416a06d0cd0201b7bcbff3c8b94a385da2 --- .../aq20trash.sql => db_world/2022_07_20_15.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/aq20trash.sql => db_world/2022_07_20_15.sql} (99%) diff --git a/data/sql/updates/pending_db_world/aq20trash.sql b/data/sql/updates/db_world/2022_07_20_15.sql similarity index 99% rename from data/sql/updates/pending_db_world/aq20trash.sql rename to data/sql/updates/db_world/2022_07_20_15.sql index 08b76a4ac..3cdcf09bd 100644 --- a/data/sql/updates/pending_db_world/aq20trash.sql +++ b/data/sql/updates/db_world/2022_07_20_15.sql @@ -1,3 +1,4 @@ +-- DB update 2022_07_20_14 -> 2022_07_20_15 -- UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` IN (15325, 15343, 15320, 15335, 15336, 15319, 15461, 15462, 15505); From a805be38750fbff764b03bf1cb2b108f3b3acf73 Mon Sep 17 00:00:00 2001 From: Gultask <100873791+Gultask@users.noreply.github.com> Date: Fri, 22 Jul 2022 11:42:05 -0300 Subject: [PATCH 054/130] fix(DB/Loot): Abyssal Crest (20513) (#12477) Create crests.sql --- data/sql/updates/pending_db_world/crests.sql | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 data/sql/updates/pending_db_world/crests.sql diff --git a/data/sql/updates/pending_db_world/crests.sql b/data/sql/updates/pending_db_world/crests.sql new file mode 100644 index 000000000..d7a2504b8 --- /dev/null +++ b/data/sql/updates/pending_db_world/crests.sql @@ -0,0 +1,2 @@ +-- +UPDATE `creature_loot_template` SET `Chance`='100' WHERE `Item`=20513 AND `Reference`=0 AND `GroupId`=0; From 0579f1426e138389aa34bd5c3688fe16f27a5ced Mon Sep 17 00:00:00 2001 From: AzerothCoreBot Date: Fri, 22 Jul 2022 14:44:03 +0000 Subject: [PATCH 055/130] chore(DB): import pending files Referenced commit(s): a805be38750fbff764b03bf1cb2b108f3b3acf73 --- .../{pending_db_world/crests.sql => db_world/2022_07_22_00.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/crests.sql => db_world/2022_07_22_00.sql} (71%) diff --git a/data/sql/updates/pending_db_world/crests.sql b/data/sql/updates/db_world/2022_07_22_00.sql similarity index 71% rename from data/sql/updates/pending_db_world/crests.sql rename to data/sql/updates/db_world/2022_07_22_00.sql index d7a2504b8..d59b77543 100644 --- a/data/sql/updates/pending_db_world/crests.sql +++ b/data/sql/updates/db_world/2022_07_22_00.sql @@ -1,2 +1,3 @@ +-- DB update 2022_07_20_15 -> 2022_07_22_00 -- UPDATE `creature_loot_template` SET `Chance`='100' WHERE `Item`=20513 AND `Reference`=0 AND `GroupId`=0; From 2d4e93dc3e2de1ab61ab98f34c0db2734da2f5ca Mon Sep 17 00:00:00 2001 From: ZhengPeiRu21 <98835050+ZhengPeiRu21@users.noreply.github.com> Date: Fri, 22 Jul 2022 19:20:14 -0600 Subject: [PATCH 056/130] fix(Core): SMART_ACTION_SET_HOME_POS should accept a parameter (#12468) --- src/server/game/AI/SmartScripts/SmartScriptMgr.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp index 0f5d71a8b..92c24beaa 100644 --- a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp +++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp @@ -679,7 +679,7 @@ bool SmartAIMgr::CheckUnusedActionParams(SmartScriptHolder const& e) case SMART_ACTION_SEND_GOSSIP_MENU: return sizeof(SmartAction::sendGossipMenu); case SMART_ACTION_GO_SET_LOOT_STATE: return sizeof(SmartAction::setGoLootState); case SMART_ACTION_SEND_TARGET_TO_TARGET: return sizeof(SmartAction::sendTargetToTarget); - case SMART_ACTION_SET_HOME_POS: return NO_PARAMS; + case SMART_ACTION_SET_HOME_POS: return sizeof(SmartAction::setHomePos); case SMART_ACTION_SET_HEALTH_REGEN: return sizeof(SmartAction::setHealthRegen); case SMART_ACTION_SET_ROOT: return sizeof(SmartAction::setRoot); case SMART_ACTION_SET_GO_FLAG: return sizeof(SmartAction::goFlag); From 22b6c35d23d35227d7a59b70399693e51a5153c5 Mon Sep 17 00:00:00 2001 From: temperrr Date: Sat, 23 Jul 2022 15:29:21 +0200 Subject: [PATCH 057/130] =?UTF-8?q?fix(DB/SAI):=20Sunhawk=20Reclaimer=20sh?= =?UTF-8?q?ould=20not=20cast=20Frost=20Ar=E2=80=A6=20(#12450)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fix(SmartScript/Creature): Sunhawk Reclaimer should not cast Frost Armor on aggro. --- data/sql/updates/pending_db_world/sunhawkreclaimer.sql | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 data/sql/updates/pending_db_world/sunhawkreclaimer.sql diff --git a/data/sql/updates/pending_db_world/sunhawkreclaimer.sql b/data/sql/updates/pending_db_world/sunhawkreclaimer.sql new file mode 100644 index 000000000..4eeabc4e7 --- /dev/null +++ b/data/sql/updates/pending_db_world/sunhawkreclaimer.sql @@ -0,0 +1,5 @@ +UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 17606; + +DELETE FROM `smart_scripts` WHERE (`entryorguid` = 17606) AND (`source_type` = 0) AND (`id` IN (1, 2)); +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(17606, 0, 1, 0, 0, 0, 100, 0, 0, 3000, 4500, 5000, 0, 11, 19816, 64, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Sunhawk Reclaimer - IC - Cast Fireball'); From 474fede553fafe99e8f1b8d76116736b87cbac50 Mon Sep 17 00:00:00 2001 From: AzerothCoreBot Date: Sat, 23 Jul 2022 13:31:24 +0000 Subject: [PATCH 058/130] chore(DB): import pending files Referenced commit(s): 22b6c35d23d35227d7a59b70399693e51a5153c5 --- .../sunhawkreclaimer.sql => db_world/2022_07_23_00.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/sunhawkreclaimer.sql => db_world/2022_07_23_00.sql} (94%) diff --git a/data/sql/updates/pending_db_world/sunhawkreclaimer.sql b/data/sql/updates/db_world/2022_07_23_00.sql similarity index 94% rename from data/sql/updates/pending_db_world/sunhawkreclaimer.sql rename to data/sql/updates/db_world/2022_07_23_00.sql index 4eeabc4e7..04e8a96a2 100644 --- a/data/sql/updates/pending_db_world/sunhawkreclaimer.sql +++ b/data/sql/updates/db_world/2022_07_23_00.sql @@ -1,3 +1,4 @@ +-- DB update 2022_07_22_00 -> 2022_07_23_00 UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 17606; DELETE FROM `smart_scripts` WHERE (`entryorguid` = 17606) AND (`source_type` = 0) AND (`id` IN (1, 2)); From 0b0a14258026d7c64d432756febab1c90e6d093a Mon Sep 17 00:00:00 2001 From: UltraNix <80540499+UltraNix@users.noreply.github.com> Date: Sat, 23 Jul 2022 18:12:07 +0200 Subject: [PATCH 059/130] =?UTF-8?q?feat(Core/Entities):=20Enabled=20loadin?= =?UTF-8?q?g=20basic=20stats=20for=20players,=20pets=20an=E2=80=A6=20(#123?= =?UTF-8?q?94)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat(Core/Entities): Enabled loading basic stats for players, pets and items from database as 32 bit integers. Closes #12386 --- .../rev_1657957555774947100.sql | 45 ++++++++++++++++++ src/server/game/Entities/Player/Player.h | 13 ++++-- src/server/game/Globals/ObjectMgr.cpp | 46 +++++++++---------- src/server/game/Globals/ObjectMgr.h | 15 +++--- 4 files changed, 85 insertions(+), 34 deletions(-) create mode 100644 data/sql/updates/pending_db_world/rev_1657957555774947100.sql diff --git a/data/sql/updates/pending_db_world/rev_1657957555774947100.sql b/data/sql/updates/pending_db_world/rev_1657957555774947100.sql new file mode 100644 index 000000000..66a58a3ec --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1657957555774947100.sql @@ -0,0 +1,45 @@ +-- +ALTER TABLE `pet_levelstats` CHANGE `hp` `hp` INT UNSIGNED DEFAULT 0 NOT NULL, +CHANGE `mana` `mana` INT UNSIGNED DEFAULT 0 NOT NULL, +CHANGE `str` `str` INT UNSIGNED DEFAULT 0 NOT NULL, +CHANGE `agi` `agi` INT UNSIGNED DEFAULT 0 NOT NULL, +CHANGE `sta` `sta` INT UNSIGNED DEFAULT 0 NOT NULL, +CHANGE `inte` `inte` INT UNSIGNED DEFAULT 0 NOT NULL, +CHANGE `spi` `spi` INT UNSIGNED DEFAULT 0 NOT NULL, +CHANGE `min_dmg` `min_dmg` INT UNSIGNED DEFAULT 0 NOT NULL, +CHANGE `max_dmg` `max_dmg` INT UNSIGNED DEFAULT 0 NOT NULL; + +ALTER TABLE `player_classlevelstats` CHANGE `basehp` `basehp` INT UNSIGNED DEFAULT 1 NOT NULL, +CHANGE `basemana` `basemana` INT UNSIGNED DEFAULT 1 NOT NULL; + +ALTER TABLE `player_levelstats` CHANGE `str` `str` INT UNSIGNED DEFAULT 0 NOT NULL, +CHANGE `agi` `agi` INT UNSIGNED DEFAULT 0 NOT NULL, +CHANGE `sta` `sta` INT UNSIGNED DEFAULT 0 NOT NULL, +CHANGE `inte` `inte` INT UNSIGNED DEFAULT 0 NOT NULL, +CHANGE `spi` `spi` INT UNSIGNED DEFAULT 0 NOT NULL; + +ALTER TABLE `creature_classlevelstats` CHANGE `basehp0` `basehp0` INT UNSIGNED DEFAULT 1 NOT NULL, +CHANGE `basehp1` `basehp1` INT UNSIGNED DEFAULT 1 NOT NULL, +CHANGE `basehp2` `basehp2` INT UNSIGNED DEFAULT 1 NOT NULL, +CHANGE `basemana` `basemana` INT UNSIGNED DEFAULT 0 NOT NULL, +CHANGE `basearmor` `basearmor` INT UNSIGNED DEFAULT 1 NOT NULL, +CHANGE `attackpower` `attackpower` INT UNSIGNED DEFAULT 0 NOT NULL, +CHANGE `rangedattackpower` `rangedattackpower` INT UNSIGNED DEFAULT 0 NOT NULL; + +ALTER TABLE `item_template` CHANGE `stat_value1` `stat_value1` INT DEFAULT 0 NOT NULL, +CHANGE `stat_value2` `stat_value2` INT DEFAULT 0 NOT NULL, +CHANGE `stat_value3` `stat_value3` INT DEFAULT 0 NOT NULL, +CHANGE `stat_value4` `stat_value4` INT DEFAULT 0 NOT NULL, +CHANGE `stat_value5` `stat_value5` INT DEFAULT 0 NOT NULL, +CHANGE `stat_value6` `stat_value6` INT DEFAULT 0 NOT NULL, +CHANGE `stat_value7` `stat_value7` INT DEFAULT 0 NOT NULL, +CHANGE `stat_value8` `stat_value8` INT DEFAULT 0 NOT NULL, +CHANGE `stat_value9` `stat_value9` INT DEFAULT 0 NOT NULL, +CHANGE `stat_value10` `stat_value10` INT DEFAULT 0 NOT NULL, +CHANGE `armor` `armor` INT UNSIGNED DEFAULT 0 NOT NULL, +CHANGE `holy_res` `holy_res` INT UNSIGNED DEFAULT 0 NOT NULL, +CHANGE `fire_res` `fire_res` INT UNSIGNED DEFAULT 0 NOT NULL, +CHANGE `nature_res` `nature_res` INT UNSIGNED DEFAULT 0 NOT NULL, +CHANGE `frost_res` `frost_res` INT UNSIGNED DEFAULT 0 NOT NULL, +CHANGE `shadow_res` `shadow_res` INT UNSIGNED DEFAULT 0 NOT NULL, +CHANGE `arcane_res` `arcane_res` INT UNSIGNED DEFAULT 0 NOT NULL; diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index 1ab612d5d..7a5b10271 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -289,8 +289,8 @@ typedef std::list PlayerCreateInfoItems; struct PlayerClassLevelInfo { PlayerClassLevelInfo() = default; - uint16 basehealth{0}; - uint16 basemana{0}; + uint32 basehealth{0}; + uint32 basemana{0}; }; struct PlayerClassInfo @@ -302,9 +302,12 @@ struct PlayerClassInfo struct PlayerLevelInfo { - PlayerLevelInfo() { for (unsigned char & stat : stats) stat = 0; } + PlayerLevelInfo() + { + stats.fill(0); + } - uint8 stats[MAX_STATS]; + std::array stats = { }; }; typedef std::list PlayerCreateInfoSpells; @@ -2729,7 +2732,7 @@ public: ActionButtonList m_actionButtons; float m_auraBaseMod[BASEMOD_END][MOD_END]; - int16 m_baseRatingValue[MAX_COMBAT_RATING]; + int32 m_baseRatingValue[MAX_COMBAT_RATING]; uint32 m_baseSpellPower; uint32 m_baseFeralAP; uint32 m_baseManaRegen; diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index ca63485ba..c82efc403 100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -2678,7 +2678,7 @@ void ObjectMgr::LoadItemTemplates() for (uint8 i = 0; i < itemTemplate.StatsCount; ++i) { itemTemplate.ItemStat[i].ItemStatType = uint32(fields[28 + i * 2].Get()); - itemTemplate.ItemStat[i].ItemStatValue = int32(fields[29 + i * 2].Get()); + itemTemplate.ItemStat[i].ItemStatValue = fields[29 + i * 2].Get(); } itemTemplate.ScalingStatDistribution = uint32(fields[48].Get()); @@ -2691,13 +2691,13 @@ void ObjectMgr::LoadItemTemplates() itemTemplate.Damage[i].DamageType = uint32(fields[52 + i * 3].Get()); } - itemTemplate.Armor = uint32(fields[56].Get()); - itemTemplate.HolyRes = uint32(fields[57].Get()); - itemTemplate.FireRes = uint32(fields[58].Get()); - itemTemplate.NatureRes = uint32(fields[59].Get()); - itemTemplate.FrostRes = uint32(fields[60].Get()); - itemTemplate.ShadowRes = uint32(fields[61].Get()); - itemTemplate.ArcaneRes = uint32(fields[62].Get()); + itemTemplate.Armor = fields[56].Get(); + itemTemplate.HolyRes = fields[57].Get(); + itemTemplate.FireRes = fields[58].Get(); + itemTemplate.NatureRes = fields[59].Get(); + itemTemplate.FrostRes = fields[60].Get(); + itemTemplate.ShadowRes = fields[61].Get(); + itemTemplate.ArcaneRes = fields[62].Get(); itemTemplate.Delay = uint32(fields[63].Get()); itemTemplate.AmmoType = uint32(fields[64].Get()); itemTemplate.RangedModRange = fields[65].Get(); @@ -3448,14 +3448,14 @@ void ObjectMgr::LoadPetLevelInfo() // data for level 1 stored in [0] array element, ... PetLevelInfo* pLevelInfo = &pInfoMapEntry[current_level - 1]; - pLevelInfo->health = fields[2].Get(); - pLevelInfo->mana = fields[3].Get(); + pLevelInfo->health = fields[2].Get(); + pLevelInfo->mana = fields[3].Get(); pLevelInfo->armor = fields[9].Get(); - pLevelInfo->min_dmg = fields[10].Get(); - pLevelInfo->max_dmg = fields[11].Get(); - for (int i = 0; i < MAX_STATS; i++) + pLevelInfo->min_dmg = fields[10].Get(); + pLevelInfo->max_dmg = fields[11].Get(); + for (uint8 i = 0; i < MAX_STATS; i++) { - pLevelInfo->stats[i] = fields[i + 4].Get(); + pLevelInfo->stats[i] = fields[i + 4].Get(); } ++count; @@ -3973,8 +3973,8 @@ void ObjectMgr::LoadPlayerInfo() PlayerClassLevelInfo& levelInfo = info->levelInfo[current_level - 1]; - levelInfo.basehealth = fields[2].Get(); - levelInfo.basemana = fields[3].Get(); + levelInfo.basehealth = fields[2].Get(); + levelInfo.basemana = fields[3].Get(); ++count; } while (result->NextRow()); @@ -4064,8 +4064,8 @@ void ObjectMgr::LoadPlayerInfo() info->levelInfo = new PlayerLevelInfo[sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL)]; PlayerLevelInfo& levelInfo = info->levelInfo[current_level - 1]; - for (int i = 0; i < MAX_STATS; i++) - levelInfo.stats[i] = fields[i + 3].Get(); + for (uint8 i = 0; i < MAX_STATS; i++) + levelInfo.stats[i] = fields[i + 3].Get(); } ++count; @@ -9359,7 +9359,7 @@ void ObjectMgr::LoadCreatureClassLevelStats() for (uint8 i = 0; i < MAX_EXPANSIONS; ++i) { - stats.BaseHealth[i] = fields[2 + i].Get(); + stats.BaseHealth[i] = fields[2 + i].Get(); if (stats.BaseHealth[i] == 0) { @@ -9389,11 +9389,11 @@ void ObjectMgr::LoadCreatureClassLevelStats() } } - stats.BaseMana = fields[5].Get(); - stats.BaseArmor = fields[6].Get(); + stats.BaseMana = fields[5].Get(); + stats.BaseArmor = fields[6].Get(); - stats.AttackPower = fields[7].Get(); - stats.RangedAttackPower = fields[8].Get(); + stats.AttackPower = fields[7].Get(); + stats.RangedAttackPower = fields[8].Get(); _creatureBaseStatsStore[MAKE_PAIR16(Level, Class)] = stats; diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h index bc2cdd748..88e82db54 100644 --- a/src/server/game/Globals/ObjectMgr.h +++ b/src/server/game/Globals/ObjectMgr.h @@ -520,14 +520,17 @@ typedef std::pair stats = { }; + uint32 health{0}; + uint32 mana{0}; uint32 armor{0}; - uint16 min_dmg{0}; - uint16 max_dmg{0}; + uint32 min_dmg{0}; + uint32 max_dmg{0}; }; struct MailLevelReward From 26079bd5283da4362407d802230089a4cb1a5697 Mon Sep 17 00:00:00 2001 From: AzerothCoreBot Date: Sat, 23 Jul 2022 16:14:20 +0000 Subject: [PATCH 060/130] chore(DB): import pending files Referenced commit(s): 0b0a14258026d7c64d432756febab1c90e6d093a --- .../rev_1657957555774947100.sql => db_world/2022_07_23_01.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/rev_1657957555774947100.sql => db_world/2022_07_23_01.sql} (98%) diff --git a/data/sql/updates/pending_db_world/rev_1657957555774947100.sql b/data/sql/updates/db_world/2022_07_23_01.sql similarity index 98% rename from data/sql/updates/pending_db_world/rev_1657957555774947100.sql rename to data/sql/updates/db_world/2022_07_23_01.sql index 66a58a3ec..5997b7e87 100644 --- a/data/sql/updates/pending_db_world/rev_1657957555774947100.sql +++ b/data/sql/updates/db_world/2022_07_23_01.sql @@ -1,3 +1,4 @@ +-- DB update 2022_07_23_00 -> 2022_07_23_01 -- ALTER TABLE `pet_levelstats` CHANGE `hp` `hp` INT UNSIGNED DEFAULT 0 NOT NULL, CHANGE `mana` `mana` INT UNSIGNED DEFAULT 0 NOT NULL, From c057b539e64606ef3356061634d25209cca2d556 Mon Sep 17 00:00:00 2001 From: Gultask <100873791+Gultask@users.noreply.github.com> Date: Sun, 24 Jul 2022 13:04:07 -0300 Subject: [PATCH 061/130] fix(DB/Creature): Moontouched Owlbeast (7453) (#12344) Create moontouched_owlbeast.sql --- .../updates/pending_db_world/moontouched_owlbeast.sql | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 data/sql/updates/pending_db_world/moontouched_owlbeast.sql diff --git a/data/sql/updates/pending_db_world/moontouched_owlbeast.sql b/data/sql/updates/pending_db_world/moontouched_owlbeast.sql new file mode 100644 index 000000000..7733778e5 --- /dev/null +++ b/data/sql/updates/pending_db_world/moontouched_owlbeast.sql @@ -0,0 +1,11 @@ +UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 7453; + +DELETE FROM `smart_scripts` WHERE (`entryorguid` = 7453) AND (`source_type` = 0) AND (`id` IN (0, 1)); +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(7453, 0, 0, 0, 0, 0, 100, 0, 7000, 11000, 15000, 18000, 0, 11, 15798, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Moontouched Owlbeast - In Combat - Cast \'Moonfire\''), +(7453, 0, 1, 0, 0, 0, 100, 0, 0, 0, 18000, 21000, 0, 11, 12160, 32, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Moontouched Owlbeast - In Combat - Cast \'Rejuvenation\''); + +DELETE FROM `creature_template_spell` WHERE (`CreatureID` = 7453) AND (`Index` IN (0, 1)); +INSERT INTO `creature_template_spell` (`CreatureID`, `Index`, `Spell`, `VerifiedBuild`) VALUES +(7453, 0, 15798, 12340), +(7453, 1, 12160, 12340); From 5bcc54a617f99b5b435360ea83266604dbe23441 Mon Sep 17 00:00:00 2001 From: UltraNix <80540499+UltraNix@users.noreply.github.com> Date: Sun, 24 Jul 2022 18:04:44 +0200 Subject: [PATCH 062/130] fix(Scripts/Spells): Replenishment should trigger only from Mind Blast. (#12503) Fixes #11878 --- src/server/scripts/Spells/spell_priest.cpp | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/src/server/scripts/Spells/spell_priest.cpp b/src/server/scripts/Spells/spell_priest.cpp index 7c92f7ec7..384bee7da 100644 --- a/src/server/scripts/Spells/spell_priest.cpp +++ b/src/server/scripts/Spells/spell_priest.cpp @@ -842,22 +842,17 @@ class spell_pri_vampiric_touch : public AuraScript bool CheckProc(ProcEventInfo& eventInfo) { if (!eventInfo.GetActionTarget() || GetOwner()->GetGUID() != eventInfo.GetActionTarget()->GetGUID()) - return false; - - if (eventInfo.GetTypeMask() & PROC_FLAG_KILLED) { - if (SpellInfo const* spellInfo = eventInfo.GetSpellInfo()) - { - if (spellInfo->SpellFamilyName == SPELLFAMILY_PRIEST && (spellInfo->SpellFamilyFlags[0] & 0x00002000)) - { - return true; - } - } - return false; } - return eventInfo.GetActionTarget()->IsAlive(); + SpellInfo const* spellInfo = eventInfo.GetSpellInfo(); + if (!spellInfo || spellInfo->SpellFamilyName != SPELLFAMILY_PRIEST || !(spellInfo->SpellFamilyFlags[0] & 0x00002000)) + { + return false; + } + + return true; } void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) From f0777d1fd32c75f4bb327d4983ad86efb8e50c0f Mon Sep 17 00:00:00 2001 From: Nefertumm Date: Sun, 24 Jul 2022 13:06:11 -0300 Subject: [PATCH 063/130] fix(Core/AI): validate stored targets (#12489) Co-authored-by: Meji Co-authored-by: Ariel Silva Co-authored-by: Shauren Co-authored-by: Meji Co-authored-by: Ariel Silva Co-authored-by: Shauren --- src/server/game/AI/SmartScripts/SmartAI.cpp | 4 +- .../game/AI/SmartScripts/SmartScript.cpp | 100 +++++++++++++++--- src/server/game/AI/SmartScripts/SmartScript.h | 6 +- .../game/AI/SmartScripts/SmartScriptMgr.h | 11 +- 4 files changed, 98 insertions(+), 23 deletions(-) diff --git a/src/server/game/AI/SmartScripts/SmartAI.cpp b/src/server/game/AI/SmartScripts/SmartAI.cpp index 0b4541985..00d1fbb9f 100644 --- a/src/server/game/AI/SmartScripts/SmartAI.cpp +++ b/src/server/game/AI/SmartScripts/SmartAI.cpp @@ -297,7 +297,7 @@ void SmartAI::EndPath(bool fail) mEscortNPCFlags = 0; } - ObjectVector const* targets = GetScript()->GetStoredTargetVector(SMART_ESCORT_TARGETS); + ObjectVector const* targets = GetScript()->GetStoredTargetVector(SMART_ESCORT_TARGETS, *me); if (targets && mEscortQuestID) { if (targets->size() == 1 && GetScript()->IsPlayer((*targets->begin()))) @@ -535,7 +535,7 @@ void SmartAI::UpdateAI(uint32 diff) bool SmartAI::IsEscortInvokerInRange() { - if (ObjectVector const* targets = GetScript()->GetStoredTargetVector(SMART_ESCORT_TARGETS)) + if (ObjectVector const* targets = GetScript()->GetStoredTargetVector(SMART_ESCORT_TARGETS, *me)) { float checkDist = me->GetInstanceScript() ? SMART_ESCORT_MAX_PLAYER_DIST * 2 : SMART_ESCORT_MAX_PLAYER_DIST; if (targets->size() == 1 && GetScript()->IsPlayer((*targets->begin()))) diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp index 5c304cfab..6e0b8b1ef 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.cpp +++ b/src/server/game/AI/SmartScripts/SmartScript.cpp @@ -2051,7 +2051,15 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u } case SMART_ACTION_SEND_TARGET_TO_TARGET: { - ObjectVector const* storedTargets = GetStoredTargetVector(e.action.sendTargetToTarget.id); + WorldObject* ref = GetBaseObject(); + + if (!ref) + ref = unit; + + if (!ref) + break; + + ObjectVector const* storedTargets = GetStoredTargetVector(e.action.sendTargetToTarget.id, *ref); if (!storedTargets) break; @@ -2919,6 +2927,17 @@ void SmartScript::GetTargets(ObjectVector& targets, SmartScriptHolder const& e, break; case SMART_TARGET_CREATURE_RANGE: { + WorldObject* ref = baseObject; + if (!ref) + ref = scriptTrigger; + + if (!ref) + { + LOG_ERROR("scripts.ai.sai", "SMART_TARGET_CREATURE_RANGE: Entry {} SourceType {} Event {} Action {} Target {} is missing base object or invoker", + e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.GetTargetType()); + break; + } + ObjectVector units; GetWorldObjectsInDist(units, static_cast(e.target.unitRange.maxDist)); @@ -2939,7 +2958,7 @@ void SmartScript::GetTargets(ObjectVector& targets, SmartScriptHolder const& e, continue; } - if (((e.target.unitRange.creature && unit->ToCreature()->GetEntry() == e.target.unitRange.creature) || !e.target.unitRange.creature) && baseObject->IsInRange(unit, (float)e.target.unitRange.minDist, (float)e.target.unitRange.maxDist)) + if (((e.target.unitRange.creature && unit->ToCreature()->GetEntry() == e.target.unitRange.creature) || !e.target.unitRange.creature) && ref->IsInRange(unit, (float)e.target.unitRange.minDist, (float)e.target.unitRange.maxDist)) targets.push_back(unit); } @@ -2994,6 +3013,18 @@ void SmartScript::GetTargets(ObjectVector& targets, SmartScriptHolder const& e, } case SMART_TARGET_GAMEOBJECT_RANGE: { + + WorldObject* ref = baseObject; + if (!ref) + ref = scriptTrigger; + + if (!ref) + { + LOG_ERROR("scripts.ai.sai", "SMART_TARGET_GAMEOBJECT_RANGE: Entry: {} SourceType {} Event {} Action {} Target {} is missing base object or invoker.", + e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.GetTargetType()); + break; + } + ObjectVector units; GetWorldObjectsInDist(units, static_cast(e.target.goRange.maxDist)); @@ -3005,7 +3036,7 @@ void SmartScript::GetTargets(ObjectVector& targets, SmartScriptHolder const& e, if (go && go->GetGUID() == unit->GetGUID()) continue; - if (((e.target.goRange.entry && IsGameObject(unit) && unit->ToGameObject()->GetEntry() == e.target.goRange.entry) || !e.target.goRange.entry) && baseObject->IsInRange((unit), (float)e.target.goRange.minDist, (float)e.target.goRange.maxDist)) + if (((e.target.goRange.entry && IsGameObject(unit) && unit->ToGameObject()->GetEntry() == e.target.goRange.entry) || !e.target.goRange.entry) && ref->IsInRange((unit), (float)e.target.goRange.minDist, (float)e.target.goRange.maxDist)) targets.push_back(unit); } @@ -3015,7 +3046,8 @@ void SmartScript::GetTargets(ObjectVector& targets, SmartScriptHolder const& e, { if (!scriptTrigger && !baseObject) { - LOG_ERROR("scripts.ai.sai", "SMART_TARGET_CREATURE_GUID can not be used without invoker"); + LOG_ERROR("scripts.ai.sai", "SMART_TARGET_CREATURE_GUID: Entry {} SourceType {} Event {} Action {} Target {} is missing base object or invoker.", + e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.GetTargetType()); break; } @@ -3028,7 +3060,8 @@ void SmartScript::GetTargets(ObjectVector& targets, SmartScriptHolder const& e, { if (!scriptTrigger && !GetBaseObject()) { - LOG_ERROR("scripts.ai.sai", "SMART_TARGET_GAMEOBJECT_GUID can not be used without invoker"); + LOG_ERROR("scripts.ai.sai", "SMART_TARGET_GAMEOBJECT_GUID: Entry {} SourceType {} Event {} Action {} Target {} is missing base object or invoker.", + e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.GetTargetType()); break; } @@ -3060,32 +3093,75 @@ void SmartScript::GetTargets(ObjectVector& targets, SmartScriptHolder const& e, } case SMART_TARGET_STORED: { - if (ObjectVector const* stored = GetStoredTargetVector(e.target.stored.id)) + WorldObject* ref = baseObject; + if (!ref) + ref = scriptTrigger; + + if (!ref) + { + LOG_ERROR("scripts.ai.sai", "SMART_TARGET_STORED: Entry {} SourceType {} Event {} Action {} Target {} is missing base object or invoker.", + e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.GetTargetType()); + break; + } + + if (ObjectVector const* stored = GetStoredTargetVector(e.target.stored.id, *ref)) targets.assign(stored->begin(), stored->end()); break; } case SMART_TARGET_CLOSEST_CREATURE: { - Creature* target = GetClosestCreatureWithEntry(GetBaseObject(), e.target.unitClosest.entry, (float)(e.target.unitClosest.dist ? e.target.unitClosest.dist : 100), !e.target.unitClosest.dead); + WorldObject* ref = baseObject; + + if (!ref) + ref = scriptTrigger; + + if (!ref) + { + LOG_ERROR("scripts.ai.sai", "SMART_TARGET_CLOSEST_CREATURE: Entry {} SourceType {} Event {} Action {} Target {} is missing base object or invoker.", + e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.GetTargetType()); + break; + } + + Creature* target = GetClosestCreatureWithEntry(ref, e.target.unitClosest.entry, (float)(e.target.unitClosest.dist ? e.target.unitClosest.dist : 100), !e.target.unitClosest.dead); if (target) targets.push_back(target); break; } case SMART_TARGET_CLOSEST_GAMEOBJECT: { - GameObject* target = GetClosestGameObjectWithEntry(GetBaseObject(), e.target.goClosest.entry, (float)(e.target.goClosest.dist ? e.target.goClosest.dist : 100), e.target.goClosest.onlySpawned); + WorldObject* ref = baseObject; + + if (!ref) + ref = scriptTrigger; + + if (!ref) + { + LOG_ERROR("scripts.ai.sai", "SMART_TARGET_CLOSEST_GAMEOBJECT: Entry {} SourceType {} Event {} Action {} Target {} is missing base object or invoker.", + e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.GetTargetType()); + break; + } + + GameObject* target = GetClosestGameObjectWithEntry(ref, e.target.goClosest.entry, (float)(e.target.goClosest.dist ? e.target.goClosest.dist : 100), e.target.goClosest.onlySpawned); if (target) targets.push_back(target); break; } case SMART_TARGET_CLOSEST_PLAYER: { - if (WorldObject* obj = GetBaseObject()) + WorldObject* ref = baseObject; + + if (!ref) + ref = scriptTrigger; + + if (!ref) { - Player* target = obj->SelectNearestPlayer((float)e.target.playerDistance.dist); - if (target) - targets.push_back(target); + LOG_ERROR("scripts.ai.sai", "SMART_TARGET_CLOSEST_PLAYER: Entry {} SourceType {} Event {} Action {} Target {} is missing base object or invoker.", + e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.GetTargetType()); + break; } + + if (Player* target = ref->SelectNearestPlayer((float)e.target.playerDistance.dist)) + targets.push_back(target); break; } case SMART_TARGET_OWNER_OR_SUMMONER: diff --git a/src/server/game/AI/SmartScripts/SmartScript.h b/src/server/game/AI/SmartScripts/SmartScript.h index 4cf33a56e..92142ec35 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.h +++ b/src/server/game/AI/SmartScripts/SmartScript.h @@ -80,7 +80,7 @@ public: { // insert or replace _storedTargets.erase(id); - _storedTargets.emplace(id, ObjectGuidVector(GetBaseObject(), targets)); + _storedTargets.emplace(id, ObjectGuidVector(targets)); } bool IsSmart(Creature* c = nullptr) @@ -112,11 +112,11 @@ public: return smart; } - ObjectVector const* GetStoredTargetVector(uint32 id) const + ObjectVector const* GetStoredTargetVector(uint32 id, WorldObject const& ref) const { auto itr = _storedTargets.find(id); if (itr != _storedTargets.end()) - return itr->second.GetObjectVector(); + return itr->second.GetObjectVector(ref); return nullptr; } diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.h b/src/server/game/AI/SmartScripts/SmartScriptMgr.h index 1c3f500ec..5bb07ec3e 100644 --- a/src/server/game/AI/SmartScripts/SmartScriptMgr.h +++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.h @@ -1785,34 +1785,33 @@ typedef std::vector ObjectVector; class ObjectGuidVector { public: - ObjectGuidVector(WorldObject* baseObject, ObjectVector const& objectVector) : _baseObject(baseObject), _objectVector(objectVector) + explicit ObjectGuidVector(ObjectVector const& objectVector) : _objectVector(objectVector) { _guidVector.reserve(_objectVector.size()); for (WorldObject* obj : _objectVector) _guidVector.push_back(obj->GetGUID()); } - ObjectVector const* GetObjectVector() const + ObjectVector const* GetObjectVector(WorldObject const& ref) const { - UpdateObjects(); + UpdateObjects(ref); return &_objectVector; } ~ObjectGuidVector() { } private: - WorldObject* const _baseObject; mutable ObjectVector _objectVector; GuidVector _guidVector; //sanitize vector using _guidVector - void UpdateObjects() const + void UpdateObjects(WorldObject const& ref) const { _objectVector.clear(); for (ObjectGuid const& guid : _guidVector) - if (WorldObject* obj = ObjectAccessor::GetWorldObject(*_baseObject, guid)) + if (WorldObject* obj = ObjectAccessor::GetWorldObject(ref, guid)) _objectVector.push_back(obj); } }; From 5b0896577f387d66bf1b8cfec523ac771d967773 Mon Sep 17 00:00:00 2001 From: Nefertumm Date: Sun, 24 Jul 2022 13:06:36 -0300 Subject: [PATCH 064/130] fix(Core): Crash on smart event: near players (#12479) --- src/server/game/AI/SmartScripts/SmartScript.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp index 6e0b8b1ef..9df81a469 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.cpp +++ b/src/server/game/AI/SmartScripts/SmartScript.cpp @@ -3945,7 +3945,7 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui if (!units.empty()) { - if (unit->GetTypeId() != TYPEID_PLAYER) + if (!unit || unit->GetTypeId() != TYPEID_PLAYER) return; if (units.size() >= e.event.nearPlayer.minCount) @@ -3961,7 +3961,7 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui if (!units.empty()) { - if (unit->GetTypeId() != TYPEID_PLAYER) + if (!unit || unit->GetTypeId() != TYPEID_PLAYER) return; if (units.size() < e.event.nearPlayerNegation.minCount) From aa39e6ab86aa7cd720a1718a3fde1a325a28058d Mon Sep 17 00:00:00 2001 From: AzerothCoreBot Date: Sun, 24 Jul 2022 16:08:53 +0000 Subject: [PATCH 065/130] chore(DB): import pending files Referenced commit(s): 5b0896577f387d66bf1b8cfec523ac771d967773 --- .../moontouched_owlbeast.sql => db_world/2022_07_24_00.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/moontouched_owlbeast.sql => db_world/2022_07_24_00.sql} (96%) diff --git a/data/sql/updates/pending_db_world/moontouched_owlbeast.sql b/data/sql/updates/db_world/2022_07_24_00.sql similarity index 96% rename from data/sql/updates/pending_db_world/moontouched_owlbeast.sql rename to data/sql/updates/db_world/2022_07_24_00.sql index 7733778e5..d4530dbdf 100644 --- a/data/sql/updates/pending_db_world/moontouched_owlbeast.sql +++ b/data/sql/updates/db_world/2022_07_24_00.sql @@ -1,3 +1,4 @@ +-- DB update 2022_07_23_01 -> 2022_07_24_00 UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 7453; DELETE FROM `smart_scripts` WHERE (`entryorguid` = 7453) AND (`source_type` = 0) AND (`id` IN (0, 1)); From 801e68b1dda6708d1ee20297d27f7ec553bc9948 Mon Sep 17 00:00:00 2001 From: UltraNix <80540499+UltraNix@users.noreply.github.com> Date: Sun, 24 Jul 2022 18:10:41 +0200 Subject: [PATCH 066/130] fix(Core/Creatures): Added new AI function `OnTeleportUnreacheablePlayer` to teleport all unreachable players. (#12193) * fix(Core/Creatures): Implemented CREATURE_FLAG_EXTRA_TELEPORT_UNREACHABLE_PLAYERS. Fixed #11750 * Update. * Update. * Update. --- src/server/game/AI/CreatureAI.cpp | 2 +- src/server/game/AI/CreatureAI.h | 3 + src/server/game/Combat/ThreatMgr.cpp | 8 +- src/server/game/Combat/ThreatMgr.h | 1 + .../game/Entities/Creature/Creature.cpp | 395 ++++++++++-------- src/server/game/Entities/Creature/Creature.h | 9 +- .../game/Entities/Creature/CreatureData.h | 3 +- .../TargetedMovementGenerator.cpp | 38 +- .../ZulGurub/boss_mandokir.cpp | 6 + 9 files changed, 274 insertions(+), 191 deletions(-) diff --git a/src/server/game/AI/CreatureAI.cpp b/src/server/game/AI/CreatureAI.cpp index 46ce5b842..e310de645 100644 --- a/src/server/game/AI/CreatureAI.cpp +++ b/src/server/game/AI/CreatureAI.cpp @@ -306,7 +306,7 @@ bool CreatureAI::_EnterEvadeMode(EvadeReason /*why*/) me->SetLootRecipient(nullptr); me->ResetPlayerDamageReq(); me->SetLastDamagedTime(0); - me->SetCannotReachTarget(false); + me->SetCannotReachTarget(); if (me->IsInEvadeMode()) { diff --git a/src/server/game/AI/CreatureAI.h b/src/server/game/AI/CreatureAI.h index a85638975..6db1fa404 100644 --- a/src/server/game/AI/CreatureAI.h +++ b/src/server/game/AI/CreatureAI.h @@ -88,6 +88,7 @@ public: EVADE_REASON_NO_HOSTILES, // the creature's threat list is empty EVADE_REASON_BOUNDARY, // the creature has moved outside its evade boundary EVADE_REASON_SEQUENCE_BREAK, // this is a boss and the pre-requisite encounters for engaging it are not defeated yet + EVADE_REASON_NO_PATH, // the creature was unable to reach its target for over 5 seconds EVADE_REASON_OTHER }; @@ -210,6 +211,8 @@ public: virtual void CalculateThreat(Unit* /*hatedUnit*/, float& /*threat*/, SpellInfo const* /*threatSpell*/) { } + virtual bool OnTeleportUnreacheablePlayer(Player* /*player*/) { return false; } + protected: virtual void MoveInLineOfSight(Unit* /*who*/); diff --git a/src/server/game/Combat/ThreatMgr.cpp b/src/server/game/Combat/ThreatMgr.cpp index 87af1c4d4..7cbbcd94d 100644 --- a/src/server/game/Combat/ThreatMgr.cpp +++ b/src/server/game/Combat/ThreatMgr.cpp @@ -261,12 +261,18 @@ HostileReference* ThreatContainer::getReferenceByTarget(Unit* victim) const if (!victim) return nullptr; - ObjectGuid const guid = victim->GetGUID(); + return getReferenceByTarget(victim->GetGUID()); +} + +HostileReference* ThreatContainer::getReferenceByTarget(ObjectGuid const& guid) const +{ for (ThreatContainer::StorageType::const_iterator i = iThreatList.begin(); i != iThreatList.end(); ++i) { HostileReference* ref = (*i); if (ref && ref->getUnitGuid() == guid) + { return ref; + } } return nullptr; diff --git a/src/server/game/Combat/ThreatMgr.h b/src/server/game/Combat/ThreatMgr.h index 5f87b094c..6844b08d1 100644 --- a/src/server/game/Combat/ThreatMgr.h +++ b/src/server/game/Combat/ThreatMgr.h @@ -164,6 +164,7 @@ public: } HostileReference* getReferenceByTarget(Unit* victim) const; + HostileReference* getReferenceByTarget(ObjectGuid const& guid) const; [[nodiscard]] StorageType const& getThreatList() const { return iThreatList; } diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index ecacbf3b3..772d74cc9 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -220,7 +220,7 @@ Creature::Creature(bool isWorldObject): Unit(isWorldObject), MovableMapObject(), m_transportCheckTimer(1000), lootPickPocketRestoreTime(0), m_reactState(REACT_AGGRESSIVE), m_defaultMovementType(IDLE_MOTION_TYPE), m_spawnId(0), m_equipmentId(0), m_originalEquipmentId(0), m_AlreadyCallAssistance(false), m_AlreadySearchedAssistance(false), m_regenHealth(true), m_AI_locked(false), m_meleeDamageSchoolMask(SPELL_SCHOOL_MASK_NORMAL), m_originalEntry(0), m_moveInLineOfSightDisabled(false), m_moveInLineOfSightStrictlyDisabled(false), - m_homePosition(), m_transportHomePosition(), m_creatureInfo(nullptr), m_creatureData(nullptr), m_detectionDistance(20.0f), m_waypointID(0), m_path_id(0), m_formation(nullptr), _lastDamagedTime(nullptr), m_cannotReachTarget(false), m_cannotReachTimer(0), + m_homePosition(), m_transportHomePosition(), m_creatureInfo(nullptr), m_creatureData(nullptr), m_detectionDistance(20.0f), m_waypointID(0), m_path_id(0), m_formation(nullptr), _lastDamagedTime(nullptr), m_cannotReachTimer(0), _isMissingSwimmingFlagOutOfCombat(false), m_assistanceTimer(0), _playerDamageReq(0), _damagedByPlayer(false) { m_regenTimer = CREATURE_REGEN_INTERVAL; @@ -628,207 +628,238 @@ void Creature::Update(uint32 diff) LOG_ERROR("entities.unit", "Creature ({}) in wrong state: JUST_DEAD (1)", GetGUID().ToString()); break; case DEAD: + { + time_t now = GameTime::GetGameTime().count(); + if (m_respawnTime <= now) { - time_t now = GameTime::GetGameTime().count(); - if (m_respawnTime <= now) + + ConditionList conditions = sConditionMgr->GetConditionsForNotGroupedEntry(CONDITION_SOURCE_TYPE_CREATURE_RESPAWN, GetEntry()); + + if (!sConditionMgr->IsObjectMeetToConditions(this, conditions)) { - - ConditionList conditions = sConditionMgr->GetConditionsForNotGroupedEntry(CONDITION_SOURCE_TYPE_CREATURE_RESPAWN, GetEntry()); - - if (!sConditionMgr->IsObjectMeetToConditions(this, conditions)) - { - // Creature should not respawn, reset respawn timer. Conditions will be checked again the next time it tries to respawn. - m_respawnTime = GameTime::GetGameTime().count() + m_respawnDelay; - break; - } - - bool allowed = !IsAIEnabled || AI()->CanRespawn(); // First check if there are any scripts that prevent us respawning - if (!allowed) // Will be rechecked on next Update call - break; - - ObjectGuid dbtableHighGuid = ObjectGuid::Create(GetEntry(), m_spawnId); - time_t linkedRespawntime = GetMap()->GetLinkedRespawnTime(dbtableHighGuid); - if (!linkedRespawntime) // Can respawn - Respawn(); - else // the master is dead - { - ObjectGuid targetGuid = sObjectMgr->GetLinkedRespawnGuid(dbtableHighGuid); - if (targetGuid == dbtableHighGuid) // if linking self, never respawn (check delayed to next day) - SetRespawnTime(DAY); - else - m_respawnTime = (now > linkedRespawntime ? now : linkedRespawntime) + urand(5, MINUTE); // else copy time from master and add a little - SaveRespawnTime(); // also save to DB immediately - } + // Creature should not respawn, reset respawn timer. Conditions will be checked again the next time it tries to respawn. + m_respawnTime = GameTime::GetGameTime().count() + m_respawnDelay; + break; + } + + bool allowed = !IsAIEnabled || AI()->CanRespawn(); // First check if there are any scripts that prevent us respawning + if (!allowed) // Will be rechecked on next Update call + break; + + ObjectGuid dbtableHighGuid = ObjectGuid::Create(GetEntry(), m_spawnId); + time_t linkedRespawntime = GetMap()->GetLinkedRespawnTime(dbtableHighGuid); + if (!linkedRespawntime) // Can respawn + Respawn(); + else // the master is dead + { + ObjectGuid targetGuid = sObjectMgr->GetLinkedRespawnGuid(dbtableHighGuid); + if (targetGuid == dbtableHighGuid) // if linking self, never respawn (check delayed to next day) + SetRespawnTime(DAY); + else + m_respawnTime = (now > linkedRespawntime ? now : linkedRespawntime) + urand(5, MINUTE); // else copy time from master and add a little + SaveRespawnTime(); // also save to DB immediately } - break; } + break; + } case CORPSE: - { - Unit::Update(diff); - // deathstate changed on spells update, prevent problems - if (m_deathState != CORPSE) - break; - - if (m_groupLootTimer && lootingGroupLowGUID) - { - if (m_groupLootTimer <= diff) - { - Group* group = sGroupMgr->GetGroupByGUID(lootingGroupLowGUID); - if (group) - group->EndRoll(&loot, GetMap()); - m_groupLootTimer = 0; - lootingGroupLowGUID = 0; - } - else - { - m_groupLootTimer -= diff; - } - } - else if (m_corpseRemoveTime <= GameTime::GetGameTime().count()) - { - RemoveCorpse(false); - LOG_DEBUG("entities.unit", "Removing corpse... {} ", GetUInt32Value(OBJECT_FIELD_ENTRY)); - } + { + Unit::Update(diff); + // deathstate changed on spells update, prevent problems + if (m_deathState != CORPSE) break; - } - case ALIVE: + + if (m_groupLootTimer && lootingGroupLowGUID) { - Unit::Update(diff); - - // creature can be dead after Unit::Update call - // CORPSE/DEAD state will processed at next tick (in other case death timer will be updated unexpectedly) - if (!IsAlive()) - break; - - // if creature is charmed, switch to charmed AI - if (NeedChangeAI) + if (m_groupLootTimer <= diff) { - UpdateCharmAI(); - NeedChangeAI = false; - IsAIEnabled = true; + Group* group = sGroupMgr->GetGroupByGUID(lootingGroupLowGUID); + if (group) + group->EndRoll(&loot, GetMap()); + m_groupLootTimer = 0; + lootingGroupLowGUID = 0; + } + else + { + m_groupLootTimer -= diff; + } + } + else if (m_corpseRemoveTime <= GameTime::GetGameTime().count()) + { + RemoveCorpse(false); + LOG_DEBUG("entities.unit", "Removing corpse... {} ", GetUInt32Value(OBJECT_FIELD_ENTRY)); + } + break; + } + case ALIVE: + { + Unit::Update(diff); - // xinef: update combat state, if npc is not in combat - return to spawn correctly by calling EnterEvadeMode - SelectVictim(); + // creature can be dead after Unit::Update call + // CORPSE/DEAD state will processed at next tick (in other case death timer will be updated unexpectedly) + if (!IsAlive()) + break; + + // if creature is charmed, switch to charmed AI + if (NeedChangeAI) + { + UpdateCharmAI(); + NeedChangeAI = false; + IsAIEnabled = true; + + // xinef: update combat state, if npc is not in combat - return to spawn correctly by calling EnterEvadeMode + SelectVictim(); + } + + // periodic check to see if the creature has passed an evade boundary + if (IsAIEnabled && !IsInEvadeMode() && IsEngaged()) + { + if (diff >= m_boundaryCheckTime) + { + AI()->CheckInRoom(); + m_boundaryCheckTime = 2500; + } + else + m_boundaryCheckTime -= diff; + } + + Unit* owner = GetCharmerOrOwner(); + if (IsCharmed() && !IsWithinDistInMap(owner, GetMap()->GetVisibilityRange(), true, false)) + { + RemoveCharmAuras(); + } + + if (Unit* victim = GetVictim()) + { + // If we are closer than 50% of the combat reach we are going to reposition the victim + if (diff >= m_moveBackwardsMovementTime) + { + float MaxRange = GetCollisionRadius() + GetVictim()->GetCollisionRadius(); + + if (IsInDist(victim, MaxRange)) + AI()->MoveBackwardsChecks(); + + m_moveBackwardsMovementTime = urand(MOVE_BACKWARDS_CHECK_INTERVAL, MOVE_BACKWARDS_CHECK_INTERVAL * 3); + } + else + { + m_moveBackwardsMovementTime -= diff; } - // periodic check to see if the creature has passed an evade boundary - if (IsAIEnabled && !IsInEvadeMode() && IsEngaged()) + // Circling the target + if (diff >= m_moveCircleMovementTime) { - if (diff >= m_boundaryCheckTime) - { - AI()->CheckInRoom(); - m_boundaryCheckTime = 2500; - } else - m_boundaryCheckTime -= diff; + AI()->MoveCircleChecks(); + m_moveCircleMovementTime = urand(MOVE_CIRCLE_CHECK_INTERVAL, MOVE_CIRCLE_CHECK_INTERVAL * 2); } - - Unit* owner = GetCharmerOrOwner(); - if (IsCharmed() && !IsWithinDistInMap(owner, GetMap()->GetVisibilityRange(), true, false)) + else { - RemoveCharmAuras(); + m_moveCircleMovementTime -= diff; } + } - if (Unit *victim = GetVictim()) + // Call for assistance if not disabled + if (m_assistanceTimer) + { + if (m_assistanceTimer <= diff) { - // If we are closer than 50% of the combat reach we are going to reposition the victim - if (diff >= m_moveBackwardsMovementTime) + if (CanPeriodicallyCallForAssistance()) { - float MaxRange = GetCollisionRadius() + GetVictim()->GetCollisionRadius(); - - if (IsInDist(victim, MaxRange)) - AI()->MoveBackwardsChecks(); - - m_moveBackwardsMovementTime = urand(MOVE_BACKWARDS_CHECK_INTERVAL, MOVE_BACKWARDS_CHECK_INTERVAL * 3); - } - else - { - m_moveBackwardsMovementTime -= diff; - } - - // Circling the target - if (diff >= m_moveCircleMovementTime) - { - AI()->MoveCircleChecks(); - m_moveCircleMovementTime = urand(MOVE_CIRCLE_CHECK_INTERVAL, MOVE_CIRCLE_CHECK_INTERVAL * 2); - } - else - { - m_moveCircleMovementTime -= diff; + SetNoCallAssistance(false); + CallAssistance(); } + m_assistanceTimer = sWorld->getIntConfig(CONFIG_CREATURE_FAMILY_ASSISTANCE_PERIOD); } - - // Call for assistance if not disabled - if (m_assistanceTimer) + else { - if (m_assistanceTimer <= diff) + m_assistanceTimer -= diff; + } + } + + if (!IsInEvadeMode() && IsAIEnabled) + { + // do not allow the AI to be changed during update + m_AI_locked = true; + i_AI->UpdateAI(diff); + m_AI_locked = false; + } + + // creature can be dead after UpdateAI call + // CORPSE/DEAD state will processed at next tick (in other case death timer will be updated unexpectedly) + if (!IsAlive()) + break; + + m_regenTimer -= diff; + if (m_regenTimer <= 0) + { + if (!IsInEvadeMode()) + { + // regenerate health if not in combat or if polymorphed) + if (!IsInCombat() || IsPolymorphed()) + RegenerateHealth(); + else if (IsNotReachableAndNeedRegen()) { - if (CanPeriodicallyCallForAssistance()) + // regenerate health if cannot reach the target and the setting is set to do so. + // this allows to disable the health regen of raid bosses if pathfinding has issues for whatever reason + if (sWorld->getBoolConfig(CONFIG_REGEN_HP_CANNOT_REACH_TARGET_IN_RAID) || !GetMap()->IsRaid()) { - SetNoCallAssistance(false); - CallAssistance(); - } - m_assistanceTimer = sWorld->getIntConfig(CONFIG_CREATURE_FAMILY_ASSISTANCE_PERIOD); - } - else - { - m_assistanceTimer -= diff; - } - } - - if (!IsInEvadeMode() && IsAIEnabled) - { - // do not allow the AI to be changed during update - m_AI_locked = true; - i_AI->UpdateAI(diff); - m_AI_locked = false; - } - - // creature can be dead after UpdateAI call - // CORPSE/DEAD state will processed at next tick (in other case death timer will be updated unexpectedly) - if (!IsAlive()) - break; - - m_regenTimer -= diff; - if (m_regenTimer <= 0) - { - if (!IsInEvadeMode()) - { - // regenerate health if not in combat or if polymorphed) - if (!IsInCombat() || IsPolymorphed()) RegenerateHealth(); - else if (IsNotReachableAndNeedRegen()) + LOG_DEBUG("entities.unit", "RegenerateHealth() enabled because Creature cannot reach the target. Detail: {}", GetDebugInfo()); + } + else + LOG_DEBUG("entities.unit", "RegenerateHealth() disabled even if the Creature cannot reach the target. Detail: {}", GetDebugInfo()); + } + } + + if (getPowerType() == POWER_ENERGY) + Regenerate(POWER_ENERGY); + else + Regenerate(POWER_MANA); + + m_regenTimer += CREATURE_REGEN_INTERVAL; + } + + if (CanNotReachTarget() && !IsInEvadeMode()) + { + m_cannotReachTimer += diff; + if (m_cannotReachTimer >= (sWorld->getIntConfig(CONFIG_NPC_EVADE_IF_NOT_REACHABLE) * IN_MILLISECONDS)) + { + Player* cannotReachPlayer = ObjectAccessor::GetPlayer(*this, m_cannotReachTarget); + if (cannotReachPlayer && IsEngagedBy(cannotReachPlayer) && IsAIEnabled && AI()->OnTeleportUnreacheablePlayer(cannotReachPlayer)) + { + SetCannotReachTarget(); + } + else if (!GetMap()->IsRaid()) + { + auto EnterEvade = [&]() { - // regenerate health if cannot reach the target and the setting is set to do so. - // this allows to disable the health regen of raid bosses if pathfinding has issues for whatever reason - if (sWorld->getBoolConfig(CONFIG_REGEN_HP_CANNOT_REACH_TARGET_IN_RAID) || !GetMap()->IsRaid()) + if (CreatureAI* ai = AI()) { - RegenerateHealth(); - LOG_DEBUG("entities.unit", "RegenerateHealth() enabled because Creature cannot reach the target. Detail: {}", GetDebugInfo()); + ai->EnterEvadeMode(CreatureAI::EvadeReason::EVADE_REASON_NO_PATH); + } + }; + + if (GetThreatMgr().getThreatList().size() <= 1) + { + EnterEvade(); + } + else + { + if (HostileReference* ref = GetThreatMgr().getOnlineContainer().getReferenceByTarget(m_cannotReachTarget)) + { + ref->removeReference(); + SetCannotReachTarget(); } else - LOG_DEBUG("entities.unit", "RegenerateHealth() disabled even if the Creature cannot reach the target. Detail: {}", GetDebugInfo()); + { + EnterEvade(); + } } } - - if (getPowerType() == POWER_ENERGY) - Regenerate(POWER_ENERGY); - else - Regenerate(POWER_MANA); - - m_regenTimer += CREATURE_REGEN_INTERVAL; } - - if (CanNotReachTarget() && !IsInEvadeMode() && !GetMap()->IsRaid()) - { - m_cannotReachTimer += diff; - if (IsNotReachable() && IsAIEnabled) - { - AI()->EnterEvadeMode(); - } - } - - break; } + break; + } default: break; } @@ -1926,7 +1957,7 @@ void Creature::setDeathState(DeathState s, bool despawn) SetFullHealth(); SetLootRecipient(nullptr); ResetPlayerDamageReq(); - SetCannotReachTarget(false); + SetCannotReachTarget(); CreatureTemplate const* cinfo = GetCreatureTemplate(); // Xinef: npc run by default //SetWalk(true); @@ -3457,15 +3488,35 @@ bool Creature::IsMovementPreventedByCasting() const return false; } -void Creature::SetCannotReachTarget(bool cannotReach) +void Creature::SetCannotReachTarget(ObjectGuid const& cannotReach) { if (cannotReach == m_cannotReachTarget) + { return; + } + m_cannotReachTarget = cannotReach; m_cannotReachTimer = 0; if (cannotReach) + { LOG_DEBUG("entities.unit", "Creature::SetCannotReachTarget() called with true. Details: {}", GetDebugInfo()); + } +} + +bool Creature::CanNotReachTarget() const +{ + return m_cannotReachTarget; +} + +bool Creature::IsNotReachableAndNeedRegen() const +{ + if (CanNotReachTarget()) + { + return m_cannotReachTimer >= (sWorld->getIntConfig(CONFIG_NPC_REGEN_TIME_IF_NOT_REACHABLE_IN_RAID) * IN_MILLISECONDS); + } + + return false; } time_t Creature::GetLastDamagedTime() const diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h index b1fd4eea4..d97d6ef17 100644 --- a/src/server/game/Entities/Creature/Creature.h +++ b/src/server/game/Entities/Creature/Creature.h @@ -309,10 +309,9 @@ public: return m_charmInfo->GetCharmSpell(pos)->GetAction(); } - void SetCannotReachTarget(bool cannotReach); - [[nodiscard]] bool CanNotReachTarget() const { return m_cannotReachTarget; } - [[nodiscard]] bool IsNotReachable() const { return (m_cannotReachTimer >= (sWorld->getIntConfig(CONFIG_NPC_EVADE_IF_NOT_REACHABLE) * IN_MILLISECONDS)) && m_cannotReachTarget; } - [[nodiscard]] bool IsNotReachableAndNeedRegen() const { return (m_cannotReachTimer >= (sWorld->getIntConfig(CONFIG_NPC_REGEN_TIME_IF_NOT_REACHABLE_IN_RAID) * IN_MILLISECONDS)) && m_cannotReachTarget; } + void SetCannotReachTarget(ObjectGuid const& target = ObjectGuid::Empty); + [[nodiscard]] bool CanNotReachTarget() const; + [[nodiscard]] bool IsNotReachableAndNeedRegen() const; void SetPosition(float x, float y, float z, float o); void SetPosition(const Position& pos) { SetPosition(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation()); } @@ -456,7 +455,7 @@ private: mutable std::shared_ptr _lastDamagedTime; // Part of Evade mechanics - bool m_cannotReachTarget; + ObjectGuid m_cannotReachTarget; uint32 m_cannotReachTimer; Spell const* _focusSpell; ///> Locks the target during spell cast for proper facing diff --git a/src/server/game/Entities/Creature/CreatureData.h b/src/server/game/Entities/Creature/CreatureData.h index 7d454e8e6..09751eac6 100644 --- a/src/server/game/Entities/Creature/CreatureData.h +++ b/src/server/game/Entities/Creature/CreatureData.h @@ -80,8 +80,7 @@ enum CreatureFlagsExtra : uint32 CREATURE_FLAG_EXTRA_HARD_RESET = 0x80000000, // Masks - CREATURE_FLAG_EXTRA_UNUSED = (CREATURE_FLAG_EXTRA_UNUSED_12 | CREATURE_FLAG_EXTRA_UNUSED_26 | - CREATURE_FLAG_EXTRA_UNUSED_27 | CREATURE_FLAG_EXTRA_UNUSED_28), // SKIP + CREATURE_FLAG_EXTRA_UNUSED = (CREATURE_FLAG_EXTRA_UNUSED_12 | CREATURE_FLAG_EXTRA_UNUSED_26 | CREATURE_FLAG_EXTRA_UNUSED_27 | CREATURE_FLAG_EXTRA_UNUSED_28), // SKIP CREATURE_FLAG_EXTRA_DB_ALLOWED = (0xFFFFFFFF & ~(CREATURE_FLAG_EXTRA_UNUSED | CREATURE_FLAG_EXTRA_DUNGEON_BOSS)) // SKIP }; diff --git a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp index 128a3b25f..30b5c8dcf 100644 --- a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp @@ -63,7 +63,7 @@ bool ChaseMovementGenerator::DoUpdate(T* owner, uint32 time_diff) _lastTargetPosition.reset(); if (Creature* cOwner2 = owner->ToCreature()) { - cOwner2->SetCannotReachTarget(false); + cOwner2->SetCannotReachTarget(); } return true; @@ -91,13 +91,14 @@ bool ChaseMovementGenerator::DoUpdate(T* owner, uint32 time_diff) if (i_recalculateTravel && PositionOkay(owner, target, _movingTowards ? maxTarget : Optional(), angle)) { - i_recalculateTravel = false; - i_path = nullptr; if (Creature* cOwner2 = owner->ToCreature()) { - cOwner2->SetCannotReachTarget(false); + cOwner2->SetCannotReachTarget(i_path && i_path->GetPathType() & PATHFIND_INCOMPLETE ? target->GetGUID() : ObjectGuid::Empty); } + i_recalculateTravel = false; + i_path = nullptr; + owner->StopMoving(); owner->SetInFront(target); MovementInform(owner); @@ -107,14 +108,24 @@ bool ChaseMovementGenerator::DoUpdate(T* owner, uint32 time_diff) if (owner->HasUnitState(UNIT_STATE_CHASE_MOVE) && owner->movespline->Finalized()) { - i_recalculateTravel = false; - i_path = nullptr; owner->ClearUnitState(UNIT_STATE_CHASE_MOVE); owner->SetInFront(target); MovementInform(owner); if (owner->IsWithinMeleeRange(this->i_target.getTarget())) + { owner->Attack(this->i_target.getTarget(), true); + } + else if (i_path && i_path->GetPathType() & PATHFIND_INCOMPLETE) + { + if (Creature* cOwner2 = owner->ToCreature()) + { + cOwner2->SetCannotReachTarget(this->i_target.getTarget()->GetGUID()); + } + } + + i_recalculateTravel = false; + i_path = nullptr; } if (_lastTargetPosition && i_target->GetPosition() == _lastTargetPosition.value() && mutualChase == _mutualChase) @@ -139,7 +150,7 @@ bool ChaseMovementGenerator::DoUpdate(T* owner, uint32 time_diff) // can we get to the target? if (cOwner && !target->isInAccessiblePlaceFor(cOwner)) { - cOwner->SetCannotReachTarget(true); + cOwner->SetCannotReachTarget(target->GetGUID()); cOwner->StopMoving(); i_path = nullptr; return true; @@ -176,7 +187,10 @@ bool ChaseMovementGenerator::DoUpdate(T* owner, uint32 time_diff) if (!success || i_path->GetPathType() & PATHFIND_NOPATH) { if (cOwner) - cOwner->SetCannotReachTarget(true); + { + cOwner->SetCannotReachTarget(target->GetGUID()); + } + return true; } @@ -184,7 +198,9 @@ bool ChaseMovementGenerator::DoUpdate(T* owner, uint32 time_diff) i_path->ShortenPathUntilDist(G3D::Vector3(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ()), maxTarget); if (cOwner) - cOwner->SetCannotReachTarget(false); + { + cOwner->SetCannotReachTarget(); + } bool walk = false; if (cOwner && !cOwner->IsPet()) @@ -239,7 +255,9 @@ void ChaseMovementGenerator::DoFinalize(T* owner) { owner->ClearUnitState(UNIT_STATE_CHASE | UNIT_STATE_CHASE_MOVE); if (Creature* cOwner = owner->ToCreature()) - cOwner->SetCannotReachTarget(false); + { + cOwner->SetCannotReachTarget(); + } } template diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_mandokir.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_mandokir.cpp index ccf460440..cf9d16c47 100644 --- a/src/server/scripts/EasternKingdoms/ZulGurub/boss_mandokir.cpp +++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_mandokir.cpp @@ -313,6 +313,12 @@ public: } } + bool OnTeleportUnreacheablePlayer(Player* player) override + { + DoCast(player, SPELL_SUMMON_PLAYER, true); + return true; + } + void DoMeleeAttackIfReady(bool ignoreCasting) { if (!ignoreCasting && me->HasUnitState(UNIT_STATE_CASTING)) From cd64e75558670a2b85cd45d49903ab88b29bf83b Mon Sep 17 00:00:00 2001 From: Gultask <100873791+Gultask@users.noreply.github.com> Date: Sun, 24 Jul 2022 13:13:02 -0300 Subject: [PATCH 067/130] fix(DB/Loot): Cannon Master Willey (10997) (#12476) * Create rev_1658464932896975300.sql * Update rev_1658464932896975300.sql * Revert "Update rev_1658464932896975300.sql" This reverts commit 1ec4a2aef8f0cffddfc80832fe5cfb72c0c62449. --- data/sql/updates/pending_db_world/rev_1658464932896975300.sql | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 data/sql/updates/pending_db_world/rev_1658464932896975300.sql diff --git a/data/sql/updates/pending_db_world/rev_1658464932896975300.sql b/data/sql/updates/pending_db_world/rev_1658464932896975300.sql new file mode 100644 index 000000000..f9a3070d4 --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1658464932896975300.sql @@ -0,0 +1,2 @@ +-- +UPDATE `reference_loot_template` SET `Chance`=0 WHERE `Entry`=35026 AND `Item` IN (22407, 22406, 22405, 22404, 22403); From bb8c9400c253d79c4ad90d49f948490cfb987304 Mon Sep 17 00:00:00 2001 From: AzerothCoreBot Date: Sun, 24 Jul 2022 16:14:59 +0000 Subject: [PATCH 068/130] chore(DB): import pending files Referenced commit(s): cd64e75558670a2b85cd45d49903ab88b29bf83b --- .../rev_1658464932896975300.sql => db_world/2022_07_24_01.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/rev_1658464932896975300.sql => db_world/2022_07_24_01.sql} (73%) diff --git a/data/sql/updates/pending_db_world/rev_1658464932896975300.sql b/data/sql/updates/db_world/2022_07_24_01.sql similarity index 73% rename from data/sql/updates/pending_db_world/rev_1658464932896975300.sql rename to data/sql/updates/db_world/2022_07_24_01.sql index f9a3070d4..e43d979c3 100644 --- a/data/sql/updates/pending_db_world/rev_1658464932896975300.sql +++ b/data/sql/updates/db_world/2022_07_24_01.sql @@ -1,2 +1,3 @@ +-- DB update 2022_07_24_00 -> 2022_07_24_01 -- UPDATE `reference_loot_template` SET `Chance`=0 WHERE `Entry`=35026 AND `Item` IN (22407, 22406, 22405, 22404, 22403); From b2c3bd06e99d44e3eed1f8476032d26e262a2736 Mon Sep 17 00:00:00 2001 From: UltraNix <80540499+UltraNix@users.noreply.github.com> Date: Sun, 24 Jul 2022 18:16:24 +0200 Subject: [PATCH 069/130] =?UTF-8?q?fix(Core/Pets):=20Warlock=20should=20no?= =?UTF-8?q?t=20be=20refunded=20with=20Soul=20Shard=20on=20log=E2=80=A6=20(?= =?UTF-8?q?#12409)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fix(Core/Pets): Warlock should not be refunded with Soul Shard on logging out. Fixes #12058 --- src/server/game/Entities/Player/Player.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 25d9425b9..2abdf6374 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -8909,7 +8909,7 @@ void Player::RemovePet(Pet* pet, PetSaveMode mode, bool returnreagent) return; } - if (returnreagent && (pet || m_temporaryUnsummonedPetNumber) && !InBattleground()) + if (returnreagent && (pet || (m_temporaryUnsummonedPetNumber && (!m_session || !m_session->PlayerLogout()))) && !InBattleground()) { //returning of reagents only for players, so best done here uint32 spellId = pet ? pet->GetUInt32Value(UNIT_CREATED_BY_SPELL) : m_oldpetspell; From d9dde93315b884bac4a62cd530b5030692a15026 Mon Sep 17 00:00:00 2001 From: ZhengPeiRu21 <98835050+ZhengPeiRu21@users.noreply.github.com> Date: Sun, 24 Jul 2022 10:21:14 -0600 Subject: [PATCH 070/130] fix(DB/SAI): Script Warmaul Chef Bufferlo (#12378) --- .../rev_1657756491696232200.sql | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 data/sql/updates/pending_db_world/rev_1657756491696232200.sql diff --git a/data/sql/updates/pending_db_world/rev_1657756491696232200.sql b/data/sql/updates/pending_db_world/rev_1657756491696232200.sql new file mode 100644 index 000000000..c70f0386e --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1657756491696232200.sql @@ -0,0 +1,38 @@ +-- Warmaul Chef Bufferlo +UPDATE `creature_template` SET `AIName`="SmartAI", `speed_walk`=1 WHERE `entry`=18440; +DELETE FROM `smart_scripts` WHERE `entryorguid`=18440 AND `source_type`=0; +DELETE FROM `smart_scripts` WHERE `entryorguid` IN (1844000,1844001,1844002) AND `source_type`=9; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`event_param5`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(18440,0,0,0,4,0,100,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"Warmaul Chef Bufferlo - On Aggro - Say Line 0"), +(18440,0,1,0,1,0,100,0,10000,30000,80000,100000,0,87,1844000,1844001,1844002,0,0,0,1,0,0,0,0,0,0,0,"Warmaul Chef Bufferlo - Out of Combat - Run Random Script"), +(18440,0,2,0,0,0,100,0,7000,12000,7000,12000,0,11,32376,0,0,0,0,0,2,0,0,0,0,0,0,0,"Warmaul Chef Bufferlo - In Combat - Cast 'Tenderize'"), +(18440,0,3,0,0,0,100,0,4000,6000,14000,18000,0,11,32378,0,0,0,0,0,2,0,0,0,0,0,0,0,"Warmaul Chef Bufferlo - In Combat - Cast 'Filet'"), +(18440,0,4,0,4,0,100,0,0,0,0,0,0,11,31994,0,0,0,0,0,2,0,0,0,0,0,0,0,"Warmaul Chef Bufferlo - On Aggro - Cast 'Shoulder Charge'"), +(1844000,9,0,0,0,0,100,0,0,0,0,0,0,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0,"Warmaul Chef Bufferlo - On Script - Say Line 1"), +(1844000,9,1,0,0,0,100,0,6000,6000,0,0,0,1,2,0,0,0,0,0,1,0,0,0,0,0,0,0,"Warmaul Chef Bufferlo - On Script - Say Line 2"), +(1844001,9,0,0,0,0,100,0,0,0,0,0,0,5,36,0,0,0,0,0,1,0,0,0,0,0,0,0,"Warmaul Chef Bufferlo - On Script - Play Emote 36"), +(1844001,9,1,0,0,0,100,0,2000,2000,0,0,0,1,3,0,0,0,0,0,1,0,0,0,0,0,0,0,"Warmaul Chef Bufferlo - On Script - Say Line 3"), +(1844002,9,0,0,0,0,100,0,0,0,0,0,0,5,35,0,0,0,0,0,1,0,0,0,0,0,0,0,"Warmaul Chef Bufferlo - On Script - Play Emote 35"), +(1844002,9,1,0,0,0,100,0,2000,2000,0,0,0,1,4,0,0,0,0,0,1,0,0,0,0,0,0,0,"Warmaul Chef Bufferlo - On Script - Say Line 4"), +(1844002,9,2,0,0,0,100,0,5000,5000,0,0,0,1,5,0,0,0,0,0,1,0,0,0,0,0,0,0,"Warmaul Chef Bufferlo - On Script - Say Line 5"), +(1844002,9,3,0,0,0,100,0,4000,4000,0,0,0,1,6,0,0,0,0,0,1,0,0,0,0,0,0,0,"Warmaul Chef Bufferlo - On Script - Say Line 6"), +(1844002,9,4,0,0,0,100,0,4000,4000,0,0,0,1,7,0,0,0,0,0,1,0,0,0,0,0,0,0,"Warmaul Chef Bufferlo - On Script - Say Line 7"), +(1844002,9,5,0,0,0,100,0,2000,2000,0,0,0,5,35,0,0,0,0,0,1,0,0,0,0,0,0,0,"Warmaul Chef Bufferlo - On Script - Play Emote 35"), +(1844002,9,6,0,0,0,100,0,2000,2000,0,0,0,1,8,0,0,0,0,0,1,0,0,0,0,0,0,0,"Warmaul Chef Bufferlo - On Script - Say Line 8"), +(1844002,9,7,0,0,0,100,0,8000,8000,0,0,0,1,9,0,0,0,0,0,1,0,0,0,0,0,0,0,"Warmaul Chef Bufferlo - On Script - Say Line 9"), +(1844002,9,8,0,0,0,100,0,3000,3000,0,0,0,5,153,0,0,0,0,0,1,0,0,0,0,0,0,0,"Warmaul Chef Bufferlo - On Script - Play Emote 153"); + +DELETE FROM `creature_text` WHERE `CreatureID`=18440; +INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES +(18440,0,0,"IT DUZ WUT IT'S TOLD!",12,0,100,0,0,0,15419,0,"Warmaul Chef Bufferlo"), +(18440,0,1,"GET IN DA STEW!",12,0,100,0,0,0,15420,0,"Warmaul Chef Bufferlo"), +(18440,0,2,"YOU GUD IN DA BELLY!",12,0,100,0,0,0,15421,0,"Warmaul Chef Bufferlo"), +(18440,1,0,"Your daddy pay Warmaul and maybe we no eat you.",12,0,100,1,0,0,15426,0,"Warmaul Chef Bufferlo"), +(18440,2,0,"Ha-ha! Just kidding. We eat you for shure anyway!",12,0,100,11,0,0,15427,0,"Warmaul Chef Bufferlo"), +(18440,3,0,"BAM! Look at dat gristle sizzle!",12,0,100,1,0,0,15430,0,"Warmaul Chef Bufferlo"), +(18440,4,0,"And dis is da recipe for da bestest Broken chowder!",12,0,100,1,0,0,15431,0,"Warmaul Chef Bufferlo"), +(18440,5,0,"First you need da spices.",12,0,100,1,0,0,15432,0,"Warmaul Chef Bufferlo"), +(18440,6,0,"Da salt goes into da pot...",12,0,100,35,0,0,15433,0,"Warmaul Chef Bufferlo"), +(18440,7,0,"Den you put da pepper in da pot...",12,0,100,0,0,0,15434,0,"Warmaul Chef Bufferlo"), +(18440,8,0,"Now we gonna kick it up a notch wit da secret ingra... ingor... inrag... da secret sauce!",12,0,100,43,0,0,15435,0,"Warmaul Chef Bufferlo"), +(18440,9,0,"And last, we put in da Corki!",12,0,100,1,0,0,15436,0,"Warmaul Chef Bufferlo"); From f6385c50547f2bd972f398196e092eb9bc6d6d06 Mon Sep 17 00:00:00 2001 From: AzerothCoreBot Date: Sun, 24 Jul 2022 16:23:10 +0000 Subject: [PATCH 071/130] chore(DB): import pending files Referenced commit(s): d9dde93315b884bac4a62cd530b5030692a15026 --- .../rev_1657756491696232200.sql => db_world/2022_07_24_02.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/rev_1657756491696232200.sql => db_world/2022_07_24_02.sql} (99%) diff --git a/data/sql/updates/pending_db_world/rev_1657756491696232200.sql b/data/sql/updates/db_world/2022_07_24_02.sql similarity index 99% rename from data/sql/updates/pending_db_world/rev_1657756491696232200.sql rename to data/sql/updates/db_world/2022_07_24_02.sql index c70f0386e..4d3fe7bc7 100644 --- a/data/sql/updates/pending_db_world/rev_1657756491696232200.sql +++ b/data/sql/updates/db_world/2022_07_24_02.sql @@ -1,3 +1,4 @@ +-- DB update 2022_07_24_01 -> 2022_07_24_02 -- Warmaul Chef Bufferlo UPDATE `creature_template` SET `AIName`="SmartAI", `speed_walk`=1 WHERE `entry`=18440; DELETE FROM `smart_scripts` WHERE `entryorguid`=18440 AND `source_type`=0; From b81a14976cd2922f5b95948af7d85014287d5c54 Mon Sep 17 00:00:00 2001 From: UltraNix <80540499+UltraNix@users.noreply.github.com> Date: Sun, 24 Jul 2022 18:38:03 +0200 Subject: [PATCH 072/130] fix(Scripts/Spells): Glyph of Felguard. (#12497) * fix(Scripts/Spells): Glyph of Felguard. Fixes #12432 * Update. --- .../rev_1658567599833438900.sql | 4 ++ src/server/game/Entities/Pet/Pet.cpp | 4 +- src/server/scripts/Spells/spell_warlock.cpp | 41 +++++++++++++++++++ 3 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 data/sql/updates/pending_db_world/rev_1658567599833438900.sql diff --git a/data/sql/updates/pending_db_world/rev_1658567599833438900.sql b/data/sql/updates/pending_db_world/rev_1658567599833438900.sql new file mode 100644 index 000000000..22331dacc --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1658567599833438900.sql @@ -0,0 +1,4 @@ +-- +DELETE FROM `spell_script_names` WHERE `spell_id`=56246; +INSERT INTO `spell_script_names` VALUES +(56246,'spell_warl_glyph_of_felguard'); diff --git a/src/server/game/Entities/Pet/Pet.cpp b/src/server/game/Entities/Pet/Pet.cpp index dccb099bd..79ea17ede 100644 --- a/src/server/game/Entities/Pet/Pet.cpp +++ b/src/server/game/Entities/Pet/Pet.cpp @@ -1154,7 +1154,9 @@ bool Guardian::InitStatsForLevel(uint8 petlevel) { // xinef: Glyph of Felguard, so ugly im crying... no appropriate spell if (AuraEffect* aurEff = owner->GetAuraEffectDummy(SPELL_GLYPH_OF_FELGUARD)) - SetModifierValue(UNIT_MOD_ATTACK_POWER, TOTAL_PCT, 1.0f + float(aurEff->GetAmount() / 100.0f)); + { + HandleStatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_PCT, aurEff->GetAmount(), true); + } break; } diff --git a/src/server/scripts/Spells/spell_warlock.cpp b/src/server/scripts/Spells/spell_warlock.cpp index cfa787420..82a3e5e99 100644 --- a/src/server/scripts/Spells/spell_warlock.cpp +++ b/src/server/scripts/Spells/spell_warlock.cpp @@ -21,6 +21,7 @@ * Scriptnames of files in this file should be prefixed with "spell_warl_". */ +#include "Pet.h" #include "Player.h" #include "ScriptMgr.h" #include "SpellAuraEffects.h" @@ -1229,6 +1230,45 @@ class spell_warl_shadowburn : public AuraScript } }; +class spell_warl_glyph_of_felguard : public AuraScript +{ + PrepareAuraScript(spell_warl_glyph_of_felguard); + + void HandleApply(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/) + { + if (Player* player = GetCaster()->ToPlayer()) + { + if (Pet* pet = player->GetPet()) + { + if (pet->GetEntry() == NPC_FELGUARD) + { + pet->HandleStatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_PCT, aurEff->GetAmount(), true); + } + } + } + } + + void HandleRemove(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/) + { + if (Player* player = GetCaster()->ToPlayer()) + { + if (Pet* pet = player->GetPet()) + { + if (pet->GetEntry() == NPC_FELGUARD) + { + pet->HandleStatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_PCT, aurEff->GetAmount(), false); + } + } + } + } + + void Register() override + { + OnEffectApply += AuraEffectApplyFn(spell_warl_glyph_of_felguard::HandleApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); + OnEffectRemove += AuraEffectRemoveFn(spell_warl_glyph_of_felguard::HandleRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); + } +}; + void AddSC_warlock_spell_scripts() { RegisterSpellScript(spell_warl_eye_of_kilrogg); @@ -1260,4 +1300,5 @@ void AddSC_warlock_spell_scripts() RegisterSpellScript(spell_warl_unstable_affliction); RegisterSpellScript(spell_warl_drain_soul); RegisterSpellScript(spell_warl_shadowburn); + RegisterSpellScript(spell_warl_glyph_of_felguard); } From 6b5370a75f5f1b5f9bb7778e2313146b3cc5e40a Mon Sep 17 00:00:00 2001 From: AzerothCoreBot Date: Sun, 24 Jul 2022 16:40:20 +0000 Subject: [PATCH 073/130] chore(DB): import pending files Referenced commit(s): b81a14976cd2922f5b95948af7d85014287d5c54 --- .../rev_1658567599833438900.sql => db_world/2022_07_24_03.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/rev_1658567599833438900.sql => db_world/2022_07_24_03.sql} (76%) diff --git a/data/sql/updates/pending_db_world/rev_1658567599833438900.sql b/data/sql/updates/db_world/2022_07_24_03.sql similarity index 76% rename from data/sql/updates/pending_db_world/rev_1658567599833438900.sql rename to data/sql/updates/db_world/2022_07_24_03.sql index 22331dacc..cb7e1ed95 100644 --- a/data/sql/updates/pending_db_world/rev_1658567599833438900.sql +++ b/data/sql/updates/db_world/2022_07_24_03.sql @@ -1,3 +1,4 @@ +-- DB update 2022_07_24_02 -> 2022_07_24_03 -- DELETE FROM `spell_script_names` WHERE `spell_id`=56246; INSERT INTO `spell_script_names` VALUES From d2f126710fb8b0a22a9b73a444a6b8ff9c3b9750 Mon Sep 17 00:00:00 2001 From: Synful-Syn Date: Sun, 24 Jul 2022 13:29:13 -0400 Subject: [PATCH 074/130] chore(Cleanup): Merge redundant `if` in Totem::Update() (#12423) TotemUpdate-too-long --- src/server/game/Entities/Totem/Totem.cpp | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/src/server/game/Entities/Totem/Totem.cpp b/src/server/game/Entities/Totem/Totem.cpp index 1ed444bb4..73486f979 100644 --- a/src/server/game/Entities/Totem/Totem.cpp +++ b/src/server/game/Entities/Totem/Totem.cpp @@ -34,20 +34,13 @@ Totem::Totem(SummonPropertiesEntry const* properties, ObjectGuid owner) : Minion void Totem::Update(uint32 time) { Unit* owner = GetOwner(); - if (!owner || !owner->IsAlive() || !IsAlive()) + if (!owner || !owner->IsAlive() || !IsAlive() || m_duration <= time) { UnSummon(); // remove self return; } - if (m_duration <= time) - { - UnSummon(); // remove self - return; - } - else - m_duration -= time; - + m_duration -= time; Creature::Update(time); } From 5008e633e368af57ab6b9ea761c123e3cf7ae66f Mon Sep 17 00:00:00 2001 From: UltraNix <80540499+UltraNix@users.noreply.github.com> Date: Sun, 24 Jul 2022 19:33:05 +0200 Subject: [PATCH 075/130] =?UTF-8?q?fix(Core/Spells):=20Elemental=20Mastery?= =?UTF-8?q?=20should=20only=20affect=20Lightning=20Bolt=E2=80=A6=20(#12499?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(Core/Spells): Elemental Mastery should only affect Lightning Bolt, Chain Lightning and Lava Burst. Fixes #10903 * Update. --- .../updates/pending_db_world/rev_1658605553284135100.sql | 2 ++ src/server/game/Spells/SpellInfoCorrections.cpp | 6 ++++++ 2 files changed, 8 insertions(+) create mode 100644 data/sql/updates/pending_db_world/rev_1658605553284135100.sql diff --git a/data/sql/updates/pending_db_world/rev_1658605553284135100.sql b/data/sql/updates/pending_db_world/rev_1658605553284135100.sql new file mode 100644 index 000000000..d1f14a6f2 --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1658605553284135100.sql @@ -0,0 +1,2 @@ +-- +UPDATE `spell_proc_event` SET `SpellFamilyName`=11, `SpellFamilyMask0`=0x00000003, `SpellFamilyMask1`=0x00001000 WHERE `entry`=16166; diff --git a/src/server/game/Spells/SpellInfoCorrections.cpp b/src/server/game/Spells/SpellInfoCorrections.cpp index 17542822f..30ca46693 100644 --- a/src/server/game/Spells/SpellInfoCorrections.cpp +++ b/src/server/game/Spells/SpellInfoCorrections.cpp @@ -4323,6 +4323,12 @@ void SpellMgr::LoadSpellInfoCorrections() spellInfo->Effects[EFFECT_0].MiscValue = 8; }); + // Elemental Mastery + ApplySpellFix({ 16166 }, [](SpellInfo* spellInfo) + { + spellInfo->Effects[EFFECT_0].SpellClassMask = flag96(0x00000003, 0x00001000); + }); + for (uint32 i = 0; i < GetSpellInfoStoreSize(); ++i) { SpellInfo* spellInfo = mSpellInfoMap[i]; From 33d0321a02710777486c18c5aa62edeffaaab78c Mon Sep 17 00:00:00 2001 From: AzerothCoreBot Date: Sun, 24 Jul 2022 17:35:13 +0000 Subject: [PATCH 076/130] chore(DB): import pending files Referenced commit(s): 5008e633e368af57ab6b9ea761c123e3cf7ae66f --- .../rev_1658605553284135100.sql => db_world/2022_07_24_04.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/rev_1658605553284135100.sql => db_world/2022_07_24_04.sql} (75%) diff --git a/data/sql/updates/pending_db_world/rev_1658605553284135100.sql b/data/sql/updates/db_world/2022_07_24_04.sql similarity index 75% rename from data/sql/updates/pending_db_world/rev_1658605553284135100.sql rename to data/sql/updates/db_world/2022_07_24_04.sql index d1f14a6f2..00eb2fee6 100644 --- a/data/sql/updates/pending_db_world/rev_1658605553284135100.sql +++ b/data/sql/updates/db_world/2022_07_24_04.sql @@ -1,2 +1,3 @@ +-- DB update 2022_07_24_03 -> 2022_07_24_04 -- UPDATE `spell_proc_event` SET `SpellFamilyName`=11, `SpellFamilyMask0`=0x00000003, `SpellFamilyMask1`=0x00001000 WHERE `entry`=16166; From 631686be7e5c90885c98f4d626a0cf4febc4d67c Mon Sep 17 00:00:00 2001 From: ZhengPeiRu21 <98835050+ZhengPeiRu21@users.noreply.github.com> Date: Sun, 24 Jul 2022 11:37:42 -0600 Subject: [PATCH 077/130] fix(Core): Instance Reset Exploit Fix (#12459) * fix(Core): Fix Instance Reset Exploit * Whitespace fix * Remove unnecessary include * Check player instance save IDs when adding to map * Only compare playerBind during login --- src/server/game/Maps/Map.cpp | 5 +++++ src/server/game/Server/WorldSession.cpp | 5 +++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp index 693d53197..6e604bb6f 100644 --- a/src/server/game/Maps/Map.cpp +++ b/src/server/game/Maps/Map.cpp @@ -2959,6 +2959,11 @@ bool InstanceMap::AddPlayerToMap(Player* player) return false; } } + else if (player->GetSession()->PlayerLoading() && playerBind && playerBind->save != mapSave) + { + // Prevent "Convert to Raid" exploit to reset instances + return false; + } else { playerBind = sInstanceSaveMgr->PlayerBindToInstance(player->GetGUID(), mapSave, false, player); diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp index 85bcb5972..617c106a6 100644 --- a/src/server/game/Server/WorldSession.cpp +++ b/src/server/game/Server/WorldSession.cpp @@ -665,11 +665,12 @@ void WorldSession::LogoutPlayer(bool save) _player->GetGroup()->SendUpdate(); _player->GetGroup()->ResetMaxEnchantingLevel(); - Map::PlayerList const& playerList = _player->GetMap()->GetPlayers(); - if (_player->GetMap()->IsDungeon() || _player->GetMap()->IsRaidOrHeroicDungeon()) + { + Map::PlayerList const &playerList = _player->GetMap()->GetPlayers(); if (playerList.IsEmpty()) _player->TeleportToEntryPoint(); + } } //! Broadcast a logout message to the player's friends From 984f039f0a58f27d8c07689122ac6e903d658657 Mon Sep 17 00:00:00 2001 From: neifion-00000000 <91289495+neifion-00000000@users.noreply.github.com> Date: Sun, 24 Jul 2022 15:21:53 -0500 Subject: [PATCH 078/130] fix(DB/SAI): Zulian Crocolisk has scripted movement (#12460) --- .../pending_db_world/rev_1658354450598559500.sql | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 data/sql/updates/pending_db_world/rev_1658354450598559500.sql diff --git a/data/sql/updates/pending_db_world/rev_1658354450598559500.sql b/data/sql/updates/pending_db_world/rev_1658354450598559500.sql new file mode 100644 index 000000000..2041414ab --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1658354450598559500.sql @@ -0,0 +1,12 @@ +-- +-- Crocs movement is a scripted action that occurs about every 30 seconds, not normal random movement +UPDATE `creature` SET `wander_distance`=0, `MovementType`=0 WHERE `id1`=15043; + +DELETE FROM `smart_scripts` WHERE `entryorguid`=15043 AND `source_type`=0; +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(15043, 0, 0, 0, 0, 0, 100, 0, 8000, 9000, 11000, 12000, 0, 11, 3604, 1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Zulian Crocolisk - In Combat - Cast \'Tendon Rip\''), +(15043, 0, 1, 0, 0, 0, 100, 0, 17000, 19000, 22000, 24000, 0, 11, 13445, 1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Zulian Crocolisk - In Combat - Cast \'Rend\''), +(15043, 0, 2, 0, 1, 0, 100, 0, 30000, 30000, 40000, 40000, 0, 89, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'ZG Crocolisks will wander a small amount for about 10 seconds out of every 40 (wander on-2)'), +(15043, 0, 3, 0, 1, 0, 100, 0, 39500, 39500, 40000, 40000, 0, 89, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'ZG Crocolisks will wander a small amount for about 10 seconds out of every 40 (wander on-0)'), +(15043, 0, 4, 0, 1, 0, 100, 0, 39999, 39999, 40000, 40000, 0, 101, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Send ZG Croclisks toward home position to control wandering range (set home POS)'), +(15043, 0, 5, 0, 1, 0, 100, 0, 40000, 40000, 40000, 40000, 0, 24, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Send ZG Croclisks toward home position to control wandering range (reset to home POS)'); From 15fb4d352238f72b1e6978945cb350bf37ef2a3d Mon Sep 17 00:00:00 2001 From: AzerothCoreBot Date: Sun, 24 Jul 2022 20:23:50 +0000 Subject: [PATCH 079/130] chore(DB): import pending files Referenced commit(s): 984f039f0a58f27d8c07689122ac6e903d658657 --- .../rev_1658354450598559500.sql => db_world/2022_07_24_05.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/rev_1658354450598559500.sql => db_world/2022_07_24_05.sql} (97%) diff --git a/data/sql/updates/pending_db_world/rev_1658354450598559500.sql b/data/sql/updates/db_world/2022_07_24_05.sql similarity index 97% rename from data/sql/updates/pending_db_world/rev_1658354450598559500.sql rename to data/sql/updates/db_world/2022_07_24_05.sql index 2041414ab..f81a7fe4c 100644 --- a/data/sql/updates/pending_db_world/rev_1658354450598559500.sql +++ b/data/sql/updates/db_world/2022_07_24_05.sql @@ -1,3 +1,4 @@ +-- DB update 2022_07_24_04 -> 2022_07_24_05 -- -- Crocs movement is a scripted action that occurs about every 30 seconds, not normal random movement UPDATE `creature` SET `wander_distance`=0, `MovementType`=0 WHERE `id1`=15043; From 8809ec55019f39df96c8041fd3671e720f018a4a Mon Sep 17 00:00:00 2001 From: Eddy Vega <61223313+Si1ker@users.noreply.github.com> Date: Sun, 24 Jul 2022 14:34:29 -0600 Subject: [PATCH 080/130] fix(scripts/RuinsOfAhnQiraj): Improve Buru (#12141) --- .../rev_1655864042959599100.sql | 18 +++++ .../Kalimdor/RuinsOfAhnQiraj/boss_buru.cpp | 78 ++++++++++++++----- .../RuinsOfAhnQiraj/ruins_of_ahnqiraj.h | 1 + 3 files changed, 78 insertions(+), 19 deletions(-) create mode 100644 data/sql/updates/pending_db_world/rev_1655864042959599100.sql diff --git a/data/sql/updates/pending_db_world/rev_1655864042959599100.sql b/data/sql/updates/pending_db_world/rev_1655864042959599100.sql new file mode 100644 index 000000000..216e601a2 --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1655864042959599100.sql @@ -0,0 +1,18 @@ + +-- Immune to Taunt +UPDATE `creature_template` SET `flags_extra`=`flags_extra`|256 WHERE `entry`=15370; + +-- Disable exp on Buru egg / Hive'zara hatchling +UPDATE `creature_template` SET `flags_extra`=`flags_extra`|64 WHERE `entry` IN (15514,15521); + +-- New smartAI - despawn +UPDATE `creature_template` SET `AIName`='SmartAI' WHERE `entry`=15521; +DELETE FROM `smart_scripts` WHERE `entryorguid`= 15521 AND `source_type`= 0 AND `id`= 0; +INSERT INTO `smart_scripts` (`entryorguid`, `event_type`, `event_flags`, `event_param1`, `event_param2`, `action_type`, `action_param1`, `target_type`, `comment`) VALUES +(15521, 1, 1, 10000, 10000, 41, 500, 1, 'Hive\'Zara Hatchling - Out of Combat - Despawn (No Repeat)'); + +-- Root egg properly - avoid reset +DELETE FROM `creature_template_movement` WHERE `CreatureId`=15514; +INSERT INTO `creature_template_movement` (`CreatureId`, `Ground`, `Swim`, `Flight`, `Rooted`, `Chase`, `Random`) VALUES +(15514, 1, 1, 0, 1, 0, 0); + diff --git a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_buru.cpp b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_buru.cpp index 58a8d28b6..beef6ec42 100644 --- a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_buru.cpp +++ b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_buru.cpp @@ -35,7 +35,7 @@ enum Spells SPELL_BURU_TRANSFORM = 24721, SPELL_SUMMON_HATCHLING = 1881, SPELL_EXPLODE = 19593, - SPELL_EXPLODE_2 = 5255, + SPELL_EXPLODE_2 = 5255, // Server-side script SPELL_BURU_EGG_TRIGGER = 26646 }; @@ -66,18 +66,19 @@ public: struct boss_buruAI : public BossAI { - boss_buruAI(Creature* creature) : BossAI(creature, DATA_BURU) - { - } + boss_buruAI(Creature* creature) : BossAI(creature, DATA_BURU) {} void EnterEvadeMode(EvadeReason why) override { BossAI::EnterEvadeMode(why); for (ObjectGuid const& guid : Eggs) + { if (Creature* egg = me->GetMap()->GetCreature(guid)) + { egg->Respawn(); - + } + } Eggs.clear(); } @@ -86,25 +87,37 @@ public: _EnterCombat(); Talk(EMOTE_TARGET, who); DoCast(me, SPELL_THORNS); - events.ScheduleEvent(EVENT_DISMEMBER, 5000); events.ScheduleEvent(EVENT_GATHERING_SPEED, 9000); events.ScheduleEvent(EVENT_FULL_SPEED, 60000); - _phase = PHASE_EGG; } + void JustDied(Unit* /*killer*/) override + { + if (InstanceScript* pInstance = me->GetInstanceScript()) + { + pInstance->DoRemoveAurasDueToSpellOnPlayers(SPELL_CREEPING_PLAGUE); + } + } + void DoAction(int32 action) override { if (action == ACTION_EXPLODE) + { if (_phase == PHASE_EGG) + { Unit::DealDamage(me, me, 45000); + } + } } void KilledUnit(Unit* victim) override { if (victim->GetTypeId() == TYPEID_PLAYER) + { ChaseNewVictim(); + } } void ChaseNewVictim() @@ -116,7 +129,6 @@ public: me->RemoveAurasDueToSpell(SPELL_GATHERING_SPEED); events.ScheduleEvent(EVENT_GATHERING_SPEED, 9000); events.ScheduleEvent(EVENT_FULL_SPEED, 60000); - if (Unit* victim = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true)) { DoResetThreat(); @@ -148,15 +160,15 @@ public: events.ScheduleEvent(EVENT_DISMEMBER, 5000); break; case EVENT_GATHERING_SPEED: - DoCast(me, SPELL_GATHERING_SPEED); + DoCastSelf(SPELL_GATHERING_SPEED); events.ScheduleEvent(EVENT_GATHERING_SPEED, 9000); break; case EVENT_FULL_SPEED: - DoCast(me, SPELL_FULL_SPEED); + DoCastSelf(SPELL_FULL_SPEED); break; case EVENT_CREEPING_PLAGUE: - DoCast(me, SPELL_CREEPING_PLAGUE); - events.ScheduleEvent(EVENT_CREEPING_PLAGUE, 6000); + DoCastAOE(SPELL_CREEPING_PLAGUE); + events.ScheduleEvent(EVENT_CREEPING_PLAGUE, urand(6250, 6500)); break; case EVENT_RESPAWN_EGG: if (Creature* egg = me->GetMap()->GetCreature(*Eggs.begin())) @@ -172,12 +184,19 @@ public: if (me->GetHealthPct() < 20.0f && _phase == PHASE_EGG) { - DoCast(me, SPELL_BURU_TRANSFORM); // Enrage - DoCast(me, SPELL_FULL_SPEED, true); + DoCastSelf(SPELL_BURU_TRANSFORM); + DoCastSelf(SPELL_FULL_SPEED, true); me->RemoveAurasDueToSpell(SPELL_THORNS); + events.CancelEvent(EVENT_DISMEMBER); + events.ScheduleEvent(EVENT_CREEPING_PLAGUE, 2000); _phase = PHASE_TRANSFORM; + std::list RemainingEgg; + me->GetCreaturesWithEntryInRange(RemainingEgg, 100.0f, NPC_BURU_EGG); + for (std::list::const_iterator itr = RemainingEgg.begin(); itr != RemainingEgg.end(); ++itr) + { + Unit::Kill(me, *itr); + } } - DoMeleeAttackIfReady(); } private: @@ -207,27 +226,44 @@ public: void EnterCombat(Unit* attacker) override { if (Creature* buru = me->GetMap()->GetCreature(_instance->GetGuidData(DATA_BURU))) + { if (!buru->IsInCombat()) + { buru->AI()->AttackStart(attacker); + } + } } void JustSummoned(Creature* who) override { if (who->GetEntry() == NPC_HATCHLING) + { if (Creature* buru = me->GetMap()->GetCreature(_instance->GetGuidData(DATA_BURU))) + { if (Unit* target = buru->AI()->SelectTarget(SelectTargetMethod::Random)) + { who->AI()->AttackStart(target); + } + } + } } void JustDied(Unit* /*killer*/) override { - DoCastAOE(SPELL_EXPLODE, true); - DoCastAOE(SPELL_EXPLODE_2, true); // Unknown purpose - DoCast(me, SPELL_SUMMON_HATCHLING, true); - if (Creature* buru = me->GetMap()->GetCreature(_instance->GetGuidData(DATA_BURU))) + { + if (!buru->HasAura(SPELL_BURU_TRANSFORM)) + { + DoCast(me, SPELL_EXPLODE, true); + DoCast(me, SPELL_EXPLODE_2, true); + DoCast(me, SPELL_BURU_EGG_TRIGGER, true); + } if (boss_buru::boss_buruAI* buruAI = dynamic_cast(buru->AI())) + { buruAI->ManageRespawn(me->GetGUID()); + } + } + DoCast(me, SPELL_SUMMON_HATCHLING, true); } private: InstanceScript* _instance; @@ -251,13 +287,17 @@ public: void HandleAfterCast() { if (Creature* buru = GetCaster()->FindNearestCreature(NPC_BURU, 5.f)) + { buru->AI()->DoAction(ACTION_EXPLODE); + } } void HandleDummyHitTarget(SpellEffIndex /*effIndex*/) { if (Unit* target = GetHitUnit()) + { Unit::DealDamage(GetCaster(), target, -16 * GetCaster()->GetDistance(target) + 500); + } } void Register() override diff --git a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/ruins_of_ahnqiraj.h b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/ruins_of_ahnqiraj.h index b735b1e9b..f79e1c710 100644 --- a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/ruins_of_ahnqiraj.h +++ b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/ruins_of_ahnqiraj.h @@ -49,6 +49,7 @@ enum Creatures NPC_SAND_VORTEX = 15428, NPC_OSSIRIAN_TRIGGER = 15590, NPC_HATCHLING = 15521, + NPC_BURU_EGG = 15514, NPC_LARVA = 15555, NPC_SWARMER = 15546, NPC_HORNET = 15934 From d859b12c1dffd2c9f7bf5df8053575b7c0af6b04 Mon Sep 17 00:00:00 2001 From: AzerothCoreBot Date: Sun, 24 Jul 2022 20:36:27 +0000 Subject: [PATCH 081/130] chore(DB): import pending files Referenced commit(s): 8809ec55019f39df96c8041fd3671e720f018a4a --- .../rev_1655864042959599100.sql => db_world/2022_07_24_06.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/rev_1655864042959599100.sql => db_world/2022_07_24_06.sql} (95%) diff --git a/data/sql/updates/pending_db_world/rev_1655864042959599100.sql b/data/sql/updates/db_world/2022_07_24_06.sql similarity index 95% rename from data/sql/updates/pending_db_world/rev_1655864042959599100.sql rename to data/sql/updates/db_world/2022_07_24_06.sql index 216e601a2..d8b0e6153 100644 --- a/data/sql/updates/pending_db_world/rev_1655864042959599100.sql +++ b/data/sql/updates/db_world/2022_07_24_06.sql @@ -1,3 +1,4 @@ +-- DB update 2022_07_24_05 -> 2022_07_24_06 -- Immune to Taunt UPDATE `creature_template` SET `flags_extra`=`flags_extra`|256 WHERE `entry`=15370; From 577ae14b2599c2d4797587fc77ceb47740912dbf Mon Sep 17 00:00:00 2001 From: Nefertumm Date: Sun, 24 Jul 2022 17:59:03 -0300 Subject: [PATCH 082/130] fix(Core/RuinsOfAhnQiraj): Kurinnaxx (#12522) --- .../rev_1658689583030214000.sql | 4 + .../RuinsOfAhnQiraj/boss_kurinnaxx.cpp | 181 ++++++++++-------- .../instance_ruins_of_ahnqiraj.cpp | 17 +- .../RuinsOfAhnQiraj/ruins_of_ahnqiraj.h | 4 +- 4 files changed, 121 insertions(+), 85 deletions(-) create mode 100644 data/sql/updates/pending_db_world/rev_1658689583030214000.sql diff --git a/data/sql/updates/pending_db_world/rev_1658689583030214000.sql b/data/sql/updates/pending_db_world/rev_1658689583030214000.sql new file mode 100644 index 000000000..c9719fd55 --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1658689583030214000.sql @@ -0,0 +1,4 @@ +-- +UPDATE `gameobject_template` SET `ScriptName` = 'go_sand_trap' WHERE `entry` = 180647; + +UPDATE `creature_text` SET `TextRange` = 3 WHERE `CreatureID` = 15339 AND `GroupID` = 5; diff --git a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_kurinnaxx.cpp b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_kurinnaxx.cpp index 510624a28..34619337a 100644 --- a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_kurinnaxx.cpp +++ b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_kurinnaxx.cpp @@ -16,14 +16,16 @@ */ #include "CreatureTextMgr.h" +#include "GameObjectAI.h" #include "ScriptMgr.h" #include "ScriptedCreature.h" +#include "TaskScheduler.h" #include "ruins_of_ahnqiraj.h" enum Spells { - SPELL_MORTALWOUND = 25646, - SPELL_SANDTRAP = 25648, + SPELL_MORTAL_WOUND = 25646, + SPELL_SAND_TRAP = 25648, SPELL_ENRAGE = 26527, SPELL_SUMMON_PLAYER = 26446, SPELL_WIDE_SLASH = 25814 @@ -32,97 +34,116 @@ enum Spells enum Events { EVENT_MORTAL_WOUND = 1, - EVENT_SANDTRAP = 2, + EVENT_SAND_TRAP = 2, EVENT_WIDE_SLASH = 3 }; enum Texts { - SAY_KURINAXX_DEATH = 5 // Yell by 'Ossirian the Unscarred' + SAY_KURINNAXX_DEATH = 5 // Yell by 'Ossirian the Unscarred' }; -class boss_kurinnaxx : public CreatureScript +struct boss_kurinnaxx : public BossAI { -public: - boss_kurinnaxx() : CreatureScript("boss_kurinnaxx") { } + boss_kurinnaxx(Creature* creature) : BossAI(creature, DATA_KURINNAXX) {} - struct boss_kurinnaxxAI : public BossAI + void Reset() override { - boss_kurinnaxxAI(Creature* creature) : BossAI(creature, DATA_KURINNAXX) {} - - void Reset() override - { - _Reset(); - _enraged = false; - events.ScheduleEvent(EVENT_MORTAL_WOUND, urand(8000, 10000)); - events.ScheduleEvent(EVENT_SANDTRAP, urand(5000, 15000)); - events.ScheduleEvent(EVENT_WIDE_SLASH, urand(10000, 15000)); - } - - void DamageTaken(Unit*, uint32& /*damage*/, DamageEffectType, SpellSchoolMask) override - { - if (!_enraged && HealthBelowPct(30)) - { - DoCastSelf(SPELL_ENRAGE); - _enraged = true; - } - } - - void JustDied(Unit* /*killer*/) override - { - _JustDied(); - if (Creature* Ossirian = me->GetMap()->GetCreature(instance->GetGuidData(DATA_OSSIRIAN))) - { - sCreatureTextMgr->SendChat(Ossirian, SAY_KURINAXX_DEATH, nullptr, CHAT_MSG_ADDON, LANG_ADDON, TEXT_RANGE_ZONE); - } - } - - void UpdateAI(uint32 diff) override - { - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch (eventId) - { - case EVENT_MORTAL_WOUND: - DoCastVictim(SPELL_MORTALWOUND); - events.ScheduleEvent(EVENT_MORTAL_WOUND, urand(8000, 10000)); - break; - case EVENT_SANDTRAP: - if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100, true)) - { - target->CastSpell(target, SPELL_SANDTRAP, true); - } - events.ScheduleEvent(EVENT_SANDTRAP, urand(5000, 15000)); - break; - case EVENT_WIDE_SLASH: - DoCastSelf(SPELL_WIDE_SLASH); - events.ScheduleEvent(EVENT_WIDE_SLASH, urand(12000, 15000)); - break; - default: - break; - } - } - DoMeleeAttackIfReady(); - } - private: - bool _enraged; - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return GetRuinsOfAhnQirajAI(creature); + BossAI::Reset(); + _enraged = false; + events.ScheduleEvent(EVENT_MORTAL_WOUND, 8s, 10s); + events.ScheduleEvent(EVENT_SAND_TRAP, 5s, 15s); + events.ScheduleEvent(EVENT_WIDE_SLASH, 10s, 15s); } + + void DamageTaken(Unit*, uint32& /*damage*/, DamageEffectType, SpellSchoolMask) override + { + if (!_enraged && HealthBelowPct(30)) + { + DoCastSelf(SPELL_ENRAGE); + _enraged = true; + } + } + + void JustDied(Unit* killer) override + { + if (killer) + killer->GetMap()->LoadGrid(-9502.80f, 2042.65f); // Ossirian grid + + if (Creature* ossirian = instance->GetCreature(DATA_OSSIRIAN)) + { + ossirian->setActive(true); + if (ossirian->GetAI()) + ossirian->AI()->Talk(SAY_KURINNAXX_DEATH); + } + BossAI::JustDied(killer); + } + + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_MORTAL_WOUND: + DoCastVictim(SPELL_MORTAL_WOUND); + events.ScheduleEvent(EVENT_MORTAL_WOUND, 8s, 10s); + break; + case EVENT_SAND_TRAP: + if (Unit* target = SelectTarget(SelectTargetMethod::Random, 1, 100.f, true)) + { + target->CastSpell(target, SPELL_SAND_TRAP, true, nullptr, nullptr, me->GetGUID()); + } + events.ScheduleEvent(EVENT_SAND_TRAP, 5s, 15s); + break; + case EVENT_WIDE_SLASH: + DoCastSelf(SPELL_WIDE_SLASH); + events.ScheduleEvent(EVENT_WIDE_SLASH, 12s, 15s); + break; + default: + break; + } + } + + DoMeleeAttackIfReady(); + } +private: + bool _enraged; +}; + +struct go_sand_trap : public GameObjectAI +{ + go_sand_trap(GameObject* go) : GameObjectAI(go) { } + + void Reset() override + { + _scheduler.Schedule(5s, [this](TaskContext /*context*/) + { + if (InstanceScript* instance = me->GetInstanceScript()) + if (Creature* kurinnaxx = instance->GetCreature(DATA_KURINNAXX)) + me->Use(kurinnaxx); + }); + } + + void UpdateAI(uint32 const diff) override + { + _scheduler.Update(diff); + } + +protected: + TaskScheduler _scheduler; }; void AddSC_boss_kurinnaxx() { - new boss_kurinnaxx(); + RegisterRuinsOfAhnQirajCreatureAI(boss_kurinnaxx); + RegisterGameObjectAI(go_sand_trap); } 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 5cb1e8373..d651cfde6 100644 --- a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/instance_ruins_of_ahnqiraj.cpp +++ b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/instance_ruins_of_ahnqiraj.cpp @@ -19,6 +19,12 @@ #include "ScriptMgr.h" #include "ruins_of_ahnqiraj.h" +ObjectData const creatureData[] = +{ + { NPC_OSSIRIAN, DATA_OSSIRIAN }, + { NPC_KURINNAXX, DATA_KURINNAXX } +}; + class instance_ruins_of_ahnqiraj : public InstanceMapScript { public: @@ -29,14 +35,17 @@ public: instance_ruins_of_ahnqiraj_InstanceMapScript(Map* map) : InstanceScript(map) { SetBossNumber(NUM_ENCOUNTER); + LoadObjectData(creatureData, nullptr); } void OnCreatureCreate(Creature* creature) override { + InstanceScript::OnCreatureCreate(creature); + switch (creature->GetEntry()) { - case NPC_KURINAXX: - _kurinaxxGUID = creature->GetGUID(); + case NPC_KURINNAXX: + _kurinnaxxGUID = creature->GetGUID(); break; case NPC_RAJAXX: _rajaxxGUID = creature->GetGUID(); @@ -75,7 +84,7 @@ public: switch (type) { case DATA_KURINNAXX: - return _kurinaxxGUID; + return _kurinnaxxGUID; case DATA_RAJAXX: return _rajaxxGUID; case DATA_MOAM: @@ -137,7 +146,7 @@ public: } private: - ObjectGuid _kurinaxxGUID; + ObjectGuid _kurinnaxxGUID; ObjectGuid _rajaxxGUID; ObjectGuid _moamGUID; ObjectGuid _buruGUID; diff --git a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/ruins_of_ahnqiraj.h b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/ruins_of_ahnqiraj.h index f79e1c710..458966ffe 100644 --- a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/ruins_of_ahnqiraj.h +++ b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/ruins_of_ahnqiraj.h @@ -37,7 +37,7 @@ enum DataTypes enum Creatures { - NPC_KURINAXX = 15348, + NPC_KURINNAXX = 15348, NPC_RAJAXX = 15341, NPC_MOAM = 15340, NPC_BURU = 15370, @@ -66,4 +66,6 @@ inline AI* GetRuinsOfAhnQirajAI(T* obj) return GetInstanceAI(obj, RuinsOfAhnQirajScriptName); } +#define RegisterRuinsOfAhnQirajCreatureAI(ai_name) RegisterCreatureAIWithFactory(ai_name, GetRuinsOfAhnQirajAI) + #endif From a7b27238238fd5683c8da25b0d8c13e3b5cf4a1b Mon Sep 17 00:00:00 2001 From: AzerothCoreBot Date: Sun, 24 Jul 2022 21:01:00 +0000 Subject: [PATCH 083/130] chore(DB): import pending files Referenced commit(s): 577ae14b2599c2d4797587fc77ceb47740912dbf --- .../rev_1658689583030214000.sql => db_world/2022_07_24_07.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/rev_1658689583030214000.sql => db_world/2022_07_24_07.sql} (80%) diff --git a/data/sql/updates/pending_db_world/rev_1658689583030214000.sql b/data/sql/updates/db_world/2022_07_24_07.sql similarity index 80% rename from data/sql/updates/pending_db_world/rev_1658689583030214000.sql rename to data/sql/updates/db_world/2022_07_24_07.sql index c9719fd55..e05b9a2fa 100644 --- a/data/sql/updates/pending_db_world/rev_1658689583030214000.sql +++ b/data/sql/updates/db_world/2022_07_24_07.sql @@ -1,3 +1,4 @@ +-- DB update 2022_07_24_06 -> 2022_07_24_07 -- UPDATE `gameobject_template` SET `ScriptName` = 'go_sand_trap' WHERE `entry` = 180647; From 35194434d7a86dd47a728a23d435e5261802d9ba Mon Sep 17 00:00:00 2001 From: Nefertumm Date: Mon, 25 Jul 2022 01:13:18 -0300 Subject: [PATCH 084/130] chore(Scripts): remove double method calling for ZG script (#12517) --- .../scripts/EasternKingdoms/ZulGurub/instance_zulgurub.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/instance_zulgurub.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/instance_zulgurub.cpp index a99c4ad5f..2e1af2680 100644 --- a/src/server/scripts/EasternKingdoms/ZulGurub/instance_zulgurub.cpp +++ b/src/server/scripts/EasternKingdoms/ZulGurub/instance_zulgurub.cpp @@ -91,8 +91,6 @@ public: default: break; } - - InstanceScript::OnCreatureCreate(creature); } void OnGameObjectCreate(GameObject* go) override From d0f70b6cbf96d3c2c88c64df19dca62745b26e12 Mon Sep 17 00:00:00 2001 From: UltraNix <80540499+UltraNix@users.noreply.github.com> Date: Mon, 25 Jul 2022 12:24:51 +0200 Subject: [PATCH 085/130] fix(DB/SAI): Fixed completing quest "Into The Realm of Shadows" (#12515) --- .../rev_1658645642391085500.sql | 2 + .../game/AI/SmartScripts/SmartScript.cpp | 40 ++++++++++++------- 2 files changed, 27 insertions(+), 15 deletions(-) create mode 100644 data/sql/updates/pending_db_world/rev_1658645642391085500.sql diff --git a/data/sql/updates/pending_db_world/rev_1658645642391085500.sql b/data/sql/updates/pending_db_world/rev_1658645642391085500.sql new file mode 100644 index 000000000..23d5a918e --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1658645642391085500.sql @@ -0,0 +1,2 @@ +-- +UPDATE `smart_scripts` SET `action_param1`=500 WHERE `entryorguid`=28788 AND `source_type`=0 AND `id`=5; diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp index 9df81a469..29cda5530 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.cpp +++ b/src/server/game/AI/SmartScripts/SmartScript.cpp @@ -847,23 +847,33 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u } case SMART_ACTION_CALL_GROUPEVENTHAPPENS: { - if (!unit) - break; - - // If invoker was pet or charm - Player* player = unit->GetCharmerOrOwnerPlayerOrPlayerItself(); - if (player && GetBaseObject()) + for (WorldObject* target : targets) { - player->GroupEventHappens(e.action.quest.quest, GetBaseObject()); - LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction: SMART_ACTION_CALL_GROUPEVENTHAPPENS: Player {}, group credit for quest {}", - unit->GetGUID().ToString(), e.action.quest.quest); - } + if (!IsUnit(target)) + continue; - // Special handling for vehicles - if (Vehicle* vehicle = unit->GetVehicleKit()) - for (auto & Seat : vehicle->Seats) - if (Player* player = ObjectAccessor::GetPlayer(*unit, Seat.second.Passenger.Guid)) - player->GroupEventHappens(e.action.quest.quest, GetBaseObject()); + Unit* unitTarget = target->ToUnit(); + // If invoker was pet or charm + Player* player = unitTarget->GetCharmerOrOwnerPlayerOrPlayerItself(); + if (player && GetBaseObject()) + { + player->GroupEventHappens(e.action.quest.quest, GetBaseObject()); + LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction: SMART_ACTION_CALL_GROUPEVENTHAPPENS: Player {}, group credit for quest {}", + unit->GetGUID().ToString(), e.action.quest.quest); + } + + // Special handling for vehicles + if (Vehicle* vehicle = unitTarget->GetVehicleKit()) + { + for (auto& Seat : vehicle->Seats) + { + if (Player* player = ObjectAccessor::GetPlayer(*unitTarget, Seat.second.Passenger.Guid)) + { + player->GroupEventHappens(e.action.quest.quest, GetBaseObject()); + } + } + } + } break; } case SMART_ACTION_REMOVEAURASFROMSPELL: From dc0a9136d76f18240545e97483cb7d5a18232455 Mon Sep 17 00:00:00 2001 From: AzerothCoreBot Date: Mon, 25 Jul 2022 10:26:54 +0000 Subject: [PATCH 086/130] chore(DB): import pending files Referenced commit(s): d0f70b6cbf96d3c2c88c64df19dca62745b26e12 --- .../rev_1658645642391085500.sql => db_world/2022_07_25_00.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/rev_1658645642391085500.sql => db_world/2022_07_25_00.sql} (71%) diff --git a/data/sql/updates/pending_db_world/rev_1658645642391085500.sql b/data/sql/updates/db_world/2022_07_25_00.sql similarity index 71% rename from data/sql/updates/pending_db_world/rev_1658645642391085500.sql rename to data/sql/updates/db_world/2022_07_25_00.sql index 23d5a918e..805766367 100644 --- a/data/sql/updates/pending_db_world/rev_1658645642391085500.sql +++ b/data/sql/updates/db_world/2022_07_25_00.sql @@ -1,2 +1,3 @@ +-- DB update 2022_07_24_07 -> 2022_07_25_00 -- UPDATE `smart_scripts` SET `action_param1`=500 WHERE `entryorguid`=28788 AND `source_type`=0 AND `id`=5; From 8f2ca7c694a48d182756fed75b936afd85fc44fc Mon Sep 17 00:00:00 2001 From: temperrr Date: Mon, 25 Jul 2022 14:56:51 +0200 Subject: [PATCH 087/130] fix(DB/Formations): Qiraji Gladiator should be linked together (#12531) fix(Formation/Creature): Qiarji Gladiator should be linked together --- .../updates/pending_db_world/qirajigladiatorlink.sql | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 data/sql/updates/pending_db_world/qirajigladiatorlink.sql diff --git a/data/sql/updates/pending_db_world/qirajigladiatorlink.sql b/data/sql/updates/pending_db_world/qirajigladiatorlink.sql new file mode 100644 index 000000000..f80fd8992 --- /dev/null +++ b/data/sql/updates/pending_db_world/qirajigladiatorlink.sql @@ -0,0 +1,10 @@ +DELETE FROM `creature_formations` WHERE `leaderguid` IN (144488, 144486, 144484, 144483); +INSERT INTO `creature_formations` (`leaderGUID`, `memberGUID`, `dist`, `angle`, `groupAI`, `point_1`, `point_2`) VALUES +(144488, 144488, 0, 0, 3, 0, 0), +(144488, 144489, 0, 0, 3, 0, 0), +(144486, 144486, 0, 0, 3, 0, 0), +(144486, 144487, 0, 0, 3, 0, 0), +(144484, 144484, 0, 0, 3, 0, 0), +(144484, 144485, 0, 0, 3, 0, 0), +(144483, 144483, 0, 0, 3, 0, 0), +(144483, 144482, 0, 0, 3, 0, 0); From 9907bdfc00c029619ec918ed70ed518b9dc40004 Mon Sep 17 00:00:00 2001 From: AzerothCoreBot Date: Mon, 25 Jul 2022 12:58:59 +0000 Subject: [PATCH 088/130] chore(DB): import pending files Referenced commit(s): 8f2ca7c694a48d182756fed75b936afd85fc44fc --- .../qirajigladiatorlink.sql => db_world/2022_07_25_01.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/qirajigladiatorlink.sql => db_world/2022_07_25_01.sql} (91%) diff --git a/data/sql/updates/pending_db_world/qirajigladiatorlink.sql b/data/sql/updates/db_world/2022_07_25_01.sql similarity index 91% rename from data/sql/updates/pending_db_world/qirajigladiatorlink.sql rename to data/sql/updates/db_world/2022_07_25_01.sql index f80fd8992..09f4321f4 100644 --- a/data/sql/updates/pending_db_world/qirajigladiatorlink.sql +++ b/data/sql/updates/db_world/2022_07_25_01.sql @@ -1,3 +1,4 @@ +-- DB update 2022_07_25_00 -> 2022_07_25_01 DELETE FROM `creature_formations` WHERE `leaderguid` IN (144488, 144486, 144484, 144483); INSERT INTO `creature_formations` (`leaderGUID`, `memberGUID`, `dist`, `angle`, `groupAI`, `point_1`, `point_2`) VALUES (144488, 144488, 0, 0, 3, 0, 0), From a8ae153ffde9ef8a6e871de050d53ed85fba80b6 Mon Sep 17 00:00:00 2001 From: temperrr Date: Mon, 25 Jul 2022 14:59:27 +0200 Subject: [PATCH 089/130] fix(DB/Formations): Scarab formations AQ20 (#12530) * fix(Formations/Creature): Scarab formations AQ20 * delete --- .../pending_db_world/scarabaqformations.sql | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 data/sql/updates/pending_db_world/scarabaqformations.sql diff --git a/data/sql/updates/pending_db_world/scarabaqformations.sql b/data/sql/updates/pending_db_world/scarabaqformations.sql new file mode 100644 index 000000000..f8d5565d1 --- /dev/null +++ b/data/sql/updates/pending_db_world/scarabaqformations.sql @@ -0,0 +1,52 @@ +DELETE FROM `creature_formations` WHERE `leaderguid` IN (144698, 144695, 144715, 144684, 144726); +INSERT INTO `creature_formations` (`leaderGUID`, `memberGUID`, `dist`, `angle`, `groupAI`, `point_1`, `point_2`) VALUES +(144698, 144698, 0, 0, 3, 0, 0), +(144698, 144723, 0, 0, 3, 0, 0), +(144698, 144699, 0, 0, 3, 0, 0), +(144698, 144725, 0, 0, 3, 0, 0), +(144698, 144700, 0, 0, 3, 0, 0), +(144698, 144721, 0, 0, 3, 0, 0), +(144698, 144722, 0, 0, 3, 0, 0), +(144698, 144724, 0, 0, 3, 0, 0), +(144698, 144697, 0, 0, 3, 0, 0), +(144698, 144696, 0, 0, 3, 0, 0), +(144695, 144695, 0, 0, 3, 0, 0), +(144695, 144720, 0, 0, 3, 0, 0), +(144695, 144718, 0, 0, 3, 0, 0), +(144695, 144694, 0, 0, 3, 0, 0), +(144695, 144717, 0, 0, 3, 0, 0), +(144695, 144692, 0, 0, 3, 0, 0), +(144695, 144716, 0, 0, 3, 0, 0), +(144695, 144690, 0, 0, 3, 0, 0), +(144695, 144693, 0, 0, 3, 0, 0), +(144695, 144719, 0, 0, 3, 0, 0), +(144715, 144715, 0, 0, 3, 0, 0), +(144715, 144688, 0, 0, 3, 0, 0), +(144715, 144691, 0, 0, 3, 0, 0), +(144715, 144714, 0, 0, 3, 0, 0), +(144715, 144689, 0, 0, 3, 0, 0), +(144715, 144713, 0, 0, 3, 0, 0), +(144715, 144712, 0, 0, 3, 0, 0), +(144715, 144686, 0, 0, 3, 0, 0), +(144715, 144687, 0, 0, 3, 0, 0), +(144715, 144711, 0, 0, 3, 0, 0), +(144684, 144684, 0, 0, 3, 0, 0), +(144684, 144710, 0, 0, 3, 0, 0), +(144684, 144708, 0, 0, 3, 0, 0), +(144684, 144709, 0, 0, 3, 0, 0), +(144684, 144683, 0, 0, 3, 0, 0), +(144684, 144682, 0, 0, 3, 0, 0), +(144684, 144681, 0, 0, 3, 0, 0), +(144684, 144706, 0, 0, 3, 0, 0), +(144684, 144707, 0, 0, 3, 0, 0), +(144684, 144685, 0, 0, 3, 0, 0), +(144726, 144726, 0, 0, 3, 0, 0), +(144726, 144727, 0, 0, 3, 0, 0), +(144726, 144703, 0, 0, 3, 0, 0), +(144726, 144729, 0, 0, 3, 0, 0), +(144726, 144704, 0, 0, 3, 0, 0), +(144726, 144702, 0, 0, 3, 0, 0), +(144726, 144701, 0, 0, 3, 0, 0), +(144726, 144728, 0, 0, 3, 0, 0), +(144726, 144730, 0, 0, 3, 0, 0), +(144726, 144705, 0, 0, 3, 0, 0); From accb01f1800c8495bd5153e849ce19a2af5ede62 Mon Sep 17 00:00:00 2001 From: AzerothCoreBot Date: Mon, 25 Jul 2022 13:01:38 +0000 Subject: [PATCH 090/130] chore(DB): import pending files Referenced commit(s): a8ae153ffde9ef8a6e871de050d53ed85fba80b6 --- .../scarabaqformations.sql => db_world/2022_07_25_02.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/scarabaqformations.sql => db_world/2022_07_25_02.sql} (97%) diff --git a/data/sql/updates/pending_db_world/scarabaqformations.sql b/data/sql/updates/db_world/2022_07_25_02.sql similarity index 97% rename from data/sql/updates/pending_db_world/scarabaqformations.sql rename to data/sql/updates/db_world/2022_07_25_02.sql index f8d5565d1..5fc890f96 100644 --- a/data/sql/updates/pending_db_world/scarabaqformations.sql +++ b/data/sql/updates/db_world/2022_07_25_02.sql @@ -1,3 +1,4 @@ +-- DB update 2022_07_25_01 -> 2022_07_25_02 DELETE FROM `creature_formations` WHERE `leaderguid` IN (144698, 144695, 144715, 144684, 144726); INSERT INTO `creature_formations` (`leaderGUID`, `memberGUID`, `dist`, `angle`, `groupAI`, `point_1`, `point_2`) VALUES (144698, 144698, 0, 0, 3, 0, 0), From cd3151df40aaa32e6e363d9d6c9cc36f83c69507 Mon Sep 17 00:00:00 2001 From: Skjalf <47818697+Nyeriah@users.noreply.github.com> Date: Mon, 25 Jul 2022 12:12:08 -0300 Subject: [PATCH 091/130] fix(Scripts/RuinsOfAhnQiraj): Implement Rajaxx waves (#12513) --- .../rev_1658621389874483000.sql | 76 +++++++++ src/server/game/AI/CreatureAI.cpp | 4 + .../game/Entities/Creature/CreatureGroups.cpp | 37 +++++ .../game/Entities/Creature/CreatureGroups.h | 3 + src/server/game/Maps/ZoneScript.h | 1 + .../Kalimdor/RuinsOfAhnQiraj/boss_rajaxx.cpp | 20 +-- .../instance_ruins_of_ahnqiraj.cpp | 148 +++++++++++++++++- .../RuinsOfAhnQiraj/ruins_of_ahnqiraj.h | 23 ++- 8 files changed, 288 insertions(+), 24 deletions(-) create mode 100644 data/sql/updates/pending_db_world/rev_1658621389874483000.sql diff --git a/data/sql/updates/pending_db_world/rev_1658621389874483000.sql b/data/sql/updates/pending_db_world/rev_1658621389874483000.sql new file mode 100644 index 000000000..6b06fcfc7 --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1658621389874483000.sql @@ -0,0 +1,76 @@ +-- Captain Qeez +DELETE FROM `creature_formations` WHERE `leaderGUID` = 144676; +INSERT INTO `creature_formations` (`leaderGUID`, `memberGUID`, `dist`, `angle`, `groupAI`, `point_1`, `point_2`) VALUES +(144676, 144676, 0, 0, 11, 0, 0), +(144676, 144611, 0, 0, 11, 0, 0), +(144676, 144656, 0, 0, 11, 0, 0), +(144676, 144653, 0, 0, 11, 0, 0), +(144676, 144655, 0, 0, 11, 0, 0), +(144676, 144610, 0, 0, 11, 0, 0), +(144676, 144654, 0, 0, 11, 0, 0); + +-- Tubid +DELETE FROM `creature_formations` WHERE `leaderGUID` = 144677; +INSERT INTO `creature_formations` (`leaderGUID`, `memberGUID`, `dist`, `angle`, `groupAI`, `point_1`, `point_2`) VALUES +(144677, 144677, 0, 0, 11, 0, 0), +(144677, 144658, 0, 0, 11, 0, 0), +(144677, 144616, 0, 0, 11, 0, 0), +(144677, 144617, 0, 0, 11, 0, 0), +(144677, 144619, 0, 0, 11, 0, 0), +(144677, 144660, 0, 0, 11, 0, 0), +(144677, 144659, 0, 0, 11, 0, 0); + +-- Drenn +DELETE FROM `creature_formations` WHERE `leaderGUID` = 144674; +INSERT INTO `creature_formations` (`leaderGUID`, `memberGUID`, `dist`, `angle`, `groupAI`, `point_1`, `point_2`) VALUES +(144674, 144674, 0, 0, 11, 0, 0), +(144674, 144618, 0, 0, 11, 0, 0), +(144674, 144657, 0, 0, 11, 0, 0), +(144674, 144614, 0, 0, 11, 0, 0), +(144674, 144613, 0, 0, 11, 0, 0), +(144674, 144612, 0, 0, 11, 0, 0), +(144674, 144615, 0, 0, 11, 0, 0); + +-- Yeggeth +DELETE FROM `creature_formations` WHERE `leaderGUID` = 144652; +INSERT INTO `creature_formations` (`leaderGUID`, `memberGUID`, `dist`, `angle`, `groupAI`, `point_1`, `point_2`) VALUES +(144652, 144652, 0, 0, 11, 0, 0), +(144652, 144664, 0, 0, 11, 0, 0), +(144652, 144622, 0, 0, 11, 0, 0), +(144652, 144624, 0, 0, 11, 0, 0), +(144652, 144663, 0, 0, 11, 0, 0), +(144652, 144621, 0, 0, 11, 0, 0), +(144652, 144620, 0, 0, 11, 0, 0); + +-- Xurrem +DELETE FROM `creature_formations` WHERE `leaderGUID` = 144675; +INSERT INTO `creature_formations` (`leaderGUID`, `memberGUID`, `dist`, `angle`, `groupAI`, `point_1`, `point_2`) VALUES +(144675, 144675, 0, 0, 11, 0, 0), +(144675, 144625, 0, 0, 11, 0, 0), +(144675, 144623, 0, 0, 11, 0, 0), +(144675, 144665, 0, 0, 11, 0, 0), +(144675, 144626, 0, 0, 11, 0, 0), +(144675, 144662, 0, 0, 11, 0, 0), +(144675, 144661, 0, 0, 11, 0, 0); + +-- Pakkon +DELETE FROM `creature_formations` WHERE `leaderGUID` = 144673; +INSERT INTO `creature_formations` (`leaderGUID`, `memberGUID`, `dist`, `angle`, `groupAI`, `point_1`, `point_2`) VALUES +(144673, 144673, 0, 0, 11, 0, 0), +(144673, 144669, 0, 0, 11, 0, 0), +(144673, 144630, 0, 0, 11, 0, 0), +(144673, 144670, 0, 0, 11, 0, 0), +(144673, 144631, 0, 0, 11, 0, 0), +(144673, 144672, 0, 0, 11, 0, 0), +(144673, 144671, 0, 0, 11, 0, 0); + +-- Zerram +DELETE FROM `creature_formations` WHERE `leaderGUID` = 144651; +INSERT INTO `creature_formations` (`leaderGUID`, `memberGUID`, `dist`, `angle`, `groupAI`, `point_1`, `point_2`) VALUES +(144651, 144651, 0, 0, 11, 0, 0), +(144651, 144668, 0, 0, 11, 0, 0), +(144651, 144629, 0, 0, 11, 0, 0), +(144651, 144667, 0, 0, 11, 0, 0), +(144651, 144628, 0, 0, 11, 0, 0), +(144651, 144666, 0, 0, 11, 0, 0), +(144651, 144627, 0, 0, 11, 0, 0); diff --git a/src/server/game/AI/CreatureAI.cpp b/src/server/game/AI/CreatureAI.cpp index e310de645..14048b6f3 100644 --- a/src/server/game/AI/CreatureAI.cpp +++ b/src/server/game/AI/CreatureAI.cpp @@ -27,6 +27,7 @@ #include "Vehicle.h" #include "ScriptMgr.h" #include "Language.h" +#include "ZoneScript.h" class PhasedRespawn : public BasicEvent { @@ -308,6 +309,9 @@ bool CreatureAI::_EnterEvadeMode(EvadeReason /*why*/) me->SetLastDamagedTime(0); me->SetCannotReachTarget(); + if (ZoneScript* zoneScript = me->GetZoneScript() ? me->GetZoneScript() : (ZoneScript*)me->GetInstanceScript()) + zoneScript->OnCreatureEvade(me); + if (me->IsInEvadeMode()) { return false; diff --git a/src/server/game/Entities/Creature/CreatureGroups.cpp b/src/server/game/Entities/Creature/CreatureGroups.cpp index 030134f26..a181c571a 100644 --- a/src/server/game/Entities/Creature/CreatureGroups.cpp +++ b/src/server/game/Entities/Creature/CreatureGroups.cpp @@ -381,3 +381,40 @@ void CreatureGroup::LeaderMoveTo(float x, float y, float z, bool run) } } } + +void CreatureGroup::RespawnFormation(bool force) +{ + for (auto const& itr : m_members) + { + if (itr.first && !itr.first->IsAlive()) + { + itr.first->Respawn(force); + } + } +} + +bool CreatureGroup::IsFormationInCombat() +{ + for (auto const& itr : m_members) + { + if (itr.first && itr.first->IsInCombat()) + { + return true; + } + } + + return false; +} + +bool CreatureGroup::IsAnyMemberAlive() +{ + for (auto const& itr : m_members) + { + if (itr.first && itr.first->IsAlive()) + { + return true; + } + } + + return false; +} diff --git a/src/server/game/Entities/Creature/CreatureGroups.h b/src/server/game/Entities/Creature/CreatureGroups.h index 9a4db6736..9fe3398f5 100644 --- a/src/server/game/Entities/Creature/CreatureGroups.h +++ b/src/server/game/Entities/Creature/CreatureGroups.h @@ -109,6 +109,9 @@ public: void LeaderMoveTo(float x, float y, float z, bool run); void MemberEngagingTarget(Creature* member, Unit* target); void MemberEvaded(Creature* member); + void RespawnFormation(bool force = false); + [[nodiscard]] bool IsFormationInCombat(); + [[nodiscard]] bool IsAnyMemberAlive(); private: Creature* m_leader; //Important do not forget sometimes to work with pointers instead synonims :D:D diff --git a/src/server/game/Maps/ZoneScript.h b/src/server/game/Maps/ZoneScript.h index 7a52ba113..ae795f6aa 100644 --- a/src/server/game/Maps/ZoneScript.h +++ b/src/server/game/Maps/ZoneScript.h @@ -39,6 +39,7 @@ public: virtual void OnGameObjectRemove(GameObject*) { } virtual void OnUnitDeath(Unit*) { } + virtual void OnCreatureEvade(Creature*) { } //All-purpose data storage 64 bit virtual ObjectGuid GetGuidData(uint32 /*DataId*/) const { return ObjectGuid::Empty; } diff --git a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_rajaxx.cpp b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_rajaxx.cpp index d9587d28e..2c648dfb0 100644 --- a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_rajaxx.cpp +++ b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_rajaxx.cpp @@ -22,16 +22,6 @@ enum Yells { - // The time of our retribution is at hand! Let darkness reign in the hearts of our enemies! Sound: 8645 Emote: 35 - SAY_ANDOROV_INTRO = 0, // Before for the first wave - SAY_ANDOROV_ATTACK = 1, // Beginning the event - - SAY_WAVE3 = 0, - SAY_WAVE4 = 1, - SAY_WAVE5 = 2, - SAY_WAVE6 = 3, - SAY_WAVE7 = 4, - SAY_INTRO = 5, SAY_UNK1 = 6, SAY_UNK2 = 7, SAY_UNK3 = 8, @@ -63,27 +53,25 @@ public: struct boss_rajaxxAI : public BossAI { - boss_rajaxxAI(Creature* creature) : BossAI(creature, DATA_RAJAXX) - { - } + boss_rajaxxAI(Creature* creature) : BossAI(creature, DATA_RAJAXX) { } void Reset() override { _Reset(); enraged = false; - events.ScheduleEvent(EVENT_DISARM, 10000); - events.ScheduleEvent(EVENT_THUNDERCRASH, 12000); } void JustDied(Unit* /*killer*/) override { - //SAY_DEATH + Talk(SAY_DEATH); _JustDied(); } void EnterCombat(Unit* /*victim*/) override { _EnterCombat(); + events.ScheduleEvent(EVENT_DISARM, 10000); + events.ScheduleEvent(EVENT_THUNDERCRASH, 12000); } void UpdateAI(uint32 diff) override 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 d651cfde6..a84522ab0 100644 --- a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/instance_ruins_of_ahnqiraj.cpp +++ b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/instance_ruins_of_ahnqiraj.cpp @@ -15,14 +15,46 @@ * with this program. If not, see . */ +#include "CreatureGroups.h" #include "InstanceScript.h" #include "ScriptMgr.h" +#include "TaskScheduler.h" #include "ruins_of_ahnqiraj.h" ObjectData const creatureData[] = { - { NPC_OSSIRIAN, DATA_OSSIRIAN }, - { NPC_KURINNAXX, DATA_KURINNAXX } + { NPC_KURINNAXX, DATA_KURINNAXX }, + { NPC_RAJAXX, DATA_RAJAXX }, + { NPC_OSSIRIAN, DATA_OSSIRIAN }, + { NPC_QUUEZ, DATA_QUUEZ }, + { NPC_TUUBID, DATA_TUUBID }, + { NPC_DRENN, DATA_DRENN }, + { NPC_XURREM, DATA_XURREM }, + { NPC_YEGGETH, DATA_YEGGETH }, + { NPC_PAKKON, DATA_PAKKON }, + { NPC_ZERRAN, DATA_ZERRAN }, +}; + +enum RajaxxText +{ + SAY_WAVE3 = 0, + SAY_WAVE4 = 1, + SAY_WAVE5 = 2, + SAY_WAVE6 = 3, + SAY_WAVE7 = 4, + SAY_ENGAGE = 5 +}; + +std::array RajaxxWavesData[] = +{ + { DATA_QUUEZ, 0 }, + { DATA_TUUBID, 0 }, + { DATA_DRENN, SAY_WAVE3 }, + { DATA_XURREM, SAY_WAVE4 }, + { DATA_YEGGETH, SAY_WAVE5 }, + { DATA_PAKKON, SAY_WAVE6 }, + { DATA_ZERRAN, SAY_WAVE7 }, + { DATA_RAJAXX, SAY_ENGAGE } }; class instance_ruins_of_ahnqiraj : public InstanceMapScript @@ -36,6 +68,7 @@ public: { SetBossNumber(NUM_ENCOUNTER); LoadObjectData(creatureData, nullptr); + _rajaxWaveCounter = 0; } void OnCreatureCreate(Creature* creature) override @@ -65,12 +98,73 @@ public: } } - bool SetBossState(uint32 bossId, EncounterState state) override + void OnCreatureEvade(Creature* creature) override { - if (!InstanceScript::SetBossState(bossId, state)) - return false; + if (CreatureGroup* formation = creature->GetFormation()) + { + if (Creature* leader = formation->GetLeader()) + { + switch (leader->GetEntry()) + { + case NPC_QUUEZ: + case NPC_TUUBID: + case NPC_DRENN: + case NPC_XURREM: + case NPC_YEGGETH: + case NPC_PAKKON: + case NPC_ZERRAN: + if (!formation->IsFormationInCombat()) + { + ResetRajaxxWaves(); + } + break; + default: + break; + } + } + } + else if (creature->GetEntry() == NPC_RAJAXX) + { + ResetRajaxxWaves(); + } + } - return true; + void OnUnitDeath(Unit* unit) override + { + if (Creature* creature = unit->ToCreature()) + { + if (CreatureGroup* formation = creature->GetFormation()) + { + if (Creature* leader = formation->GetLeader()) + { + switch (leader->GetEntry()) + { + case NPC_QUUEZ: + case NPC_TUUBID: + case NPC_DRENN: + case NPC_XURREM: + case NPC_YEGGETH: + case NPC_PAKKON: + case NPC_ZERRAN: + _scheduler.CancelAll(); + _scheduler.Schedule(1s, [this, formation](TaskContext /*context*/) { + if (!formation->IsAnyMemberAlive()) + { + CallNextRajaxxLeader(); + } + }); + break; + default: + break; + } + } + } + } + } + + void Update(uint32 diff) override + { + _scheduler.Update(diff); } void SetGuidData(uint32 type, ObjectGuid data) override @@ -145,6 +239,46 @@ public: OUT_LOAD_INST_DATA_COMPLETE; } + void CallNextRajaxxLeader() + { + ++_rajaxWaveCounter; + + if (Creature* nextLeader = GetCreature(RajaxxWavesData[_rajaxWaveCounter].at(0))) + { + if (_rajaxWaveCounter >= 2) + { + if (Creature* rajaxx = GetCreature(DATA_RAJAXX)) + { + rajaxx->AI()->Talk(RajaxxWavesData[_rajaxWaveCounter].at(1)); + } + } + + if (nextLeader->IsAlive()) + { + nextLeader->SetInCombatWithZone(); + } + else + { + CallNextRajaxxLeader(); + } + } + } + + void ResetRajaxxWaves() + { + _rajaxWaveCounter = 0; + for (auto const& data : RajaxxWavesData) + { + if (Creature* creature = GetCreature(data.at(0))) + { + if (CreatureGroup* group = creature->GetFormation()) + { + group->RespawnFormation(true); + } + } + } + } + private: ObjectGuid _kurinnaxxGUID; ObjectGuid _rajaxxGUID; @@ -153,6 +287,8 @@ public: ObjectGuid _ayamissGUID; ObjectGuid _ossirianGUID; ObjectGuid _paralyzedGUID; + uint32 _rajaxWaveCounter; + TaskScheduler _scheduler; }; InstanceScript* GetInstanceScript(InstanceMap* map) const override diff --git a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/ruins_of_ahnqiraj.h b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/ruins_of_ahnqiraj.h index 458966ffe..522b70c78 100644 --- a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/ruins_of_ahnqiraj.h +++ b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/ruins_of_ahnqiraj.h @@ -32,7 +32,17 @@ enum DataTypes DATA_OSSIRIAN = 5, NUM_ENCOUNTER = 6, - DATA_PARALYZED = 7 + DATA_PARALYZED = 7, + + DATA_QUUEZ = 8, + DATA_TUUBID = 9, + DATA_DRENN = 10, + DATA_XURREM = 11, + DATA_YEGGETH = 12, + DATA_PAKKON = 13, + DATA_ZERRAN = 14, + + DATA_ENGAGED_FORMATION = 1 }; enum Creatures @@ -52,7 +62,16 @@ enum Creatures NPC_BURU_EGG = 15514, NPC_LARVA = 15555, NPC_SWARMER = 15546, - NPC_HORNET = 15934 + NPC_HORNET = 15934, + + // Rajaxx + NPC_QUUEZ = 15391, + NPC_TUUBID = 15392, + NPC_DRENN = 15389, + NPC_XURREM = 15390, + NPC_YEGGETH = 15386, + NPC_PAKKON = 15388, + NPC_ZERRAN = 15385 }; enum GameObjects From e3c7b52253b8c78f4104fb3068c28b250c77efe2 Mon Sep 17 00:00:00 2001 From: Skjalf <47818697+Nyeriah@users.noreply.github.com> Date: Mon, 25 Jul 2022 12:12:27 -0300 Subject: [PATCH 092/130] =?UTF-8?q?feat(Core/Creature):=20Implement=20SetR?= =?UTF-8?q?egeneratingPower()=20to=20disable=20powe=E2=80=A6=20(#12535)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit feat(Core/Creature): Implement SetRegeneratingPower() to disable power gains --- src/server/game/Entities/Creature/Creature.cpp | 7 ++++++- src/server/game/Entities/Creature/Creature.h | 2 ++ src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_moam.cpp | 1 + 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index 772d74cc9..046d404a8 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -219,7 +219,7 @@ Creature::Creature(bool isWorldObject): Unit(isWorldObject), MovableMapObject(), m_corpseRemoveTime(0), m_respawnTime(0), m_respawnDelay(300), m_corpseDelay(60), m_wanderDistance(0.0f), m_boundaryCheckTime(2500), m_transportCheckTimer(1000), lootPickPocketRestoreTime(0), m_reactState(REACT_AGGRESSIVE), m_defaultMovementType(IDLE_MOTION_TYPE), m_spawnId(0), m_equipmentId(0), m_originalEquipmentId(0), m_AlreadyCallAssistance(false), - m_AlreadySearchedAssistance(false), m_regenHealth(true), m_AI_locked(false), m_meleeDamageSchoolMask(SPELL_SCHOOL_MASK_NORMAL), m_originalEntry(0), m_moveInLineOfSightDisabled(false), m_moveInLineOfSightStrictlyDisabled(false), + m_AlreadySearchedAssistance(false), m_regenHealth(true), m_regenPower(true), m_AI_locked(false), m_meleeDamageSchoolMask(SPELL_SCHOOL_MASK_NORMAL), m_originalEntry(0), m_moveInLineOfSightDisabled(false), m_moveInLineOfSightStrictlyDisabled(false), m_homePosition(), m_transportHomePosition(), m_creatureInfo(nullptr), m_creatureData(nullptr), m_detectionDistance(20.0f), m_waypointID(0), m_path_id(0), m_formation(nullptr), _lastDamagedTime(nullptr), m_cannotReachTimer(0), _isMissingSwimmingFlagOutOfCombat(false), m_assistanceTimer(0), _playerDamageReq(0), _damagedByPlayer(false) { @@ -914,6 +914,11 @@ void Creature::Regenerate(Powers power) if (!HasUnitFlag2(UNIT_FLAG2_REGENERATE_POWER) && !GetOwnerGUID().IsPlayer()) return; + if (!m_regenPower) + { + return; + } + if (curValue >= maxValue) return; diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h index d97d6ef17..447515ebc 100644 --- a/src/server/game/Entities/Creature/Creature.h +++ b/src/server/game/Entities/Creature/Creature.h @@ -300,6 +300,7 @@ public: bool isRegeneratingHealth() { return m_regenHealth; } void SetRegeneratingHealth(bool c) { m_regenHealth = c; } + void SetRegeneratingPower(bool c) { m_regenPower = c; } [[nodiscard]] virtual uint8 GetPetAutoSpellSize() const { return MAX_SPELL_CHARM; } [[nodiscard]] virtual uint32 GetPetAutoSpellOnPos(uint8 pos) const { @@ -417,6 +418,7 @@ protected: bool m_AlreadyCallAssistance; bool m_AlreadySearchedAssistance; bool m_regenHealth; + bool m_regenPower; bool m_AI_locked; SpellSchoolMask m_meleeDamageSchoolMask; diff --git a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_moam.cpp b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_moam.cpp index f38bfd8e0..3bc0f9d55 100644 --- a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_moam.cpp +++ b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_moam.cpp @@ -66,6 +66,7 @@ public: { _Reset(); me->SetPower(POWER_MANA, 0); + me->SetRegeneratingPower(false); _isStonePhase = false; events.ScheduleEvent(EVENT_STONE_PHASE, 90000); //events.ScheduleEvent(EVENT_WIDE_SLASH, 11000); From 1cec5d25343ce177ebe2ea9ea6b24d190bb6d02e Mon Sep 17 00:00:00 2001 From: Skjalf <47818697+Nyeriah@users.noreply.github.com> Date: Mon, 25 Jul 2022 12:12:43 -0300 Subject: [PATCH 093/130] =?UTF-8?q?refactor(Scripts/TempleOfAhnQiraj):=20R?= =?UTF-8?q?emove=20Giant=20Flesh=20Claw=20script=20as=E2=80=A6=20(#12526)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit refactor(Scripts/TempleOfAhnQiraj): Remove Giant Flesh Claw script as it is not needed --- .../rev_1658719876642198500.sql | 6 ++++ .../Kalimdor/TempleOfAhnQiraj/boss_cthun.cpp | 36 ++----------------- 2 files changed, 9 insertions(+), 33 deletions(-) create mode 100644 data/sql/updates/pending_db_world/rev_1658719876642198500.sql diff --git a/data/sql/updates/pending_db_world/rev_1658719876642198500.sql b/data/sql/updates/pending_db_world/rev_1658719876642198500.sql new file mode 100644 index 000000000..b04cd7172 --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1658719876642198500.sql @@ -0,0 +1,6 @@ +-- +DELETE FROM `creature_template_movement` WHERE `creatureId` = 15802; +INSERT INTO `creature_template_movement` (`CreatureId`, `Ground`, `Swim`, `Flight`, `Rooted`, `Chase`, `Random`, `InteractionPauseTimer`) VALUES +(15802, 1, 0, 0, 1, 0, 0, 0); + +UPDATE `creature_template` SET `ScriptName` = '' WHERE `entry` = 15802; diff --git a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_cthun.cpp b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_cthun.cpp index c262aafe2..e2a9f9453 100644 --- a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_cthun.cpp +++ b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_cthun.cpp @@ -831,13 +831,11 @@ public: } } - void DoAction(int32 param) override + void SummonedCreatureDies(Creature* creature, Unit* /*killer*/) override { - switch (param) + if (creature->GetEntry() == NPC_FLESH_TENTACLE) { - case ACTION_FLESH_TENTACLE_KILLED: - ++FleshTentaclesKilled; - break; + ++FleshTentaclesKilled; } } }; @@ -1190,33 +1188,6 @@ public: }; }; -class npc_giant_flesh_tentacle : public CreatureScript -{ -public: - npc_giant_flesh_tentacle() : CreatureScript("npc_giant_flesh_tentacle") { } - - CreatureAI* GetAI(Creature* creature) const override - { - return new flesh_tentacleAI(creature); - } - - struct flesh_tentacleAI : public ScriptedAI - { - flesh_tentacleAI(Creature* creature) : ScriptedAI(creature) - { - SetCombatMovement(false); - } - - void JustDied(Unit* /*killer*/) override - { - if (TempSummon* summon = me->ToTempSummon()) - if (Unit* summoner = summon->GetSummonerUnit()) - if (summoner->IsAIEnabled) - summoner->GetAI()->DoAction(ACTION_FLESH_TENTACLE_KILLED); - } - }; -}; - //GetAIs void AddSC_boss_cthun() @@ -1227,5 +1198,4 @@ void AddSC_boss_cthun() new npc_claw_tentacle(); new npc_giant_claw_tentacle(); new npc_giant_eye_tentacle(); - new npc_giant_flesh_tentacle(); } From 5b142671593c0c4f64359df159f3093892fba95b Mon Sep 17 00:00:00 2001 From: Skjalf <47818697+Nyeriah@users.noreply.github.com> Date: Mon, 25 Jul 2022 12:13:06 -0300 Subject: [PATCH 094/130] fix(Scripts/Spells): Script spell Itch (AQ20) and improve Consume (AQ20) (#12502) --- .../rev_1658582043233714100.sql | 3 + src/server/scripts/Spells/spell_generic.cpp | 58 +++++++++++++++++-- 2 files changed, 57 insertions(+), 4 deletions(-) create mode 100644 data/sql/updates/pending_db_world/rev_1658582043233714100.sql diff --git a/data/sql/updates/pending_db_world/rev_1658582043233714100.sql b/data/sql/updates/pending_db_world/rev_1658582043233714100.sql new file mode 100644 index 000000000..c063deef4 --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1658582043233714100.sql @@ -0,0 +1,3 @@ +-- +DELETE FROM `spell_script_names` WHERE `spell_id` = 25185 AND `ScriptName` = 'spell_itch_aq20'; +INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES (25185, 'spell_itch_aq20'); diff --git a/src/server/scripts/Spells/spell_generic.cpp b/src/server/scripts/Spells/spell_generic.cpp index 9b4af72b0..8204f55b4 100644 --- a/src/server/scripts/Spells/spell_generic.cpp +++ b/src/server/scripts/Spells/spell_generic.cpp @@ -4475,7 +4475,10 @@ class spell_gen_remove_impairing_auras : public SpellScript enum AQSpells { SPELL_CONSUME_LEECH_AQ20 = 25373, - SPELL_CONSUME_LEECH_HEAL_AQ20 = 25378 + SPELL_CONSUME_LEECH_HEAL_AQ20 = 25378, + SPELL_CONSUME_SPIT_OUT = 25383, + + SPELL_HIVEZARA_CATALYST = 25187 }; class spell_gen_consume : public AuraScript @@ -4494,18 +4497,30 @@ public: { if (Unit* caster = GetCaster()) { + if (!caster->IsAlive()) + { + GetUnitOwner()->RemoveAurasDueToSpell(GetSpellInfo()->Id); + return; + } + caster->CastSpell(GetUnitOwner(), _spellId1, true); } } void AfterRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) { - // Final heal only on duration end - if (GetTargetApplication() && GetTargetApplication()->GetRemoveMode() == AURA_REMOVE_BY_DEATH) + if (GetTargetApplication()) { if (Unit* caster = GetCaster()) { - caster->CastSpell(caster, _spellId2, true); + if (GetTargetApplication()->GetRemoveMode() == AURA_REMOVE_BY_DEATH) + { + caster->CastSpell(caster, _spellId2, true); + } + else if (GetTargetApplication()->GetRemoveMode() == AURA_REMOVE_BY_EXPIRE) + { + caster->CastSpell(GetTarget(), SPELL_CONSUME_SPIT_OUT, true); + } } } } @@ -4521,6 +4536,40 @@ private: uint32 _spellId2; }; +class spell_gen_apply_aura_after_expiration : public AuraScript +{ + PrepareAuraScript(spell_gen_apply_aura_after_expiration); + +public: + spell_gen_apply_aura_after_expiration(uint32 spellId, uint32 effect, uint32 aura) : AuraScript(), _spellId(spellId), _effect(effect), _aura(aura) { } + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo({ _spellId }); + } + + void AfterRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + if (GetTargetApplication() && GetTargetApplication()->GetRemoveMode() == AURA_REMOVE_BY_EXPIRE) + { + if (Unit* caster = GetCaster()) + { + caster->CastSpell(GetTarget(), _spellId, true); + } + } + } + + void Register() override + { + AfterEffectRemove += AuraEffectRemoveFn(spell_gen_apply_aura_after_expiration::AfterRemove, _effect, _aura, AURA_EFFECT_HANDLE_REAL); + } + +private: + uint32 _spellId; + uint32 _effect; + uint32 _aura; +}; + void AddSC_generic_spell_scripts() { RegisterSpellScript(spell_silithyst); @@ -4656,4 +4705,5 @@ void AddSC_generic_spell_scripts() RegisterSpellScript(spell_gen_arcane_charge); RegisterSpellScript(spell_gen_remove_impairing_auras); RegisterSpellScriptWithArgs(spell_gen_consume, "spell_consume_aq20", SPELL_CONSUME_LEECH_AQ20, SPELL_CONSUME_LEECH_HEAL_AQ20); + RegisterSpellScriptWithArgs(spell_gen_apply_aura_after_expiration, "spell_itch_aq20", SPELL_HIVEZARA_CATALYST, EFFECT_0, SPELL_AURA_DUMMY); } From 344d80e216e8c05d9b79e13447d6b0e08e87d609 Mon Sep 17 00:00:00 2001 From: AzerothCoreBot Date: Mon, 25 Jul 2022 15:15:16 +0000 Subject: [PATCH 095/130] chore(DB): import pending files Referenced commit(s): 5b142671593c0c4f64359df159f3093892fba95b --- .../rev_1658582043233714100.sql => db_world/2022_07_25_03.sql} | 1 + .../rev_1658621389874483000.sql => db_world/2022_07_25_04.sql} | 1 + .../rev_1658719876642198500.sql => db_world/2022_07_25_05.sql} | 1 + 3 files changed, 3 insertions(+) rename data/sql/updates/{pending_db_world/rev_1658582043233714100.sql => db_world/2022_07_25_03.sql} (81%) rename data/sql/updates/{pending_db_world/rev_1658621389874483000.sql => db_world/2022_07_25_04.sql} (98%) rename data/sql/updates/{pending_db_world/rev_1658719876642198500.sql => db_world/2022_07_25_05.sql} (87%) diff --git a/data/sql/updates/pending_db_world/rev_1658582043233714100.sql b/data/sql/updates/db_world/2022_07_25_03.sql similarity index 81% rename from data/sql/updates/pending_db_world/rev_1658582043233714100.sql rename to data/sql/updates/db_world/2022_07_25_03.sql index c063deef4..bff1790eb 100644 --- a/data/sql/updates/pending_db_world/rev_1658582043233714100.sql +++ b/data/sql/updates/db_world/2022_07_25_03.sql @@ -1,3 +1,4 @@ +-- DB update 2022_07_25_02 -> 2022_07_25_03 -- DELETE FROM `spell_script_names` WHERE `spell_id` = 25185 AND `ScriptName` = 'spell_itch_aq20'; INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES (25185, 'spell_itch_aq20'); diff --git a/data/sql/updates/pending_db_world/rev_1658621389874483000.sql b/data/sql/updates/db_world/2022_07_25_04.sql similarity index 98% rename from data/sql/updates/pending_db_world/rev_1658621389874483000.sql rename to data/sql/updates/db_world/2022_07_25_04.sql index 6b06fcfc7..28073f0bd 100644 --- a/data/sql/updates/pending_db_world/rev_1658621389874483000.sql +++ b/data/sql/updates/db_world/2022_07_25_04.sql @@ -1,3 +1,4 @@ +-- DB update 2022_07_25_03 -> 2022_07_25_04 -- Captain Qeez DELETE FROM `creature_formations` WHERE `leaderGUID` = 144676; INSERT INTO `creature_formations` (`leaderGUID`, `memberGUID`, `dist`, `angle`, `groupAI`, `point_1`, `point_2`) VALUES diff --git a/data/sql/updates/pending_db_world/rev_1658719876642198500.sql b/data/sql/updates/db_world/2022_07_25_05.sql similarity index 87% rename from data/sql/updates/pending_db_world/rev_1658719876642198500.sql rename to data/sql/updates/db_world/2022_07_25_05.sql index b04cd7172..feb66b714 100644 --- a/data/sql/updates/pending_db_world/rev_1658719876642198500.sql +++ b/data/sql/updates/db_world/2022_07_25_05.sql @@ -1,3 +1,4 @@ +-- DB update 2022_07_25_04 -> 2022_07_25_05 -- DELETE FROM `creature_template_movement` WHERE `creatureId` = 15802; INSERT INTO `creature_template_movement` (`CreatureId`, `Ground`, `Swim`, `Flight`, `Rooted`, `Chase`, `Random`, `InteractionPauseTimer`) VALUES From 3564d019d28a31965dd422c8cf4a8b1613d79386 Mon Sep 17 00:00:00 2001 From: temperrr Date: Mon, 25 Jul 2022 17:33:46 +0200 Subject: [PATCH 096/130] fix(DB/SAI): AQ20 Trash improvements (#12528) --- .../pending_db_world/aq20trashupdate.sql | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 data/sql/updates/pending_db_world/aq20trashupdate.sql diff --git a/data/sql/updates/pending_db_world/aq20trashupdate.sql b/data/sql/updates/pending_db_world/aq20trashupdate.sql new file mode 100644 index 000000000..b7f970d97 --- /dev/null +++ b/data/sql/updates/pending_db_world/aq20trashupdate.sql @@ -0,0 +1,18 @@ +UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 15343; +DELETE FROM `smart_scripts` WHERE (`entryorguid` = 15343) AND (`source_type` = 0) AND (`id` IN (0)); +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(15343, 0, 0, 0, 9, 0, 100, 0, 0, 5, 5000, 7000, 0, 11, 25174, 3, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 'Qiraji Swarmguard - Within 0-5 Range - Cast \'Sundering Cleave\''); + +UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 15325; +DELETE FROM `smart_scripts` WHERE (`entryorguid` = 15325) AND (`source_type` = 0) AND (`id` IN (0)); +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(15325, 0, 0, 0, 9, 0, 100, 0, 0, 40, 11000, 16000, 0, 11, 25185, 4, 3, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 'Hive\'Zara Wasp - Within 0-40 Range - Cast \'Itch\''); + +UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 15338; +DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 15338); +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(15338, 0, 0, 0, 0, 0, 100, 0, 5000, 9000, 8000, 11000, 0, 11, 25756, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Obsidian Destroyer - In Combat - Cast \'Purge\''), +(15338, 0, 1, 0, 0, 0, 100, 0, 2000, 4000, 6000, 6000, 0, 11, 25755, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Obsidian Destroyer - In Combat - Cast \'Drain Mana\''), +(15338, 0, 2, 0, 6, 0, 100, 0, 0, 0, 0, 0, 0, 11, 27627, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'Obsidian Destroyer - On Just Died - Cast \'Serverside - Drop Obsidian\''), +(15338, 0, 3, 0, 7, 0, 100, 0, 0, 0, 0, 0, 0, 108, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Obsidian Destroyer - On Respawn - Set Mana To 0'); +UPDATE `creature_template` SET `unit_flags2` = 0 WHERE (`entry` = 15338); From 54d18c46ad262d7b924efe360aa2e66d385d571c Mon Sep 17 00:00:00 2001 From: AzerothCoreBot Date: Mon, 25 Jul 2022 15:35:52 +0000 Subject: [PATCH 097/130] chore(DB): import pending files Referenced commit(s): 3564d019d28a31965dd422c8cf4a8b1613d79386 --- .../aq20trashupdate.sql => db_world/2022_07_25_06.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/aq20trashupdate.sql => db_world/2022_07_25_06.sql} (98%) diff --git a/data/sql/updates/pending_db_world/aq20trashupdate.sql b/data/sql/updates/db_world/2022_07_25_06.sql similarity index 98% rename from data/sql/updates/pending_db_world/aq20trashupdate.sql rename to data/sql/updates/db_world/2022_07_25_06.sql index b7f970d97..a11a226dd 100644 --- a/data/sql/updates/pending_db_world/aq20trashupdate.sql +++ b/data/sql/updates/db_world/2022_07_25_06.sql @@ -1,3 +1,4 @@ +-- DB update 2022_07_25_05 -> 2022_07_25_06 UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 15343; DELETE FROM `smart_scripts` WHERE (`entryorguid` = 15343) AND (`source_type` = 0) AND (`id` IN (0)); INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES From 2a7b5685e98210833e7803570d9fba7289e14ad5 Mon Sep 17 00:00:00 2001 From: Skjalf <47818697+Nyeriah@users.noreply.github.com> Date: Mon, 25 Jul 2022 15:27:03 -0300 Subject: [PATCH 098/130] =?UTF-8?q?fix(Scripts/RuinsOfAhnQiraj):=20Moam=20?= =?UTF-8?q?should=20spawn=20a=20Large=20Obsidian=20Chun=E2=80=A6=20(#12536?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../scripts/Kalimdor/RuinsOfAhnQiraj/boss_moam.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_moam.cpp b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_moam.cpp index 3bc0f9d55..7a1fd966a 100644 --- a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_moam.cpp +++ b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_moam.cpp @@ -33,7 +33,9 @@ enum Spells SPELL_SUMMON_MANA_FIEND_1 = 25681, // TARGET_DEST_CASTER_FRONT SPELL_SUMMON_MANA_FIEND_2 = 25682, // TARGET_DEST_CASTER_LEFT SPELL_SUMMON_MANA_FIEND_3 = 25683, // TARGET_DEST_CASTER_RIGHT - SPELL_ENERGIZE = 25685 + SPELL_ENERGIZE = 25685, + + SPELL_LARGE_OBSIDIAN_CHUNK = 27630 // Server-side }; enum Events @@ -106,6 +108,12 @@ public: } } + void JustDied(Unit* /*killer*/) override + { + _JustDied(); + DoCastAOE(SPELL_LARGE_OBSIDIAN_CHUNK, true); + } + void UpdateAI(uint32 diff) override { if (!UpdateVictim()) From 7aea91fcb3f43f1401e1383e6ccc4de218d79b1a Mon Sep 17 00:00:00 2001 From: UltraNix <80540499+UltraNix@users.noreply.github.com> Date: Mon, 25 Jul 2022 21:09:39 +0200 Subject: [PATCH 099/130] =?UTF-8?q?fix(Core/Spells):=20Lightning=20Shield?= =?UTF-8?q?=20should=20not=20proc=20off=20from=20self-cast=E2=80=A6=20(#12?= =?UTF-8?q?501)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fix(Core/Spells): Lightning Shield should not proc off from self-casted items. Fixes #12361 --- src/server/game/Entities/Unit/Unit.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 1823c9be7..9e642a36f 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -8920,6 +8920,15 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg // Lightning Shield (overwrite non existing triggered spell call in spell.dbc if (auraSpellInfo->SpellFamilyFlags[0] & 0x400) { + // Do not proc off from self-casted items + if (Spell const* spell = eventInfo.GetProcSpell()) + { + if (spell->m_castItemGUID && victim->GetGUID() == GetGUID()) + { + return false; + } + } + trigger_spell_id = sSpellMgr->GetSpellWithRank(26364, auraSpellInfo->GetRank()); } // Nature's Guardian From c19d6b74e9fe6c2c877a5bb2bac263d340069a73 Mon Sep 17 00:00:00 2001 From: UltraNix <80540499+UltraNix@users.noreply.github.com> Date: Mon, 25 Jul 2022 21:34:21 +0200 Subject: [PATCH 100/130] =?UTF-8?q?fix(Core/Spells):=20Make=20sure=20that?= =?UTF-8?q?=20attacker=20is=20always=20in=20combat=20with=20it=E2=80=A6=20?= =?UTF-8?q?(#12516)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fix(Core/Spells): Make sure that attacker is always in combat with its victim when dealing damage/generating threat done by spells. Fixes #10801 --- src/server/game/Entities/Unit/Unit.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 9e642a36f..1de73ca27 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -1033,7 +1033,14 @@ uint32 Unit::DealDamage(Unit* attacker, Unit* victim, uint32 damage, CleanDamage victim->ToCreature()->SetLastDamagedTime(GameTime::GetGameTime().count() + MAX_AGGRO_RESET_TIME); if (attacker) + { + if (spellProto && !victim->IsInCombatWith(attacker)) + { + victim->CombatStart(attacker, !(spellProto->AttributesEx3 & SPELL_ATTR3_SUPRESS_TARGET_PROCS)); + } + victim->AddThreat(attacker, float(damage), damageSchoolMask, spellProto); + } } else // victim is a player { From 60e70ac81f055f25f5fdd5e20e4cf0a4daebf8a5 Mon Sep 17 00:00:00 2001 From: Eddy Vega <61223313+Si1ker@users.noreply.github.com> Date: Mon, 25 Jul 2022 17:32:53 -0600 Subject: [PATCH 101/130] fix(Scripts/RuinsOfAhnQiraj): Improve Ossirian (#12138) --- .../rev_1655863908221203900.sql | 6 ++ .../RuinsOfAhnQiraj/boss_ossirian.cpp | 79 +++++++++---------- 2 files changed, 44 insertions(+), 41 deletions(-) create mode 100644 data/sql/updates/pending_db_world/rev_1655863908221203900.sql diff --git a/data/sql/updates/pending_db_world/rev_1655863908221203900.sql b/data/sql/updates/pending_db_world/rev_1655863908221203900.sql new file mode 100644 index 000000000..ec73606c1 --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1655863908221203900.sql @@ -0,0 +1,6 @@ + +-- Ossirian immune to Taunt +UPDATE `creature_template` SET `flags_extra`=`flags_extra`|256 WHERE `entry`=15339; + +-- Sand Vortex UNIT_FLAG_NOT_SELECTABLE +UPDATE `creature_template` SET `unit_flags`=`unit_flags`|33554432 WHERE `entry`=15428; diff --git a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_ossirian.cpp b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_ossirian.cpp index af994f8b8..ceae706d1 100644 --- a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_ossirian.cpp +++ b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_ossirian.cpp @@ -25,41 +25,36 @@ enum Texts { - SAY_SUPREME = 0, - SAY_INTRO = 1, - SAY_AGGRO = 2, - SAY_SLAY = 3, - SAY_DEATH = 4 + SAY_SUPREME = 0, + SAY_INTRO = 1, + SAY_AGGRO = 2, + SAY_SLAY = 3, + SAY_DEATH = 4 }; enum Spells { - SPELL_SILENCE = 25195, - SPELL_CYCLONE = 25189, - SPELL_STOMP = 25188, - SPELL_SUPREME = 25176, - SPELL_SUMMON = 20477, - SPELL_SAND_STORM = 25160, - SPELL_SUMMON_CRYSTAL = 25192 + SPELL_CURSE_OF_TONGUES = 25195, + SPELL_ENVELOPING_WINDS = 25189, + SPELL_WAR_STOMP = 25188, + SPELL_STRENGHT_OF_OSSIRIAN = 25176, + SPELL_SAND_STORM = 25160, + SPELL_SUMMON_CRYSTAL = 25192 }; enum Actions { - ACTION_TRIGGER_WEAKNESS = 1 + ACTION_TRIGGER_WEAKNESS = 1 }; enum Events { - EVENT_SILENCE = 1, - EVENT_CYCLONE = 2, - EVENT_STOMP = 3 + EVENT_SILENCE = 1, + EVENT_CYCLONE = 2, + EVENT_STOMP = 3 }; -uint8 const NUM_CRYSTALS = 9; - -// You spin me right round, baby -// right round like a record, baby -// right round round round +uint8 const NUM_CRYSTALS = 9; Position CrystalCoordinates[NUM_CRYSTALS] = { { -9394.230469f, 1951.808594f, 85.97733f, 0.0f }, @@ -73,9 +68,9 @@ Position CrystalCoordinates[NUM_CRYSTALS] = { -9406.73f, 1863.13f, 85.5558f, 0.0f } }; -float RoomRadius = 165.0f; -uint8 const NUM_TORNADOS = 5; /// @todo This number is completly random! -uint8 const NUM_WEAKNESS = 5; +float RoomRadius = 165.0f; +uint8 const NUM_TORNADOS = 2; +uint8 const NUM_WEAKNESS = 5; uint32 const SpellWeakness[NUM_WEAKNESS] = { 25177, 25178, 25180, 25181, 25183 }; Position const RoomCenter = { -9343.041992f, 1923.278198f, 85.555984f, 0.0 }; @@ -110,7 +105,7 @@ public: { if (spell->Id == SpellWeakness[i]) { - me->RemoveAurasDueToSpell(SPELL_SUPREME); + me->RemoveAurasDueToSpell(SPELL_STRENGHT_OF_OSSIRIAN); ((TempSummon*)caster)->UnSummon(); SpawnNextCrystal(); } @@ -120,9 +115,15 @@ public: void DoAction(int32 action) override { if (action == ACTION_TRIGGER_WEAKNESS) + { if (Creature* Trigger = me->GetMap()->GetCreature(TriggerGUID)) + { if (!Trigger->HasUnitState(UNIT_STATE_CASTING)) + { Trigger->CastSpell(Trigger, SpellWeakness[urand(0, 4)], false); + } + } + } } void EnterCombat(Unit* /*who*/) override @@ -132,8 +133,7 @@ public: events.ScheduleEvent(EVENT_SILENCE, 30000); events.ScheduleEvent(EVENT_CYCLONE, 20000); events.ScheduleEvent(EVENT_STOMP, 30000); - - DoCast(me, SPELL_SUPREME); + DoCastSelf(SPELL_STRENGHT_OF_OSSIRIAN); Talk(SAY_AGGRO); Map* map = me->GetMap(); @@ -142,14 +142,14 @@ public: WorldPackets::Misc::Weather weather(WEATHER_STATE_HEAVY_SANDSTORM, 1.0f); map->SendToPlayers(weather.Write()); - for (uint8 i = 0; i < NUM_TORNADOS; ++i) { Position Point = me->GetRandomPoint(RoomCenter, RoomRadius); if (Creature* Tornado = me->GetMap()->SummonCreature(NPC_SAND_VORTEX, Point)) + { Tornado->CastSpell(Tornado, SPELL_SAND_STORM, true); + } } - SpawnNextCrystal(); } @@ -174,7 +174,9 @@ public: void Cleanup() { if (GameObject* Crystal = me->GetMap()->GetGameObject(CrystalGUID)) + { Crystal->Use(me); + } } void SpawnNextCrystal() @@ -215,15 +217,11 @@ public: return; events.Update(diff); - - // No kiting! - if (me->GetDistance(me->GetVictim()) > 60.00f && me->GetDistance(me->GetVictim()) < 120.00f) - DoCastVictim(SPELL_SUMMON); - bool ApplySupreme = true; - - if (me->HasAura(SPELL_SUPREME)) + if (me->HasAura(SPELL_STRENGHT_OF_OSSIRIAN)) + { ApplySupreme = false; + } else { for (uint8 i = 0; i < NUM_WEAKNESS; ++i) @@ -238,7 +236,7 @@ public: if (ApplySupreme) { - DoCast(me, SPELL_SUPREME); + DoCastSelf(SPELL_STRENGHT_OF_OSSIRIAN); Talk(SAY_SUPREME); } @@ -247,22 +245,21 @@ public: switch (eventId) { case EVENT_SILENCE: - DoCast(me, SPELL_SILENCE); + DoCastAOE(SPELL_CURSE_OF_TONGUES); events.ScheduleEvent(EVENT_SILENCE, urand(20000, 30000)); break; case EVENT_CYCLONE: - DoCastVictim(SPELL_CYCLONE); + DoCastVictim(SPELL_ENVELOPING_WINDS); events.ScheduleEvent(EVENT_CYCLONE, 20000); break; case EVENT_STOMP: - DoCast(me, SPELL_STOMP); + DoCastAOE(SPELL_WAR_STOMP); events.ScheduleEvent(EVENT_STOMP, 30000); break; default: break; } } - DoMeleeAttackIfReady(); } }; From a3474b0772751890d8d64cd5cfdeb9b25be7f994 Mon Sep 17 00:00:00 2001 From: AzerothCoreBot Date: Mon, 25 Jul 2022 23:35:02 +0000 Subject: [PATCH 102/130] chore(DB): import pending files Referenced commit(s): 60e70ac81f055f25f5fdd5e20e4cf0a4daebf8a5 --- .../rev_1655863908221203900.sql => db_world/2022_07_25_07.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/rev_1655863908221203900.sql => db_world/2022_07_25_07.sql} (84%) diff --git a/data/sql/updates/pending_db_world/rev_1655863908221203900.sql b/data/sql/updates/db_world/2022_07_25_07.sql similarity index 84% rename from data/sql/updates/pending_db_world/rev_1655863908221203900.sql rename to data/sql/updates/db_world/2022_07_25_07.sql index ec73606c1..91426fa0d 100644 --- a/data/sql/updates/pending_db_world/rev_1655863908221203900.sql +++ b/data/sql/updates/db_world/2022_07_25_07.sql @@ -1,3 +1,4 @@ +-- DB update 2022_07_25_06 -> 2022_07_25_07 -- Ossirian immune to Taunt UPDATE `creature_template` SET `flags_extra`=`flags_extra`|256 WHERE `entry`=15339; From a498584adf7af2c8203205d496b6c317c6882edd Mon Sep 17 00:00:00 2001 From: Skjalf <47818697+Nyeriah@users.noreply.github.com> Date: Mon, 25 Jul 2022 20:55:44 -0300 Subject: [PATCH 103/130] fix(Scripts/RuinsOfAhnQiraj): Script Anubisath Guardians (#12537) --- .../rev_1658788379158805300.sql | 2 + .../RuinsOfAhnQiraj/boss_ossirian.cpp | 77 +++++++++++++++++++ 2 files changed, 79 insertions(+) create mode 100644 data/sql/updates/pending_db_world/rev_1658788379158805300.sql diff --git a/data/sql/updates/pending_db_world/rev_1658788379158805300.sql b/data/sql/updates/pending_db_world/rev_1658788379158805300.sql new file mode 100644 index 000000000..c0052d560 --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1658788379158805300.sql @@ -0,0 +1,2 @@ +-- +UPDATE `creature_template` SET `ScriptName` = 'npc_anubisath_guardian' WHERE `entry` = 15355; diff --git a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_ossirian.cpp b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_ossirian.cpp index ceae706d1..a085e99c5 100644 --- a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_ossirian.cpp +++ b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_ossirian.cpp @@ -22,6 +22,7 @@ #include "ScriptedCreature.h" #include "SpellInfo.h" #include "ruins_of_ahnqiraj.h" +#include "TaskScheduler.h" enum Texts { @@ -290,8 +291,84 @@ public: } }; +enum AnubisathGuardian +{ + SPELL_METEOR = 24340, + SPELL_PLAGUE = 22997, + SPELL_SHADOW_STORM = 2148, + SPELL_THUNDER_CLAP = 2834, + SPELL_REFLECT_ARCANE_FIRE = 13022, + SPELL_REFLECT_FROST_SHADOW = 19595, + SPELL_ENRAGE = 8599, + SPELL_EXPLODE = 25698, + + SPELL_SUMMON_ANUB_SWARMGUARD = 17430, + SPELL_SUMMON_ANUB_WARRIOR = 17431, +}; + +struct npc_anubisath_guardian : public ScriptedAI +{ + npc_anubisath_guardian(Creature* creature) : ScriptedAI(creature) { } + + void Reset() override + { + _enraged = false; + _spells[0] = RAND(SPELL_SHADOW_STORM, SPELL_THUNDER_CLAP); + _spells[1] = RAND(SPELL_REFLECT_ARCANE_FIRE, SPELL_REFLECT_FROST_SHADOW); + + _scheduler.SetValidator([this] + { + return !me->HasUnitState(UNIT_STATE_CASTING); + }); + } + + void EnterCombat(Unit* /*who*/) override + { + DoCastSelf(_spells[0]); + DoCastSelf(_spells[1]); + + _scheduler.CancelAll(); + + uint32 spell = RAND(SPELL_METEOR, SPELL_PLAGUE); + _scheduler.Schedule(10s, [this, spell](TaskContext context) { + DoCastRandomTarget(spell); + context.Repeat(10s, 15s); + }); + + spell = RAND(SPELL_SUMMON_ANUB_SWARMGUARD, SPELL_SUMMON_ANUB_WARRIOR); + _scheduler.Schedule(10s, [this, spell](TaskContext context) { + DoCastAOE(spell); + context.Repeat(10s, 15s); + }); + } + + void DamageTaken(Unit* /*doneBy*/, uint32& damage, DamageEffectType /* damagetype */, SpellSchoolMask /*damageSchoolMask*/) override + { + if (!_enraged && me->HealthBelowPctDamaged(10, damage)) + { + _enraged = true; + DoCastSelf(RAND(SPELL_ENRAGE, SPELL_EXPLODE), true); + } + } + + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; + + _scheduler.Update(diff, + std::bind(&ScriptedAI::DoMeleeAttackIfReady, this)); + } + +private: + bool _enraged; + uint32 _spells[2]; + TaskScheduler _scheduler; +}; + void AddSC_boss_ossirian() { new boss_ossirian(); new go_ossirian_crystal(); + RegisterCreatureAI(npc_anubisath_guardian); } From e9474a38fc501e5a56f7c23ac48ba83bd8fad44e Mon Sep 17 00:00:00 2001 From: AzerothCoreBot Date: Mon, 25 Jul 2022 23:57:52 +0000 Subject: [PATCH 104/130] chore(DB): import pending files Referenced commit(s): a498584adf7af2c8203205d496b6c317c6882edd --- .../rev_1658788379158805300.sql => db_world/2022_07_25_08.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/rev_1658788379158805300.sql => db_world/2022_07_25_08.sql} (68%) diff --git a/data/sql/updates/pending_db_world/rev_1658788379158805300.sql b/data/sql/updates/db_world/2022_07_25_08.sql similarity index 68% rename from data/sql/updates/pending_db_world/rev_1658788379158805300.sql rename to data/sql/updates/db_world/2022_07_25_08.sql index c0052d560..0e6d9ddf2 100644 --- a/data/sql/updates/pending_db_world/rev_1658788379158805300.sql +++ b/data/sql/updates/db_world/2022_07_25_08.sql @@ -1,2 +1,3 @@ +-- DB update 2022_07_25_07 -> 2022_07_25_08 -- UPDATE `creature_template` SET `ScriptName` = 'npc_anubisath_guardian' WHERE `entry` = 15355; From 6e659a1681522b64f2f9ca57f5a1c76df6827386 Mon Sep 17 00:00:00 2001 From: Eddy Vega <61223313+Si1ker@users.noreply.github.com> Date: Mon, 25 Jul 2022 19:10:50 -0600 Subject: [PATCH 105/130] fix(Scripts/RuinsOfAhnQiraj): Improve Moam (#12142) --- .../rev_1658790562433074900.sql | 8 ++ .../Kalimdor/RuinsOfAhnQiraj/boss_moam.cpp | 97 ++++++++----------- 2 files changed, 48 insertions(+), 57 deletions(-) create mode 100644 data/sql/updates/pending_db_world/rev_1658790562433074900.sql diff --git a/data/sql/updates/pending_db_world/rev_1658790562433074900.sql b/data/sql/updates/pending_db_world/rev_1658790562433074900.sql new file mode 100644 index 000000000..bdbcd5bde --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1658790562433074900.sql @@ -0,0 +1,8 @@ +-- + +UPDATE `creature_template` SET `mingold`=0, `maxgold`=0, `AIName`='SmartAI' WHERE `entry`=15527; +DELETE FROM `smart_scripts` WHERE `entryorguid`=15527 AND `source_type`=0; +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `action_type`, `action_param1`, `action_param2`, `target_type`, `comment`) VALUES +(15527, 0, 0, 0, 0, 0, 100, 0, 6000, 6000, 6000, 6000, 11, 25679, 2, 2, 'Mana Fiend - In Combat - Cast Arcane Explosion'), +(15527, 0, 1, 0, 13, 0, 100, 0, 10000, 20000, 0, 0, 11, 15122, 0, 2, 'Mana Fiend - In Combat - Cast Counterspell'); + diff --git a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_moam.cpp b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_moam.cpp index 7a1fd966a..f1908a381 100644 --- a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_moam.cpp +++ b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_moam.cpp @@ -21,8 +21,8 @@ enum Texts { - EMOTE_AGGRO = 0, - EMOTE_MANA_FULL = 1 + EMOTE_AGGRO = 0, + EMOTE_MANA_FULL = 1 }; enum Spells @@ -40,17 +40,16 @@ enum Spells enum Events { - EVENT_TRAMPLE = 1, - EVENT_DRAIN_MANA = 2, - EVENT_STONE_PHASE = 3, - EVENT_STONE_PHASE_END = 4, - EVENT_WIDE_SLASH = 5, + EVENT_SPELL_TRAMPLE = 1, + EVENT_SPELL_DRAIN_MANA = 2, + EVENT_STONE_PHASE = 3, + EVENT_STONE_PHASE_END = 4 }; enum Actions { - ACTION_STONE_PHASE_START = 1, - ACTION_STONE_PHASE_END = 2, + ACTION_STONE_PHASE_START = 1, + ACTION_STONE_PHASE_END = 2 }; class boss_moam : public CreatureScript @@ -60,9 +59,7 @@ public: struct boss_moamAI : public BossAI { - boss_moamAI(Creature* creature) : BossAI(creature, DATA_MOAM) - { - } + boss_moamAI(Creature* creature) : BossAI(creature, DATA_MOAM) {} void Reset() override { @@ -70,17 +67,6 @@ public: me->SetPower(POWER_MANA, 0); me->SetRegeneratingPower(false); _isStonePhase = false; - events.ScheduleEvent(EVENT_STONE_PHASE, 90000); - //events.ScheduleEvent(EVENT_WIDE_SLASH, 11000); - } - - void DamageTaken(Unit*, uint32& /*damage*/, DamageEffectType, SpellSchoolMask) override - { - if (!_isStonePhase && HealthBelowPct(45)) - { - _isStonePhase = true; - DoAction(ACTION_STONE_PHASE_START); - } } void DoAction(int32 action) override @@ -96,10 +82,10 @@ public: } case ACTION_STONE_PHASE_START: { - DoCast(me, SPELL_SUMMON_MANA_FIEND_1); - DoCast(me, SPELL_SUMMON_MANA_FIEND_2); - DoCast(me, SPELL_SUMMON_MANA_FIEND_3); - DoCast(me, SPELL_ENERGIZE); + DoCastSelf(SPELL_SUMMON_MANA_FIEND_1); + DoCastSelf(SPELL_SUMMON_MANA_FIEND_2); + DoCastSelf(SPELL_SUMMON_MANA_FIEND_3); + DoCastSelf(SPELL_ENERGIZE); events.ScheduleEvent(EVENT_STONE_PHASE_END, 90000); break; } @@ -108,6 +94,15 @@ public: } } + void EnterCombat(Unit* who) override + { + BossAI::EnterCombat(who); + Talk(EMOTE_AGGRO); + events.ScheduleEvent(EVENT_STONE_PHASE, 90000); + events.ScheduleEvent(EVENT_SPELL_TRAMPLE, 9000); + events.ScheduleEvent(EVENT_SPELL_DRAIN_MANA, 3000); + } + void JustDied(Unit* /*killer*/) override { _JustDied(); @@ -120,26 +115,13 @@ public: return; events.Update(diff); - if (me->GetPower(POWER_MANA) == me->GetMaxPower(POWER_MANA)) { - if (_isStonePhase) - DoAction(ACTION_STONE_PHASE_END); - DoCastAOE(SPELL_ARCANE_ERUPTION); + Talk(EMOTE_MANA_FULL); + DoCastAOE(SPELL_ARCANE_ERUPTION, true); me->SetPower(POWER_MANA, 0); } - if (_isStonePhase) - { - if (events.ExecuteEvent() == EVENT_STONE_PHASE_END) - DoAction(ACTION_STONE_PHASE_END); - return; - } - - // Messing up mana-drain channel - //if (me->HasUnitState(UNIT_STATE_CASTING)) - // return; - while (uint32 eventId = events.ExecuteEvent()) { switch (eventId) @@ -147,37 +129,38 @@ public: case EVENT_STONE_PHASE: DoAction(ACTION_STONE_PHASE_START); break; - case EVENT_DRAIN_MANA: + case EVENT_STONE_PHASE_END: + DoAction(ACTION_STONE_PHASE_END); + break; + case EVENT_SPELL_DRAIN_MANA: { std::list targetList; { const std::list& threatlist = me->GetThreatMgr().getThreatList(); for (std::list::const_iterator itr = threatlist.begin(); itr != threatlist.end(); ++itr) + { if ((*itr)->getTarget()->GetTypeId() == TYPEID_PLAYER && (*itr)->getTarget()->getPowerType() == POWER_MANA) + { targetList.push_back((*itr)->getTarget()); + } + } } - - Acore::Containers::RandomResize(targetList, 5); - + Acore::Containers::RandomResize(targetList, 6); for (std::list::iterator itr = targetList.begin(); itr != targetList.end(); ++itr) + { DoCast(*itr, SPELL_DRAIN_MANA); - - events.ScheduleEvent(EVENT_DRAIN_MANA, urand(5000, 15000)); + } + events.ScheduleEvent(EVENT_SPELL_DRAIN_MANA, urand(2000, 6000)); break; - }/* - case EVENT_WIDE_SLASH: - DoCast(me, SPELL_WIDE_SLASH); - events.ScheduleEvent(EVENT_WIDE_SLASH, 11000); + } + case EVENT_SPELL_TRAMPLE: + DoCastVictim(SPELL_TRAMPLE); + events.ScheduleEvent(EVENT_SPELL_TRAMPLE, 15000); break; - case EVENT_TRASH: - DoCast(me, SPELL_TRASH); - events.ScheduleEvent(EVENT_WIDE_SLASH, 16000); - break;*/ default: break; } } - DoMeleeAttackIfReady(); } private: From c7df977d103115397fe7bbfc5a733e05a4e3c874 Mon Sep 17 00:00:00 2001 From: AzerothCoreBot Date: Tue, 26 Jul 2022 01:12:47 +0000 Subject: [PATCH 106/130] chore(DB): import pending files Referenced commit(s): 6e659a1681522b64f2f9ca57f5a1c76df6827386 --- .../rev_1658790562433074900.sql => db_world/2022_07_26_00.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/rev_1658790562433074900.sql => db_world/2022_07_26_00.sql} (94%) diff --git a/data/sql/updates/pending_db_world/rev_1658790562433074900.sql b/data/sql/updates/db_world/2022_07_26_00.sql similarity index 94% rename from data/sql/updates/pending_db_world/rev_1658790562433074900.sql rename to data/sql/updates/db_world/2022_07_26_00.sql index bdbcd5bde..e88653012 100644 --- a/data/sql/updates/pending_db_world/rev_1658790562433074900.sql +++ b/data/sql/updates/db_world/2022_07_26_00.sql @@ -1,3 +1,4 @@ +-- DB update 2022_07_25_08 -> 2022_07_26_00 -- UPDATE `creature_template` SET `mingold`=0, `maxgold`=0, `AIName`='SmartAI' WHERE `entry`=15527; From 8e74bc8edd6b689e5fecf9be0954701b03b2f56b Mon Sep 17 00:00:00 2001 From: temperrr Date: Tue, 26 Jul 2022 03:15:13 +0200 Subject: [PATCH 107/130] =?UTF-8?q?fix(DB/Creature):=20Deadwood=20Shaman,?= =?UTF-8?q?=20Avengers,=20Den=20Watchers,=20should=20not=E2=80=A6=20(#1245?= =?UTF-8?q?6)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fix(DB/Creature): Deadwood Shaman, Avengers, Den Watchers, should not give rep above honored. --- data/sql/updates/pending_db_world/deadwoodrep.sql | 1 + 1 file changed, 1 insertion(+) create mode 100644 data/sql/updates/pending_db_world/deadwoodrep.sql diff --git a/data/sql/updates/pending_db_world/deadwoodrep.sql b/data/sql/updates/pending_db_world/deadwoodrep.sql new file mode 100644 index 000000000..c75e75cd6 --- /dev/null +++ b/data/sql/updates/pending_db_world/deadwoodrep.sql @@ -0,0 +1 @@ +UPDATE `creature_onkill_reputation` SET `MaxStanding1` = 5 WHERE (`creature_id` IN (7157, 7156, 7158)); From 423fdc333e0f469fceb783d8f0830a271bd4682b Mon Sep 17 00:00:00 2001 From: AzerothCoreBot Date: Tue, 26 Jul 2022 01:17:15 +0000 Subject: [PATCH 108/130] chore(DB): import pending files Referenced commit(s): 8e74bc8edd6b689e5fecf9be0954701b03b2f56b --- .../deadwoodrep.sql => db_world/2022_07_26_01.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/deadwoodrep.sql => db_world/2022_07_26_01.sql} (70%) diff --git a/data/sql/updates/pending_db_world/deadwoodrep.sql b/data/sql/updates/db_world/2022_07_26_01.sql similarity index 70% rename from data/sql/updates/pending_db_world/deadwoodrep.sql rename to data/sql/updates/db_world/2022_07_26_01.sql index c75e75cd6..49814d44c 100644 --- a/data/sql/updates/pending_db_world/deadwoodrep.sql +++ b/data/sql/updates/db_world/2022_07_26_01.sql @@ -1 +1,2 @@ +-- DB update 2022_07_26_00 -> 2022_07_26_01 UPDATE `creature_onkill_reputation` SET `MaxStanding1` = 5 WHERE (`creature_id` IN (7157, 7156, 7158)); From b1136c7c24eb423f1f9f92fd526f0c7f33847dd3 Mon Sep 17 00:00:00 2001 From: Nefertumm Date: Tue, 26 Jul 2022 00:35:20 -0300 Subject: [PATCH 109/130] refactor(Core/RuinsOfAhnQiraj): Ossirian (#12541) --- .../RuinsOfAhnQiraj/boss_ossirian.cpp | 416 +++++++++--------- 1 file changed, 204 insertions(+), 212 deletions(-) diff --git a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_ossirian.cpp b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_ossirian.cpp index a085e99c5..b885ce139 100644 --- a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_ossirian.cpp +++ b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_ossirian.cpp @@ -55,220 +55,210 @@ enum Events EVENT_STOMP = 3 }; -uint8 const NUM_CRYSTALS = 9; +uint8 const NUM_CRYSTALS = 9; Position CrystalCoordinates[NUM_CRYSTALS] = { - { -9394.230469f, 1951.808594f, 85.97733f, 0.0f }, + { -9394.230469f, 1951.808594f, 85.97733f, 0.0f }, { -9357.931641f, 1930.596802f, 85.556198f, 0.0f }, { -9383.113281f, 2011.042725f, 85.556389f, 0.0f }, - { -9243.36f, 1979.04f, 85.556f, 0.0f }, - { -9281.68f, 1886.66f, 85.5558f, 0.0f }, - { -9241.8f, 1806.39f, 85.5557f, 0.0f }, - { -9366.78f, 1781.76f, 85.5561f, 0.0f }, - { -9430.37f, 1786.86f, 85.557f, 0.0f }, - { -9406.73f, 1863.13f, 85.5558f, 0.0f } + { -9243.36f, 1979.04f, 85.556f, 0.0f }, + { -9281.68f, 1886.66f, 85.5558f, 0.0f }, + { -9241.8f, 1806.39f, 85.5557f, 0.0f }, + { -9366.78f, 1781.76f, 85.5561f, 0.0f }, + { -9430.37f, 1786.86f, 85.557f, 0.0f }, + { -9406.73f, 1863.13f, 85.5558f, 0.0f } }; -float RoomRadius = 165.0f; -uint8 const NUM_TORNADOS = 2; -uint8 const NUM_WEAKNESS = 5; -uint32 const SpellWeakness[NUM_WEAKNESS] = { 25177, 25178, 25180, 25181, 25183 }; +float roomRadius = 165.0f; +uint8 const NUM_TORNADOS = 2; +uint8 const NUM_WEAKNESS = 5; +uint32 const spellWeakness[NUM_WEAKNESS] = { 25177, 25178, 25180, 25181, 25183 }; Position const RoomCenter = { -9343.041992f, 1923.278198f, 85.555984f, 0.0 }; -class boss_ossirian : public CreatureScript +struct boss_ossirian : public BossAI { -public: - boss_ossirian() : CreatureScript("boss_ossirian") { } - - struct boss_ossirianAI : public BossAI + boss_ossirian(Creature* creature) : BossAI(creature, DATA_OSSIRIAN) { - boss_ossirianAI(Creature* creature) : BossAI(creature, DATA_OSSIRIAN) - { - SaidIntro = false; - } - - ObjectGuid TriggerGUID; - ObjectGuid CrystalGUID; - uint8 CrystalIterator; - bool SaidIntro; - - void Reset() override - { - _Reset(); - CrystalIterator = 0; - TriggerGUID.Clear(); - CrystalGUID.Clear(); - } - - void SpellHit(Unit* caster, SpellInfo const* spell) override - { - for (uint8 i = 0; i < NUM_WEAKNESS; ++i) - { - if (spell->Id == SpellWeakness[i]) - { - me->RemoveAurasDueToSpell(SPELL_STRENGHT_OF_OSSIRIAN); - ((TempSummon*)caster)->UnSummon(); - SpawnNextCrystal(); - } - } - } - - void DoAction(int32 action) override - { - if (action == ACTION_TRIGGER_WEAKNESS) - { - if (Creature* Trigger = me->GetMap()->GetCreature(TriggerGUID)) - { - if (!Trigger->HasUnitState(UNIT_STATE_CASTING)) - { - Trigger->CastSpell(Trigger, SpellWeakness[urand(0, 4)], false); - } - } - } - } - - void EnterCombat(Unit* /*who*/) override - { - _EnterCombat(); - events.Reset(); - events.ScheduleEvent(EVENT_SILENCE, 30000); - events.ScheduleEvent(EVENT_CYCLONE, 20000); - events.ScheduleEvent(EVENT_STOMP, 30000); - DoCastSelf(SPELL_STRENGHT_OF_OSSIRIAN); - Talk(SAY_AGGRO); - - Map* map = me->GetMap(); - if (!map->IsDungeon()) - return; - - WorldPackets::Misc::Weather weather(WEATHER_STATE_HEAVY_SANDSTORM, 1.0f); - map->SendToPlayers(weather.Write()); - for (uint8 i = 0; i < NUM_TORNADOS; ++i) - { - Position Point = me->GetRandomPoint(RoomCenter, RoomRadius); - if (Creature* Tornado = me->GetMap()->SummonCreature(NPC_SAND_VORTEX, Point)) - { - Tornado->CastSpell(Tornado, SPELL_SAND_STORM, true); - } - } - SpawnNextCrystal(); - } - - void KilledUnit(Unit* /*victim*/) override - { - Talk(SAY_SLAY); - } - - void EnterEvadeMode(EvadeReason why) override - { - Cleanup(); - summons.DespawnAll(); - BossAI::EnterEvadeMode(why); - } - - void JustDied(Unit* /*killer*/) override - { - Cleanup(); - _JustDied(); - } - - void Cleanup() - { - if (GameObject* Crystal = me->GetMap()->GetGameObject(CrystalGUID)) - { - Crystal->Use(me); - } - } - - void SpawnNextCrystal() - { - if (CrystalIterator == NUM_CRYSTALS) - CrystalIterator = 0; - - if (Creature* Trigger = me->GetMap()->SummonCreature(NPC_OSSIRIAN_TRIGGER, CrystalCoordinates[CrystalIterator])) - { - TriggerGUID = 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 = Crystal->GetGUID(); - ++CrystalIterator; - Crystal->SetOwnerGUID(ObjectGuid::Empty); - } - } - } - - void MoveInLineOfSight(Unit* who) override - - { - if (!SaidIntro) - { - Talk(SAY_INTRO); - SaidIntro = true; - } - BossAI::MoveInLineOfSight(who); - } - - void UpdateAI(uint32 diff) override - { - if (!UpdateVictim()) - return; - - events.Update(diff); - bool ApplySupreme = true; - if (me->HasAura(SPELL_STRENGHT_OF_OSSIRIAN)) - { - ApplySupreme = false; - } - else - { - for (uint8 i = 0; i < NUM_WEAKNESS; ++i) - { - if (me->HasAura(SpellWeakness[i])) - { - ApplySupreme = false; - break; - } - } - } - - if (ApplySupreme) - { - DoCastSelf(SPELL_STRENGHT_OF_OSSIRIAN); - Talk(SAY_SUPREME); - } - - while (uint32 eventId = events.ExecuteEvent()) - { - switch (eventId) - { - case EVENT_SILENCE: - DoCastAOE(SPELL_CURSE_OF_TONGUES); - events.ScheduleEvent(EVENT_SILENCE, urand(20000, 30000)); - break; - case EVENT_CYCLONE: - DoCastVictim(SPELL_ENVELOPING_WINDS); - events.ScheduleEvent(EVENT_CYCLONE, 20000); - break; - case EVENT_STOMP: - DoCastAOE(SPELL_WAR_STOMP); - events.ScheduleEvent(EVENT_STOMP, 30000); - break; - default: - break; - } - } - DoMeleeAttackIfReady(); - } - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return GetRuinsOfAhnQirajAI(creature); + _saidIntro = false; } + + void Reset() override + { + BossAI::Reset(); + _crystalIterator = 0; + _triggerGUID.Clear(); + _crystalGUID.Clear(); + } + + void SpellHit(Unit* caster, SpellInfo const* spell) override + { + for (uint8 weakness : spellWeakness) + { + if (spell->Id == weakness) + { + me->RemoveAurasDueToSpell(SPELL_STRENGHT_OF_OSSIRIAN); + ((TempSummon*)caster)->UnSummon(); + SpawnNextCrystal(); + } + } + } + + void DoAction(int32 action) override + { + if (action == ACTION_TRIGGER_WEAKNESS) + { + if (Creature* trigger = me->GetMap()->GetCreature(_triggerGUID)) + { + if (!trigger->HasUnitState(UNIT_STATE_CASTING)) + { + trigger->CastSpell(trigger, spellWeakness[urand(0, 4)], false); + } + } + } + } + + void EnterCombat(Unit* who) override + { + BossAI::EnterCombat(who); + events.Reset(); + events.ScheduleEvent(EVENT_SILENCE, 30s); + events.ScheduleEvent(EVENT_CYCLONE, 20s); + events.ScheduleEvent(EVENT_STOMP, 30s); + DoCastSelf(SPELL_STRENGHT_OF_OSSIRIAN); + Talk(SAY_AGGRO); + + Map* map = me->GetMap(); + if (!map->IsDungeon()) + return; + + WorldPackets::Misc::Weather weather(WEATHER_STATE_HEAVY_SANDSTORM, 1.0f); + map->SendToPlayers(weather.Write()); + for (uint8 i = 0; i < NUM_TORNADOS; ++i) + { + Position Point = me->GetRandomPoint(RoomCenter, roomRadius); + if (Creature* Tornado = me->GetMap()->SummonCreature(NPC_SAND_VORTEX, Point)) + { + Tornado->CastSpell(Tornado, SPELL_SAND_STORM, true); + } + } + SpawnNextCrystal(); + } + + void KilledUnit(Unit* /*victim*/) override + { + Talk(SAY_SLAY); + } + + void EnterEvadeMode(EvadeReason why) override + { + Cleanup(); + summons.DespawnAll(); + BossAI::EnterEvadeMode(why); + } + + void JustDied(Unit* killer) override + { + Cleanup(); + BossAI::JustDied(killer); + } + + void Cleanup() + { + if (GameObject* crystal = me->GetMap()->GetGameObject(_crystalGUID)) + { + crystal->Use(me); + } + } + + void SpawnNextCrystal() + { + if (_crystalIterator == NUM_CRYSTALS) + _crystalIterator = 0; + + if (Creature* trigger = me->GetMap()->SummonCreature(NPC_OSSIRIAN_TRIGGER, CrystalCoordinates[_crystalIterator])) + { + _triggerGUID = 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 = crystal->GetGUID(); + ++_crystalIterator; + crystal->SetOwnerGUID(ObjectGuid::Empty); + } + } + } + + void MoveInLineOfSight(Unit* who) override + + { + if (!_saidIntro) + { + Talk(SAY_INTRO); + _saidIntro = true; + } + BossAI::MoveInLineOfSight(who); + } + + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; + + events.Update(diff); + bool applySupreme = true; + if (me->HasAura(SPELL_STRENGHT_OF_OSSIRIAN)) + { + applySupreme = false; + } + else + { + for (uint8 weakness : spellWeakness) + { + if (me->HasAura(weakness)) + { + applySupreme = false; + break; + } + } + } + + if (applySupreme) + { + DoCastSelf(SPELL_STRENGHT_OF_OSSIRIAN); + Talk(SAY_SUPREME); + } + + while (uint32 eventId = events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_SILENCE: + DoCastAOE(SPELL_CURSE_OF_TONGUES); + events.ScheduleEvent(EVENT_SILENCE, 20s, 30s); + break; + case EVENT_CYCLONE: + DoCastVictim(SPELL_ENVELOPING_WINDS); + events.ScheduleEvent(EVENT_CYCLONE, 20s); + break; + case EVENT_STOMP: + DoCastAOE(SPELL_WAR_STOMP); + events.ScheduleEvent(EVENT_STOMP, 30s); + break; + default: + break; + } + } + DoMeleeAttackIfReady(); + } + +protected: + ObjectGuid _triggerGUID; + ObjectGuid _crystalGUID; + uint8 _crystalIterator; + bool _saidIntro; }; class go_ossirian_crystal : public GameObjectScript @@ -278,15 +268,15 @@ public: bool OnGossipHello(Player* player, GameObject* /*go*/) override { - InstanceScript* Instance = player->GetInstanceScript(); - if (!Instance) + InstanceScript* instance = player->GetInstanceScript(); + if (!instance) return false; - Creature* Ossirian = player->FindNearestCreature(NPC_OSSIRIAN, 30.0f); - if (!Ossirian || Instance->GetBossState(DATA_OSSIRIAN) != IN_PROGRESS) + Creature* ossirian = instance->GetCreature(DATA_OSSIRIAN); + if (!ossirian || instance->GetBossState(DATA_OSSIRIAN) != IN_PROGRESS) return false; - Ossirian->AI()->DoAction(ACTION_TRIGGER_WEAKNESS); + ossirian->AI()->DoAction(ACTION_TRIGGER_WEAKNESS); return true; } }; @@ -308,13 +298,15 @@ enum AnubisathGuardian struct npc_anubisath_guardian : public ScriptedAI { - npc_anubisath_guardian(Creature* creature) : ScriptedAI(creature) { } + npc_anubisath_guardian(Creature* creature) : ScriptedAI(creature) + { + _spells[0] = RAND(SPELL_SHADOW_STORM, SPELL_THUNDER_CLAP); + _spells[1] = RAND(SPELL_REFLECT_ARCANE_FIRE, SPELL_REFLECT_FROST_SHADOW); + } void Reset() override { _enraged = false; - _spells[0] = RAND(SPELL_SHADOW_STORM, SPELL_THUNDER_CLAP); - _spells[1] = RAND(SPELL_REFLECT_ARCANE_FIRE, SPELL_REFLECT_FROST_SHADOW); _scheduler.SetValidator([this] { @@ -368,7 +360,7 @@ private: void AddSC_boss_ossirian() { - new boss_ossirian(); + RegisterRuinsOfAhnQirajCreatureAI(boss_ossirian); new go_ossirian_crystal(); RegisterCreatureAI(npc_anubisath_guardian); } From fdb18e0204665b3c5b1ea03a9e3fd306e9827590 Mon Sep 17 00:00:00 2001 From: Skjalf <47818697+Nyeriah@users.noreply.github.com> Date: Tue, 26 Jul 2022 01:25:29 -0300 Subject: [PATCH 110/130] fix(Scripts/RuinsOfAhnQiraj): Rewrite Moam (#12539) * fix(Scripts/RuinsOfAhnQiraj): Rewrite Moam * serverside spell for summons, as well as summon phase handling * end stone phase if he reaches full mana * add missing emote * remove unused variable * move script to the new model * Update boss_moam.cpp * should not drain mana while stoned --- .../rev_1658801275458302100.sql | 12 + .../Kalimdor/RuinsOfAhnQiraj/boss_moam.cpp | 233 ++++++++++-------- 2 files changed, 136 insertions(+), 109 deletions(-) create mode 100644 data/sql/updates/pending_db_world/rev_1658801275458302100.sql diff --git a/data/sql/updates/pending_db_world/rev_1658801275458302100.sql b/data/sql/updates/pending_db_world/rev_1658801275458302100.sql new file mode 100644 index 000000000..c3423a875 --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1658801275458302100.sql @@ -0,0 +1,12 @@ +-- +DELETE FROM `spell_script_names` WHERE `ScriptName` = 'spell_moam_mana_drain_filter'; +INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES +(25676, 'spell_moam_mana_drain_filter'); + +DELETE FROM `spell_script_names` WHERE `ScriptName` = 'spell_moam_summon_mana_fiends'; +INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES +(25684, 'spell_moam_summon_mana_fiends'); + +DELETE FROM `creature_text` WHERE `CreatureID` = 15340 AND `GroupID` = 2; +INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES +(15340, 2, 0, '%s drains your mana and turns to stone.', 16, 0, 100, 0, 0, 0, 11474, 0, 'moam EMOTE_STONE_PHASE'); diff --git a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_moam.cpp b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_moam.cpp index f1908a381..a4f70a104 100644 --- a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_moam.cpp +++ b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_moam.cpp @@ -15,21 +15,26 @@ * with this program. If not, see . */ +#include "Player.h" #include "ScriptMgr.h" #include "ScriptedCreature.h" +#include "SpellScript.h" #include "ruins_of_ahnqiraj.h" enum Texts { EMOTE_AGGRO = 0, - EMOTE_MANA_FULL = 1 + EMOTE_MANA_FULL = 1, + EMOTE_STONE_PHASE = 2 }; enum Spells { SPELL_TRAMPLE = 15550, + SPELL_DRAIN_MANA_SERVERSIDE = 25676, SPELL_DRAIN_MANA = 25671, SPELL_ARCANE_ERUPTION = 25672, + SPELL_SUMMON_MANA_FIENDS = 25684, SPELL_SUMMON_MANA_FIEND_1 = 25681, // TARGET_DEST_CASTER_FRONT SPELL_SUMMON_MANA_FIEND_2 = 25682, // TARGET_DEST_CASTER_LEFT SPELL_SUMMON_MANA_FIEND_3 = 25683, // TARGET_DEST_CASTER_RIGHT @@ -46,134 +51,144 @@ enum Events EVENT_STONE_PHASE_END = 4 }; -enum Actions +struct boss_moam : public BossAI { - ACTION_STONE_PHASE_START = 1, - ACTION_STONE_PHASE_END = 2 -}; + boss_moam(Creature* creature) : BossAI(creature, DATA_MOAM) {} -class boss_moam : public CreatureScript -{ -public: - boss_moam() : CreatureScript("boss_moam") { } - - struct boss_moamAI : public BossAI + void Reset() override { - boss_moamAI(Creature* creature) : BossAI(creature, DATA_MOAM) {} + _Reset(); + me->SetPower(POWER_MANA, 0); + me->SetRegeneratingPower(false); + } - void Reset() override + void EnterCombat(Unit* who) override + { + BossAI::EnterCombat(who); + Talk(EMOTE_AGGRO); + events.ScheduleEvent(EVENT_STONE_PHASE, 90000); + events.ScheduleEvent(EVENT_SPELL_TRAMPLE, 9000); + events.ScheduleEvent(EVENT_SPELL_DRAIN_MANA, 3000); + } + + void JustDied(Unit* /*killer*/) override + { + _JustDied(); + DoCastAOE(SPELL_LARGE_OBSIDIAN_CHUNK, true); + } + + void SummonedCreatureDies(Creature* /*creature*/, Unit* /*killer*/) override + { + if (!summons.IsAnyCreatureAlive() && me->HasAura(SPELL_ENERGIZE)) { - _Reset(); - me->SetPower(POWER_MANA, 0); - me->SetRegeneratingPower(false); - _isStonePhase = false; + events.RescheduleEvent(EVENT_STONE_PHASE_END, 1s); + } + } + + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->GetPower(POWER_MANA) == me->GetMaxPower(POWER_MANA)) + { + if (me->HasAura(SPELL_ENERGIZE)) + { + me->RemoveAurasDueToSpell(SPELL_ENERGIZE); + events.RescheduleEvent(EVENT_STONE_PHASE_END, 1s); + } + + Talk(EMOTE_MANA_FULL); + DoCastAOE(SPELL_ARCANE_ERUPTION); } - void DoAction(int32 action) override + while (uint32 eventId = events.ExecuteEvent()) { - switch (action) + switch (eventId) { - case ACTION_STONE_PHASE_END: - { - me->RemoveAurasDueToSpell(SPELL_ENERGIZE); - events.ScheduleEvent(EVENT_STONE_PHASE, 90000); - _isStonePhase = false; - break; - } - case ACTION_STONE_PHASE_START: - { - DoCastSelf(SPELL_SUMMON_MANA_FIEND_1); - DoCastSelf(SPELL_SUMMON_MANA_FIEND_2); - DoCastSelf(SPELL_SUMMON_MANA_FIEND_3); - DoCastSelf(SPELL_ENERGIZE); - events.ScheduleEvent(EVENT_STONE_PHASE_END, 90000); - break; - } + case EVENT_STONE_PHASE: + Talk(EMOTE_STONE_PHASE); + DoCastAOE(SPELL_SUMMON_MANA_FIENDS); + DoCastSelf(SPELL_ENERGIZE); + events.CancelEvent(EVENT_SPELL_DRAIN_MANA); + events.ScheduleEvent(EVENT_STONE_PHASE_END, 90000); + break; + case EVENT_STONE_PHASE_END: + me->RemoveAurasDueToSpell(SPELL_ENERGIZE); + events.ScheduleEvent(EVENT_SPELL_DRAIN_MANA, urand(2000, 6000)); + events.ScheduleEvent(EVENT_STONE_PHASE, 90000); + break; + case EVENT_SPELL_DRAIN_MANA: + DoCastAOE(SPELL_DRAIN_MANA_SERVERSIDE); + events.ScheduleEvent(EVENT_SPELL_DRAIN_MANA, urand(2000, 6000)); + break; + case EVENT_SPELL_TRAMPLE: + DoCastAOE(SPELL_TRAMPLE); + events.ScheduleEvent(EVENT_SPELL_TRAMPLE, 15000); + break; default: break; } } - void EnterCombat(Unit* who) override - { - BossAI::EnterCombat(who); - Talk(EMOTE_AGGRO); - events.ScheduleEvent(EVENT_STONE_PHASE, 90000); - events.ScheduleEvent(EVENT_SPELL_TRAMPLE, 9000); - events.ScheduleEvent(EVENT_SPELL_DRAIN_MANA, 3000); - } + DoMeleeAttackIfReady(); + } +}; - void JustDied(Unit* /*killer*/) override - { - _JustDied(); - DoCastAOE(SPELL_LARGE_OBSIDIAN_CHUNK, true); - } +// 25676 - Drain Mana (server-side) +class spell_moam_mana_drain_filter : public SpellScript +{ + PrepareSpellScript(spell_moam_mana_drain_filter); - void UpdateAI(uint32 diff) override - { - if (!UpdateVictim()) - return; - - events.Update(diff); - if (me->GetPower(POWER_MANA) == me->GetMaxPower(POWER_MANA)) - { - Talk(EMOTE_MANA_FULL); - DoCastAOE(SPELL_ARCANE_ERUPTION, true); - me->SetPower(POWER_MANA, 0); - } - - while (uint32 eventId = events.ExecuteEvent()) - { - switch (eventId) - { - case EVENT_STONE_PHASE: - DoAction(ACTION_STONE_PHASE_START); - break; - case EVENT_STONE_PHASE_END: - DoAction(ACTION_STONE_PHASE_END); - break; - case EVENT_SPELL_DRAIN_MANA: - { - std::list targetList; - { - const std::list& threatlist = me->GetThreatMgr().getThreatList(); - for (std::list::const_iterator itr = threatlist.begin(); itr != threatlist.end(); ++itr) - { - if ((*itr)->getTarget()->GetTypeId() == TYPEID_PLAYER && (*itr)->getTarget()->getPowerType() == POWER_MANA) - { - targetList.push_back((*itr)->getTarget()); - } - } - } - Acore::Containers::RandomResize(targetList, 6); - for (std::list::iterator itr = targetList.begin(); itr != targetList.end(); ++itr) - { - DoCast(*itr, SPELL_DRAIN_MANA); - } - events.ScheduleEvent(EVENT_SPELL_DRAIN_MANA, urand(2000, 6000)); - break; - } - case EVENT_SPELL_TRAMPLE: - DoCastVictim(SPELL_TRAMPLE); - events.ScheduleEvent(EVENT_SPELL_TRAMPLE, 15000); - break; - default: - break; - } - } - DoMeleeAttackIfReady(); - } - private: - bool _isStonePhase; - }; - - CreatureAI* GetAI(Creature* creature) const override + void FilterTargets(std::list& targets) { - return GetRuinsOfAhnQirajAI(creature); + targets.remove_if([&](WorldObject* target) -> bool + { + return !target->IsPlayer() || target->ToPlayer()->getPowerType() != POWER_MANA; + }); + } + + void HandleScript(SpellEffIndex /*effIndex*/) + { + if (Unit* caster = GetCaster()) + { + caster->CastSpell(GetHitUnit(), SPELL_DRAIN_MANA, true); + } + } + + void Register() override + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_moam_mana_drain_filter::FilterTargets, EFFECT_ALL, TARGET_UNIT_DEST_AREA_ENEMY); + OnEffectHitTarget += SpellEffectFn(spell_moam_mana_drain_filter::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } +}; + +// 25684 - Summon Mana Fiends (server-side) +class spell_moam_summon_mana_fiends : public SpellScript +{ + PrepareSpellScript(spell_moam_summon_mana_fiends); + + void HandleScript(SpellEffIndex /*effIndex*/) + { + const uint32 spellIds[3] = { SPELL_SUMMON_MANA_FIEND_1, SPELL_SUMMON_MANA_FIEND_2, SPELL_SUMMON_MANA_FIEND_3 }; + + for (uint32 spellId : spellIds) + { + GetCaster()->CastSpell((Unit*)nullptr, spellId, true); + } + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_moam_summon_mana_fiends::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); } }; void AddSC_boss_moam() { - new boss_moam(); + RegisterRuinsOfAhnQirajCreatureAI(boss_moam); + RegisterSpellScript(spell_moam_mana_drain_filter); + RegisterSpellScript(spell_moam_summon_mana_fiends); } From 90d08158d9e10f6da5422793503b944022f27ba7 Mon Sep 17 00:00:00 2001 From: AzerothCoreBot Date: Tue, 26 Jul 2022 04:27:33 +0000 Subject: [PATCH 111/130] chore(DB): import pending files Referenced commit(s): fdb18e0204665b3c5b1ea03a9e3fd306e9827590 --- .../rev_1658801275458302100.sql => db_world/2022_07_26_02.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/rev_1658801275458302100.sql => db_world/2022_07_26_02.sql} (94%) diff --git a/data/sql/updates/pending_db_world/rev_1658801275458302100.sql b/data/sql/updates/db_world/2022_07_26_02.sql similarity index 94% rename from data/sql/updates/pending_db_world/rev_1658801275458302100.sql rename to data/sql/updates/db_world/2022_07_26_02.sql index c3423a875..d69db58fc 100644 --- a/data/sql/updates/pending_db_world/rev_1658801275458302100.sql +++ b/data/sql/updates/db_world/2022_07_26_02.sql @@ -1,3 +1,4 @@ +-- DB update 2022_07_26_01 -> 2022_07_26_02 -- DELETE FROM `spell_script_names` WHERE `ScriptName` = 'spell_moam_mana_drain_filter'; INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES From f23692149802f82ea9581a59ac4a055bdd339aa5 Mon Sep 17 00:00:00 2001 From: Nefertumm Date: Tue, 26 Jul 2022 01:29:12 -0300 Subject: [PATCH 112/130] fix(Core/RuinsOfAhnQiraj): Buru (#12524) * fix(Core/RuinsOfAhnQiraj): Buru * spaces * revert phase transition * leftover conversion --- .../rev_1658706852781829600.sql | 4 + .../Kalimdor/RuinsOfAhnQiraj/boss_buru.cpp | 437 ++++++++---------- .../instance_ruins_of_ahnqiraj.cpp | 1 + 3 files changed, 205 insertions(+), 237 deletions(-) create mode 100644 data/sql/updates/pending_db_world/rev_1658706852781829600.sql diff --git a/data/sql/updates/pending_db_world/rev_1658706852781829600.sql b/data/sql/updates/pending_db_world/rev_1658706852781829600.sql new file mode 100644 index 000000000..19663fe7c --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1658706852781829600.sql @@ -0,0 +1,4 @@ +-- +DELETE FROM `spell_custom_attr` WHERE `spell_id` = 5255; +INSERT INTO `spell_custom_attr` (`spell_id`, `attributes`) VALUES +(5255, 0x00008000); diff --git a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_buru.cpp b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_buru.cpp index beef6ec42..97a419af7 100644 --- a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_buru.cpp +++ b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_buru.cpp @@ -18,6 +18,7 @@ #include "ScriptMgr.h" #include "ScriptedCreature.h" #include "SpellScript.h" +#include "TaskScheduler.h" #include "ruins_of_ahnqiraj.h" enum Emotes @@ -35,8 +36,9 @@ enum Spells SPELL_BURU_TRANSFORM = 24721, SPELL_SUMMON_HATCHLING = 1881, SPELL_EXPLODE = 19593, - SPELL_EXPLODE_2 = 5255, // Server-side script - SPELL_BURU_EGG_TRIGGER = 26646 + SPELL_EXPLODE_2 = 5255, + SPELL_BURU_EGG_TRIGGER = 26646, + SPELL_CREATURE_SPECIAL = 7155, // from sniffs }; enum Events @@ -45,7 +47,7 @@ enum Events EVENT_GATHERING_SPEED = 2, EVENT_FULL_SPEED = 3, EVENT_CREEPING_PLAGUE = 4, - EVENT_RESPAWN_EGG = 5 + EVENT_RESPAWN_EGG = 5, }; enum Phases @@ -54,268 +56,229 @@ enum Phases PHASE_TRANSFORM = 1 }; -enum Actions +struct boss_buru : public BossAI { - ACTION_EXPLODE = 0 -}; + boss_buru(Creature* creature) : BossAI(creature, DATA_BURU) {} -class boss_buru : public CreatureScript -{ -public: - boss_buru() : CreatureScript("boss_buru") { } - - struct boss_buruAI : public BossAI + void EnterEvadeMode(EvadeReason why) override { - boss_buruAI(Creature* creature) : BossAI(creature, DATA_BURU) {} + BossAI::EnterEvadeMode(why); - void EnterEvadeMode(EvadeReason why) override - { - BossAI::EnterEvadeMode(why); + DoCastSelf(SPELL_FULL_SPEED, true); - for (ObjectGuid const& guid : Eggs) - { - if (Creature* egg = me->GetMap()->GetCreature(guid)) - { - egg->Respawn(); - } - } - Eggs.clear(); - } + ManipulateEggs(true); + _eggs.clear(); + } - void EnterCombat(Unit* who) override - { - _EnterCombat(); - Talk(EMOTE_TARGET, who); - DoCast(me, SPELL_THORNS); - events.ScheduleEvent(EVENT_DISMEMBER, 5000); - events.ScheduleEvent(EVENT_GATHERING_SPEED, 9000); - events.ScheduleEvent(EVENT_FULL_SPEED, 60000); - _phase = PHASE_EGG; - } + void ManipulateEggs(bool respawn) + { + std::list eggs; + me->GetCreaturesWithEntryInRange(eggs, 150.0f, NPC_BURU_EGG); + for (Creature* egg : eggs) + respawn ? egg->Respawn() : Unit::Kill(me, egg); + } - void JustDied(Unit* /*killer*/) override - { - if (InstanceScript* pInstance = me->GetInstanceScript()) - { - pInstance->DoRemoveAurasDueToSpellOnPlayers(SPELL_CREEPING_PLAGUE); - } - } + void EnterCombat(Unit* who) override + { + _EnterCombat(); + Talk(EMOTE_TARGET, who); + DoCastSelf(SPELL_THORNS); + ManipulateEggs(true); + me->RemoveAurasDueToSpell(SPELL_FULL_SPEED); + events.ScheduleEvent(EVENT_DISMEMBER, 5s); + events.ScheduleEvent(EVENT_GATHERING_SPEED, 9s); + events.ScheduleEvent(EVENT_FULL_SPEED, 60s); + _phase = PHASE_EGG; + } - void DoAction(int32 action) override - { - if (action == ACTION_EXPLODE) - { - if (_phase == PHASE_EGG) - { - Unit::DealDamage(me, me, 45000); - } - } - } - - void KilledUnit(Unit* victim) override - { - if (victim->GetTypeId() == TYPEID_PLAYER) - { - ChaseNewVictim(); - } - } - - void ChaseNewVictim() - { - if (_phase != PHASE_EGG) - return; - - me->RemoveAurasDueToSpell(SPELL_FULL_SPEED); - me->RemoveAurasDueToSpell(SPELL_GATHERING_SPEED); - events.ScheduleEvent(EVENT_GATHERING_SPEED, 9000); - events.ScheduleEvent(EVENT_FULL_SPEED, 60000); - if (Unit* victim = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true)) - { - DoResetThreat(); - AttackStart(victim); - Talk(EMOTE_TARGET, victim); - } - } - - void ManageRespawn(ObjectGuid EggGUID) - { + void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override + { + if (spell->Id == SPELL_CREATURE_SPECIAL) ChaseNewVictim(); - Eggs.push_back(EggGUID); - events.ScheduleEvent(EVENT_RESPAWN_EGG, 100000); - } - - void UpdateAI(uint32 diff) override - { - if (!UpdateVictim()) - return; - - events.Update(diff); - - while (uint32 eventId = events.ExecuteEvent()) - { - switch (eventId) - { - case EVENT_DISMEMBER: - DoCastVictim(SPELL_DISMEMBER); - events.ScheduleEvent(EVENT_DISMEMBER, 5000); - break; - case EVENT_GATHERING_SPEED: - DoCastSelf(SPELL_GATHERING_SPEED); - events.ScheduleEvent(EVENT_GATHERING_SPEED, 9000); - break; - case EVENT_FULL_SPEED: - DoCastSelf(SPELL_FULL_SPEED); - break; - case EVENT_CREEPING_PLAGUE: - DoCastAOE(SPELL_CREEPING_PLAGUE); - events.ScheduleEvent(EVENT_CREEPING_PLAGUE, urand(6250, 6500)); - break; - case EVENT_RESPAWN_EGG: - if (Creature* egg = me->GetMap()->GetCreature(*Eggs.begin())) - { - egg->Respawn(); - Eggs.pop_front(); - } - break; - default: - break; - } - } - - if (me->GetHealthPct() < 20.0f && _phase == PHASE_EGG) - { - DoCastSelf(SPELL_BURU_TRANSFORM); - DoCastSelf(SPELL_FULL_SPEED, true); - me->RemoveAurasDueToSpell(SPELL_THORNS); - events.CancelEvent(EVENT_DISMEMBER); - events.ScheduleEvent(EVENT_CREEPING_PLAGUE, 2000); - _phase = PHASE_TRANSFORM; - std::list RemainingEgg; - me->GetCreaturesWithEntryInRange(RemainingEgg, 100.0f, NPC_BURU_EGG); - for (std::list::const_iterator itr = RemainingEgg.begin(); itr != RemainingEgg.end(); ++itr) - { - Unit::Kill(me, *itr); - } - } - DoMeleeAttackIfReady(); - } - private: - uint8 _phase; - GuidList Eggs; - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return GetRuinsOfAhnQirajAI(creature); } + + void JustDied(Unit* /*killer*/) override + { + if (InstanceScript* pInstance = me->GetInstanceScript()) + { + pInstance->DoRemoveAurasDueToSpellOnPlayers(SPELL_CREEPING_PLAGUE); + } + } + + void KilledUnit(Unit* victim) override + { + if (victim->GetTypeId() == TYPEID_PLAYER) + ChaseNewVictim(); + } + + void ChaseNewVictim() + { + if (_phase != PHASE_EGG) + return; + + me->RemoveAurasDueToSpell(SPELL_FULL_SPEED); + me->RemoveAurasDueToSpell(SPELL_GATHERING_SPEED); + events.ScheduleEvent(EVENT_GATHERING_SPEED, 9s); + events.ScheduleEvent(EVENT_FULL_SPEED, 60s); + if (Unit* victim = SelectTarget(SelectTargetMethod::Random, 0, 0.f, true)) + { + DoResetThreat(); + AttackStart(victim); + me->AddThreat(victim, 1000000.f); + Talk(EMOTE_TARGET, victim); + } + } + + void SetGUID(ObjectGuid const guid, int32 /*type*/) override + { + _eggs.push_back(guid); + events.ScheduleEvent(EVENT_RESPAWN_EGG, 120s); + } + + void DamageTaken(Unit* attacker, uint32& damage, DamageEffectType, SpellSchoolMask) override + { + if (attacker->GetEntry() != NPC_BURU_EGG && _phase == PHASE_EGG) + { + damage = damage * 0.01f; // 99% dmg resist + } + + if (me->HealthBelowPctDamaged(20, damage) && _phase == PHASE_EGG) + { + DoCastSelf(SPELL_FULL_SPEED, true); + ManipulateEggs(false); + me->RemoveAurasDueToSpell(SPELL_THORNS); + events.Reset(); + _phase = PHASE_TRANSFORM; + DoResetThreat(); + events.ScheduleEvent(EVENT_CREEPING_PLAGUE, 2s); + DoCastSelf(SPELL_BURU_TRANSFORM); + } + } + + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; + + events.Update(diff); + + while (uint32 eventId = events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_DISMEMBER: + DoCastVictim(SPELL_DISMEMBER); + events.ScheduleEvent(EVENT_DISMEMBER, 5s); + break; + case EVENT_GATHERING_SPEED: + DoCastSelf(SPELL_GATHERING_SPEED); + events.ScheduleEvent(EVENT_GATHERING_SPEED, 9s); + break; + case EVENT_FULL_SPEED: + DoCastSelf(SPELL_FULL_SPEED); + break; + case EVENT_CREEPING_PLAGUE: + DoCastAOE(SPELL_CREEPING_PLAGUE); + events.ScheduleEvent(EVENT_CREEPING_PLAGUE, 6s); + break; + case EVENT_RESPAWN_EGG: + if (Creature* egg = me->GetMap()->GetCreature(*_eggs.begin())) + egg->Respawn(); + + _eggs.pop_front(); + break; + default: + break; + } + } + + DoMeleeAttackIfReady(); + } +private: + uint8 _phase; + GuidList _eggs; }; -class npc_buru_egg : public CreatureScript +struct npc_buru_egg : public ScriptedAI { -public: - npc_buru_egg() : CreatureScript("npc_buru_egg") { } - - struct npc_buru_eggAI : public ScriptedAI + npc_buru_egg(Creature* creature) : ScriptedAI(creature) { - npc_buru_eggAI(Creature* creature) : ScriptedAI(creature) - { - _instance = me->GetInstanceScript(); - SetCombatMovement(false); - } - - void EnterCombat(Unit* attacker) override - { - if (Creature* buru = me->GetMap()->GetCreature(_instance->GetGuidData(DATA_BURU))) - { - if (!buru->IsInCombat()) - { - buru->AI()->AttackStart(attacker); - } - } - } - - void JustSummoned(Creature* who) override - { - if (who->GetEntry() == NPC_HATCHLING) - { - if (Creature* buru = me->GetMap()->GetCreature(_instance->GetGuidData(DATA_BURU))) - { - if (Unit* target = buru->AI()->SelectTarget(SelectTargetMethod::Random)) - { - who->AI()->AttackStart(target); - } - } - } - } - - void JustDied(Unit* /*killer*/) override - { - if (Creature* buru = me->GetMap()->GetCreature(_instance->GetGuidData(DATA_BURU))) - { - if (!buru->HasAura(SPELL_BURU_TRANSFORM)) - { - DoCast(me, SPELL_EXPLODE, true); - DoCast(me, SPELL_EXPLODE_2, true); - DoCast(me, SPELL_BURU_EGG_TRIGGER, true); - } - if (boss_buru::boss_buruAI* buruAI = dynamic_cast(buru->AI())) - { - buruAI->ManageRespawn(me->GetGUID()); - } - } - DoCast(me, SPELL_SUMMON_HATCHLING, true); - } - private: - InstanceScript* _instance; - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return GetRuinsOfAhnQirajAI(creature); + _instance = me->GetInstanceScript(); + SetCombatMovement(false); + me->SetReactState(REACT_PASSIVE); } + + void EnterCombat(Unit* attacker) override + { + if (Creature* buru = _instance->GetCreature(DATA_BURU)) + { + if (!buru->IsInCombat()) + { + buru->AI()->AttackStart(attacker); + } + } + } + + void JustSummoned(Creature* who) override + { + if (who->GetEntry() == NPC_HATCHLING) + { + if (Creature* buru = _instance->GetCreature(DATA_BURU)) + { + if (Unit* target = buru->AI()->SelectTarget(SelectTargetMethod::Random)) + { + who->AI()->AttackStart(target); + } + } + } + } + + void JustDied(Unit* killer) override + { + DoCastSelf(SPELL_SUMMON_HATCHLING, true); + if (killer->GetEntry() != NPC_BURU) + { + if (Creature* buru = _instance->GetCreature(DATA_BURU)) + { + DoCastSelf(SPELL_EXPLODE); + DoCastSelf(SPELL_BURU_EGG_TRIGGER, true); + buru->CastSpell(buru, SPELL_CREATURE_SPECIAL, true); + if (buru->GetAI()) + buru->AI()->SetGUID(me->GetGUID()); + } + } + } +private: + InstanceScript* _instance; }; -class spell_egg_explosion : public SpellScriptLoader +class spell_egg_explosion : public SpellScript { -public: - spell_egg_explosion() : SpellScriptLoader("spell_egg_explosion") { } + PrepareSpellScript(spell_egg_explosion); - class spell_egg_explosion_SpellScript : public SpellScript + void HandleDummyHitTarget(SpellEffIndex /*effIndex*/) { - PrepareSpellScript(spell_egg_explosion_SpellScript); - - void HandleAfterCast() + if (Unit* target = GetHitUnit()) { - if (Creature* buru = GetCaster()->FindNearestCreature(NPC_BURU, 5.f)) - { - buru->AI()->DoAction(ACTION_EXPLODE); - } - } + int32 damage = 0; + if (target->IsPlayer()) + damage = -16 * GetCaster()->GetDistance(target) + 500; + else if (target->GetEntry() == NPC_BURU && target->HasAura(SPELL_THORNS)) + damage = target->GetMaxHealth() * 7.f / 100; - void HandleDummyHitTarget(SpellEffIndex /*effIndex*/) - { - if (Unit* target = GetHitUnit()) - { - Unit::DealDamage(GetCaster(), target, -16 * GetCaster()->GetDistance(target) + 500); - } + GetCaster()->CastCustomSpell(target, SPELL_EXPLODE_2, &damage, nullptr, nullptr, true); } + } - void Register() override - { - AfterCast += SpellCastFn(spell_egg_explosion_SpellScript::HandleAfterCast); - OnEffectHitTarget += SpellEffectFn(spell_egg_explosion_SpellScript::HandleDummyHitTarget, EFFECT_0, SPELL_EFFECT_DUMMY); - } - }; - - SpellScript* GetSpellScript() const override + void Register() override { - return new spell_egg_explosion_SpellScript(); + OnEffectHitTarget += SpellEffectFn(spell_egg_explosion::HandleDummyHitTarget, EFFECT_0, SPELL_EFFECT_DUMMY); } }; void AddSC_boss_buru() { - new boss_buru(); - new npc_buru_egg(); - new spell_egg_explosion(); + RegisterRuinsOfAhnQirajCreatureAI(boss_buru); + RegisterRuinsOfAhnQirajCreatureAI(npc_buru_egg); + RegisterSpellScript(spell_egg_explosion); } 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 a84522ab0..aa088d091 100644 --- a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/instance_ruins_of_ahnqiraj.cpp +++ b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/instance_ruins_of_ahnqiraj.cpp @@ -23,6 +23,7 @@ ObjectData const creatureData[] = { + { NPC_BURU, DATA_BURU }, { NPC_KURINNAXX, DATA_KURINNAXX }, { NPC_RAJAXX, DATA_RAJAXX }, { NPC_OSSIRIAN, DATA_OSSIRIAN }, From 016375ee8aa3c68c2843a09923a3495f3f49d408 Mon Sep 17 00:00:00 2001 From: AzerothCoreBot Date: Tue, 26 Jul 2022 04:31:34 +0000 Subject: [PATCH 113/130] chore(DB): import pending files Referenced commit(s): f23692149802f82ea9581a59ac4a055bdd339aa5 --- .../rev_1658706852781829600.sql => db_world/2022_07_26_03.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/rev_1658706852781829600.sql => db_world/2022_07_26_03.sql} (76%) diff --git a/data/sql/updates/pending_db_world/rev_1658706852781829600.sql b/data/sql/updates/db_world/2022_07_26_03.sql similarity index 76% rename from data/sql/updates/pending_db_world/rev_1658706852781829600.sql rename to data/sql/updates/db_world/2022_07_26_03.sql index 19663fe7c..eae6e9558 100644 --- a/data/sql/updates/pending_db_world/rev_1658706852781829600.sql +++ b/data/sql/updates/db_world/2022_07_26_03.sql @@ -1,3 +1,4 @@ +-- DB update 2022_07_26_02 -> 2022_07_26_03 -- DELETE FROM `spell_custom_attr` WHERE `spell_id` = 5255; INSERT INTO `spell_custom_attr` (`spell_id`, `attributes`) VALUES From 278845f731f0a20ffec9fa555c7cf238f01090b3 Mon Sep 17 00:00:00 2001 From: Eddy Vega <61223313+Si1ker@users.noreply.github.com> Date: Tue, 26 Jul 2022 07:02:22 -0600 Subject: [PATCH 114/130] fix(Scripts/RuinsOfAhnQiraj): Improve Ayamiss (#12143) --- .../rev_1655864210422775700.sql | 7 ++ .../Kalimdor/RuinsOfAhnQiraj/boss_ayamiss.cpp | 86 ++++++++++--------- 2 files changed, 51 insertions(+), 42 deletions(-) create mode 100644 data/sql/updates/pending_db_world/rev_1655864210422775700.sql diff --git a/data/sql/updates/pending_db_world/rev_1655864210422775700.sql b/data/sql/updates/pending_db_world/rev_1655864210422775700.sql new file mode 100644 index 000000000..1211dc870 --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1655864210422775700.sql @@ -0,0 +1,7 @@ +-- + +UPDATE `creature_template` SET `mingold`=0, `maxgold`=0 WHERE `entry`=15546; +UPDATE `creature_template` SET `flags_extra`=`flags_extra`|256 WHERE `entry`=15369; +INSERT INTO `creature_addon` (`guid`, `auras`) VALUES +(144641, '8876'); -- Triggers SPELL_THRASH = 3391 + diff --git a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_ayamiss.cpp b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_ayamiss.cpp index 977f2fbb4..d1198e820 100644 --- a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_ayamiss.cpp +++ b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_ayamiss.cpp @@ -25,7 +25,6 @@ enum Spells SPELL_STINGER_SPRAY = 25749, SPELL_POISON_STINGER = 25748, SPELL_PARALYZE = 25725, - SPELL_TRASH = 3391, SPELL_FRENZY = 8269, SPELL_LASH = 25852, SPELL_FEED = 25721 @@ -38,8 +37,7 @@ enum Events EVENT_SUMMON_SWARMER = 3, EVENT_SWARMER_ATTACK = 4, EVENT_PARALYZE = 5, - EVENT_LASH = 6, - EVENT_TRASH = 7 + EVENT_LASH = 6 }; enum Emotes @@ -77,9 +75,7 @@ public: struct boss_ayamissAI : public BossAI { - boss_ayamissAI(Creature* creature) : BossAI(creature, DATA_AYAMISS) - { - } + boss_ayamissAI(Creature* creature) : BossAI(creature, DATA_AYAMISS) {} void Reset() override { @@ -101,7 +97,9 @@ public: break; case NPC_HORNET: if (Unit* target = SelectTarget(SelectTargetMethod::Random)) + { who->AI()->AttackStart(target); + } break; } } @@ -116,7 +114,7 @@ public: me->AddUnitState(UNIT_STATE_ROOT); break; case POINT_GROUND: - me->ClearUnitState(UNIT_STATE_ROOT); + me->GetMotionMaster()->MoveChase(me->GetVictim()); break; } } @@ -131,55 +129,51 @@ public: void EnterCombat(Unit* attacker) override { BossAI::EnterCombat(attacker); - events.ScheduleEvent(EVENT_STINGER_SPRAY, urand(20000, 30000)); events.ScheduleEvent(EVENT_POISON_STINGER, 5000); events.ScheduleEvent(EVENT_SUMMON_SWARMER, 5000); events.ScheduleEvent(EVENT_SWARMER_ATTACK, 60000); events.ScheduleEvent(EVENT_PARALYZE, 15000); - me->SetCanFly(true); me->SetDisableGravity(true); me->GetMotionMaster()->MovePoint(POINT_AIR, AyamissAirPos); } + void DamageTaken(Unit*, uint32& /*damage*/, DamageEffectType, SpellSchoolMask) override + { + if (_phase == PHASE_AIR && me->GetHealthPct() < 70.0f) + { + _phase = PHASE_GROUND; + SetCombatMovement(true); + me->ClearUnitState(UNIT_STATE_ROOT); + me->SetCanFly(false); + me->SetDisableGravity(false); + Position VictimPos = me->GetVictim()->GetPosition(); + me->GetMotionMaster()->MovePoint(POINT_GROUND, VictimPos); + events.ScheduleEvent(EVENT_LASH, urand(5000, 8000)); + events.CancelEvent(EVENT_POISON_STINGER); + DoResetThreat(); + } + if (!_enraged && me->GetHealthPct() < 20.0f) + { + DoCastSelf(SPELL_FRENZY); + Talk(EMOTE_FRENZY); + _enraged = true; + } + } + void UpdateAI(uint32 diff) override { if (!UpdateVictim()) return; events.Update(diff); - - if (_phase == PHASE_AIR && me->GetHealthPct() < 70.0f) - { - _phase = PHASE_GROUND; - SetCombatMovement(true); - me->SetCanFly(false); - Position VictimPos = me->GetVictim()->GetPosition(); - me->GetMotionMaster()->MovePoint(POINT_GROUND, VictimPos); - DoResetThreat(); - events.ScheduleEvent(EVENT_LASH, urand(5000, 8000)); - events.ScheduleEvent(EVENT_TRASH, urand(3000, 6000)); - events.CancelEvent(EVENT_POISON_STINGER); - } - else - { - DoMeleeAttackIfReady(); - } - - if (!_enraged && me->GetHealthPct() < 20.0f) - { - DoCast(me, SPELL_FRENZY); - Talk(EMOTE_FRENZY); - _enraged = true; - } - while (uint32 eventId = events.ExecuteEvent()) { switch (eventId) { case EVENT_STINGER_SPRAY: - DoCast(me, SPELL_STINGER_SPRAY); + DoCastSelf(SPELL_STINGER_SPRAY); events.ScheduleEvent(EVENT_STINGER_SPRAY, urand(15000, 20000)); break; case EVENT_POISON_STINGER: @@ -198,30 +192,32 @@ public: break; case EVENT_SWARMER_ATTACK: for (ObjectGuid const& guid : _swarmers) + { if (Creature* swarmer = me->GetMap()->GetCreature(guid)) + { if (Unit* target = SelectTarget(SelectTargetMethod::Random)) + { swarmer->AI()->AttackStart(target); - + } + } + } _swarmers.clear(); events.ScheduleEvent(EVENT_SWARMER_ATTACK, 60000); break; case EVENT_SUMMON_SWARMER: { Position Pos = me->GetRandomPoint(SwarmerPos, 80.0f); - me->SummonCreature(NPC_SWARMER, Pos); + me->SummonCreature(NPC_SWARMER, Pos, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 5000); events.ScheduleEvent(EVENT_SUMMON_SWARMER, 5000); break; } - case EVENT_TRASH: - DoCastVictim(SPELL_TRASH); - events.ScheduleEvent(EVENT_TRASH, urand(5000, 7000)); - break; case EVENT_LASH: DoCastVictim(SPELL_LASH); events.ScheduleEvent(EVENT_LASH, urand(8000, 15000)); break; } } + DoMeleeAttackIfReady(); } private: GuidList _swarmers; @@ -250,9 +246,15 @@ public: void MovementInform(uint32 type, uint32 id) override { if (type == POINT_MOTION_TYPE) + { if (id == POINT_PARALYZE) + { if (Player* target = ObjectAccessor::GetPlayer(*me, _instance->GetGuidData(DATA_PARALYZED))) - DoCast(target, SPELL_FEED); // Omnomnom + { + DoCast(target, SPELL_FEED); + } + } + } } void MoveInLineOfSight(Unit* who) override From d3f2809c277ffa4e4e1c36a1b319266448ca458d Mon Sep 17 00:00:00 2001 From: AzerothCoreBot Date: Tue, 26 Jul 2022 13:04:39 +0000 Subject: [PATCH 115/130] chore(DB): import pending files Referenced commit(s): 278845f731f0a20ffec9fa555c7cf238f01090b3 --- .../rev_1655864210422775700.sql => db_world/2022_07_26_04.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/rev_1655864210422775700.sql => db_world/2022_07_26_04.sql} (86%) diff --git a/data/sql/updates/pending_db_world/rev_1655864210422775700.sql b/data/sql/updates/db_world/2022_07_26_04.sql similarity index 86% rename from data/sql/updates/pending_db_world/rev_1655864210422775700.sql rename to data/sql/updates/db_world/2022_07_26_04.sql index 1211dc870..b81a33be0 100644 --- a/data/sql/updates/pending_db_world/rev_1655864210422775700.sql +++ b/data/sql/updates/db_world/2022_07_26_04.sql @@ -1,3 +1,4 @@ +-- DB update 2022_07_26_03 -> 2022_07_26_04 -- UPDATE `creature_template` SET `mingold`=0, `maxgold`=0 WHERE `entry`=15546; From d0561c56df194aa9eff0f18b237664659153c85b Mon Sep 17 00:00:00 2001 From: Skjalf <47818697+Nyeriah@users.noreply.github.com> Date: Tue, 26 Jul 2022 14:29:17 -0300 Subject: [PATCH 116/130] =?UTF-8?q?fix(Scripts/TempleOfAhnQiraj):=20Clear?= =?UTF-8?q?=20Eye=20of=20C'thun=20scheduler=20during=20p=E2=80=A6=20(#1254?= =?UTF-8?q?5)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fix(Scripts/TempleOfAhnQiraj): Clear Eye of C'thun scheduler during phase 2 --- src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_cthun.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_cthun.cpp b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_cthun.cpp index e2a9f9453..66211a1b0 100644 --- a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_cthun.cpp +++ b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_cthun.cpp @@ -379,6 +379,7 @@ public: me->InterruptNonMeleeSpells(true); me->RemoveAllAuras(); + _scheduler.CancelAll(); break; case PHASE_CTHUN_DONE: From 8f386e83de103d0e3f5229c0915468017dd13ff7 Mon Sep 17 00:00:00 2001 From: ZhengPeiRu21 <98835050+ZhengPeiRu21@users.noreply.github.com> Date: Tue, 26 Jul 2022 17:06:10 -0600 Subject: [PATCH 117/130] fix(DB/Pathing): Missing Durotar Pathing (#12373) --- .../rev_1657730289541881400.sql | 759 ++++++++++++++++++ 1 file changed, 759 insertions(+) create mode 100644 data/sql/updates/pending_db_world/rev_1657730289541881400.sql diff --git a/data/sql/updates/pending_db_world/rev_1657730289541881400.sql b/data/sql/updates/pending_db_world/rev_1657730289541881400.sql new file mode 100644 index 000000000..de5504e54 --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1657730289541881400.sql @@ -0,0 +1,759 @@ +-- +/* Vile Familiar - GUID 4701 */ + + +SET @NPC := 4701; +SET @PATH := @NPC * 10; + +UPDATE `creature` SET `position_x` = -35.7399, `position_y` = -4228.09, `position_z` = 65.2618, `orientation` = 3.89663 WHERE `guid` = @NPC; + +DELETE FROM `creature_addon` WHERE `guid` = @NPC; +INSERT INTO `creature_addon` (`guid`, `path_id`) VALUES (@NPC, @PATH); +UPDATE `creature` SET `MovementType` = 2 WHERE `guid` = @NPC; + +DELETE FROM `waypoint_data` where `id` = @PATH; +INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `orientation`, `delay`) VALUES +(@PATH, 1, -35.7399, -4228.09, 65.2618, 100.0, 0), +(@PATH, 2, -25.1474, -4238.52, 68.0743, 100.0, 0), +(@PATH, 3, -28.5747, -4245.48, 68.4759, 100.0, 0), +(@PATH, 4, -23.6166, -4258.85, 66.6592, 100.0, 0), +(@PATH, 5, -35.6993, -4270.22, 66.894, 100.0, 0), +(@PATH, 6, -56.3938, -4280.35, 70.0308, 100.0, 0), +(@PATH, 7, -53.3781, -4302.13, 69.8885, 100.0, 0), +(@PATH, 8, -39.7387, -4310.99, 70.2738, 100.0, 0), +(@PATH, 9, -53.3781, -4302.13, 69.8885, 100.0, 0), +(@PATH, 10, -56.3938, -4280.35, 70.0308, 100.0, 0), +(@PATH, 11, -35.6993, -4270.22, 66.894, 100.0, 0), +(@PATH, 12, -23.6166, -4258.85, 66.6592, 100.0, 0), +(@PATH, 13, -28.5747, -4245.48, 68.4759, 100.0, 0), +(@PATH, 14, -25.1474, -4238.52, 68.0743, 100.0, 0), +(@PATH, 15, -35.7399, -4228.09, 65.2619, 100.0, 0), +(@PATH, 16, -49.5318, -4222.88, 62.2678, 100.0, 0); + + +/* Vile Familiar - GUID 4705 */ + + +SET @NPC := 4705; +SET @PATH := @NPC * 10; + +UPDATE `creature` SET `position_x` = -152.718, `position_y` = -4264.43, `position_z` = 61.5234, `orientation` = 1.04177 WHERE `guid` = @NPC; + +DELETE FROM `creature_addon` WHERE `guid` = @NPC; +INSERT INTO `creature_addon` (`guid`, `path_id`) VALUES (@NPC, @PATH); +UPDATE `creature` SET `MovementType` = 2 WHERE `guid` = @NPC; + +DELETE FROM `waypoint_data` where `id` = @PATH; +INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `orientation`, `delay`) VALUES +(@PATH, 1, -152.718, -4264.43, 61.5234, 100.0, 0), +(@PATH, 2, -150.795, -4251.99, 59.8122, 100.0, 0), +(@PATH, 3, -140.417, -4234.24, 58.089, 100.0, 0), +(@PATH, 4, -127.943, -4230.0, 57.2045, 100.0, 0), +(@PATH, 5, -110.444, -4210.7, 54.7955, 100.0, 0), +(@PATH, 6, -96.4095, -4201.51, 51.431, 100.0, 0), +(@PATH, 7, -80.8383, -4204.42, 49.8348, 100.0, 0), +(@PATH, 8, -79.6806, -4223.97, 53.0284, 100.0, 0), +(@PATH, 9, -83.5118, -4242.02, 52.784, 100.0, 0), +(@PATH, 10, -96.4792, -4250.83, 51.9981, 100.0, 0), +(@PATH, 11, -83.5118, -4242.02, 52.784, 100.0, 0), +(@PATH, 12, -79.6806, -4223.97, 53.0284, 100.0, 0), +(@PATH, 13, -80.8383, -4204.42, 49.8348, 100.0, 0), +(@PATH, 14, -96.4095, -4201.51, 51.431, 100.0, 0), +(@PATH, 15, -110.265, -4210.5, 54.7808, 100.0, 0), +(@PATH, 16, -127.943, -4230.0, 57.2045, 100.0, 0), +(@PATH, 17, -140.286, -4234.02, 58.09, 100.0, 0), +(@PATH, 18, -150.776, -4251.96, 59.792, 100.0, 0), +(@PATH, 19, -152.797, -4264.3, 61.4815, 100.0, 0), +(@PATH, 20, -145.721, -4275.72, 63.287, 100.0, 0); + +/* Sen'jin Watcher - GUID 6401 */ + + +SET @NPC := 6401; +SET @PATH := @NPC * 10; + +UPDATE `creature` SET `position_x` = -820.061, `position_y` = -4892.82, `position_z` = 19.3183, `orientation` = 3.33843 WHERE `guid` = @NPC; + +DELETE FROM `creature_addon` WHERE `guid` = @NPC; +INSERT INTO `creature_addon` (`guid`, `path_id`) VALUES (@NPC, @PATH); +UPDATE `creature` SET `MovementType` = 2 WHERE `guid` = @NPC; + +DELETE FROM `waypoint_data` where `id` = @PATH; +INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `orientation`, `delay`) VALUES +(@PATH, 1, -820.061, -4892.82, 19.3183, 100.0, 0), +(@PATH, 2, -814.445, -4894.38, 19.1953, 100.0, 0), +(@PATH, 3, -810.197, -4898.55, 19.2201, 100.0, 0), +(@PATH, 4, -805.71, -4902.39, 19.3582, 100.0, 0), +(@PATH, 5, -800.273, -4902.95, 19.4798, 100.0, 0), +(@PATH, 6, -794.502, -4901.52, 19.5224, 100.0, 0), +(@PATH, 7, -791.733, -4902.05, 19.5467, 100.0, 0), +(@PATH, 8, -789.871, -4904.44, 19.5926, 100.0, 0), +(@PATH, 9, -790.881, -4909.7, 19.5959, 100.0, 0), +(@PATH, 10, -793.125, -4911.08, 19.5652, 100.0, 0), +(@PATH, 11, -798.939, -4909.47, 19.4492, 100.0, 0), +(@PATH, 12, -801.808, -4908.93, 19.3913, 100.0, 0), +(@PATH, 13, -804.86, -4909.7, 19.3525, 100.0, 0), +(@PATH, 14, -808.699, -4913.92, 19.2707, 100.0, 0), +(@PATH, 15, -811.502, -4919.28, 19.3742, 100.0, 0), +(@PATH, 16, -815.664, -4923.35, 19.5169, 100.0, 0), +(@PATH, 17, -821.037, -4926.27, 19.7472, 100.0, 0), +(@PATH, 18, -824.913, -4930.46, 20.2496, 100.0, 0), +(@PATH, 19, -825.216, -4933.02, 20.4924, 100.0, 0), +(@PATH, 20, -822.131, -4938.15, 20.9481, 100.0, 0), +(@PATH, 21, -822.812, -4941.48, 21.2641, 100.0, 0), +(@PATH, 22, -828.34, -4939.55, 21.1166, 100.0, 0), +(@PATH, 23, -831.006, -4931.77, 20.6677, 100.0, 0), +(@PATH, 24, -833.433, -4930.48, 20.7289, 100.0, 0), +(@PATH, 25, -835.654, -4928.46, 20.7985, 100.0, 0), +(@PATH, 26, -839.542, -4923.88, 20.6797, 100.0, 0), +(@PATH, 27, -840.869, -4921.56, 20.6249, 100.0, 0), +(@PATH, 28, -842.204, -4918.86, 20.5327, 100.0, 0), +(@PATH, 29, -842.497, -4916.01, 20.4017, 100.0, 0), +(@PATH, 30, -840.453, -4910.24, 20.1169, 100.0, 0), +(@PATH, 31, -838.588, -4907.94, 19.9559, 100.0, 0), +(@PATH, 32, -833.656, -4904.45, 19.8107, 100.0, 0), +(@PATH, 33, -831.472, -4902.45, 19.8099, 100.0, 0), +(@PATH, 34, -829.256, -4897.08, 19.89, 100.0, 0), +(@PATH, 35, -828.472, -4894.54, 19.858, 100.0, 0); + + +/* Sen'jin Watcher - GUID 7318 */ + + +SET @NPC := 7318; +SET @PATH := @NPC * 10; + +DELETE FROM `creature_addon` WHERE `guid` = @NPC; +INSERT INTO `creature_addon` (`guid`, `path_id`) VALUES (@NPC, @PATH); +UPDATE `creature` SET `MovementType` = 2 WHERE `guid` = @NPC; + +DELETE FROM `waypoint_data` where `id` = @PATH; +INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `orientation`, `delay`) VALUES +(@PATH, 1, -751.532, -4937.42, 22.0626, 1.39087, 0), +(@PATH, 2, -749.446, -4925.95, 21.7179, 1.40658, 0), +(@PATH, 3, -748.146, -4909.12, 21.6451, 1.53224, 0), +(@PATH, 4, -749.044, -4894.65, 21.3131, 1.80792, 0), +(@PATH, 5, -758.065, -4886.38, 20.7674, 2.42367, 0), +(@PATH, 6, -769.284, -4881.33, 20.2048, 2.81558, 0), +(@PATH, 7, -786.327, -4873.79, 19.3151, 2.69777, 0), +(@PATH, 8, -800.025, -4868.83, 19.0121, 2.81558, 0), +(@PATH, 9, -814.01, -4868.4, 19.1711, 3.05199, 0), +(@PATH, 10, -830.176, -4867.12, 20.0416, 3.19336, 0), +(@PATH, 11, -840.925, -4866.71, 20.9414, 3.11796, 0), +(@PATH, 12, -852.233, -4866.44, 20.6684, 3.11796, 0), +(@PATH, 13, -862.73, -4866.2, 19.5395, 3.11796, 0), +(@PATH, 14, -877.267, -4867.57, 15.675, 3.35358, 0), +(@PATH, 15, -889.625, -4876.12, 11.69, 4.09814, 0), +(@PATH, 16, -892.882, -4882.87, 10.4069, 4.41387, 0), +(@PATH, 17, -894.161, -4891.19, 9.9882, 4.72724, 0), +(@PATH, 18, -891.952, -4904.18, 11.096, 5.00292, 0), +(@PATH, 19, -887.942, -4917.59, 13.5855, 5.00292, 0), +(@PATH, 20, -885.714, -4929.01, 15.4245, 4.84505, 0), +(@PATH, 21, -884.325, -4939.42, 16.5051, 4.84505, 0), +(@PATH, 22, -882.937, -4949.83, 17.3169, 4.84505, 0), +(@PATH, 23, -881.758, -4958.38, 17.6026, 5.00292, 0), +(@PATH, 24, -877.399, -4967.48, 17.6634, 5.3964, 0), +(@PATH, 25, -869.496, -4975.38, 16.6692, 5.55427, 0), +(@PATH, 26, -860.011, -4982.71, 14.9847, 5.67208, 0), +(@PATH, 27, -852.52, -4987.43, 14.0936, 5.78989, 0), +(@PATH, 28, -840.341, -4990.7, 14.844, 6.18102, 0), +(@PATH, 29, -830.497, -4989.98, 15.4556, 0.13345, 0), +(@PATH, 30, -819.594, -4986.79, 16.2936, 0.369069, 0), +(@PATH, 31, -809.257, -4982.2, 17.4642, 0.446824, 0), +(@PATH, 32, -793.258, -4973.57, 18.1898, 0.486879, 0), +(@PATH, 33, -775.559, -4963.22, 20.2241, 0.564633, 0), +(@PATH, 34, -763.732, -4955.73, 21.347, 0.564633, 0), +(@PATH, 35, -757.087, -4948.8, 21.8513, 0.878007, 0), +(@PATH, 36, -750.98, -4940.85, 22.1672, 0.995817, 0); + + +/* Sen'jin Watcher - GUID 7324 */ + + +SET @NPC := 7324; +SET @PATH := @NPC * 10; + +UPDATE `creature` SET `position_x` = -772.175, `position_y` = -4941.56, `position_z` = 36.863, `orientation` = 2.03416 WHERE `guid` = @NPC; + +DELETE FROM `creature_addon` WHERE `guid` = @NPC; +INSERT INTO `creature_addon` (`guid`, `path_id`) VALUES (@NPC, @PATH); +UPDATE `creature` SET `MovementType` = 2 WHERE `guid` = @NPC; + +DELETE FROM `waypoint_data` where `id` = @PATH; +INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `orientation`, `delay`) VALUES +(@PATH, 1, -772.175, -4941.56, 36.863, 100.0, 0), +(@PATH, 2, -774.724, -4940.84, 38.2501, 100.0, 0), +(@PATH, 3, -777.686, -4940.8, 38.2811, 100.0, 0), +(@PATH, 4, -779.612, -4942.97, 38.2811, 100.0, 0), +(@PATH, 5, -781.083, -4945.55, 38.2811, 100.0, 0), +(@PATH, 6, -786.085, -4947.83, 38.2811, 100.0, 0), +(@PATH, 7, -788.325, -4946.54, 38.2811, 100.0, 0), +(@PATH, 8, -789.578, -4943.82, 38.2811, 100.0, 0), +(@PATH, 9, -789.76, -4940.87, 38.2811, 100.0, 0), +(@PATH, 10, -784.81, -4937.9, 38.2811, 100.0, 0), +(@PATH, 11, -779.324, -4939.52, 38.2811, 100.0, 0), +(@PATH, 12, -776.578, -4940.72, 38.2811, 100.0, 0), +(@PATH, 13, -768.679, -4942.92, 34.9, 100.0, 0), +(@PATH, 14, -766.035, -4944.11, 33.9918, 100.0, 0), +(@PATH, 15, -763.665, -4945.41, 32.7905, 100.0, 0), +(@PATH, 16, -762.145, -4947.73, 31.7292, 100.0, 0), +(@PATH, 17, -762.604, -4953.17, 29.8729, 100.0, 0), +(@PATH, 18, -764.436, -4955.34, 29.2952, 100.0, 0), +(@PATH, 19, -767.039, -4956.27, 28.2648, 100.0, 0), +(@PATH, 20, -772.457, -4955.5, 26.0306, 100.0, 0), +(@PATH, 21, -779.579, -4952.01, 22.2463, 100.0, 0), +(@PATH, 22, -782.32, -4950.71, 22.2463, 100.0, 0), +(@PATH, 23, -786.267, -4947.33, 22.2463, 100.0, 0), +(@PATH, 24, -786.019, -4944.63, 22.2463, 100.0, 0), +(@PATH, 25, -781.034, -4943.89, 22.2463, 100.0, 0), +(@PATH, 26, -778.747, -4948.8, 22.2463, 100.0, 0), +(@PATH, 27, -777.972, -4951.7, 22.2463, 100.0, 0), +(@PATH, 28, -771.84, -4955.62, 26.2679, 100.0, 0), +(@PATH, 29, -769.283, -4956.47, 27.5535, 100.0, 0), +(@PATH, 30, -766.381, -4956.36, 28.4894, 100.0, 0), +(@PATH, 31, -763.87, -4955.03, 29.4397, 100.0, 0), +(@PATH, 32, -762.094, -4952.75, 30.1289, 100.0, 0), +(@PATH, 33, -761.814, -4947.37, 31.8481, 100.0, 0), +(@PATH, 34, -763.198, -4945.0, 32.8622, 100.0, 0), +(@PATH, 35, -768.301, -4942.61, 34.8163, 100.0, 0); + +/* Den Grunt - GUID 7656 */ + + +SET @NPC := 7656; +SET @PATH := @NPC * 10; + +UPDATE `creature` SET `position_x` = -600.043, `position_y` = -4342.45, `position_z` = 37.8159, `orientation` = 1.11138 WHERE `guid` = @NPC; + +UPDATE `creature_addon` set `path_id` = @PATH WHERE `guid` = @NPC; +UPDATE `creature` SET `MovementType` = 2 WHERE `guid` = @NPC; + +DELETE FROM `waypoint_data` where `id` = @PATH; +INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `orientation`, `delay`) VALUES +(@PATH, 1, -600.043, -4342.45, 37.8159, 100.0, 0), +(@PATH, 2, -599.399, -4324.38, 37.5988, 100.0, 0), +(@PATH, 3, -599.657, -4312.29, 37.5986, 100.0, 0), +(@PATH, 4, -599.869, -4298.37, 37.811, 100.0, 0), +(@PATH, 5, -599.768, -4307.47, 37.5992, 100.0, 0), +(@PATH, 6, -599.445, -4319.6, 37.5986, 100.0, 0), +(@PATH, 7, -599.705, -4334.79, 37.5988, 100.0, 0), +(@PATH, 8, -600.446, -4349.94, 38.131, 100.0, 0), +(@PATH, 9, -600.588, -4362.75, 38.8676, 100.0, 0), +(@PATH, 10, -601.845, -4378.2, 39.9664, 100.0, 0), +(@PATH, 11, -601.612, -4395.27, 42.6652, 100.0, 0), +(@PATH, 12, -600.024, -4410.47, 43.5231, 100.0, 0), +(@PATH, 13, -594.057, -4427.35, 42.4307, 100.0, 0), +(@PATH, 14, -579.457, -4457.44, 41.9763, 100.0, 0), +(@PATH, 15, -573.993, -4468.27, 42.2239, 100.0, 0), +(@PATH, 16, -570.217, -4476.48, 42.5183, 100.0, 0), +(@PATH, 17, -569.013, -4485.33, 42.566, 100.0, 0), +(@PATH, 18, -570.17, -4497.38, 42.5664, 100.0, 0), +(@PATH, 19, -578.906, -4511.47, 42.5098, 100.0, 0), +(@PATH, 20, -581.195, -4514.85, 42.4688, 100.0, 0), +(@PATH, 21, -572.172, -4501.6, 42.5659, 100.0, 0), +(@PATH, 22, -569.257, -4490.21, 42.5659, 100.0, 0), +(@PATH, 23, -569.142, -4481.09, 42.566, 100.0, 0), +(@PATH, 24, -571.964, -4472.59, 42.4032, 100.0, 0), +(@PATH, 25, -578.171, -4460.08, 41.9867, 100.0, 0), +(@PATH, 26, -583.786, -4448.55, 41.618, 100.0, 0), +(@PATH, 27, -589.919, -4434.83, 42.0238, 100.0, 0), +(@PATH, 28, -597.115, -4418.48, 43.1092, 100.0, 0), +(@PATH, 29, -600.253, -4403.03, 43.6641, 100.0, 0), +(@PATH, 30, -601.071, -4387.19, 41.4481, 100.0, 0), +(@PATH, 31, -600.667, -4370.0, 39.3044, 100.0, 0), +(@PATH, 32, -600.132, -4356.39, 38.4777, 100.0, 0); + +/* Clattering Scorpid - GUID 7953 */ + + +SET @NPC := 7953; +SET @PATH := @NPC * 10; + +DELETE FROM `creature_addon` WHERE `guid` = @NPC; +INSERT INTO `creature_addon` (`guid`, `path_id`) VALUES (@NPC, @PATH); +UPDATE `creature` SET `MovementType` = 2 WHERE `guid` = @NPC; + +DELETE FROM `waypoint_data` where `id` = @PATH; +INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `orientation`, `delay`) VALUES +(@PATH, 1, -103.086, -4657.6, 33.6479, 100.0, 0), +(@PATH, 2, -85.3881, -4677.97, 32.5394, 100.0, 0), +(@PATH, 3, -81.7362, -4701.13, 30.2284, 100.0, 0), +(@PATH, 4, -70.1425, -4695.94, 30.9405, 100.0, 0), +(@PATH, 5, -59.5394, -4681.0, 33.771, 100.0, 0), +(@PATH, 6, -54.5816, -4677.98, 35.3588, 100.0, 0), +(@PATH, 7, -49.7002, -4676.23, 38.9528, 100.0, 0), +(@PATH, 8, -46.3046, -4673.13, 41.046, 100.0, 0), +(@PATH, 9, -44.1007, -4670.26, 41.0807, 100.0, 0), +(@PATH, 10, -44.0761, -4665.47, 38.7072, 100.0, 0), +(@PATH, 11, -44.3984, -4659.13, 35.8799, 100.0, 0), +(@PATH, 12, -40.1175, -4644.03, 36.3342, 100.0, 0), +(@PATH, 13, -34.7326, -4631.52, 40.2554, 100.0, 0), +(@PATH, 14, -33.4486, -4622.9, 43.117, 100.0, 0), +(@PATH, 15, -45.7339, -4611.2, 44.6652, 100.0, 0), +(@PATH, 16, -59.8055, -4613.19, 43.9173, 100.0, 0), +(@PATH, 17, -72.1956, -4616.84, 41.993, 100.0, 0), +(@PATH, 18, -82.2069, -4628.65, 38.7271, 100.0, 0), +(@PATH, 19, -89.89, -4632.09, 38.1229, 100.0, 0), +(@PATH, 20, -103.297, -4625.97, 39.8145, 100.0, 0), +(@PATH, 21, -112.51, -4623.24, 41.5492, 100.0, 0), +(@PATH, 22, -116.701, -4640.65, 36.011, 100.0, 0), +(@PATH, 23, -116.177, -4648.41, 34.4998, 100.0, 0); + +/* Dire Mottled Boar - GUID 8539 */ + + +SET @NPC := 8539; +SET @PATH := @NPC * 10; + +DELETE FROM `creature_addon` WHERE `guid` = @NPC; +INSERT INTO `creature_addon` (`guid`, `path_id`) VALUES (@NPC, @PATH); +UPDATE `creature` SET `MovementType` = 2 WHERE `guid` = @NPC; + +DELETE FROM `waypoint_data` where `id` = @PATH; +INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `orientation`, `delay`) VALUES +(@PATH, 1, -214.372, -4845.64, 29.1291, 100.0, 0), +(@PATH, 2, -225.02, -4850.37, 30.6568, 100.0, 0), +(@PATH, 3, -235.224, -4854.72, 31.7916, 100.0, 0), +(@PATH, 4, -247.126, -4856.09, 31.6676, 100.0, 0), +(@PATH, 5, -256.584, -4848.05, 31.4637, 100.0, 0), +(@PATH, 6, -269.014, -4841.03, 32.0333, 100.0, 0), +(@PATH, 7, -289.34, -4837.1, 34.9092, 100.0, 0), +(@PATH, 8, -310.287, -4836.23, 39.2223, 100.0, 0), +(@PATH, 9, -320.813, -4838.24, 39.9581, 100.0, 0), +(@PATH, 10, -330.673, -4844.51, 40.5147, 100.0, 0), +(@PATH, 11, -333.401, -4850.53, 40.7722, 100.0, 0), +(@PATH, 12, -328.735, -4858.96, 40.7124, 100.0, 0), +(@PATH, 13, -321.563, -4868.14, 40.2101, 100.0, 0), +(@PATH, 14, -317.509, -4873.85, 39.4117, 100.0, 0), +(@PATH, 15, -306.572, -4879.36, 36.7733, 100.0, 0), +(@PATH, 16, -292.646, -4884.23, 33.3096, 100.0, 0), +(@PATH, 17, -280.699, -4884.3, 31.3057, 100.0, 0), +(@PATH, 18, -270.147, -4887.51, 29.426, 100.0, 0), +(@PATH, 19, -265.117, -4889.67, 28.3422, 100.0, 0), +(@PATH, 20, -252.422, -4898.02, 27.9178, 100.0, 0), +(@PATH, 21, -246.598, -4899.89, 27.4249, 100.0, 0), +(@PATH, 22, -239.562, -4898.45, 29.0681, 100.0, 0), +(@PATH, 23, -234.568, -4895.74, 29.3167, 100.0, 0), +(@PATH, 24, -226.236, -4890.71, 29.3149, 100.0, 0), +(@PATH, 25, -217.424, -4884.85, 29.7653, 100.0, 0), +(@PATH, 26, -211.227, -4871.29, 29.6777, 100.0, 0), +(@PATH, 27, -210.178, -4858.07, 29.221, 100.0, 0); + +/* Clattering Scorpid - GUID 10474 */ + + +SET @NPC := 10474; +SET @PATH := @NPC * 10; + +DELETE FROM `creature_addon` WHERE `guid` = @NPC; +INSERT INTO `creature_addon` (`guid`, `path_id`) VALUES (@NPC, @PATH); +UPDATE `creature` SET `MovementType` = 2 WHERE `guid` = @NPC; + +DELETE FROM `waypoint_data` where `id` = @PATH; +INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `orientation`, `delay`) VALUES +(@PATH, 1, -406.087, -4716.63, 44.8804, 100.0, 0), +(@PATH, 2, -408.276, -4708.65, 45.1308, 100.0, 0), +(@PATH, 3, -409.576, -4703.31, 40.2804, 100.0, 0), +(@PATH, 4, -412.923, -4691.66, 39.5794, 100.0, 0), +(@PATH, 5, -419.728, -4679.76, 38.7276, 100.0, 0), +(@PATH, 6, -428.741, -4672.17, 37.967, 100.0, 0), +(@PATH, 7, -439.755, -4664.31, 40.0006, 100.0, 0), +(@PATH, 8, -456.36, -4658.33, 40.9741, 100.0, 0), +(@PATH, 9, -460.767, -4666.47, 39.0189, 100.0, 0), +(@PATH, 10, -467.21, -4674.15, 36.7182, 100.0, 0), +(@PATH, 11, -478.211, -4682.6, 38.8073, 100.0, 0), +(@PATH, 12, -489.172, -4689.26, 36.6404, 100.0, 0), +(@PATH, 13, -494.44, -4693.17, 36.7468, 100.0, 0), +(@PATH, 14, -482.252, -4697.46, 36.8586, 100.0, 0), +(@PATH, 15, -470.356, -4697.13, 38.0726, 100.0, 0), +(@PATH, 16, -455.515, -4698.51, 38.4622, 100.0, 0), +(@PATH, 17, -444.913, -4710.9, 37.4488, 100.0, 0), +(@PATH, 18, -433.46, -4722.15, 38.8961, 100.0, 0), +(@PATH, 19, -424.593, -4731.05, 40.0664, 100.0, 0), +(@PATH, 20, -415.99, -4737.86, 40.2052, 100.0, 0), +(@PATH, 21, -409.609, -4729.68, 41.9805, 100.0, 0), +(@PATH, 22, -406.009, -4721.75, 41.9123, 100.0, 0); + + +/* Vile Familiar - GUID 12169 */ + + +SET @NPC := 12169; +SET @PATH := @NPC * 10; + +UPDATE `creature` SET `position_x` = -107.068, `position_y` = -4306.76, `position_z` = 62.6159, `orientation` = 6.04921 WHERE `guid` = @NPC; + +DELETE FROM `creature_addon` WHERE `guid` = @NPC; +INSERT INTO `creature_addon` (`guid`, `path_id`) VALUES (@NPC, @PATH); +UPDATE `creature` SET `MovementType` = 2 WHERE `guid` = @NPC; + +DELETE FROM `waypoint_data` where `id` = @PATH; +INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `orientation`, `delay`) VALUES +(@PATH, 1, -107.068, -4306.76, 62.6159, 100.0, 0), +(@PATH, 2, -124.8, -4318.37, 66.0147, 100.0, 0), +(@PATH, 3, -139.239, -4303.63, 66.1942, 100.0, 0), +(@PATH, 4, -143.22, -4283.83, 64.4553, 100.0, 0), +(@PATH, 5, -129.423, -4280.46, 64.745, 100.0, 0), +(@PATH, 6, -109.47, -4285.22, 63.7303, 100.0, 0), +(@PATH, 7, -94.2235, -4292.27, 60.9362, 100.0, 0); + +/* Clattering Scorpid - GUID 12264 */ + + +SET @NPC := 12264; +SET @PATH := @NPC * 10; + +UPDATE `creature` SET `position_x` = -121.162, `position_y` = -4709.15, `position_z` = 27.93, `orientation` = 0.263307 WHERE `guid` = @NPC; + +DELETE FROM `creature_addon` WHERE `guid` = @NPC; +INSERT INTO `creature_addon` (`guid`, `path_id`) VALUES (@NPC, @PATH); +UPDATE `creature` SET `MovementType` = 2 WHERE `guid` = @NPC; + +DELETE FROM `waypoint_data` where `id` = @PATH; +INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `orientation`, `delay`) VALUES +(@PATH, 1, -121.162, -4709.15, 27.93, 100.0, 0), +(@PATH, 2, -103.324, -4704.22, 28.4752, 100.0, 0), +(@PATH, 3, -91.8912, -4693.48, 30.4882, 100.0, 0), +(@PATH, 4, -98.0826, -4668.58, 32.5437, 100.0, 0), +(@PATH, 5, -108.558, -4659.12, 33.0813, 100.0, 0), +(@PATH, 6, -123.121, -4652.93, 33.8118, 100.0, 0), +(@PATH, 7, -137.574, -4653.24, 35.3335, 100.0, 0), +(@PATH, 8, -152.153, -4651.58, 37.4562, 100.0, 0), +(@PATH, 9, -167.803, -4649.81, 37.7494, 100.0, 0), +(@PATH, 10, -186.079, -4647.93, 38.5911, 100.0, 0), +(@PATH, 11, -188.795, -4657.63, 36.2397, 100.0, 0), +(@PATH, 12, -189.618, -4669.97, 33.4692, 100.0, 0), +(@PATH, 13, -198.707, -4679.42, 33.1351, 100.0, 0), +(@PATH, 14, -209.977, -4691.24, 32.6171, 100.0, 0), +(@PATH, 15, -217.987, -4698.61, 31.033, 100.0, 0), +(@PATH, 16, -221.252, -4706.95, 29.1452, 100.0, 0), +(@PATH, 17, -226.853, -4716.18, 29.2998, 100.0, 0), +(@PATH, 18, -228.244, -4721.6, 29.3076, 100.0, 0), +(@PATH, 19, -222.968, -4725.64, 29.6394, 100.0, 0), +(@PATH, 20, -217.048, -4728.59, 31.5374, 100.0, 0), +(@PATH, 21, -209.686, -4728.02, 32.0704, 100.0, 0), +(@PATH, 22, -196.465, -4727.24, 32.0757, 100.0, 0), +(@PATH, 23, -178.542, -4717.88, 31.7107, 100.0, 0), +(@PATH, 24, -175.455, -4698.0, 32.316, 100.0, 0), +(@PATH, 25, -153.919, -4700.8, 30.4153, 100.0, 0), +(@PATH, 26, -141.606, -4706.08, 28.791, 100.0, 0), +(@PATH, 27, -132.901, -4712.47, 27.927, 100.0, 0); + +/* Razormane Scout - GUID 12307 */ + + +SET @NPC := 12307; +SET @PATH := @NPC * 10; + +UPDATE `creature` SET `position_x` = 69.2959, `position_y` = -4609.61, `position_z` = 48.2853, `orientation` = 0.64357 WHERE `guid` = @NPC; + +DELETE FROM `creature_addon` WHERE `guid` = @NPC; +INSERT INTO `creature_addon` (`guid`, `path_id`) VALUES (@NPC, @PATH); +UPDATE `creature` SET `MovementType` = 2 WHERE `guid` = @NPC; + +DELETE FROM `waypoint_data` where `id` = @PATH; +INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `orientation`, `delay`) VALUES +(@PATH, 1, 69.2959, -4609.61, 48.2853, 100.0, 10000), +(@PATH, 2, 72.8356, -4591.06, 55.2529, 100.0, 0), +(@PATH, 3, 76.6362, -4578.17, 56.5297, 100.0, 0), +(@PATH, 4, 84.8748, -4572.65, 56.1986, 100.0, 0), +(@PATH, 5, 93.5395, -4567.38, 55.1739, 100.0, 0), +(@PATH, 6, 95.7022, -4560.2, 54.7452, 100.0, 0), +(@PATH, 7, 90.0297, -4556.16, 54.7916, 100.0, 0), +(@PATH, 8, 84.1164, -4557.37, 54.8289, 100.0, 0), +(@PATH, 9, 79.8056, -4559.84, 54.9896, 100.0, 0), +(@PATH, 10, 74.5471, -4569.52, 55.9016, 100.0, 0), +(@PATH, 11, 75.6316, -4575.49, 56.3877, 100.0, 0), +(@PATH, 12, 81.4626, -4576.27, 56.6136, 100.0, 0), +(@PATH, 13, 84.9299, -4571.12, 55.8428, 100.0, 0), +(@PATH, 14, 84.1083, -4562.97, 54.7466, 100.0, 0), +(@PATH, 15, 82.6289, -4555.58, 55.1128, 100.0, 0), +(@PATH, 16, 83.1458, -4551.12, 55.8152, 100.0, 0), +(@PATH, 17, 88.5177, -4548.67, 56.596, 100.0, 20000), +(@PATH, 18, 85.0209, -4556.79, 54.8304, 100.0, 0), +(@PATH, 19, 81.9841, -4566.79, 55.1042, 100.0, 0), +(@PATH, 20, 78.8213, -4577.88, 56.6008, 100.0, 0), +(@PATH, 21, 75.8794, -4588.68, 56.083, 100.0, 0), +(@PATH, 22, 72.7215, -4599.41, 52.3967, 100.0, 0); + +/* Dire Mottled Boar - GUID 12312 */ + + +SET @NPC := 12312; +SET @PATH := @NPC * 10; + +UPDATE `creature` SET `position_x` = -61.8657, `position_y` = -4828.86, `position_z` = 22.6982, `orientation` = 1.96017 WHERE `guid` = @NPC; + +DELETE FROM `creature_addon` WHERE `guid` = @NPC; +INSERT INTO `creature_addon` (`guid`, `path_id`) VALUES (@NPC, @PATH); +UPDATE `creature` SET `MovementType` = 2 WHERE `guid` = @NPC; + +DELETE FROM `waypoint_data` where `id` = @PATH; +INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `orientation`, `delay`) VALUES +(@PATH, 1, -61.8657, -4828.86, 22.6982, 100.0, 0), +(@PATH, 2, -74.1842, -4823.68, 23.4622, 100.0, 0), +(@PATH, 3, -83.4586, -4827.15, 23.5508, 100.0, 0), +(@PATH, 4, -91.9781, -4833.29, 23.7535, 100.0, 0), +(@PATH, 5, -103.712, -4841.91, 22.8193, 100.0, 0), +(@PATH, 6, -114.994, -4850.2, 21.4633, 100.0, 0), +(@PATH, 7, -126.212, -4858.57, 20.7062, 100.0, 0), +(@PATH, 8, -130.104, -4870.51, 20.677, 100.0, 0), +(@PATH, 9, -127.47, -4878.73, 21.0682, 100.0, 0), +(@PATH, 10, -118.877, -4883.74, 21.1563, 100.0, 0), +(@PATH, 11, -107.751, -4884.02, 20.3514, 100.0, 0), +(@PATH, 12, -99.2225, -4885.73, 18.9527, 100.0, 0), +(@PATH, 13, -83.4712, -4889.91, 17.615, 100.0, 0), +(@PATH, 14, -76.0254, -4891.22, 17.5674, 100.0, 0), +(@PATH, 15, -68.0709, -4887.69, 17.682, 100.0, 0), +(@PATH, 16, -60.9011, -4879.28, 18.6881, 100.0, 0), +(@PATH, 17, -58.3497, -4872.06, 20.4372, 100.0, 0), +(@PATH, 18, -55.5972, -4863.78, 20.8662, 100.0, 0), +(@PATH, 19, -54.8455, -4852.25, 21.3061, 100.0, 0), +(@PATH, 20, -56.5215, -4843.12, 22.1018, 100.0, 0); + + +/* Razormane Scout - GUID 12316 */ + + +SET @NPC := 12316; +SET @PATH := @NPC * 10; + +DELETE FROM `creature_addon` WHERE `guid` = @NPC; +INSERT INTO `creature_addon` (`guid`, `path_id`) VALUES (@NPC, @PATH); +UPDATE `creature` SET `MovementType` = 2 WHERE `guid` = @NPC; + +DELETE FROM `waypoint_data` where `id` = @PATH; +INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `orientation`, `delay`) VALUES +(@PATH, 1, 124.53, -4582.72, 63.7189, 100.0, 0), +(@PATH, 2, 133.618, -4582.61, 63.8564, 100.0, 0), +(@PATH, 3, 138.082, -4583.02, 62.9627, 100.0, 0), +(@PATH, 4, 141.923, -4585.0, 65.7188, 100.0, 0), +(@PATH, 5, 145.08, -4587.58, 64.9695, 100.0, 20000), +(@PATH, 6, 141.282, -4584.24, 65.4642, 100.0, 0), +(@PATH, 7, 137.239, -4583.36, 62.5436, 100.0, 0), +(@PATH, 8, 134.007, -4582.37, 63.8799, 100.0, 0), +(@PATH, 9, 123.97, -4582.68, 63.7515, 100.0, 0), +(@PATH, 10, 117.123, -4580.07, 62.112, 100.0, 0), +(@PATH, 11, 110.209, -4572.99, 57.9044, 100.0, 0), +(@PATH, 12, 102.608, -4566.32, 55.3204, 100.0, 20000), +(@PATH, 13, 110.348, -4573.89, 58.1059, 100.0, 0), +(@PATH, 14, 116.007, -4578.7, 61.2531, 100.0, 0), +(@PATH, 15, 121.21, -4582.27, 63.9267, 100.0, 0); + +/* Dire Mottled Boar - GUID 12943 */ + + +SET @NPC := 12943; +SET @PATH := @NPC * 10; + +UPDATE `creature` SET `position_x` = -200.386, `position_y` = -4883.89, `position_z` = 27.1407, `orientation` = 3.59203 WHERE `guid` = @NPC; + +DELETE FROM `creature_addon` WHERE `guid` = @NPC; +INSERT INTO `creature_addon` (`guid`, `path_id`) VALUES (@NPC, @PATH); +UPDATE `creature` SET `MovementType` = 2 WHERE `guid` = @NPC; + +DELETE FROM `waypoint_data` where `id` = @PATH; +INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `orientation`, `delay`) VALUES +(@PATH, 1, -200.386, -4883.89, 27.1407, 100.0, 0), +(@PATH, 2, -193.105, -4896.78, 25.5057, 100.0, 0), +(@PATH, 3, -187.962, -4899.92, 23.7865, 100.0, 0), +(@PATH, 4, -182.618, -4903.26, 19.2486, 100.0, 0), +(@PATH, 5, -170.129, -4906.9, 19.2486, 100.0, 0), +(@PATH, 6, -156.713, -4894.43, 19.5028, 100.0, 0), +(@PATH, 7, -146.434, -4884.93, 20.0447, 100.0, 0), +(@PATH, 8, -126.3, -4870.36, 21.0744, 100.0, 0), +(@PATH, 9, -129.568, -4853.1, 20.1477, 100.0, 0), +(@PATH, 10, -117.071, -4842.32, 21.1624, 100.0, 0), +(@PATH, 11, -103.254, -4835.31, 23.3766, 100.0, 0), +(@PATH, 12, -100.011, -4829.95, 23.8422, 100.0, 0), +(@PATH, 13, -105.703, -4815.96, 24.8568, 100.0, 0), +(@PATH, 14, -111.89, -4808.07, 25.1118, 100.0, 0), +(@PATH, 15, -123.375, -4813.62, 24.5666, 100.0, 0), +(@PATH, 16, -146.001, -4825.22, 23.1651, 100.0, 0), +(@PATH, 17, -153.565, -4838.05, 21.2692, 100.0, 0), +(@PATH, 18, -168.864, -4845.25, 20.7892, 100.0, 0), +(@PATH, 19, -182.876, -4852.28, 22.8461, 100.0, 0), +(@PATH, 20, -192.274, -4840.5, 25.7954, 100.0, 0), +(@PATH, 21, -196.924, -4835.91, 26.8833, 100.0, 0), +(@PATH, 22, -201.854, -4832.7, 24.8223, 100.0, 0), +(@PATH, 23, -209.203, -4836.12, 24.9899, 100.0, 0), +(@PATH, 24, -214.462, -4839.38, 27.5361, 100.0, 0), +(@PATH, 25, -223.442, -4846.79, 29.9977, 100.0, 0), +(@PATH, 26, -226.932, -4855.15, 31.4781, 100.0, 0), +(@PATH, 27, -218.524, -4863.81, 30.614, 100.0, 0), +(@PATH, 28, -206.247, -4873.63, 28.7488, 100.0, 0); + +/* Kul Tiras Marine - GUID 12998 */ + + +SET @NPC := 12998; +SET @PATH := @NPC * 10; + +UPDATE `creature` SET `position_x` = -230.719, `position_y` = -5125.15, `position_z` = 42.4774, `orientation` = 4.53786 WHERE `guid` = @NPC; + +DELETE FROM `creature_addon` WHERE `guid` = @NPC; +INSERT INTO `creature_addon` (`guid`, `path_id`) VALUES (@NPC, @PATH); +UPDATE `creature` SET `MovementType` = 2 WHERE `guid` = @NPC; + +DELETE FROM `waypoint_data` where `id` = @PATH; +INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `orientation`, `delay`) VALUES +(@PATH, 1, -230.719, -5125.15, 42.4774, 100.0, 0), +(@PATH, 2, -230.686, -5131.19, 45.7119, 100.0, 0), +(@PATH, 3, -229.064, -5132.69, 45.8029, 100.0, 0), +(@PATH, 4, -222.909, -5132.9, 49.2699, 100.0, 0), +(@PATH, 5, -221.358, -5132.17, 49.2699, 100.0, 0), +(@PATH, 6, -221.043, -5127.19, 49.2699, 100.0, 0), +(@PATH, 7, -224.449, -5124.92, 49.2699, 100.0, 0), +(@PATH, 8, -225.147, -5115.53, 49.3237, 100.0, 0), +(@PATH, 9, -224.832, -5124.48, 49.2703, 100.0, 0), +(@PATH, 10, -220.976, -5127.14, 49.2703, 100.0, 0), +(@PATH, 11, -221.009, -5131.62, 49.2703, 100.0, 0), +(@PATH, 12, -223.324, -5132.8, 49.2703, 100.0, 0), +(@PATH, 13, -229.317, -5132.73, 45.712, 100.0, 0), +(@PATH, 14, -230.802, -5130.94, 45.712, 100.0, 0), +(@PATH, 15, -230.745, -5125.24, 42.477, 100.0, 0), +(@PATH, 16, -229.071, -5123.85, 42.477, 100.0, 0), +(@PATH, 17, -221.9, -5124.38, 38.2719, 100.0, 0), +(@PATH, 18, -220.41, -5126.12, 38.2719, 100.0, 0), +(@PATH, 19, -220.741, -5128.71, 38.2719, 100.0, 0), +(@PATH, 20, -224.215, -5129.94, 38.2719, 100.0, 0), +(@PATH, 21, -231.927, -5129.92, 34.0668, 100.0, 0), +(@PATH, 22, -233.333, -5128.56, 34.0668, 100.0, 0), +(@PATH, 23, -232.741, -5126.2, 34.0668, 100.0, 0), +(@PATH, 24, -229.79, -5125.62, 34.0668, 100.0, 0), +(@PATH, 25, -228.711, -5122.72, 34.0653, 100.0, 0), +(@PATH, 26, -228.582, -5108.82, 34.0653, 100.0, 0), +(@PATH, 27, -228.8, -5098.57, 41.3473, 100.0, 0), +(@PATH, 28, -231.072, -5095.27, 41.3473, 100.0, 0), +(@PATH, 29, -235.625, -5093.99, 41.3473, 100.0, 0), +(@PATH, 30, -252.0, -5094.0, 41.3473, 100.0, 0), +(@PATH, 31, -232.244, -5094.07, 41.3473, 100.0, 0), +(@PATH, 32, -228.875, -5098.53, 41.3473, 100.0, 0), +(@PATH, 33, -228.729, -5108.67, 34.0658, 100.0, 0), +(@PATH, 34, -229.067, -5111.95, 34.0658, 100.0, 0), +(@PATH, 35, -234.399, -5112.87, 34.0658, 100.0, 0), +(@PATH, 36, -252.847, -5113.07, 34.0658, 100.0, 0), +(@PATH, 37, -231.446, -5112.98, 34.0658, 100.0, 0), +(@PATH, 38, -228.84, -5117.89, 34.0658, 100.0, 0), +(@PATH, 39, -228.85, -5124.55, 34.0658, 100.0, 0), +(@PATH, 40, -231.059, -5125.75, 34.0658, 100.0, 0), +(@PATH, 41, -233.287, -5126.61, 34.0658, 100.0, 0), +(@PATH, 42, -233.166, -5129.52, 34.0658, 100.0, 0), +(@PATH, 43, -231.672, -5129.95, 34.0669, 100.0, 0), +(@PATH, 44, -224.454, -5129.98, 38.2726, 100.0, 0), +(@PATH, 45, -221.865, -5129.24, 38.2726, 100.0, 0), +(@PATH, 46, -220.17, -5126.07, 38.2726, 100.0, 0), +(@PATH, 47, -221.888, -5124.38, 38.2719, 100.0, 0), +(@PATH, 48, -229.382, -5123.85, 42.4772, 100.0, 0); + +/* Clattering Scorpid - GUID 13002 */ + + +SET @NPC := 13002; +SET @PATH := @NPC * 10; + +UPDATE `creature` SET `position_x` = -327.766, `position_y` = -4760.08, `position_z` = 36.6491, `orientation` = 6.08023 WHERE `guid` = @NPC; + +DELETE FROM `creature_addon` WHERE `guid` = @NPC; +INSERT INTO `creature_addon` (`guid`, `path_id`) VALUES (@NPC, @PATH); +UPDATE `creature` SET `MovementType` = 2 WHERE `guid` = @NPC; + +DELETE FROM `waypoint_data` where `id` = @PATH; +INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `orientation`, `delay`) VALUES +(@PATH, 1, -327.766, -4760.08, 36.6491, 100.0, 0), +(@PATH, 2, -307.026, -4757.96, 36.3603, 100.0, 0), +(@PATH, 3, -286.811, -4756.11, 34.1922, 100.0, 0), +(@PATH, 4, -272.284, -4754.77, 34.1844, 100.0, 0), +(@PATH, 5, -265.5, -4753.05, 33.6913, 100.0, 0), +(@PATH, 6, -256.536, -4741.59, 32.2737, 100.0, 0), +(@PATH, 7, -256.426, -4725.89, 33.2756, 100.0, 0), +(@PATH, 8, -257.675, -4709.1, 34.2231, 100.0, 0), +(@PATH, 9, -260.288, -4699.09, 37.0144, 100.0, 0), +(@PATH, 10, -264.176, -4694.38, 38.3938, 100.0, 0), +(@PATH, 11, -269.589, -4690.96, 38.8834, 100.0, 0), +(@PATH, 12, -280.665, -4690.68, 39.2254, 100.0, 0), +(@PATH, 13, -291.292, -4693.17, 39.4739, 100.0, 0), +(@PATH, 14, -303.736, -4689.96, 41.9234, 100.0, 0), +(@PATH, 15, -311.884, -4690.42, 41.0454, 100.0, 0), +(@PATH, 16, -321.512, -4692.89, 40.3765, 100.0, 0), +(@PATH, 17, -337.345, -4696.95, 38.814, 100.0, 0), +(@PATH, 18, -347.369, -4707.03, 38.2411, 100.0, 0), +(@PATH, 19, -357.466, -4726.06, 38.4795, 100.0, 0), +(@PATH, 20, -361.583, -4734.52, 39.4971, 100.0, 0), +(@PATH, 21, -366.072, -4742.29, 38.7492, 100.0, 0), +(@PATH, 22, -369.61, -4747.54, 40.3396, 100.0, 0), +(@PATH, 23, -361.003, -4753.41, 37.5095, 100.0, 0), +(@PATH, 24, -345.576, -4759.72, 36.8648, 100.0, 0); + + + +/* Hexed Troll - GUID 13026 */ + + +SET @NPC := 13026; +SET @PATH := @NPC * 10; + +UPDATE `creature` SET `position_x` = -1138.31, `position_y` = -5597.88, `position_z` = 7.61002, `orientation` = 3.24477 WHERE `guid` = @NPC; + +DELETE FROM `creature_addon` WHERE `guid` = @NPC; +INSERT INTO `creature_addon` (`guid`, `path_id`) VALUES (@NPC, @PATH); +UPDATE `creature` SET `MovementType` = 2 WHERE `guid` = @NPC; + +DELETE FROM `waypoint_data` where `id` = @PATH; +INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `orientation`, `delay`) VALUES +(@PATH, 1, -1138.31, -5597.88, 7.61002, 100.0, 0), +(@PATH, 2, -1148.76, -5592.07, 8.36803, 100.0, 0), +(@PATH, 3, -1153.21, -5584.65, 8.89221, 100.0, 0), +(@PATH, 4, -1161.68, -5573.5, 8.47221, 100.0, 0), +(@PATH, 5, -1164.14, -5566.63, 8.27151, 100.0, 0), +(@PATH, 6, -1157.9, -5555.72, 7.68995, 100.0, 0), +(@PATH, 7, -1153.67, -5550.14, 7.69433, 100.0, 0), +(@PATH, 8, -1147.32, -5541.78, 7.18916, 100.0, 0), +(@PATH, 9, -1144.69, -5538.37, 7.33432, 100.0, 0), +(@PATH, 10, -1137.1, -5531.1, 6.45399, 100.0, 0), +(@PATH, 11, -1130.09, -5526.81, 7.79135, 100.0, 0), +(@PATH, 12, -1124.47, -5527.46, 8.42845, 100.0, 0), +(@PATH, 13, -1115.83, -5535.14, 8.6434, 100.0, 0), +(@PATH, 14, -1106.94, -5544.4, 7.6163, 100.0, 0), +(@PATH, 15, -1098.62, -5551.2, 9.11498, 100.0, 0), +(@PATH, 16, -1098.47, -5559.96, 8.45261, 100.0, 0), +(@PATH, 17, -1103.26, -5568.14, 7.54396, 100.0, 0), +(@PATH, 18, -1109.9, -5578.23, 7.82146, 100.0, 0), +(@PATH, 19, -1117.06, -5586.63, 8.32589, 100.0, 0), +(@PATH, 20, -1127.57, -5595.51, 7.71829, 100.0, 0); + + +/* Vile Familiar - GUID 13062 */ + + +SET @NPC := 13062; +SET @PATH := @NPC * 10; + +UPDATE `creature` SET `position_x` = -154.199, `position_y` = -4357.06, `position_z` = 66.8175, `orientation` = 3.49807 WHERE `guid` = @NPC; + +DELETE FROM `creature_addon` WHERE `guid` = @NPC; +INSERT INTO `creature_addon` (`guid`, `path_id`) VALUES (@NPC, @PATH); +UPDATE `creature` SET `MovementType` = 2 WHERE `guid` = @NPC; + +DELETE FROM `waypoint_data` where `id` = @PATH; +INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `orientation`, `delay`) VALUES +(@PATH, 1, -154.199, -4357.06, 66.8175, 100.0, 0), +(@PATH, 2, -139.779, -4370.04, 66.2358, 100.0, 0), +(@PATH, 3, -132.177, -4361.44, 67.0957, 100.0, 0), +(@PATH, 4, -129.829, -4346.96, 66.2549, 100.0, 0), +(@PATH, 5, -127.669, -4337.69, 64.1934, 100.0, 0), +(@PATH, 6, -113.978, -4332.43, 65.8378, 100.0, 0), +(@PATH, 7, -95.8724, -4329.41, 64.5048, 100.0, 0), +(@PATH, 8, -78.0683, -4330.18, 66.9585, 100.0, 0), +(@PATH, 9, -69.2985, -4337.84, 67.894, 100.0, 0), +(@PATH, 10, -53.1216, -4331.94, 68.3126, 100.0, 0), +(@PATH, 11, -69.2985, -4337.84, 67.894, 100.0, 0), +(@PATH, 12, -78.0683, -4330.18, 66.9585, 100.0, 0), +(@PATH, 13, -95.8724, -4329.41, 64.5048, 100.0, 0), +(@PATH, 14, -113.978, -4332.43, 65.8378, 100.0, 0), +(@PATH, 15, -127.627, -4337.51, 64.1911, 100.0, 0), +(@PATH, 16, -129.829, -4346.96, 66.2549, 100.0, 0), +(@PATH, 17, -132.177, -4361.44, 67.0957, 100.0, 0), +(@PATH, 18, -139.779, -4370.04, 66.2358, 100.0, 0), +(@PATH, 19, -154.199, -4357.06, 66.8175, 100.0, 0), +(@PATH, 20, -162.918, -4360.37, 67.2569, 100.0, 0); From 8106b7f3210a30317719943b92ab350dca523574 Mon Sep 17 00:00:00 2001 From: AzerothCoreBot Date: Tue, 26 Jul 2022 23:08:11 +0000 Subject: [PATCH 118/130] chore(DB): import pending files Referenced commit(s): 8f386e83de103d0e3f5229c0915468017dd13ff7 --- .../rev_1657730289541881400.sql => db_world/2022_07_26_05.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/rev_1657730289541881400.sql => db_world/2022_07_26_05.sql} (99%) diff --git a/data/sql/updates/pending_db_world/rev_1657730289541881400.sql b/data/sql/updates/db_world/2022_07_26_05.sql similarity index 99% rename from data/sql/updates/pending_db_world/rev_1657730289541881400.sql rename to data/sql/updates/db_world/2022_07_26_05.sql index de5504e54..efb011b83 100644 --- a/data/sql/updates/pending_db_world/rev_1657730289541881400.sql +++ b/data/sql/updates/db_world/2022_07_26_05.sql @@ -1,3 +1,4 @@ +-- DB update 2022_07_26_04 -> 2022_07_26_05 -- /* Vile Familiar - GUID 4701 */ From 9bfe8c5c136c510ad61a685bf089dafe60e3d623 Mon Sep 17 00:00:00 2001 From: schell244 Date: Wed, 27 Jul 2022 01:14:43 +0200 Subject: [PATCH 119/130] fix(DB/SAI): Shadowfang Keep: improve Arugal intro script (#12405) * fix(DB/texts): Shadowfang Keep: add broadcast texts for arugal intro event * new line * Improve Arugal intro script * Add more missing script parts * add missing source_type Co-authored-by: schell244 <> --- .../rev_1658003120465824400.sql | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 data/sql/updates/pending_db_world/rev_1658003120465824400.sql diff --git a/data/sql/updates/pending_db_world/rev_1658003120465824400.sql b/data/sql/updates/pending_db_world/rev_1658003120465824400.sql new file mode 100644 index 000000000..9e1fd5ddc --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1658003120465824400.sql @@ -0,0 +1,22 @@ +-- +UPDATE `creature_text` SET `BroadcastTextId` = 1456 WHERE `CreatureID` = 10000 AND `GroupID` = 0; +UPDATE `creature_text` SET `BroadcastTextId` = 5680 WHERE `CreatureID` = 10000 AND `GroupID` = 1; +UPDATE `creature_text` SET `BroadcastTextId` = 5681 WHERE `CreatureID` = 10000 AND `GroupID` = 2; +UPDATE `creature_text` SET `BroadcastTextId` = 5682 WHERE `CreatureID` = 10000 AND `GroupID` = 3; + +-- SFK: Arugal intro script +DELETE FROM `smart_scripts` WHERE `entryorguid` = 10000 AND `source_type`= 0; +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(10000,0,0,0,60,0,100,1,0,0,0,0,0,47,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,'Arugal - Set Invisible'), +(10000,0,1,0,60,0,100,1,5000,5000,0,0,0,47,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,'Arugal - Set Visible'), +(10000,0,2,0,60,0,100,1,5000,5000,0,0,0,11,7741,0,0,0,0,0,1,0,0,0,0,0,0,0,0,'Arugal - Cast spell teleport'), +(10000,0,3,0,60,0,100,1,7000,7000,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,'Arugal - Say text 0'), +(10000,0,4,0,60,0,100,1,7000,7000,0,0,0,5,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,'Arugal - Emote talk'), +(10000,0,5,0,60,0,100,1,10000,10000,0,0,0,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,'Arugal - Say text 1'), +(10000,0,6,0,60,0,100,1,10000,10000,0,0,0,5,25,0,0,0,0,0,1,0,0,0,0,0,0,0,0,'Arugal - Emote point'), +(10000,0,7,0,60,0,100,1,14000,14000,0,0,0,1,2,0,0,0,0,0,1,0,0,0,0,0,0,0,0,'Arugal - Say text 2'), +(10000,0,8,0,60,0,100,1,14000,14000,0,0,0,5,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,'Arugal - Emote talk'), +(10000,0,9,0,60,0,100,1,16000,16000,0,0,0,5,11,0,0,0,0,0,1,0,0,0,0,0,0,0,0,'Arugal - Emote laught'), +(10000,0,10,0,60,0,100,1,19000,19000,0,0,0,1,3,0,0,0,0,0,1,0,0,0,0,0,0,0,0,'Arugal - Say text 3'), +(10000,0,11,0,60,0,100,1,21000,21000,0,0,0,11,7741,0,0,0,0,0,1,0,0,0,0,0,0,0,0,'Arugal - Cast spell teleport'), +(10000,0,12,0,60,0,100,1,0,0,0,0,0,41,22000,0,0,0,0,0,1,0,0,0,0,0,0,0,0,'Arugal - Despawn'); From f53b19dfd3cb4258e3a396b2bac492771de7dc69 Mon Sep 17 00:00:00 2001 From: AzerothCoreBot Date: Tue, 26 Jul 2022 23:16:46 +0000 Subject: [PATCH 120/130] chore(DB): import pending files Referenced commit(s): 9bfe8c5c136c510ad61a685bf089dafe60e3d623 --- .../rev_1658003120465824400.sql => db_world/2022_07_26_06.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/rev_1658003120465824400.sql => db_world/2022_07_26_06.sql} (98%) diff --git a/data/sql/updates/pending_db_world/rev_1658003120465824400.sql b/data/sql/updates/db_world/2022_07_26_06.sql similarity index 98% rename from data/sql/updates/pending_db_world/rev_1658003120465824400.sql rename to data/sql/updates/db_world/2022_07_26_06.sql index 9e1fd5ddc..7462b205f 100644 --- a/data/sql/updates/pending_db_world/rev_1658003120465824400.sql +++ b/data/sql/updates/db_world/2022_07_26_06.sql @@ -1,3 +1,4 @@ +-- DB update 2022_07_26_05 -> 2022_07_26_06 -- UPDATE `creature_text` SET `BroadcastTextId` = 1456 WHERE `CreatureID` = 10000 AND `GroupID` = 0; UPDATE `creature_text` SET `BroadcastTextId` = 5680 WHERE `CreatureID` = 10000 AND `GroupID` = 1; From dcbf224392da9a4ce2df3c441b0b2d15b14a3d6f Mon Sep 17 00:00:00 2001 From: AnchyDev <35346484+AnchyDev@users.noreply.github.com> Date: Wed, 27 Jul 2022 01:08:41 +0100 Subject: [PATCH 121/130] feat(Core): Add OnGroupRollRewardItem hook. (#12538) Added OnGroupRollRewardItem hook. --- src/server/game/Groups/Group.cpp | 6 ++++-- src/server/game/Scripting/ScriptDefines/PlayerScript.cpp | 8 ++++++++ src/server/game/Scripting/ScriptMgr.h | 5 +++++ 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/server/game/Groups/Group.cpp b/src/server/game/Groups/Group.cpp index d93c476b3..ab72656b9 100644 --- a/src/server/game/Groups/Group.cpp +++ b/src/server/game/Groups/Group.cpp @@ -1448,7 +1448,8 @@ void Group::CountTheRoll(Rolls::iterator rollI, Map* allowedMap) roll->getLoot()->NotifyItemRemoved(roll->itemSlot); roll->getLoot()->unlootedCount--; AllowedLooterSet looters = item->GetAllowedLooters(); - player->StoreNewItem(dest, roll->itemid, true, item->randomPropertyId, looters); + Item* _item = player->StoreNewItem(dest, roll->itemid, true, item->randomPropertyId, looters); + sScriptMgr->OnGroupRollRewardItem(player, _item, _item->GetCount(), NEED, roll); player->UpdateLootAchievements(item, roll->getLoot()); } else @@ -1516,7 +1517,8 @@ void Group::CountTheRoll(Rolls::iterator rollI, Map* allowedMap) roll->getLoot()->NotifyItemRemoved(roll->itemSlot); roll->getLoot()->unlootedCount--; AllowedLooterSet looters = item->GetAllowedLooters(); - player->StoreNewItem(dest, roll->itemid, true, item->randomPropertyId, looters); + Item* _item = player->StoreNewItem(dest, roll->itemid, true, item->randomPropertyId, looters); + sScriptMgr->OnGroupRollRewardItem(player, _item, _item->GetCount(), GREED, roll); player->UpdateLootAchievements(item, roll->getLoot()); } else diff --git a/src/server/game/Scripting/ScriptDefines/PlayerScript.cpp b/src/server/game/Scripting/ScriptDefines/PlayerScript.cpp index 959fc2b35..a759e4047 100644 --- a/src/server/game/Scripting/ScriptDefines/PlayerScript.cpp +++ b/src/server/game/Scripting/ScriptDefines/PlayerScript.cpp @@ -590,6 +590,14 @@ void ScriptMgr::OnQuestRewardItem(Player* player, Item* item, uint32 count) }); } +void ScriptMgr::OnGroupRollRewardItem(Player* player, Item* item, uint32 count, RollVote voteType, Roll* roll) +{ + ExecuteScript([&](PlayerScript* script) + { + script->OnGroupRollRewardItem(player, item, count, voteType, roll); + }); +} + void ScriptMgr::OnFirstLogin(Player* player) { ExecuteScript([&](PlayerScript* script) diff --git a/src/server/game/Scripting/ScriptMgr.h b/src/server/game/Scripting/ScriptMgr.h index 66d2eeca1..2e17704f1 100644 --- a/src/server/game/Scripting/ScriptMgr.h +++ b/src/server/game/Scripting/ScriptMgr.h @@ -26,6 +26,7 @@ #include "DBCStores.h" #include "DynamicObject.h" #include "GameEventMgr.h" +#include "Group.h" #include "LFGMgr.h" #include "ObjectMgr.h" #include "PetDefines.h" @@ -1172,6 +1173,9 @@ public: // After receiving item as a quest reward virtual void OnQuestRewardItem(Player* /*player*/, Item* /*item*/, uint32 /*count*/) { } + // After receiving item as a group roll reward + virtual void OnGroupRollRewardItem(Player* /*player*/, Item* /*item*/, uint32 /*count*/, RollVote /*voteType*/, Roll* /*roll*/) { } + // After completed a quest [[nodiscard]] virtual bool OnBeforeQuestComplete(Player* /*player*/, uint32 /*quest_id*/) { return true; } @@ -2244,6 +2248,7 @@ public: /* PlayerScript */ void OnLootItem(Player* player, Item* item, uint32 count, ObjectGuid lootguid); void OnCreateItem(Player* player, Item* item, uint32 count); void OnQuestRewardItem(Player* player, Item* item, uint32 count); + void OnGroupRollRewardItem(Player* player, Item* item, uint32 count, RollVote voteType, Roll* roll); bool OnBeforePlayerQuestComplete(Player* player, uint32 quest_id); void OnQuestComputeXP(Player* player, Quest const* quest, uint32& xpValue); void OnBeforePlayerDurabilityRepair(Player* player, ObjectGuid npcGUID, ObjectGuid itemGUID, float& discountMod, uint8 guildBank); From ce487f2afdf28c66115c30b923a70dcc24e1cd8e Mon Sep 17 00:00:00 2001 From: Eddy Vega <61223313+Si1ker@users.noreply.github.com> Date: Tue, 26 Jul 2022 19:00:40 -0600 Subject: [PATCH 122/130] fix(DB/Update): Fix update 2022_07_26_04.sql (#12553) init Co-authored-by: Si1ker --- data/sql/updates/db_world/2022_07_26_04.sql | 1 + 1 file changed, 1 insertion(+) diff --git a/data/sql/updates/db_world/2022_07_26_04.sql b/data/sql/updates/db_world/2022_07_26_04.sql index b81a33be0..0e601cfc5 100644 --- a/data/sql/updates/db_world/2022_07_26_04.sql +++ b/data/sql/updates/db_world/2022_07_26_04.sql @@ -3,6 +3,7 @@ UPDATE `creature_template` SET `mingold`=0, `maxgold`=0 WHERE `entry`=15546; UPDATE `creature_template` SET `flags_extra`=`flags_extra`|256 WHERE `entry`=15369; +DELETE FROM `creature_addon` WHERE `guid`=144641; INSERT INTO `creature_addon` (`guid`, `auras`) VALUES (144641, '8876'); -- Triggers SPELL_THRASH = 3391 From 07c043552aa833bd101ffc0eb2ed71594fdea773 Mon Sep 17 00:00:00 2001 From: Nefertumm Date: Wed, 27 Jul 2022 00:41:20 -0300 Subject: [PATCH 123/130] fix(Scripts/RuinsOfAhnQiraj): Ossirian reset (#12548) --- .../sql/updates/pending_db_world/rev_1658857216982492500.sql | 2 ++ .../scripts/Kalimdor/RuinsOfAhnQiraj/boss_ossirian.cpp | 5 +++++ 2 files changed, 7 insertions(+) create mode 100644 data/sql/updates/pending_db_world/rev_1658857216982492500.sql diff --git a/data/sql/updates/pending_db_world/rev_1658857216982492500.sql b/data/sql/updates/pending_db_world/rev_1658857216982492500.sql new file mode 100644 index 000000000..a54d274f3 --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1658857216982492500.sql @@ -0,0 +1,2 @@ +-- +UPDATE `creature_template` SET `flags_extra` = `flags_extra`|0x80000000 WHERE `entry` = 15339; diff --git a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_ossirian.cpp b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_ossirian.cpp index b885ce139..bfa85bc52 100644 --- a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_ossirian.cpp +++ b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_ossirian.cpp @@ -168,6 +168,11 @@ struct boss_ossirian : public BossAI { crystal->Use(me); } + + std::list vortexes; + me->GetCreaturesWithEntryInRange(vortexes, 200.f, NPC_SAND_VORTEX); + for (Creature* vortex : vortexes) + vortex->DespawnOrUnsummon(); } void SpawnNextCrystal() From 3ea74e26190e3a62b76128298cac98f83ae5ba34 Mon Sep 17 00:00:00 2001 From: AzerothCoreBot Date: Wed, 27 Jul 2022 03:43:28 +0000 Subject: [PATCH 124/130] chore(DB): import pending files Referenced commit(s): 07c043552aa833bd101ffc0eb2ed71594fdea773 --- .../rev_1658857216982492500.sql => db_world/2022_07_27_00.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/rev_1658857216982492500.sql => db_world/2022_07_27_00.sql} (69%) diff --git a/data/sql/updates/pending_db_world/rev_1658857216982492500.sql b/data/sql/updates/db_world/2022_07_27_00.sql similarity index 69% rename from data/sql/updates/pending_db_world/rev_1658857216982492500.sql rename to data/sql/updates/db_world/2022_07_27_00.sql index a54d274f3..dac106a95 100644 --- a/data/sql/updates/pending_db_world/rev_1658857216982492500.sql +++ b/data/sql/updates/db_world/2022_07_27_00.sql @@ -1,2 +1,3 @@ +-- DB update 2022_07_26_06 -> 2022_07_27_00 -- UPDATE `creature_template` SET `flags_extra` = `flags_extra`|0x80000000 WHERE `entry` = 15339; From 3385cd0fcec1f4115807e8463a401abc85e7f77d Mon Sep 17 00:00:00 2001 From: temperrr Date: Wed, 27 Jul 2022 14:39:32 +0200 Subject: [PATCH 125/130] fix(DB/SAI): Destroyer should have 0 mana on repull (#12558) Fix(SmartScript/Creature): Destroyer should have 0 mana on repull --- data/sql/updates/pending_db_world/aqdestroyer.sql | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 data/sql/updates/pending_db_world/aqdestroyer.sql diff --git a/data/sql/updates/pending_db_world/aqdestroyer.sql b/data/sql/updates/pending_db_world/aqdestroyer.sql new file mode 100644 index 000000000..55d813608 --- /dev/null +++ b/data/sql/updates/pending_db_world/aqdestroyer.sql @@ -0,0 +1,8 @@ +UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 15338; +DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 15338); +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(15338, 0, 0, 0, 0, 0, 100, 0, 5000, 9000, 8000, 11000, 0, 11, 25756, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Obsidian Destroyer - In Combat - Cast \'Purge\''), +(15338, 0, 1, 0, 0, 0, 100, 0, 2000, 4000, 6000, 6000, 0, 11, 25755, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Obsidian Destroyer - In Combat - Cast \'Drain Mana\''), +(15338, 0, 2, 0, 6, 0, 100, 0, 0, 0, 0, 0, 0, 11, 27627, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'Obsidian Destroyer - On Just Died - Cast \'Serverside - Drop Obsidian\''), +(15338, 0, 3, 0, 11, 0, 100, 0, 0, 0, 0, 0, 0, 108, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Obsidian Destroyer - On Respawn - Set Mana To 0'), +(15338, 0, 4, 0, 7, 0, 100, 0, 0, 0, 0, 0, 0, 108, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Obsidian Destroyer - On Evade - Set Mana To 0'); From 37ce61e129bd168af74dbd4b09df3484c249c838 Mon Sep 17 00:00:00 2001 From: temperrr Date: Wed, 27 Jul 2022 14:40:18 +0200 Subject: [PATCH 126/130] fix(DB/SAI): Hive Wasp should target 3 people every cast (#12557) * Create aq20wasp.sql * whitespace * Update data/sql/updates/pending_db_world/aq20wasp.sql Co-authored-by: Nefertumm --- data/sql/updates/pending_db_world/aq20wasp.sql | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 data/sql/updates/pending_db_world/aq20wasp.sql diff --git a/data/sql/updates/pending_db_world/aq20wasp.sql b/data/sql/updates/pending_db_world/aq20wasp.sql new file mode 100644 index 000000000..026bddab9 --- /dev/null +++ b/data/sql/updates/pending_db_world/aq20wasp.sql @@ -0,0 +1,7 @@ +-- +UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 15325; +DELETE FROM `smart_scripts` WHERE (`entryorguid` = 15325) AND (`source_type` = 0) AND (`id` IN (0, 1, 2)); +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(15325, 0, 0, 1, 9, 0, 100, 0, 0, 40, 11000, 16000, 0, 11, 25185, 4, 3, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 'Hive\'Zara Wasp - Within 0-40 Range - Cast \'Itch\''), +(15325, 0, 1, 2, 61, 0, 100, 0, 0, 0, 0, 0, 0, 11, 25185, 4, 3, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 'Hive\'Zara Wasp - Within 0-40 Range - Cast \'Itch\''), +(15325, 0, 2, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 11, 25185, 4, 3, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 'Hive\'Zara Wasp - Within 0-40 Range - Cast \'Itch\''); From 9ea048b46071ae38cb184bbdbf0bcb5c670830f8 Mon Sep 17 00:00:00 2001 From: UltraNix <80540499+UltraNix@users.noreply.github.com> Date: Wed, 27 Jul 2022 14:41:24 +0200 Subject: [PATCH 127/130] =?UTF-8?q?fix(DB/Spells):=20Greater=20Heal=20spel?= =?UTF-8?q?l=20from=208P=20T2=20Priest=20set=20should=20scale=E2=80=A6=20(?= =?UTF-8?q?#12504)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(DB/Spells): Greater Heal spell from 8P T2 Priest set should scale with spell power. Fixes #11934 * Update. --- data/sql/updates/pending_db_world/rev_1658587246185545500.sql | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 data/sql/updates/pending_db_world/rev_1658587246185545500.sql diff --git a/data/sql/updates/pending_db_world/rev_1658587246185545500.sql b/data/sql/updates/pending_db_world/rev_1658587246185545500.sql new file mode 100644 index 000000000..e5f3a6ba4 --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1658587246185545500.sql @@ -0,0 +1,4 @@ +-- +DELETE FROM `spell_bonus_data` WHERE `entry`=22009; +INSERT INTO `spell_bonus_data` VALUES +(22009,0,0.2,0,0,'Priest - Greater Heal - 8P T2'); From 66fcb8064a7b32b97586bfc15effa6411293b51d Mon Sep 17 00:00:00 2001 From: AzerothCoreBot Date: Wed, 27 Jul 2022 12:44:07 +0000 Subject: [PATCH 128/130] chore(DB): import pending files Referenced commit(s): 9ea048b46071ae38cb184bbdbf0bcb5c670830f8 --- .../aq20wasp.sql => db_world/2022_07_27_01.sql} | 1 + .../aqdestroyer.sql => db_world/2022_07_27_02.sql} | 1 + .../rev_1658587246185545500.sql => db_world/2022_07_27_03.sql} | 1 + 3 files changed, 3 insertions(+) rename data/sql/updates/{pending_db_world/aq20wasp.sql => db_world/2022_07_27_01.sql} (96%) rename data/sql/updates/{pending_db_world/aqdestroyer.sql => db_world/2022_07_27_02.sql} (97%) rename data/sql/updates/{pending_db_world/rev_1658587246185545500.sql => db_world/2022_07_27_03.sql} (76%) diff --git a/data/sql/updates/pending_db_world/aq20wasp.sql b/data/sql/updates/db_world/2022_07_27_01.sql similarity index 96% rename from data/sql/updates/pending_db_world/aq20wasp.sql rename to data/sql/updates/db_world/2022_07_27_01.sql index 026bddab9..ff9db182a 100644 --- a/data/sql/updates/pending_db_world/aq20wasp.sql +++ b/data/sql/updates/db_world/2022_07_27_01.sql @@ -1,3 +1,4 @@ +-- DB update 2022_07_27_00 -> 2022_07_27_01 -- UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 15325; DELETE FROM `smart_scripts` WHERE (`entryorguid` = 15325) AND (`source_type` = 0) AND (`id` IN (0, 1, 2)); diff --git a/data/sql/updates/pending_db_world/aqdestroyer.sql b/data/sql/updates/db_world/2022_07_27_02.sql similarity index 97% rename from data/sql/updates/pending_db_world/aqdestroyer.sql rename to data/sql/updates/db_world/2022_07_27_02.sql index 55d813608..72ebdab17 100644 --- a/data/sql/updates/pending_db_world/aqdestroyer.sql +++ b/data/sql/updates/db_world/2022_07_27_02.sql @@ -1,3 +1,4 @@ +-- DB update 2022_07_27_01 -> 2022_07_27_02 UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 15338; DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 15338); INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES diff --git a/data/sql/updates/pending_db_world/rev_1658587246185545500.sql b/data/sql/updates/db_world/2022_07_27_03.sql similarity index 76% rename from data/sql/updates/pending_db_world/rev_1658587246185545500.sql rename to data/sql/updates/db_world/2022_07_27_03.sql index e5f3a6ba4..c0f3e3ae3 100644 --- a/data/sql/updates/pending_db_world/rev_1658587246185545500.sql +++ b/data/sql/updates/db_world/2022_07_27_03.sql @@ -1,3 +1,4 @@ +-- DB update 2022_07_27_02 -> 2022_07_27_03 -- DELETE FROM `spell_bonus_data` WHERE `entry`=22009; INSERT INTO `spell_bonus_data` VALUES From 5024e380cea5d432ff93cabf3c35d3113cc54874 Mon Sep 17 00:00:00 2001 From: temperrr Date: Wed, 27 Jul 2022 14:45:37 +0200 Subject: [PATCH 129/130] fix(DB/Formations): ZG Trash Formations (#12533) * fix(Formations/Creature): ZG trash formations * Update zgtrashformations.sql * Update zgtrashformations.sql --- .../pending_db_world/zgtrashformations.sql | 77 +++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 data/sql/updates/pending_db_world/zgtrashformations.sql diff --git a/data/sql/updates/pending_db_world/zgtrashformations.sql b/data/sql/updates/pending_db_world/zgtrashformations.sql new file mode 100644 index 000000000..0fd16f2b9 --- /dev/null +++ b/data/sql/updates/pending_db_world/zgtrashformations.sql @@ -0,0 +1,77 @@ +DELETE FROM `creature_formations` WHERE `leaderguid` IN (49609, 49059, 51584, 49309, 51350, 51974, 51570, 49793, 49274, 51979, 49290); +DELETE FROM `creature_formations` WHERE `leaderguid` = 49065 AND `memberGUID` = 49051; +DELETE FROM `creature_formations` WHERE `leaderguid` = 49062 AND `memberGUID` = 49052; +INSERT INTO `creature_formations` (`leaderGUID`, `memberGUID`, `dist`, `angle`, `groupAI`, `point_1`, `point_2`) VALUES +(51584, 51584, 0, 0, 3, 0, 0), +(51584, 49801, 0, 0, 3, 0, 0), +(51584, 49802, 0, 0, 3, 0, 0), +(51584, 49803, 0, 0, 3, 0, 0), +(51584, 49804, 0, 0, 3, 0, 0), +(51584, 51583, 0, 0, 3, 0, 0), +(51584, 49805, 0, 0, 3, 0, 0), +(51584, 51582, 0, 0, 3, 0, 0), +(49309, 49309, 0, 0, 3, 0, 0), +(49309, 49296, 0, 0, 3, 0, 0), +(49309, 49297, 0, 0, 3, 0, 0), +(49309, 49308, 0, 0, 3, 0, 0), +(49309, 49300, 0, 0, 3, 0, 0), +(49309, 49307, 0, 0, 3, 0, 0), +(49309, 49299, 0, 0, 3, 0, 0), +(49309, 49298, 0, 0, 3, 0, 0), +(51350, 51350, 0, 0, 3, 0, 0), +(51350, 51351, 0, 0, 3, 0, 0), +(51350, 49813, 0, 0, 3, 0, 0), +(51350, 51352, 0, 0, 3, 0, 0), +(51350, 49812, 0, 0, 3, 0, 0), +(51350, 49811, 0, 0, 3, 0, 0), +(51350, 51349, 0, 0, 3, 0, 0), +(51974, 51974, 0, 0, 3, 0, 0), +(51974, 51460, 0, 0, 3, 0, 0), +(51974, 51983, 0, 0, 3, 0, 0), +(51974, 51461, 0, 0, 3, 0, 0), +(51570, 51570, 0, 0, 3, 0, 0), +(51570, 51967, 0, 0, 3, 0, 0), +(51570, 51571, 0, 0, 3, 0, 0), +(51570, 51572, 0, 0, 3, 0, 0), +(51570, 51968, 0, 0, 3, 0, 0), +(51570, 51969, 0, 0, 3, 0, 0), +(49793, 49793, 0, 0, 3, 0, 0), +(49793, 49796, 0, 0, 3, 0, 0), +(49793, 49795, 0, 0, 3, 0, 0), +(49793, 49794, 0, 0, 3, 0, 0), +(49274, 49274, 0, 0, 3, 0, 0), +(49274, 49276, 0, 0, 3, 0, 0), +(49274, 51565, 0, 0, 3, 0, 0), +(49274, 51564, 0, 0, 3, 0, 0), +(49274, 49275, 0, 0, 3, 0, 0), +(49274, 51462, 0, 0, 3, 0, 0), +(51979, 51979, 0, 0, 3, 0, 0), +(51979, 51455, 0, 0, 3, 0, 0), +(51979, 51453, 0, 0, 3, 0, 0), +(51979, 51454, 0, 0, 3, 0, 0), +(51979, 51980, 0, 0, 3, 0, 0), +(51979, 51978, 0, 0, 3, 0, 0), +(49290, 49290, 0, 0, 3, 0, 0), +(49290, 51580, 0, 0, 3, 0, 0), +(49290, 49304, 0, 0, 3, 0, 0), +(49290, 51581, 0, 0, 3, 0, 0), +(49290, 49810, 0, 0, 3, 0, 0), +(49290, 49800, 0, 0, 3, 0, 0), +(49290, 49291, 0, 0, 3, 0, 0), +(49290, 49306, 0, 0, 3, 0, 0), +(49290, 49289, 0, 0, 3, 0, 0), +(49059, 49059, 0, 0, 3, 0, 0), +(49059, 49060, 0, 0, 3, 0, 0), +(49059, 49061, 0, 0, 3, 0, 0), +(49065, 49051, 0, 0, 3, 0, 0), +(49062, 49052, 0, 0, 3, 0, 0), +(49609, 49609, 0, 0, 3, 0, 0), +(49609, 49574, 0, 0, 3, 0, 0), +(49609, 49421, 0, 0, 3, 0, 0), +(49609, 49576, 0, 0, 3, 0, 0), +(49609, 49402, 0, 0, 3, 0, 0), +(49609, 49650, 0, 0, 3, 0, 0), +(49609, 49575, 0, 0, 3, 0, 0), +(49609, 49573, 0, 0, 3, 0, 0), +(49609, 49403, 0, 0, 3, 0, 0), +(49609, 49577, 0, 0, 3, 0, 0); From bad616c68a66b79934d1102ccc8c8e7d443cb4cf Mon Sep 17 00:00:00 2001 From: AzerothCoreBot Date: Wed, 27 Jul 2022 12:47:50 +0000 Subject: [PATCH 130/130] chore(DB): import pending files Referenced commit(s): 5024e380cea5d432ff93cabf3c35d3113cc54874 --- .../zgtrashformations.sql => db_world/2022_07_27_04.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/zgtrashformations.sql => db_world/2022_07_27_04.sql} (98%) diff --git a/data/sql/updates/pending_db_world/zgtrashformations.sql b/data/sql/updates/db_world/2022_07_27_04.sql similarity index 98% rename from data/sql/updates/pending_db_world/zgtrashformations.sql rename to data/sql/updates/db_world/2022_07_27_04.sql index 0fd16f2b9..9a6a16b56 100644 --- a/data/sql/updates/pending_db_world/zgtrashformations.sql +++ b/data/sql/updates/db_world/2022_07_27_04.sql @@ -1,3 +1,4 @@ +-- DB update 2022_07_27_03 -> 2022_07_27_04 DELETE FROM `creature_formations` WHERE `leaderguid` IN (49609, 49059, 51584, 49309, 51350, 51974, 51570, 49793, 49274, 51979, 49290); DELETE FROM `creature_formations` WHERE `leaderguid` = 49065 AND `memberGUID` = 49051; DELETE FROM `creature_formations` WHERE `leaderguid` = 49062 AND `memberGUID` = 49052;