TrinityCore
Loading...
Searching...
No Matches
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 {
134 MovementGeneratorCreator const* mv_factory = sMovementGeneratorRegistry->GetRegistryItem(unit->GetDefaultMovementType());
135 return ASSERT_NOTNULL(mv_factory)->Create(unit);
136 }
137
139 {
140 // scriptname in db
141 if (GameObjectAI* scriptedAI = sScriptMgr->GetGameObjectAI(go))
142 return scriptedAI;
143
144 return SelectFactory<GameObjectAI>(go)->Create(go);
145 }
146
148 {
149 if (uint32 id = go->GetScriptId())
150 {
151 if (sScriptMgr->CanCreateGameObjectAI(id))
152 {
153 return id;
154 }
155 }
156
157 auto const* factory = dynamic_cast<SelectableAI<GameObject, GameObjectAI> const*>(SelectFactory<GameObjectAI>(go));
158 ASSERT(factory);
159
160 return factory->GetScriptId();
161 }
162
164 {
165 return sObjectMgr->GetScriptId("NullAreaTriggerAI", false);
166 }
167
169 {
170 if (AreaTriggerAI* ai = sScriptMgr->GetAreaTriggerAI(at))
171 return ai;
172 else
174 }
175
177 {
178 if (uint32 id = at->GetScriptId())
179 {
180 if (sScriptMgr->CanCreateAreaTriggerAI(id))
181 {
182 return id;
183 }
184 }
185
187 }
188
190 {
191 return sObjectMgr->GetScriptId("NullConversationAI", false);
192 }
193
195 {
196 if (ConversationAI* ai = sScriptMgr->GetConversationAI(conversation))
197 return ai;
198
199 return new NullConversationAI(conversation, GetNullConversationAIScriptId());
200 }
201
203 {
204 if (uint32 id = conversation->GetScriptId())
205 {
206 if (sScriptMgr->CanCreateConversationAI(id))
207 return id;
208 }
209
211 }
212}
#define sCreatureAIRegistry
int32_t int32
Definition Define.h:150
uint32_t uint32
Definition Define.h:154
#define ABORT
Definition Errors.h:87
#define ASSERT_NOTNULL(pointer)
Definition Errors.h:82
#define ASSERT
Definition Errors.h:80
#define TC_LOG_ERROR(filterType__, message__,...)
Definition Log.h:190
#define sMovementGeneratorRegistry
#define sObjectMgr
Definition ObjectMgr.h:1885
#define sScriptMgr
Definition ScriptMgr.h:1449
uint32 GetScriptId() const
uint32 GetScriptId() const
uint32 GetScriptId() const
std::string GetScriptName() const
virtual T * Create(O *object=nullptr) const =0
Abstract Factory create method.
uint32 GetScriptId() const
T const * GetRegistryItem(Key const &key) const
Returns a registry item.
uint32 GetEntry() const
Definition Object.h:89
virtual int32 Permit(T const *) const =0
Definition Unit.h:635
virtual MovementGeneratorType GetDefaultMovementType() const
Definition Unit.cpp:10675
bool IsPet() const
Definition Unit.h:751
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