/*
* 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 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 .
*/
#include "CreatureAISelector.h"
#include "Creature.h"
#include "CreatureAIFactory.h"
#include "MovementGenerator.h"
#include "GameObject.h"
#include "ScriptMgr.h"
namespace FactorySelector
{
template
inline int32 GetPermitFor(T const* obj, Value const& value)
{
Permissible const* const p = ASSERT_NOTNULL(dynamic_cast const*>(value.second.get()));
return p->Permit(obj);
}
template
struct PermissibleOrderPred
{
public:
PermissibleOrderPred(T const* obj) : _obj(obj) { }
template
bool operator()(Value const& left, Value const& right) const
{
return GetPermitFor(_obj, left) < GetPermitFor(_obj, right);
}
private:
T const* const _obj;
};
template
inline FactoryHolder const* SelectFactory(T* obj)
{
static_assert(std::is_same::value || std::is_same::value, "Invalid template parameter");
static_assert(std::is_same::value == std::is_same::value, "Incompatible AI for type");
static_assert(std::is_same::value == std::is_same::value, "Incompatible AI for type");
using AIRegistry = typename FactoryHolder::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(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(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)
{
// scriptname in db
if (GameObjectAI* scriptedAI = sScriptMgr->GetGameObjectAI(go))
return scriptedAI;
return SelectFactory(go)->Create(go);
}
}