2010-10-27 21:01:47 +02:00
/*
2020-01-02 06:44:10 +01:00
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
2010-10-27 21:01:47 +02:00
*
* 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 <http://www.gnu.org/licenses/>.
*/
2017-05-18 23:52:58 +02:00
#include "SmartScriptMgr.h"
2021-02-05 18:12:55 +01:00
#include "AreaTriggerDataStore.h"
#include "AreaTriggerTemplate.h"
2021-02-27 12:22:55 +02:00
#include "ConversationDataStore.h"
2017-05-18 23:52:58 +02:00
#include "CreatureTextMgr.h"
2020-09-04 13:38:24 +02:00
#include "DB2Stores.h"
2010-10-27 21:01:47 +02:00
#include "DatabaseEnv.h"
2011-12-11 16:22:18 +01:00
#include "GameEventMgr.h"
2017-05-18 23:52:58 +02:00
#include "InstanceScript.h"
#include "Log.h"
2018-06-03 10:06:57 -07:00
#include "MovementDefines.h"
2017-06-04 01:00:45 +02:00
#include "ObjectAccessor.h"
2017-05-18 23:52:58 +02:00
#include "ObjectMgr.h"
2013-09-02 17:48:17 +02:00
#include "SpellInfo.h"
2017-05-18 23:52:58 +02:00
#include "SpellMgr.h"
2017-06-04 01:00:45 +02:00
#include "Timer.h"
#include "UnitDefines.h"
2017-08-12 01:40:25 +02:00
#include "WaypointDefines.h"
2017-06-04 01:00:45 +02:00
#include <algorithm>
2010-10-27 21:01:47 +02:00
2016-03-11 17:11:05 +01:00
SmartWaypointMgr * SmartWaypointMgr :: instance ()
{
static SmartWaypointMgr instance ;
return & instance ;
}
2010-10-27 21:01:47 +02:00
void SmartWaypointMgr :: LoadFromDB ()
{
2010-12-19 17:06:33 +01:00
uint32 oldMSTime = getMSTime ();
2017-08-12 01:40:25 +02:00
_waypointStore . clear ();
2010-10-27 21:01:47 +02:00
2019-07-27 01:00:37 +02:00
WorldDatabasePreparedStatement * stmt = WorldDatabase . GetPreparedStatement ( WORLD_SEL_SMARTAI_WP );
2010-10-27 21:01:47 +02:00
PreparedQueryResult result = WorldDatabase . Query ( stmt );
if ( ! result )
{
2013-11-08 10:50:51 +01:00
TC_LOG_INFO ( "server.loading" , ">> Loaded 0 SmartAI Waypoint Paths. DB table `waypoints` is empty." );
2012-08-03 15:54:54 +02:00
2010-10-27 21:01:47 +02:00
return ;
}
uint32 count = 0 ;
uint32 total = 0 ;
2017-08-12 01:40:25 +02:00
uint32 lastEntry = 0 ;
uint32 lastId = 1 ;
2010-10-27 21:01:47 +02:00
do
{
2011-03-27 12:54:42 +02:00
Field * fields = result -> Fetch ();
2010-10-27 21:01:47 +02:00
uint32 entry = fields [ 0 ]. GetUInt32 ();
uint32 id = fields [ 1 ]. GetUInt32 ();
2017-08-12 01:40:25 +02:00
float x = fields [ 2 ]. GetFloat ();
float y = fields [ 3 ]. GetFloat ();
float z = fields [ 4 ]. GetFloat ();
2010-12-13 22:37:56 +01:00
2017-08-12 01:40:25 +02:00
if ( lastEntry != entry )
2010-10-27 21:01:47 +02:00
{
2017-08-12 01:40:25 +02:00
lastId = 1 ;
++ count ;
2010-10-27 21:01:47 +02:00
}
2011-11-26 01:53:44 +01:00
2017-08-12 01:40:25 +02:00
if ( lastId != id )
TC_LOG_ERROR ( "sql.sql" , "SmartWaypointMgr::LoadFromDB: Path entry %u, unexpected point id %u, expected %u." , entry , id , lastId );
++ lastId ;
2011-11-26 01:53:44 +01:00
2017-08-12 01:40:25 +02:00
WaypointPath & path = _waypointStore [ entry ];
path . id = entry ;
path . nodes . emplace_back ( id , x , y , z );
2010-10-27 21:01:47 +02:00
2017-08-12 01:40:25 +02:00
lastEntry = entry ;
++ total ;
2010-12-19 17:06:33 +01:00
}
while ( result -> NextRow ());
2010-10-27 21:01:47 +02:00
2013-11-08 10:50:51 +01:00
TC_LOG_INFO ( "server.loading" , ">> Loaded %u SmartAI waypoint paths (total %u waypoints) in %u ms" , count , total , GetMSTimeDiffToNow ( oldMSTime ));
2010-10-27 21:01:47 +02:00
}
2017-08-12 01:40:25 +02:00
WaypointPath const * SmartWaypointMgr :: GetPath ( uint32 id )
2016-11-25 00:31:10 +01:00
{
2017-08-12 01:40:25 +02:00
auto itr = _waypointStore . find ( id );
if ( itr != _waypointStore . end ())
return & itr -> second ;
return nullptr ;
2016-11-25 00:31:10 +01:00
}
2016-03-11 17:11:05 +01:00
SmartAIMgr * SmartAIMgr :: instance ()
{
static SmartAIMgr instance ;
return & instance ;
}
2010-10-27 21:01:47 +02:00
void SmartAIMgr :: LoadSmartAIFromDB ()
{
2013-12-11 18:53:05 +01:00
LoadHelperStores ();
2010-12-19 17:06:33 +01:00
uint32 oldMSTime = getMSTime ();
2010-10-27 21:01:47 +02:00
for ( uint8 i = 0 ; i < SMART_SCRIPT_TYPE_MAX ; i ++ )
mEventMap [ i ]. clear (); //Drop Existing SmartAI List
2019-07-27 01:00:37 +02:00
WorldDatabasePreparedStatement * stmt = WorldDatabase . GetPreparedStatement ( WORLD_SEL_SMART_SCRIPTS );
2010-10-27 21:01:47 +02:00
PreparedQueryResult result = WorldDatabase . Query ( stmt );
if ( ! result )
{
2013-11-08 10:50:51 +01:00
TC_LOG_INFO ( "server.loading" , ">> Loaded 0 SmartAI scripts. DB table `smartai_scripts` is empty." );
2010-10-27 21:01:47 +02:00
return ;
}
2010-12-19 17:06:33 +01:00
uint32 count = 0 ;
2010-10-27 21:01:47 +02:00
do
{
Field * fields = result -> Fetch ();
SmartScriptHolder temp ;
2014-10-26 02:57:28 +02:00
temp . entryOrGuid = fields [ 0 ]. GetInt64 ();
2011-02-20 19:11:42 +00:00
SmartScriptType source_type = ( SmartScriptType ) fields [ 1 ]. GetUInt8 ();
2010-10-27 21:01:47 +02:00
if ( source_type >= SMART_SCRIPT_TYPE_MAX )
{
2013-11-08 10:50:51 +01:00
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr::LoadSmartAIFromDB: invalid source_type (%u), skipped loading." , uint32 ( source_type ));
2010-10-27 21:01:47 +02:00
continue ;
}
if ( temp . entryOrGuid >= 0 )
{
2011-09-29 12:43:05 +02:00
switch ( source_type )
2010-10-27 21:01:47 +02:00
{
case SMART_SCRIPT_TYPE_CREATURE :
{
2014-10-04 16:19:25 +02:00
CreatureTemplate const * creatureInfo = sObjectMgr -> GetCreatureTemplate (( uint32 ) temp . entryOrGuid );
if ( ! creatureInfo )
2010-10-27 21:01:47 +02:00
{
2013-11-08 10:50:51 +01:00
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr::LoadSmartAIFromDB: Creature entry (%u) does not exist, skipped loading." , uint32 ( temp . entryOrGuid ));
2010-10-27 21:01:47 +02:00
continue ;
}
2014-10-04 16:19:25 +02:00
if ( creatureInfo -> AIName != "SmartAI" )
{
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr::LoadSmartAIFromDB: Creature entry (%u) is not using SmartAI, skipped loading." , uint32 ( temp . entryOrGuid ));
continue ;
}
2010-10-27 21:01:47 +02:00
break ;
}
case SMART_SCRIPT_TYPE_GAMEOBJECT :
{
2014-10-04 16:19:25 +02:00
GameObjectTemplate const * gameObjectInfo = sObjectMgr -> GetGameObjectTemplate (( uint32 ) temp . entryOrGuid );
if ( ! gameObjectInfo )
2010-10-27 21:01:47 +02:00
{
2013-11-08 10:50:51 +01:00
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr::LoadSmartAIFromDB: GameObject entry (%u) does not exist, skipped loading." , uint32 ( temp . entryOrGuid ));
2010-10-27 21:01:47 +02:00
continue ;
}
2014-10-04 16:19:25 +02:00
if ( gameObjectInfo -> AIName != "SmartGameObjectAI" )
{
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr::LoadSmartAIFromDB: GameObject entry (%u) is not using SmartGameObjectAI, skipped loading." , uint32 ( temp . entryOrGuid ));
continue ;
}
2010-10-27 21:01:47 +02:00
break ;
}
case SMART_SCRIPT_TYPE_AREATRIGGER :
{
if ( ! sAreaTriggerStore . LookupEntry (( uint32 ) temp . entryOrGuid ))
{
2013-11-08 10:50:51 +01:00
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr::LoadSmartAIFromDB: AreaTrigger entry (%u) does not exist, skipped loading." , uint32 ( temp . entryOrGuid ));
2010-10-27 21:01:47 +02:00
continue ;
}
break ;
}
2021-03-06 15:20:39 +02:00
case SMART_SCRIPT_TYPE_QUEST :
{
if ( ! sObjectMgr -> GetQuestTemplate (( uint32 ) temp . entryOrGuid ))
{
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr::LoadSmartAIFromDB: Quest entry (%u) does not exist, skipped loading." , uint32 ( temp . entryOrGuid ));
continue ;
}
break ;
}
2017-03-17 21:21:35 +01:00
case SMART_SCRIPT_TYPE_SCENE :
{
if ( ! sObjectMgr -> GetSceneTemplate (( uint32 ) temp . entryOrGuid ))
{
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr::LoadSmartAIFromDB: Scene id (%u) does not exist, skipped loading." , uint32 ( temp . entryOrGuid ));
continue ;
}
break ;
}
2010-11-03 14:10:16 +01:00
case SMART_SCRIPT_TYPE_TIMED_ACTIONLIST :
break ; //nothing to check, really
2021-02-05 18:12:55 +01:00
case SMART_SCRIPT_TYPE_AREATRIGGER_ENTITY :
{
if ( ! sAreaTriggerDataStore -> GetAreaTriggerTemplate ({ ( uint32 ) temp . entryOrGuid , false }))
{
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr::LoadSmartAIFromDB: AreaTrigger entry (%u IsServerSide false) does not exist, skipped loading." , uint32 ( temp . entryOrGuid ));
continue ;
}
break ;
}
case SMART_SCRIPT_TYPE_AREATRIGGER_ENTITY_SERVERSIDE :
{
if ( ! sAreaTriggerDataStore -> GetAreaTriggerTemplate ({ ( uint32 ) temp . entryOrGuid , true }))
{
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr::LoadSmartAIFromDB: AreaTrigger entry (%u IsServerSide true) does not exist, skipped loading." , uint32 ( temp . entryOrGuid ));
continue ;
}
break ;
}
2010-10-27 21:01:47 +02:00
default :
2013-11-08 10:50:51 +01:00
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr::LoadSmartAIFromDB: not yet implemented source_type %u" , ( uint32 ) source_type );
2010-10-27 21:01:47 +02:00
continue ;
}
2011-10-30 13:12:39 +00:00
}
else
2010-10-27 21:01:47 +02:00
{
2017-03-05 04:28:54 -03:00
switch ( source_type )
2010-10-27 21:01:47 +02:00
{
2017-03-05 04:28:54 -03:00
case SMART_SCRIPT_TYPE_CREATURE :
{
CreatureData const * creature = sObjectMgr -> GetCreatureData ( uint64 ( - temp . entryOrGuid ));
if ( ! creature )
{
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr::LoadSmartAIFromDB: Creature guid (" SI64FMTD ") does not exist, skipped loading." , - temp . entryOrGuid );
continue ;
}
2014-10-04 16:19:25 +02:00
2017-03-05 04:28:54 -03:00
CreatureTemplate const * creatureInfo = sObjectMgr -> GetCreatureTemplate ( creature -> id );
if ( ! creatureInfo )
{
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr::LoadSmartAIFromDB: Creature entry (%u) guid (" SI64FMTD ") does not exist, skipped loading." , creature -> id , - temp . entryOrGuid );
continue ;
}
2014-10-04 16:19:25 +02:00
2017-03-05 04:28:54 -03:00
if ( creatureInfo -> AIName != "SmartAI" )
{
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr::LoadSmartAIFromDB: Creature entry (%u) guid (" SI64FMTD ") is not using SmartAI, skipped loading." , creature -> id , - temp . entryOrGuid );
continue ;
}
break ;
}
case SMART_SCRIPT_TYPE_GAMEOBJECT :
{
2017-05-07 21:48:41 +01:00
GameObjectData const * gameObject = sObjectMgr -> GetGameObjectData ( uint64 ( - temp . entryOrGuid ));
2017-03-05 04:28:54 -03:00
if ( ! gameObject )
{
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr::LoadSmartAIFromDB: GameObject guid (" SI64FMTD ") does not exist, skipped loading." , - temp . entryOrGuid );
continue ;
}
GameObjectTemplate const * gameObjectInfo = sObjectMgr -> GetGameObjectTemplate ( gameObject -> id );
if ( ! gameObjectInfo )
{
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr::LoadSmartAIFromDB: GameObject entry (%u) guid (" SI64FMTD ") does not exist, skipped loading." , gameObject -> id , - temp . entryOrGuid );
continue ;
}
if ( gameObjectInfo -> AIName != "SmartGameObjectAI" )
{
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr::LoadSmartAIFromDB: GameObject entry (%u) guid (" SI64FMTD ") is not using SmartGameObjectAI, skipped loading." , gameObject -> id , - temp . entryOrGuid );
continue ;
}
break ;
}
default :
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr::LoadSmartAIFromDB: GUID-specific scripting not yet implemented for source_type %u" , ( uint32 ) source_type );
continue ;
2014-10-04 16:19:25 +02:00
}
2010-10-27 21:01:47 +02:00
}
2011-10-30 13:12:39 +00:00
2010-10-27 21:01:47 +02:00
temp . source_type = source_type ;
2011-02-20 19:11:42 +00:00
temp . event_id = fields [ 2 ]. GetUInt16 ();
temp . link = fields [ 3 ]. GetUInt16 ();
temp . event . type = ( SMART_EVENT ) fields [ 4 ]. GetUInt8 ();
2017-02-17 21:33:18 +01:00
temp . event . event_phase_mask = fields [ 5 ]. GetUInt16 ();
2011-02-20 19:11:42 +00:00
temp . event . event_chance = fields [ 6 ]. GetUInt8 ();
2016-09-02 23:14:50 +02:00
temp . event . event_flags = fields [ 7 ]. GetUInt16 ();
2010-10-27 21:01:47 +02:00
temp . event . raw . param1 = fields [ 8 ]. GetUInt32 ();
temp . event . raw . param2 = fields [ 9 ]. GetUInt32 ();
temp . event . raw . param3 = fields [ 10 ]. GetUInt32 ();
temp . event . raw . param4 = fields [ 11 ]. GetUInt32 ();
2019-04-30 13:03:49 +02:00
temp . event . raw . param5 = fields [ 12 ]. GetUInt32 ();
temp . event . param_string = fields [ 13 ]. GetString ();
temp . action . type = ( SMART_ACTION ) fields [ 14 ]. GetUInt8 ();
temp . action . raw . param1 = fields [ 15 ]. GetUInt32 ();
temp . action . raw . param2 = fields [ 16 ]. GetUInt32 ();
temp . action . raw . param3 = fields [ 17 ]. GetUInt32 ();
temp . action . raw . param4 = fields [ 18 ]. GetUInt32 ();
temp . action . raw . param5 = fields [ 19 ]. GetUInt32 ();
temp . action . raw . param6 = fields [ 20 ]. GetUInt32 ();
temp . target . type = ( SMARTAI_TARGETS ) fields [ 21 ]. GetUInt8 ();
temp . target . raw . param1 = fields [ 22 ]. GetUInt32 ();
temp . target . raw . param2 = fields [ 23 ]. GetUInt32 ();
temp . target . raw . param3 = fields [ 24 ]. GetUInt32 ();
temp . target . x = fields [ 25 ]. GetFloat ();
temp . target . y = fields [ 26 ]. GetFloat ();
temp . target . z = fields [ 27 ]. GetFloat ();
temp . target . o = fields [ 28 ]. GetFloat ();
2010-10-27 21:01:47 +02:00
//check target
if ( ! IsTargetValid ( temp ))
continue ;
// check all event and action params
if ( ! IsEventValid ( temp ))
continue ;
2017-02-17 21:33:18 +01:00
// specific check for timed events
switch ( temp . event . type )
{
case SMART_EVENT_UPDATE :
case SMART_EVENT_UPDATE_OOC :
case SMART_EVENT_UPDATE_IC :
case SMART_EVENT_HEALT_PCT :
case SMART_EVENT_TARGET_HEALTH_PCT :
case SMART_EVENT_MANA_PCT :
case SMART_EVENT_TARGET_MANA_PCT :
case SMART_EVENT_RANGE :
case SMART_EVENT_FRIENDLY_HEALTH :
case SMART_EVENT_FRIENDLY_HEALTH_PCT :
case SMART_EVENT_FRIENDLY_MISSING_BUFF :
case SMART_EVENT_HAS_AURA :
case SMART_EVENT_TARGET_BUFFED :
if ( temp . event . minMaxRepeat . repeatMin == 0 && temp . event . minMaxRepeat . repeatMax == 0 && ! ( temp . event . event_flags & SMART_EVENT_FLAG_NOT_REPEATABLE ) && temp . source_type != SMART_SCRIPT_TYPE_TIMED_ACTIONLIST )
{
temp . event . event_flags |= SMART_EVENT_FLAG_NOT_REPEATABLE ;
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr::LoadSmartAIFromDB: Entry " SI64FMTD " SourceType %u, Event %u, Missing Repeat flag." ,
temp . entryOrGuid , temp . GetScriptType (), temp . event_id );
}
break ;
case SMART_EVENT_VICTIM_CASTING :
case SMART_EVENT_IS_BEHIND_TARGET :
if ( temp . event . minMaxRepeat . min == 0 && temp . event . minMaxRepeat . max == 0 && ! ( temp . event . event_flags & SMART_EVENT_FLAG_NOT_REPEATABLE ) && temp . source_type != SMART_SCRIPT_TYPE_TIMED_ACTIONLIST )
{
temp . event . event_flags |= SMART_EVENT_FLAG_NOT_REPEATABLE ;
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr::LoadSmartAIFromDB: Entry " SI64FMTD " SourceType %u, Event %u, Missing Repeat flag." ,
temp . entryOrGuid , temp . GetScriptType (), temp . event_id );
}
break ;
case SMART_EVENT_FRIENDLY_IS_CC :
if ( temp . event . friendlyCC . repeatMin == 0 && temp . event . friendlyCC . repeatMax == 0 && ! ( temp . event . event_flags & SMART_EVENT_FLAG_NOT_REPEATABLE ) && temp . source_type != SMART_SCRIPT_TYPE_TIMED_ACTIONLIST )
{
temp . event . event_flags |= SMART_EVENT_FLAG_NOT_REPEATABLE ;
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr::LoadSmartAIFromDB: Entry " SI64FMTD " SourceType %u, Event %u, Missing Repeat flag." ,
temp . entryOrGuid , temp . GetScriptType (), temp . event_id );
}
break ;
default :
break ;
}
2010-10-27 21:01:47 +02:00
// creature entry / guid not found in storage, create empty event list for it and increase counters
if ( mEventMap [ source_type ]. find ( temp . entryOrGuid ) == mEventMap [ source_type ]. end ())
{
2010-12-19 17:06:33 +01:00
++ count ;
2010-10-27 21:01:47 +02:00
SmartAIEventList eventList ;
mEventMap [ source_type ][ temp . entryOrGuid ] = eventList ;
}
// store the new event
mEventMap [ source_type ][ temp . entryOrGuid ]. push_back ( temp );
2010-12-19 17:06:33 +01:00
}
while ( result -> NextRow ());
2010-10-27 21:01:47 +02:00
2014-10-11 18:52:01 +02:00
// Post Loading Validation
for ( uint8 i = 0 ; i < SMART_SCRIPT_TYPE_MAX ; ++ i )
2014-10-02 21:11:20 +02:00
{
2014-10-11 18:52:01 +02:00
for ( SmartAIEventMap :: iterator itr = mEventMap [ i ]. begin (); itr != mEventMap [ i ]. end (); ++ itr )
2014-10-02 21:11:20 +02:00
{
2014-10-11 18:52:01 +02:00
for ( SmartScriptHolder const & e : itr -> second )
2014-10-02 21:11:20 +02:00
{
2014-10-11 18:52:01 +02:00
if ( e . link )
2014-10-02 21:11:20 +02:00
{
2014-10-11 18:52:01 +02:00
if ( ! FindLinkedEvent ( itr -> second , e . link ))
2014-10-02 21:11:20 +02:00
{
2014-10-26 02:57:28 +02:00
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr::LoadSmartAIFromDB: Entry " SI64FMTD " SourceType %u, Event %u, Link Event %u not found or invalid." ,
2014-10-11 18:52:01 +02:00
e . entryOrGuid , e . GetScriptType (), e . event_id , e . link );
2014-10-02 21:11:20 +02:00
}
2014-10-11 18:52:01 +02:00
}
2014-10-02 22:24:59 +02:00
2014-10-11 18:52:01 +02:00
if ( e . GetEventType () == SMART_EVENT_LINK )
{
if ( ! FindLinkedSourceEvent ( itr -> second , e . event_id ))
{
2014-10-26 02:57:28 +02:00
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr::LoadSmartAIFromDB: Entry " SI64FMTD " SourceType %u, Event %u, Link Source Event not found or invalid. Event will never trigger." ,
2014-10-11 18:52:01 +02:00
e . entryOrGuid , e . GetScriptType (), e . event_id );
}
2014-10-02 21:11:20 +02:00
}
}
}
}
2013-11-08 10:50:51 +01:00
TC_LOG_INFO ( "server.loading" , ">> Loaded %u SmartAI scripts in %u ms" , count , GetMSTimeDiffToNow ( oldMSTime ));
2012-08-03 14:20:18 +02:00
2013-12-11 18:53:05 +01:00
UnLoadHelperStores ();
2010-10-27 21:01:47 +02:00
}
2017-05-18 23:52:58 +02:00
SmartAIEventList SmartAIMgr :: GetScript ( int32 entry , SmartScriptType type )
{
SmartAIEventList temp ;
if ( mEventMap [ uint32 ( type )]. find ( entry ) != mEventMap [ uint32 ( type )]. end ())
return mEventMap [ uint32 ( type )][ entry ];
else
{
if ( entry > 0 ) //first search is for guid (negative), do not drop error if not found
TC_LOG_DEBUG ( "scripts.ai" , "SmartAIMgr::GetScript: Could not load Script for Entry %d ScriptType %u." , entry , uint32 ( type ));
return temp ;
}
}
SmartScriptHolder & SmartAIMgr :: FindLinkedSourceEvent ( SmartAIEventList & list , uint32 eventId )
{
SmartAIEventList :: iterator itr = std :: find_if ( list . begin (), list . end (),
[ eventId ]( SmartScriptHolder & source ) { return source . link == eventId ; });
if ( itr != list . end ())
return * itr ;
static SmartScriptHolder SmartScriptHolderDummy ;
return SmartScriptHolderDummy ;
}
SmartScriptHolder & SmartAIMgr :: FindLinkedEvent ( SmartAIEventList & list , uint32 link )
{
SmartAIEventList :: iterator itr = std :: find_if ( list . begin (), list . end (),
[ link ]( SmartScriptHolder & linked ) { return linked . event_id == link && linked . GetEventType () == SMART_EVENT_LINK ; });
if ( itr != list . end ())
return * itr ;
static SmartScriptHolder SmartScriptHolderDummy ;
return SmartScriptHolderDummy ;
}
2018-02-13 16:38:28 +01:00
/*static*/ bool SmartAIMgr :: EventHasInvoker ( SMART_EVENT event )
{
switch ( event )
{ // white list of events that actually have an invoker passed to them
case SMART_EVENT_AGGRO :
case SMART_EVENT_DEATH :
case SMART_EVENT_KILL :
case SMART_EVENT_SUMMONED_UNIT :
case SMART_EVENT_SPELLHIT :
case SMART_EVENT_SPELLHIT_TARGET :
case SMART_EVENT_DAMAGED :
case SMART_EVENT_RECEIVE_HEAL :
case SMART_EVENT_RECEIVE_EMOTE :
case SMART_EVENT_JUST_SUMMONED :
case SMART_EVENT_DAMAGED_TARGET :
case SMART_EVENT_SUMMON_DESPAWNED :
case SMART_EVENT_PASSENGER_BOARDED :
case SMART_EVENT_PASSENGER_REMOVED :
case SMART_EVENT_GOSSIP_HELLO :
case SMART_EVENT_GOSSIP_SELECT :
case SMART_EVENT_ACCEPTED_QUEST :
case SMART_EVENT_REWARD_QUEST :
case SMART_EVENT_FOLLOW_COMPLETED :
case SMART_EVENT_ON_SPELLCLICK :
case SMART_EVENT_GO_LOOT_STATE_CHANGED :
case SMART_EVENT_AREATRIGGER_ONTRIGGER :
case SMART_EVENT_IC_LOS :
case SMART_EVENT_OOC_LOS :
case SMART_EVENT_DISTANCE_CREATURE :
case SMART_EVENT_FRIENDLY_HEALTH :
case SMART_EVENT_FRIENDLY_HEALTH_PCT :
case SMART_EVENT_FRIENDLY_IS_CC :
case SMART_EVENT_FRIENDLY_MISSING_BUFF :
case SMART_EVENT_ACTION_DONE :
case SMART_EVENT_TARGET_HEALTH_PCT :
case SMART_EVENT_TARGET_MANA_PCT :
case SMART_EVENT_RANGE :
case SMART_EVENT_VICTIM_CASTING :
case SMART_EVENT_TARGET_BUFFED :
case SMART_EVENT_IS_BEHIND_TARGET :
case SMART_EVENT_INSTANCE_PLAYER_ENTER :
case SMART_EVENT_TRANSPORT_ADDCREATURE :
2018-02-15 11:44:37 +01:00
case SMART_EVENT_DATA_SET :
2018-02-13 16:38:28 +01:00
case SMART_EVENT_QUEST_ACCEPTED :
case SMART_EVENT_QUEST_OBJ_COPLETETION :
case SMART_EVENT_QUEST_COMPLETION :
case SMART_EVENT_QUEST_FAIL :
case SMART_EVENT_QUEST_REWARDED :
case SMART_EVENT_SCENE_START :
case SMART_EVENT_SCENE_TRIGGER :
case SMART_EVENT_SCENE_CANCEL :
case SMART_EVENT_SCENE_COMPLETE :
return true ;
default :
return false ;
}
}
2011-05-12 10:40:53 +02:00
bool SmartAIMgr :: IsTargetValid ( SmartScriptHolder const & e )
2010-10-27 21:01:47 +02:00
{
2014-10-11 05:33:08 +02:00
if ( std :: abs ( e . target . o ) > 2 * float ( M_PI ))
2014-10-27 21:56:12 +00:00
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: Entry " SI64FMTD " SourceType %u Event %u Action %u has abs(`target.o` = %f) > 2*PI (orientation is expressed in radians)" ,
2014-10-11 18:56:58 +02:00
e . entryOrGuid , e . GetScriptType (), e . event_id , e . GetActionType (), e . target . o );
2014-10-11 05:33:08 +02:00
2010-10-27 21:01:47 +02:00
if ( e . GetActionType () == SMART_ACTION_INSTALL_AI_TEMPLATE )
2011-10-30 13:12:39 +00:00
return true ; // AI template has special handling
2014-10-11 18:52:01 +02:00
2010-10-27 21:01:47 +02:00
switch ( e . GetTargetType ())
{
case SMART_TARGET_CREATURE_DISTANCE :
case SMART_TARGET_CREATURE_RANGE :
2011-10-30 13:12:39 +00:00
{
if ( e . target . unitDistance . creature && ! sObjectMgr -> GetCreatureTemplate ( e . target . unitDistance . creature ))
2010-10-27 21:01:47 +02:00
{
2014-10-26 02:57:28 +02:00
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: Entry " SI64FMTD " SourceType %u Event %u Action %u uses non-existent Creature entry %u as target_param1, skipped." , e . entryOrGuid , e . GetScriptType (), e . event_id , e . GetActionType (), e . target . unitDistance . creature );
2011-10-30 13:12:39 +00:00
return false ;
2010-10-27 21:01:47 +02:00
}
2011-10-30 13:12:39 +00:00
break ;
}
2010-10-27 21:01:47 +02:00
case SMART_TARGET_GAMEOBJECT_DISTANCE :
case SMART_TARGET_GAMEOBJECT_RANGE :
2011-10-30 13:12:39 +00:00
{
if ( e . target . goDistance . entry && ! sObjectMgr -> GetGameObjectTemplate ( e . target . goDistance . entry ))
2010-10-27 21:01:47 +02:00
{
2014-10-26 02:57:28 +02:00
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: Entry " SI64FMTD " SourceType %u Event %u Action %u uses non-existent GameObject entry %u as target_param1, skipped." , e . entryOrGuid , e . GetScriptType (), e . event_id , e . GetActionType (), e . target . goDistance . entry );
2011-10-30 13:12:39 +00:00
return false ;
2010-10-27 21:01:47 +02:00
}
2011-10-30 13:12:39 +00:00
break ;
}
2010-10-27 21:01:47 +02:00
case SMART_TARGET_CREATURE_GUID :
2011-10-30 13:12:39 +00:00
{
2011-12-27 20:23:55 -05:00
if ( e . target . unitGUID . entry && ! IsCreatureValid ( e , e . target . unitGUID . entry ))
return false ;
2011-10-30 13:12:39 +00:00
break ;
}
2010-10-27 21:01:47 +02:00
case SMART_TARGET_GAMEOBJECT_GUID :
2011-10-30 13:12:39 +00:00
{
2012-02-18 16:52:08 +01:00
if ( e . target . goGUID . entry && ! IsGameObjectValid ( e , e . target . goGUID . entry ))
2011-12-27 20:23:55 -05:00
return false ;
2011-10-30 13:12:39 +00:00
break ;
}
case SMART_TARGET_PLAYER_DISTANCE :
case SMART_TARGET_CLOSEST_PLAYER :
{
if ( e . target . playerDistance . dist == 0 )
2010-10-27 21:01:47 +02:00
{
2014-10-26 02:57:28 +02:00
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: Entry " SI64FMTD " SourceType %u Event %u Action %u has maxDist 0 as target_param1, skipped." , e . entryOrGuid , e . GetScriptType (), e . event_id , e . GetActionType ());
2011-10-30 13:12:39 +00:00
return false ;
2010-10-27 21:01:47 +02:00
}
2011-10-30 13:12:39 +00:00
break ;
}
2018-02-13 16:38:28 +01:00
case SMART_TARGET_ACTION_INVOKER :
case SMART_TARGET_ACTION_INVOKER_VEHICLE :
case SMART_TARGET_INVOKER_PARTY :
if ( e . GetScriptType () != SMART_SCRIPT_TYPE_TIMED_ACTIONLIST && e . GetEventType () != SMART_EVENT_LINK && ! EventHasInvoker ( e . event . type ))
{
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: Entry " SI64FMTD " SourceType %u Event %u Action %u has invoker target, but action does not provide any invoker!" , e . entryOrGuid , e . GetScriptType (), e . GetEventType (), e . GetActionType ());
// allow this to load for now
// return false;
}
break ;
2010-10-27 21:01:47 +02:00
case SMART_TARGET_PLAYER_RANGE :
case SMART_TARGET_SELF :
case SMART_TARGET_VICTIM :
case SMART_TARGET_HOSTILE_SECOND_AGGRO :
case SMART_TARGET_HOSTILE_LAST_AGGRO :
case SMART_TARGET_HOSTILE_RANDOM :
case SMART_TARGET_HOSTILE_RANDOM_NOT_TOP :
case SMART_TARGET_POSITION :
case SMART_TARGET_NONE :
2010-11-07 18:02:33 +01:00
case SMART_TARGET_OWNER_OR_SUMMONER :
2010-11-20 12:42:10 +01:00
case SMART_TARGET_THREAT_LIST :
2011-10-30 13:12:39 +00:00
case SMART_TARGET_CLOSEST_GAMEOBJECT :
case SMART_TARGET_CLOSEST_CREATURE :
2013-08-07 19:59:06 +01:00
case SMART_TARGET_CLOSEST_ENEMY :
2013-08-15 01:22:22 +01:00
case SMART_TARGET_CLOSEST_FRIENDLY :
2011-12-27 20:23:55 -05:00
case SMART_TARGET_STORED :
2016-08-19 14:25:23 +02:00
case SMART_TARGET_LOOT_RECIPIENTS :
2017-02-17 21:33:18 +01:00
case SMART_TARGET_FARTHEST :
2018-01-16 23:58:41 +03:30
case SMART_TARGET_VEHICLE_PASSENGER :
2010-10-27 21:01:47 +02:00
break ;
default :
2014-10-26 02:57:28 +02:00
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: Not handled target_type(%u), Entry " SI64FMTD " SourceType %u Event %u Action %u, skipped." , e . GetTargetType (), e . entryOrGuid , e . GetScriptType (), e . event_id , e . GetActionType ());
2010-10-27 21:01:47 +02:00
return false ;
}
return true ;
}
2017-05-18 23:52:58 +02:00
bool SmartAIMgr :: IsMinMaxValid ( SmartScriptHolder const & e , uint32 min , uint32 max )
{
if ( max < min )
{
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: Entry " SI64FMTD " SourceType %u Event %u Action %u uses min/max params wrong (%u/%u), skipped." , e . entryOrGuid , e . GetScriptType (), e . event_id , e . GetActionType (), min , max );
return false ;
}
return true ;
}
bool SmartAIMgr :: NotNULL ( SmartScriptHolder const & e , uint32 data )
{
if ( ! data )
{
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: Entry " SI64FMTD " SourceType %u Event %u Action %u Parameter can not be NULL, skipped." , e . entryOrGuid , e . GetScriptType (), e . event_id , e . GetActionType ());
return false ;
}
return true ;
}
bool SmartAIMgr :: IsCreatureValid ( SmartScriptHolder const & e , uint32 entry )
{
if ( ! sObjectMgr -> GetCreatureTemplate ( entry ))
{
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: Entry " SI64FMTD " SourceType %u Event %u Action %u uses non-existent Creature entry %u, skipped." , e . entryOrGuid , e . GetScriptType (), e . event_id , e . GetActionType (), entry );
return false ;
}
return true ;
}
bool SmartAIMgr :: IsQuestValid ( SmartScriptHolder const & e , uint32 entry )
{
if ( ! sObjectMgr -> GetQuestTemplate ( entry ))
{
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: Entry " SI64FMTD " SourceType %u Event %u Action %u uses non-existent Quest entry %u, skipped." , e . entryOrGuid , e . GetScriptType (), e . event_id , e . GetActionType (), entry );
return false ;
}
return true ;
}
bool SmartAIMgr :: IsGameObjectValid ( SmartScriptHolder const & e , uint32 entry )
{
if ( ! sObjectMgr -> GetGameObjectTemplate ( entry ))
{
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: Entry " SI64FMTD " SourceType %u Event %u Action %u uses non-existent GameObject entry %u, skipped." , e . entryOrGuid , e . GetScriptType (), e . event_id , e . GetActionType (), entry );
return false ;
}
return true ;
}
bool SmartAIMgr :: IsSpellValid ( SmartScriptHolder const & e , uint32 entry )
{
2020-06-12 01:29:18 +02:00
if ( ! sSpellMgr -> GetSpellInfo ( entry , DIFFICULTY_NONE ))
2017-05-18 23:52:58 +02:00
{
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: Entry " SI64FMTD " SourceType %u Event %u Action %u uses non-existent Spell entry %u, skipped." , e . entryOrGuid , e . GetScriptType (), e . event_id , e . GetActionType (), entry );
return false ;
}
return true ;
}
bool SmartAIMgr :: IsItemValid ( SmartScriptHolder const & e , uint32 entry )
{
if ( ! sItemStore . LookupEntry ( entry ))
{
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: Entry " SI64FMTD " SourceType %u Event %u Action %u uses non-existent Item entry %u, skipped." , e . entryOrGuid , e . GetScriptType (), e . event_id , e . GetActionType (), entry );
return false ;
}
return true ;
}
bool SmartAIMgr :: IsTextEmoteValid ( SmartScriptHolder const & e , uint32 entry )
{
if ( ! sEmotesTextStore . LookupEntry ( entry ))
{
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: Entry " SI64FMTD " SourceType %u Event %u Action %u uses non-existent Text Emote entry %u, skipped." , e . entryOrGuid , e . GetScriptType (), e . event_id , e . GetActionType (), entry );
return false ;
}
return true ;
}
bool SmartAIMgr :: IsEmoteValid ( SmartScriptHolder const & e , uint32 entry )
{
if ( ! sEmotesStore . LookupEntry ( entry ))
{
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: Entry " SI64FMTD " SourceType %u Event %u Action %u uses non-existent Emote entry %u, skipped." , e . entryOrGuid , e . GetScriptType (), e . event_id , e . GetActionType (), entry );
return false ;
}
return true ;
}
bool SmartAIMgr :: IsAreaTriggerValid ( SmartScriptHolder const & e , uint32 entry )
{
if ( ! sAreaTriggerStore . LookupEntry ( entry ))
{
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: Entry " SI64FMTD " SourceType %u Event %u Action %u uses non-existent AreaTrigger entry %u, skipped." , e . entryOrGuid , e . GetScriptType (), e . event_id , e . GetActionType (), entry );
return false ;
}
return true ;
}
bool SmartAIMgr :: IsSoundValid ( SmartScriptHolder const & e , uint32 entry )
{
if ( ! sSoundKitStore . LookupEntry ( entry ))
{
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: Entry " SI64FMTD " SourceType %u Event %u Action %u uses non-existent Sound entry %u, skipped." , e . entryOrGuid , e . GetScriptType (), e . event_id , e . GetActionType (), entry );
return false ;
}
return true ;
}
bool SmartAIMgr :: IsAnimKitValid ( SmartScriptHolder const & e , uint32 entry )
{
if ( ! sAnimKitStore . LookupEntry ( entry ))
{
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: Entry " SI64FMTD " SourceType %u Event %u Action %u uses non-existent AnimKit entry %u, skipped." , e . entryOrGuid , e . GetScriptType (), e . event_id , e . GetActionType (), entry );
return false ;
}
return true ;
}
2019-09-01 15:51:01 +02:00
bool SmartAIMgr :: IsSpellVisualKitValid ( SmartScriptHolder const & e , uint32 entry )
{
if ( ! sSpellVisualKitStore . LookupEntry ( entry ))
{
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: Entry " SI64FMTD " SourceType %u Event %u Action %u uses non-existent SpellVisualKit entry %u, skipped." , e . entryOrGuid , e . GetScriptType (), e . event_id , e . GetActionType (), entry );
return false ;
}
return true ;
}
2011-08-18 14:55:27 -03:00
bool SmartAIMgr :: IsEventValid ( SmartScriptHolder & e )
2010-10-27 21:01:47 +02:00
{
if ( e . event . type >= SMART_EVENT_END )
{
2014-10-26 02:57:28 +02:00
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: EntryOrGuid " SI64FMTD " using event(%u) has invalid event type (%u), skipped." , e . entryOrGuid , e . event_id , e . GetEventType ());
2010-10-27 21:01:47 +02:00
return false ;
}
2014-10-11 18:52:01 +02:00
2010-11-03 14:10:16 +01:00
// in SMART_SCRIPT_TYPE_TIMED_ACTIONLIST all event types are overriden by core
if ( e . GetScriptType () != SMART_SCRIPT_TYPE_TIMED_ACTIONLIST && ! ( SmartAIEventMask [ e . event . type ][ 1 ] & SmartAITypeMask [ e . GetScriptType ()][ 1 ]))
2010-10-27 21:01:47 +02:00
{
2014-10-26 02:57:28 +02:00
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: EntryOrGuid " SI64FMTD ", event type %u can not be used for Script type %u" , e . entryOrGuid , e . GetEventType (), e . GetScriptType ());
2010-10-27 21:01:47 +02:00
return false ;
}
2014-10-11 18:52:01 +02:00
2012-05-20 16:13:52 +01:00
if ( e . action . type <= 0 || e . action . type >= SMART_ACTION_END )
2010-10-27 21:01:47 +02:00
{
2014-10-26 02:57:28 +02:00
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: EntryOrGuid " SI64FMTD " using event(%u) has invalid action type (%u), skipped." , e . entryOrGuid , e . event_id , e . GetActionType ());
2010-10-27 21:01:47 +02:00
return false ;
}
2014-10-11 18:52:01 +02:00
2010-10-27 21:01:47 +02:00
if ( e . event . event_phase_mask > SMART_EVENT_PHASE_ALL )
{
2014-10-26 02:57:28 +02:00
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: EntryOrGuid " SI64FMTD " using event(%u) has invalid phase mask (%u), skipped." , e . entryOrGuid , e . event_id , e . event . event_phase_mask );
2010-10-27 21:01:47 +02:00
return false ;
}
2014-10-11 18:52:01 +02:00
2012-05-20 16:13:52 +01:00
if ( e . event . event_flags > SMART_EVENT_FLAGS_ALL )
{
2014-10-26 02:57:28 +02:00
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: EntryOrGuid " SI64FMTD " using event(%u) has invalid event flags (%u), skipped." , e . entryOrGuid , e . event_id , e . event . event_flags );
2012-05-20 16:13:52 +01:00
return false ;
}
2014-10-11 18:52:01 +02:00
if ( e . link && e . link == e . event_id )
{
2014-10-26 02:57:28 +02:00
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: EntryOrGuid " SI64FMTD " SourceType %u, Event %u, Event is linking self (infinite loop), skipped." , e . entryOrGuid , e . GetScriptType (), e . event_id );
2014-10-11 18:52:01 +02:00
return false ;
}
2010-11-03 14:10:16 +01:00
if ( e . GetScriptType () == SMART_SCRIPT_TYPE_TIMED_ACTIONLIST )
2010-10-27 21:01:47 +02:00
{
2010-11-03 14:10:16 +01:00
e . event . type = SMART_EVENT_UPDATE_OOC ; //force default OOC, can change when calling the script!
2012-03-28 20:00:29 +08:00
if ( ! IsMinMaxValid ( e , e . event . minMaxRepeat . min , e . event . minMaxRepeat . max ))
return false ;
if ( ! IsMinMaxValid ( e , e . event . minMaxRepeat . repeatMin , e . event . minMaxRepeat . repeatMax ))
return false ;
2010-11-03 14:10:16 +01:00
}
else
{
2014-10-11 18:52:01 +02:00
switch ( e . GetEventType ())
2010-11-03 14:10:16 +01:00
{
case SMART_EVENT_UPDATE :
case SMART_EVENT_UPDATE_IC :
case SMART_EVENT_UPDATE_OOC :
case SMART_EVENT_HEALT_PCT :
case SMART_EVENT_MANA_PCT :
case SMART_EVENT_TARGET_HEALTH_PCT :
case SMART_EVENT_TARGET_MANA_PCT :
case SMART_EVENT_RANGE :
case SMART_EVENT_DAMAGED :
case SMART_EVENT_DAMAGED_TARGET :
case SMART_EVENT_RECEIVE_HEAL :
2012-03-28 20:00:29 +08:00
if ( ! IsMinMaxValid ( e , e . event . minMaxRepeat . min , e . event . minMaxRepeat . max ))
return false ;
if ( ! IsMinMaxValid ( e , e . event . minMaxRepeat . repeatMin , e . event . minMaxRepeat . repeatMax ))
return false ;
2010-11-03 14:10:16 +01:00
break ;
case SMART_EVENT_SPELLHIT :
case SMART_EVENT_SPELLHIT_TARGET :
if ( e . event . spellHit . spell )
2010-10-27 21:01:47 +02:00
{
2020-06-12 01:29:18 +02:00
SpellInfo const * spellInfo = sSpellMgr -> GetSpellInfo ( e . event . spellHit . spell , DIFFICULTY_NONE );
2011-08-20 20:31:31 -03:00
if ( ! spellInfo )
2010-11-03 14:10:16 +01:00
{
2014-10-26 02:57:28 +02:00
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: Entry " SI64FMTD " SourceType %u Event %u Action %u uses non-existent Spell entry %u, skipped." , e . entryOrGuid , e . GetScriptType (), e . event_id , e . GetActionType (), e . event . spellHit . spell );
2010-11-03 14:10:16 +01:00
return false ;
}
2011-08-20 20:31:31 -03:00
if ( e . event . spellHit . school && ( e . event . spellHit . school & spellInfo -> SchoolMask ) != spellInfo -> SchoolMask )
2010-11-03 14:10:16 +01:00
{
2014-10-26 02:57:28 +02:00
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: Entry " SI64FMTD " SourceType %u Event %u Action %u uses Spell entry %u with invalid school mask, skipped." , e . entryOrGuid , e . GetScriptType (), e . event_id , e . GetActionType (), e . event . spellHit . spell );
2010-11-03 14:10:16 +01:00
return false ;
}
2010-10-27 21:01:47 +02:00
}
2012-03-28 20:00:29 +08:00
if ( ! IsMinMaxValid ( e , e . event . spellHit . cooldownMin , e . event . spellHit . cooldownMax ))
return false ;
2010-11-03 14:10:16 +01:00
break ;
case SMART_EVENT_OOC_LOS :
case SMART_EVENT_IC_LOS :
2012-03-28 20:00:29 +08:00
if ( ! IsMinMaxValid ( e , e . event . los . cooldownMin , e . event . los . cooldownMax ))
return false ;
2010-11-03 14:10:16 +01:00
break ;
case SMART_EVENT_RESPAWN :
if ( e . event . respawn . type == SMART_SCRIPT_RESPAWN_CONDITION_MAP && ! sMapStore . LookupEntry ( e . event . respawn . map ))
2010-10-27 21:01:47 +02:00
{
2014-10-26 02:57:28 +02:00
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: Entry " SI64FMTD " SourceType %u Event %u Action %u uses non-existent Map entry %u, skipped." , e . entryOrGuid , e . GetScriptType (), e . event_id , e . GetActionType (), e . event . respawn . map );
2010-10-27 21:01:47 +02:00
return false ;
}
2016-02-02 19:13:04 +01:00
if ( e . event . respawn . type == SMART_SCRIPT_RESPAWN_CONDITION_AREA && ! sAreaTableStore . LookupEntry ( e . event . respawn . area ))
2010-10-27 21:01:47 +02:00
{
2014-10-26 02:57:28 +02:00
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: Entry " SI64FMTD " SourceType %u Event %u Action %u uses non-existent Area entry %u, skipped." , e . entryOrGuid , e . GetScriptType (), e . event_id , e . GetActionType (), e . event . respawn . area );
2010-10-27 21:01:47 +02:00
return false ;
}
break ;
2010-11-03 14:10:16 +01:00
case SMART_EVENT_FRIENDLY_HEALTH :
2013-09-01 10:49:29 +02:00
if ( ! NotNULL ( e , e . event . friendlyHealth . radius ))
2012-03-28 20:00:29 +08:00
return false ;
2013-09-01 10:49:29 +02:00
if ( ! IsMinMaxValid ( e , e . event . friendlyHealth . repeatMin , e . event . friendlyHealth . repeatMax ))
2012-03-28 20:00:29 +08:00
return false ;
2010-11-03 14:10:16 +01:00
break ;
case SMART_EVENT_FRIENDLY_IS_CC :
2012-03-28 20:00:29 +08:00
if ( ! IsMinMaxValid ( e , e . event . friendlyCC . repeatMin , e . event . friendlyCC . repeatMax ))
return false ;
2010-11-03 14:10:16 +01:00
break ;
case SMART_EVENT_FRIENDLY_MISSING_BUFF :
2010-10-27 21:01:47 +02:00
{
2012-03-28 20:00:29 +08:00
if ( ! IsSpellValid ( e , e . event . missingBuff . spell ))
return false ;
if ( ! NotNULL ( e , e . event . missingBuff . radius ))
return false ;
if ( ! IsMinMaxValid ( e , e . event . missingBuff . repeatMin , e . event . missingBuff . repeatMax ))
return false ;
2010-10-27 21:01:47 +02:00
break ;
}
2010-11-03 14:10:16 +01:00
case SMART_EVENT_KILL :
2012-03-28 20:00:29 +08:00
if ( ! IsMinMaxValid ( e , e . event . kill . cooldownMin , e . event . kill . cooldownMax ))
return false ;
if ( e . event . kill . creature && ! IsCreatureValid ( e , e . event . kill . creature ))
return false ;
2010-11-03 14:10:16 +01:00
break ;
2013-10-22 15:59:32 +02:00
case SMART_EVENT_VICTIM_CASTING :
2020-06-12 01:29:18 +02:00
if ( e . event . targetCasting . spellId > 0 && ! sSpellMgr -> GetSpellInfo ( e . event . targetCasting . spellId , DIFFICULTY_NONE ))
2013-09-01 10:49:29 +02:00
{
2014-10-26 02:57:28 +02:00
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: Entry " SI64FMTD " SourceType %u Event %u Action %u uses non-existent Spell entry %u, skipped." , e . entryOrGuid , e . GetScriptType (), e . event_id , e . GetActionType (), e . event . spellHit . spell );
2013-09-01 10:49:29 +02:00
return false ;
}
if ( ! IsMinMaxValid ( e , e . event . targetCasting . repeatMin , e . event . targetCasting . repeatMax ))
return false ;
break ;
2010-11-03 14:10:16 +01:00
case SMART_EVENT_PASSENGER_BOARDED :
case SMART_EVENT_PASSENGER_REMOVED :
2012-03-28 20:00:29 +08:00
if ( ! IsMinMaxValid ( e , e . event . minMax . repeatMin , e . event . minMax . repeatMax ))
return false ;
2010-11-03 14:10:16 +01:00
break ;
case SMART_EVENT_SUMMON_DESPAWNED :
case SMART_EVENT_SUMMONED_UNIT :
2012-03-28 20:00:29 +08:00
if ( e . event . summoned . creature && ! IsCreatureValid ( e , e . event . summoned . creature ))
return false ;
if ( ! IsMinMaxValid ( e , e . event . summoned . cooldownMin , e . event . summoned . cooldownMax ))
return false ;
2010-11-03 14:10:16 +01:00
break ;
case SMART_EVENT_ACCEPTED_QUEST :
case SMART_EVENT_REWARD_QUEST :
2011-10-24 23:21:34 +01:00
if ( e . event . quest . quest && ! IsQuestValid ( e , e . event . quest . quest ))
return false ;
2010-11-03 14:10:16 +01:00
break ;
case SMART_EVENT_RECEIVE_EMOTE :
2010-10-27 21:01:47 +02:00
{
2012-03-28 20:00:29 +08:00
if ( e . event . emote . emote && ! IsTextEmoteValid ( e , e . event . emote . emote ))
return false ;
if ( ! IsMinMaxValid ( e , e . event . emote . cooldownMin , e . event . emote . cooldownMax ))
return false ;
2010-10-27 21:01:47 +02:00
break ;
}
2010-11-03 14:10:16 +01:00
case SMART_EVENT_HAS_AURA :
case SMART_EVENT_TARGET_BUFFED :
2010-10-27 21:01:47 +02:00
{
2012-03-28 20:00:29 +08:00
if ( ! IsSpellValid ( e , e . event . aura . spell ))
return false ;
if ( ! IsMinMaxValid ( e , e . event . aura . repeatMin , e . event . aura . repeatMax ))
return false ;
2010-11-03 14:10:16 +01:00
break ;
}
case SMART_EVENT_TRANSPORT_ADDCREATURE :
2012-06-17 21:50:01 +01:00
{
if ( e . event . transportAddCreature . creature && ! IsCreatureValid ( e , e . event . transportAddCreature . creature ))
return false ;
break ;
}
2010-11-03 14:10:16 +01:00
case SMART_EVENT_MOVEMENTINFORM :
2012-06-17 21:50:01 +01:00
{
2018-04-23 23:35:31 +02:00
if ( IsInvalidMovementGeneratorType ( e . event . movementInform . type ))
2010-11-03 14:10:16 +01:00
{
2014-10-26 02:57:28 +02:00
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: Entry " SI64FMTD " SourceType %u Event %u Action %u uses invalid Motion type %u, skipped." , e . entryOrGuid , e . GetScriptType (), e . event_id , e . GetActionType (), e . event . movementInform . type );
2012-06-17 21:50:01 +01:00
return false ;
2010-10-27 21:01:47 +02:00
}
2012-06-17 21:50:01 +01:00
break ;
}
2010-11-03 14:10:16 +01:00
case SMART_EVENT_DATA_SET :
2012-06-17 21:50:01 +01:00
{
if ( ! IsMinMaxValid ( e , e . event . dataSet . cooldownMin , e . event . dataSet . cooldownMax ))
return false ;
break ;
}
2010-11-03 14:10:16 +01:00
case SMART_EVENT_AREATRIGGER_ONTRIGGER :
2012-06-17 21:50:01 +01:00
{
2021-02-05 18:12:55 +01:00
if ( e . event . areatrigger . id && ( e . GetScriptType () == SMART_SCRIPT_TYPE_AREATRIGGER_ENTITY || e . GetScriptType () == SMART_SCRIPT_TYPE_AREATRIGGER_ENTITY_SERVERSIDE ))
{
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: Entry " SI64FMTD " SourceType %u Event %u Action %u areatrigger param not supported for SMART_SCRIPT_TYPE_AREATRIGGER_ENTITY and SMART_SCRIPT_TYPE_AREATRIGGER_ENTITY_SERVERSIDE, skipped." , e . entryOrGuid , e . GetScriptType (), e . event_id , e . GetActionType ());
return false ;
}
2012-06-17 21:50:01 +01:00
if ( e . event . areatrigger . id && ! IsAreaTriggerValid ( e , e . event . areatrigger . id ))
return false ;
break ;
}
2010-11-03 14:10:16 +01:00
case SMART_EVENT_TEXT_OVER :
2014-10-11 18:52:01 +02:00
if ( ! IsTextValid ( e , e . event . textOver . textGroupID ))
2012-06-17 21:50:01 +01:00
return false ;
break ;
2017-06-10 19:17:41 -03:00
case SMART_EVENT_EVENT_PHASE_CHANGE :
{
if ( ! e . event . eventPhaseChange . phasemask )
{
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: Entry " SI64FMTD " SourceType %u Event %u Action %u has no param set, event won't be executed!." , e . entryOrGuid , e . GetScriptType (), e . event_id , e . GetActionType ());
return false ;
}
if ( e . event . eventPhaseChange . phasemask > SMART_EVENT_PHASE_ALL )
{
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: Entry " SI64FMTD " SourceType %u Event %u Action %u uses invalid phasemask %u, skipped." , e . entryOrGuid , e . GetScriptType (), e . event_id , e . GetActionType (), e . event . eventPhaseChange . phasemask );
return false ;
}
if ( e . event . event_phase_mask && ! ( e . event . event_phase_mask & e . event . eventPhaseChange . phasemask ))
{
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: Entry " SI64FMTD " SourceType %u Event %u Action %u uses event phasemask %u and incompatible event_param1 %u, skipped." , e . entryOrGuid , e . GetScriptType (), e . event_id , e . GetActionType (), e . event . event_phase_mask , e . event . eventPhaseChange . phasemask );
return false ;
}
break ;
}
2011-04-14 00:30:32 -03:00
case SMART_EVENT_IS_BEHIND_TARGET :
2012-06-17 21:50:01 +01:00
{
2011-04-14 00:30:32 -03:00
if ( ! IsMinMaxValid ( e , e . event . behindTarget . cooldownMin , e . event . behindTarget . cooldownMax ))
return false ;
break ;
2012-06-17 21:50:01 +01:00
}
2011-12-11 16:22:18 +01:00
case SMART_EVENT_GAME_EVENT_START :
case SMART_EVENT_GAME_EVENT_END :
2012-06-17 21:50:01 +01:00
{
GameEventMgr :: GameEventDataMap const & events = sGameEventMgr -> GetEventMap ();
if ( e . event . gameEvent . gameEventId >= events . size () || ! events [ e . event . gameEvent . gameEventId ]. isValid ())
return false ;
break ;
}
case SMART_EVENT_ACTION_DONE :
{
2012-06-19 00:07:20 +02:00
if ( e . event . doAction . eventId > EVENT_CHARGE )
2011-12-11 16:22:18 +01:00
{
2014-10-26 02:57:28 +02:00
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: Entry " SI64FMTD " SourceType %u Event %u Action %u uses invalid event id %u, skipped." , e . entryOrGuid , e . GetScriptType (), e . event_id , e . GetActionType (), e . event . doAction . eventId );
2012-06-17 21:50:01 +01:00
return false ;
2011-12-11 16:22:18 +01:00
}
2012-06-17 21:50:01 +01:00
break ;
}
2013-08-15 01:18:10 +01:00
case SMART_EVENT_FRIENDLY_HEALTH_PCT :
2013-09-01 10:49:29 +02:00
if ( ! IsMinMaxValid ( e , e . event . friendlyHealthPct . repeatMin , e . event . friendlyHealthPct . repeatMax ))
2013-08-15 01:18:10 +01:00
return false ;
2013-09-01 10:49:29 +02:00
if ( e . event . friendlyHealthPct . maxHpPct > 100 || e . event . friendlyHealthPct . minHpPct > 100 )
2013-08-15 01:18:10 +01:00
{
2014-10-26 02:57:28 +02:00
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: Entry " SI64FMTD " SourceType %u Event %u Action %u has pct value above 100, skipped." , e . entryOrGuid , e . GetScriptType (), e . event_id , e . GetActionType ());
2013-08-15 01:18:10 +01:00
return false ;
}
switch ( e . GetTargetType ())
{
case SMART_TARGET_CREATURE_RANGE :
case SMART_TARGET_CREATURE_GUID :
case SMART_TARGET_CREATURE_DISTANCE :
case SMART_TARGET_CLOSEST_CREATURE :
case SMART_TARGET_CLOSEST_PLAYER :
case SMART_TARGET_PLAYER_RANGE :
case SMART_TARGET_PLAYER_DISTANCE :
break ;
default :
2014-10-26 02:57:28 +02:00
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: Entry " SI64FMTD " SourceType %u Event %u Action %u uses invalid target_type %u, skipped." , e . entryOrGuid , e . GetScriptType (), e . event_id , e . GetActionType (), e . GetTargetType ());
2013-08-15 01:18:10 +01:00
return false ;
}
break ;
2014-03-17 16:58:10 -04:00
case SMART_EVENT_DISTANCE_CREATURE :
if ( e . event . distance . guid == 0 && e . event . distance . entry == 0 )
{
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: Event SMART_EVENT_DISTANCE_CREATURE did not provide creature guid or entry, skipped." );
return false ;
}
if ( e . event . distance . guid != 0 && e . event . distance . entry != 0 )
{
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: Event SMART_EVENT_DISTANCE_CREATURE provided both an entry and guid, skipped." );
return false ;
}
if ( e . event . distance . guid != 0 && ! sObjectMgr -> GetCreatureData ( e . event . distance . guid ))
{
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: Event SMART_EVENT_DISTANCE_CREATURE using invalid creature guid %u, skipped." , e . event . distance . guid );
return false ;
}
if ( e . event . distance . entry != 0 && ! sObjectMgr -> GetCreatureTemplate ( e . event . distance . entry ))
{
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: Event SMART_EVENT_DISTANCE_CREATURE using invalid creature entry %u, skipped." , e . event . distance . entry );
return false ;
}
break ;
case SMART_EVENT_DISTANCE_GAMEOBJECT :
if ( e . event . distance . guid == 0 && e . event . distance . entry == 0 )
{
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: Event SMART_EVENT_DISTANCE_GAMEOBJECT did not provide gameobject guid or entry, skipped." );
return false ;
}
if ( e . event . distance . guid != 0 && e . event . distance . entry != 0 )
{
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: Event SMART_EVENT_DISTANCE_GAMEOBJECT provided both an entry and guid, skipped." );
return false ;
}
2017-05-07 21:48:41 +01:00
if ( e . event . distance . guid != 0 && ! sObjectMgr -> GetGameObjectData ( e . event . distance . guid ))
2014-03-17 16:58:10 -04:00
{
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: Event SMART_EVENT_DISTANCE_GAMEOBJECT using invalid gameobject guid %u, skipped." , e . event . distance . guid );
return false ;
}
if ( e . event . distance . entry != 0 && ! sObjectMgr -> GetGameObjectTemplate ( e . event . distance . entry ))
{
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: Event SMART_EVENT_DISTANCE_GAMEOBJECT using invalid gameobject entry %u, skipped." , e . event . distance . entry );
return false ;
}
break ;
2015-04-02 18:02:34 +02:00
case SMART_EVENT_COUNTER_SET :
if ( ! IsMinMaxValid ( e , e . event . counter . cooldownMin , e . event . counter . cooldownMax ))
return false ;
if ( e . event . counter . id == 0 )
{
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: Event SMART_EVENT_COUNTER_SET using invalid counter id %u, skipped." , e . event . counter . id );
return false ;
}
if ( e . event . counter . value == 0 )
{
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: Event SMART_EVENT_COUNTER_SET using invalid value %u, skipped." , e . event . counter . value );
return false ;
}
break ;
2021-03-06 15:20:39 +02:00
case SMART_EVENT_QUEST_OBJ_COPLETETION :
if ( ! sObjectMgr -> GetQuestObjective ( e . event . questObjective . id ))
{
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: Event SMART_EVENT_QUEST_OBJ_COPLETETION using invalid objective id %u, skipped." , e . event . questObjective . id );
return false ;
}
break ;
case SMART_EVENT_QUEST_ACCEPTED :
case SMART_EVENT_QUEST_COMPLETION :
case SMART_EVENT_QUEST_REWARDED :
case SMART_EVENT_QUEST_FAIL :
break ;
2014-10-11 18:52:01 +02:00
case SMART_EVENT_LINK :
2017-05-01 18:19:36 -03:00
case SMART_EVENT_GO_LOOT_STATE_CHANGED :
2012-06-11 11:10:46 +02:00
case SMART_EVENT_GO_EVENT_INFORM :
2010-11-03 14:10:16 +01:00
case SMART_EVENT_TIMED_EVENT_TRIGGERED :
case SMART_EVENT_INSTANCE_PLAYER_ENTER :
case SMART_EVENT_TRANSPORT_RELOCATE :
case SMART_EVENT_CHARMED :
case SMART_EVENT_CHARMED_TARGET :
case SMART_EVENT_CORPSE_REMOVED :
case SMART_EVENT_AI_INIT :
case SMART_EVENT_TRANSPORT_ADDPLAYER :
case SMART_EVENT_TRANSPORT_REMOVE_PLAYER :
case SMART_EVENT_AGGRO :
case SMART_EVENT_DEATH :
case SMART_EVENT_EVADE :
case SMART_EVENT_REACHED_HOME :
case SMART_EVENT_RESET :
case SMART_EVENT_JUST_SUMMONED :
case SMART_EVENT_WAYPOINT_START :
case SMART_EVENT_WAYPOINT_REACHED :
case SMART_EVENT_WAYPOINT_PAUSED :
case SMART_EVENT_WAYPOINT_RESUMED :
case SMART_EVENT_WAYPOINT_STOPPED :
case SMART_EVENT_WAYPOINT_ENDED :
case SMART_EVENT_GOSSIP_SELECT :
case SMART_EVENT_GOSSIP_HELLO :
case SMART_EVENT_JUST_CREATED :
2010-11-17 23:24:21 +01:00
case SMART_EVENT_FOLLOW_COMPLETED :
2012-06-19 00:07:20 +02:00
case SMART_EVENT_ON_SPELLCLICK :
2017-03-17 21:21:35 +01:00
case SMART_EVENT_SCENE_START :
case SMART_EVENT_SCENE_CANCEL :
case SMART_EVENT_SCENE_COMPLETE :
case SMART_EVENT_SCENE_TRIGGER :
2010-11-03 14:10:16 +01:00
break ;
2010-12-13 22:37:56 +01:00
default :
2014-10-26 02:57:28 +02:00
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: Not handled event_type(%u), Entry " SI64FMTD " SourceType %u Event %u Action %u, skipped." , e . GetEventType (), e . entryOrGuid , e . GetScriptType (), e . event_id , e . GetActionType ());
2010-11-03 14:10:16 +01:00
return false ;
}
2010-10-27 21:01:47 +02:00
}
2010-11-03 14:10:16 +01:00
2010-10-27 21:01:47 +02:00
switch ( e . GetActionType ())
{
2014-10-03 16:02:11 +02:00
case SMART_ACTION_TALK :
2014-10-11 18:52:01 +02:00
case SMART_ACTION_SIMPLE_TALK :
if ( ! IsTextValid ( e , e . action . talk . textGroupID ))
return false ;
2014-10-03 16:02:11 +02:00
break ;
2010-10-27 21:01:47 +02:00
case SMART_ACTION_SET_FACTION :
2011-08-26 05:15:38 +01:00
if ( e . action . faction . factionID && ! sFactionTemplateStore . LookupEntry ( e . action . faction . factionID ))
2010-10-27 21:01:47 +02:00
{
2014-10-26 02:57:28 +02:00
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: Entry " SI64FMTD " SourceType %u Event %u Action %u uses non-existent Faction %u, skipped." , e . entryOrGuid , e . GetScriptType (), e . event_id , e . GetActionType (), e . action . faction . factionID );
2010-10-27 21:01:47 +02:00
return false ;
}
break ;
case SMART_ACTION_MORPH_TO_ENTRY_OR_MODEL :
case SMART_ACTION_MOUNT_TO_ENTRY_OR_MODEL :
if ( e . action . morphOrMount . creature || e . action . morphOrMount . model )
{
2011-04-28 22:57:08 +02:00
if ( e . action . morphOrMount . creature > 0 && ! sObjectMgr -> GetCreatureTemplate ( e . action . morphOrMount . creature ))
2010-10-27 21:01:47 +02:00
{
2014-10-26 02:57:28 +02:00
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: Entry " SI64FMTD " SourceType %u Event %u Action %u uses non-existent Creature entry %u, skipped." , e . entryOrGuid , e . GetScriptType (), e . event_id , e . GetActionType (), e . action . morphOrMount . creature );
2010-10-27 21:01:47 +02:00
return false ;
}
if ( e . action . morphOrMount . model )
{
if ( e . action . morphOrMount . creature )
{
2014-10-26 02:57:28 +02:00
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: Entry " SI64FMTD " SourceType %u Event %u Action %u has ModelID set with also set CreatureId, skipped." , e . entryOrGuid , e . GetScriptType (), e . event_id , e . GetActionType ());
2010-10-27 21:01:47 +02:00
return false ;
}
else if ( ! sCreatureDisplayInfoStore . LookupEntry ( e . action . morphOrMount . model ))
{
2014-10-26 02:57:28 +02:00
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: Entry " SI64FMTD " SourceType %u Event %u Action %u uses non-existent Model id %u, skipped." , e . entryOrGuid , e . GetScriptType (), e . event_id , e . GetActionType (), e . action . morphOrMount . model );
2010-10-27 21:01:47 +02:00
return false ;
}
}
}
break ;
case SMART_ACTION_SOUND :
2011-10-24 23:21:34 +01:00
if ( ! IsSoundValid ( e , e . action . sound . sound ))
return false ;
2010-10-27 21:01:47 +02:00
break ;
case SMART_ACTION_SET_EMOTE_STATE :
case SMART_ACTION_PLAY_EMOTE :
2012-03-28 20:00:29 +08:00
if ( ! IsEmoteValid ( e , e . action . emote . emote ))
return false ;
2010-10-27 21:01:47 +02:00
break ;
2017-03-11 13:39:38 +01:00
case SMART_ACTION_PLAY_ANIMKIT :
2017-03-21 23:27:07 +01:00
if ( e . action . animKit . animKit && ! IsAnimKitValid ( e , e . action . animKit . animKit ))
2017-03-11 13:39:38 +01:00
return false ;
if ( e . action . animKit . type > 3 )
{
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: Entry " SI64FMTD " SourceType %u Event %u Action %u uses invalid AnimKit type %u, skipped." , e . entryOrGuid , e . GetScriptType (), e . event_id , e . GetActionType (), e . action . animKit . type );
return false ;
}
break ;
2019-09-01 15:51:01 +02:00
case SMART_ACTION_PLAY_SPELL_VISUAL_KIT :
if ( e . action . spellVisualKit . spellVisualKitId && ! IsSpellVisualKitValid ( e , e . action . spellVisualKit . spellVisualKitId ))
return false ;
break ;
2010-10-27 21:01:47 +02:00
case SMART_ACTION_FAIL_QUEST :
2016-08-19 23:01:03 +02:00
case SMART_ACTION_OFFER_QUEST :
2012-03-28 20:00:29 +08:00
if ( ! e . action . quest . quest || ! IsQuestValid ( e , e . action . quest . quest ))
return false ;
2010-10-27 21:01:47 +02:00
break ;
2010-11-19 20:23:08 +01:00
case SMART_ACTION_ACTIVATE_TAXI :
{
if ( ! sTaxiPathStore . LookupEntry ( e . action . taxi . id ))
{
2014-10-26 02:57:28 +02:00
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: Entry " SI64FMTD " SourceType %u Event %u Action %u uses invalid Taxi path ID %u, skipped." , e . entryOrGuid , e . GetScriptType (), e . event_id , e . GetActionType (), e . action . taxi . id );
2010-11-19 20:23:08 +01:00
return false ;
}
break ;
}
2010-10-27 21:01:47 +02:00
case SMART_ACTION_RANDOM_EMOTE :
2017-06-03 10:21:06 +02:00
{
2020-06-25 12:15:21 +02:00
if ( std :: all_of ( std :: begin ( e . action . randomEmote . emotes ), std :: end ( e . action . randomEmote . emotes ), []( uint32 emote ) { return emote == 0 ; }))
2017-06-03 10:21:06 +02:00
{
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: Entry " SI64FMTD " SourceType %u Event %u Action %u does not have any non-zero emote" ,
e . entryOrGuid , e . GetScriptType (), e . event_id , e . GetActionType ());
2012-03-28 20:00:29 +08:00
return false ;
2017-06-03 10:21:06 +02:00
}
2012-03-28 20:00:29 +08:00
2017-06-03 10:21:06 +02:00
for ( uint32 emote : e . action . randomEmote . emotes )
if ( emote && ! IsEmoteValid ( e , emote ))
return false ;
break ;
}
case SMART_ACTION_CALL_RANDOM_TIMED_ACTIONLIST :
{
2020-06-25 12:15:21 +02:00
if ( std :: all_of ( std :: begin ( e . action . randTimedActionList . actionLists ), std :: end ( e . action . randTimedActionList . actionLists ), []( uint32 actionList ) { return actionList == 0 ; }))
2017-06-03 10:21:06 +02:00
{
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: Entry " SI64FMTD " SourceType %u Event %u Action %u does not have any non-zero action list" ,
e . entryOrGuid , e . GetScriptType (), e . event_id , e . GetActionType ());
2012-03-28 20:00:29 +08:00
return false ;
2017-06-03 10:21:06 +02:00
}
break ;
}
case SMART_ACTION_START_CLOSEST_WAYPOINT :
{
2020-06-25 12:15:21 +02:00
if ( std :: all_of ( std :: begin ( e . action . closestWaypointFromList . wps ), std :: end ( e . action . closestWaypointFromList . wps ), []( uint32 wp ) { return wp == 0 ; }))
2017-06-03 10:21:06 +02:00
{
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: Entry " SI64FMTD " SourceType %u Event %u Action %u does not have any non-zero waypoint id" ,
e . entryOrGuid , e . GetScriptType (), e . event_id , e . GetActionType ());
2012-03-28 20:00:29 +08:00
return false ;
2017-06-03 10:21:06 +02:00
}
2010-10-27 21:01:47 +02:00
break ;
2017-06-03 10:21:06 +02:00
}
2016-01-26 03:26:41 +00:00
case SMART_ACTION_RANDOM_SOUND :
2016-01-26 03:37:07 +00:00
{
2017-05-18 23:52:58 +02:00
if ( std :: all_of ( std :: begin ( e . action . randomSound . sounds ), std :: end ( e . action . randomSound . sounds ), []( uint32 sound ) { return sound == 0 ; }))
2016-01-26 03:26:41 +00:00
{
2016-04-02 19:22:30 +02:00
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: Entry " SI64FMTD " SourceType %u Event %u Action %u does not have any non-zero sound" ,
2016-01-26 03:37:07 +00:00
e . entryOrGuid , e . GetScriptType (), e . event_id , e . GetActionType ());
return false ;
2016-01-26 03:26:41 +00:00
}
2016-01-26 03:37:07 +00:00
for ( uint32 sound : e . action . randomSound . sounds )
if ( sound && ! IsSoundValid ( e , sound ))
return false ;
2016-01-26 03:26:41 +00:00
break ;
2016-01-26 03:37:07 +00:00
}
2010-10-27 21:01:47 +02:00
case SMART_ACTION_CAST :
2014-09-30 18:55:51 +02:00
{
if ( ! IsSpellValid ( e , e . action . cast . spell ))
return false ;
2021-09-04 15:13:15 +02:00
for ( SpellEffectInfo const & spellEffectInfo : sSpellMgr -> AssertSpellInfo ( e . action . cast . spell , DIFFICULTY_NONE ) -> GetEffects ())
2014-09-30 18:55:51 +02:00
{
2021-09-04 15:13:15 +02:00
if ( spellEffectInfo . IsEffect ( SPELL_EFFECT_KILL_CREDIT ) || spellEffectInfo . IsEffect ( SPELL_EFFECT_KILL_CREDIT2 ))
2014-09-30 18:55:51 +02:00
{
2021-09-04 15:13:15 +02:00
if ( spellEffectInfo . TargetA . GetTarget () == TARGET_UNIT_CASTER )
2014-10-26 02:57:28 +02:00
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: Entry " SI64FMTD " SourceType %u Event %u Action %u Effect: SPELL_EFFECT_KILL_CREDIT: (SpellId: %u targetA: %u - targetB: %u) has invalid target for this Action" ,
2021-09-04 15:13:15 +02:00
e . entryOrGuid , e . GetScriptType (), e . event_id , e . GetActionType (), e . action . cast . spell , spellEffectInfo . TargetA . GetTarget (), spellEffectInfo . TargetB . GetTarget ());
2014-09-30 18:55:51 +02:00
}
}
break ;
}
2017-02-17 21:33:18 +01:00
case SMART_ACTION_CROSS_CAST :
{
if ( ! IsSpellValid ( e , e . action . crossCast . spell ))
return false ;
break ;
}
2014-09-30 18:55:51 +02:00
case SMART_ACTION_ADD_AURA :
2010-11-06 23:18:04 +01:00
case SMART_ACTION_INVOKER_CAST :
2012-03-28 20:00:29 +08:00
if ( ! IsSpellValid ( e , e . action . cast . spell ))
return false ;
2010-10-27 21:01:47 +02:00
break ;
case SMART_ACTION_CALL_AREAEXPLOREDOREVENTHAPPENS :
case SMART_ACTION_CALL_GROUPEVENTHAPPENS :
2010-12-22 21:25:23 +01:00
if ( Quest const * qid = sObjectMgr -> GetQuestTemplate ( e . action . quest . quest ))
2010-10-27 21:01:47 +02:00
{
2012-08-18 21:08:21 +01:00
if ( ! qid -> HasSpecialFlag ( QUEST_SPECIAL_FLAGS_EXPLORATION_OR_EVENT ))
2010-10-27 21:01:47 +02:00
{
2014-10-26 02:57:28 +02:00
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: Entry " SI64FMTD " SourceType %u Event %u Action %u SpecialFlags for Quest entry %u does not include FLAGS_EXPLORATION_OR_EVENT(2), skipped." , e . entryOrGuid , e . GetScriptType (), e . event_id , e . GetActionType (), e . action . quest . quest );
2010-10-27 21:01:47 +02:00
return false ;
}
}
else
{
2014-10-26 02:57:28 +02:00
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: Entry " SI64FMTD " SourceType %u Event %u Action %u uses non-existent Quest entry %u, skipped." , e . entryOrGuid , e . GetScriptType (), e . event_id , e . GetActionType (), e . action . quest . quest );
2010-10-27 21:01:47 +02:00
return false ;
}
break ;
case SMART_ACTION_SET_EVENT_PHASE :
if ( e . action . setEventPhase . phase >= SMART_EVENT_PHASE_MAX )
{
2014-10-26 02:57:28 +02:00
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: Entry " SI64FMTD " SourceType %u Event %u Action %u attempts to set phase %u. Phase mask cannot be used past phase %u, skipped." , e . entryOrGuid , e . GetScriptType (), e . event_id , e . GetActionType (), e . action . setEventPhase . phase , SMART_EVENT_PHASE_MAX - 1 );
2010-10-27 21:01:47 +02:00
return false ;
}
break ;
case SMART_ACTION_INC_EVENT_PHASE :
if ( ! e . action . incEventPhase . inc && ! e . action . incEventPhase . dec )
{
2014-10-26 02:57:28 +02:00
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: Entry " SI64FMTD " SourceType %u Event %u Action %u is incrementing phase by 0, skipped." , e . entryOrGuid , e . GetScriptType (), e . event_id , e . GetActionType ());
2010-10-27 21:01:47 +02:00
return false ;
}
else if ( e . action . incEventPhase . inc > SMART_EVENT_PHASE_MAX || e . action . incEventPhase . dec > SMART_EVENT_PHASE_MAX )
{
2014-10-26 02:57:28 +02:00
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: Entry " SI64FMTD " SourceType %u Event %u Action %u attempts to increment phase by too large value, skipped." , e . entryOrGuid , e . GetScriptType (), e . event_id , e . GetActionType ());
2010-10-27 21:01:47 +02:00
return false ;
}
break ;
case SMART_ACTION_REMOVEAURASFROMSPELL :
2012-06-02 14:28:24 +01:00
if ( e . action . removeAura . spell != 0 && ! IsSpellValid ( e , e . action . removeAura . spell ))
2012-03-28 20:00:29 +08:00
return false ;
2010-10-27 21:01:47 +02:00
break ;
case SMART_ACTION_RANDOM_PHASE :
2017-06-03 10:21:06 +02:00
{
2020-06-25 12:15:21 +02:00
if ( std :: all_of ( std :: begin ( e . action . randomPhase . phases ), std :: end ( e . action . randomPhase . phases ), []( uint32 phase ) { return phase == 0 ; }))
2010-10-27 21:01:47 +02:00
{
2017-06-03 10:21:06 +02:00
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: Entry " SI64FMTD " SourceType %u Event %u Action %u does not have any non-zero phase" ,
e . entryOrGuid , e . GetScriptType (), e . event_id , e . GetActionType ());
return false ;
}
2020-06-25 12:15:21 +02:00
if ( std :: any_of ( std :: begin ( e . action . randomPhase . phases ), std :: end ( e . action . randomPhase . phases ), []( uint32 phase ) { return phase >= SMART_EVENT_PHASE_MAX ; }))
2017-06-03 10:21:06 +02:00
{
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: Entry " SI64FMTD " SourceType %u Event %u Action %u attempts to set invalid phase, skipped." , e . entryOrGuid , e . GetScriptType (), e . event_id , e . GetActionType ());
return false ;
2010-10-27 21:01:47 +02:00
}
break ;
2017-06-03 10:21:06 +02:00
}
2010-10-27 21:01:47 +02:00
case SMART_ACTION_RANDOM_PHASE_RANGE : //PhaseMin, PhaseMax
2017-06-03 10:21:06 +02:00
{
if ( e . action . randomPhaseRange . phaseMin >= SMART_EVENT_PHASE_MAX ||
e . action . randomPhaseRange . phaseMax >= SMART_EVENT_PHASE_MAX )
2010-10-27 21:01:47 +02:00
{
2017-06-03 10:21:06 +02:00
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: Entry " SI64FMTD " SourceType %u Event %u Action %u attempts to set invalid phase, skipped." , e . entryOrGuid , e . GetScriptType (), e . event_id , e . GetActionType ());
return false ;
2010-10-27 21:01:47 +02:00
}
2017-06-03 10:21:06 +02:00
if ( ! IsMinMaxValid ( e , e . action . randomPhaseRange . phaseMin , e . action . randomPhaseRange . phaseMax ))
return false ;
break ;
}
2010-10-27 21:01:47 +02:00
case SMART_ACTION_SUMMON_CREATURE :
2013-12-11 18:53:05 +01:00
{
2012-03-28 20:00:29 +08:00
if ( ! IsCreatureValid ( e , e . action . summonCreature . creature ))
return false ;
2013-09-05 16:16:23 +02:00
2013-12-11 18:53:05 +01:00
CacheSpellContainerBounds sBounds = GetSummonCreatureSpellContainerBounds ( e . action . summonCreature . creature );
for ( CacheSpellContainer :: const_iterator itr = sBounds . first ; itr != sBounds . second ; ++ itr )
2014-10-26 02:57:28 +02:00
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: Entry " SI64FMTD " SourceType %u Event %u Action %u creature summon: There is a summon spell for creature entry %u (SpellId: %u, effect: %u)" ,
2013-12-11 18:53:05 +01:00
e . entryOrGuid , e . GetScriptType (), e . event_id , e . GetActionType (), e . action . summonCreature . creature , itr -> second . first , itr -> second . second );
2013-09-05 16:16:23 +02:00
2011-09-19 14:41:21 +02:00
if ( e . action . summonCreature . type < TEMPSUMMON_TIMED_OR_DEAD_DESPAWN || e . action . summonCreature . type > TEMPSUMMON_MANUAL_DESPAWN )
2010-10-27 21:01:47 +02:00
{
2014-10-26 02:57:28 +02:00
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: Entry " SI64FMTD " SourceType %u Event %u Action %u uses incorrect TempSummonType %u, skipped." , e . entryOrGuid , e . GetScriptType (), e . event_id , e . GetActionType (), e . action . summonCreature . type );
2010-10-27 21:01:47 +02:00
return false ;
}
break ;
2013-12-11 18:53:05 +01:00
}
2010-10-27 21:01:47 +02:00
case SMART_ACTION_CALL_KILLEDMONSTER :
2013-12-11 18:53:05 +01:00
{
2012-03-28 20:00:29 +08:00
if ( ! IsCreatureValid ( e , e . action . killedMonster . creature ))
return false ;
2013-09-02 17:48:17 +02:00
2013-12-11 18:53:05 +01:00
CacheSpellContainerBounds sBounds = GetKillCreditSpellContainerBounds ( e . action . killedMonster . creature );
for ( CacheSpellContainer :: const_iterator itr = sBounds . first ; itr != sBounds . second ; ++ itr )
2014-10-26 02:57:28 +02:00
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: Entry " SI64FMTD " SourceType %u Event %u Action %u Kill Credit: There is a killcredit spell for creatureEntry %u (SpellId: %u effect: %u)" ,
2013-12-11 18:53:05 +01:00
e . entryOrGuid , e . GetScriptType (), e . event_id , e . GetActionType (), e . action . killedMonster . creature , itr -> second . first , itr -> second . second );
2013-09-02 17:48:17 +02:00
2013-07-08 18:01:41 +02:00
if ( e . GetTargetType () == SMART_TARGET_POSITION )
{
2014-10-26 02:57:28 +02:00
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: Entry " SI64FMTD " SourceType %u Event %u Action %u uses incorrect TargetType %u, skipped." , e . entryOrGuid , e . GetScriptType (), e . event_id , e . GetActionType (), e . GetTargetType ());
2013-07-08 18:01:41 +02:00
return false ;
}
2010-10-27 21:01:47 +02:00
break ;
2013-12-11 18:53:05 +01:00
}
2010-10-27 21:01:47 +02:00
case SMART_ACTION_UPDATE_TEMPLATE :
2013-12-13 09:45:58 +01:00
if ( ! IsCreatureValid ( e , e . action . updateTemplate . creature ))
2012-03-28 20:00:29 +08:00
return false ;
2010-10-27 21:01:47 +02:00
break ;
case SMART_ACTION_SET_SHEATH :
if ( e . action . setSheath . sheath && e . action . setSheath . sheath >= MAX_SHEATH_STATE )
{
2014-10-26 02:57:28 +02:00
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: Entry " SI64FMTD " SourceType %u Event %u Action %u uses incorrect Sheath state %u, skipped." , e . entryOrGuid , e . GetScriptType (), e . event_id , e . GetActionType (), e . action . setSheath . sheath );
2010-10-27 21:01:47 +02:00
return false ;
}
break ;
case SMART_ACTION_SET_REACT_STATE :
{
if ( e . action . react . state > REACT_AGGRESSIVE )
{
2014-10-26 02:57:28 +02:00
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: Creature " SI64FMTD " Event %u Action %u uses invalid React State %u, skipped." , e . entryOrGuid , e . event_id , e . GetActionType (), e . action . react . state );
2010-10-27 21:01:47 +02:00
return false ;
}
break ;
}
case SMART_ACTION_SUMMON_GO :
2013-12-11 18:53:05 +01:00
{
2012-03-28 20:00:29 +08:00
if ( ! IsGameObjectValid ( e , e . action . summonGO . entry ))
return false ;
2013-09-05 16:16:23 +02:00
2013-12-11 18:53:05 +01:00
CacheSpellContainerBounds sBounds = GetSummonGameObjectSpellContainerBounds ( e . action . summonGO . entry );
for ( CacheSpellContainer :: const_iterator itr = sBounds . first ; itr != sBounds . second ; ++ itr )
2014-10-26 02:57:28 +02:00
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: Entry " SI64FMTD " SourceType %u Event %u Action %u gameobject summon: There is a summon spell for gameobject entry %u (SpellId: %u, effect: %u)" ,
2014-09-21 17:45:31 +02:00
e . entryOrGuid , e . GetScriptType (), e . event_id , e . GetActionType (), e . action . summonGO . entry , itr -> second . first , itr -> second . second );
2010-10-27 21:01:47 +02:00
break ;
2013-12-11 18:53:05 +01:00
}
2010-10-27 21:01:47 +02:00
case SMART_ACTION_REMOVE_ITEM :
2012-03-28 20:00:29 +08:00
if ( ! IsItemValid ( e , e . action . item . entry ))
return false ;
if ( ! NotNULL ( e , e . action . item . count ))
return false ;
2010-10-27 21:01:47 +02:00
break ;
2014-09-21 17:45:31 +02:00
case SMART_ACTION_ADD_ITEM :
{
if ( ! IsItemValid ( e , e . action . item . entry ))
return false ;
if ( ! NotNULL ( e , e . action . item . count ))
return false ;
2014-10-11 18:52:01 +02:00
CacheSpellContainerBounds sBounds = GetCreateItemSpellContainerBounds ( e . action . item . entry );
2014-09-21 17:45:31 +02:00
for ( CacheSpellContainer :: const_iterator itr = sBounds . first ; itr != sBounds . second ; ++ itr )
2014-10-26 02:57:28 +02:00
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: Entry " SI64FMTD " SourceType %u Event %u Action %u Create Item: There is a create item spell for item %u (SpellId: %u effect: %u)" ,
2014-10-11 18:52:01 +02:00
e . entryOrGuid , e . GetScriptType (), e . event_id , e . GetActionType (), e . action . item . entry , itr -> second . first , itr -> second . second );
2014-09-21 17:45:31 +02:00
break ;
}
2010-10-27 21:01:47 +02:00
case SMART_ACTION_TELEPORT :
if ( ! sMapStore . LookupEntry ( e . action . teleport . mapID ))
{
2014-10-26 02:57:28 +02:00
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: Entry " SI64FMTD " SourceType %u Event %u Action %u uses non-existent Map entry %u, skipped." , e . entryOrGuid , e . GetScriptType (), e . event_id , e . GetActionType (), e . action . teleport . mapID );
2010-10-27 21:01:47 +02:00
return false ;
}
break ;
case SMART_ACTION_INSTALL_AI_TEMPLATE :
if ( e . action . installTtemplate . id >= SMARTAI_TEMPLATE_END )
{
2014-10-26 02:57:28 +02:00
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: Creature " SI64FMTD " Event %u Action %u uses non-existent AI template id %u, skipped." , e . entryOrGuid , e . event_id , e . GetActionType (), e . action . installTtemplate . id );
2010-10-27 21:01:47 +02:00
return false ;
}
break ;
case SMART_ACTION_WP_STOP :
2012-03-28 20:00:29 +08:00
if ( e . action . wpStop . quest && ! IsQuestValid ( e , e . action . wpStop . quest ))
return false ;
2010-10-27 21:01:47 +02:00
break ;
case SMART_ACTION_WP_START :
2017-08-12 01:40:25 +02:00
{
WaypointPath const * path = sSmartWaypointMgr -> GetPath ( e . action . wpStart . pathID );
if ( ! path || path -> nodes . empty ())
2010-10-27 21:01:47 +02:00
{
2017-08-12 01:40:25 +02:00
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: Creature " SI64FMTD " Event %u Action %u uses non-existent WaypointPath id %u, skipped." , e . entryOrGuid , e . event_id , e . GetActionType (), e . action . wpStart . pathID );
return false ;
2010-10-27 21:01:47 +02:00
}
2017-08-12 01:40:25 +02:00
if ( e . action . wpStart . quest && ! IsQuestValid ( e , e . action . wpStart . quest ))
return false ;
if ( e . action . wpStart . reactState > REACT_AGGRESSIVE )
{
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: Creature " SI64FMTD " Event %u Action %u uses invalid React State %u, skipped." , e . entryOrGuid , e . event_id , e . GetActionType (), e . action . wpStart . reactState );
return false ;
}
break ;
}
2010-10-27 21:01:47 +02:00
case SMART_ACTION_CREATE_TIMED_EVENT :
{
2012-03-28 20:00:29 +08:00
if ( ! IsMinMaxValid ( e , e . action . timeEvent . min , e . action . timeEvent . max ))
return false ;
if ( ! IsMinMaxValid ( e , e . action . timeEvent . repeatMin , e . action . timeEvent . repeatMax ))
return false ;
2010-10-27 21:01:47 +02:00
break ;
}
2014-02-09 16:09:09 +01:00
case SMART_ACTION_CALL_RANDOM_RANGE_TIMED_ACTIONLIST :
{
2017-06-03 10:21:06 +02:00
if ( ! IsMinMaxValid ( e , e . action . randTimedActionList . actionLists [ 0 ], e . action . randTimedActionList . actionLists [ 1 ]))
2014-02-09 16:09:09 +01:00
return false ;
break ;
}
2013-08-10 14:13:17 +02:00
case SMART_ACTION_SET_POWER :
case SMART_ACTION_ADD_POWER :
case SMART_ACTION_REMOVE_POWER :
if ( e . action . power . powerType > MAX_POWERS )
{
2014-10-26 02:57:28 +02:00
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: Entry " SI64FMTD " SourceType %u Event %u Action %u uses non-existent Power %u, skipped." , e . entryOrGuid , e . GetScriptType (), e . event_id , e . GetActionType (), e . action . power . powerType );
2013-08-10 14:13:17 +02:00
return false ;
}
break ;
2013-08-30 01:16:12 +02:00
case SMART_ACTION_GAME_EVENT_STOP :
{
uint32 eventId = e . action . gameEventStop . id ;
GameEventMgr :: GameEventDataMap const & events = sGameEventMgr -> GetEventMap ();
if ( eventId < 1 || eventId >= events . size ())
{
2014-10-26 02:57:28 +02:00
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: Entry " SI64FMTD " SourceType %u Event %u Action %u uses non-existent event, eventId %u, skipped." , e . entryOrGuid , e . GetScriptType (), e . event_id , e . GetActionType (), e . action . gameEventStop . id );
2013-08-30 01:16:12 +02:00
return false ;
}
GameEventData const & eventData = events [ eventId ];
if ( ! eventData . isValid ())
{
2014-10-26 02:57:28 +02:00
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: Entry " SI64FMTD " SourceType %u Event %u Action %u uses non-existent event, eventId %u, skipped." , e . entryOrGuid , e . GetScriptType (), e . event_id , e . GetActionType (), e . action . gameEventStop . id );
2013-08-30 01:16:12 +02:00
return false ;
}
break ;
}
case SMART_ACTION_GAME_EVENT_START :
{
uint32 eventId = e . action . gameEventStart . id ;
GameEventMgr :: GameEventDataMap const & events = sGameEventMgr -> GetEventMap ();
if ( eventId < 1 || eventId >= events . size ())
{
2014-10-26 02:57:28 +02:00
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: Entry " SI64FMTD " SourceType %u Event %u Action %u uses non-existent event, eventId %u, skipped." , e . entryOrGuid , e . GetScriptType (), e . event_id , e . GetActionType (), e . action . gameEventStart . id );
2013-08-30 01:16:12 +02:00
return false ;
}
GameEventData const & eventData = events [ eventId ];
if ( ! eventData . isValid ())
{
2014-10-26 02:57:28 +02:00
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: Entry " SI64FMTD " SourceType %u Event %u Action %u uses non-existent event, eventId %u, skipped." , e . entryOrGuid , e . GetScriptType (), e . event_id , e . GetActionType (), e . action . gameEventStart . id );
2013-08-30 01:16:12 +02:00
return false ;
}
break ;
}
2014-03-31 17:31:21 +02:00
case SMART_ACTION_EQUIP :
{
if ( e . GetScriptType () == SMART_SCRIPT_TYPE_CREATURE )
{
2017-06-03 10:21:06 +02:00
if ( int8 equipId = static_cast < int8 > ( e . action . equip . entry ))
2014-03-31 17:31:21 +02:00
{
2017-06-03 10:21:06 +02:00
EquipmentInfo const * eInfo = sObjectMgr -> GetEquipmentInfo ( e . entryOrGuid , equipId );
if ( ! eInfo )
{
TC_LOG_ERROR ( "sql.sql" , "SmartScript: SMART_ACTION_EQUIP uses non-existent equipment info id %u for creature " SI64FMTD ", skipped." , equipId , e . entryOrGuid );
return false ;
}
2014-03-31 17:31:21 +02:00
}
}
break ;
}
2016-06-14 13:29:51 -03:00
case SMART_ACTION_SET_INST_DATA :
{
if ( e . action . setInstanceData . type > 1 )
{
2016-06-15 06:44:36 +02:00
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: Entry " SI64FMTD " SourceType %u Event %u Action %u uses invalid data type %u (value range 0-1), skipped." , e . entryOrGuid , e . GetScriptType (), e . event_id , e . GetActionType (), e . action . setInstanceData . type );
2016-06-14 13:29:51 -03:00
return false ;
}
else if ( e . action . setInstanceData . type == 1 )
{
if ( e . action . setInstanceData . data > TO_BE_DECIDED )
{
2016-06-15 06:44:36 +02:00
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: Entry " SI64FMTD " SourceType %u Event %u Action %u uses invalid boss state %u (value range 0-5), skipped." , e . entryOrGuid , e . GetScriptType (), e . event_id , e . GetActionType (), e . action . setInstanceData . data );
2016-06-14 13:29:51 -03:00
return false ;
}
}
break ;
}
2014-06-05 13:05:29 -05:00
case SMART_ACTION_SET_INGAME_PHASE_ID :
{
uint32 phaseId = e . action . ingamePhaseId . id ;
uint32 apply = e . action . ingamePhaseId . apply ;
if ( apply != 0 && apply != 1 )
{
2014-10-26 02:57:28 +02:00
TC_LOG_ERROR ( "sql.sql" , "SmartScript: SMART_ACTION_SET_INGAME_PHASE_ID uses invalid apply value %u (Should be 0 or 1) for creature " SI64FMTD ", skipped" , apply , e . entryOrGuid );
2014-06-05 13:05:29 -05:00
return false ;
}
2016-02-06 17:53:37 +01:00
if ( ! sPhaseStore . LookupEntry ( phaseId ))
2014-06-05 13:05:29 -05:00
{
2014-10-26 02:57:28 +02:00
TC_LOG_ERROR ( "sql.sql" , "SmartScript: SMART_ACTION_SET_INGAME_PHASE_ID uses invalid phaseid %u for creature " SI64FMTD ", skipped" , phaseId , e . entryOrGuid );
2014-06-05 13:05:29 -05:00
return false ;
}
break ;
}
case SMART_ACTION_SET_INGAME_PHASE_GROUP :
{
2014-06-06 12:08:42 -05:00
uint32 phaseGroup = e . action . ingamePhaseGroup . groupId ;
2014-06-05 13:05:29 -05:00
uint32 apply = e . action . ingamePhaseGroup . apply ;
if ( apply != 0 && apply != 1 )
{
2014-10-26 02:57:28 +02:00
TC_LOG_ERROR ( "sql.sql" , "SmartScript: SMART_ACTION_SET_INGAME_PHASE_GROUP uses invalid apply value %u (Should be 0 or 1) for creature " SI64FMTD ", skipped" , apply , e . entryOrGuid );
2014-06-05 13:05:29 -05:00
return false ;
}
2018-01-28 11:37:20 +01:00
if ( ! sDB2Manager . GetPhasesForGroup ( phaseGroup ))
2014-06-05 13:05:29 -05:00
{
2014-10-26 02:57:28 +02:00
TC_LOG_ERROR ( "sql.sql" , "SmartScript: SMART_ACTION_SET_INGAME_PHASE_GROUP uses invalid phase group id %u for creature " SI64FMTD ", skipped" , phaseGroup , e . entryOrGuid );
2014-06-05 13:05:29 -05:00
return false ;
}
break ;
}
2017-03-17 21:21:35 +01:00
case SMART_ACTION_SCENE_PLAY :
{
if ( ! sObjectMgr -> GetSceneTemplate ( e . action . scene . sceneId ))
{
TC_LOG_ERROR ( "sql.sql" , "SmartScript: SMART_ACTION_SCENE_PLAY uses sceneId %u but scene don't exist, skipped" , e . action . scene . sceneId );
return false ;
}
break ;
}
case SMART_ACTION_SCENE_CANCEL :
{
if ( ! sObjectMgr -> GetSceneTemplate ( e . action . scene . sceneId ))
{
TC_LOG_ERROR ( "sql.sql" , "SmartScript: SMART_ACTION_SCENE_CANCEL uses sceneId %u but scene don't exist, skipped" , e . action . scene . sceneId );
return false ;
}
break ;
}
2017-02-17 21:33:18 +01:00
case SMART_ACTION_REMOVE_AURAS_BY_TYPE :
{
if ( e . action . auraType . type >= TOTAL_AURAS )
{
TC_LOG_ERROR ( "sql.sql" , "Entry " SI64FMTD " SourceType %u Event %u Action %u uses invalid data type %u (value range 0-TOTAL_AURAS), skipped." , e . entryOrGuid , e . GetScriptType (), e . event_id , e . GetActionType (), e . action . auraType . type );
return false ;
}
break ;
}
2018-02-23 03:20:03 +01:00
case SMART_ACTION_RESPAWN_BY_SPAWNID :
{
if ( ! sObjectMgr -> GetSpawnData ( SpawnObjectType ( e . action . respawnData . spawnType ), e . action . respawnData . spawnId ))
{
TC_LOG_ERROR ( "sql.sql" , "Entry " SI64FMTD " SourceType %u Event %u Action %u specifies invalid spawn data (%u,%u)" , e . entryOrGuid , e . GetScriptType (), e . event_id , e . GetActionType (), e . action . respawnData . spawnType , e . action . respawnData . spawnId );
return false ;
}
break ;
}
2018-02-24 02:26:35 +01:00
case SMART_ACTION_ENABLE_TEMP_GOBJ :
{
if ( ! e . action . enableTempGO . duration )
{
TC_LOG_ERROR ( "sql.sql" , "Entry " SI64FMTD " SourceType %u Event %u Action %u does not specify duration" , e . entryOrGuid , e . GetScriptType (), e . event_id , e . GetActionType ());
return false ;
}
2021-08-28 16:08:33 +02:00
break ;
2018-02-24 02:26:35 +01:00
}
2018-01-30 11:31:52 +01:00
case SMART_ACTION_SET_MOVEMENT_SPEED :
{
if ( e . action . movementSpeed . movementType >= MAX_MOVE_TYPE )
{
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: Entry " SI64FMTD " SourceType %u Event %u Action %u uses invalid movementType %u, skipped." , e . entryOrGuid , e . GetScriptType (), e . event_id , e . GetActionType (), e . action . movementSpeed . movementType );
return false ;
}
if ( ! e . action . movementSpeed . speedInteger && ! e . action . movementSpeed . speedFraction )
{
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: Entry " SI64FMTD " SourceType %u Event %u Action %u uses speed 0, skipped." , e . entryOrGuid , e . GetScriptType (), e . event_id , e . GetActionType ());
return false ;
}
break ;
}
2021-02-27 11:42:44 +01:00
case SMART_ACTION_CREATE_CONVERSATION :
2021-02-27 12:22:55 +02:00
{
if ( ! sConversationDataStore -> GetConversationTemplate ( e . action . conversation . id ))
{
2021-04-26 22:39:22 +03:00
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: SMART_ACTION_CREATE_CONVERSATION Entry " SI64FMTD " SourceType %u Event %u Action %u uses invalid entry %u, skipped." , e . entryOrGuid , e . GetScriptType (), e . event_id , e . GetActionType (), e . action . conversation . id );
2021-02-27 12:22:55 +02:00
return false ;
}
break ;
}
2010-10-27 21:01:47 +02:00
case SMART_ACTION_FOLLOW :
case SMART_ACTION_SET_ORIENTATION :
case SMART_ACTION_STORE_TARGET_LIST :
case SMART_ACTION_EVADE :
case SMART_ACTION_FLEE_FOR_ASSIST :
2015-07-24 22:54:15 +02:00
case SMART_ACTION_COMBAT_STOP :
2010-10-27 21:01:47 +02:00
case SMART_ACTION_DIE :
case SMART_ACTION_SET_IN_COMBAT_WITH_ZONE :
case SMART_ACTION_SET_ACTIVE :
case SMART_ACTION_WP_RESUME :
case SMART_ACTION_KILL_UNIT :
case SMART_ACTION_SET_INVINCIBILITY_HP_LEVEL :
case SMART_ACTION_RESET_GOBJECT :
case SMART_ACTION_ATTACK_START :
case SMART_ACTION_THREAT_ALL_PCT :
case SMART_ACTION_THREAT_SINGLE_PCT :
case SMART_ACTION_SET_INST_DATA64 :
case SMART_ACTION_AUTO_ATTACK :
case SMART_ACTION_ALLOW_COMBAT_MOVEMENT :
case SMART_ACTION_CALL_FOR_HELP :
case SMART_ACTION_SET_DATA :
case SMART_ACTION_SET_VISIBILITY :
case SMART_ACTION_WP_PAUSE :
2017-02-17 21:33:18 +01:00
case SMART_ACTION_SET_DISABLE_GRAVITY :
case SMART_ACTION_SET_CAN_FLY :
2010-10-27 21:01:47 +02:00
case SMART_ACTION_SET_RUN :
2011-08-21 00:07:38 -03:00
case SMART_ACTION_SET_SWIM :
2010-10-27 21:01:47 +02:00
case SMART_ACTION_FORCE_DESPAWN :
case SMART_ACTION_SET_UNIT_FLAG :
case SMART_ACTION_REMOVE_UNIT_FLAG :
case SMART_ACTION_PLAYMOVIE :
case SMART_ACTION_MOVE_TO_POS :
case SMART_ACTION_CLOSE_GOSSIP :
case SMART_ACTION_TRIGGER_TIMED_EVENT :
case SMART_ACTION_REMOVE_TIMED_EVENT :
case SMART_ACTION_OVERRIDE_SCRIPT_BASE_OBJECT :
case SMART_ACTION_RESET_SCRIPT_BASE_OBJECT :
case SMART_ACTION_ACTIVATE_GOBJECT :
case SMART_ACTION_CALL_SCRIPT_RESET :
2012-12-29 22:26:40 +01:00
case SMART_ACTION_SET_RANGED_MOVEMENT :
2010-11-03 14:10:16 +01:00
case SMART_ACTION_CALL_TIMED_ACTIONLIST :
case SMART_ACTION_SET_NPC_FLAG :
case SMART_ACTION_ADD_NPC_FLAG :
case SMART_ACTION_REMOVE_NPC_FLAG :
2010-11-20 13:23:29 +01:00
case SMART_ACTION_RANDOM_MOVE :
2011-02-07 09:35:14 -07:00
case SMART_ACTION_SET_UNIT_FIELD_BYTES_1 :
2011-02-07 10:15:54 -07:00
case SMART_ACTION_REMOVE_UNIT_FIELD_BYTES_1 :
2011-02-15 00:29:33 -03:00
case SMART_ACTION_INTERRUPT_SPELL :
2011-03-02 16:50:09 +01:00
case SMART_ACTION_SEND_GO_CUSTOM_ANIM :
2011-06-12 17:50:23 +02:00
case SMART_ACTION_SET_DYNAMIC_FLAG :
case SMART_ACTION_ADD_DYNAMIC_FLAG :
case SMART_ACTION_REMOVE_DYNAMIC_FLAG :
2011-07-02 07:52:03 +02:00
case SMART_ACTION_JUMP_TO_POS :
2011-10-23 12:55:17 +01:00
case SMART_ACTION_SEND_GOSSIP_MENU :
2012-01-22 10:02:31 -05:00
case SMART_ACTION_GO_SET_LOOT_STATE :
2016-12-27 19:00:57 +01:00
case SMART_ACTION_GO_SET_GO_STATE :
2012-01-22 10:02:31 -05:00
case SMART_ACTION_SEND_TARGET_TO_TARGET :
2012-09-08 00:55:47 +01:00
case SMART_ACTION_SET_HOME_POS :
2012-09-17 13:56:12 -04:00
case SMART_ACTION_SET_HEALTH_REGEN :
2013-02-02 18:18:27 +01:00
case SMART_ACTION_SET_ROOT :
2013-02-16 18:41:55 +00:00
case SMART_ACTION_SET_GO_FLAG :
case SMART_ACTION_ADD_GO_FLAG :
case SMART_ACTION_REMOVE_GO_FLAG :
2013-03-09 02:03:37 +01:00
case SMART_ACTION_SUMMON_CREATURE_GROUP :
2016-07-15 18:37:17 +02:00
case SMART_ACTION_MOVE_OFFSET :
2016-03-03 23:16:59 +01:00
case SMART_ACTION_SET_CORPSE_DELAY :
2016-08-19 14:53:53 +02:00
case SMART_ACTION_DISABLE_EVADE :
2017-02-17 21:33:18 +01:00
case SMART_ACTION_SET_SIGHT_DIST :
case SMART_ACTION_FLEE :
case SMART_ACTION_ADD_THREAT :
case SMART_ACTION_LOAD_EQUIPMENT :
case SMART_ACTION_TRIGGER_RANDOM_TIMED_EVENT :
case SMART_ACTION_SET_COUNTER :
case SMART_ACTION_REMOVE_ALL_GAMEOBJECTS :
2017-05-07 21:48:41 +01:00
case SMART_ACTION_SPAWN_SPAWNGROUP :
case SMART_ACTION_DESPAWN_SPAWNGROUP :
2018-06-03 10:06:57 -07:00
case SMART_ACTION_REMOVE_MOVEMENT :
2010-10-27 21:01:47 +02:00
break ;
default :
2014-10-26 02:57:28 +02:00
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: Not handled action_type(%u), event_type(%u), Entry " SI64FMTD " SourceType %u Event %u, skipped." , e . GetActionType (), e . GetEventType (), e . entryOrGuid , e . GetScriptType (), e . event_id );
2010-10-27 21:01:47 +02:00
return false ;
}
return true ;
}
2014-10-11 18:52:01 +02:00
bool SmartAIMgr :: IsTextValid ( SmartScriptHolder const & e , uint32 id )
2010-10-27 21:01:47 +02:00
{
2014-10-11 18:52:01 +02:00
if ( e . GetScriptType () != SMART_SCRIPT_TYPE_CREATURE )
return true ;
2010-10-27 21:01:47 +02:00
uint32 entry = 0 ;
2014-10-03 20:05:19 +02:00
2014-10-11 18:52:01 +02:00
if ( e . GetEventType () == SMART_EVENT_TEXT_OVER )
2014-10-07 21:49:50 +02:00
{
2014-10-11 18:52:01 +02:00
entry = e . event . textOver . creatureEntry ;
2014-10-07 21:49:50 +02:00
}
2014-10-03 20:05:19 +02:00
else
{
2014-10-11 18:52:01 +02:00
switch ( e . GetTargetType ())
2010-10-27 21:01:47 +02:00
{
2014-10-11 18:52:01 +02:00
case SMART_TARGET_CREATURE_DISTANCE :
case SMART_TARGET_CREATURE_RANGE :
case SMART_TARGET_CLOSEST_CREATURE :
return true ; // ignore
default :
if ( e . entryOrGuid < 0 )
{
2015-07-19 21:54:48 +01:00
ObjectGuid :: LowType guid = ObjectGuid :: LowType ( - e . entryOrGuid );
CreatureData const * data = sObjectMgr -> GetCreatureData ( guid );
2014-10-11 18:52:01 +02:00
if ( ! data )
{
2015-07-19 21:54:48 +01:00
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: Entry " SI64FMTD " SourceType %u Event %u Action %u using non-existent Creature guid " UI64FMTD ", skipped." , e . entryOrGuid , e . GetScriptType (), e . event_id , e . GetActionType (), guid );
2014-10-11 18:52:01 +02:00
return false ;
}
else
entry = data -> id ;
}
else
entry = uint32 ( e . entryOrGuid );
break ;
2010-10-27 21:01:47 +02:00
}
}
2014-10-03 20:05:19 +02:00
2010-12-22 21:25:23 +01:00
if ( ! entry || ! sCreatureTextMgr -> TextExist ( entry , uint8 ( id )))
2010-10-27 21:01:47 +02:00
{
2014-10-26 02:57:28 +02:00
TC_LOG_ERROR ( "sql.sql" , "SmartAIMgr: Entry " SI64FMTD "SourceType %u Event %u Action %u using non-existent Text id %d, skipped." , e . entryOrGuid , e . GetScriptType (), e . event_id , e . GetActionType (), id );
2010-10-27 21:01:47 +02:00
return false ;
}
2014-10-03 20:05:19 +02:00
2010-10-27 21:01:47 +02:00
return true ;
2014-10-03 20:05:19 +02:00
}
2013-12-11 18:53:05 +01:00
void SmartAIMgr :: LoadHelperStores ()
{
uint32 oldMSTime = getMSTime ();
2020-06-12 01:29:18 +02:00
sSpellMgr -> ForEachSpellInfo ([ this ]( SpellInfo const * spellInfo )
2013-12-11 18:53:05 +01:00
{
2021-09-04 15:13:15 +02:00
for ( SpellEffectInfo const & spellEffectInfo : spellInfo -> GetEffects ())
2013-12-11 18:53:05 +01:00
{
2021-09-04 15:13:15 +02:00
if ( spellEffectInfo . IsEffect ( SPELL_EFFECT_SUMMON ))
SummonCreatureSpellStore . insert ( std :: make_pair ( uint32 ( spellEffectInfo . MiscValue ), std :: make_pair ( spellInfo -> Id , spellEffectInfo . EffectIndex )));
else if ( spellEffectInfo . IsEffect ( SPELL_EFFECT_SUMMON_OBJECT_WILD ))
SummonGameObjectSpellStore . insert ( std :: make_pair ( uint32 ( spellEffectInfo . MiscValue ), std :: make_pair ( spellInfo -> Id , spellEffectInfo . EffectIndex )));
else if ( spellEffectInfo . IsEffect ( SPELL_EFFECT_KILL_CREDIT ) || spellEffectInfo . IsEffect ( SPELL_EFFECT_KILL_CREDIT2 ))
KillCreditSpellStore . insert ( std :: make_pair ( uint32 ( spellEffectInfo . MiscValue ), std :: make_pair ( spellInfo -> Id , spellEffectInfo . EffectIndex )));
else if ( spellEffectInfo . IsEffect ( SPELL_EFFECT_CREATE_ITEM ))
CreateItemSpellStore . insert ( std :: make_pair ( uint32 ( spellEffectInfo . ItemType ), std :: make_pair ( spellInfo -> Id , spellEffectInfo . EffectIndex )));
2013-12-11 18:53:05 +01:00
}
2020-06-12 01:29:18 +02:00
});
2013-12-11 18:53:05 +01:00
TC_LOG_INFO ( "server.loading" , ">> Loaded SmartAIMgr Helpers in %u ms" , GetMSTimeDiffToNow ( oldMSTime ));
}
void SmartAIMgr :: UnLoadHelperStores ()
{
SummonCreatureSpellStore . clear ();
SummonGameObjectSpellStore . clear ();
KillCreditSpellStore . clear ();
2014-09-21 17:45:31 +02:00
CreateItemSpellStore . clear ();
2013-12-11 18:53:05 +01:00
}
CacheSpellContainerBounds SmartAIMgr :: GetSummonCreatureSpellContainerBounds ( uint32 creatureEntry ) const
{
return SummonCreatureSpellStore . equal_range ( creatureEntry );
}
CacheSpellContainerBounds SmartAIMgr :: GetSummonGameObjectSpellContainerBounds ( uint32 gameObjectEntry ) const
{
return SummonGameObjectSpellStore . equal_range ( gameObjectEntry );
}
CacheSpellContainerBounds SmartAIMgr :: GetKillCreditSpellContainerBounds ( uint32 killCredit ) const
{
return KillCreditSpellStore . equal_range ( killCredit );
}
2014-09-21 17:45:31 +02:00
2014-10-11 18:52:01 +02:00
CacheSpellContainerBounds SmartAIMgr :: GetCreateItemSpellContainerBounds ( uint32 itemId ) const
2014-09-21 17:45:31 +02:00
{
return CreateItemSpellStore . equal_range ( itemId );
}
2020-06-25 12:15:21 +02:00
ObjectGuidVector :: ObjectGuidVector ( ObjectVector const & objectVector ) : _objectVector ( objectVector )
{
_guidVector . reserve ( _objectVector . size ());
for ( WorldObject * obj : _objectVector )
_guidVector . push_back ( obj -> GetGUID ());
}
void ObjectGuidVector :: UpdateObjects ( WorldObject const & ref ) const
{
_objectVector . clear ();
for ( ObjectGuid const & guid : _guidVector )
if ( WorldObject * obj = ObjectAccessor :: GetWorldObject ( ref , guid ))
_objectVector . push_back ( obj );
2017-06-10 19:17:41 -03:00
}