diff options
34 files changed, 273 insertions, 302 deletions
diff --git a/src/server/game/AI/CoreAI/CombatAI.cpp b/src/server/game/AI/CoreAI/CombatAI.cpp index 2f2461b5ab0..ec60d790fee 100644 --- a/src/server/game/AI/CoreAI/CombatAI.cpp +++ b/src/server/game/AI/CoreAI/CombatAI.cpp @@ -32,7 +32,7 @@ // AggressorAI ///////////////// -int AggressorAI::Permissible(const Creature* 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()) @@ -344,3 +344,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 9e4e05d9544..9082ad515e8 100644 --- a/src/server/game/AI/CoreAI/CombatAI.h +++ b/src/server/game/AI/CoreAI/CombatAI.h @@ -28,7 +28,7 @@ class TC_GAME_API AggressorAI : public CreatureAI explicit AggressorAI(Creature* c) : CreatureAI(c) { } void UpdateAI(uint32) override; - static int Permissible(const Creature*); + static int32 Permissible(Creature const* creature); }; typedef std::vector<uint32> SpellVct; @@ -45,7 +45,7 @@ class TC_GAME_API CombatAI : public CreatureAI void UpdateAI(uint32 diff) override; void SpellInterrupted(uint32 spellId, uint32 unTimeMs) override; - static int Permissible(Creature const* /*creature*/) { return PERMIT_BASE_NO; } + static int32 Permissible(Creature const* /*creature*/) { return PERMIT_BASE_NO; } protected: EventMap events; @@ -71,7 +71,7 @@ struct TC_GAME_API ArcherAI : public CreatureAI 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; @@ -85,7 +85,7 @@ struct TC_GAME_API TurretAI : public CreatureAI 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; @@ -104,7 +104,7 @@ struct TC_GAME_API VehicleAI : public CreatureAI 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 48caa63dbce..94fe71f449d 100644 --- a/src/server/game/AI/CoreAI/GameObjectAI.cpp +++ b/src/server/game/AI/CoreAI/GameObjectAI.cpp @@ -20,11 +20,8 @@ #include "GameObject.h" #include "QuestDef.h" -//GameObjectAI::GameObjectAI(GameObject* g) : go(g) { } -int GameObjectAI::Permissible(const GameObject* go) +int32 GameObjectAI::Permissible(GameObject const* /*go*/) { - if (go->GetAIName() == "GameObjectAI") - return PERMIT_BASE_SPECIAL; return PERMIT_BASE_NO; } @@ -35,7 +32,7 @@ uint32 GameObjectAI::GetDialogStatus(Player* /*player*/) NullGameObjectAI::NullGameObjectAI(GameObject* g) : GameObjectAI(g) { } -int NullGameObjectAI::Permissible(GameObject const* /*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 655035d505b..4bfc6c7a2f3 100644 --- a/src/server/game/AI/CoreAI/GameObjectAI.h +++ b/src/server/game/AI/CoreAI/GameObjectAI.h @@ -46,7 +46,7 @@ class TC_GAME_API GameObjectAI virtual void SetGUID(uint64 /*guid*/, int32 /*id = 0 */) { } virtual uint64 GetGUID(int32 /*id = 0 */) const { return 0; } - static int Permissible(GameObject const* go); + static int32 Permissible(GameObject const* /*go*/); // Called when a player opens a gossip dialog with the gameobject. virtual bool GossipHello(Player* /*player*/, bool /*reportUse*/) { return false; } @@ -88,6 +88,6 @@ class TC_GAME_API NullGameObjectAI : public GameObjectAI void UpdateAI(uint32 /*diff*/) override { } - static int Permissible(GameObject const* /*go*/); + 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 f9d3b96cadb..2b358945bd9 100644 --- a/src/server/game/AI/CoreAI/GuardAI.cpp +++ b/src/server/game/AI/CoreAI/GuardAI.cpp @@ -26,10 +26,10 @@ GuardAI::GuardAI(Creature* creature) : ScriptedAI(creature) { } -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 a731e160e90..037094cff4b 100644 --- a/src/server/game/AI/CoreAI/GuardAI.h +++ b/src/server/game/AI/CoreAI/GuardAI.h @@ -27,7 +27,7 @@ class TC_GAME_API GuardAI : public ScriptedAI public: explicit GuardAI(Creature* creature); - static int Permissible(Creature const* creature); + static int32 Permissible(Creature const* creature); void UpdateAI(uint32 diff) override; bool CanSeeAlways(WorldObject const* obj) override; diff --git a/src/server/game/AI/CoreAI/PassiveAI.cpp b/src/server/game/AI/CoreAI/PassiveAI.cpp index 417a3c9bf04..5c3e8026600 100644 --- a/src/server/game/AI/CoreAI/PassiveAI.cpp +++ b/src/server/game/AI/CoreAI/PassiveAI.cpp @@ -22,6 +22,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->HasNpcFlag(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()) @@ -76,8 +87,24 @@ void CritterAI::EnterEvadeMode(EvadeReason why) CreatureAI::EnterEvadeMode(why); } +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, nullptr, nullptr, summoner->GetGUID()); } + +int32 TriggerAI::Permissible(Creature const* creature) +{ + if (creature->IsTrigger() && creature->m_spells[0]) + return PERMIT_BASE_PROACTIVE; + + return PERMIT_BASE_NO; +} diff --git a/src/server/game/AI/CoreAI/PassiveAI.h b/src/server/game/AI/CoreAI/PassiveAI.h index 43ad670e0df..41d4c2bfb12 100644 --- a/src/server/game/AI/CoreAI/PassiveAI.h +++ b/src/server/game/AI/CoreAI/PassiveAI.h @@ -29,7 +29,7 @@ class TC_GAME_API PassiveAI : public CreatureAI void AttackStart(Unit*) override { } void UpdateAI(uint32) override; - static int Permissible(const Creature*) { return PERMIT_BASE_IDLE; } + static int32 Permissible(Creature const* /*creature*/) { return PERMIT_BASE_NO; } }; class TC_GAME_API PossessedAI : public CreatureAI @@ -47,7 +47,7 @@ class TC_GAME_API PossessedAI : public CreatureAI void OnCharmed(bool /*apply*/) override; - static int Permissible(const Creature*) { return PERMIT_BASE_IDLE; } + static int32 Permissible(Creature const* /*creature*/) { return PERMIT_BASE_NO; } }; class TC_GAME_API NullCreatureAI : public CreatureAI @@ -61,7 +61,7 @@ class TC_GAME_API NullCreatureAI : public CreatureAI void EnterEvadeMode(EvadeReason /*why*/) override { } void OnCharmed(bool /*apply*/) override { } - static int Permissible(const Creature*) { return PERMIT_BASE_IDLE; } + static int32 Permissible(Creature const* creature); }; class TC_GAME_API CritterAI : public PassiveAI @@ -71,6 +71,8 @@ class TC_GAME_API CritterAI : public PassiveAI void DamageTaken(Unit* done_by, uint32& /*damage*/) override; void EnterEvadeMode(EvadeReason why) override; + + static int32 Permissible(Creature const* creature); }; class TC_GAME_API TriggerAI : public NullCreatureAI @@ -78,6 +80,8 @@ class TC_GAME_API 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 a39e4a8dfc0..aa0dbfb76e3 100644 --- a/src/server/game/AI/CoreAI/PetAI.cpp +++ b/src/server/game/AI/CoreAI/PetAI.cpp @@ -31,11 +31,18 @@ #include "SpellMgr.h" #include "Util.h" -int PetAI::Permissible(const Creature* creature) +int32 PetAI::Permissible(Creature const* creature) { if (creature->IsPet()) return PERMIT_BASE_SPECIAL; + if (creature->HasUnitTypeMask(UNIT_MASK_CONTROLABLE_GUARDIAN)) + { + if (reinterpret_cast<Guardian const*>(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 c712d42651d..4455c1cd494 100644 --- a/src/server/game/AI/CoreAI/PetAI.h +++ b/src/server/game/AI/CoreAI/PetAI.h @@ -33,7 +33,7 @@ class TC_GAME_API PetAI : public CreatureAI explicit PetAI(Creature* c); void UpdateAI(uint32) override; - static int Permissible(const Creature*); + 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 836cc1e0358..8b15bed1908 100644 --- a/src/server/game/AI/CoreAI/ReactorAI.cpp +++ b/src/server/game/AI/CoreAI/ReactorAI.cpp @@ -18,7 +18,7 @@ #include "ReactorAI.h" #include "Creature.h" -int ReactorAI::Permissible(const Creature* 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 fa0bd2d8ee1..be76f855781 100644 --- a/src/server/game/AI/CoreAI/ReactorAI.h +++ b/src/server/game/AI/CoreAI/ReactorAI.h @@ -29,6 +29,6 @@ class TC_GAME_API ReactorAI : public CreatureAI void MoveInLineOfSight(Unit*) override { } void UpdateAI(uint32 diff) override; - static int Permissible(const Creature*); + 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 4d2bda5faa0..c727ea45003 100644 --- a/src/server/game/AI/CoreAI/TotemAI.cpp +++ b/src/server/game/AI/CoreAI/TotemAI.cpp @@ -24,7 +24,7 @@ #include "GridNotifiersImpl.h" #include "CellImpl.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 2938190c771..fd25ca86df6 100644 --- a/src/server/game/AI/CoreAI/TotemAI.h +++ b/src/server/game/AI/CoreAI/TotemAI.h @@ -35,7 +35,7 @@ class TC_GAME_API TotemAI : public CreatureAI void EnterEvadeMode(EvadeReason /*why*/) 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 b274a4794d1..41e6ab2501d 100644 --- a/src/server/game/AI/CreatureAI.h +++ b/src/server/game/AI/CreatureAI.h @@ -204,7 +204,7 @@ class TC_GAME_API CreatureAI : public UnitAI 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 656435ad632..92e757d835d 100644 --- a/src/server/game/AI/CreatureAIFactory.h +++ b/src/server/game/AI/CreatureAIFactory.h @@ -18,66 +18,34 @@ #ifndef TRINITY_CREATUREAIFACTORY_H #define TRINITY_CREATUREAIFACTORY_H -//#include "Policies/Singleton.h" #include "ObjectRegistry.h" #include "FactoryHolder.h" -#include "GameObjectAI.h" -struct SelectableAI : public FactoryHolder<CreatureAI>, public Permissible<Creature> +typedef FactoryHolder<CreatureAI, Creature> CreatureAICreator; + +struct SelectableAI : public CreatureAICreator, public Permissible<Creature> { - SelectableAI(const char* id) : FactoryHolder<CreatureAI>(id) { } + SelectableAI(std::string const& name) : CreatureAICreator(name), Permissible<Creature>() { } }; template<class REAL_AI> struct CreatureAIFactory : public SelectableAI { - CreatureAIFactory(const char* name) : SelectableAI(name) { } + CreatureAIFactory(std::string const& name) : SelectableAI(name) { } - CreatureAI* Create(void*) const override; + inline CreatureAI* Create(Creature* c) const override + { + return new REAL_AI(c); + } - int Permit(const Creature* c) const override { return REAL_AI::Permissible(c); } + int32 Permit(Creature const* c) const override + { + return REAL_AI::Permissible(c); + } }; -template<class REAL_AI> -inline CreatureAI* -CreatureAIFactory<REAL_AI>::Create(void* data) const -{ - Creature* creature = reinterpret_cast<Creature*>(data); - return (new REAL_AI(creature)); -} - -typedef FactoryHolder<CreatureAI> CreatureAICreator; -typedef FactoryHolder<CreatureAI>::FactoryHolderRegistry CreatureAIRegistry; +typedef CreatureAICreator::FactoryHolderRegistry CreatureAIRegistry; #define sCreatureAIRegistry CreatureAIRegistry::instance() -//GO -struct SelectableGameObjectAI : public FactoryHolder<GameObjectAI>, public Permissible<GameObject> -{ - SelectableGameObjectAI(const char* id) : FactoryHolder<GameObjectAI>(id) { } -}; - -template<class REAL_GO_AI> -struct GameObjectAIFactory : public SelectableGameObjectAI -{ - GameObjectAIFactory(const char* name) : SelectableGameObjectAI(name) { } - - GameObjectAI* Create(void*) const override; - - int Permit(const GameObject* g) const override { return REAL_GO_AI::Permissible(g); } -}; - -template<class REAL_GO_AI> -inline GameObjectAI* -GameObjectAIFactory<REAL_GO_AI>::Create(void* data) const -{ - GameObject* go = reinterpret_cast<GameObject*>(data); - return (new REAL_GO_AI(go)); -} - -typedef FactoryHolder<GameObjectAI> GameObjectAICreator; -typedef FactoryHolder<GameObjectAI>::FactoryHolderRegistry GameObjectAIRegistry; - -#define sGameObjectAIRegistry GameObjectAIRegistry::instance() - #endif diff --git a/src/server/game/AI/CreatureAIRegistry.cpp b/src/server/game/AI/CreatureAIRegistry.cpp index 9aab7376ab2..34cc64af22b 100644 --- a/src/server/game/AI/CreatureAIRegistry.cpp +++ b/src/server/game/AI/CreatureAIRegistry.cpp @@ -22,10 +22,11 @@ #include "PetAI.h" #include "TotemAI.h" #include "RandomMovementGenerator.h" -#include "MovementGeneratorImpl.h" +#include "MovementGenerator.h" #include "CreatureAIRegistry.h" #include "WaypointMovementGenerator.h" #include "CreatureAIFactory.h" +#include "GameObjectAIFactory.h" #include "SmartAI.h" namespace AIRegistry @@ -47,10 +48,12 @@ namespace AIRegistry (new CreatureAIFactory<VehicleAI>("VehicleAI"))->RegisterSelf(); (new CreatureAIFactory<SmartAI>("SmartAI"))->RegisterSelf(); + (new GameObjectAIFactory<NullGameObjectAI>("NullGameObjectAI"))->RegisterSelf(); (new GameObjectAIFactory<GameObjectAI>("GameObjectAI"))->RegisterSelf(); (new GameObjectAIFactory<SmartGameObjectAI>("SmartGameObjectAI"))->RegisterSelf(); - (new MovementGeneratorFactory<RandomMovementGenerator<Creature> >(RANDOM_MOTION_TYPE))->RegisterSelf(); - (new MovementGeneratorFactory<WaypointMovementGenerator<Creature> >(WAYPOINT_MOTION_TYPE))->RegisterSelf(); + (new IdleMovementFactory())->RegisterSelf(); + (new MovementGeneratorFactory<RandomMovementGenerator<Creature>>(RANDOM_MOTION_TYPE))->RegisterSelf(); + (new MovementGeneratorFactory<WaypointMovementGenerator<Creature>>(WAYPOINT_MOTION_TYPE))->RegisterSelf(); } } diff --git a/src/server/game/AI/CreatureAISelector.cpp b/src/server/game/AI/CreatureAISelector.cpp index 487511eff3e..610a8e5b537 100644 --- a/src/server/game/AI/CreatureAISelector.cpp +++ b/src/server/game/AI/CreatureAISelector.cpp @@ -17,130 +17,100 @@ #include "Creature.h" #include "CreatureAISelector.h" -#include "GameObject.h" -#include "PassiveAI.h" +#include "CreatureAIFactory.h" #include "Log.h" #include "MovementGenerator.h" -#include "TemporarySummon.h" -#include "CreatureAIFactory.h" + +#include "GameObject.h" +#include "GameObjectAIFactory.h" + #include "ScriptMgr.h" namespace FactorySelector { - CreatureAI* selectAI(Creature* creature) + template <class T> + struct PermissibleOrderPred { - const CreatureAICreator* ai_factory = NULL; + public: + PermissibleOrderPred(T const* obj) : _obj(obj) { } - if (creature->IsPet()) - ai_factory = sCreatureAIRegistry->GetRegistryItem("PetAI"); + template <class Value> + bool operator()(Value const& left, Value const& right) const + { + Permissible<T> const* leftPermit = ASSERT_NOTNULL(dynamic_cast<Permissible<T> const*>(left.second.get())); + Permissible<T> const* rightPermit = ASSERT_NOTNULL(dynamic_cast<Permissible<T> 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 = sCreatureAIRegistry->GetRegistryItem(ainame); - - // select by NPC flags - if (!ai_factory) - { - if (creature->IsVehicle()) - ai_factory = sCreatureAIRegistry->GetRegistryItem("VehicleAI"); - else if (creature->HasUnitTypeMask(UNIT_MASK_CONTROLABLE_GUARDIAN) && ((Guardian*)creature)->GetOwner()->GetTypeId() == TYPEID_PLAYER) - ai_factory = sCreatureAIRegistry->GetRegistryItem("PetAI"); - else if (creature->HasNpcFlag(UNIT_NPC_FLAG_SPELLCLICK)) - ai_factory = sCreatureAIRegistry->GetRegistryItem("NullCreatureAI"); - else if (creature->IsGuard()) - ai_factory = sCreatureAIRegistry->GetRegistryItem("GuardAI"); - else if (creature->HasUnitTypeMask(UNIT_MASK_CONTROLABLE_GUARDIAN)) - ai_factory = sCreatureAIRegistry->GetRegistryItem("PetAI"); - else if (creature->IsTotem()) - ai_factory = sCreatureAIRegistry->GetRegistryItem("TotemAI"); - else if (creature->IsTrigger()) - { - if (creature->m_spells[0]) - ai_factory = sCreatureAIRegistry->GetRegistryItem("TriggerAI"); - else - ai_factory = sCreatureAIRegistry->GetRegistryItem("NullCreatureAI"); - } - else if (creature->IsCritter() && !creature->HasUnitTypeMask(UNIT_MASK_GUARDIAN)) - ai_factory = sCreatureAIRegistry->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 = sCreatureAIRegistry->GetRegisteredItems(); - for (RMT::const_iterator iter = l.begin(); iter != l.end(); ++iter) - { - const CreatureAICreator* factory = iter->second; - const SelectableAI* p = dynamic_cast<const SelectableAI*>(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>(creature)); + if (itr != items.end()) + ai_factory = itr->second.get(); } - // select NullCreatureAI if not another cases - ainame = (ai_factory == NULL) ? "NullCreatureAI" : ai_factory->key(); + if (!ai_factory) + ai_factory = sCreatureAIRegistry->GetRegistryItem("NullCreatureAI"); - TC_LOG_DEBUG("scripts", "Creature %s (%s DB GUID: " UI64FMTD ") is using AI type: %s.", creature->GetName().c_str(), creature->GetGUID().ToString().c_str(), creature->GetSpawnId(), ainame.c_str()); - return (ai_factory == NULL ? new NullCreatureAI(creature) : ai_factory->Create(creature)); + 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 == NULL) - { - int best_val = -1; - StringVector l; - mv_registry.GetRegisteredItems(l); - for (StringVector::iterator iter = l.begin(); iter != l.end(); ++iter) - { - const MovementGeneratorCreator *factory = mv_registry.GetRegistryItem((*iter).c_str()); - const SelectableMovement *p = dynamic_cast<const SelectableMovement *>(factory); - ASSERT(p != NULL); - int val = p->Permit(creature); - if (val > best_val) - { - best_val = val; - mv_factory = p; - } - } - }*/ - - return (mv_factory == NULL ? NULL : mv_factory->Create(creature)); + MovementGeneratorCreator const* mv_factory = sMovementGeneratorRegistry->GetRegistryItem(type); + return ASSERT_NOTNULL(mv_factory)->Create(unit); } GameObjectAI* SelectGameObjectAI(GameObject* go) { - GameObjectAICreator const* ai_factory = NULL; + GameObjectAICreator const* ai_factory = nullptr; // scriptname in db if (GameObjectAI* scriptedAI = sScriptMgr->GetGameObjectAI(go)) return scriptedAI; - ai_factory = sGameObjectAIRegistry->GetRegistryItem(go->GetAIName()); - - //future goAI types go here + // AIname in db + std::string const& aiName = go->GetAIName(); + if (!ai_factory && !aiName.empty()) + ai_factory = sGameObjectAIRegistry->GetRegistryItem(aiName); - std::string ainame = (ai_factory == NULL || go->GetScriptId()) ? "NullGameObjectAI" : ai_factory->key(); + // select by permit check + if (!ai_factory) + { + GameObjectAIRegistry::RegistryMapType const& items = sGameObjectAIRegistry->GetRegisteredItems(); + auto itr = std::max_element(items.begin(), items.end(), PermissibleOrderPred<GameObject>(go)); + if (itr != items.end()) + ai_factory = itr->second.get(); + } - TC_LOG_DEBUG("scripts", "%s used AI is %s.", go->GetGUID().ToString().c_str(), ainame.c_str()); + if (!ai_factory) + ai_factory = sGameObjectAIRegistry->GetRegistryItem("NullGameObjectAI"); - return (ai_factory == NULL ? 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 d22bf0bb1e7..b4046a5e982 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 { - TC_GAME_API CreatureAI* selectAI(Creature*); - TC_GAME_API MovementGenerator* selectMovementGenerator(Creature*); - TC_GAME_API GameObjectAI* SelectGameObjectAI(GameObject*); + TC_GAME_API CreatureAI* SelectAI(Creature* creature); + TC_GAME_API MovementGenerator* SelectMovementGenerator(Unit* unit); + TC_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 00000000000..88dcb5cbb81 --- /dev/null +++ b/src/server/game/AI/GameObjectAIFactory.h @@ -0,0 +1,54 @@ +/* + * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef TRINITY_GAMEOBJECTAIFACTORY_H +#define TRINITY_GAMEOBJECTAIFACTORY_H + +#include "ObjectRegistry.h" +#include "FactoryHolder.h" + +class GameObject; +class GameObjectAI; + +typedef FactoryHolder<GameObjectAI, GameObject> GameObjectAICreator; + +struct SelectableGameObjectAI : public GameObjectAICreator, public Permissible<GameObject> +{ + SelectableGameObjectAI(std::string const& name) : GameObjectAICreator(name), Permissible<GameObject>() { } +}; + +template<class REAL_GO_AI> +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 b33c6f5093a..065ca31bee0 100644 --- a/src/server/game/AI/SmartScripts/SmartAI.cpp +++ b/src/server/game/AI/SmartScripts/SmartAI.cpp @@ -596,13 +596,6 @@ void SmartAI::JustRespawned() mFollowCreditType = 0; } -int SmartAI::Permissible(const Creature* creature) -{ - if (creature->GetAIName() == "SmartAI") - return PERMIT_BASE_SPECIAL; - return PERMIT_BASE_NO; -} - void SmartAI::JustReachedHome() { GetScript()->OnReset(); @@ -966,13 +959,6 @@ void SmartAI::CheckConditions(uint32 diff) mConditionsTimer -= diff; } -int SmartGameObjectAI::Permissible(const GameObject* 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 788e41b9003..070165efa40 100644 --- a/src/server/game/AI/SmartScripts/SmartAI.h +++ b/src/server/game/AI/SmartScripts/SmartAI.h @@ -158,7 +158,7 @@ class TC_GAME_API SmartAI : public CreatureAI ObjectGuid GetGUID(int32 id = 0) const override; //core related - static int Permissible(const Creature*); + static int32 Permissible(Creature const* /*creature*/) { return PERMIT_BASE_NO; } // Called at movepoint reached void MovepointReached(uint32 id); @@ -258,7 +258,7 @@ class TC_GAME_API SmartGameObjectAI : public GameObjectAI void InitializeAI() override; void Reset() override; SmartScript* GetScript() { return &mScript; } - static int Permissible(const GameObject* g); + static int32 Permissible(GameObject const* /*go*/) { return PERMIT_BASE_NO; } bool GossipHello(Player* player, bool reportUse) override; bool GossipSelect(Player* player, uint32 menuId, uint32 gossipListId) override; diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index fbdfedc6625..ba761b95ed0 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -978,7 +978,7 @@ bool Creature::AIM_Create(CreatureAI* ai /*= nullptr*/) Motion_Initialize(); - i_AI = ai ? ai : FactorySelector::selectAI(this); + i_AI = ai ? ai : FactorySelector::SelectAI(this); return true; } @@ -2810,7 +2810,7 @@ uint8 Creature::GetLevelForTarget(WorldObject const* target) const return Unit::GetLevelForTarget(target); } -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 4d7171b4c0d..beb9ed4d64f 100644 --- a/src/server/game/Entities/Creature/Creature.h +++ b/src/server/game/Entities/Creature/Creature.h @@ -172,7 +172,7 @@ class TC_GAME_API Creature : public Unit, public GridObject<Creature>, public Ma CreatureData const* GetCreatureData() const { return m_creatureData; } CreatureAddon const* GetCreatureAddon() const; - std::string GetAIName() const; + std::string const& GetAIName() const; std::string GetScriptName() const; uint32 GetScriptId() const; diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp index 6df8c23d765..cd3ebd306ea 100644 --- a/src/server/game/Entities/GameObject/GameObject.cpp +++ b/src/server/game/Entities/GameObject/GameObject.cpp @@ -166,12 +166,9 @@ bool GameObject::AIM_Initialize() return true; } -std::string GameObject::GetAIName() const +std::string const& GameObject::GetAIName() const { - if (GameObjectTemplate const* got = sObjectMgr->GetGameObjectTemplate(GetEntry())) - return got->AIName; - - return ""; + return sObjectMgr->GetGameObjectTemplate(GetEntry())->AIName; } void GameObject::CleanupsBeforeDelete(bool finalCleanup) diff --git a/src/server/game/Entities/GameObject/GameObject.h b/src/server/game/Entities/GameObject/GameObject.h index da06d1842f8..7bbf09a26ad 100644 --- a/src/server/game/Entities/GameObject/GameObject.h +++ b/src/server/game/Entities/GameObject/GameObject.h @@ -283,7 +283,7 @@ class TC_GAME_API GameObject : public WorldObject, public GridObject<GameObject> uint32 GetScriptId() const; GameObjectAI* AI() const { return m_AI; } - std::string GetAIName() const; + std::string const& GetAIName() const; void SetDisplayId(uint32 displayid); uint32 GetDisplayId() const { return m_gameObjectData->DisplayID; } uint8 GetNameSetId() const; diff --git a/src/server/game/Movement/MotionMaster.cpp b/src/server/game/Movement/MotionMaster.cpp index 3b446733bbb..295c70039e6 100644 --- a/src/server/game/Movement/MotionMaster.cpp +++ b/src/server/game/Movement/MotionMaster.cpp @@ -35,9 +35,14 @@ #include "MoveSplineInit.h" #include "PathGenerator.h" +inline MovementGenerator* GetIdleMovementGenerator() +{ + return sMovementGeneratorRegistry->GetRegistryItem(IDLE_MOTION_TYPE)->Create(); +} + inline bool IsStatic(MovementGenerator* movement) { - return (movement == &si_idleMovement); + return (movement == GetIdleMovementGenerator()); } MotionMaster::~MotionMaster() @@ -75,15 +80,7 @@ void MotionMaster::Initialize() // set new default movement generator void MotionMaster::InitDefault() { - if (_owner->GetTypeId() == TYPEID_UNIT) - { - MovementGenerator* movement = FactorySelector::selectMovementGenerator(_owner->ToCreature()); - Mutate(movement == nullptr ? &si_idleMovement : movement, MOTION_SLOT_IDLE); - } - else - { - Mutate(&si_idleMovement, MOTION_SLOT_IDLE); - } + Mutate(FactorySelector::SelectMovementGenerator(_owner), MOTION_SLOT_IDLE); } void MotionMaster::UpdateMotion(uint32 diff) @@ -198,7 +195,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::MoveTargetedHome() diff --git a/src/server/game/Movement/MovementGenerator.cpp b/src/server/game/Movement/MovementGenerator.cpp index 5ce585b483d..661267401d2 100644 --- a/src/server/game/Movement/MovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerator.cpp @@ -16,5 +16,12 @@ */ #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 fdf5506dd15..4af0709aa06 100755 --- a/src/server/game/Movement/MovementGenerator.h +++ b/src/server/game/Movement/MovementGenerator.h @@ -69,20 +69,28 @@ class MovementGeneratorMedium : public MovementGenerator } }; -struct SelectableMovement : public FactoryHolder<MovementGenerator, MovementGeneratorType> +typedef FactoryHolder<MovementGenerator, Unit, MovementGeneratorType> MovementGeneratorCreator; + +template<class Movement> +struct MovementGeneratorFactory : public MovementGeneratorCreator { - SelectableMovement(MovementGeneratorType movementGeneratorType) : FactoryHolder<MovementGenerator, MovementGeneratorType>(movementGeneratorType) { } + MovementGeneratorFactory(MovementGeneratorType movementGeneratorType) : MovementGeneratorCreator(movementGeneratorType) { } + + MovementGenerator* Create(Unit* /*object*/) const override + { + return new Movement(); + } }; -template<class Movement> -struct MovementGeneratorFactory : public SelectableMovement +struct IdleMovementFactory : public MovementGeneratorCreator { - MovementGeneratorFactory(MovementGeneratorType movementGeneratorType) : SelectableMovement(movementGeneratorType) { } + IdleMovementFactory() : MovementGeneratorCreator(IDLE_MOTION_TYPE) { } - MovementGenerator* Create(void *) const override; + MovementGenerator* Create(Unit* object) const override; }; -typedef FactoryHolder<MovementGenerator, MovementGeneratorType> MovementGeneratorCreator; -typedef FactoryHolder<MovementGenerator, MovementGeneratorType>::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 0b5474b22b3..00000000000 --- a/src/server/game/Movement/MovementGeneratorImpl.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef TRINITY_MOVEMENTGENERATOR_IMPL_H -#define TRINITY_MOVEMENTGENERATOR_IMPL_H - -#include "MovementGenerator.h" - -template<class Movement> -inline MovementGenerator* MovementGeneratorFactory<Movement>::Create(void * /*data*/) const -{ - return (new Movement()); -} - -#endif diff --git a/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.cpp index 76b1aca3cc2..43638197578 100644 --- a/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.cpp @@ -20,8 +20,6 @@ #include "Creature.h" #include <G3D/g3dmath.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 9bb58419433..773d4dc03b7 100755 --- a/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.h +++ b/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.h @@ -31,8 +31,6 @@ class IdleMovementGenerator : public MovementGenerator MovementGeneratorType GetMovementGeneratorType() const override { return IDLE_MOTION_TYPE; } }; -TC_GAME_API extern IdleMovementGenerator si_idleMovement; - class RotateMovementGenerator : public MovementGenerator { public: diff --git a/src/server/shared/Dynamic/FactoryHolder.h b/src/server/shared/Dynamic/FactoryHolder.h index ce6622daea4..32c4343e503 100644 --- a/src/server/shared/Dynamic/FactoryHolder.h +++ b/src/server/shared/Dynamic/FactoryHolder.h @@ -24,23 +24,22 @@ /** FactoryHolder holds a factory object of a specific type */ -template<class T, class Key = std::string> +template<class T, class O, class Key = std::string> class FactoryHolder { public: - typedef ObjectRegistry<FactoryHolder<T, Key >, Key > FactoryHolderRegistry; + typedef ObjectRegistry<FactoryHolder<T, O, Key>, Key> FactoryHolderRegistry; - FactoryHolder(Key k) : i_key(k) { } + explicit FactoryHolder(Key const& k) : _key(k) { } virtual ~FactoryHolder() { } - inline Key key() const { return i_key; } + inline Key GetKey() const { return _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 = NULL) 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 @@ -52,6 +51,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/server/shared/Dynamic/ObjectRegistry.h b/src/server/shared/Dynamic/ObjectRegistry.h index 45380d699d3..89ca33f15fa 100644 --- a/src/server/shared/Dynamic/ObjectRegistry.h +++ b/src/server/shared/Dynamic/ObjectRegistry.h @@ -23,14 +23,15 @@ #include <string> #include <map> #include <vector> +#include <memory> /** ObjectRegistry holds all registry item of the same type */ template<class T, class Key = std::string> -class ObjectRegistry +class ObjectRegistry final { public: - typedef std::map<Key, T*> RegistryMapType; + typedef std::map<Key, std::unique_ptr<T>> RegistryMapType; static ObjectRegistry<T, Key>* instance() { @@ -39,71 +40,41 @@ class ObjectRegistry } /// 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() ? NULL : iter->second ); + auto itr = _registeredObjects.find(key); + if (itr == _registeredObjects.end()) + return nullptr; + return itr->second.get(); } /// 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<Key> &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 + 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 |