TrinityCore
CreatureAISelector.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include "AIException.h"
19#include "AreaTrigger.h"
20#include "Creature.h"
21#include "CreatureAISelector.h"
22#include "CreatureAIFactory.h"
23#include "Log.h"
24#include "MovementGenerator.h"
25
26#include "GameObject.h"
27#include "GameObjectAIFactory.h"
28
29#include "AreaTriggerAI.h"
30
31#include "ScriptMgr.h"
32
34{
35 template <class T, class Value>
36 inline int32 GetPermitFor(T const* obj, Value const& value)
37 {
38 Permissible<T> const* const p = ASSERT_NOTNULL(dynamic_cast<Permissible<T> const*>(value.second.get()));
39 return p->Permit(obj);
40 }
41
42 template <class T>
44 {
45 public:
46 PermissibleOrderPred(T const* obj) : _obj(obj) { }
47
48 template <class Value>
49 bool operator()(Value const& left, Value const& right) const
50 {
51 return GetPermitFor(_obj, left) < GetPermitFor(_obj, right);
52 }
53
54 private:
55 T const* const _obj;
56 };
57
58 template <class AI, class T>
59 inline FactoryHolder<AI, T> const* SelectFactory(T const* obj)
60 {
61 static_assert(std::is_same<AI, CreatureAI>::value || std::is_same<AI, GameObjectAI>::value, "Invalid template parameter");
62 static_assert(std::is_same<AI, CreatureAI>::value == std::is_same<T, Creature>::value, "Incompatible AI for type");
63 static_assert(std::is_same<AI, GameObjectAI>::value == std::is_same<T, GameObject>::value, "Incompatible AI for type");
64
66
67 // AIName in db
68 std::string const& aiName = obj->GetAIName();
69 if (!aiName.empty())
70 return AIRegistry::instance()->GetRegistryItem(aiName);
71
72 // select by permit check
73 typename AIRegistry::RegistryMapType const& items = AIRegistry::instance()->GetRegisteredItems();
74 auto itr = std::max_element(items.begin(), items.end(), PermissibleOrderPred<T>(obj));
75 if (itr != items.end() && GetPermitFor(obj, *itr) >= 0)
76 return itr->second.get();
77
78 // should _never_ happen, Null AI types defined as PERMIT_BASE_IDLE, it must've been found
79 ABORT();
80 return nullptr;
81 }
82
84 {
85 // special pet case, if a tamed creature uses AIName (example SmartAI) we need to override it
86 if (creature->IsPet())
87 return ASSERT_NOTNULL(sCreatureAIRegistry->GetRegistryItem("PetAI"))->Create(creature);
88
89 // scriptname in db
90 try
91 {
92 if (CreatureAI* scriptedAI = sScriptMgr->GetCreatureAI(creature))
93 return scriptedAI;
94 }
95 catch (InvalidAIException const& e)
96 {
97 TC_LOG_ERROR("entities.unit", "Exception trying to assign script '{}' to Creature (Entry: {}), this Creature will have a default AI. Exception message: {}",
98 creature->GetScriptName(), creature->GetEntry(), e.what());
99 }
100
101 return SelectFactory<CreatureAI>(creature)->Create(creature);
102 }
103
105 {
106 if (creature->IsPet())
107 {
108 auto const* registry = ASSERT_NOTNULL(sCreatureAIRegistry->GetRegistryItem("PetAI"));
109 auto const* factory = dynamic_cast<SelectableAI<Creature, CreatureAI> const*>(registry);
110 ASSERT(factory);
111
112 return factory->GetScriptId();
113 }
114
115 if (uint32 id = creature->GetScriptId())
116 {
117 if (sScriptMgr->CanCreateCreatureAI(id))
118 {
119 return id;
120 }
121 }
122
123 auto const* factory = dynamic_cast<SelectableAI<Creature, CreatureAI> const*>(SelectFactory<CreatureAI>(creature));
124 ASSERT(factory);
125
126 return factory->GetScriptId();
127 }
128
130 {
132 if (Creature* creature = unit->ToCreature())
133 if (!creature->GetPlayerMovingMe())
134 type = creature->GetDefaultMovementType();
135
136 MovementGeneratorCreator const* mv_factory = sMovementGeneratorRegistry->GetRegistryItem(type);
137 return ASSERT_NOTNULL(mv_factory)->Create(unit);
138 }
139
141 {
142 // scriptname in db
143 if (GameObjectAI* scriptedAI = sScriptMgr->GetGameObjectAI(go))
144 return scriptedAI;
145
146 return SelectFactory<GameObjectAI>(go)->Create(go);
147 }
148
150 {
151 if (uint32 id = go->GetScriptId())
152 {
153 if (sScriptMgr->CanCreateGameObjectAI(id))
154 {
155 return id;
156 }
157 }
158
159 auto const* factory = dynamic_cast<SelectableAI<GameObject, GameObjectAI> const*>(SelectFactory<GameObjectAI>(go));
160 ASSERT(factory);
161
162 return factory->GetScriptId();
163 }
164
166 {
167 return sObjectMgr->GetScriptId("NullAreaTriggerAI", false);
168 }
169
171 {
172 if (AreaTriggerAI* ai = sScriptMgr->GetAreaTriggerAI(at))
173 return ai;
174 else
176 }
177
179 {
180 if (uint32 id = at->GetScriptId())
181 {
182 if (sScriptMgr->CanCreateAreaTriggerAI(id))
183 {
184 return id;
185 }
186 }
187
189 }
190}
#define sCreatureAIRegistry
int32_t int32
Definition: Define.h:138
uint32_t uint32
Definition: Define.h:142
#define ABORT
Definition: Errors.h:74
#define ASSERT_NOTNULL(pointer)
Definition: Errors.h:84
#define ASSERT
Definition: Errors.h:68
#define TC_LOG_ERROR(filterType__, message__,...)
Definition: Log.h:188
MovementGeneratorType
#define sMovementGeneratorRegistry
#define sObjectMgr
Definition: ObjectMgr.h:1979
#define sScriptMgr
Definition: ScriptMgr.h:1418
uint32 GetScriptId() const
uint32 GetScriptId() const
Definition: Creature.cpp:3146
std::string GetScriptName() const
Definition: Creature.cpp:3141
uint32 GetScriptId() const
T const * GetRegistryItem(Key const &key) const
Returns a registry item.
static Creature * ToCreature(Object *o)
Definition: Object.h:220
uint32 GetEntry() const
Definition: Object.h:162
virtual int32 Permit(T const *) const =0
Definition: Unit.h:628
virtual MovementGeneratorType GetDefaultMovementType() const
Definition: Unit.cpp:10347
bool IsPet() const
Definition: Unit.h:744
uint32 GetSelectedAIId(Creature const *creature)
MovementGenerator * SelectMovementGenerator(Unit *unit)
CreatureAI * SelectAI(Creature *creature)
static uint32 GetNullAreaTriggerAIScriptId()
GameObjectAI * SelectGameObjectAI(GameObject *go)
AreaTriggerAI * SelectAreaTriggerAI(AreaTrigger *at)
int32 GetPermitFor(T const *obj, Value const &value)
FactoryHolder< AI, T > const * SelectFactory(T const *obj)
bool operator()(Value const &left, Value const &right) const