diff --git a/src/server/game/AI/AIException.cpp b/src/server/game/AI/AIException.cpp new file mode 100644 index 00000000000..ce3d601302f --- /dev/null +++ b/src/server/game/AI/AIException.cpp @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2008-2018 TrinityCore + * + * 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 "AIException.h" + +InvalidAIException::InvalidAIException(char const* _message) +{ + message().assign(_message); +} diff --git a/src/server/game/AI/AIException.h b/src/server/game/AI/AIException.h new file mode 100644 index 00000000000..265e5dddb5c --- /dev/null +++ b/src/server/game/AI/AIException.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2008-2018 TrinityCore + * + * 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 . + */ + +#ifndef TRINITY_AIEXCEPTION_H +#define TRINITY_AIEXCEPTION_H + +#include "Define.h" +#include +#include + +class TC_GAME_API InvalidAIException : public std::exception +{ +public: + InvalidAIException(char const* _message); + ~InvalidAIException() throw() { } + + char const* what() const noexcept override { return msg_.c_str(); } + +protected: + std::string & message() throw() { return msg_; } + +private: + std::string msg_; +}; + +#endif diff --git a/src/server/game/AI/CoreAI/PetAI.cpp b/src/server/game/AI/CoreAI/PetAI.cpp index 2283616df73..1068f2334fd 100644 --- a/src/server/game/AI/CoreAI/PetAI.cpp +++ b/src/server/game/AI/CoreAI/PetAI.cpp @@ -17,17 +17,20 @@ */ #include "PetAI.h" +#include "AIException.h" +#include "Creature.h" #include "Errors.h" +#include "Group.h" +#include "Log.h" +#include "MotionMaster.h" +#include "ObjectAccessor.h" #include "Pet.h" #include "Player.h" #include "Spell.h" -#include "ObjectAccessor.h" #include "SpellHistory.h" -#include "SpellMgr.h" -#include "Creature.h" -#include "Util.h" -#include "Group.h" #include "SpellInfo.h" +#include "SpellMgr.h" +#include "Util.h" int32 PetAI::Permissible(Creature const* creature) { @@ -43,6 +46,8 @@ int32 PetAI::Permissible(Creature const* creature) PetAI::PetAI(Creature* c) : CreatureAI(c), i_tracker(TIME_INTERVAL_LOOK) { + if (!me->GetCharmInfo()) + throw InvalidAIException("Creature doesn't have a valid charm info"); UpdateAllies(); } @@ -152,7 +157,7 @@ void PetAI::UpdateAI(uint32 diff) if (!spellInfo) continue; - if (me->GetCharmInfo() && me->GetSpellHistory()->HasGlobalCooldown(spellInfo)) + if (me->GetSpellHistory()->HasGlobalCooldown(spellInfo)) continue; // check spell cooldown diff --git a/src/server/game/AI/CreatureAISelector.cpp b/src/server/game/AI/CreatureAISelector.cpp index 17a9431a94f..88fedcda68b 100644 --- a/src/server/game/AI/CreatureAISelector.cpp +++ b/src/server/game/AI/CreatureAISelector.cpp @@ -16,6 +16,7 @@ * with this program. If not, see . */ +#include "AIException.h" #include "Creature.h" #include "CreatureAISelector.h" #include "CreatureAIFactory.h" @@ -84,8 +85,16 @@ namespace FactorySelector return ASSERT_NOTNULL(sCreatureAIRegistry->GetRegistryItem("PetAI"))->Create(creature); // scriptname in db - if (CreatureAI* scriptedAI = sScriptMgr->GetCreatureAI(creature)) - return scriptedAI; + try + { + if (CreatureAI* scriptedAI = sScriptMgr->GetCreatureAI(creature)) + return scriptedAI; + } + catch (InvalidAIException const& e) + { + TC_LOG_ERROR("entities.unit", "Exception trying to assign script '%s' to Creature (Entry: %u), this Creature will have a default AI. Exception message: %s", + creature->GetScriptName().c_str(), creature->GetEntry(), e.what()); + } return SelectFactory(creature)->Create(creature); }