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 "Conversation.h"
32#include "ConversationAI.h"
33
34#include "ScriptMgr.h"
35
37{
38 template <class T, class Value>
39 inline int32 GetPermitFor(T const* obj, Value const& value)
40 {
41 Permissible<T> const* const p = ASSERT_NOTNULL(dynamic_cast<Permissible<T> const*>(value.second.get()));
42 return p->Permit(obj);
43 }
44
45 template <class T>
47 {
48 public:
49 PermissibleOrderPred(T const* obj) : _obj(obj) { }
50
51 template <class Value>
52 bool operator()(Value const& left, Value const& right) const
53 {
54 return GetPermitFor(_obj, left) < GetPermitFor(_obj, right);
55 }
56
57 private:
58 T const* const _obj;
59 };
60
61 template <class AI, class T>
62 inline FactoryHolder<AI, T> const* SelectFactory(T const* obj)
63 {
64 static_assert(std::is_same<AI, CreatureAI>::value || std::is_same<AI, GameObjectAI>::value, "Invalid template parameter");
65 static_assert(std::is_same<AI, CreatureAI>::value == std::is_same<T, Creature>::value, "Incompatible AI for type");
66 static_assert(std::is_same<AI, GameObjectAI>::value == std::is_same<T, GameObject>::value, "Incompatible AI for type");
67
69
70 // AIName in db
71 std::string const& aiName = obj->GetAIName();
72 if (!aiName.empty())
73 return AIRegistry::instance()->GetRegistryItem(aiName);
74
75 // select by permit check
76 typename AIRegistry::RegistryMapType const& items = AIRegistry::instance()->GetRegisteredItems();
77 auto itr = std::max_element(items.begin(), items.end(), PermissibleOrderPred<T>(obj));
78 if (itr != items.end() && GetPermitFor(obj, *itr) >= 0)
79 return itr->second.get();
80
81 // should _never_ happen, Null AI types defined as PERMIT_BASE_IDLE, it must've been found
82 ABORT();
83 return nullptr;
84 }
85
87 {
88 // special pet case, if a tamed creature uses AIName (example SmartAI) we need to override it
89 if (creature->IsPet())
90 return ASSERT_NOTNULL(sCreatureAIRegistry->GetRegistryItem("PetAI"))->Create(creature);
91
92 // scriptname in db
93 try
94 {
95 if (CreatureAI* scriptedAI = sScriptMgr->GetCreatureAI(creature))
96 return scriptedAI;
97 }
98 catch (InvalidAIException const& e)
99 {
100 TC_LOG_ERROR("entities.unit", "Exception trying to assign script '{}' to Creature (Entry: {}), this Creature will have a default AI. Exception message: {}",
101 creature->GetScriptName(), creature->GetEntry(), e.what());
102 }
103
104 return SelectFactory<CreatureAI>(creature)->Create(creature);
105 }
106
108 {
109 if (creature->IsPet())
110 {
111 auto const* registry = ASSERT_NOTNULL(sCreatureAIRegistry->GetRegistryItem("PetAI"));
112 auto const* factory = dynamic_cast<SelectableAI<Creature, CreatureAI> const*>(registry);
113 ASSERT(factory);
114
115 return factory->GetScriptId();
116 }
117
118 if (uint32 id = creature->GetScriptId())
119 {
120 if (sScriptMgr->CanCreateCreatureAI(id))
121 {
122 return id;
123 }
124 }
125
126 auto const* factory = dynamic_cast<SelectableAI<Creature, CreatureAI> const*>(SelectFactory<CreatureAI>(creature));
127 ASSERT(factory);
128
129 return factory->GetScriptId();
130 }
131
133 {
135 if (Creature* creature = unit->ToCreature())
136 if (!creature->GetPlayerMovingMe())
137 type = creature->GetDefaultMovementType();
138
139 MovementGeneratorCreator const* mv_factory = sMovementGeneratorRegistry->GetRegistryItem(type);
140 return ASSERT_NOTNULL(mv_factory)->Create(unit);
141 }
142
144 {
145 // scriptname in db
146 if (GameObjectAI* scriptedAI = sScriptMgr->GetGameObjectAI(go))
147 return scriptedAI;
148
149 return SelectFactory<GameObjectAI>(go)->Create(go);
150 }
151
153 {
154 if (uint32 id = go->GetScriptId())
155 {
156 if (sScriptMgr->CanCreateGameObjectAI(id))
157 {
158 return id;
159 }
160 }
161
162 auto const* factory = dynamic_cast<SelectableAI<GameObject, GameObjectAI> const*>(SelectFactory<GameObjectAI>(go));
163 ASSERT(factory);
164
165 return factory->GetScriptId();
166 }
167
169 {
170 return sObjectMgr->GetScriptId("NullAreaTriggerAI", false);
171 }
172
174 {
175 if (AreaTriggerAI* ai = sScriptMgr->GetAreaTriggerAI(at))
176 return ai;
177 else
179 }
180
182 {
183 if (uint32 id = at->GetScriptId())
184 {
185 if (sScriptMgr->CanCreateAreaTriggerAI(id))
186 {
187 return id;
188 }
189 }
190
192 }
193
195 {
196 return sObjectMgr->GetScriptId("NullConversationAI", false);
197 }
198
200 {
201 if (ConversationAI* ai = sScriptMgr->GetConversationAI(conversation))
202 return ai;
203
204 return new NullConversationAI(conversation, GetNullConversationAIScriptId());
205 }
206
208 {
209 if (uint32 id = conversation->GetScriptId())
210 {
211 if (sScriptMgr->CanCreateConversationAI(id))
212 return id;
213 }
214
216 }
217}
#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:1986
#define sScriptMgr
Definition: ScriptMgr.h:1417
uint32 GetScriptId() const
uint32 GetScriptId() const
uint32 GetScriptId() const
Definition: Creature.cpp:3166
std::string GetScriptName() const
Definition: Creature.cpp:3161
uint32 GetScriptId() const
T const * GetRegistryItem(Key const &key) const
Returns a registry item.
static Creature * ToCreature(Object *o)
Definition: Object.h:255
uint32 GetEntry() const
Definition: Object.h:197
virtual int32 Permit(T const *) const =0
Definition: Unit.h:631
virtual MovementGeneratorType GetDefaultMovementType() const
Definition: Unit.cpp:10428
bool IsPet() const
Definition: Unit.h:747
uint32 GetSelectedAIId(Creature const *creature)
MovementGenerator * SelectMovementGenerator(Unit *unit)
CreatureAI * SelectAI(Creature *creature)
ConversationAI * SelectConversationAI(Conversation *conversation)
static uint32 GetNullAreaTriggerAIScriptId()
GameObjectAI * SelectGameObjectAI(GameObject *go)
AreaTriggerAI * SelectAreaTriggerAI(AreaTrigger *at)
static uint32 GetNullConversationAIScriptId()
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