mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2026-03-08 18:20:29 +00:00
Merge branch 'azerothcore:master' into Playerbot
This commit is contained in:
@@ -26,11 +26,11 @@
|
||||
// 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())
|
||||
return PERMIT_BASE_PROACTIVE;
|
||||
return PERMIT_BASE_REACTIVE;
|
||||
|
||||
return PERMIT_BASE_NO;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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<uint32> 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();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -28,10 +28,14 @@
|
||||
#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<Guardian const*>(creature)->GetOwner()->GetTypeId() == TYPEID_PLAYER)
|
||||
return PERMIT_BASE_PROACTIVE;
|
||||
return PERMIT_BASE_REACTIVE;
|
||||
}
|
||||
|
||||
return PERMIT_BASE_NO;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -222,7 +222,7 @@ private:
|
||||
bool m_MoveInLineOfSight_locked;
|
||||
};
|
||||
|
||||
enum Permitions
|
||||
enum Permitions : int32
|
||||
{
|
||||
PERMIT_BASE_NO = -1,
|
||||
PERMIT_BASE_IDLE = 1,
|
||||
|
||||
@@ -19,60 +19,32 @@
|
||||
#define ACORE_CREATUREAIFACTORY_H
|
||||
|
||||
#include "FactoryHolder.h"
|
||||
#include "GameObjectAI.h"
|
||||
#include "ObjectRegistry.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;
|
||||
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<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;
|
||||
|
||||
//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;
|
||||
|
||||
int Permit(GameObject const* g) const { 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;
|
||||
typedef CreatureAICreator::FactoryHolderRegistry CreatureAIRegistry;
|
||||
#define sCreatureAIRegistry CreatureAIRegistry::instance()
|
||||
|
||||
#endif
|
||||
|
||||
@@ -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>("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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,132 +15,97 @@
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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 <class T, class Value>
|
||||
inline int32 GetPermitFor(T const* obj, Value const& value)
|
||||
{
|
||||
const CreatureAICreator* ai_factory = nullptr;
|
||||
CreatureAIRegistry& ai_registry(*CreatureAIRegistry::instance());
|
||||
|
||||
// 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");
|
||||
|
||||
//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");
|
||||
}
|
||||
|
||||
// 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<const SelectableAI*>(factory);
|
||||
ASSERT(p);
|
||||
int val = p->Permit(creature);
|
||||
if (val > best_val)
|
||||
{
|
||||
best_val = val;
|
||||
ai_factory = p;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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));
|
||||
Permissible<T> const* const p = ASSERT_NOTNULL(dynamic_cast<Permissible<T> const*>(value.second.get()));
|
||||
return p->Permit(obj);
|
||||
}
|
||||
|
||||
MovementGenerator* selectMovementGenerator(Creature* creature)
|
||||
template <class T>
|
||||
struct PermissibleOrderPred
|
||||
{
|
||||
MovementGeneratorRegistry& mv_registry(*MovementGeneratorRegistry::instance());
|
||||
ASSERT(creature->GetCreatureTemplate());
|
||||
const MovementGeneratorCreator* mv_factory = mv_registry.GetRegistryItem(creature->GetDefaultMovementType());
|
||||
public:
|
||||
PermissibleOrderPred(T const* obj) : _obj(obj) { }
|
||||
|
||||
/* if (mv_factory == nullptr)
|
||||
template <class Value>
|
||||
bool operator()(Value const& left, Value const& right) const
|
||||
{
|
||||
int best_val = -1;
|
||||
std::vector<std::string> l;
|
||||
mv_registry.GetRegisteredItems(l);
|
||||
for (std::vector<std::string>::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 != nullptr);
|
||||
int val = p->Permit(creature);
|
||||
if (val > best_val)
|
||||
{
|
||||
best_val = val;
|
||||
mv_factory = p;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
return GetPermitFor(_obj, left) < GetPermitFor(_obj, right);
|
||||
}
|
||||
|
||||
return (!mv_factory ? nullptr : mv_factory->Create(creature));
|
||||
private:
|
||||
T const* const _obj;
|
||||
};
|
||||
|
||||
template <class AI, class T>
|
||||
inline FactoryHolder<AI, T> const* SelectFactory(T* obj)
|
||||
{
|
||||
static_assert(std::is_same<AI, CreatureAI>::value || std::is_same<AI, GameObjectAI>::value, "Invalid template parameter");
|
||||
static_assert(std::is_same<AI, CreatureAI>::value == std::is_same<T, Creature>::value, "Incompatible AI for type");
|
||||
static_assert(std::is_same<AI, GameObjectAI>::value == std::is_same<T, GameObject>::value, "Incompatible AI for type");
|
||||
|
||||
using AIRegistry = typename FactoryHolder<AI, T>::FactoryHolderRegistry;
|
||||
|
||||
// AIName in db
|
||||
std::string const& aiName = obj->GetAIName();
|
||||
if (!aiName.empty())
|
||||
return AIRegistry::instance()->GetRegistryItem(aiName);
|
||||
|
||||
// select by permit check
|
||||
typename AIRegistry::RegistryMapType const& items = AIRegistry::instance()->GetRegisteredItems();
|
||||
auto itr = std::max_element(items.begin(), items.end(), PermissibleOrderPred<T>(obj));
|
||||
if (itr != items.end() && GetPermitFor(obj, *itr) >= 0)
|
||||
return itr->second.get();
|
||||
|
||||
// should _never_ happen, Null AI types defined as PERMIT_BASE_IDLE, it must've been found
|
||||
ABORT();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
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<CreatureAI>(creature)->Create(creature);
|
||||
}
|
||||
|
||||
MovementGenerator* SelectMovementGenerator(Unit* unit)
|
||||
{
|
||||
MovementGeneratorType type = IDLE_MOTION_TYPE;
|
||||
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);
|
||||
}
|
||||
|
||||
GameObjectAI* SelectGameObjectAI(GameObject* go)
|
||||
{
|
||||
const GameObjectAICreator* ai_factory = nullptr;
|
||||
GameObjectAIRegistry& ai_registry(*GameObjectAIRegistry::instance());
|
||||
|
||||
// scriptname in db
|
||||
if (GameObjectAI* scriptedAI = sScriptMgr->GetGameObjectAI(go))
|
||||
return scriptedAI;
|
||||
|
||||
ai_factory = ai_registry.GetRegistryItem(go->GetAIName());
|
||||
|
||||
//future goAI types go here
|
||||
|
||||
std::string ainame = (!ai_factory || go->GetScriptId()) ? "NullGameObjectAI" : ai_factory->key();
|
||||
LOG_DEBUG("scripts.ai", "GameObject {} used AI is {}.", go->GetGUID().ToString(), ainame);
|
||||
|
||||
return (!ai_factory ? new NullGameObjectAI(go) : ai_factory->Create(go));
|
||||
return SelectFactory<GameObjectAI>(go)->Create(go);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
51
src/server/game/AI/GameObjectAIFactory.h
Normal file
51
src/server/game/AI/GameObjectAIFactory.h
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef ACORE_GAMEOBJECTAIFACTORY_H
|
||||
#define ACORE_GAMEOBJECTAIFACTORY_H
|
||||
|
||||
#include "ObjectRegistry.h"
|
||||
#include "FactoryHolder.h"
|
||||
|
||||
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
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -763,13 +762,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 +1125,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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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<Creature*>& _list, float range);
|
||||
void DoFindFriendlyMissingBuff(std::list<Creature*>& list, float range, uint32 spellid);
|
||||
Unit* DoFindClosestFriendlyInRange(float range, bool playerOnly);
|
||||
void DoFindFriendlyCC(std::vector<Creature*>& creatures, float range) const;
|
||||
void DoFindFriendlyMissingBuff(std::vector<Creature*>& 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<uint32, uint32> CounterMap;
|
||||
CounterMap mCounterList;
|
||||
@@ -284,6 +272,8 @@ private:
|
||||
// Xinef: misc
|
||||
bool _allowPhaseReset;
|
||||
|
||||
ObjectVectorMap _storedTargets;
|
||||
|
||||
SMARTAI_TEMPLATE mTemplate;
|
||||
void InstallEvents();
|
||||
|
||||
|
||||
@@ -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<int8>(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:
|
||||
|
||||
@@ -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<uint32, SMART_ACTION_PARAM_COUNT> emotes;
|
||||
} randomEmote;
|
||||
|
||||
struct
|
||||
@@ -858,12 +863,7 @@ struct SmartAction
|
||||
|
||||
struct
|
||||
{
|
||||
uint32 phase1;
|
||||
uint32 phase2;
|
||||
uint32 phase3;
|
||||
uint32 phase4;
|
||||
uint32 phase5;
|
||||
uint32 phase6;
|
||||
std::array<uint32, SMART_ACTION_PARAM_COUNT> phases;
|
||||
} randomPhase;
|
||||
|
||||
struct
|
||||
@@ -1049,9 +1049,7 @@ struct SmartAction
|
||||
{
|
||||
uint32 entry;
|
||||
uint32 mask;
|
||||
uint32 slot1;
|
||||
uint32 slot2;
|
||||
uint32 slot3;
|
||||
std::array<uint32, MAX_EQUIPMENT_ITEMS> slots;
|
||||
} equip;
|
||||
|
||||
struct
|
||||
@@ -1086,12 +1084,7 @@ struct SmartAction
|
||||
|
||||
struct
|
||||
{
|
||||
uint32 entry1;
|
||||
uint32 entry2;
|
||||
uint32 entry3;
|
||||
uint32 entry4;
|
||||
uint32 entry5;
|
||||
uint32 entry6;
|
||||
std::array<uint32, SMART_ACTION_PARAM_COUNT> actionLists;
|
||||
} randTimedActionList;
|
||||
|
||||
struct
|
||||
@@ -1209,12 +1202,7 @@ struct SmartAction
|
||||
|
||||
struct
|
||||
{
|
||||
uint32 wp1;
|
||||
uint32 wp2;
|
||||
uint32 wp3;
|
||||
uint32 wp4;
|
||||
uint32 wp5;
|
||||
uint32 wp6;
|
||||
std::array<uint32, SMART_ACTION_PARAM_COUNT> 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<uint32, WayPoint*> WPPath;
|
||||
|
||||
typedef std::list<WorldObject*> ObjectList;
|
||||
typedef std::vector<WorldObject*> 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<uint32, ObjectGuidList*> ObjectListMap;
|
||||
typedef std::unordered_map<uint32, ObjectGuidVector> ObjectVectorMap;
|
||||
|
||||
class SmartWaypointMgr
|
||||
{
|
||||
|
||||
@@ -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();
|
||||
@@ -2861,7 +2861,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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -1001,7 +1001,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); }
|
||||
|
||||
|
||||
@@ -12573,8 +12573,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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<CreatureTemplate*>(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)
|
||||
{
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -16,7 +16,14 @@
|
||||
*/
|
||||
|
||||
#include "MovementGenerator.h"
|
||||
#include "IdleMovementGenerator.h"
|
||||
|
||||
MovementGenerator::~MovementGenerator()
|
||||
{
|
||||
}
|
||||
|
||||
MovementGenerator* IdleMovementFactory::Create(Unit* /*object*/) const
|
||||
{
|
||||
static IdleMovementGenerator instance;
|
||||
return &instance;
|
||||
}
|
||||
|
||||
@@ -82,19 +82,28 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
struct SelectableMovement : public FactoryHolder<MovementGenerator, MovementGeneratorType>
|
||||
typedef FactoryHolder<MovementGenerator, Unit, MovementGeneratorType> MovementGeneratorCreator;
|
||||
|
||||
template<class Movement>
|
||||
struct MovementGeneratorFactory : public MovementGeneratorCreator
|
||||
{
|
||||
SelectableMovement(MovementGeneratorType mgt) : FactoryHolder<MovementGenerator, MovementGeneratorType>(mgt) {}
|
||||
MovementGeneratorFactory(MovementGeneratorType movementGeneratorType) : MovementGeneratorCreator(movementGeneratorType) { }
|
||||
|
||||
MovementGenerator* Create(Unit* /*object*/) const
|
||||
{
|
||||
return new Movement();
|
||||
}
|
||||
};
|
||||
|
||||
template<class REAL_MOVEMENT>
|
||||
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<MovementGenerator, MovementGeneratorType> MovementGeneratorCreator;
|
||||
typedef FactoryHolder<MovementGenerator, MovementGeneratorType>::FactoryHolderRegistry MovementGeneratorRegistry;
|
||||
typedef MovementGeneratorCreator::FactoryHolderRegistry MovementGeneratorRegistry;
|
||||
|
||||
#define sMovementGeneratorRegistry MovementGeneratorRegistry::instance()
|
||||
|
||||
#endif
|
||||
|
||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef ACORE_MOVEMENTGENERATOR_IMPL_H
|
||||
#define ACORE_MOVEMENTGENERATOR_IMPL_H
|
||||
|
||||
#include "MovementGenerator.h"
|
||||
|
||||
template<class MOVEMENT_GEN>
|
||||
inline MovementGenerator*
|
||||
MovementGeneratorFactory<MOVEMENT_GEN>::Create(void* /*data*/) const
|
||||
{
|
||||
return (new MOVEMENT_GEN());
|
||||
}
|
||||
#endif
|
||||
@@ -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)
|
||||
|
||||
@@ -30,8 +30,6 @@ public:
|
||||
MovementGeneratorType GetMovementGeneratorType() override { return IDLE_MOTION_TYPE; }
|
||||
};
|
||||
|
||||
extern IdleMovementGenerator si_idleMovement;
|
||||
|
||||
class RotateMovementGenerator : public MovementGenerator
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -41,7 +41,7 @@ void PointMovementGenerator<T>::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<class T>
|
||||
void PointMovementGenerator<T>::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<T>::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);
|
||||
}
|
||||
|
||||
@@ -1568,6 +1568,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();
|
||||
|
||||
@@ -2036,9 +2039,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", " ");
|
||||
|
||||
Reference in New Issue
Block a user