2010-10-27 21:01:47 +02:00
/*
2011-01-01 15:01:13 +01:00
* Copyright (C) 2008-2011 TrinityCore <http://www.trinitycore.org/>
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/>.
*/
#include "DatabaseEnv.h"
#include "ObjectMgr.h"
#include "ObjectDefines.h"
#include "GridDefines.h"
#include "GridNotifiers.h"
#include "SpellMgr.h"
#include "GridNotifiersImpl.h"
#include "Cell.h"
#include "CellImpl.h"
#include "InstanceScript.h"
#include "ScriptedCreature.h"
#include "GossipDef.h"
#include "ScriptedCreature.h"
#include "SmartScript.h"
#include "SmartAI.h"
2010-11-29 07:50:31 +01:00
#include "Group.h"
2011-08-03 12:28:42 +02:00
#include "Vehicle.h"
2011-10-23 12:55:17 +01:00
#include "ScriptedGossip.h"
2010-10-27 21:01:47 +02:00
SmartScript :: SmartScript ()
{
go = NULL ;
me = NULL ;
mEventPhase = 0 ;
mInvinceabilityHpLevel = 0 ;
mPathId = 0 ;
mTargetStorage = new ObjectListMap ();
mStoredEvents . clear ();
mTextTimer = 0 ;
mLastTextID = 0 ;
mTextGUID = 0 ;
mUseTextTimer = false ;
2011-09-20 17:56:47 +02:00
mTalkerEntry = 0 ;
2010-10-27 21:01:47 +02:00
mTemplate = SMARTAI_TEMPLATE_BASIC ;
meOrigGUID = 0 ;
goOrigGUID = 0 ;
2010-11-03 14:10:16 +01:00
mResumeActionList = true ;
2011-03-27 12:54:11 +02:00
mLastInvoker = 0 ;
}
SmartScript ::~ SmartScript ()
{
for ( ObjectListMap :: iterator itr = mTargetStorage -> begin (); itr != mTargetStorage -> end (); ++ itr )
delete itr -> second ;
delete mTargetStorage ;
2010-10-27 21:01:47 +02:00
}
void SmartScript :: OnReset ()
{
SetPhase ( 0 );
ResetBaseObject ();
for ( SmartAIEventList :: iterator i = mEvents . begin (); i != mEvents . end (); ++ i )
{
2010-11-03 14:10:16 +01:00
InitTimer (( * i ));
2010-10-27 21:01:47 +02:00
( * i ). runOnce = false ;
}
ProcessEventsFor ( SMART_EVENT_RESET );
2011-04-23 15:53:48 +02:00
mLastInvoker = 0 ;
2010-10-27 21:01:47 +02:00
}
2011-07-26 23:09:28 +02:00
void SmartScript :: ProcessEventsFor ( SMART_EVENT e , Unit * unit , uint32 var0 , uint32 var1 , bool bvar , const SpellInfo * spell , GameObject * gob )
2010-10-27 21:01:47 +02:00
{
2010-11-03 14:10:16 +01:00
if ( e == SMART_EVENT_AGGRO )
{
if ( ! mResumeActionList )
mTimedActionList . clear (); //clear action list if it is not resumable
else
{
for ( SmartAIEventList :: iterator itr = mTimedActionList . begin (); itr != mTimedActionList . end (); ++ itr )
{
if ( itr -> enableTimed )
{
InitTimer (( * itr )); //re-init the currently enabled timer, so it restarts the timer when resumed
break ;
}
}
}
}
2010-10-27 21:01:47 +02:00
for ( SmartAIEventList :: iterator i = mEvents . begin (); i != mEvents . end (); ++ i )
{
2010-11-16 14:08:12 +01:00
SMART_EVENT eventType = SMART_EVENT (( * i ). GetEventType ());
if ( eventType == SMART_EVENT_LINK ) //special handling
2010-10-27 21:01:47 +02:00
continue ;
2010-12-13 22:37:56 +01:00
2010-11-16 14:08:12 +01:00
if ( eventType == e /* && (!(*i).event.event_phase_mask || IsInPhase((*i).event.event_phase_mask)) && !((*i).event.event_flags & SMART_EVENT_FLAG_NOT_REPEATABLE && (*i).runOnce)*/ )
2010-10-27 21:01:47 +02:00
ProcessEvent ( * i , unit , var0 , var1 , bvar , spell , gob );
}
}
2011-07-26 23:09:28 +02:00
void SmartScript :: ProcessAction ( SmartScriptHolder & e , Unit * unit , uint32 var0 , uint32 var1 , bool bvar , const SpellInfo * spell , GameObject * gob )
2010-10-27 21:01:47 +02:00
{
//calc random
if ( e . GetEventType () != SMART_EVENT_LINK && e . event . event_chance < 100 && e . event . event_chance )
{
uint32 rnd = urand ( 0 , 100 );
if ( e . event . event_chance <= rnd )
return ;
}
e . runOnce = true ; //used for repeat check
2010-11-04 19:56:39 +01:00
if ( unit )
2011-02-21 22:23:43 +01:00
mLastInvoker = unit -> GetGUID ();
2010-11-04 19:56:39 +01:00
2010-10-27 21:01:47 +02:00
if ( e . link && e . link != e . event_id )
{
SmartScriptHolder linked = FindLinkedEvent ( e . link );
if ( linked . GetActionType () && linked . GetEventType () == SMART_EVENT_LINK )
ProcessEvent ( linked , unit , var0 , var1 , bvar , spell , gob );
2011-02-20 20:16:34 +01:00
else
2010-12-23 23:25:44 +01:00
sLog -> outErrorDb ( "SmartScript::ProcessAction: Entry %d SourceType %u, Event %u, Link Event %u not found or invalid, skipped." , e . entryOrGuid , e . GetScriptType (), e . event_id , e . link );
2010-10-27 21:01:47 +02:00
}
2011-02-21 22:23:43 +01:00
if ( Unit * tempInvoker = GetLastInvoker ())
sLog -> outDebug ( LOG_FILTER_DATABASE_AI , "SmartScript::ProcessAction: Invoker: %s (guidlow: %u)" , tempInvoker -> GetName (), tempInvoker -> GetGUIDLow ());
2011-02-21 01:15:14 +01:00
2010-10-27 21:01:47 +02:00
switch ( e . GetActionType ())
{
case SMART_ACTION_TALK :
2011-03-26 23:45:23 +01:00
{
2011-06-15 17:33:06 +02:00
if ( ! me )
return ;
2011-03-26 23:45:23 +01:00
ObjectList * targets = GetTargets ( e , unit );
2011-09-20 17:56:47 +02:00
Creature * talker = me ;
2011-10-31 13:33:57 +01:00
Player * targetPlayer = NULL ;
2011-03-26 23:45:23 +01:00
if ( targets )
2010-11-01 11:00:53 +01:00
{
2011-03-27 12:54:42 +02:00
for ( ObjectList :: const_iterator itr = targets -> begin (); itr != targets -> end (); ++ itr )
2010-11-01 11:00:53 +01:00
{
2011-03-26 23:45:23 +01:00
if ( IsCreature (( * itr )))
2010-11-01 11:00:53 +01:00
{
2011-03-26 23:45:23 +01:00
talker = ( * itr ) -> ToCreature ();
break ;
2010-11-01 11:00:53 +01:00
}
2011-10-30 14:26:49 +00:00
else if ( IsPlayer (( * itr )))
{
targetPlayer = ( * itr ) -> ToPlayer ();
break ;
}
2010-11-01 11:00:53 +01:00
}
2011-02-21 01:15:14 +01:00
2011-03-26 23:45:23 +01:00
delete targets ;
2010-11-05 19:38:43 +01:00
}
2011-10-30 14:26:49 +00:00
2011-09-20 17:56:47 +02:00
mTalkerEntry = talker -> GetEntry ();
2011-03-26 23:45:23 +01:00
mLastTextID = e . action . talk . textGroupID ;
mTextTimer = e . action . talk . duration ;
2011-10-30 14:26:49 +00:00
if ( IsPlayer ( GetLastInvoker ())) // used for $vars in texts and whisper target
mTextGUID = GetLastInvoker () -> GetGUID ();
else if ( targetPlayer )
mTextGUID = targetPlayer -> GetGUID ();
else
mTextGUID = 0 ;
2011-03-26 23:45:23 +01:00
mUseTextTimer = true ;
sCreatureTextMgr -> SendChat ( talker , uint8 ( e . action . talk . textGroupID ), mTextGUID );
sLog -> outDebug ( LOG_FILTER_DATABASE_AI , "SmartScript::ProcessAction: SMART_ACTION_TALK: talker: %s (GuidLow: %u), textGuid: %u" ,
2011-05-11 11:12:26 +06:00
talker -> GetName (), talker -> GetGUIDLow (), GUID_LOPART ( mTextGUID ));
2011-03-26 23:45:23 +01:00
break ;
}
2010-11-05 19:38:43 +01:00
case SMART_ACTION_SIMPLE_TALK :
2011-03-26 23:45:23 +01:00
{
ObjectList * targets = GetTargets ( e , unit );
if ( targets )
2010-11-05 19:38:43 +01:00
{
2011-03-27 12:54:42 +02:00
for ( ObjectList :: const_iterator itr = targets -> begin (); itr != targets -> end (); ++ itr )
2010-11-05 19:38:43 +01:00
{
2011-06-15 17:33:06 +02:00
if ( IsCreature ( * itr ))
2011-04-23 15:53:48 +02:00
sCreatureTextMgr -> SendChat (( * itr ) -> ToCreature (), uint8 ( e . action . talk . textGroupID ), IsPlayer ( GetLastInvoker ()) ? GetLastInvoker () -> GetGUID () : 0 );
2011-06-15 17:33:06 +02:00
else if ( IsPlayer ( * itr ) && me )
2010-11-05 19:38:43 +01:00
{
2011-03-26 23:45:23 +01:00
Unit * templastInvoker = GetLastInvoker ();
2011-05-13 22:44:01 +02:00
sCreatureTextMgr -> SendChat ( me , uint8 ( e . action . talk . textGroupID ), IsPlayer ( templastInvoker ) ? templastInvoker -> GetGUID () : 0 , CHAT_MSG_ADDON , LANG_ADDON , TEXT_RANGE_NORMAL , 0 , TEAM_OTHER , false , ( * itr ) -> ToPlayer ());
2010-11-05 19:38:43 +01:00
}
2011-03-26 23:45:23 +01:00
sLog -> outDebug ( LOG_FILTER_DATABASE_AI , "SmartScript::ProcessAction:: SMART_ACTION_SIMPLE_TALK: talker: %s (GuidLow: %u), textGroupId: %u" ,
( * itr ) -> GetName (), ( * itr ) -> GetGUIDLow (), uint8 ( e . action . talk . textGroupID ));
2010-11-05 19:38:43 +01:00
}
2011-03-26 23:45:23 +01:00
delete targets ;
2010-11-01 11:00:53 +01:00
}
2011-03-26 23:45:23 +01:00
break ;
}
2010-10-27 21:01:47 +02:00
case SMART_ACTION_PLAY_EMOTE :
2011-03-26 23:45:23 +01:00
{
ObjectList * targets = GetTargets ( e , unit );
if ( targets )
2010-11-02 13:13:54 +01:00
{
2011-03-27 12:54:42 +02:00
for ( ObjectList :: const_iterator itr = targets -> begin (); itr != targets -> end (); ++ itr )
2011-06-15 17:33:06 +02:00
{
if ( IsUnit ( * itr ))
2011-03-26 23:45:23 +01:00
{
( * itr ) -> ToUnit () -> HandleEmoteCommand ( e . action . emote . emote );
sLog -> outDebug ( LOG_FILTER_DATABASE_AI , "SmartScript::ProcessAction:: SMART_ACTION_PLAY_EMOTE: target: %s (GuidLow: %u), emote: %u" ,
( * itr ) -> GetName (), ( * itr ) -> GetGUIDLow (), e . action . emote . emote );
}
2011-06-15 17:33:06 +02:00
}
2011-03-26 23:45:23 +01:00
2011-06-15 17:33:06 +02:00
delete targets ;
2010-11-02 13:13:54 +01:00
}
2011-03-26 23:45:23 +01:00
break ;
}
2010-10-27 21:01:47 +02:00
case SMART_ACTION_SOUND :
2011-03-26 23:45:23 +01:00
{
ObjectList * targets = GetTargets ( e , unit );
if ( targets )
2010-11-02 13:13:54 +01:00
{
2011-03-27 12:54:42 +02:00
for ( ObjectList :: const_iterator itr = targets -> begin (); itr != targets -> end (); ++ itr )
2011-03-26 23:45:23 +01:00
{
2011-11-13 06:40:14 +01:00
if ( IsUnit ( * itr ))
2011-03-26 23:45:23 +01:00
{
2011-09-20 17:46:40 +02:00
( * itr ) -> SendPlaySound ( e . action . sound . sound , e . action . sound . range > 0 ? true : false );
sLog -> outDebug ( LOG_FILTER_DATABASE_AI , "SmartScript::ProcessAction:: SMART_ACTION_SOUND: target: %s (GuidLow: %u), sound: %u, onlyself: %u" ,
2011-03-26 23:45:23 +01:00
( * itr ) -> GetName (), ( * itr ) -> GetGUIDLow (), e . action . sound . sound , e . action . sound . range );
}
}
delete targets ;
2010-11-02 13:13:54 +01:00
}
2011-03-26 23:45:23 +01:00
break ;
}
2010-10-27 21:01:47 +02:00
case SMART_ACTION_SET_FACTION :
{
2010-11-02 13:13:54 +01:00
ObjectList * targets = GetTargets ( e , unit );
if ( targets )
2010-10-27 21:01:47 +02:00
{
2011-03-27 12:54:42 +02:00
for ( ObjectList :: const_iterator itr = targets -> begin (); itr != targets -> end (); ++ itr )
2010-10-27 21:01:47 +02:00
{
2011-06-15 17:33:06 +02:00
if ( IsCreature ( * itr ))
2010-11-02 13:13:54 +01:00
{
if ( e . action . faction . factionID )
2011-02-21 01:15:14 +01:00
{
2010-11-02 13:13:54 +01:00
( * itr ) -> ToCreature () -> setFaction ( e . action . faction . factionID );
2011-02-21 01:15:14 +01:00
sLog -> outDebug ( LOG_FILTER_DATABASE_AI , "SmartScript::ProcessAction:: SMART_ACTION_SET_FACTION: Creature entry %u, GuidLow %u set faction to %u" ,
( * itr ) -> GetEntry (), ( * itr ) -> GetGUIDLow (), e . action . faction . factionID );
}
2010-11-02 13:13:54 +01:00
else
{
2011-04-28 22:57:08 +02:00
if ( CreatureTemplate const * ci = sObjectMgr -> GetCreatureTemplate (( * itr ) -> ToCreature () -> GetEntry ()))
2010-11-02 13:13:54 +01:00
{
if (( * itr ) -> ToCreature () -> getFaction () != ci -> faction_A )
2011-02-21 01:15:14 +01:00
{
2010-11-02 13:13:54 +01:00
( * itr ) -> ToCreature () -> setFaction ( ci -> faction_A );
2011-02-21 01:15:14 +01:00
sLog -> outDebug ( LOG_FILTER_DATABASE_AI , "SmartScript::ProcessAction:: SMART_ACTION_SET_FACTION: Creature entry %u, GuidLow %u set faction to %u" ,
( * itr ) -> GetEntry (), ( * itr ) -> GetGUIDLow (), ci -> faction_A );
}
2010-11-02 13:13:54 +01:00
}
}
}
2010-10-27 21:01:47 +02:00
}
2011-03-26 23:45:23 +01:00
delete targets ;
2010-10-27 21:01:47 +02:00
}
break ;
}
case SMART_ACTION_MORPH_TO_ENTRY_OR_MODEL :
{
2010-11-02 13:13:54 +01:00
ObjectList * targets = GetTargets ( e , unit );
2011-03-26 23:45:23 +01:00
if ( ! targets )
return ;
2011-06-15 17:33:06 +02:00
2011-03-27 12:54:42 +02:00
for ( ObjectList :: const_iterator itr = targets -> begin (); itr != targets -> end (); ++ itr )
2010-10-27 21:01:47 +02:00
{
2011-06-15 17:33:06 +02:00
if ( ! IsCreature ( * itr ))
2010-11-02 13:13:54 +01:00
continue ;
2010-12-13 22:37:56 +01:00
2010-11-02 13:13:54 +01:00
if ( e . action . morphOrMount . creature || e . action . morphOrMount . model )
2010-10-27 21:01:47 +02:00
{
2010-11-02 13:13:54 +01:00
//set model based on entry from creature_template
if ( e . action . morphOrMount . creature )
2010-10-27 21:01:47 +02:00
{
2011-04-28 22:57:08 +02:00
if ( CreatureTemplate const * ci = sObjectMgr -> GetCreatureTemplate ( e . action . morphOrMount . creature ))
2010-11-02 13:13:54 +01:00
{
2010-12-22 21:25:23 +01:00
uint32 display_id = sObjectMgr -> ChooseDisplayId ( 0 , ci );
2010-11-02 13:13:54 +01:00
( * itr ) -> ToCreature () -> SetDisplayId ( display_id );
2011-02-21 01:15:14 +01:00
sLog -> outDebug ( LOG_FILTER_DATABASE_AI , "SmartScript::ProcessAction:: SMART_ACTION_MORPH_TO_ENTRY_OR_MODEL: Creature entry %u, GuidLow %u set displayid to %u" ,
( * itr ) -> GetEntry (), ( * itr ) -> GetGUIDLow (), display_id );
2010-11-02 13:13:54 +01:00
}
2010-10-27 21:01:47 +02:00
}
2010-11-02 13:13:54 +01:00
//if no param1, then use value from param2 (modelId)
else
2011-02-21 01:15:14 +01:00
{
2010-11-02 13:13:54 +01:00
( * itr ) -> ToCreature () -> SetDisplayId ( e . action . morphOrMount . model );
2011-02-21 01:15:14 +01:00
sLog -> outDebug ( LOG_FILTER_DATABASE_AI , "SmartScript::ProcessAction:: SMART_ACTION_MORPH_TO_ENTRY_OR_MODEL: Creature entry %u, GuidLow %u set displayid to %u" ,
( * itr ) -> GetEntry (), ( * itr ) -> GetGUIDLow (), e . action . morphOrMount . model );
}
2010-10-27 21:01:47 +02:00
}
else
2011-02-21 01:15:14 +01:00
{
2010-11-02 13:13:54 +01:00
( * itr ) -> ToCreature () -> DeMorph ();
2011-02-21 01:15:14 +01:00
sLog -> outDebug ( LOG_FILTER_DATABASE_AI , "SmartScript::ProcessAction:: SMART_ACTION_MORPH_TO_ENTRY_OR_MODEL: Creature entry %u, GuidLow %u demorphs." ,
( * itr ) -> GetEntry (), ( * itr ) -> GetGUIDLow ());
}
2010-10-27 21:01:47 +02:00
}
2011-03-26 23:45:23 +01:00
delete targets ;
2010-10-27 21:01:47 +02:00
break ;
}
case SMART_ACTION_FAIL_QUEST :
{
2010-11-02 13:13:54 +01:00
ObjectList * targets = GetTargets ( e , unit );
2011-03-26 23:45:23 +01:00
if ( ! targets )
return ;
2011-06-15 17:33:06 +02:00
2011-03-27 12:54:42 +02:00
for ( ObjectList :: const_iterator itr = targets -> begin (); itr != targets -> end (); ++ itr )
2010-11-02 13:13:54 +01:00
{
2011-06-15 17:33:06 +02:00
if ( IsPlayer ( * itr ))
2011-02-21 01:15:14 +01:00
{
2010-11-02 13:13:54 +01:00
( * itr ) -> ToPlayer () -> FailQuest ( e . action . quest . quest );
2011-02-21 01:15:14 +01:00
sLog -> outDebug ( LOG_FILTER_DATABASE_AI , "SmartScript::ProcessAction:: SMART_ACTION_FAIL_QUEST: Player guidLow %u fails quest %u" ,
( * itr ) -> GetGUIDLow (), e . action . quest . quest );
}
2010-11-02 13:13:54 +01:00
}
2011-03-26 23:45:23 +01:00
delete targets ;
2010-10-27 21:01:47 +02:00
break ;
}
case SMART_ACTION_ADD_QUEST :
{
2010-11-02 13:13:54 +01:00
ObjectList * targets = GetTargets ( e , unit );
2011-03-26 23:45:23 +01:00
if ( ! targets )
return ;
2011-06-15 17:33:06 +02:00
2011-03-27 12:54:42 +02:00
for ( ObjectList :: const_iterator itr = targets -> begin (); itr != targets -> end (); ++ itr )
2010-11-02 13:13:54 +01:00
{
2011-06-15 17:33:06 +02:00
if ( IsPlayer ( * itr ))
{
if ( Quest const * q = sObjectMgr -> GetQuestTemplate ( e . action . quest . quest ))
2011-02-21 01:15:14 +01:00
{
2010-11-02 13:13:54 +01:00
( * itr ) -> ToPlayer () -> AddQuest ( q , NULL );
2011-02-21 01:15:14 +01:00
sLog -> outDebug ( LOG_FILTER_DATABASE_AI , "SmartScript::ProcessAction:: SMART_ACTION_ADD_QUEST: Player guidLow %u add quest %u" ,
( * itr ) -> GetGUIDLow (), e . action . quest . quest );
}
2011-06-15 17:33:06 +02:00
}
2010-11-02 13:13:54 +01:00
}
2011-03-26 23:45:23 +01:00
delete targets ;
2010-10-27 21:01:47 +02:00
break ;
}
case SMART_ACTION_SET_REACT_STATE :
{
2011-02-21 01:15:14 +01:00
if ( ! me )
return ;
2010-10-27 21:01:47 +02:00
me -> SetReactState ( ReactStates ( e . action . react . state ));
2011-02-21 04:23:53 +01:00
sLog -> outDebug ( LOG_FILTER_DATABASE_AI , "SmartScript::ProcessAction:: SMART_ACTION_SET_REACT_STATE: Creature guidLow %u set reactstate %u" ,
2011-02-21 01:15:14 +01:00
me -> GetGUIDLow (), e . action . react . state );
2010-10-27 21:01:47 +02:00
break ;
}
case SMART_ACTION_RANDOM_EMOTE :
2011-03-26 23:45:23 +01:00
{
ObjectList * targets = GetTargets ( e , unit );
if ( ! targets )
return ;
2011-06-15 17:33:06 +02:00
2011-03-26 23:45:23 +01:00
uint32 emotes [ SMART_ACTION_PARAM_COUNT ];
emotes [ 0 ] = e . action . randomEmote . emote1 ;
emotes [ 1 ] = e . action . randomEmote . emote2 ;
emotes [ 2 ] = e . action . randomEmote . emote3 ;
emotes [ 3 ] = e . action . randomEmote . emote4 ;
emotes [ 4 ] = e . action . randomEmote . emote5 ;
emotes [ 5 ] = e . action . randomEmote . emote6 ;
uint32 temp [ SMART_ACTION_PARAM_COUNT ];
uint32 count = 0 ;
for ( uint8 i = 0 ; i < SMART_ACTION_PARAM_COUNT ; i ++ )
{
if ( emotes [ i ])
{
temp [ count ] = emotes [ i ];
2011-06-15 17:33:06 +02:00
++ count ;
2011-03-26 23:45:23 +01:00
}
}
2011-03-27 12:54:42 +02:00
for ( ObjectList :: const_iterator itr = targets -> begin (); itr != targets -> end (); ++ itr )
2010-10-27 21:01:47 +02:00
{
2011-06-15 17:33:06 +02:00
if ( IsUnit ( * itr ))
2010-10-27 21:01:47 +02:00
{
2011-03-26 23:45:23 +01:00
uint32 emote = temp [ urand ( 0 , count )];
( * itr ) -> ToUnit () -> HandleEmoteCommand ( emote );
sLog -> outDebug ( LOG_FILTER_DATABASE_AI , "SmartScript::ProcessAction:: SMART_ACTION_RANDOM_EMOTE: Creature guidLow %u handle random emote %u" ,
( * itr ) -> GetGUIDLow (), emote );
2010-10-27 21:01:47 +02:00
}
}
2011-03-26 23:45:23 +01:00
delete targets ;
break ;
}
2010-10-27 21:01:47 +02:00
case SMART_ACTION_THREAT_ALL_PCT :
{
2011-02-21 01:15:14 +01:00
if ( ! me )
return ;
2011-03-26 23:45:23 +01:00
std :: list < HostileReference *> const & threatList = me -> getThreatManager (). getThreatList ();
for ( std :: list < HostileReference *>:: const_iterator i = threatList . begin (); i != threatList . end (); ++ i )
{
2011-06-15 17:33:06 +02:00
if ( Unit * target = Unit :: GetUnit ( * me , ( * i ) -> getUnitGuid ()))
2011-02-21 01:15:14 +01:00
{
2011-06-15 17:33:06 +02:00
me -> getThreatManager (). modifyThreatPercent ( target , e . action . threatPCT . threatINC ? ( int32 ) e . action . threatPCT . threatINC : - ( int32 ) e . action . threatPCT . threatDEC );
2011-02-21 01:15:14 +01:00
sLog -> outDebug ( LOG_FILTER_DATABASE_AI , "SmartScript::ProcessAction:: SMART_ACTION_THREAT_ALL_PCT: Creature guidLow %u modify threat for unit %u, value %i" ,
2011-06-15 17:33:06 +02:00
me -> GetGUIDLow (), target -> GetGUIDLow (), e . action . threatPCT . threatINC ? ( int32 ) e . action . threatPCT . threatINC : - ( int32 ) e . action . threatPCT . threatDEC );
2011-02-21 01:15:14 +01:00
}
2011-03-26 23:45:23 +01:00
}
2010-10-27 21:01:47 +02:00
break ;
}
case SMART_ACTION_THREAT_SINGLE_PCT :
{
2011-02-21 01:15:14 +01:00
if ( ! me )
return ;
2010-10-27 21:01:47 +02:00
ObjectList * targets = GetTargets ( e , unit );
2011-03-26 23:45:23 +01:00
if ( ! targets )
return ;
2011-03-27 12:54:42 +02:00
for ( ObjectList :: const_iterator itr = targets -> begin (); itr != targets -> end (); ++ itr )
2011-03-26 23:45:23 +01:00
{
2011-06-15 17:33:06 +02:00
if ( IsUnit ( * itr ))
2011-02-21 01:15:14 +01:00
{
2010-10-27 21:01:47 +02:00
me -> getThreatManager (). modifyThreatPercent (( * itr ) -> ToUnit (), e . action . threatPCT . threatINC ? ( int32 ) e . action . threatPCT . threatINC : - ( int32 ) e . action . threatPCT . threatDEC );
2011-02-21 01:15:14 +01:00
sLog -> outDebug ( LOG_FILTER_DATABASE_AI , "SmartScript::ProcessAction:: SMART_ACTION_THREAT_SINGLE_PCT: Creature guidLow %u modify threat for unit %u, value %i" ,
me -> GetGUIDLow (), ( * itr ) -> GetGUIDLow (), e . action . threatPCT . threatINC ? ( int32 ) e . action . threatPCT . threatINC : - ( int32 ) e . action . threatPCT . threatDEC );
}
2011-03-26 23:45:23 +01:00
}
delete targets ;
2010-10-27 21:01:47 +02:00
break ;
}
case SMART_ACTION_CALL_AREAEXPLOREDOREVENTHAPPENS :
2011-03-26 23:45:23 +01:00
{
ObjectList * targets = GetTargets ( e , unit );
if ( ! targets )
return ;
2011-03-27 12:54:42 +02:00
for ( ObjectList :: const_iterator itr = targets -> begin (); itr != targets -> end (); ++ itr )
2010-10-27 21:01:47 +02:00
{
2011-06-15 17:33:06 +02:00
if ( IsPlayer ( * itr ))
2011-03-26 23:45:23 +01:00
{
( * itr ) -> ToPlayer () -> AreaExploredOrEventHappens ( e . action . quest . quest );
sLog -> outDebug ( LOG_FILTER_DATABASE_AI , "SmartScript::ProcessAction:: SMART_ACTION_CALL_AREAEXPLOREDOREVENTHAPPENS: Player guidLow %u credited quest %u" ,
( * itr ) -> GetGUIDLow (), e . action . quest . quest );
}
2010-10-27 21:01:47 +02:00
}
2011-03-26 23:45:23 +01:00
delete targets ;
break ;
}
2010-10-27 21:01:47 +02:00
case SMART_ACTION_SEND_CASTCREATUREORGO :
2011-03-26 23:45:23 +01:00
{
if ( ! GetBaseObject ())
return ;
ObjectList * targets = GetTargets ( e , unit );
if ( ! targets )
return ;
2011-03-27 12:54:42 +02:00
for ( ObjectList :: const_iterator itr = targets -> begin (); itr != targets -> end (); ++ itr )
2010-10-27 21:01:47 +02:00
{
2011-06-15 17:33:06 +02:00
if ( IsPlayer ( * itr ))
2011-03-26 23:45:23 +01:00
{
( * itr ) -> ToPlayer () -> CastedCreatureOrGO ( e . action . castedCreatureOrGO . creature , GetBaseObject () -> GetGUID (), e . action . castedCreatureOrGO . spell );
2011-09-29 12:43:05 +02:00
sLog -> outDebug ( LOG_FILTER_DATABASE_AI , "SmartScript::ProcessAction:: SMART_ACTION_SEND_CASTCREATUREORGO: Player guidLow %u.org Creature: %u, BaseObject GUID: " UI64FMTD ", Spell: %u" ,
2011-05-11 11:12:26 +06:00
( * itr ) -> GetGUIDLow (), e . action . castedCreatureOrGO . creature , GetBaseObject () -> GetGUID (), e . action . castedCreatureOrGO . spell );
2011-03-26 23:45:23 +01:00
}
2010-10-27 21:01:47 +02:00
}
2011-03-26 23:45:23 +01:00
delete targets ;
break ;
}
2010-10-27 21:01:47 +02:00
case SMART_ACTION_CAST :
2011-03-26 23:45:23 +01:00
{
if ( ! me )
return ;
2011-02-21 01:15:14 +01:00
2011-03-26 23:45:23 +01:00
ObjectList * targets = GetTargets ( e , unit );
if ( ! targets )
return ;
2011-02-21 01:15:14 +01:00
2011-03-27 12:54:42 +02:00
for ( ObjectList :: const_iterator itr = targets -> begin (); itr != targets -> end (); ++ itr )
2011-03-26 23:45:23 +01:00
{
2011-06-15 17:33:06 +02:00
if ( IsUnit ( * itr ))
2011-03-26 23:45:23 +01:00
{
if ( e . action . cast . flags & SMARTCAST_INTERRUPT_PREVIOUS )
me -> InterruptNonMeleeSpells ( false );
me -> CastSpell (( * itr ) -> ToUnit (), e . action . cast . spell , ( e . action . cast . flags & SMARTCAST_TRIGGERED ) ? true : false );
sLog -> outDebug ( LOG_FILTER_DATABASE_AI , "SmartScript::ProcessAction:: SMART_ACTION_CAST:: Creature %u casts spell %u on target %u with castflags %u" ,
me -> GetGUIDLow (), e . action . cast . spell , ( * itr ) -> GetGUIDLow (), e . action . cast . flags );
}
2010-10-27 21:01:47 +02:00
}
2011-03-26 23:45:23 +01:00
delete targets ;
break ;
}
2010-11-06 23:18:04 +01:00
case SMART_ACTION_INVOKER_CAST :
2011-03-26 23:45:23 +01:00
{
Unit * tempLastInvoker = GetLastInvoker ();
if ( ! tempLastInvoker )
return ;
ObjectList * targets = GetTargets ( e , unit );
if ( ! targets )
return ;
2011-03-27 12:54:42 +02:00
for ( ObjectList :: const_iterator itr = targets -> begin (); itr != targets -> end (); ++ itr )
2010-11-06 23:18:04 +01:00
{
2011-06-15 17:33:06 +02:00
if ( IsUnit ( * itr ))
2011-03-26 23:45:23 +01:00
{
if ( e . action . cast . flags & SMARTCAST_INTERRUPT_PREVIOUS )
tempLastInvoker -> InterruptNonMeleeSpells ( false );
2011-02-21 01:15:14 +01:00
2011-03-26 23:45:23 +01:00
tempLastInvoker -> CastSpell (( * itr ) -> ToUnit (), e . action . cast . spell , ( e . action . cast . flags & SMARTCAST_TRIGGERED ) ? true : false );
2011-05-11 11:12:26 +06:00
sLog -> outDebug ( LOG_FILTER_DATABASE_AI , "SmartScript::ProcessAction:: SMART_ACTION_INVOKER_CAST: Invoker %u casts spell %u on target %u with castflags %u" ,
tempLastInvoker -> GetGUIDLow (), e . action . cast . spell , ( * itr ) -> GetGUIDLow (), e . action . cast . flags );
2011-03-26 23:45:23 +01:00
}
2010-11-06 23:18:04 +01:00
}
2011-03-26 23:45:23 +01:00
delete targets ;
break ;
}
2010-10-27 21:01:47 +02:00
case SMART_ACTION_ADD_AURA :
2011-03-26 23:45:23 +01:00
{
ObjectList * targets = GetTargets ( e , unit );
if ( ! targets )
return ;
2011-02-21 01:15:14 +01:00
2011-03-27 12:54:42 +02:00
for ( ObjectList :: const_iterator itr = targets -> begin (); itr != targets -> end (); ++ itr )
2011-03-26 23:45:23 +01:00
{
2011-06-15 17:33:06 +02:00
if ( IsUnit ( * itr ))
2011-03-26 23:45:23 +01:00
{
( * itr ) -> ToUnit () -> AddAura ( e . action . cast . spell , ( * itr ) -> ToUnit ());
sLog -> outDebug ( LOG_FILTER_DATABASE_AI , "SmartScript::ProcessAction:: SMART_ACTION_ADD_AURA: Adding aura %u to unit %u" ,
e . action . cast . spell , ( * itr ) -> GetGUIDLow ());
}
2010-10-27 21:01:47 +02:00
}
2011-03-26 23:45:23 +01:00
delete targets ;
break ;
}
2010-10-27 21:01:47 +02:00
case SMART_ACTION_ACTIVATE_GOBJECT :
2011-03-26 23:45:23 +01:00
{
ObjectList * targets = GetTargets ( e , unit );
if ( ! targets )
return ;
2011-02-21 01:15:14 +01:00
2011-03-27 12:54:42 +02:00
for ( ObjectList :: const_iterator itr = targets -> begin (); itr != targets -> end (); ++ itr )
2011-03-26 23:45:23 +01:00
{
2011-06-15 17:33:06 +02:00
if ( IsGameObject ( * itr ))
2011-03-26 23:45:23 +01:00
{
// Activate
( * itr ) -> ToGameObject () -> SetLootState ( GO_READY );
( * itr ) -> ToGameObject () -> UseDoorOrButton ();
sLog -> outDebug ( LOG_FILTER_DATABASE_AI , "SmartScript::ProcessAction:: SMART_ACTION_ACTIVATE_GOBJECT. Gameobject %u (entry: %u) activated" ,
( * itr ) -> GetGUIDLow (), ( * itr ) -> GetEntry ());
}
2010-10-27 21:01:47 +02:00
}
2011-03-26 23:45:23 +01:00
delete targets ;
break ;
}
2010-10-27 21:01:47 +02:00
case SMART_ACTION_RESET_GOBJECT :
2011-03-26 23:45:23 +01:00
{
ObjectList * targets = GetTargets ( e , unit );
if ( ! targets )
return ;
2011-06-15 17:33:06 +02:00
2011-03-27 12:54:42 +02:00
for ( ObjectList :: const_iterator itr = targets -> begin (); itr != targets -> end (); ++ itr )
2010-10-27 21:01:47 +02:00
{
2011-06-15 17:33:06 +02:00
if ( IsGameObject ( * itr ))
2011-03-26 23:45:23 +01:00
{
( * itr ) -> ToGameObject () -> ResetDoorOrButton ();
sLog -> outDebug ( LOG_FILTER_DATABASE_AI , "SmartScript::ProcessAction:: SMART_ACTION_RESET_GOBJECT. Gameobject %u (entry: %u) reset" ,
( * itr ) -> GetGUIDLow (), ( * itr ) -> GetEntry ());
}
2010-10-27 21:01:47 +02:00
}
2011-03-26 23:45:23 +01:00
delete targets ;
break ;
}
2010-10-27 21:01:47 +02:00
case SMART_ACTION_SET_EMOTE_STATE :
2011-03-26 23:45:23 +01:00
{
ObjectList * targets = GetTargets ( e , unit );
if ( ! targets )
return ;
2011-03-27 12:54:42 +02:00
for ( ObjectList :: const_iterator itr = targets -> begin (); itr != targets -> end (); ++ itr )
2010-10-27 21:01:47 +02:00
{
2011-06-15 17:33:06 +02:00
if ( IsUnit ( * itr ))
2011-03-26 23:45:23 +01:00
{
( * itr ) -> ToUnit () -> SetUInt32Value ( UNIT_NPC_EMOTESTATE , e . action . emote . emote );
sLog -> outDebug ( LOG_FILTER_DATABASE_AI , "SmartScript::ProcessAction:: SMART_ACTION_SET_EMOTE_STATE. Unit %u set emotestate to %u" ,
( * itr ) -> GetGUIDLow (), e . action . emote . emote );
}
2010-10-27 21:01:47 +02:00
}
2011-03-26 23:45:23 +01:00
delete targets ;
break ;
}
2010-10-27 21:01:47 +02:00
case SMART_ACTION_SET_UNIT_FLAG :
2011-03-26 23:45:23 +01:00
{
ObjectList * targets = GetTargets ( e , unit );
if ( ! targets )
return ;
2011-06-15 17:33:06 +02:00
2011-03-27 12:54:42 +02:00
for ( ObjectList :: const_iterator itr = targets -> begin (); itr != targets -> end (); ++ itr )
2010-10-27 21:01:47 +02:00
{
2011-06-15 17:33:06 +02:00
if ( IsUnit ( * itr ))
2011-03-26 23:45:23 +01:00
{
( * itr ) -> ToUnit () -> SetFlag ( UNIT_FIELD_FLAGS , e . action . unitFlag . flag );
sLog -> outDebug ( LOG_FILTER_DATABASE_AI , "SmartScript::ProcessAction:: SMART_ACTION_SET_UNIT_FLAG. Unit %u added flag %u to UNIT_FIELD_FLAGS" ,
( * itr ) -> GetGUIDLow (), e . action . unitFlag . flag );
}
2010-10-27 21:01:47 +02:00
}
2011-03-26 23:45:23 +01:00
delete targets ;
break ;
}
2010-10-27 21:01:47 +02:00
case SMART_ACTION_REMOVE_UNIT_FLAG :
2011-03-26 23:45:23 +01:00
{
ObjectList * targets = GetTargets ( e , unit );
if ( ! targets )
return ;
2011-03-27 12:54:42 +02:00
for ( ObjectList :: const_iterator itr = targets -> begin (); itr != targets -> end (); ++ itr )
2011-03-26 23:45:23 +01:00
{
2011-06-15 17:33:06 +02:00
if ( IsUnit ( * itr ))
2011-03-26 23:45:23 +01:00
{
( * itr ) -> ToUnit () -> RemoveFlag ( UNIT_FIELD_FLAGS , e . action . unitFlag . flag );
sLog -> outDebug ( LOG_FILTER_DATABASE_AI , "SmartScript::ProcessAction:: SMART_ACTION_REMOVE_UNIT_FLAG. Unit %u removed flag %u to UNIT_FIELD_FLAGS" ,
( * itr ) -> GetGUIDLow (), e . action . unitFlag . flag );
}
2010-10-27 21:01:47 +02:00
}
2011-03-26 23:45:23 +01:00
delete targets ;
break ;
}
2010-10-27 21:01:47 +02:00
case SMART_ACTION_AUTO_ATTACK :
2011-03-26 23:45:23 +01:00
{
if ( ! IsSmart ())
return ;
2011-02-21 01:15:14 +01:00
2011-03-26 23:45:23 +01:00
CAST_AI ( SmartAI , me -> AI ()) -> SetAutoAttack ( e . action . autoAttack . attack ? true : false );
sLog -> outDebug ( LOG_FILTER_DATABASE_AI , "SmartScript::ProcessAction:: SMART_ACTION_AUTO_ATTACK: Creature: %u bool on = %u" ,
me -> GetGUIDLow (), e . action . autoAttack . attack );
break ;
}
2010-10-27 21:01:47 +02:00
case SMART_ACTION_ALLOW_COMBAT_MOVEMENT :
2011-03-26 23:45:23 +01:00
{
if ( ! IsSmart ())
return ;
2011-02-21 01:15:14 +01:00
2011-03-26 23:45:23 +01:00
bool move = e . action . combatMove . move ? true : false ;
CAST_AI ( SmartAI , me -> AI ()) -> SetCombatMove ( move );
sLog -> outDebug ( LOG_FILTER_DATABASE_AI , "SmartScript::ProcessAction:: SMART_ACTION_ALLOW_COMBAT_MOVEMENT: Creature %u bool on = %u" ,
me -> GetGUIDLow (), e . action . combatMove . move );
break ;
}
2010-10-27 21:01:47 +02:00
case SMART_ACTION_SET_EVENT_PHASE :
2011-03-26 23:45:23 +01:00
{
2011-06-15 17:33:06 +02:00
if ( ! GetBaseObject ())
return ;
2011-03-26 23:45:23 +01:00
SetPhase ( e . action . setEventPhase . phase );
sLog -> outDebug ( LOG_FILTER_DATABASE_AI , "SmartScript::ProcessAction:: SMART_ACTION_SET_EVENT_PHASE: Creature %u set event phase %u" ,
2011-06-15 17:33:06 +02:00
GetBaseObject () -> GetGUIDLow (), e . action . setEventPhase . phase );
2011-03-26 23:45:23 +01:00
break ;
}
2010-10-27 21:01:47 +02:00
case SMART_ACTION_INC_EVENT_PHASE :
2011-03-26 23:45:23 +01:00
{
2011-06-15 17:33:06 +02:00
if ( ! GetBaseObject ())
return ;
2011-03-26 23:45:23 +01:00
IncPhase ( e . action . incEventPhase . inc );
DecPhase ( e . action . incEventPhase . dec );
sLog -> outDebug ( LOG_FILTER_DATABASE_AI , "SmartScript::ProcessAction:: SMART_ACTION_INC_EVENT_PHASE: Creature %u inc event phase by %u, "
2011-06-15 17:33:06 +02:00
"decrease by %u" , GetBaseObject () -> GetGUIDLow (), e . action . incEventPhase . inc , e . action . incEventPhase . dec );
2011-03-26 23:45:23 +01:00
break ;
}
2010-10-27 21:01:47 +02:00
case SMART_ACTION_EVADE :
2011-03-26 23:45:23 +01:00
{
if ( ! me )
2010-10-27 21:01:47 +02:00
return ;
2011-03-26 23:45:23 +01:00
me -> AI () -> EnterEvadeMode ();
sLog -> outDebug ( LOG_FILTER_DATABASE_AI , "SmartScript::ProcessAction:: SMART_ACTION_EVADE: Creature %u EnterEvadeMode" , me -> GetGUIDLow ());
return ;
}
2010-10-27 21:01:47 +02:00
case SMART_ACTION_FLEE_FOR_ASSIST :
2011-03-26 23:45:23 +01:00
{
if ( ! me )
return ;
2011-02-21 01:15:14 +01:00
2011-03-26 23:45:23 +01:00
me -> DoFleeToGetAssistance ();
2011-09-04 18:51:16 +01:00
if ( e . action . flee . withEmote )
sCreatureTextMgr -> SendChatString ( me , sObjectMgr -> GetTrinityStringForDBCLocale ( LANG_FLEE ), CHAT_MSG_MONSTER_EMOTE );
2011-03-26 23:45:23 +01:00
sLog -> outDebug ( LOG_FILTER_DATABASE_AI , "SmartScript::ProcessAction:: SMART_ACTION_FLEE_FOR_ASSIST: Creature %u DoFleeToGetAssistance" , me -> GetGUIDLow ());
break ;
}
2010-10-27 21:01:47 +02:00
case SMART_ACTION_CALL_GROUPEVENTHAPPENS :
2011-03-26 23:45:23 +01:00
{
if ( IsPlayer ( unit ) && GetBaseObject ())
2010-10-27 21:01:47 +02:00
{
2011-03-26 23:45:23 +01:00
unit -> ToPlayer () -> GroupEventHappens ( e . action . quest . quest , GetBaseObject ());
sLog -> outDebug ( LOG_FILTER_DATABASE_AI , "SmartScript::ProcessAction: SMART_ACTION_CALL_GROUPEVENTHAPPENS: Player %u, group credit for quest %u" ,
unit -> GetGUIDLow (), e . action . quest . quest );
2010-10-27 21:01:47 +02:00
}
2011-03-26 23:45:23 +01:00
break ;
}
2010-10-27 21:01:47 +02:00
case SMART_ACTION_CALL_CASTEDCREATUREORGO :
2011-03-26 23:45:23 +01:00
{
if ( ! GetBaseObject ())
return ;
2011-02-21 01:15:14 +01:00
2011-03-26 23:45:23 +01:00
ObjectList * targets = GetTargets ( e , unit );
if ( ! targets )
return ;
2011-02-21 01:15:14 +01:00
2011-03-27 12:54:42 +02:00
for ( ObjectList :: const_iterator itr = targets -> begin (); itr != targets -> end (); ++ itr )
2011-03-26 23:45:23 +01:00
{
if ( IsPlayer (( * itr )))
2010-11-20 12:42:10 +01:00
{
2011-03-26 23:45:23 +01:00
( * itr ) -> ToPlayer () -> CastedCreatureOrGO ( e . action . castedCreatureOrGO . creature , GetBaseObject () -> GetGUID (), e . action . castedCreatureOrGO . spell );
sLog -> outDebug ( LOG_FILTER_DATABASE_AI , "SmartScript::ProcessAction: SMART_ACTION_CALL_CASTEDCREATUREORGO: Player %u, target %u, spell %u" ,
( * itr ) -> GetGUIDLow (), e . action . castedCreatureOrGO . creature , e . action . castedCreatureOrGO . spell );
2010-11-20 12:42:10 +01:00
}
2010-10-27 21:01:47 +02:00
}
2011-03-26 23:45:23 +01:00
delete targets ;
break ;
}
2010-10-27 21:01:47 +02:00
case SMART_ACTION_REMOVEAURASFROMSPELL :
2011-03-26 23:45:23 +01:00
{
ObjectList * targets = GetTargets ( e , unit );
if ( ! targets )
return ;
2011-02-21 01:15:14 +01:00
2011-03-27 12:54:42 +02:00
for ( ObjectList :: const_iterator itr = targets -> begin (); itr != targets -> end (); ++ itr )
2011-03-26 23:45:23 +01:00
{
if ( ! IsUnit (( * itr )))
continue ;
2011-02-21 01:15:14 +01:00
2011-03-26 23:45:23 +01:00
( * itr ) -> ToUnit () -> RemoveAurasDueToSpell ( e . action . removeAura . spell );
sLog -> outDebug ( LOG_FILTER_DATABASE_AI , "SmartScript::ProcessAction: SMART_ACTION_REMOVEAURASFROMSPELL: Unit %u, spell %u" ,
( * itr ) -> GetGUIDLow (), e . action . removeAura . spell );
2010-10-27 21:01:47 +02:00
}
2011-03-26 23:45:23 +01:00
delete targets ;
break ;
}
2010-10-27 21:01:47 +02:00
case SMART_ACTION_FOLLOW :
2011-03-26 23:45:23 +01:00
{
if ( ! IsSmart ())
return ;
2011-02-21 01:15:14 +01:00
2011-03-26 23:45:23 +01:00
ObjectList * targets = GetTargets ( e , unit );
if ( ! targets )
return ;
2011-02-21 01:15:14 +01:00
2011-03-27 12:54:42 +02:00
for ( ObjectList :: const_iterator itr = targets -> begin (); itr != targets -> end (); ++ itr )
2011-03-26 23:45:23 +01:00
{
if ( IsUnit (( * itr )))
2010-10-27 21:01:47 +02:00
{
2011-03-26 23:45:23 +01:00
CAST_AI ( SmartAI , me -> AI ()) -> SetFollow (( * itr ) -> ToUnit (), ( float ) e . action . follow . dist , ( float ) e . action . follow . angle , e . action . follow . credit , e . action . follow . entry , e . action . follow . creditType );
sLog -> outDebug ( LOG_FILTER_DATABASE_AI , "SmartScript::ProcessAction: SMART_ACTION_FOLLOW: Creature %u following target %u" ,
me -> GetGUIDLow (), ( * itr ) -> GetGUIDLow ());
2011-05-11 21:19:22 +02:00
break ;
2010-10-27 21:01:47 +02:00
}
}
2011-03-26 23:45:23 +01:00
delete targets ;
break ;
}
2010-10-27 21:01:47 +02:00
case SMART_ACTION_RANDOM_PHASE :
2011-03-26 23:45:23 +01:00
{
2011-06-15 17:33:06 +02:00
if ( ! GetBaseObject ())
return ;
2011-03-26 23:45:23 +01:00
uint32 phases [ SMART_ACTION_PARAM_COUNT ];
phases [ 0 ] = e . action . randomPhase . phase1 ;
phases [ 1 ] = e . action . randomPhase . phase2 ;
phases [ 2 ] = e . action . randomPhase . phase3 ;
phases [ 3 ] = e . action . randomPhase . phase4 ;
phases [ 4 ] = e . action . randomPhase . phase5 ;
phases [ 5 ] = e . action . randomPhase . phase6 ;
uint32 temp [ SMART_ACTION_PARAM_COUNT ];
uint32 count = 0 ;
for ( uint8 i = 0 ; i < SMART_ACTION_PARAM_COUNT ; i ++ )
{
if ( phases [ i ] > 0 )
{
temp [ count ] = phases [ i ];
2011-06-15 17:33:06 +02:00
++ count ;
2010-10-27 21:01:47 +02:00
}
}
2011-03-26 23:45:23 +01:00
uint32 phase = temp [ urand ( 0 , count )];
SetPhase ( phase );
sLog -> outDebug ( LOG_FILTER_DATABASE_AI , "SmartScript::ProcessAction: SMART_ACTION_RANDOM_PHASE: Creature %u sets event phase to %u" ,
2011-06-15 17:33:06 +02:00
GetBaseObject () -> GetGUIDLow (), phase );
2011-03-26 23:45:23 +01:00
break ;
}
2010-10-27 21:01:47 +02:00
case SMART_ACTION_RANDOM_PHASE_RANGE :
2011-03-26 23:45:23 +01:00
{
2011-06-15 17:33:06 +02:00
if ( ! GetBaseObject ())
return ;
2011-03-26 23:45:23 +01:00
uint32 phase = urand ( e . action . randomPhaseRange . phaseMin , e . action . randomPhaseRange . phaseMax );
SetPhase ( phase );
sLog -> outDebug ( LOG_FILTER_DATABASE_AI , "SmartScript::ProcessAction: SMART_ACTION_RANDOM_PHASE_RANGE: Creature %u sets event phase to %u" ,
2011-06-15 17:33:06 +02:00
GetBaseObject () -> GetGUIDLow (), phase );
2011-03-26 23:45:23 +01:00
break ;
}
2010-10-27 21:01:47 +02:00
case SMART_ACTION_CALL_KILLEDMONSTER :
2011-03-26 23:45:23 +01:00
{
2011-06-15 17:33:06 +02:00
Player * player = NULL ;
2011-03-26 23:45:23 +01:00
if ( me )
2011-06-15 17:33:06 +02:00
player = me -> GetLootRecipient ();
2011-02-21 01:15:14 +01:00
2011-06-15 17:33:06 +02:00
if ( me && player )
player -> RewardPlayerAndGroupAtEvent ( e . action . killedMonster . creature , player );
2011-03-26 23:45:23 +01:00
else if ( GetBaseObject ())
2010-10-27 21:01:47 +02:00
{
2011-03-26 23:45:23 +01:00
ObjectList * targets = GetTargets ( e , unit );
if ( ! targets )
2010-12-04 15:04:46 +01:00
return ;
2011-02-21 01:15:14 +01:00
2011-03-27 12:54:42 +02:00
for ( ObjectList :: const_iterator itr = targets -> begin (); itr != targets -> end (); ++ itr )
2010-10-27 21:01:47 +02:00
{
2011-06-15 17:33:06 +02:00
if ( ! IsPlayer ( * itr ))
2011-03-26 23:45:23 +01:00
continue ;
( * itr ) -> ToPlayer () -> RewardPlayerAndGroupAtEvent ( e . action . killedMonster . creature , ( * itr ) -> ToPlayer ());
sLog -> outDebug ( LOG_FILTER_DATABASE_AI , "SmartScript::ProcessAction: SMART_ACTION_CALL_KILLEDMONSTER: Player %u, Killcredit: %u" ,
( * itr ) -> GetGUIDLow (), e . action . killedMonster . creature );
2010-10-27 21:01:47 +02:00
}
2011-02-21 01:15:14 +01:00
2011-03-26 23:45:23 +01:00
delete targets ;
2010-10-27 21:01:47 +02:00
}
2011-03-26 23:45:23 +01:00
else if ( trigger && IsPlayer ( unit ))
2010-10-27 21:01:47 +02:00
{
2011-03-26 23:45:23 +01:00
unit -> ToPlayer () -> RewardPlayerAndGroupAtEvent ( e . action . killedMonster . creature , unit );
sLog -> outDebug ( LOG_FILTER_DATABASE_AI , "SmartScript::ProcessAction: SMART_ACTION_CALL_KILLEDMONSTER: (trigger == true) Player %u, Killcredit: %u" ,
unit -> GetGUIDLow (), e . action . killedMonster . creature );
}
break ;
}
case SMART_ACTION_SET_INST_DATA :
{
WorldObject * obj = GetBaseObject ();
if ( ! obj )
obj = unit ;
2011-02-21 01:15:14 +01:00
2011-03-26 23:45:23 +01:00
if ( ! obj )
return ;
2011-02-21 01:15:14 +01:00
2011-06-15 17:33:06 +02:00
InstanceScript * instance = obj -> GetInstanceScript ();
if ( ! instance )
2011-03-26 23:45:23 +01:00
{
sLog -> outErrorDb ( "SmartScript: Event %u attempt to set instance data without instance script. EntryOrGuid %d" , e . GetEventType (), e . entryOrGuid );
return ;
}
2011-02-21 01:15:14 +01:00
2011-06-15 17:33:06 +02:00
instance -> SetData ( e . action . setInstanceData . field , e . action . setInstanceData . data );
2011-03-26 23:45:23 +01:00
sLog -> outDebug ( LOG_FILTER_DATABASE_AI , "SmartScript::ProcessAction: SMART_ACTION_SET_INST_DATA: Field: %u, data: %u" ,
e . action . setInstanceData . field , e . action . setInstanceData . data );
break ;
}
case SMART_ACTION_SET_INST_DATA64 :
{
WorldObject * obj = GetBaseObject ();
if ( ! obj )
obj = unit ;
2011-02-21 01:15:14 +01:00
2011-03-26 23:45:23 +01:00
if ( ! obj )
return ;
2010-12-13 22:37:56 +01:00
2011-06-15 17:33:06 +02:00
InstanceScript * instance = obj -> GetInstanceScript ();
if ( ! instance )
2011-03-26 23:45:23 +01:00
{
sLog -> outErrorDb ( "SmartScript: Event %u attempt to set instance data without instance script. EntryOrGuid %d" , e . GetEventType (), e . entryOrGuid );
return ;
2010-10-27 21:01:47 +02:00
}
2011-03-26 23:45:23 +01:00
ObjectList * targets = GetTargets ( e , unit );
if ( ! targets )
return ;
2011-06-15 17:33:06 +02:00
instance -> SetData64 ( e . action . setInstanceData64 . field , targets -> front () -> GetGUID ());
2011-03-26 23:45:23 +01:00
sLog -> outDebug ( LOG_FILTER_DATABASE_AI , "SmartScript::ProcessAction: SMART_ACTION_SET_INST_DATA64: Field: %u, data: " UI64FMTD ,
e . action . setInstanceData64 . field , targets -> front () -> GetGUID ());
delete targets ;
break ;
}
2010-10-27 21:01:47 +02:00
case SMART_ACTION_UPDATE_TEMPLATE :
2011-03-26 23:45:23 +01:00
{
if ( ! me || me -> GetEntry () == e . action . updateTemplate . creature )
return ;
2011-02-21 01:15:14 +01:00
2011-03-26 23:45:23 +01:00
me -> UpdateEntry ( e . action . updateTemplate . creature , e . action . updateTemplate . team ? HORDE : ALLIANCE );
sLog -> outDebug ( LOG_FILTER_DATABASE_AI , "SmartScript::ProcessAction: SMART_ACTION_UPDATE_TEMPLATE: Creature %u, Template: %u, Team: %u" ,
2011-05-11 11:12:26 +06:00
me -> GetGUIDLow (), me -> GetEntry (), e . action . updateTemplate . team ? HORDE : ALLIANCE );
2011-03-26 23:45:23 +01:00
break ;
}
2010-10-27 21:01:47 +02:00
case SMART_ACTION_DIE :
2011-03-26 23:45:23 +01:00
{
if ( me && ! me -> isDead ())
2010-10-27 21:01:47 +02:00
{
2011-03-26 23:45:23 +01:00
me -> Kill ( me );
sLog -> outDebug ( LOG_FILTER_DATABASE_AI , "SmartScript::ProcessAction: SMART_ACTION_DIE: Creature %u" , me -> GetGUIDLow ());
2010-10-27 21:01:47 +02:00
}
2011-03-26 23:45:23 +01:00
break ;
}
2010-10-27 21:01:47 +02:00
case SMART_ACTION_SET_IN_COMBAT_WITH_ZONE :
2011-03-26 23:45:23 +01:00
{
if ( me )
2010-10-27 21:01:47 +02:00
{
2011-03-26 23:45:23 +01:00
me -> SetInCombatWithZone ();
sLog -> outDebug ( LOG_FILTER_DATABASE_AI , "SmartScript::ProcessAction: SMART_ACTION_SET_IN_COMBAT_WITH_ZONE: Creature %u" , me -> GetGUIDLow ());
2010-10-27 21:01:47 +02:00
}
2011-03-26 23:45:23 +01:00
break ;
}
2010-10-27 21:01:47 +02:00
case SMART_ACTION_CALL_FOR_HELP :
2011-03-26 23:45:23 +01:00
{
if ( me )
2010-10-27 21:01:47 +02:00
{
2011-03-26 23:45:23 +01:00
me -> CallForHelp (( float ) e . action . callHelp . range );
sLog -> outDebug ( LOG_FILTER_DATABASE_AI , "SmartScript::ProcessAction: SMART_ACTION_CALL_FOR_HELP: Creature %u" , me -> GetGUIDLow ());
2010-10-27 21:01:47 +02:00
}
2011-03-26 23:45:23 +01:00
break ;
}
2010-10-27 21:01:47 +02:00
case SMART_ACTION_SET_SHEATH :
2011-03-26 23:45:23 +01:00
{
if ( me )
2010-10-27 21:01:47 +02:00
{
2011-03-26 23:45:23 +01:00
me -> SetSheath ( SheathState ( e . action . setSheath . sheath ));
sLog -> outDebug ( LOG_FILTER_DATABASE_AI , "SmartScript::ProcessAction: SMART_ACTION_SET_SHEATH: Creature %u, State: %u" ,
me -> GetGUIDLow (), e . action . setSheath . sheath );
2010-10-27 21:01:47 +02:00
}
2011-03-26 23:45:23 +01:00
break ;
}
2010-10-27 21:01:47 +02:00
case SMART_ACTION_FORCE_DESPAWN :
2011-03-26 23:45:23 +01:00
{
if ( ! IsSmart ())
return ;
2011-06-15 17:33:06 +02:00
2011-03-26 23:45:23 +01:00
CAST_AI ( SmartAI , me -> AI ()) -> SetDespawnTime ( e . action . forceDespawn . delay + 1 ); //next tick
CAST_AI ( SmartAI , me -> AI ()) -> StartDespawn ();
break ;
}
2010-10-27 21:01:47 +02:00
case SMART_ACTION_SET_INGAME_PHASE_MASK :
2011-03-26 23:45:23 +01:00
{
if ( GetBaseObject ())
GetBaseObject () -> SetPhaseMask ( e . action . ingamePhaseMask . mask , true );
break ;
}
2010-10-27 21:01:47 +02:00
case SMART_ACTION_MOUNT_TO_ENTRY_OR_MODEL :
2011-03-26 23:45:23 +01:00
{
ObjectList * targets = GetTargets ( e , unit );
if ( ! targets )
return ;
2011-06-15 17:33:06 +02:00
2011-03-27 12:54:42 +02:00
for ( ObjectList :: const_iterator itr = targets -> begin (); itr != targets -> end (); ++ itr )
2010-10-27 21:01:47 +02:00
{
2011-06-15 17:33:06 +02:00
if ( ! IsUnit ( * itr ))
2011-06-12 02:30:32 +02:00
continue ;
2011-06-15 17:33:06 +02:00
2011-03-26 23:45:23 +01:00
if ( e . action . morphOrMount . creature || e . action . morphOrMount . model )
2010-10-27 21:01:47 +02:00
{
2011-03-26 23:45:23 +01:00
if ( e . action . morphOrMount . creature > 0 )
2010-10-27 21:01:47 +02:00
{
2011-04-28 22:57:08 +02:00
if ( CreatureTemplate const * cInfo = sObjectMgr -> GetCreatureTemplate ( e . action . morphOrMount . creature ))
2010-10-27 21:01:47 +02:00
{
2011-03-26 23:45:23 +01:00
uint32 display_id = sObjectMgr -> ChooseDisplayId ( 0 , cInfo );
( * itr ) -> ToUnit () -> Mount ( display_id );
2010-10-27 21:01:47 +02:00
}
}
else
2011-03-26 23:45:23 +01:00
( * itr ) -> ToUnit () -> Mount ( e . action . morphOrMount . model );
2010-10-27 21:01:47 +02:00
}
else
2011-12-19 22:06:29 +01:00
( * itr ) -> ToUnit () -> Dismount ();
2010-10-27 21:01:47 +02:00
}
2011-03-26 23:45:23 +01:00
delete targets ;
break ;
}
case SMART_ACTION_SET_INVINCIBILITY_HP_LEVEL :
{
2011-06-15 17:33:06 +02:00
if ( ! me )
2011-03-26 23:45:23 +01:00
return ;
2011-06-15 17:33:06 +02:00
2011-03-27 12:54:42 +02:00
if ( e . action . invincHP . percent )
mInvinceabilityHpLevel = me -> CountPctFromMaxHealth ( e . action . invincHP . percent );
2011-03-26 23:45:23 +01:00
else
mInvinceabilityHpLevel = e . action . invincHP . minHP ;
break ;
}
2010-10-27 21:01:47 +02:00
case SMART_ACTION_SET_DATA :
2011-03-26 23:45:23 +01:00
{
ObjectList * targets = GetTargets ( e , unit );
if ( ! targets )
return ;
2011-03-27 12:54:42 +02:00
for ( ObjectList :: const_iterator itr = targets -> begin (); itr != targets -> end (); ++ itr )
2010-10-27 21:01:47 +02:00
{
2011-03-27 12:54:42 +02:00
if ( IsCreature ( * itr ))
2011-03-26 23:45:23 +01:00
( * itr ) -> ToCreature () -> AI () -> SetData ( e . action . setData . field , e . action . setData . data );
2011-03-27 12:54:42 +02:00
else if ( IsGameObject ( * itr ))
2011-03-26 23:45:23 +01:00
( * itr ) -> ToGameObject () -> AI () -> SetData ( e . action . setData . field , e . action . setData . data );
2010-10-27 21:01:47 +02:00
}
2011-03-26 23:45:23 +01:00
delete targets ;
break ;
}
2010-10-27 21:01:47 +02:00
case SMART_ACTION_MOVE_FORWARD :
2011-03-26 23:45:23 +01:00
{
if ( ! me )
return ;
2011-06-15 17:33:06 +02:00
2011-03-26 23:45:23 +01:00
float x , y , z ;
me -> GetClosePoint ( x , y , z , me -> GetObjectSize () / 3 , ( float ) e . action . moveRandom . distance );
me -> GetMotionMaster () -> MovePoint ( SMART_RANDOM_POINT , x , y , z );
break ;
}
2010-10-27 21:01:47 +02:00
case SMART_ACTION_SET_VISIBILITY :
2011-03-26 23:45:23 +01:00
{
if ( me )
me -> SetVisible ( e . action . visibility . state ? true : false );
break ;
}
2010-10-27 21:01:47 +02:00
case SMART_ACTION_SET_ACTIVE :
2011-03-26 23:45:23 +01:00
{
if ( GetBaseObject ())
GetBaseObject () -> setActive ( true );
break ;
}
2010-10-27 21:01:47 +02:00
case SMART_ACTION_ATTACK_START :
2011-03-26 23:45:23 +01:00
{
if ( ! me )
return ;
ObjectList * targets = GetTargets ( e , unit );
if ( ! targets )
return ;
2011-03-27 12:54:42 +02:00
for ( ObjectList :: const_iterator itr = targets -> begin (); itr != targets -> end (); ++ itr )
2010-10-27 21:01:47 +02:00
{
2011-03-26 23:45:23 +01:00
if ( IsUnit ( * itr ))
2010-10-27 21:01:47 +02:00
{
2011-03-26 23:45:23 +01:00
me -> AI () -> AttackStart (( * itr ) -> ToUnit ());
2011-05-11 21:19:22 +02:00
break ;
2010-10-27 21:01:47 +02:00
}
}
2011-06-15 17:33:06 +02:00
2011-05-11 21:19:22 +02:00
delete targets ;
2011-03-26 23:45:23 +01:00
break ;
}
2010-10-27 21:01:47 +02:00
case SMART_ACTION_SUMMON_CREATURE :
2011-03-26 23:45:23 +01:00
{
float x , y , z , o ;
ObjectList * targets = GetTargets ( e , unit );
if ( targets )
2010-10-27 21:01:47 +02:00
{
2011-03-27 12:54:42 +02:00
for ( ObjectList :: const_iterator itr = targets -> begin (); itr != targets -> end (); ++ itr )
2010-10-27 21:01:47 +02:00
{
2011-03-26 23:45:23 +01:00
if ( ! IsUnit ( * itr ))
continue ;
( * itr ) -> GetPosition ( x , y , z , o );
if ( Creature * summon = GetBaseObject () -> SummonCreature ( e . action . summonCreature . creature , x , y , z , o , ( TempSummonType ) e . action . summonCreature . type , e . action . summonCreature . duration ))
if ( unit && e . action . summonCreature . attackInvoker )
summon -> AI () -> AttackStart (( * itr ) -> ToUnit ());
2010-10-27 21:01:47 +02:00
}
2011-03-26 23:45:23 +01:00
delete targets ;
2010-10-27 21:01:47 +02:00
}
2011-03-26 23:45:23 +01:00
if ( e . GetTargetType () != SMART_TARGET_POSITION )
return ;
if ( Creature * summon = GetBaseObject () -> SummonCreature ( e . action . summonCreature . creature , e . target . x , e . target . y , e . target . z , e . target . o , ( TempSummonType ) e . action . summonCreature . type , e . action . summonCreature . duration ))
if ( unit && e . action . summonCreature . attackInvoker )
summon -> AI () -> AttackStart ( unit );
break ;
}
2010-10-27 21:01:47 +02:00
case SMART_ACTION_SUMMON_GO :
2011-03-26 23:45:23 +01:00
{
if ( ! GetBaseObject ())
return ;
float x , y , z , o ;
ObjectList * targets = GetTargets ( e , unit );
if ( targets )
2010-10-27 21:01:47 +02:00
{
2011-03-27 12:54:42 +02:00
for ( ObjectList :: const_iterator itr = targets -> begin (); itr != targets -> end (); ++ itr )
2010-10-27 21:01:47 +02:00
{
2011-03-26 23:45:23 +01:00
if ( ! IsUnit ( * itr ))
continue ;
( * itr ) -> GetPosition ( x , y , z , o );
GetBaseObject () -> SummonGameObject ( e . action . summonGO . entry , x , y , z , o , 0 , 0 , 0 , 0 , e . action . summonGO . despawnTime );
2010-10-27 21:01:47 +02:00
}
2011-03-26 23:45:23 +01:00
delete targets ;
2010-10-27 21:01:47 +02:00
}
2011-03-26 23:45:23 +01:00
if ( e . GetTargetType () != SMART_TARGET_POSITION )
return ;
GetBaseObject () -> SummonGameObject ( e . action . summonGO . entry , e . target . x , e . target . y , e . target . z , e . target . o , 0 , 0 , 0 , 0 , e . action . summonGO . despawnTime );
break ;
}
2010-10-27 21:01:47 +02:00
case SMART_ACTION_KILL_UNIT :
2011-03-26 23:45:23 +01:00
{
ObjectList * targets = GetTargets ( e , unit );
if ( ! targets )
return ;
2011-06-15 17:33:06 +02:00
2011-03-27 12:54:42 +02:00
for ( ObjectList :: const_iterator itr = targets -> begin (); itr != targets -> end (); ++ itr )
2010-10-27 21:01:47 +02:00
{
2011-03-26 23:45:23 +01:00
if ( ! IsUnit ( * itr ))
continue ;
( * itr ) -> ToUnit () -> Kill (( * itr ) -> ToUnit ());
2010-10-27 21:01:47 +02:00
}
2011-03-26 23:45:23 +01:00
delete targets ;
break ;
}
2010-10-27 21:01:47 +02:00
case SMART_ACTION_INSTALL_AI_TEMPLATE :
2011-03-26 23:45:23 +01:00
{
InstallTemplate ( e );
break ;
}
2010-10-27 21:01:47 +02:00
case SMART_ACTION_ADD_ITEM :
2011-03-26 23:45:23 +01:00
{
ObjectList * targets = GetTargets ( e , unit );
if ( ! targets )
return ;
2011-03-27 12:54:42 +02:00
for ( ObjectList :: const_iterator itr = targets -> begin (); itr != targets -> end (); ++ itr )
2010-10-27 21:01:47 +02:00
{
2011-03-26 23:45:23 +01:00
if ( ! IsPlayer ( * itr ))
continue ;
( * itr ) -> ToPlayer () -> AddItem ( e . action . item . entry , e . action . item . count );
2010-10-27 21:01:47 +02:00
}
2011-03-26 23:45:23 +01:00
delete targets ;
break ;
}
2010-10-27 21:01:47 +02:00
case SMART_ACTION_REMOVE_ITEM :
2011-03-26 23:45:23 +01:00
{
ObjectList * targets = GetTargets ( e , unit );
if ( ! targets )
return ;
2011-03-27 12:54:42 +02:00
for ( ObjectList :: const_iterator itr = targets -> begin (); itr != targets -> end (); ++ itr )
2010-10-27 21:01:47 +02:00
{
2011-03-26 23:45:23 +01:00
if ( ! IsPlayer ( * itr ))
continue ;
( * itr ) -> ToPlayer () -> DestroyItemCount ( e . action . item . entry , e . action . item . count , true );
2010-10-27 21:01:47 +02:00
}
2011-03-26 23:45:23 +01:00
delete targets ;
break ;
}
2010-10-27 21:01:47 +02:00
case SMART_ACTION_STORE_VARIABLE_DECIMAL :
2011-03-26 23:45:23 +01:00
{
if ( mStoredDecimals . find ( e . action . storeVar . id ) != mStoredDecimals . end ())
mStoredDecimals . erase ( e . action . storeVar . id );
mStoredDecimals [ e . action . storeVar . id ] = e . action . storeVar . number ;
break ;
}
2010-10-27 21:01:47 +02:00
case SMART_ACTION_STORE_TARGET_LIST :
2011-03-26 23:45:23 +01:00
{
ObjectList * targets = GetTargets ( e , unit );
StoreTargetList ( targets , e . action . storeTargets . id );
break ;
}
2010-10-27 21:01:47 +02:00
case SMART_ACTION_TELEPORT :
2011-03-26 23:45:23 +01:00
{
ObjectList * targets = GetTargets ( e , unit );
if ( ! targets )
return ;
2011-03-27 12:54:42 +02:00
for ( ObjectList :: const_iterator itr = targets -> begin (); itr != targets -> end (); ++ itr )
2010-10-27 21:01:47 +02:00
{
2011-03-26 23:45:23 +01:00
if ( ! IsPlayer ( * itr ))
continue ;
( * itr ) -> ToPlayer () -> TeleportTo ( e . action . teleport . mapID , e . target . x , e . target . y , e . target . z , e . target . o );
2010-10-27 21:01:47 +02:00
}
2011-03-26 23:45:23 +01:00
delete targets ;
break ;
}
2010-10-27 21:01:47 +02:00
case SMART_ACTION_SET_FLY :
2011-03-26 23:45:23 +01:00
{
if ( ! IsSmart ())
return ;
2011-06-15 17:33:06 +02:00
2011-03-26 23:45:23 +01:00
CAST_AI ( SmartAI , me -> AI ()) -> SetFly ( e . action . setFly . fly ? true : false );
break ;
}
2010-10-27 21:01:47 +02:00
case SMART_ACTION_SET_RUN :
2011-03-26 23:45:23 +01:00
{
if ( ! IsSmart ())
return ;
2011-06-15 17:33:06 +02:00
2011-03-26 23:45:23 +01:00
CAST_AI ( SmartAI , me -> AI ()) -> SetRun ( e . action . setRun . run ? true : false );
break ;
}
2011-08-21 00:07:38 -03:00
case SMART_ACTION_SET_SWIM :
2011-03-26 23:45:23 +01:00
{
if ( ! IsSmart ())
return ;
2011-06-15 17:33:06 +02:00
2011-08-21 00:07:38 -03:00
CAST_AI ( SmartAI , me -> AI ()) -> SetSwim ( e . action . setSwim . swim ? true : false );
2011-03-26 23:45:23 +01:00
break ;
}
2010-10-27 21:01:47 +02:00
case SMART_ACTION_WP_START :
2011-03-26 23:45:23 +01:00
{
if ( ! IsSmart ())
return ;
2011-06-15 17:33:06 +02:00
2011-03-26 23:45:23 +01:00
bool run = e . action . wpStart . run ? true : false ;
uint32 entry = e . action . wpStart . pathID ;
bool repeat = e . action . wpStart . repeat ? true : false ;
ObjectList * targets = GetTargets ( e , unit );
StoreTargetList ( targets , SMART_ESCORT_TARGETS );
me -> SetReactState (( ReactStates ) e . action . wpStart . reactState );
CAST_AI ( SmartAI , me -> AI ()) -> StartPath ( run , entry , repeat , unit );
uint32 quest = e . action . wpStart . quest ;
uint32 DespawnTime = e . action . wpStart . despawnTime ;
CAST_AI ( SmartAI , me -> AI ()) -> mEscortQuestID = quest ;
CAST_AI ( SmartAI , me -> AI ()) -> SetDespawnTime ( DespawnTime );
break ;
}
2010-10-27 21:01:47 +02:00
case SMART_ACTION_WP_PAUSE :
2011-03-26 23:45:23 +01:00
{
if ( ! IsSmart ())
return ;
2011-06-15 17:33:06 +02:00
2011-03-26 23:45:23 +01:00
uint32 delay = e . action . wpPause . delay ;
CAST_AI ( SmartAI , me -> AI ()) -> PausePath ( delay , e . GetEventType () == SMART_EVENT_WAYPOINT_REACHED ? false : true );
break ;
}
2010-10-27 21:01:47 +02:00
case SMART_ACTION_WP_STOP :
2011-03-26 23:45:23 +01:00
{
if ( ! IsSmart ())
return ;
2011-06-15 17:33:06 +02:00
2011-03-26 23:45:23 +01:00
uint32 DespawnTime = e . action . wpStop . despawnTime ;
uint32 quest = e . action . wpStop . quest ;
bool fail = e . action . wpStop . fail ? true : false ;
CAST_AI ( SmartAI , me -> AI ()) -> StopPath ( DespawnTime , quest , fail );
break ;
}
2010-10-27 21:01:47 +02:00
case SMART_ACTION_WP_RESUME :
2011-03-26 23:45:23 +01:00
{
if ( ! IsSmart ())
return ;
2011-06-15 17:33:06 +02:00
2011-03-26 23:45:23 +01:00
CAST_AI ( SmartAI , me -> AI ()) -> ResumePath ();
break ;
}
2010-10-27 21:01:47 +02:00
case SMART_ACTION_SET_ORIENTATION :
2011-03-26 23:45:23 +01:00
{
if ( ! me )
return ;
ObjectList * targets = GetTargets ( e , unit );
if ( e . GetTargetType () == SMART_TARGET_SELF )
2011-04-22 12:19:34 +02:00
me -> SetFacing ( me -> GetHomePosition (). GetOrientation (), NULL );
2011-03-26 23:45:23 +01:00
else if ( e . GetTargetType () == SMART_TARGET_POSITION )
me -> SetFacing ( e . target . o , NULL );
else if ( targets && ! targets -> empty ())
me -> SetFacing ( 0 , ( * targets -> begin ()));
delete targets ;
break ;
}
2010-10-27 21:01:47 +02:00
case SMART_ACTION_PLAYMOVIE :
2011-03-26 23:45:23 +01:00
{
ObjectList * targets = GetTargets ( e , unit );
if ( ! targets )
return ;
2010-10-27 21:01:47 +02:00
2011-03-27 12:54:42 +02:00
for ( ObjectList :: const_iterator itr = targets -> begin (); itr != targets -> end (); ++ itr )
2010-10-27 21:01:47 +02:00
{
2011-03-26 23:45:23 +01:00
if ( ! IsPlayer ( * itr ))
continue ;
2011-03-27 12:54:42 +02:00
2011-03-26 23:45:23 +01:00
( * itr ) -> ToPlayer () -> SendMovieStart ( e . action . movie . entry );
2010-10-27 21:01:47 +02:00
}
2011-03-26 23:45:23 +01:00
delete targets ;
break ;
}
case SMART_ACTION_MOVE_TO_POS :
{
if ( ! IsSmart ())
return ;
2011-06-15 17:33:06 +02:00
2011-12-30 19:01:22 +01:00
WorldObject * target = NULL ;
if ( e . GetTargetType () == SMART_TARGET_CREATURE_RANGE || e . GetTargetType () == SMART_TARGET_CREATURE_GUID ||
e . GetTargetType () == SMART_TARGET_CREATURE_DISTANCE || e . GetTargetType () == SMART_TARGET_GAMEOBJECT_RANGE ||
e . GetTargetType () == SMART_TARGET_GAMEOBJECT_GUID || e . GetTargetType () == SMART_TARGET_GAMEOBJECT_DISTANCE ||
2011-12-27 20:37:42 -05:00
e . GetTargetType () == SMART_TARGET_CLOSEST_CREATURE || e . GetTargetType () == SMART_TARGET_CLOSEST_GAMEOBJECT ||
e . GetTargetType () == SMART_TARGET_OWNER_OR_SUMMONER )
2011-12-27 20:25:50 -05:00
{
ObjectList * targets = GetTargets ( e , unit );
if ( ! targets )
return ;
2011-12-30 19:01:22 +01:00
target = targets -> front ();
2011-12-27 20:25:50 -05:00
}
2011-03-26 23:45:23 +01:00
bool run = e . action . setRun . run ? true : false ;
CAST_AI ( SmartAI , me -> AI ()) -> SetRun ( run );
2011-12-27 20:25:50 -05:00
if ( ! target )
me -> GetMotionMaster () -> MovePoint ( 0 , e . target . x , e . target . y , e . target . z );
else
me -> GetMotionMaster () -> MovePoint ( 0 , target -> GetPositionX (), target -> GetPositionY (), target -> GetPositionZ ());
2011-03-26 23:45:23 +01:00
break ;
}
2010-10-27 21:01:47 +02:00
case SMART_ACTION_RESPAWN_TARGET :
{
ObjectList * targets = GetTargets ( e , unit );
2011-03-26 23:45:23 +01:00
if ( ! targets )
return ;
2011-03-27 12:54:42 +02:00
for ( ObjectList :: const_iterator itr = targets -> begin (); itr != targets -> end (); ++ itr )
2010-10-27 21:01:47 +02:00
{
2011-03-26 23:45:23 +01:00
if ( IsCreature ( * itr ))
2010-10-27 21:01:47 +02:00
( * itr ) -> ToCreature () -> Respawn ();
2011-03-26 23:45:23 +01:00
else if ( IsGameObject ( * itr ))
2011-10-23 12:55:17 +01:00
( * itr ) -> ToGameObject () -> SetRespawnTime ( e . action . RespawnTarget . goRespawnTime );
2010-10-27 21:01:47 +02:00
}
2011-03-26 23:45:23 +01:00
delete targets ;
2010-10-27 21:01:47 +02:00
break ;
}
case SMART_ACTION_CLOSE_GOSSIP :
2011-03-26 23:45:23 +01:00
{
ObjectList * targets = GetTargets ( e , unit );
if ( ! targets )
return ;
2011-03-27 12:54:42 +02:00
for ( ObjectList :: const_iterator itr = targets -> begin (); itr != targets -> end (); ++ itr )
2011-03-26 23:45:23 +01:00
if ( IsPlayer ( * itr ))
2011-05-26 23:57:17 +02:00
( * itr ) -> ToPlayer () -> PlayerTalkClass -> SendCloseGossip ();
2011-03-26 23:45:23 +01:00
delete targets ;
break ;
}
2010-10-27 21:01:47 +02:00
case SMART_ACTION_EQUIP :
2011-03-26 23:45:23 +01:00
{
ObjectList * targets = GetTargets ( e , unit );
if ( ! targets )
return ;
2011-03-27 12:54:42 +02:00
for ( ObjectList :: const_iterator itr = targets -> begin (); itr != targets -> end (); ++ itr )
2010-10-27 21:01:47 +02:00
{
2011-06-12 02:30:32 +02:00
if ( Creature * npc = ( * itr ) -> ToCreature ())
2010-10-27 21:01:47 +02:00
{
2011-03-26 23:45:23 +01:00
uint32 slot [ 3 ];
if ( e . action . equip . entry )
2010-10-27 21:01:47 +02:00
{
2011-03-27 12:54:42 +02:00
EquipmentInfo const * einfo = sObjectMgr -> GetEquipmentInfo ( e . action . equip . entry );
2011-03-26 23:45:23 +01:00
if ( ! einfo )
2010-11-06 23:08:33 +01:00
{
2011-03-26 23:45:23 +01:00
sLog -> outErrorDb ( "SmartScript: SMART_ACTION_EQUIP uses non-existent equipment info entry %u" , e . action . equip . entry );
return ;
2010-11-06 23:08:33 +01:00
}
2011-03-26 23:45:23 +01:00
npc -> SetCurrentEquipmentId ( e . action . equip . entry );
2011-04-28 22:34:40 +02:00
slot [ 0 ] = einfo -> ItemEntry [ 0 ];
slot [ 1 ] = einfo -> ItemEntry [ 1 ];
slot [ 2 ] = einfo -> ItemEntry [ 2 ];
2011-03-26 23:45:23 +01:00
}
else
{
slot [ 0 ] = e . action . equip . slot1 ;
slot [ 1 ] = e . action . equip . slot2 ;
slot [ 2 ] = e . action . equip . slot3 ;
2010-10-27 21:01:47 +02:00
}
2011-03-26 23:45:23 +01:00
if ( ! e . action . equip . mask || e . action . equip . mask & 1 )
npc -> SetUInt32Value ( UNIT_VIRTUAL_ITEM_SLOT_ID + 0 , slot [ 0 ]);
if ( ! e . action . equip . mask || e . action . equip . mask & 2 )
npc -> SetUInt32Value ( UNIT_VIRTUAL_ITEM_SLOT_ID + 1 , slot [ 1 ]);
if ( ! e . action . equip . mask || e . action . equip . mask & 4 )
npc -> SetUInt32Value ( UNIT_VIRTUAL_ITEM_SLOT_ID + 2 , slot [ 2 ]);
2010-10-27 21:01:47 +02:00
}
}
2011-03-26 23:45:23 +01:00
delete targets ;
break ;
}
case SMART_ACTION_CREATE_TIMED_EVENT :
{
SmartEvent ne ;
ne . type = ( SMART_EVENT ) SMART_EVENT_UPDATE ;
ne . event_chance = e . action . timeEvent . chance ;
if ( ! ne . event_chance ) ne . event_chance = 100 ;
ne . minMaxRepeat . min = e . action . timeEvent . min ;
ne . minMaxRepeat . max = e . action . timeEvent . max ;
ne . minMaxRepeat . repeatMin = e . action . timeEvent . repeatMin ;
ne . minMaxRepeat . repeatMax = e . action . timeEvent . repeatMax ;
2011-05-12 10:40:53 +02:00
ne . event_flags = 0 ;
2011-03-26 23:45:23 +01:00
if ( ! ne . minMaxRepeat . repeatMin && ! ne . minMaxRepeat . repeatMax )
ne . event_flags |= SMART_EVENT_FLAG_NOT_REPEATABLE ;
SmartAction ac ;
ac . type = ( SMART_ACTION ) SMART_ACTION_TRIGGER_TIMED_EVENT ;
ac . timeEvent . id = e . action . timeEvent . id ;
SmartScriptHolder ev ;
ev . event = ne ;
ev . event_id = e . action . timeEvent . id ;
ev . target = e . target ;
ev . action = ac ;
InitTimer ( ev );
mStoredEvents . push_back ( ev );
break ;
}
2010-10-27 21:01:47 +02:00
case SMART_ACTION_TRIGGER_TIMED_EVENT :
2011-03-26 23:45:23 +01:00
ProcessEventsFor (( SMART_EVENT ) SMART_EVENT_TIMED_EVENT_TRIGGERED , NULL , e . action . timeEvent . id );
break ;
2010-10-27 21:01:47 +02:00
case SMART_ACTION_REMOVE_TIMED_EVENT :
2011-03-26 23:45:23 +01:00
mRemIDs . push_back ( e . action . timeEvent . id );
break ;
2010-10-27 21:01:47 +02:00
case SMART_ACTION_OVERRIDE_SCRIPT_BASE_OBJECT :
2011-03-26 23:45:23 +01:00
{
ObjectList * targets = GetTargets ( e , unit );
if ( ! targets )
return ;
2011-03-27 12:54:42 +02:00
for ( ObjectList :: iterator itr = targets -> begin (); itr != targets -> end (); ++ itr )
2010-10-27 21:01:47 +02:00
{
2011-03-26 23:45:23 +01:00
if ( IsCreature ( * itr ))
2010-10-27 21:01:47 +02:00
{
2011-03-26 23:45:23 +01:00
if ( ! meOrigGUID )
meOrigGUID = me ? me -> GetGUID () : 0 ;
if ( ! goOrigGUID )
goOrigGUID = go ? go -> GetGUID () : 0 ;
go = NULL ;
me = ( * itr ) -> ToCreature ();
2011-05-12 10:40:53 +02:00
break ;
2011-03-26 23:45:23 +01:00
}
else if ( IsGameObject ( * itr ))
{
if ( ! meOrigGUID )
meOrigGUID = me ? me -> GetGUID () : 0 ;
if ( ! goOrigGUID )
goOrigGUID = go ? go -> GetGUID () : 0 ;
go = ( * itr ) -> ToGameObject ();
me = NULL ;
2011-05-12 10:40:53 +02:00
break ;
2010-10-27 21:01:47 +02:00
}
}
2011-03-26 23:45:23 +01:00
delete targets ;
break ;
}
2010-10-27 21:01:47 +02:00
case SMART_ACTION_RESET_SCRIPT_BASE_OBJECT :
ResetBaseObject ();
break ;
case SMART_ACTION_CALL_SCRIPT_RESET :
OnReset ();
break ;
2010-11-03 14:10:16 +01:00
case SMART_ACTION_CALL_TIMED_ACTIONLIST :
2011-03-26 23:45:23 +01:00
{
if ( e . GetTargetType () == SMART_TARGET_NONE )
2010-11-03 14:10:16 +01:00
{
2011-03-26 23:45:23 +01:00
sLog -> outErrorDb ( "SmartScript: Entry %d SourceType %u Event %u Action %u is using TARGET_NONE(0) for Script9 target. Please correct target_type in database." , e . entryOrGuid , e . GetScriptType (), e . GetEventType (), e . GetActionType ());
return ;
}
ObjectList * targets = GetTargets ( e , unit );
if ( targets )
{
2011-03-27 12:54:42 +02:00
for ( ObjectList :: iterator itr = targets -> begin (); itr != targets -> end (); ++ itr )
2010-12-07 18:31:34 +01:00
{
2011-03-26 23:45:23 +01:00
if ( Creature * target = ( * itr ) -> ToCreature ())
2010-12-07 18:31:34 +01:00
{
2011-03-26 23:45:23 +01:00
if ( IsSmart ( target ))
CAST_AI ( SmartAI , target -> AI ()) -> SetScript9 ( e , e . action . timedActionList . id , GetLastInvoker ());
}
2011-11-23 17:55:16 +01:00
else if ( GameObject * goTarget = ( * itr ) -> ToGameObject ())
2011-03-26 23:45:23 +01:00
{
2011-11-23 17:55:16 +01:00
if ( IsSmartGO ( goTarget ))
2011-12-10 13:44:06 +01:00
CAST_AI ( SmartGameObjectAI , goTarget -> AI ()) -> SetScript9 ( e , e . action . timedActionList . id , GetLastInvoker ());
2010-12-07 18:31:34 +01:00
}
}
2011-03-26 23:45:23 +01:00
delete targets ;
2010-11-03 14:10:16 +01:00
}
2011-03-26 23:45:23 +01:00
break ;
}
2010-11-03 14:10:16 +01:00
case SMART_ACTION_SET_NPC_FLAG :
2011-03-26 23:45:23 +01:00
{
ObjectList * targets = GetTargets ( e , unit );
if ( ! targets )
return ;
2011-03-27 12:54:42 +02:00
for ( ObjectList :: const_iterator itr = targets -> begin (); itr != targets -> end (); ++ itr )
2011-03-26 23:45:23 +01:00
if ( IsUnit ( * itr ))
( * itr ) -> ToUnit () -> SetUInt32Value ( UNIT_NPC_FLAGS , e . action . unitFlag . flag );
delete targets ;
break ;
}
2010-11-03 14:10:16 +01:00
case SMART_ACTION_ADD_NPC_FLAG :
2011-03-26 23:45:23 +01:00
{
ObjectList * targets = GetTargets ( e , unit );
if ( ! targets )
return ;
2011-03-27 12:54:42 +02:00
for ( ObjectList :: const_iterator itr = targets -> begin (); itr != targets -> end (); ++ itr )
2011-03-26 23:45:23 +01:00
if ( IsUnit ( * itr ))
( * itr ) -> ToUnit () -> SetFlag ( UNIT_NPC_FLAGS , e . action . unitFlag . flag );
delete targets ;
break ;
}
2010-11-03 14:10:16 +01:00
case SMART_ACTION_REMOVE_NPC_FLAG :
2011-03-26 23:45:23 +01:00
{
ObjectList * targets = GetTargets ( e , unit );
if ( ! targets )
return ;
2011-03-27 12:54:42 +02:00
for ( ObjectList :: const_iterator itr = targets -> begin (); itr != targets -> end (); ++ itr )
2011-03-26 23:45:23 +01:00
if ( IsUnit ( * itr ))
( * itr ) -> ToUnit () -> RemoveFlag ( UNIT_NPC_FLAGS , e . action . unitFlag . flag );
delete targets ;
break ;
}
case SMART_ACTION_CROSS_CAST :
{
ObjectList * casters = GetTargets ( CreateEvent ( SMART_EVENT_UPDATE_IC , 0 , 0 , 0 , 0 , 0 , SMART_ACTION_NONE , 0 , 0 , 0 , 0 , 0 , 0 , ( SMARTAI_TARGETS ) e . action . cast . targetType , e . action . cast . targetParam1 , e . action . cast . targetParam2 , e . action . cast . targetParam3 , 0 ), unit );
if ( ! casters )
return ;
ObjectList * targets = GetTargets ( e , unit );
if ( ! targets )
2010-11-03 14:10:16 +01:00
{
2011-03-26 23:45:23 +01:00
delete casters ; // casters already validated, delete now
return ;
2010-11-03 14:10:16 +01:00
}
2011-03-26 23:45:23 +01:00
2011-03-27 12:54:42 +02:00
for ( ObjectList :: const_iterator itr = casters -> begin (); itr != casters -> end (); ++ itr )
2010-11-07 18:34:04 +01:00
{
2011-03-26 23:45:23 +01:00
if ( IsUnit ( * itr ))
2010-11-07 18:34:04 +01:00
{
2011-03-26 23:45:23 +01:00
if ( e . action . cast . flags & SMARTCAST_INTERRUPT_PREVIOUS )
( * itr ) -> ToUnit () -> InterruptNonMeleeSpells ( false );
2010-11-07 18:34:04 +01:00
2011-05-12 10:40:53 +02:00
for ( ObjectList :: const_iterator it = targets -> begin (); it != targets -> end (); ++ it )
2011-03-26 23:45:23 +01:00
if ( IsUnit ( * it ))
( * itr ) -> ToUnit () -> CastSpell (( * it ) -> ToUnit (), e . action . cast . spell , ( e . action . cast . flags & SMARTCAST_TRIGGERED ) ? true : false );
2010-11-07 18:34:04 +01:00
}
}
2011-03-26 23:45:23 +01:00
delete targets ;
delete casters ;
break ;
}
2010-11-07 22:10:11 +01:00
case SMART_ACTION_CALL_RANDOM_TIMED_ACTIONLIST :
2011-03-26 23:45:23 +01:00
{
uint32 actions [ SMART_ACTION_PARAM_COUNT ];
actions [ 0 ] = e . action . randTimedActionList . entry1 ;
actions [ 1 ] = e . action . randTimedActionList . entry2 ;
actions [ 2 ] = e . action . randTimedActionList . entry3 ;
actions [ 3 ] = e . action . randTimedActionList . entry4 ;
actions [ 4 ] = e . action . randTimedActionList . entry5 ;
actions [ 5 ] = e . action . randTimedActionList . entry6 ;
uint32 temp [ SMART_ACTION_PARAM_COUNT ];
uint32 count = 0 ;
for ( uint8 i = 0 ; i < SMART_ACTION_PARAM_COUNT ; i ++ )
{
if ( actions [ i ] > 0 )
{
temp [ count ] = actions [ i ];
++ count ;
2010-12-07 20:25:45 +01:00
}
2011-03-26 23:45:23 +01:00
}
uint32 id = temp [ urand ( 0 , count )];
if ( e . GetTargetType () == SMART_TARGET_NONE )
{
sLog -> outErrorDb ( "SmartScript: Entry %d SourceType %u Event %u Action %u is using TARGET_NONE(0) for Script9 target. Please correct target_type in database." , e . entryOrGuid , e . GetScriptType (), e . GetEventType (), e . GetActionType ());
return ;
}
ObjectList * targets = GetTargets ( e , unit );
if ( targets )
{
2011-03-27 12:54:42 +02:00
for ( ObjectList :: iterator itr = targets -> begin (); itr != targets -> end (); ++ itr )
2010-12-07 18:31:34 +01:00
{
2011-03-26 23:45:23 +01:00
if ( Creature * target = ( * itr ) -> ToCreature ())
2010-12-07 18:31:34 +01:00
{
2011-03-26 23:45:23 +01:00
if ( IsSmart ( target ))
CAST_AI ( SmartAI , target -> AI ()) -> SetScript9 ( e , id , GetLastInvoker ());
}
2011-11-23 17:55:16 +01:00
else if ( GameObject * goTarget = ( * itr ) -> ToGameObject ())
2011-03-26 23:45:23 +01:00
{
2011-11-23 17:55:16 +01:00
if ( IsSmartGO ( goTarget ))
2011-12-10 13:44:06 +01:00
CAST_AI ( SmartGameObjectAI , goTarget -> AI ()) -> SetScript9 ( e , id , GetLastInvoker ());
2010-12-07 18:31:34 +01:00
}
}
2011-03-26 23:45:23 +01:00
delete targets ;
2010-11-07 22:10:11 +01:00
}
2011-03-26 23:45:23 +01:00
break ;
}
2010-11-07 22:10:11 +01:00
case SMART_ACTION_CALL_RANDOM_RANGE_TIMED_ACTIONLIST :
2011-03-26 23:45:23 +01:00
{
uint32 id = urand ( e . action . randTimedActionList . entry1 , e . action . randTimedActionList . entry2 );
if ( e . GetTargetType () == SMART_TARGET_NONE )
2010-11-07 22:10:11 +01:00
{
2011-03-26 23:45:23 +01:00
sLog -> outErrorDb ( "SmartScript: Entry %d SourceType %u Event %u Action %u is using TARGET_NONE(0) for Script9 target. Please correct target_type in database." , e . entryOrGuid , e . GetScriptType (), e . GetEventType (), e . GetActionType ());
return ;
}
ObjectList * targets = GetTargets ( e , unit );
if ( targets )
{
2011-03-27 12:54:42 +02:00
for ( ObjectList :: iterator itr = targets -> begin (); itr != targets -> end (); ++ itr )
2010-12-07 18:31:34 +01:00
{
2011-03-26 23:45:23 +01:00
if ( Creature * target = ( * itr ) -> ToCreature ())
2010-12-07 18:31:34 +01:00
{
2011-03-26 23:45:23 +01:00
if ( IsSmart ( target ))
CAST_AI ( SmartAI , target -> AI ()) -> SetScript9 ( e , id , GetLastInvoker ());
2011-06-15 17:33:06 +02:00
}
2011-11-23 17:55:16 +01:00
else if ( GameObject * goTarget = ( * itr ) -> ToGameObject ())
2011-03-26 23:45:23 +01:00
{
2011-11-23 17:55:16 +01:00
if ( IsSmartGO ( goTarget ))
2011-12-10 13:44:06 +01:00
CAST_AI ( SmartGameObjectAI , goTarget -> AI ()) -> SetScript9 ( e , id , GetLastInvoker ());
2010-12-07 18:31:34 +01:00
}
}
2011-03-26 23:45:23 +01:00
delete targets ;
2010-11-07 22:10:11 +01:00
}
2011-03-26 23:45:23 +01:00
break ;
}
2010-11-19 20:23:08 +01:00
case SMART_ACTION_ACTIVATE_TAXI :
2011-03-26 23:45:23 +01:00
{
ObjectList * targets = GetTargets ( e , unit );
if ( ! targets )
return ;
2011-03-27 12:54:42 +02:00
for ( ObjectList :: const_iterator itr = targets -> begin (); itr != targets -> end (); ++ itr )
2011-03-26 23:45:23 +01:00
if ( IsPlayer ( * itr ))
( * itr ) -> ToPlayer () -> ActivateTaxiPathTo ( e . action . taxi . id );
delete targets ;
break ;
}
2010-11-20 13:23:29 +01:00
case SMART_ACTION_RANDOM_MOVE :
2011-03-26 23:45:23 +01:00
{
ObjectList * targets = GetTargets ( e , unit );
if ( ! targets )
return ;
2011-03-27 12:54:42 +02:00
for ( ObjectList :: const_iterator itr = targets -> begin (); itr != targets -> end (); ++ itr )
2010-11-20 13:23:29 +01:00
{
2011-03-26 23:45:23 +01:00
if ( IsCreature (( * itr )))
{
if ( e . action . moveRandom . distance )
( * itr ) -> ToCreature () -> GetMotionMaster () -> MoveRandom (( float ) e . action . moveRandom . distance );
else
( * itr ) -> ToCreature () -> GetMotionMaster () -> MoveIdle ();
}
2010-11-20 13:23:29 +01:00
}
2011-03-26 23:45:23 +01:00
delete targets ;
break ;
}
2011-02-07 09:35:14 -07:00
case SMART_ACTION_SET_UNIT_FIELD_BYTES_1 :
2011-03-26 23:45:23 +01:00
{
ObjectList * targets = GetTargets ( e , unit );
if ( ! targets )
return ;
2011-03-27 12:54:42 +02:00
for ( ObjectList :: const_iterator itr = targets -> begin (); itr != targets -> end (); ++ itr )
2011-03-26 23:45:23 +01:00
if ( IsUnit ( * itr ))
( * itr ) -> ToUnit () -> SetByteFlag ( UNIT_FIELD_BYTES_1 , 0 , e . action . setunitByte . byte1 );
delete targets ;
break ;
}
2011-02-07 10:15:54 -07:00
case SMART_ACTION_REMOVE_UNIT_FIELD_BYTES_1 :
2011-03-26 23:45:23 +01:00
{
ObjectList * targets = GetTargets ( e , unit );
if ( ! targets )
return ;
2011-06-15 17:33:06 +02:00
2011-03-27 12:54:42 +02:00
for ( ObjectList :: const_iterator itr = targets -> begin (); itr != targets -> end (); ++ itr )
2011-03-26 23:45:23 +01:00
if ( IsUnit ( * itr ))
( * itr ) -> ToUnit () -> RemoveByteFlag ( UNIT_FIELD_BYTES_1 , 0 , e . action . delunitByte . byte1 );
delete targets ;
break ;
}
2011-02-15 00:29:33 -03:00
case SMART_ACTION_INTERRUPT_SPELL :
2011-03-26 23:45:23 +01:00
{
ObjectList * targets = GetTargets ( e , unit );
if ( ! targets )
return ;
2011-02-27 18:34:24 +01:00
2011-03-27 12:54:42 +02:00
for ( ObjectList :: const_iterator itr = targets -> begin (); itr != targets -> end (); ++ itr )
2011-03-26 23:45:23 +01:00
if ( IsUnit ( * itr ))
( * itr ) -> ToUnit () -> InterruptNonMeleeSpells ( e . action . interruptSpellCasting . withDelayed , e . action . interruptSpellCasting . spell_id , e . action . interruptSpellCasting . withInstant );
2011-02-15 00:29:33 -03:00
2011-03-26 23:45:23 +01:00
delete targets ;
break ;
}
2011-03-02 16:50:09 +01:00
case SMART_ACTION_SEND_GO_CUSTOM_ANIM :
2011-03-26 23:45:23 +01:00
{
ObjectList * targets = GetTargets ( e , unit );
if ( ! targets )
return ;
2011-03-02 16:50:09 +01:00
2011-03-27 12:54:42 +02:00
for ( ObjectList :: const_iterator itr = targets -> begin (); itr != targets -> end (); ++ itr )
2011-03-26 23:45:23 +01:00
if ( IsGameObject ( * itr ))
( * itr ) -> ToGameObject () -> SendCustomAnim ( e . action . sendGoCustomAnim . anim );
2011-03-02 16:50:09 +01:00
2011-03-26 23:45:23 +01:00
delete targets ;
break ;
}
2011-06-12 17:50:23 +02:00
case SMART_ACTION_SET_DYNAMIC_FLAG :
{
ObjectList * targets = GetTargets ( e , unit );
if ( ! targets )
return ;
for ( ObjectList :: const_iterator itr = targets -> begin (); itr != targets -> end (); ++ itr )
if ( IsUnit ( * itr ))
( * itr ) -> ToUnit () -> SetUInt32Value ( UNIT_DYNAMIC_FLAGS , e . action . unitFlag . flag );
delete targets ;
break ;
}
case SMART_ACTION_ADD_DYNAMIC_FLAG :
{
ObjectList * targets = GetTargets ( e , unit );
if ( ! targets )
return ;
for ( ObjectList :: const_iterator itr = targets -> begin (); itr != targets -> end (); ++ itr )
if ( IsUnit ( * itr ))
( * itr ) -> ToUnit () -> SetFlag ( UNIT_DYNAMIC_FLAGS , e . action . unitFlag . flag );
delete targets ;
break ;
}
case SMART_ACTION_REMOVE_DYNAMIC_FLAG :
{
ObjectList * targets = GetTargets ( e , unit );
if ( ! targets )
return ;
for ( ObjectList :: const_iterator itr = targets -> begin (); itr != targets -> end (); ++ itr )
if ( IsUnit ( * itr ))
( * itr ) -> ToUnit () -> RemoveFlag ( UNIT_DYNAMIC_FLAGS , e . action . unitFlag . flag );
delete targets ;
break ;
}
2011-07-02 07:52:03 +02:00
case SMART_ACTION_JUMP_TO_POS :
{
2011-10-24 23:21:34 +01:00
if ( ! me )
return ;
me -> GetMotionMaster () -> Clear ();
2011-09-29 12:43:05 +02:00
me -> GetMotionMaster () -> MoveJump ( e . target . x , e . target . y , e . target . z , ( float ) e . action . jump . speedxy , ( float ) e . action . jump . speedz );
2011-10-24 23:21:34 +01:00
// TODO: Resume path when reached jump location
2011-07-02 07:52:03 +02:00
break ;
}
2011-10-23 12:55:17 +01:00
case SMART_ACTION_SEND_GOSSIP_MENU :
{
2011-10-31 02:01:17 +01:00
if ( ! GetBaseObject ())
return ;
2011-12-06 12:37:05 +01:00
sLog -> outDebug ( LOG_FILTER_DATABASE_AI , "SmartScript::ProcessAction:: SMART_ACTION_SEND_GOSSIP_MENU: gossipMenuId %d, gossipNpcTextId %d" ,
e . action . sendGossipMenu . gossipMenuId , e . action . sendGossipMenu . gossipNpcTextId );
2011-10-23 12:55:17 +01:00
ObjectList * targets = GetTargets ( e , unit );
if ( ! targets )
return ;
for ( ObjectList :: const_iterator itr = targets -> begin (); itr != targets -> end (); ++ itr )
2011-10-24 23:21:34 +01:00
if ( Player * player = ( * itr ) -> ToPlayer ())
2011-10-23 12:55:17 +01:00
{
if ( e . action . sendGossipMenu . gossipMenuId )
player -> PrepareGossipMenu ( GetBaseObject (), e . action . sendGossipMenu . gossipMenuId , true );
else
player -> PlayerTalkClass -> ClearMenus ();
2011-12-06 12:37:05 +01:00
player -> SEND_GOSSIP_MENU ( e . action . sendGossipMenu . gossipNpcTextId , GetBaseObject () -> GetGUID ());
2011-10-23 12:55:17 +01:00
}
delete targets ;
break ;
}
2010-10-27 21:01:47 +02:00
default :
2010-12-23 23:25:44 +01:00
sLog -> outErrorDb ( "SmartScript::ProcessAction: Unhandled Action type %u" , e . GetActionType ());
2010-10-27 21:01:47 +02:00
break ;
}
}
2011-05-12 10:40:53 +02:00
void SmartScript :: InstallTemplate ( SmartScriptHolder const & e )
2010-10-27 21:01:47 +02:00
{
if ( ! GetBaseObject ())
return ;
if ( mTemplate )
{
2010-12-23 23:25:44 +01:00
sLog -> outErrorDb ( "SmartScript::InstallTemplate: Entry %d SourceType %u AI Template can not be set more then once, skipped." , e . entryOrGuid , e . GetScriptType ());
2010-10-27 21:01:47 +02:00
return ;
}
mTemplate = ( SMARTAI_TEMPLATE ) e . action . installTtemplate . id ;
switch (( SMARTAI_TEMPLATE ) e . action . installTtemplate . id )
{
case SMARTAI_TEMPLATE_CASTER :
{
2011-03-26 23:45:23 +01:00
AddEvent ( SMART_EVENT_UPDATE_IC , 0 , 0 , 0 , e . action . installTtemplate . param2 , e . action . installTtemplate . param3 , SMART_ACTION_CAST , e . action . installTtemplate . param1 , e . target . raw . param1 , 0 , 0 , 0 , 0 , SMART_TARGET_VICTIM , 0 , 0 , 0 , 1 );
AddEvent ( SMART_EVENT_RANGE , 0 , e . action . installTtemplate . param4 , 300 , 0 , 0 , SMART_ACTION_ALLOW_COMBAT_MOVEMENT , 1 , 0 , 0 , 0 , 0 , 0 , SMART_TARGET_NONE , 0 , 0 , 0 , 1 );
AddEvent ( SMART_EVENT_RANGE , 0 , 0 , e . action . installTtemplate . param4 > 10 ? e . action . installTtemplate . param4 - 10 : 0 , 0 , 0 , SMART_ACTION_ALLOW_COMBAT_MOVEMENT , 0 , 0 , 0 , 0 , 0 , 0 , SMART_TARGET_NONE , 0 , 0 , 0 , 1 );
AddEvent ( SMART_EVENT_MANA_PCT , 0 , e . action . installTtemplate . param5 - 15 > 100 ? 100 : e . action . installTtemplate . param5 + 15 , 100 , 1000 , 1000 , SMART_ACTION_SET_EVENT_PHASE , 1 , 0 , 0 , 0 , 0 , 0 , SMART_TARGET_NONE , 0 , 0 , 0 , 0 );
AddEvent ( SMART_EVENT_MANA_PCT , 0 , 0 , e . action . installTtemplate . param5 , 1000 , 1000 , SMART_ACTION_SET_EVENT_PHASE , 0 , 0 , 0 , 0 , 0 , 0 , SMART_TARGET_NONE , 0 , 0 , 0 , 0 );
AddEvent ( SMART_EVENT_MANA_PCT , 0 , 0 , e . action . installTtemplate . param5 , 1000 , 1000 , SMART_ACTION_ALLOW_COMBAT_MOVEMENT , 1 , 0 , 0 , 0 , 0 , 0 , SMART_TARGET_NONE , 0 , 0 , 0 , 0 );
2010-10-27 21:01:47 +02:00
break ;
}
case SMARTAI_TEMPLATE_TURRET :
{
2011-03-26 23:45:23 +01:00
AddEvent ( SMART_EVENT_UPDATE_IC , 0 , 0 , 0 , e . action . installTtemplate . param2 , e . action . installTtemplate . param3 , SMART_ACTION_CAST , e . action . installTtemplate . param1 , e . target . raw . param1 , 0 , 0 , 0 , 0 , SMART_TARGET_VICTIM , 0 , 0 , 0 , 0 );
AddEvent ( SMART_EVENT_JUST_CREATED , 0 , 0 , 0 , 0 , 0 , SMART_ACTION_ALLOW_COMBAT_MOVEMENT , 0 , 0 , 0 , 0 , 0 , 0 , SMART_TARGET_NONE , 0 , 0 , 0 , 0 );
2010-10-27 21:01:47 +02:00
break ;
}
case SMARTAI_TEMPLATE_CAGED_NPC_PART :
{
if ( ! me ) return ;
//store cage as id1
2011-03-26 23:45:23 +01:00
AddEvent ( SMART_EVENT_DATA_SET , 0 , 0 , 0 , 0 , 0 , SMART_ACTION_STORE_TARGET_LIST , 1 , 0 , 0 , 0 , 0 , 0 , SMART_TARGET_CLOSEST_GAMEOBJECT , e . action . installTtemplate . param1 , 10 , 0 , 0 );
2010-10-27 21:01:47 +02:00
//reset(close) cage on hostage(me) respawn
2011-03-26 23:45:23 +01:00
AddEvent ( SMART_EVENT_UPDATE , SMART_EVENT_FLAG_NOT_REPEATABLE , 0 , 0 , 0 , 0 , SMART_ACTION_RESET_GOBJECT , 0 , 0 , 0 , 0 , 0 , 0 , SMART_TARGET_GAMEOBJECT_DISTANCE , e . action . installTtemplate . param1 , 5 , 0 , 0 );
2010-12-13 22:37:56 +01:00
2011-03-26 23:45:23 +01:00
AddEvent ( SMART_EVENT_DATA_SET , 0 , 0 , 0 , 0 , 0 , SMART_ACTION_SET_RUN , e . action . installTtemplate . param3 , 0 , 0 , 0 , 0 , 0 , SMART_TARGET_NONE , 0 , 0 , 0 , 0 );
AddEvent ( SMART_EVENT_DATA_SET , 0 , 0 , 0 , 0 , 0 , SMART_ACTION_SET_EVENT_PHASE , 1 , 0 , 0 , 0 , 0 , 0 , SMART_TARGET_NONE , 0 , 0 , 0 , 0 );
2010-10-27 21:01:47 +02:00
2011-03-26 23:45:23 +01:00
AddEvent ( SMART_EVENT_UPDATE , SMART_EVENT_FLAG_NOT_REPEATABLE , 1000 , 1000 , 0 , 0 , SMART_ACTION_MOVE_FORWARD , e . action . installTtemplate . param4 , 0 , 0 , 0 , 0 , 0 , SMART_TARGET_NONE , 0 , 0 , 0 , 1 );
2010-10-27 21:01:47 +02:00
//phase 1: give quest credit on movepoint reached
2011-03-26 23:45:23 +01:00
AddEvent ( SMART_EVENT_MOVEMENTINFORM , 0 , POINT_MOTION_TYPE , SMART_RANDOM_POINT , 0 , 0 , SMART_ACTION_SET_DATA , 0 , 0 , 0 , 0 , 0 , 0 , SMART_TARGET_STORED , 1 , 0 , 0 , 1 );
2010-10-27 21:01:47 +02:00
//phase 1: despawn after time on movepoint reached
2011-03-26 23:45:23 +01:00
AddEvent ( SMART_EVENT_MOVEMENTINFORM , 0 , POINT_MOTION_TYPE , SMART_RANDOM_POINT , 0 , 0 , SMART_ACTION_FORCE_DESPAWN , e . action . installTtemplate . param2 , 0 , 0 , 0 , 0 , 0 , SMART_TARGET_NONE , 0 , 0 , 0 , 1 );
2010-10-27 21:01:47 +02:00
2010-12-22 21:25:23 +01:00
if ( sCreatureTextMgr -> TextExist ( me -> GetEntry (), ( uint8 ) e . action . installTtemplate . param5 ))
2011-03-26 23:45:23 +01:00
AddEvent ( SMART_EVENT_MOVEMENTINFORM , 0 , POINT_MOTION_TYPE , SMART_RANDOM_POINT , 0 , 0 , SMART_ACTION_TALK , e . action . installTtemplate . param5 , 0 , 0 , 0 , 0 , 0 , SMART_TARGET_NONE , 0 , 0 , 0 , 1 );
2010-10-27 21:01:47 +02:00
break ;
}
case SMARTAI_TEMPLATE_CAGED_GO_PART :
{
if ( ! go ) return ;
//store hostage as id1
2011-03-26 23:45:23 +01:00
AddEvent ( SMART_EVENT_GOSSIP_HELLO , 0 , 0 , 0 , 0 , 0 , SMART_ACTION_STORE_TARGET_LIST , 1 , 0 , 0 , 0 , 0 , 0 , SMART_TARGET_CLOSEST_CREATURE , e . action . installTtemplate . param1 , 10 , 0 , 0 );
2010-10-27 21:01:47 +02:00
//store invoker as id2
2011-03-26 23:45:23 +01:00
AddEvent ( SMART_EVENT_GOSSIP_HELLO , 0 , 0 , 0 , 0 , 0 , SMART_ACTION_STORE_TARGET_LIST , 2 , 0 , 0 , 0 , 0 , 0 , SMART_TARGET_NONE , 0 , 0 , 0 , 0 );
2010-10-27 21:01:47 +02:00
//signal hostage
2011-03-26 23:45:23 +01:00
AddEvent ( SMART_EVENT_GOSSIP_HELLO , 0 , 0 , 0 , 0 , 0 , SMART_ACTION_SET_DATA , 0 , 0 , 0 , 0 , 0 , 0 , SMART_TARGET_STORED , 1 , 0 , 0 , 0 );
2010-10-27 21:01:47 +02:00
//when hostage raeched end point, give credit to invoker
if ( e . action . installTtemplate . param2 )
2011-03-26 23:45:23 +01:00
AddEvent ( SMART_EVENT_DATA_SET , 0 , 0 , 0 , 0 , 0 , SMART_ACTION_CALL_KILLEDMONSTER , e . action . installTtemplate . param1 , 0 , 0 , 0 , 0 , 0 , SMART_TARGET_STORED , 2 , 0 , 0 , 0 );
2010-10-27 21:01:47 +02:00
else
2011-03-26 23:45:23 +01:00
AddEvent ( SMART_EVENT_GOSSIP_HELLO , 0 , 0 , 0 , 0 , 0 , SMART_ACTION_CALL_KILLEDMONSTER , e . action . installTtemplate . param1 , 0 , 0 , 0 , 0 , 0 , SMART_TARGET_STORED , 2 , 0 , 0 , 0 );
2010-10-27 21:01:47 +02:00
break ;
}
case SMARTAI_TEMPLATE_BASIC :
default :
return ;
}
}
void SmartScript :: AddEvent ( SMART_EVENT e , uint32 event_flags , uint32 event_param1 , uint32 event_param2 , uint32 event_param3 , uint32 event_param4 , SMART_ACTION action , uint32 action_param1 , uint32 action_param2 , uint32 action_param3 , uint32 action_param4 , uint32 action_param5 , uint32 action_param6 , SMARTAI_TARGETS t , uint32 target_param1 , uint32 target_param2 , uint32 target_param3 , uint32 phaseMask )
{
mInstallEvents . push_back ( CreateEvent ( e , event_flags , event_param1 , event_param2 , event_param3 , event_param4 , action , action_param1 , action_param2 , action_param3 , action_param4 , action_param5 , action_param6 , t , target_param1 , target_param2 , target_param3 , phaseMask ));
}
SmartScriptHolder SmartScript :: CreateEvent ( SMART_EVENT e , uint32 event_flags , uint32 event_param1 , uint32 event_param2 , uint32 event_param3 , uint32 event_param4 , SMART_ACTION action , uint32 action_param1 , uint32 action_param2 , uint32 action_param3 , uint32 action_param4 , uint32 action_param5 , uint32 action_param6 , SMARTAI_TARGETS t , uint32 target_param1 , uint32 target_param2 , uint32 target_param3 , uint32 phaseMask )
{
SmartScriptHolder script ;
script . event . type = e ;
script . event . raw . param1 = event_param1 ;
script . event . raw . param2 = event_param2 ;
script . event . raw . param3 = event_param3 ;
script . event . raw . param4 = event_param4 ;
script . event . event_phase_mask = phaseMask ;
script . event . event_flags = event_flags ;
script . action . type = action ;
script . action . raw . param1 = action_param1 ;
script . action . raw . param2 = action_param2 ;
script . action . raw . param3 = action_param3 ;
script . action . raw . param4 = action_param4 ;
script . action . raw . param5 = action_param5 ;
script . action . raw . param6 = action_param6 ;
script . target . type = t ;
script . target . raw . param1 = target_param1 ;
script . target . raw . param2 = target_param2 ;
script . target . raw . param3 = target_param3 ;
script . source_type = SMART_SCRIPT_TYPE_CREATURE ;
InitTimer ( script );
return script ;
}
2011-05-12 10:40:53 +02:00
ObjectList * SmartScript :: GetTargets ( SmartScriptHolder const & e , Unit * invoker /*= NULL*/ )
2010-10-27 21:01:47 +02:00
{
2010-11-04 19:56:39 +01:00
Unit * trigger = NULL ;
if ( invoker )
trigger = invoker ;
2011-02-21 22:23:43 +01:00
else if ( Unit * tempLastInvoker = GetLastInvoker ())
trigger = tempLastInvoker ;
2011-03-26 23:45:23 +01:00
2010-10-27 21:01:47 +02:00
ObjectList * l = new ObjectList ();
switch ( e . GetTargetType ())
{
case SMART_TARGET_SELF :
if ( GetBaseObject ())
l -> push_back ( GetBaseObject ());
break ;
case SMART_TARGET_VICTIM :
if ( me && me -> getVictim ())
l -> push_back ( me -> getVictim ());
break ;
case SMART_TARGET_HOSTILE_SECOND_AGGRO :
2011-03-26 23:45:23 +01:00
if ( me )
if ( Unit * u = me -> AI () -> SelectTarget ( SELECT_TARGET_TOPAGGRO , 1 ))
l -> push_back ( u );
2010-10-27 21:01:47 +02:00
break ;
case SMART_TARGET_HOSTILE_LAST_AGGRO :
2011-03-26 23:45:23 +01:00
if ( me )
if ( Unit * u = me -> AI () -> SelectTarget ( SELECT_TARGET_BOTTOMAGGRO , 0 ))
l -> push_back ( u );
2010-10-27 21:01:47 +02:00
break ;
case SMART_TARGET_HOSTILE_RANDOM :
2011-03-26 23:45:23 +01:00
if ( me )
if ( Unit * u = me -> AI () -> SelectTarget ( SELECT_TARGET_RANDOM , 0 ))
l -> push_back ( u );
2010-10-27 21:01:47 +02:00
break ;
case SMART_TARGET_HOSTILE_RANDOM_NOT_TOP :
2011-03-26 23:45:23 +01:00
if ( me )
if ( Unit * u = me -> AI () -> SelectTarget ( SELECT_TARGET_RANDOM , 1 ))
l -> push_back ( u );
2010-10-27 21:01:47 +02:00
break ;
case SMART_TARGET_NONE :
case SMART_TARGET_ACTION_INVOKER :
2010-11-04 19:56:39 +01:00
if ( trigger )
l -> push_back ( trigger );
2010-10-27 21:01:47 +02:00
break ;
2010-10-31 14:21:35 +01:00
case SMART_TARGET_ACTION_INVOKER_VEHICLE :
2010-11-04 19:56:39 +01:00
if ( trigger && trigger -> GetVehicle () && trigger -> GetVehicle () -> GetBase ())
l -> push_back ( trigger -> GetVehicle () -> GetBase ());
2010-10-31 14:21:35 +01:00
break ;
2010-10-27 21:01:47 +02:00
case SMART_TARGET_INVOKER_PARTY :
2010-11-04 19:56:39 +01:00
if ( trigger )
2010-10-27 21:01:47 +02:00
{
2010-11-04 19:56:39 +01:00
l -> push_back ( trigger );
2011-08-20 20:31:31 -03:00
if ( Player * player = trigger -> ToPlayer ())
if ( Group * group = player -> GetGroup ())
for ( GroupReference * groupRef = group -> GetFirstMember (); groupRef != NULL ; groupRef = groupRef -> next ())
2011-03-26 23:45:23 +01:00
if ( Player * member = groupRef -> getSource ())
l -> push_back ( member );
2010-10-27 21:01:47 +02:00
}
break ;
case SMART_TARGET_CREATURE_RANGE :
2011-03-26 23:45:23 +01:00
{
// will always return a valid pointer, even if empty list
ObjectList * units = GetWorldObjectsInDist (( float ) e . target . unitRange . maxDist );
for ( ObjectList :: const_iterator itr = units -> begin (); itr != units -> end (); ++ itr )
2010-10-27 21:01:47 +02:00
{
2011-03-26 23:45:23 +01:00
if ( ! IsCreature ( * itr ))
continue ;
if ( me && me == * itr )
continue ;
if ((( e . target . unitRange . creature && ( * itr ) -> ToCreature () -> GetEntry () == e . target . unitRange . creature ) || ! e . target . unitRange . creature ) && GetBaseObject () -> IsInRange ( * itr , ( float ) e . target . unitRange . minDist , ( float ) e . target . unitRange . maxDist ))
l -> push_back ( * itr );
2010-10-27 21:01:47 +02:00
}
2011-03-26 23:45:23 +01:00
delete units ;
break ;
}
2010-10-27 21:01:47 +02:00
case SMART_TARGET_CREATURE_DISTANCE :
2011-03-26 23:45:23 +01:00
{
// will always return a valid pointer, even if empty list
ObjectList * units = GetWorldObjectsInDist (( float ) e . target . unitDistance . dist );
for ( ObjectList :: const_iterator itr = units -> begin (); itr != units -> end (); ++ itr )
2010-10-27 21:01:47 +02:00
{
2011-03-26 23:45:23 +01:00
if ( ! IsCreature ( * itr ))
continue ;
if ( me && me == * itr )
continue ;
if (( e . target . unitDistance . creature && ( * itr ) -> ToCreature () -> GetEntry () == e . target . unitDistance . creature ) || ! e . target . unitDistance . creature )
l -> push_back ( * itr );
2010-10-27 21:01:47 +02:00
}
2011-03-26 23:45:23 +01:00
delete units ;
break ;
}
2010-10-27 21:01:47 +02:00
case SMART_TARGET_GAMEOBJECT_DISTANCE :
2011-03-26 23:45:23 +01:00
{
// will always return a valid pointer, even if empty list
ObjectList * units = GetWorldObjectsInDist (( float ) e . target . goDistance . dist );
for ( ObjectList :: const_iterator itr = units -> begin (); itr != units -> end (); ++ itr )
2010-10-27 21:01:47 +02:00
{
2011-03-26 23:45:23 +01:00
if ( ! IsGameObject ( * itr ))
continue ;
if ( go && go == * itr )
continue ;
if (( e . target . goDistance . entry && ( * itr ) -> ToGameObject () -> GetEntry () == e . target . goDistance . entry ) || ! e . target . goDistance . entry )
l -> push_back ( * itr );
2010-10-27 21:01:47 +02:00
}
2011-03-26 23:45:23 +01:00
delete units ;
break ;
}
2010-10-27 21:01:47 +02:00
case SMART_TARGET_GAMEOBJECT_RANGE :
2011-03-26 23:45:23 +01:00
{
// will always return a valid pointer, even if empty list
ObjectList * units = GetWorldObjectsInDist (( float ) e . target . goRange . maxDist );
for ( ObjectList :: const_iterator itr = units -> begin (); itr != units -> end (); ++ itr )
2010-10-27 21:01:47 +02:00
{
2011-06-12 02:30:32 +02:00
if ( ! IsGameObject ( * itr ))
2011-03-26 23:45:23 +01:00
continue ;
if ( go && go == * itr )
continue ;
if ((( e . target . goRange . entry && IsGameObject ( * itr ) && ( * itr ) -> ToGameObject () -> GetEntry () == e . target . goRange . entry ) || ! e . target . goRange . entry ) && GetBaseObject () -> IsInRange (( * itr ), ( float ) e . target . goRange . minDist , ( float ) e . target . goRange . maxDist ))
l -> push_back ( * itr );
2010-10-27 21:01:47 +02:00
}
2011-03-26 23:45:23 +01:00
delete units ;
break ;
}
2010-10-27 21:01:47 +02:00
case SMART_TARGET_CREATURE_GUID :
2011-03-26 23:45:23 +01:00
{
Creature * target = NULL ;
if ( e . target . unitGUID . entry )
2010-10-27 21:01:47 +02:00
{
2011-03-26 23:45:23 +01:00
uint64 guid = MAKE_NEW_GUID ( e . target . unitGUID . guid , e . target . unitGUID . entry , HIGHGUID_UNIT );
target = HashMapHolder < Creature >:: Find ( guid );
2010-10-27 21:01:47 +02:00
}
2011-03-26 23:45:23 +01:00
else
2010-10-27 21:01:47 +02:00
{
2011-03-26 23:45:23 +01:00
if ( ! trigger && ! GetBaseObject ())
2010-10-27 21:01:47 +02:00
{
2011-03-26 23:45:23 +01:00
sLog -> outErrorDb ( "SMART_TARGET_CREATURE_GUID can not be used without invoker and without entry" );
break ;
2010-10-27 21:01:47 +02:00
}
2011-03-26 23:45:23 +01:00
target = FindCreatureNear ( trigger ? trigger : GetBaseObject (), e . target . unitGUID . guid );
2010-10-27 21:01:47 +02:00
}
2011-03-26 23:45:23 +01:00
if ( target )
l -> push_back ( target );
break ;
}
case SMART_TARGET_GAMEOBJECT_GUID :
{
GameObject * target = NULL ;
if ( e . target . unitGUID . entry )
2010-10-27 21:01:47 +02:00
{
2011-03-26 23:45:23 +01:00
uint64 guid = MAKE_NEW_GUID ( e . target . goGUID . guid , e . target . goGUID . entry , HIGHGUID_GAMEOBJECT );
target = HashMapHolder < GameObject >:: Find ( guid );
2010-10-27 21:01:47 +02:00
}
2011-03-26 23:45:23 +01:00
else
2010-10-27 21:01:47 +02:00
{
2011-03-26 23:45:23 +01:00
if ( ! trigger && ! GetBaseObject ())
2010-10-27 21:01:47 +02:00
{
2011-03-26 23:45:23 +01:00
sLog -> outErrorDb ( "SMART_TARGET_GAMEOBJECT_GUID can not be used without invoker and without entry" );
break ;
2010-10-27 21:01:47 +02:00
}
2011-03-26 23:45:23 +01:00
target = FindGameObjectNear ( trigger ? trigger : GetBaseObject (), e . target . goGUID . guid );
2010-10-27 21:01:47 +02:00
}
2011-03-26 23:45:23 +01:00
if ( target )
l -> push_back ( target );
break ;
}
case SMART_TARGET_PLAYER_RANGE :
{
// will always return a valid pointer, even if empty list
ObjectList * units = GetWorldObjectsInDist (( float ) e . target . playerRange . maxDist );
if ( ! units -> empty () && GetBaseObject ())
for ( ObjectList :: const_iterator itr = units -> begin (); itr != units -> end (); ++ itr )
if ( IsPlayer ( * itr ) && GetBaseObject () -> IsInRange ( * itr , ( float ) e . target . playerRange . minDist , ( float ) e . target . playerRange . maxDist ))
l -> push_back ( * itr );
delete units ;
break ;
}
case SMART_TARGET_PLAYER_DISTANCE :
{
// will always return a valid pointer, even if empty list
ObjectList * units = GetWorldObjectsInDist (( float ) e . target . playerDistance . dist );
2011-03-27 12:54:42 +02:00
for ( ObjectList :: const_iterator itr = units -> begin (); itr != units -> end (); ++ itr )
2011-03-26 23:45:23 +01:00
if ( IsPlayer ( * itr ))
l -> push_back ( * itr );
delete units ;
break ;
}
2010-10-27 21:01:47 +02:00
case SMART_TARGET_STORED :
2011-03-26 23:45:23 +01:00
{
ObjectListMap :: iterator itr = mTargetStorage -> find ( e . target . stored . id );
if ( itr != mTargetStorage -> end ())
l -> assign ( itr -> second -> begin (), itr -> second -> end ());
return l ;
}
2010-10-27 21:01:47 +02:00
case SMART_TARGET_CLOSEST_CREATURE :
2011-03-26 23:45:23 +01:00
{
Creature * target = GetClosestCreatureWithEntry ( GetBaseObject (), e . target . closest . entry , ( float )( e . target . closest . dist ? e . target . closest . dist : 100 ), e . target . closest . dead ? false : true );
if ( target )
l -> push_back ( target );
break ;
}
2010-10-27 21:01:47 +02:00
case SMART_TARGET_CLOSEST_GAMEOBJECT :
2011-03-26 23:45:23 +01:00
{
GameObject * target = GetClosestGameObjectWithEntry ( GetBaseObject (), e . target . closest . entry , ( float )( e . target . closest . dist ? e . target . closest . dist : 100 ));
if ( target )
l -> push_back ( target );
break ;
}
2011-10-25 21:43:24 +01:00
case SMART_TARGET_CLOSEST_PLAYER :
{
if ( me )
{
2011-10-25 23:50:00 +01:00
Player * target = me -> SelectNearestPlayer (( float ) e . target . playerDistance . dist );
2011-10-25 21:43:24 +01:00
if ( target )
l -> push_back ( target );
}
break ;
}
2010-11-07 18:02:33 +01:00
case SMART_TARGET_OWNER_OR_SUMMONER :
2011-03-26 23:45:23 +01:00
{
if ( me )
if ( Unit * owner = ObjectAccessor :: GetUnit ( * me , me -> GetCharmerOrOwnerGUID ()))
2010-11-07 18:02:33 +01:00
l -> push_back ( owner );
2011-03-26 23:45:23 +01:00
break ;
}
2010-11-20 12:42:10 +01:00
case SMART_TARGET_THREAT_LIST :
2011-03-26 23:45:23 +01:00
{
if ( me )
2010-11-20 12:42:10 +01:00
{
2011-03-26 23:45:23 +01:00
std :: list < HostileReference *> const & threatList = me -> getThreatManager (). getThreatList ();
for ( std :: list < HostileReference *>:: const_iterator i = threatList . begin (); i != threatList . end (); ++ i )
if ( Unit * temp = Unit :: GetUnit ( * me , ( * i ) -> getUnitGuid ()))
l -> push_back ( temp );
2010-11-20 12:42:10 +01:00
}
2011-03-26 23:45:23 +01:00
break ;
}
2010-10-27 21:01:47 +02:00
case SMART_TARGET_POSITION :
default :
2011-03-26 23:45:23 +01:00
break ;
}
if ( l -> empty ())
{
delete l ;
l = NULL ;
2010-10-27 21:01:47 +02:00
}
2011-03-26 23:45:23 +01:00
2010-10-27 21:01:47 +02:00
return l ;
}
ObjectList * SmartScript :: GetWorldObjectsInDist ( float dist )
{
ObjectList * targets = new ObjectList ();
WorldObject * obj = GetBaseObject ();
if ( obj )
{
Trinity :: AllWorldObjectsInRange u_check ( obj , dist );
Trinity :: WorldObjectListSearcher < Trinity :: AllWorldObjectsInRange > searcher ( obj , * targets , u_check );
obj -> VisitNearbyObject ( dist , searcher );
}
return targets ;
}
2011-07-26 23:09:28 +02:00
void SmartScript :: ProcessEvent ( SmartScriptHolder & e , Unit * unit , uint32 var0 , uint32 var1 , bool bvar , const SpellInfo * spell , GameObject * gob )
2010-10-27 21:01:47 +02:00
{
if ( ! e . active && e . GetEventType () != SMART_EVENT_LINK )
return ;
if (( e . event . event_phase_mask && ! IsInPhase ( e . event . event_phase_mask )) || (( e . event . event_flags & SMART_EVENT_FLAG_NOT_REPEATABLE ) && e . runOnce ))
return ;
2010-12-13 22:37:56 +01:00
2010-10-27 21:01:47 +02:00
switch ( e . GetEventType ())
{
case SMART_EVENT_LINK : //special handling
ProcessAction ( e , unit , var0 , var1 , bvar , spell , gob );
break ;
//called from Update tick
case SMART_EVENT_UPDATE :
RecalcTimer ( e , e . event . minMaxRepeat . repeatMin , e . event . minMaxRepeat . repeatMax );
ProcessAction ( e );
break ;
case SMART_EVENT_UPDATE_OOC :
2011-06-12 02:30:32 +02:00
if ( me && me -> isInCombat ())
2010-10-27 21:01:47 +02:00
return ;
RecalcTimer ( e , e . event . minMaxRepeat . repeatMin , e . event . minMaxRepeat . repeatMax );
ProcessAction ( e );
break ;
case SMART_EVENT_UPDATE_IC :
2011-06-12 02:30:32 +02:00
if ( ! me || ! me -> isInCombat ())
2010-10-27 21:01:47 +02:00
return ;
RecalcTimer ( e , e . event . minMaxRepeat . repeatMin , e . event . minMaxRepeat . repeatMax );
ProcessAction ( e );
break ;
case SMART_EVENT_HEALT_PCT :
2011-03-27 12:54:42 +02:00
{
if ( ! me || ! me -> isInCombat () || ! me -> GetMaxHealth ())
return ;
uint32 perc = ( uint32 ) me -> GetHealthPct ();
if ( perc > e . event . minMaxRepeat . max || perc < e . event . minMaxRepeat . min )
return ;
RecalcTimer ( e , e . event . minMaxRepeat . repeatMin , e . event . minMaxRepeat . repeatMax );
ProcessAction ( e );
break ;
}
2010-10-27 21:01:47 +02:00
case SMART_EVENT_TARGET_HEALTH_PCT :
2011-03-27 12:54:42 +02:00
{
if ( ! me || ! me -> isInCombat () || ! me -> getVictim () || ! me -> getVictim () -> GetMaxHealth ())
return ;
uint32 perc = ( uint32 ) me -> getVictim () -> GetHealthPct ();
if ( perc > e . event . minMaxRepeat . max || perc < e . event . minMaxRepeat . min )
return ;
RecalcTimer ( e , e . event . minMaxRepeat . repeatMin , e . event . minMaxRepeat . repeatMax );
ProcessAction ( e , me -> getVictim ());
break ;
}
2010-10-27 21:01:47 +02:00
case SMART_EVENT_MANA_PCT :
2011-03-27 12:54:42 +02:00
{
if ( ! me || ! me -> isInCombat () || ! me -> GetMaxPower ( POWER_MANA ))
return ;
uint32 perc = uint32 ( 100.0f * me -> GetPower ( POWER_MANA ) / me -> GetMaxPower ( POWER_MANA ));
if ( perc > e . event . minMaxRepeat . max || perc < e . event . minMaxRepeat . min )
return ;
RecalcTimer ( e , e . event . minMaxRepeat . repeatMin , e . event . minMaxRepeat . repeatMax );
ProcessAction ( e );
break ;
}
2010-10-27 21:01:47 +02:00
case SMART_EVENT_TARGET_MANA_PCT :
2011-03-27 12:54:42 +02:00
{
if ( ! me || ! me -> isInCombat () || ! me -> getVictim () || ! me -> getVictim () -> GetMaxPower ( POWER_MANA ))
return ;
uint32 perc = uint32 ( 100.0f * me -> getVictim () -> GetPower ( POWER_MANA ) / me -> getVictim () -> GetMaxPower ( POWER_MANA ));
if ( perc > e . event . minMaxRepeat . max || perc < e . event . minMaxRepeat . min )
return ;
RecalcTimer ( e , e . event . minMaxRepeat . repeatMin , e . event . minMaxRepeat . repeatMax );
ProcessAction ( e , me -> getVictim ());
break ;
}
2010-10-27 21:01:47 +02:00
case SMART_EVENT_RANGE :
2011-03-27 12:54:42 +02:00
{
if ( ! me || ! me -> isInCombat () || ! me -> getVictim ())
return ;
2010-11-03 17:25:46 +01:00
2011-03-27 12:54:42 +02:00
if ( me -> IsInRange ( me -> getVictim (), ( float ) e . event . minMaxRepeat . min , ( float ) e . event . minMaxRepeat . max ))
2010-10-27 21:01:47 +02:00
{
ProcessAction ( e , me -> getVictim ());
2011-03-27 12:54:42 +02:00
RecalcTimer ( e , e . event . minMaxRepeat . repeatMin , e . event . minMaxRepeat . repeatMax );
2010-10-27 21:01:47 +02:00
}
2011-03-27 12:54:42 +02:00
break ;
}
case SMART_EVENT_TARGET_CASTING :
{
if ( ! me || ! me -> isInCombat () || ! me -> getVictim () || ! me -> getVictim () -> IsNonMeleeSpellCasted ( false , false , true ))
return ;
ProcessAction ( e , me -> getVictim ());
RecalcTimer ( e , e . event . minMax . repeatMin , e . event . minMax . repeatMax );
}
2010-10-27 21:01:47 +02:00
case SMART_EVENT_FRIENDLY_HEALTH :
{
if ( ! me || ! me -> isInCombat ())
return ;
2011-11-23 17:55:16 +01:00
Unit * target = DoSelectLowestHpFriendly (( float ) e . event . friendlyHealt . radius , e . event . friendlyHealt . hpDeficit );
if ( ! target )
2010-10-27 21:01:47 +02:00
return ;
2011-11-23 17:55:16 +01:00
ProcessAction ( e , target );
2010-10-27 21:01:47 +02:00
RecalcTimer ( e , e . event . friendlyHealt . repeatMin , e . event . friendlyHealt . repeatMax );
break ;
}
case SMART_EVENT_FRIENDLY_IS_CC :
{
if ( ! me || ! me -> isInCombat ())
return ;
std :: list < Creature *> pList ;
DoFindFriendlyCC ( pList , ( float ) e . event . friendlyCC . radius );
if ( pList . empty ())
return ;
ProcessAction ( e , * ( pList . begin ()));
RecalcTimer ( e , e . event . friendlyCC . repeatMin , e . event . friendlyCC . repeatMax );
break ;
}
case SMART_EVENT_FRIENDLY_MISSING_BUFF :
{
std :: list < Creature *> pList ;
DoFindFriendlyMissingBuff ( pList , ( float ) e . event . missingBuff . radius , e . event . missingBuff . spell );
if ( pList . empty ())
return ;
ProcessAction ( e , * ( pList . begin ()));
RecalcTimer ( e , e . event . missingBuff . repeatMin , e . event . missingBuff . repeatMax );
break ;
}
case SMART_EVENT_HAS_AURA :
{
2011-03-27 12:54:42 +02:00
if ( ! me )
return ;
2010-10-27 21:01:47 +02:00
uint32 count = me -> GetAuraCount ( e . event . aura . spell );
2010-10-31 22:11:56 +01:00
if (( ! e . event . aura . count && ! count ) || ( e . event . aura . count && count >= e . event . aura . count ))
{
ProcessAction ( e );
RecalcTimer ( e , e . event . aura . repeatMin , e . event . aura . repeatMax );
}
2010-10-27 21:01:47 +02:00
break ;
}
case SMART_EVENT_TARGET_BUFFED :
{
2011-03-27 12:54:42 +02:00
if ( ! me || ! me -> getVictim ())
return ;
2010-10-27 21:01:47 +02:00
uint32 count = me -> getVictim () -> GetAuraCount ( e . event . aura . spell );
if ( count < e . event . aura . count )
return ;
ProcessAction ( e );
RecalcTimer ( e , e . event . aura . repeatMin , e . event . aura . repeatMax );
break ;
}
//no params
case SMART_EVENT_AGGRO :
case SMART_EVENT_DEATH :
case SMART_EVENT_EVADE :
case SMART_EVENT_REACHED_HOME :
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_QUEST_ACCEPTED :
case SMART_EVENT_QUEST_OBJ_COPLETETION :
case SMART_EVENT_QUEST_COMPLETION :
case SMART_EVENT_QUEST_REWARDED :
case SMART_EVENT_QUEST_FAIL :
case SMART_EVENT_JUST_SUMMONED :
case SMART_EVENT_RESET :
case SMART_EVENT_JUST_CREATED :
case SMART_EVENT_GOSSIP_HELLO :
2010-11-17 23:24:21 +01:00
case SMART_EVENT_FOLLOW_COMPLETED :
2010-10-27 21:01:47 +02:00
ProcessAction ( e , unit , var0 , var1 , bvar , spell , gob );
break ;
2011-04-14 00:30:32 -03:00
case SMART_EVENT_IS_BEHIND_TARGET :
{
if ( ! me )
return ;
if ( Unit * victim = me -> getVictim ())
{
if ( ! victim -> HasInArc ( static_cast < float > ( M_PI ), me ))
{
ProcessAction ( e , victim );
RecalcTimer ( e , e . event . behindTarget . cooldownMin , e . event . behindTarget . cooldownMax );
}
}
break ;
}
2010-10-27 21:01:47 +02:00
case SMART_EVENT_RECEIVE_EMOTE :
if ( e . event . emote . emote == var0 )
{
ProcessAction ( e , unit );
RecalcTimer ( e , e . event . emote . cooldownMin , e . event . emote . cooldownMax );
}
break ;
case SMART_EVENT_KILL :
{
2011-03-27 12:54:42 +02:00
if ( ! me || ! unit )
return ;
2010-10-27 21:01:47 +02:00
if ( e . event . kill . playerOnly && unit -> GetTypeId () != TYPEID_PLAYER )
return ;
if ( e . event . kill . creature && unit -> GetEntry () != e . event . kill . creature )
return ;
ProcessAction ( e , unit );
RecalcTimer ( e , e . event . kill . cooldownMin , e . event . kill . cooldownMax );
break ;
}
case SMART_EVENT_SPELLHIT_TARGET :
case SMART_EVENT_SPELLHIT :
{
2011-03-27 12:54:42 +02:00
if ( ! spell )
return ;
if (( ! e . event . spellHit . spell || spell -> Id == e . event . spellHit . spell ) &&
( ! e . event . spellHit . school || ( spell -> SchoolMask & e . event . spellHit . school )))
2010-10-27 21:01:47 +02:00
{
ProcessAction ( e , unit , 0 , 0 , bvar , spell );
RecalcTimer ( e , e . event . spellHit . cooldownMin , e . event . spellHit . cooldownMax );
}
break ;
}
case SMART_EVENT_OOC_LOS :
{
2011-03-27 12:54:42 +02:00
if ( ! me || me -> isInCombat ())
return ;
2010-10-27 21:01:47 +02:00
//can trigger if closer than fMaxAllowedRange
float range = ( float ) e . event . los . maxDist ;
//if range is ok and we are actually in LOS
if ( me -> IsWithinDistInMap ( unit , range ) && me -> IsWithinLOSInMap ( unit ))
{
//if friendly event&&who is not hostile OR hostile event&&who is hostile
if (( e . event . los . noHostile && ! me -> IsHostileTo ( unit )) ||
( ! e . event . los . noHostile && me -> IsHostileTo ( unit )))
{
ProcessAction ( e , unit );
RecalcTimer ( e , e . event . los . cooldownMin , e . event . los . cooldownMax );
}
}
break ;
}
case SMART_EVENT_IC_LOS :
{
2011-03-27 12:54:42 +02:00
if ( ! me || ! me -> isInCombat ())
return ;
2010-10-27 21:01:47 +02:00
//can trigger if closer than fMaxAllowedRange
float range = ( float ) e . event . los . maxDist ;
//if range is ok and we are actually in LOS
if ( me -> IsWithinDistInMap ( unit , range ) && me -> IsWithinLOSInMap ( unit ))
{
//if friendly event&&who is not hostile OR hostile event&&who is hostile
if (( e . event . los . noHostile && ! me -> IsHostileTo ( unit )) ||
( ! e . event . los . noHostile && me -> IsHostileTo ( unit )))
{
ProcessAction ( e , unit );
RecalcTimer ( e , e . event . los . cooldownMin , e . event . los . cooldownMax );
}
}
break ;
}
case SMART_EVENT_RESPAWN :
{
2011-03-27 12:54:42 +02:00
if ( ! GetBaseObject ())
return ;
2010-10-27 21:01:47 +02:00
if ( e . event . respawn . type == SMART_SCRIPT_RESPAWN_CONDITION_MAP && GetBaseObject () -> GetMapId () != e . event . respawn . map )
return ;
if ( e . event . respawn . type == SMART_SCRIPT_RESPAWN_CONDITION_AREA && GetBaseObject () -> GetZoneId () != e . event . respawn . area )
return ;
ProcessAction ( e );
break ;
}
case SMART_EVENT_SUMMONED_UNIT :
{
2011-03-27 12:54:42 +02:00
if ( ! IsCreature ( unit ))
return ;
2010-10-27 21:01:47 +02:00
if ( e . event . summoned . creature && unit -> GetEntry () != e . event . summoned . creature )
return ;
ProcessAction ( e , unit );
RecalcTimer ( e , e . event . summoned . cooldownMin , e . event . summoned . cooldownMax );
break ;
}
case SMART_EVENT_RECEIVE_HEAL :
case SMART_EVENT_DAMAGED :
case SMART_EVENT_DAMAGED_TARGET :
{
if ( var0 > e . event . minMaxRepeat . max || var0 < e . event . minMaxRepeat . min )
return ;
ProcessAction ( e , unit );
2011-03-26 23:45:23 +01:00
RecalcTimer ( e , e . event . minMaxRepeat . repeatMin , e . event . minMaxRepeat . repeatMax );
2010-10-27 21:01:47 +02:00
break ;
}
case SMART_EVENT_MOVEMENTINFORM :
{
if (( e . event . movementInform . type && var0 != e . event . movementInform . type ) || ( e . event . movementInform . id && var1 != e . event . movementInform . id ))
return ;
ProcessAction ( e , unit , var0 , var1 );
break ;
}
case SMART_EVENT_TRANSPORT_RELOCATE :
case SMART_EVENT_WAYPOINT_START :
{
if ( e . event . waypoint . pathID && var0 != e . event . waypoint . pathID )
return ;
ProcessAction ( e , unit , var0 );
break ;
}
case SMART_EVENT_WAYPOINT_REACHED :
case SMART_EVENT_WAYPOINT_RESUMED :
case SMART_EVENT_WAYPOINT_PAUSED :
case SMART_EVENT_WAYPOINT_STOPPED :
case SMART_EVENT_WAYPOINT_ENDED :
{
if ( ! me || ( e . event . waypoint . pointID && var0 != e . event . waypoint . pointID ) || ( e . event . waypoint . pathID && GetPathId () != e . event . waypoint . pathID ))
return ;
ProcessAction ( e , unit );
break ;
}
case SMART_EVENT_SUMMON_DESPAWNED :
case SMART_EVENT_INSTANCE_PLAYER_ENTER :
{
if ( e . event . instancePlayerEnter . team && var0 != e . event . instancePlayerEnter . team )
return ;
ProcessAction ( e , unit , var0 );
RecalcTimer ( e , e . event . instancePlayerEnter . cooldownMin , e . event . instancePlayerEnter . cooldownMax );
break ;
}
case SMART_EVENT_ACCEPTED_QUEST :
case SMART_EVENT_REWARD_QUEST :
{
if ( e . event . quest . quest && var0 != e . event . quest . quest )
return ;
ProcessAction ( e , unit , var0 );
break ;
}
case SMART_EVENT_TRANSPORT_ADDCREATURE :
{
if ( e . event . transportAddCreature . creature && var0 != e . event . transportAddCreature . creature )
return ;
ProcessAction ( e , unit , var0 );
break ;
}
case SMART_EVENT_AREATRIGGER_ONTRIGGER :
{
if ( e . event . areatrigger . id && var0 != e . event . areatrigger . id )
return ;
ProcessAction ( e , unit , var0 );
break ;
}
case SMART_EVENT_TEXT_OVER :
{
2010-11-01 11:00:53 +01:00
if ( var0 != e . event . textOver . textGroupID || ( e . event . textOver . creatureEntry && e . event . textOver . creatureEntry != var1 ))
2010-10-27 21:01:47 +02:00
return ;
ProcessAction ( e , unit , var0 );
break ;
}
case SMART_EVENT_DATA_SET :
{
if ( e . event . dataSet . id != var0 || e . event . dataSet . value != var1 )
return ;
ProcessAction ( e , unit , var0 , var1 );
RecalcTimer ( e , e . event . dataSet . cooldownMin , e . event . dataSet . cooldownMax );
break ;
}
case SMART_EVENT_PASSENGER_REMOVED :
case SMART_EVENT_PASSENGER_BOARDED :
{
2011-03-27 12:54:42 +02:00
if ( ! unit )
return ;
2010-10-27 21:01:47 +02:00
ProcessAction ( e , unit );
RecalcTimer ( e , e . event . minMax . repeatMin , e . event . minMax . repeatMax );
break ;
}
case SMART_EVENT_TIMED_EVENT_TRIGGERED :
2011-03-27 12:54:42 +02:00
{
if ( e . event . timedEvent . id == var0 )
ProcessAction ( e , unit );
break ;
}
2010-10-27 21:01:47 +02:00
case SMART_EVENT_GOSSIP_SELECT :
2011-03-27 12:54:42 +02:00
{
sLog -> outDebug ( LOG_FILTER_DATABASE_AI , "SmartScript: Gossip Select: menu %u action %u" , var0 , var1 ); //little help for scripters
if ( e . event . gossip . sender != var0 || e . event . gossip . action != var1 )
return ;
ProcessAction ( e , unit , var0 , var1 );
break ;
}
2010-11-17 23:24:21 +01:00
case SMART_EVENT_DUMMY_EFFECT :
2011-03-27 12:54:42 +02:00
{
if ( e . event . dummy . spell != var0 || e . event . dummy . effIndex != var1 )
return ;
ProcessAction ( e , unit , var0 , var1 );
break ;
}
2011-12-11 16:22:18 +01:00
case SMART_EVENT_GAME_EVENT_START :
case SMART_EVENT_GAME_EVENT_END :
{
if ( e . event . gameEvent . gameEventId != var0 )
return ;
ProcessAction ( e , NULL , var0 );
break ;
}
2010-10-27 21:01:47 +02:00
default :
2010-12-23 23:25:44 +01:00
sLog -> outErrorDb ( "SmartScript::ProcessEvent: Unhandled Event type %u" , e . GetEventType ());
2010-10-27 21:01:47 +02:00
break ;
}
}
2011-03-27 12:54:42 +02:00
void SmartScript :: InitTimer ( SmartScriptHolder & e )
2010-10-27 21:01:47 +02:00
{
switch ( e . GetEventType ())
2011-03-27 12:54:42 +02:00
{
//set only events which have initial timers
2010-10-27 21:01:47 +02:00
case SMART_EVENT_UPDATE :
case SMART_EVENT_UPDATE_IC :
case SMART_EVENT_UPDATE_OOC :
case SMART_EVENT_OOC_LOS :
case SMART_EVENT_IC_LOS :
RecalcTimer ( e , e . event . minMaxRepeat . min , e . event . minMaxRepeat . max );
break ;
default :
e . active = true ;
break ;
}
}
2011-03-27 12:54:42 +02:00
void SmartScript :: RecalcTimer ( SmartScriptHolder & e , uint32 min , uint32 max )
2010-10-27 21:01:47 +02:00
{
// min/max was checked at loading!
e . timer = urand ( uint32 ( min ), uint32 ( max ));
e . active = e . timer ? false : true ;
}
2011-03-27 12:54:42 +02:00
void SmartScript :: UpdateTimer ( SmartScriptHolder & e , uint32 const diff )
2010-10-27 21:01:47 +02:00
{
if ( e . GetEventType () == SMART_EVENT_LINK )
return ;
2011-03-27 12:54:42 +02:00
2010-10-27 21:01:47 +02:00
if ( e . event . event_phase_mask && ! IsInPhase ( e . event . event_phase_mask ))
return ;
2010-12-13 22:37:56 +01:00
2010-11-03 14:10:16 +01:00
if ( e . GetEventType () == SMART_EVENT_UPDATE_IC && ( ! me || ! me -> isInCombat ()))
return ;
2011-03-27 12:54:42 +02:00
2010-11-03 14:10:16 +01:00
if ( e . GetEventType () == SMART_EVENT_UPDATE_OOC && ( me && me -> isInCombat ())) //can be used with me=NULL (go script)
return ;
2011-03-27 12:54:42 +02:00
2010-10-27 21:01:47 +02:00
if ( e . timer < diff )
{
2011-10-23 21:34:50 +03:00
// delay spell cast event if another spell is being casted
if ( e . GetActionType () == SMART_ACTION_CAST )
{
if ( ! ( e . action . cast . flags & SMARTCAST_INTERRUPT_PREVIOUS ))
{
if ( me && me -> HasUnitState ( UNIT_STAT_CASTING ))
{
e . timer = 1 ;
return ;
}
}
}
2010-10-27 21:01:47 +02:00
e . active = true ; //activate events with cooldown
switch ( e . GetEventType ()) //process ONLY timed events
{
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 :
2010-12-13 22:37:56 +01:00
case SMART_EVENT_RANGE :
2010-10-27 21:01:47 +02:00
case SMART_EVENT_TARGET_CASTING :
case SMART_EVENT_FRIENDLY_HEALTH :
case SMART_EVENT_FRIENDLY_IS_CC :
2010-12-13 22:37:56 +01:00
case SMART_EVENT_FRIENDLY_MISSING_BUFF :
2010-10-27 21:01:47 +02:00
case SMART_EVENT_HAS_AURA :
case SMART_EVENT_TARGET_BUFFED :
2011-04-14 00:30:32 -03:00
case SMART_EVENT_IS_BEHIND_TARGET :
2010-11-03 14:10:16 +01:00
{
2010-10-27 21:01:47 +02:00
ProcessEvent ( e );
2010-11-03 14:10:16 +01:00
if ( e . GetScriptType () == SMART_SCRIPT_TYPE_TIMED_ACTIONLIST )
{
e . enableTimed = false ; //disable event if it is in an ActionList and was processed once
for ( SmartAIEventList :: iterator i = mTimedActionList . begin (); i != mTimedActionList . end (); ++ i )
{
//find the first event which is not the current one and enable it
if ( i -> event_id > e . event_id )
{
i -> enableTimed = true ;
break ;
}
}
}
2010-10-27 21:01:47 +02:00
break ;
2010-11-03 14:10:16 +01:00
}
2010-10-27 21:01:47 +02:00
}
2011-03-27 12:54:42 +02:00
}
else
e . timer -= diff ;
2010-10-27 21:01:47 +02:00
}
2011-03-27 12:54:42 +02:00
bool SmartScript :: CheckTimer ( SmartScriptHolder const & e ) const
2010-10-27 21:01:47 +02:00
{
return e . active ;
}
void SmartScript :: InstallEvents ()
{
if ( ! mInstallEvents . empty ())
{
for ( SmartAIEventList :: iterator i = mInstallEvents . begin (); i != mInstallEvents . end (); ++ i )
2011-03-27 12:54:42 +02:00
mEvents . push_back ( * i ); //must be before UpdateTimers
2010-10-27 21:01:47 +02:00
mInstallEvents . clear ();
}
}
2011-03-27 12:54:42 +02:00
void SmartScript :: OnUpdate ( uint32 const diff )
2010-10-27 21:01:47 +02:00
{
if (( mScriptType == SMART_SCRIPT_TYPE_CREATURE || mScriptType == SMART_SCRIPT_TYPE_GAMEOBJECT ) && ! GetBaseObject ())
return ;
2011-03-27 12:54:42 +02:00
2010-10-27 21:01:47 +02:00
InstallEvents (); //before UpdateTimers
for ( SmartAIEventList :: iterator i = mEvents . begin (); i != mEvents . end (); ++ i )
2011-03-27 12:54:42 +02:00
UpdateTimer ( * i , diff );
2010-10-27 21:01:47 +02:00
if ( ! mStoredEvents . empty ())
for ( SmartAIEventList :: iterator i = mStoredEvents . begin (); i != mStoredEvents . end (); ++ i )
2011-03-27 12:54:42 +02:00
UpdateTimer ( * i , diff );
2010-11-03 14:10:16 +01:00
bool needCleanup = true ;
if ( ! mTimedActionList . empty ())
{
for ( SmartAIEventList :: iterator i = mTimedActionList . begin (); i != mTimedActionList . end (); ++ i )
{
if (( * i ). enableTimed )
{
2011-03-27 12:54:42 +02:00
UpdateTimer ( * i , diff );
2010-11-03 14:10:16 +01:00
needCleanup = false ;
}
}
}
if ( needCleanup )
mTimedActionList . clear ();
2010-10-27 21:01:47 +02:00
if ( ! mRemIDs . empty ())
{
for ( std :: list < uint32 >:: iterator i = mRemIDs . begin (); i != mRemIDs . end (); ++ i )
{
RemoveStoredEvent (( * i ));
}
}
if ( mUseTextTimer && me )
{
if ( mTextTimer < diff )
{
2011-09-20 17:56:47 +02:00
uint32 textID = mLastTextID ;
2010-11-01 11:00:53 +01:00
mLastTextID = 0 ;
2011-09-20 17:56:47 +02:00
uint32 entry = mTalkerEntry ;
mTalkerEntry = 0 ;
2010-11-01 11:00:53 +01:00
mTextTimer = 0 ;
mUseTextTimer = false ;
2011-09-20 17:56:47 +02:00
ProcessEventsFor ( SMART_EVENT_TEXT_OVER , NULL , textID , entry );
2010-10-27 21:01:47 +02:00
} else mTextTimer -= diff ;
}
}
void SmartScript :: FillScript ( SmartAIEventList e , WorldObject * obj , AreaTriggerEntry const * at )
{
if ( e . empty ())
{
if ( obj )
2011-02-20 20:16:34 +01:00
sLog -> outDebug ( LOG_FILTER_DATABASE_AI , "SmartScript: EventMap for Entry %u is empty but is using SmartScript." , obj -> GetEntry ());
2010-10-27 21:01:47 +02:00
if ( at )
2011-02-20 20:16:34 +01:00
sLog -> outDebug ( LOG_FILTER_DATABASE_AI , "SmartScript: EventMap for AreaTrigger %u is empty but is using SmartScript." , at -> id );
2010-10-27 21:01:47 +02:00
return ;
}
for ( SmartAIEventList :: iterator i = e . begin (); i != e . end (); ++ i )
{
#ifndef TRINITY_DEBUG
2010-10-27 20:03:42 -07:00
if (( * i ). event . event_flags & SMART_EVENT_FLAG_DEBUG_ONLY )
2010-10-27 21:01:47 +02:00
continue ;
#endif
if (( * i ). event . event_flags & SMART_EVENT_FLAG_DIFFICULTY_ALL ) //if has instance flag add only if in it
{
if ( obj && obj -> GetMap () -> IsDungeon ())
{
if (( 1 << ( obj -> GetMap () -> GetSpawnMode () + 1 )) & ( * i ). event . event_flags )
{
mEvents . push_back (( * i ));
}
}
continue ;
}
mEvents . push_back (( * i )); //NOTE: 'world(0)' events still get processed in ANY instance mode
}
if ( mEvents . empty () && obj )
2010-12-23 23:25:44 +01:00
sLog -> outErrorDb ( "SmartScript: Entry %u has events but no events added to list because of instance flags." , obj -> GetEntry ());
2010-10-27 21:01:47 +02:00
if ( mEvents . empty () && at )
2010-12-23 23:25:44 +01:00
sLog -> outErrorDb ( "SmartScript: AreaTrigger %u has events but no events added to list because of instance flags. NOTE: triggers can not handle any instance flags." , at -> id );
2010-10-27 21:01:47 +02:00
}
void SmartScript :: GetScript ()
{
SmartAIEventList e ;
if ( me )
{
2010-12-22 21:25:23 +01:00
e = sSmartScriptMgr -> GetScript ( - (( int32 ) me -> GetDBTableGUIDLow ()), mScriptType );
2010-10-27 21:01:47 +02:00
if ( e . empty ())
2010-12-22 21:25:23 +01:00
e = sSmartScriptMgr -> GetScript (( int32 ) me -> GetEntry (), mScriptType );
2010-10-27 21:01:47 +02:00
FillScript ( e , me , NULL );
}
else if ( go )
{
2010-12-22 21:25:23 +01:00
e = sSmartScriptMgr -> GetScript ( - (( int32 ) go -> GetDBTableGUIDLow ()), mScriptType );
2010-10-27 21:01:47 +02:00
if ( e . empty ())
2010-12-22 21:25:23 +01:00
e = sSmartScriptMgr -> GetScript (( int32 ) go -> GetEntry (), mScriptType );
2010-10-27 21:01:47 +02:00
FillScript ( e , go , NULL );
}
else if ( trigger )
{
2010-12-22 21:25:23 +01:00
e = sSmartScriptMgr -> GetScript (( int32 ) trigger -> id , mScriptType );
2010-10-27 21:01:47 +02:00
FillScript ( e , NULL , trigger );
}
}
void SmartScript :: OnInitialize ( WorldObject * obj , AreaTriggerEntry const * at )
{
if ( obj ) //handle object based scripts
{
switch ( obj -> GetTypeId ())
{
case TYPEID_UNIT :
mScriptType = SMART_SCRIPT_TYPE_CREATURE ;
me = obj -> ToCreature ();
2011-02-20 20:16:34 +01:00
sLog -> outDebug ( LOG_FILTER_DATABASE_AI , "SmartScript::OnInitialize: source is Creature %u" , me -> GetEntry ());
2010-10-27 21:01:47 +02:00
break ;
case TYPEID_GAMEOBJECT :
mScriptType = SMART_SCRIPT_TYPE_GAMEOBJECT ;
go = obj -> ToGameObject ();
2011-02-20 20:16:34 +01:00
sLog -> outDebug ( LOG_FILTER_DATABASE_AI , "SmartScript::OnInitialize: source is GameObject %u" , go -> GetEntry ());
2010-10-27 21:01:47 +02:00
break ;
default :
2010-12-23 23:25:44 +01:00
sLog -> outError ( "SmartScript::OnInitialize: Unhandled TypeID !WARNING!" );
2010-10-27 21:01:47 +02:00
return ;
}
} else if ( at )
{
mScriptType = SMART_SCRIPT_TYPE_AREATRIGGER ;
trigger = at ;
2011-02-20 20:16:34 +01:00
sLog -> outDebug ( LOG_FILTER_DATABASE_AI , "SmartScript::OnInitialize: source is AreaTrigger %u" , trigger -> id );
2010-10-27 21:01:47 +02:00
}
else
{
2010-12-23 23:25:44 +01:00
sLog -> outError ( "SmartScript::OnInitialize: !WARNING! Initialized objects are NULL." );
2010-10-27 21:01:47 +02:00
return ;
}
GetScript (); //load copy of script
for ( SmartAIEventList :: iterator i = mEvents . begin (); i != mEvents . end (); ++ i )
InitTimer (( * i )); //calculate timers for first time use
ProcessEventsFor ( SMART_EVENT_AI_INIT );
InstallEvents ();
ProcessEventsFor ( SMART_EVENT_JUST_CREATED );
}
void SmartScript :: OnMoveInLineOfSight ( Unit * who )
{
ProcessEventsFor ( SMART_EVENT_OOC_LOS , who );
2011-06-12 02:30:32 +02:00
if ( ! me ) return ;
2010-10-27 21:01:47 +02:00
if ( me -> getVictim ())
return ;
ProcessEventsFor ( SMART_EVENT_IC_LOS , who );
2010-12-13 22:37:56 +01:00
2010-10-27 21:01:47 +02:00
}
/*
void SmartScript::UpdateAIWhileCharmed(const uint32 diff)
{
}
void SmartScript::DoAction(const int32 param)
{
}
uint32 SmartScript::GetData(uint32 id)
{
return 0;
}
void SmartScript::SetData(uint32 id, uint32 value)
{
}
2011-08-30 13:46:36 +02:00
void SmartScript::SetGUID(uint64 guid, int32 id)
2010-10-27 21:01:47 +02:00
{
}
uint64 SmartScript::GetGUID(int32 id)
{
return 0;
}
void SmartScript::MovepointStart(uint32 id)
{
}
void SmartScript::SetRun(bool run)
{
}
void SmartScript::SetMovePathEndAction(SMART_ACTION action)
{
}
uint32 SmartScript::DoChat(int8 id, uint64 whisperGuid)
{
return 0;
}*/
// SmartScript end
Unit * SmartScript :: DoSelectLowestHpFriendly ( float range , uint32 MinHPDiff )
{
2011-10-19 17:40:44 +01:00
if ( ! me )
return NULL ;
2011-10-18 10:53:34 -04:00
CellCoord p ( Trinity :: ComputeCellCoord ( me -> GetPositionX (), me -> GetPositionY ()));
2010-10-27 21:01:47 +02:00
Cell cell ( p );
cell . SetNoCreate ();
2011-08-20 20:31:31 -03:00
Unit * unit = NULL ;
2010-10-27 21:01:47 +02:00
Trinity :: MostHPMissingInRange u_check ( me , range , MinHPDiff );
2011-08-20 20:31:31 -03:00
Trinity :: UnitLastSearcher < Trinity :: MostHPMissingInRange > searcher ( me , unit , u_check );
2010-10-27 21:01:47 +02:00
TypeContainerVisitor < Trinity :: UnitLastSearcher < Trinity :: MostHPMissingInRange > , GridTypeMapContainer > grid_unit_searcher ( searcher );
cell . Visit ( p , grid_unit_searcher , * me -> GetMap (), * me , range );
2011-08-20 20:31:31 -03:00
return unit ;
2010-10-27 21:01:47 +02:00
}
void SmartScript :: DoFindFriendlyCC ( std :: list < Creature *>& _list , float range )
{
2011-10-19 17:40:44 +01:00
if ( ! me )
return ;
2011-10-18 10:53:34 -04:00
CellCoord p ( Trinity :: ComputeCellCoord ( me -> GetPositionX (), me -> GetPositionY ()));
2010-10-27 21:01:47 +02:00
Cell cell ( p );
cell . SetNoCreate ();
Trinity :: FriendlyCCedInRange u_check ( me , range );
Trinity :: CreatureListSearcher < Trinity :: FriendlyCCedInRange > searcher ( me , _list , u_check );
TypeContainerVisitor < Trinity :: CreatureListSearcher < Trinity :: FriendlyCCedInRange > , GridTypeMapContainer > grid_creature_searcher ( searcher );
2011-10-19 17:40:44 +01:00
cell . Visit ( p , grid_creature_searcher , * me -> GetMap (), * me , range );
2010-10-27 21:01:47 +02:00
}
2011-06-15 17:33:06 +02:00
void SmartScript :: DoFindFriendlyMissingBuff ( std :: list < Creature *>& list , float range , uint32 spellid )
2010-10-27 21:01:47 +02:00
{
2011-10-19 17:40:44 +01:00
if ( ! me )
return ;
2011-10-18 10:53:34 -04:00
CellCoord p ( Trinity :: ComputeCellCoord ( me -> GetPositionX (), me -> GetPositionY ()));
2010-10-27 21:01:47 +02:00
Cell cell ( p );
cell . SetNoCreate ();
Trinity :: FriendlyMissingBuffInRange u_check ( me , range , spellid );
2011-06-15 17:33:06 +02:00
Trinity :: CreatureListSearcher < Trinity :: FriendlyMissingBuffInRange > searcher ( me , list , u_check );
2010-10-27 21:01:47 +02:00
TypeContainerVisitor < Trinity :: CreatureListSearcher < Trinity :: FriendlyMissingBuffInRange > , GridTypeMapContainer > grid_creature_searcher ( searcher );
2011-10-19 17:40:44 +01:00
cell . Visit ( p , grid_creature_searcher , * me -> GetMap (), * me , range );
2010-11-07 22:10:11 +01:00
}
2011-03-27 12:54:42 +02:00
void SmartScript :: SetScript9 ( SmartScriptHolder & e , uint32 entry )
2010-11-07 22:10:11 +01:00
{
mTimedActionList . clear ();
2010-12-22 21:25:23 +01:00
mTimedActionList = sSmartScriptMgr -> GetScript ( entry , SMART_SCRIPT_TYPE_TIMED_ACTIONLIST );
2010-11-07 22:10:11 +01:00
if ( mTimedActionList . empty ())
return ;
for ( SmartAIEventList :: iterator i = mTimedActionList . begin (); i != mTimedActionList . end (); ++ i )
{
if ( i == mTimedActionList . begin ())
{
i -> enableTimed = true ; //enable processing only for the first action
}
else i -> enableTimed = false ;
2010-12-13 22:37:56 +01:00
2010-11-07 22:10:11 +01:00
if ( e . action . timedActionList . timerType == 1 )
i -> event . type = SMART_EVENT_UPDATE_IC ;
else if ( e . action . timedActionList . timerType > 1 )
i -> event . type = SMART_EVENT_UPDATE ;
mResumeActionList = e . action . timedActionList . dontResume ? false : true ;
InitTimer (( * i ));
}
2011-12-11 16:22:18 +01:00
}
Unit * SmartScript :: GetLastInvoker ()
2011-02-21 22:23:43 +01:00
{
return ObjectAccessor :: FindUnit ( mLastInvoker );
2010-11-16 14:08:12 +01:00
}