OregonCore  revision be9e804-git
Your Favourite TBC server
SmartScript.cpp
Go to the documentation of this file.
1 /*
2 * This file is part of the OregonCore Project. See AUTHORS file for Copyright information
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <https://www.gnu.org/licenses/>.
16 */
17 
18 #include "Common.h"
19 #include "G3D/Vector3.h"
20 #include "Cell.h"
21 #include "CellImpl.h"
22 #include "CreatureTextMgr.h"
23 #include "DatabaseEnv.h"
24 #include "GossipDef.h"
25 #include "GridDefines.h"
26 #include "GridNotifiers.h"
27 #include "GridNotifiersImpl.h"
28 #include "Group.h"
29 #include "Language.h"
30 #include "ObjectMgr.h"
31 #include "ScriptedCreature.h"
32 #include "ScriptedGossip.h"
33 #include "SmartAI.h"
34 #include "SmartScript.h"
35 #include "SpellMgr.h"
36 #include "GameEventMgr.h"
37 #include "ScriptMgr.h"
38 
40 {
41  public:
42  OregonStringTextBuilder(WorldObject* obj, ChatMsg msgtype, int32 id, uint32 language, WorldObject* target)
43  : _source(obj), _msgType(msgtype), _textId(id), _language(language), _target(target)
44  {
45  }
46 
47  size_t operator()(WorldPacket* data, int locale) const
48  {
49  std::string text = sObjectMgr.GetOregonString(_textId, locale);
50 
52  }
53 
59 };
60 
62 {
63  go = NULL;
64  me = NULL;
65  trigger = NULL;
66  mEventPhase = 0;
67  mPathId = 0;
68  mTargetStorage = new ObjectListMap();
69  mTextTimer = 0;
70  mLastTextID = 0;
71  mUseTextTimer = false;
72  mTalkerEntry = 0;
73  mTemplate = SMARTAI_TEMPLATE_BASIC;
74  mScriptType = SMART_SCRIPT_TYPE_CREATURE;
75  isProcessingTimedActionList = false;
76 }
77 
79 {
80  for (ObjectListMap::iterator itr = mTargetStorage->begin(); itr != mTargetStorage->end(); ++itr)
81  delete itr->second;
82 
83  delete mTargetStorage;
84  mCounterList.clear();
85 }
86 
88 {
89  ResetBaseObject();
90  for (SmartAIEventList::iterator i = mEvents.begin(); i != mEvents.end(); ++i)
91  {
92  if (!((*i).event.event_flags & SMART_EVENT_FLAG_DONT_RESET))
93  {
94  InitTimer((*i));
95  (*i).runOnce = false;
96  }
97  }
98  ProcessEventsFor(SMART_EVENT_RESET);
99  mLastInvoker.Clear();
100  mCounterList.clear();
101 }
102 
103 void SmartScript::ProcessEventsFor(SMART_EVENT e, Unit* unit, uint32 var0, uint32 var1, bool bvar, const SpellEntry* spell, GameObject* gob)
104 {
105  for (SmartAIEventList::iterator i = mEvents.begin(); i != mEvents.end(); ++i)
106  {
107  SMART_EVENT eventType = SMART_EVENT(i->GetEventType());
108  if (eventType == SMART_EVENT_LINK)//special handling
109  continue;
110 
111  if (eventType == e)
112  {
113  ConditionList conds = sConditionMgr.GetConditionsForSmartEvent(i->entryOrGuid, i->event_id, i->source_type);
114  ConditionSourceInfo info = ConditionSourceInfo(unit, GetBaseObject());
115 
116  if (sConditionMgr.IsObjectMeetToConditions(info, conds))
117  ProcessEvent(*i, unit, var0, var1, bvar, spell, gob);
118  }
119  }
120 }
121 
122 void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, uint32 var1, bool bvar, const SpellEntry* spell, GameObject* gob)
123 {
124  // calc random
126  {
128  return;
129  }
130  e.runOnce = true;//used for repeat check
131 
132  if (unit)
133  mLastInvoker = unit->GetGUID();
134 
135  if (Unit* tempInvoker = GetLastInvoker())
136  sLog.outDebug("SmartScript::ProcessAction: Invoker: %s (guidlow: %u)", tempInvoker->GetName(), tempInvoker->GetGUIDLow());
137 
138  switch (e.GetActionType())
139  {
140  case SMART_ACTION_TALK:
141  {
142  ObjectList* targets = GetTargets(e, unit);
143  Creature* talker = me;
144  Player* targetPlayer = NULL;
145  Unit* talkTarget = NULL;
146 
147  if (targets)
148  {
149  for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr)
150  {
151  if (IsCreature(*itr) && !(*itr)->ToCreature()->IsPet()) // Prevented sending text to pets.
152  {
153  if (e.action.talk.useTalkTarget)
154  talkTarget = (*itr)->ToCreature();
155  else
156  talker = (*itr)->ToCreature();
157  break;
158  }
159  else if (IsPlayer(*itr))
160  {
161  targetPlayer = (*itr)->ToPlayer();
162  break;
163  }
164  }
165 
166  delete targets;
167  }
168 
169  if (!talker)
170  break;
171 
172  mTalkerEntry = talker->GetEntry();
173  mLastTextID = e.action.talk.textGroupID;
174  mTextTimer = e.action.talk.duration;
175 
176  if (IsPlayer(GetLastInvoker())) // used for $vars in texts and whisper target
177  talkTarget = GetLastInvoker();
178  else if (targetPlayer)
179  talkTarget = targetPlayer;
180 
181  mUseTextTimer = true;
182 
183  sCreatureTextMgr->SendChat(talker, uint8(e.action.talk.textGroupID), talkTarget);
184  sLog.outDebug("SmartScript::ProcessAction: SMART_ACTION_TALK: talker: %s (GuidLow: %u), textGuid: %u",
185  talker->GetName(), talker->GetGUIDLow(), talkTarget ? talkTarget->GetGUIDLow() : 0);
186  break;
187  }
189  {
190  ObjectList* targets = GetTargets(e, unit);
191  if (targets)
192  {
193  for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr)
194  {
195  if (IsCreature(*itr))
196  sCreatureTextMgr->SendChat((*itr)->ToCreature(), uint8(e.action.talk.textGroupID), IsPlayer(GetLastInvoker()) ? GetLastInvoker() : 0);
197  else if (IsPlayer(*itr) && me)
198  {
199  Unit* templastInvoker = GetLastInvoker();
200  sCreatureTextMgr->SendChat(me, uint8(e.action.talk.textGroupID), IsPlayer(templastInvoker) ? templastInvoker : 0, CHAT_MSG_ADDON, LANG_ADDON, TEXT_RANGE_NORMAL, 0, TEAM_NONE, false, (*itr)->ToPlayer());
201  }
202  //sLog.outDebug("SmartScript::ProcessAction:: SMART_ACTION_SIMPLE_TALK: talker: %s (GuidLow: %u), textGroupId: %u",
203  //(*itr)->GetName(), (*itr)->GetGUIDLow(), uint8(e.action.talk.textGroupID));
204  }
205 
206  delete targets;
207  }
208  break;
209  }
211  {
212  ObjectList* targets = GetTargets(e, unit);
213  if (targets)
214  {
215  for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr)
216  {
217  if (IsUnit(*itr))
218  {
219  (*itr)->ToUnit()->HandleEmoteCommand(e.action.emote.emote);
220  sLog.outDebug("SmartScript::ProcessAction:: SMART_ACTION_PLAY_EMOTE: target: %s (GuidLow: %u), emote: %u",
221  (*itr)->GetName(), (*itr)->GetGUIDLow(), e.action.emote.emote);
222  }
223  }
224 
225  delete targets;
226  }
227  break;
228  }
229  case SMART_ACTION_SOUND:
230  {
231  ObjectList* targets = GetTargets(e, unit);
232  if (targets)
233  {
234  for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr)
235  {
236  if (IsUnit(*itr))
237  {
238  if (e.action.sound.distance == 1)
239  (*itr)->PlayDistanceSound(e.action.sound.sound, e.action.sound.onlySelf ? (*itr)->ToPlayer() : nullptr);
240  else
241  (*itr)->PlayDirectSound(e.action.sound.sound, e.action.sound.onlySelf ? (*itr)->ToPlayer() : nullptr);
242 
243  sLog.outDebug("SmartScript::ProcessAction:: SMART_ACTION_SOUND: target: %s (GuidLow: %u), sound: %u, onlyself: %u",
244  (*itr)->GetName(), (*itr)->GetGUIDLow(), e.action.sound.sound, e.action.sound.onlySelf);
245  }
246  }
247 
248  delete targets;
249  }
250  break;
251  }
253  {
254  ObjectList* targets = GetTargets(e, unit);
255  if (targets)
256  {
257  for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr)
258  {
259  if (IsCreature(*itr))
260  {
261  if (e.action.faction.factionID)
262  {
263  (*itr)->ToCreature()->SetFaction(e.action.faction.factionID);
264  sLog.outDebug("SmartScript::ProcessAction:: SMART_ACTION_SET_FACTION: Creature entry %u, GuidLow %u set faction to %u",
265  (*itr)->GetEntry(), (*itr)->GetGUIDLow(), e.action.faction.factionID);
266  }
267  else
268  {
269  if (CreatureInfo const* ci = sObjectMgr.GetCreatureTemplate((*itr)->ToCreature()->GetEntry()))
270  {
271  if ((*itr)->ToCreature()->GetFaction() != ci->faction)
272  {
273  (*itr)->ToCreature()->SetFaction(ci->faction);
274  sLog.outDebug("SmartScript::ProcessAction:: SMART_ACTION_SET_FACTION: Creature entry %u, GuidLow %u set faction to %u",
275  (*itr)->GetEntry(), (*itr)->GetGUIDLow(), ci->faction);
276  }
277  }
278  }
279  }
280  }
281 
282  delete targets;
283  }
284  break;
285  }
287  {
288  ObjectList* targets = GetTargets(e, unit);
289  if (!targets)
290  break;
291 
292  for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr)
293  {
294  if (!IsCreature(*itr))
295  continue;
296 
297  if (e.action.morphOrMount.creature || e.action.morphOrMount.model)
298  {
299  //set model based on entry from creature_template
300  if (e.action.morphOrMount.creature)
301  {
302  if (CreatureInfo const* ci = sObjectMgr.GetCreatureTemplate(e.action.morphOrMount.creature))
303  {
304  uint32 displayId = ci->GetRandomValidModelId();
305  (*itr)->ToCreature()->SetDisplayId(displayId);
306  sLog.outDebug("SmartScript::ProcessAction:: SMART_ACTION_MORPH_TO_ENTRY_OR_MODEL: Creature entry %u, GuidLow %u set displayid to %u",
307  (*itr)->GetEntry(), (*itr)->GetGUIDLow(), displayId);
308  }
309  }
310  //if no param1, then use value from param2 (modelId)
311  else
312  {
313  (*itr)->ToCreature()->SetDisplayId(e.action.morphOrMount.model);
314  sLog.outDebug("SmartScript::ProcessAction:: SMART_ACTION_MORPH_TO_ENTRY_OR_MODEL: Creature entry %u, GuidLow %u set displayid to %u",
315  (*itr)->GetEntry(), (*itr)->GetGUIDLow(), e.action.morphOrMount.model);
316  }
317  }
318  else
319  {
320  (*itr)->ToCreature()->DeMorph();
321  sLog.outDebug("SmartScript::ProcessAction:: SMART_ACTION_MORPH_TO_ENTRY_OR_MODEL: Creature entry %u, GuidLow %u demorphs.",
322  (*itr)->GetEntry(), (*itr)->GetGUIDLow());
323  }
324  }
325 
326  delete targets;
327  break;
328  }
330  {
331  ObjectList* targets = GetTargets(e, unit);
332  if (!targets)
333  break;
334 
335  for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr)
336  {
337  if (IsPlayer(*itr))
338  {
339  (*itr)->ToPlayer()->FailQuest(e.action.quest.quest);
340  sLog.outDebug("SmartScript::ProcessAction:: SMART_ACTION_FAIL_QUEST: Player guidLow %u fails quest %u",
341  (*itr)->GetGUIDLow(), e.action.quest.quest);
342  }
343  }
344 
345  delete targets;
346  break;
347  }
349  {
350  ObjectList* targets = GetTargets(e, unit);
351  if (!targets)
352  break;
353 
354  for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr)
355  {
356  if (IsPlayer(*itr))
357  {
358  if (Quest const* q = sObjectMgr.GetQuestTemplate(e.action.quest.quest))
359  {
360  (*itr)->ToPlayer()->AddQuest(q, NULL);
361  sLog.outDebug("SmartScript::ProcessAction:: SMART_ACTION_ADD_QUEST: Player guidLow %u add quest %u",
362  (*itr)->GetGUIDLow(), e.action.quest.quest);
363  }
364  }
365  }
366 
367  delete targets;
368  break;
369  }
371  {
372  ObjectList* targets = GetTargets(e, unit);
373  if (!targets)
374  break;
375 
376  for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr)
377  {
378  if (!IsCreature(*itr))
379  continue;
380 
381  (*itr)->ToCreature()->SetReactState(ReactStates(e.action.react.state));
382  }
383 
384  delete targets;
385  break;
386  }
388  {
389  ObjectList* targets = GetTargets(e, unit);
390  if (!targets)
391  break;
392 
394  emotes[0] = e.action.randomEmote.emote1;
395  emotes[1] = e.action.randomEmote.emote2;
396  emotes[2] = e.action.randomEmote.emote3;
397  emotes[3] = e.action.randomEmote.emote4;
398  emotes[4] = e.action.randomEmote.emote5;
399  emotes[5] = e.action.randomEmote.emote6;
401  uint32 count = 0;
402  for (uint8 i = 0; i < SMART_ACTION_PARAM_COUNT; i++)
403  {
404  if (emotes[i])
405  {
406  temp[count] = emotes[i];
407  ++count;
408  }
409  }
410 
411  if (count == 0)
412  {
413  delete targets;
414  break;
415  }
416 
417  for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr)
418  {
419  if (IsUnit(*itr))
420  {
421  uint32 emote = temp[urand(0, count - 1)];
422  (*itr)->ToUnit()->HandleEmoteCommand(emote);
423  sLog.outDebug("SmartScript::ProcessAction:: SMART_ACTION_RANDOM_EMOTE: Creature guidLow %u handle random emote %u",
424  (*itr)->GetGUIDLow(), emote);
425  }
426  }
427 
428  delete targets;
429  break;
430  }
432  {
433  if (!me)
434  break;
435 
436  ThreatContainer::StorageType threatList = me->getThreatManager().getThreatList();
437  for (ThreatContainer::StorageType::const_iterator i = threatList.begin(); i != threatList.end(); ++i)
438  {
439  if (Unit* target = ObjectAccessor::GetUnit(*me, (*i)->getUnitGuid()))
440  {
441  me->getThreatManager().modifyThreatPercent(target, e.action.threatPCT.threatINC ? (int32)e.action.threatPCT.threatINC : -(int32)e.action.threatPCT.threatDEC);
442  sLog.outDebug("SmartScript::ProcessAction:: SMART_ACTION_THREAT_ALL_PCT: Creature guidLow %u modify threat for unit %u, value %i",
443  me->GetGUIDLow(), target->GetGUIDLow(), e.action.threatPCT.threatINC ? (int32)e.action.threatPCT.threatINC : -(int32)e.action.threatPCT.threatDEC);
444  }
445  }
446  break;
447  }
449  {
450  if (!me)
451  break;
452 
453  ObjectList* targets = GetTargets(e, unit);
454  if (!targets)
455  break;
456 
457  for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr)
458  {
459  if (IsUnit(*itr))
460  {
461  me->getThreatManager().modifyThreatPercent((*itr)->ToUnit(), e.action.threatPCT.threatINC ? (int32)e.action.threatPCT.threatINC : -(int32)e.action.threatPCT.threatDEC);
462  sLog.outDebug("SmartScript::ProcessAction:: SMART_ACTION_THREAT_SINGLE_PCT: Creature guidLow %u modify threat for unit %u, value %i",
463  me->GetGUIDLow(), (*itr)->GetGUIDLow(), e.action.threatPCT.threatINC ? (int32)e.action.threatPCT.threatINC : -(int32)e.action.threatPCT.threatDEC);
464  }
465  }
466 
467  delete targets;
468  break;
469  }
471  {
472  ObjectList* targets = GetTargets(e, unit);
473  if (!targets)
474  break;
475 
476  for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr)
477  {
478  if (IsPlayer(*itr))
479  {
480  (*itr)->ToPlayer()->GroupEventHappens(e.action.quest.quest, me);
481 
482  sLog.outDebug("SmartScript::ProcessAction:: SMART_ACTION_CALL_AREAEXPLOREDOREVENTHAPPENS: Player guidLow %u credited quest %u",
483  (*itr)->GetGUIDLow(), e.action.quest.quest);
484  }
485  }
486 
487  delete targets;
488  break;
489  }
490  case SMART_ACTION_CAST:
491  {
492  ObjectList* targets = GetTargets(e, unit);
493  if (!targets)
494  break;
495 
496  for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr)
497  {
498  if (!IsUnit(*itr))
499  continue;
500 
501  if (!(e.action.cast.flags & SMARTCAST_AURA_NOT_PRESENT) || !(*itr)->ToUnit()->HasAura(e.action.cast.spell))
502  {
503  if (me)
504  {
506  me->InterruptNonMeleeSpells(false);
507 
508  if (e.action.cast.flags & SMARTCAST_COMBAT_MOVE)
509  {
510  // If cast flag SMARTCAST_COMBAT_MOVE is set combat movement will not be allowed
511  // unless target is outside spell range, out of mana, or LOS.
512 
513  bool _allowMove = false;
514  SpellEntry const* spellInfo = sSpellStore.LookupEntry(e.action.cast.spell);
515  float maxRange = sSpellRangeStore.LookupEntry(spellInfo->rangeIndex)->maxRange;
516  float minRange = sSpellRangeStore.LookupEntry(spellInfo->rangeIndex)->minRange;
517  int32 mana = me->GetPower(POWER_MANA);
518  if (me->GetDistance(*itr) > maxRange ||
519  me->GetDistance(*itr) < minRange ||
520  !me->IsWithinLOSInMap(*itr) ||
521  mana < CalculatePowerCost(spellInfo, me, GetSpellSchoolMask(spellInfo)))
522  _allowMove = true;
523 
524  CAST_AI(SmartAI, me->AI())->SetCombatMove(_allowMove);
525  }
526 
527  me->CastSpell((*itr)->ToUnit(), e.action.cast.spell, (e.action.cast.flags & SMARTCAST_TRIGGERED) != 0);
528  }
529  else if (go)
530  go->CastSpell((*itr)->ToUnit(), e.action.cast.spell, (e.action.cast.flags & SMARTCAST_TRIGGERED) != 0);
531 
532  sLog.outDebug("SmartScript::ProcessAction:: SMART_ACTION_CAST:: %s: %u casts spell %u on target %u with castflags %u",
533  (me ? me->GetObjectGUID() : go->GetObjectGUID()).GetTypeName(), me ? me->GetGUIDLow() : go->GetGUIDLow(), e.action.cast.spell, (*itr)->GetGUIDLow(), e.action.cast.flags);
534  }
535  else
536  sLog.outDebug("Spell %u not cast because it has flag SMARTCAST_AURA_NOT_PRESENT and the target (%s) already has the aura", e.action.cast.spell, (*itr)->GetObjectGUID().GetString().c_str());
537  }
538 
539  delete targets;
540  break;
541  }
543  {
544  Unit* tempLastInvoker = GetLastInvoker();
545  if (!tempLastInvoker)
546  break;
547 
548  ObjectList* targets = GetTargets(e, unit);
549  if (!targets)
550  break;
551 
552  for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr)
553  {
554  if (!IsUnit(*itr))
555  continue;
556 
557  if (!(e.action.cast.flags & SMARTCAST_AURA_NOT_PRESENT) || !(*itr)->ToUnit()->HasAura(e.action.cast.spell))
558  {
560  tempLastInvoker->InterruptNonMeleeSpells(false);
561 
562  tempLastInvoker->CastSpell((*itr)->ToUnit(), e.action.cast.spell, (e.action.cast.flags & SMARTCAST_TRIGGERED) != 0);
563  sLog.outDebug("SmartScript::ProcessAction:: SMART_ACTION_INVOKER_CAST: Invoker %u casts spell %u on target %u with castflags %u",
564  tempLastInvoker->GetGUIDLow(), e.action.cast.spell, (*itr)->GetGUIDLow(), e.action.cast.flags);
565  }
566  else
567  sLog.outDebug("Spell %u not cast because it has flag SMARTCAST_AURA_NOT_PRESENT and the target (%s) already has the aura", e.action.cast.spell, (*itr)->GetObjectGUID().GetString().c_str());
568  }
569 
570  delete targets;
571  break;
572  }
574  {
575  ObjectList* targets = GetTargets(e, unit);
576  if (!targets)
577  break;
578 
579  for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr)
580  {
581  if (IsUnit(*itr))
582  {
583  (*itr)->ToUnit()->AddAura(e.action.cast.spell, (*itr)->ToUnit());
584  sLog.outDebug("SmartScript::ProcessAction:: SMART_ACTION_ADD_AURA: Adding aura %u to unit %u",
585  e.action.cast.spell, (*itr)->GetGUIDLow());
586  }
587  }
588 
589  delete targets;
590  break;
591  }
593  {
594  ObjectList* targets = GetTargets(e, unit);
595  if (!targets)
596  break;
597 
598  for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr)
599  {
600  if (IsGameObject(*itr))
601  {
602  // Activate
603  (*itr)->ToGameObject()->SetLootState(GO_READY);
604  (*itr)->ToGameObject()->UseDoorOrButton(0, false, unit);
605  sLog.outDebug("SmartScript::ProcessAction:: SMART_ACTION_ACTIVATE_GOBJECT. Gameobject %u (entry: %u) activated",
606  (*itr)->GetGUIDLow(), (*itr)->GetEntry());
607  }
608  }
609 
610  delete targets;
611  break;
612  }
614  {
615  ObjectList* targets = GetTargets(e, unit);
616  if (!targets)
617  break;
618 
619  for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr)
620  {
621  if (IsGameObject(*itr))
622  {
623  (*itr)->ToGameObject()->ResetDoorOrButton();
624  sLog.outDebug("SmartScript::ProcessAction:: SMART_ACTION_RESET_GOBJECT. Gameobject %u (entry: %u) reset",
625  (*itr)->GetGUIDLow(), (*itr)->GetEntry());
626  }
627  }
628 
629  delete targets;
630  break;
631  }
633  {
634  ObjectList* targets = GetTargets(e, unit);
635  if (!targets)
636  break;
637 
638  for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr)
639  {
640  if (IsUnit(*itr))
641  {
642  (*itr)->ToUnit()->SetUInt32Value(UNIT_NPC_EMOTESTATE, e.action.emote.emote);
643  sLog.outDebug("SmartScript::ProcessAction:: SMART_ACTION_SET_EMOTE_STATE. Unit %u set emotestate to %u",
644  (*itr)->GetGUIDLow(), e.action.emote.emote);
645  }
646  }
647 
648  delete targets;
649  break;
650  }
652  {
653  ObjectList* targets = GetTargets(e, unit);
654  if (!targets)
655  break;
656 
657  for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr)
658  {
659  if (IsUnit(*itr))
660  {
661  if (!e.action.unitFlag.type)
662  {
663  (*itr)->ToUnit()->SetFlag(UNIT_FIELD_FLAGS, e.action.unitFlag.flag);
664  sLog.outDebug("SmartScript::ProcessAction:: SMART_ACTION_SET_UNIT_FLAG. Unit %u added flag %u to UNIT_FIELD_FLAGS",
665  (*itr)->GetGUIDLow(), e.action.unitFlag.flag);
666  }
667  else
668  {
669  (*itr)->ToUnit()->SetFlag(UNIT_FIELD_FLAGS_2, e.action.unitFlag.flag);
670  sLog.outDebug("SmartScript::ProcessAction:: SMART_ACTION_SET_UNIT_FLAG. Unit %u added flag %u to UNIT_FIELD_FLAGS_2",
671  (*itr)->GetGUIDLow(), e.action.unitFlag.flag);
672  }
673  }
674  }
675 
676  delete targets;
677  break;
678  }
680  {
681  ObjectList* targets = GetTargets(e, unit);
682  if (!targets)
683  break;
684 
685  for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr)
686  {
687  if (IsUnit(*itr))
688  {
689  if (!e.action.unitFlag.type)
690  {
691  (*itr)->ToUnit()->RemoveFlag(UNIT_FIELD_FLAGS, e.action.unitFlag.flag);
692  sLog.outDebug("SmartScript::ProcessAction:: SMART_ACTION_REMOVE_UNIT_FLAG. Unit %u removed flag %u to UNIT_FIELD_FLAGS",
693  (*itr)->GetGUIDLow(), e.action.unitFlag.flag);
694  }
695  else
696  {
697  (*itr)->ToUnit()->RemoveFlag(UNIT_FIELD_FLAGS_2, e.action.unitFlag.flag);
698  sLog.outDebug("SmartScript::ProcessAction:: SMART_ACTION_REMOVE_UNIT_FLAG. Unit %u removed flag %u to UNIT_FIELD_FLAGS_2",
699  (*itr)->GetGUIDLow(), e.action.unitFlag.flag);
700  }
701  }
702  }
703 
704  delete targets;
705  break;
706  }
708  {
709  if (!IsSmart())
710  break;
711 
712  CAST_AI(SmartAI, me->AI())->SetAutoAttack(e.action.autoAttack.attack != 0);
713  sLog.outDebug("SmartScript::ProcessAction:: SMART_ACTION_AUTO_ATTACK: Creature: %u bool on = %u",
714  me->GetGUIDLow(), e.action.autoAttack.attack);
715  break;
716  }
718  {
719  if (!IsSmart())
720  break;
721 
722  bool move = e.action.combatMove.move != 0;
723  CAST_AI(SmartAI, me->AI())->SetCombatMove(move);
724  sLog.outDebug("SmartScript::ProcessAction:: SMART_ACTION_ALLOW_COMBAT_MOVEMENT: Creature %u bool on = %u",
725  me->GetGUIDLow(), e.action.combatMove.move);
726  break;
727  }
729  {
730  if (!GetBaseObject())
731  break;
732 
733  SetPhase(e.action.setEventPhase.phase);
734  sLog.outDebug("SmartScript::ProcessAction:: SMART_ACTION_SET_EVENT_PHASE: Creature %u set event phase %u",
735  GetBaseObject()->GetGUIDLow(), e.action.setEventPhase.phase);
736  break;
737  }
739  {
740  if (!GetBaseObject())
741  break;
742 
743  IncPhase(e.action.incEventPhase.inc);
744  DecPhase(e.action.incEventPhase.dec);
745  sLog.outDebug("SmartScript::ProcessAction:: SMART_ACTION_INC_EVENT_PHASE: Creature %u inc event phase by %u, "
746  "decrease by %u", GetBaseObject()->GetGUIDLow(), e.action.incEventPhase.inc, e.action.incEventPhase.dec);
747  break;
748  }
749  case SMART_ACTION_EVADE:
750  {
751  if (!me)
752  break;
753 
754  me->AI()->EnterEvadeMode();
755  sLog.outDebug("SmartScript::ProcessAction:: SMART_ACTION_EVADE: Creature %u EnterEvadeMode", me->GetGUIDLow());
756  break;
757  }
759  {
760  if (!me)
761  break;
762 
763  me->DoFleeToGetAssistance();
764  if (e.action.flee.withEmote)
765  {
767  sCreatureTextMgr->SendChatPacket(me, builder, CHAT_MSG_MONSTER_EMOTE);
768  }
769  sLog.outDebug("SmartScript::ProcessAction:: SMART_ACTION_FLEE_FOR_ASSIST: Creature %u DoFleeToGetAssistance", me->GetGUIDLow());
770  break;
771  }
773  {
774  if (!unit)
775  break;
776 
777  if (IsPlayer(unit) && GetBaseObject())
778  {
779  unit->ToPlayer()->GroupEventHappens(e.action.quest.quest, GetBaseObject());
780  sLog.outDebug("SmartScript::ProcessAction: SMART_ACTION_CALL_GROUPEVENTHAPPENS: Player %u, group credit for quest %u",
781  unit->GetGUIDLow(), e.action.quest.quest);
782  }
783 
784  break;
785  }
787  {
788  if (!me)
789  break;
790 
791  me->CombatStop(true);
792  sLog.outDebug("SmartScript::ProcessAction:: SMART_ACTION_COMBAT_STOP: %s CombatStop", me->GetObjectGUID().GetString().c_str());
793  break;
794  }
796  {
797  ObjectList* targets = GetTargets(e, unit);
798  if (!targets)
799  break;
800 
801  for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr)
802  {
803  if (!IsUnit(*itr))
804  continue;
805 
806  if (e.action.removeAura.spell)
807  (*itr)->ToUnit()->RemoveAurasDueToSpell(e.action.removeAura.spell);
808  else
809  (*itr)->ToUnit()->RemoveAllAuras();
810 
811  sLog.outDebug("SmartScript::ProcessAction: SMART_ACTION_REMOVEAURASFROMSPELL: Unit %u, spell %u",
812  (*itr)->GetGUIDLow(), e.action.removeAura.spell);
813  }
814 
815  delete targets;
816  break;
817  }
818  case SMART_ACTION_FOLLOW:
819  {
820  if (!IsSmart())
821  break;
822 
823  ObjectList* targets = GetTargets(e, unit);
824  if (!targets)
825  {
826  CAST_AI(SmartAI, me->AI())->StopFollow();
827  break;
828  }
829 
830  for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr)
831  {
832  if (IsUnit(*itr))
833  {
834  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);
835  sLog.outDebug("SmartScript::ProcessAction: SMART_ACTION_FOLLOW: Creature %u following target %u",
836  me->GetGUIDLow(), (*itr)->GetGUIDLow());
837  break;
838  }
839  }
840 
841  delete targets;
842  break;
843  }
845  {
846  if (!GetBaseObject())
847  break;
848 
850  phases[0] = e.action.randomPhase.phase1;
851  phases[1] = e.action.randomPhase.phase2;
852  phases[2] = e.action.randomPhase.phase3;
853  phases[3] = e.action.randomPhase.phase4;
854  phases[4] = e.action.randomPhase.phase5;
855  phases[5] = e.action.randomPhase.phase6;
857  uint32 count = 0;
858  for (uint8 i = 0; i < SMART_ACTION_PARAM_COUNT; i++)
859  {
860  if (phases[i] > 0)
861  {
862  temp[count] = phases[i];
863  ++count;
864  }
865  }
866 
867  if (count == 0)
868  break;
869 
870  uint32 phase = temp[urand(0, count - 1)];
871  SetPhase(phase);
872  sLog.outDebug("SmartScript::ProcessAction: SMART_ACTION_RANDOM_PHASE: Creature %u sets event phase to %u",
873  GetBaseObject()->GetGUIDLow(), phase);
874  break;
875  }
877  {
878  if (!GetBaseObject())
879  break;
880 
881  uint32 phase = urand(e.action.randomPhaseRange.phaseMin, e.action.randomPhaseRange.phaseMax);
882  SetPhase(phase);
883  sLog.outDebug("SmartScript::ProcessAction: SMART_ACTION_RANDOM_PHASE_RANGE: Creature %u sets event phase to %u",
884  GetBaseObject()->GetGUIDLow(), phase);
885  break;
886  }
888  {
889  if (e.target.type == SMART_TARGET_NONE || e.target.type == SMART_TARGET_SELF) // Loot recipient and his group members
890  {
891  if (!me)
892  break;
893 
894  if (Player* player = me->GetLootRecipient())
895  {
896  player->RewardPlayerAndGroupAtEvent(e.action.killedMonster.creature, player);
897  sLog.outDebug("SmartScript::ProcessAction: SMART_ACTION_CALL_KILLEDMONSTER: Player %u, Killcredit: %u",
898  player->GetGUIDLow(), e.action.killedMonster.creature);
899  }
900  }
901  else // Specific target type
902  {
903  ObjectList* targets = GetTargets(e, unit);
904  if (!targets)
905  break;
906 
907  for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr)
908  {
909  if (IsPlayer(*itr))
910  {
911  (*itr)->ToPlayer()->KilledMonsterCredit(e.action.killedMonster.creature);
912  sLog.outDebug("SmartScript::ProcessAction: SMART_ACTION_CALL_KILLEDMONSTER: Player %u, Killcredit: %u",
913  (*itr)->GetGUIDLow(), e.action.killedMonster.creature);
914  }
915  }
916 
917  delete targets;
918  }
919  break;
920  }
922  {
923  WorldObject* obj = GetBaseObject();
924  if (!obj)
925  obj = unit;
926 
927  if (!obj)
928  break;
929 
930  InstanceData* instance = obj->GetInstanceData();
931  if (!instance)
932  {
933  sLog.outError("SmartScript: Event %u attempt to set instance data without instance script. EntryOrGuid %d", e.GetEventType(), e.entryOrGuid);
934  break;
935  }
936 
937  instance->SetData(e.action.setInstanceData.field, e.action.setInstanceData.data);
938  sLog.outDebug("SmartScript::ProcessAction: SMART_ACTION_SET_INST_DATA: Field: %u, data: %u",
939  e.action.setInstanceData.field, e.action.setInstanceData.data);
940  break;
941  }
943  {
944  WorldObject* obj = GetBaseObject();
945  if (!obj)
946  obj = unit;
947 
948  if (!obj)
949  break;
950 
951  InstanceData* instance = obj->GetInstanceData();
952  if (!instance)
953  {
954  sLog.outError("SmartScript: Event %u attempt to set instance data without instance script. EntryOrGuid %d", e.GetEventType(), e.entryOrGuid);
955  break;
956  }
957 
958  ObjectList* targets = GetTargets(e, unit);
959  if (!targets)
960  break;
961 
962  instance->SetData64(e.action.setInstanceData64.field, targets->front()->GetGUID());
963  sLog.outDebug("SmartScript::ProcessAction: SMART_ACTION_SET_INST_DATA64: Field: %u, data: %s",
964  e.action.setInstanceData64.field, targets->front()->GetObjectGUID().GetString().c_str());
965 
966  delete targets;
967  break;
968  }
970  {
971  ObjectList* targets = GetTargets(e, unit);
972 
973  if (!targets)
974  break;
975 
976  for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr)
977  if (IsCreature(*itr))
978  (*itr)->ToCreature()->UpdateEntry(e.action.updateTemplate.creature);
979 
980  delete targets;
981  break;
982  }
983  case SMART_ACTION_DIE:
984  {
985  if (me && !me->isDead())
986  {
987  me->Kill(me);
988  sLog.outDebug("SmartScript::ProcessAction: SMART_ACTION_DIE: Creature %u", me->GetGUIDLow());
989  }
990  break;
991  }
993  {
994  if (me)
995  {
996  me->SetInCombatWithZone();
997  sLog.outDebug("SmartScript::ProcessAction: SMART_ACTION_SET_IN_COMBAT_WITH_ZONE: Creature %u", me->GetGUIDLow());
998  }
999  break;
1000  }
1002  {
1003  if (me)
1004  {
1005  me->CallForHelp((float)e.action.callHelp.range);
1006  if (e.action.callHelp.withEmote)
1007  {
1009  sCreatureTextMgr->SendChatPacket(me, builder, CHAT_MSG_MONSTER_EMOTE);
1010  }
1011  sLog.outDebug("SmartScript::ProcessAction: SMART_ACTION_CALL_FOR_HELP: Creature %u", me->GetGUIDLow());
1012  }
1013  break;
1014  }
1016  {
1017  if (me)
1018  {
1019  me->SetSheath(SheathState(e.action.setSheath.sheath));
1020  sLog.outDebug("SmartScript::ProcessAction: SMART_ACTION_SET_SHEATH: Creature %u, State: %u",
1021  me->GetGUIDLow(), e.action.setSheath.sheath);
1022  }
1023  break;
1024  }
1026  {
1027  ObjectList* targets = GetTargets(e, unit);
1028 
1029  if (!targets)
1030  break;
1031 
1032  // there should be at least a world update tick before despawn, to avoid breaking linked actions
1033  int32 const respawnDelay = std::max<int32>(e.action.forceDespawn.delay, 1);
1034 
1035  for (WorldObject* target : *targets)
1036  {
1037  if (Creature* creatureTarget = target->ToCreature())
1038  {
1039  if (SmartAI* smartAI = CAST_AI(SmartAI, creatureTarget->AI()))
1040  {
1041  smartAI->SetDespawnTime(respawnDelay);
1042  smartAI->StartDespawn();
1043  }
1044  else
1045  creatureTarget->DespawnOrUnsummon(respawnDelay);
1046  }
1047  else if (GameObject* goTarget = target->ToGameObject())
1048  goTarget->SetRespawnTime(respawnDelay);
1049  }
1050 
1051  delete targets;
1052  break;
1053  }
1055  {
1056  // No phasing on tbc
1057  break;
1058  }
1060  {
1061  ObjectList* targets = GetTargets(e, unit);
1062  if (!targets)
1063  break;
1064 
1065  for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr)
1066  {
1067  if (!IsUnit(*itr))
1068  continue;
1069 
1070  if (e.action.morphOrMount.creature || e.action.morphOrMount.model)
1071  {
1072  if (e.action.morphOrMount.creature > 0)
1073  {
1074  if (CreatureInfo const* cInfo = sObjectMgr.GetCreatureTemplate(e.action.morphOrMount.creature))
1075  (*itr)->ToUnit()->Mount(cInfo->GetRandomValidModelId());
1076  }
1077  else
1078  (*itr)->ToUnit()->Mount(e.action.morphOrMount.model);
1079  }
1080  else
1081  (*itr)->ToUnit()->Dismount();
1082  }
1083 
1084  delete targets;
1085  break;
1086  }
1088  {
1089  if (!me)
1090  break;
1091 
1092  SmartAI* ai = CAST_AI(SmartAI, me->AI());
1093 
1094  if (!ai)
1095  break;
1096 
1097  if (e.action.invincHP.percent)
1098  ai->SetInvincibilityHpLevel(me->CountPctFromMaxHealth(e.action.invincHP.percent));
1099  else
1101 
1102  break;
1103  }
1104  case SMART_ACTION_SET_DATA:
1105  {
1106  ObjectList* targets = GetTargets(e, unit);
1107  if (!targets)
1108  break;
1109 
1110  for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr)
1111  {
1112  if (IsCreature(*itr))
1113  (*itr)->ToCreature()->AI()->SetData(e.action.setData.field, e.action.setData.data);
1114  else if (IsGameObject(*itr))
1115  (*itr)->ToGameObject()->AI()->SetData(e.action.setData.field, e.action.setData.data);
1116  }
1117 
1118  delete targets;
1119  break;
1120  }
1122  {
1123  if (!me)
1124  break;
1125 
1126  float x, y, z;
1127  me->GetClosePoint(x, y, z, me->GetObjectSize() / 3, (float)e.action.moveRandom.distance);
1128  me->GetMotionMaster()->MovePoint(SMART_RANDOM_POINT, x, y, z);
1129  break;
1130  }
1132  {
1133  ObjectList* targets = GetTargets(e, unit);
1134  if (!targets)
1135  break;
1136 
1137  for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr)
1138  {
1139  if (!IsCreature(*itr))
1140  continue;
1141 
1142  Position pos = (*itr)->GetPosition();
1143 
1144  // Use forward/backward/left/right cartesian plane movement
1145  float x, y, z, o;
1146  o = pos.GetOrientation();
1147  x = pos.GetPositionX() + (std::cos(o - (M_PI / 2))*e.target.x) + (std::cos(o)*e.target.y);
1148  y = pos.GetPositionY() + (std::sin(o - (M_PI / 2))*e.target.x) + (std::sin(o)*e.target.y);
1149  z = pos.GetPositionZ() + e.target.z;
1150  (*itr)->ToCreature()->GetMotionMaster()->MovePoint(SMART_RANDOM_POINT, x, y, z);
1151  }
1152  break;
1153  }
1155  {
1156  if (me)
1157  me->SetVisible(e.action.visibility.state ? true : false);
1158  break;
1159  }
1161  {
1162  if (WorldObject* baseObj = GetBaseObject())
1163  baseObj->setActive(e.action.active.state != 0);
1164 
1165  break;
1166  }
1168  {
1169  if (!me)
1170  break;
1171 
1172  ObjectList* targets = GetTargets(e, unit);
1173  if (!targets)
1174  break;
1175 
1176  for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr)
1177  {
1178  if (IsUnit(*itr))
1179  {
1180  me->AI()->AttackStart((*itr)->ToUnit());
1181  break;
1182  }
1183  }
1184 
1185  delete targets;
1186  break;
1187  }
1189  {
1190  ObjectList* targets = GetTargets(e, unit);
1191  if (targets)
1192  {
1193  float x, y, z, o;
1194  for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr)
1195  {
1196  (*itr)->GetPosition(x, y, z, o);
1197  x += e.target.x;
1198  y += e.target.y;
1199  z += e.target.z;
1200  o += e.target.o;
1201  if (Creature* summon = GetBaseObject()->SummonCreature(e.action.summonCreature.creature, x, y, z, o, (TempSummonType)e.action.summonCreature.type, e.action.summonCreature.duration))
1202  if (e.action.summonCreature.attackInvoker)
1203  summon->AI()->AttackStart((*itr)->ToUnit());
1204  }
1205 
1206  delete targets;
1207  }
1208 
1210  break;
1211 
1212  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))
1213  if (unit && e.action.summonCreature.attackInvoker)
1214  summon->AI()->AttackStart(unit);
1215  break;
1216  }
1218  {
1219  if (!GetBaseObject())
1220  break;
1221 
1222  ObjectList* targets = GetTargets(e, unit);
1223  if (targets)
1224  {
1225  float x, y, z, o;
1226  for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr)
1227  {
1228  if (!IsUnit(*itr))
1229  continue;
1230 
1231  (*itr)->GetPosition(x, y, z, o);
1232  x += e.target.x;
1233  y += e.target.y;
1234  z += e.target.z;
1235  o += e.target.o;
1236  GetBaseObject()->SummonGameObject(e.action.summonGO.entry, x, y, z, o, 0, 0, 0, 0, e.action.summonGO.despawnTime);
1237  }
1238 
1239  delete targets;
1240  }
1241 
1243  break;
1244 
1245  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);
1246  break;
1247  }
1249  {
1250  ObjectList* targets = GetTargets(e, unit);
1251  if (!targets)
1252  break;
1253 
1254  for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr)
1255  {
1256  if (!IsUnit(*itr))
1257  continue;
1258 
1259  (*itr)->ToUnit()->Kill((*itr)->ToUnit());
1260  }
1261 
1262  delete targets;
1263  break;
1264  }
1266  {
1267  InstallTemplate(e);
1268  break;
1269  }
1270  case SMART_ACTION_ADD_ITEM:
1271  {
1272  ObjectList* targets = GetTargets(e, unit);
1273  if (!targets)
1274  break;
1275 
1276  for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr)
1277  {
1278  if (!IsPlayer(*itr))
1279  continue;
1280 
1281  (*itr)->ToPlayer()->AddItem(e.action.item.entry, e.action.item.count);
1282  }
1283 
1284  delete targets;
1285  break;
1286  }
1288  {
1289  ObjectList* targets = GetTargets(e, unit);
1290  if (!targets)
1291  break;
1292 
1293  for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr)
1294  {
1295  if (!IsPlayer(*itr))
1296  continue;
1297 
1298  (*itr)->ToPlayer()->DestroyItemCount(e.action.item.entry, e.action.item.count, true);
1299  }
1300 
1301  delete targets;
1302  break;
1303  }
1305  {
1306  ObjectList* targets = GetTargets(e, unit);
1307  StoreTargetList(targets, e.action.storeTargets.id);
1308  break;
1309  }
1310  case SMART_ACTION_TELEPORT:
1311  {
1312  ObjectList* targets = GetTargets(e, unit);
1313  if (!targets)
1314  break;
1315 
1316  for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr)
1317  {
1318  if (IsPlayer(*itr))
1319  (*itr)->ToPlayer()->TeleportTo(e.action.teleport.mapID, e.target.x, e.target.y, e.target.z, e.target.o);
1320  else if (IsCreature(*itr))
1321  (*itr)->ToCreature()->NearTeleportTo(e.target.x, e.target.y, e.target.z, e.target.o);
1322  }
1323 
1324  delete targets;
1325  break;
1326  }
1327  case SMART_ACTION_SET_FLY:
1328  {
1329  if (!IsSmart())
1330  break;
1331 
1332  CAST_AI(SmartAI, me->AI())->SetFly(e.action.setFly.fly != 0);
1333  break;
1334  }
1335  case SMART_ACTION_SET_RUN:
1336  {
1337  if (!IsSmart())
1338  break;
1339 
1340  CAST_AI(SmartAI, me->AI())->SetRun(e.action.setRun.run != 0);
1341  break;
1342  }
1343  case SMART_ACTION_SET_SWIM:
1344  {
1345  if (!IsSmart())
1346  break;
1347 
1348  CAST_AI(SmartAI, me->AI())->SetSwim(e.action.setSwim.swim != 0);
1349  break;
1350  }
1352  {
1353  if (ObjectList* targets = GetTargets(e, unit))
1354  {
1355  for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr)
1356  {
1357  if (IsCreature(*itr))
1358  {
1359  if (SmartAI* ai = CAST_AI(SmartAI, (*itr)->ToCreature()->AI()))
1360  ai->GetScript()->StoreCounter(e.action.setCounter.counterId, e.action.setCounter.value, e.action.setCounter.reset);
1361  else
1362  sLog.outError("SmartScript: Action target for SMART_ACTION_SET_COUNTER is not using SmartAI, skipping");
1363  }
1364  else if (IsGameObject(*itr))
1365  {
1366  if (SmartGameObjectAI* ai = CAST_AI(SmartGameObjectAI, (*itr)->ToGameObject()->AI()))
1367  ai->GetScript()->StoreCounter(e.action.setCounter.counterId, e.action.setCounter.value, e.action.setCounter.reset);
1368  else
1369  sLog.outError("SmartScript: Action target for SMART_ACTION_SET_COUNTER is not using SmartGameObjectAI, skipping");
1370  }
1371  }
1372 
1373  delete targets;
1374  }
1375  else
1376  StoreCounter(e.action.setCounter.counterId, e.action.setCounter.value, e.action.setCounter.reset);
1377 
1378  break;
1379  }
1380  case SMART_ACTION_WP_START:
1381  {
1382  if (!IsSmart())
1383  break;
1384 
1385  bool run = e.action.wpStart.run != 0;
1386  uint32 entry = e.action.wpStart.pathID;
1387  bool repeat = e.action.wpStart.repeat != 0;
1388  ObjectList* targets = GetTargets(e, unit);
1389  StoreTargetList(targets, SMART_ESCORT_TARGETS);
1390  me->SetReactState((ReactStates)e.action.wpStart.reactState);
1391  CAST_AI(SmartAI, me->AI())->StartPath(run, entry, repeat, unit);
1392 
1393  uint32 quest = e.action.wpStart.quest;
1394  uint32 DespawnTime = e.action.wpStart.despawnTime;
1395  CAST_AI(SmartAI, me->AI())->mEscortQuestID = quest;
1396  CAST_AI(SmartAI, me->AI())->SetDespawnTime(DespawnTime);
1397  break;
1398  }
1399  case SMART_ACTION_WP_PAUSE:
1400  {
1401  if (!IsSmart())
1402  break;
1403 
1404  uint32 delay = e.action.wpPause.delay;
1405  CAST_AI(SmartAI, me->AI())->PausePath(delay, e.GetEventType() == SMART_EVENT_WAYPOINT_REACHED ? false : true);
1406  break;
1407  }
1408  case SMART_ACTION_WP_STOP:
1409  {
1410  if (!IsSmart())
1411  break;
1412 
1413  uint32 DespawnTime = e.action.wpStop.despawnTime;
1414  uint32 quest = e.action.wpStop.quest;
1415  bool fail = e.action.wpStop.fail != 0;
1416  CAST_AI(SmartAI, me->AI())->StopPath(DespawnTime, quest, fail);
1417  break;
1418  }
1420  {
1421  if (!IsSmart())
1422  break;
1423 
1424  CAST_AI(SmartAI, me->AI())->ResumePath();
1425  break;
1426  }
1428  {
1429  if (!me)
1430  break;
1431 
1432  if (e.GetTargetType() == SMART_TARGET_SELF)
1433  me->SetFacingTo(me->GetHomePosition().GetOrientation());
1434  else if (e.GetTargetType() == SMART_TARGET_POSITION)
1435  me->SetFacingTo(e.target.o);
1436  else if (ObjectList* targets = GetTargets(e, unit))
1437  {
1438  if (!targets->empty())
1439  me->SetFacingToObject(*targets->begin());
1440 
1441  delete targets;
1442  }
1443 
1444  break;
1445  }
1447  {
1448  // no exist in tbc
1449  break;
1450  }
1452  {
1453  if (!IsSmart())
1454  break;
1455 
1456  WorldObject* target = NULL;
1457 
1464  {
1465  ObjectList* targets = GetTargets(e, unit);
1466  if (!targets)
1467  break;
1468 
1469  target = targets->front();
1470  delete targets;
1471  }
1472 
1473  if (!target)
1474  {
1475  G3D::Vector3 dest(e.target.x, e.target.y, e.target.z);
1476  me->GetMotionMaster()->MovePoint(e.action.MoveToPos.pointId, dest.x, dest.y, dest.z);
1477  }
1478  else
1479  me->GetMotionMaster()->MovePoint(e.action.MoveToPos.pointId, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ());
1480  break;
1481  }
1483  {
1484  ObjectList* targets = GetTargets(e, unit);
1485  if (!targets)
1486  break;
1487 
1488  for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr)
1489  {
1490  if (IsCreature(*itr))
1491  (*itr)->ToCreature()->Respawn();
1492  else if (IsGameObject(*itr))
1493  (*itr)->ToGameObject()->SetRespawnTime(e.action.RespawnTarget.goRespawnTime);
1494  }
1495 
1496  delete targets;
1497  break;
1498  }
1500  {
1501  ObjectList* targets = GetTargets(e, unit);
1502  if (!targets)
1503  break;
1504 
1505  for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr)
1506  if (IsPlayer(*itr))
1507  (*itr)->ToPlayer()->PlayerTalkClass->SendCloseGossip();
1508 
1509  delete targets;
1510  break;
1511  }
1512  case SMART_ACTION_EQUIP:
1513  {
1514  ObjectList* targets = GetTargets(e, unit);
1515  if (!targets)
1516  break;
1517 
1518  for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr)
1519  {
1520  if (Creature* npc = (*itr)->ToCreature())
1521  {
1522  uint32 slot[3];
1523  uint32 equipId = e.action.equip.entry;
1524  if (equipId)
1525  {
1526  EquipmentInfo const* einfo = sObjectMgr.GetEquipmentInfo(equipId);
1527  if (!einfo)
1528  {
1529  sLog.outError("SmartScript: SMART_ACTION_EQUIP uses non-existent equipment info id %u for creature %u", equipId, npc->GetEntry());
1530  break;
1531  }
1532 
1533  npc->SetCurrentEquipmentId(equipId);
1534  slot[0] = einfo->equipentry[0];
1535  slot[1] = einfo->equipentry[1];
1536  slot[2] = einfo->equipentry[2];
1537 
1538  for (uint8 i = 0; i < MAX_VIRTUAL_ITEM_SLOT; ++i)
1539  npc->SetVirtualItem(VirtualItemSlot(i), einfo->equipentry[i]);
1540 
1541  }
1542  else
1543  {
1544  slot[0] = e.action.equip.slot1;
1545  slot[1] = e.action.equip.slot2;
1546  slot[2] = e.action.equip.slot3;
1547 
1548  for (uint8 i = 0; i < MAX_VIRTUAL_ITEM_SLOT; ++i)
1549  npc->SetVirtualItem(VirtualItemSlot(i), slot[i]);
1550  }
1551  }
1552  }
1553 
1554  delete targets;
1555  break;
1556  }
1558  {
1559  SmartEvent ne = SmartEvent();
1561  ne.event_chance = e.action.timeEvent.chance;
1562  if (!ne.event_chance) ne.event_chance = 100;
1563 
1564  ne.minMaxRepeat.min = e.action.timeEvent.min;
1565  ne.minMaxRepeat.max = e.action.timeEvent.max;
1566  ne.minMaxRepeat.repeatMin = e.action.timeEvent.repeatMin;
1567  ne.minMaxRepeat.repeatMax = e.action.timeEvent.repeatMax;
1568 
1569  ne.event_flags = 0;
1570  if (!ne.minMaxRepeat.repeatMin && !ne.minMaxRepeat.repeatMax)
1572 
1573  SmartAction ac = SmartAction();
1575  ac.timeEvent.id = e.action.timeEvent.id;
1576 
1578  ev.event = ne;
1579  ev.event_id = e.action.timeEvent.id;
1580  ev.target = e.target;
1581  ev.action = ac;
1582  InitTimer(ev);
1583  mStoredEvents.push_back(ev);
1584  break;
1585  }
1587  ProcessEventsFor((SMART_EVENT)SMART_EVENT_TIMED_EVENT_TRIGGERED, NULL, e.action.timeEvent.id);
1588  break;
1590  mRemIDs.push_back(e.action.timeEvent.id);
1591  break;
1593  {
1594  ObjectList* targets = GetTargets(e, unit);
1595  if (!targets)
1596  break;
1597 
1598  for (ObjectList::iterator itr = targets->begin(); itr != targets->end(); ++itr)
1599  {
1600  if (IsCreature(*itr))
1601  {
1602  if (!meOrigGUID && me)
1603  meOrigGUID = me->GetGUID();
1604  if (!goOrigGUID && go)
1605  goOrigGUID = go->GetGUID();
1606  go = NULL;
1607  me = (*itr)->ToCreature();
1608  break;
1609  }
1610  else if (IsGameObject(*itr))
1611  {
1612  if (!meOrigGUID && me)
1613  meOrigGUID = me->GetGUID();
1614  if (!goOrigGUID && go)
1615  goOrigGUID = go->GetGUID();
1616  go = (*itr)->ToGameObject();
1617  me = NULL;
1618  break;
1619  }
1620  }
1621 
1622  delete targets;
1623  break;
1624  }
1626  ResetBaseObject();
1627  break;
1629  SetPhase(0);
1630  OnReset();
1631  break;
1633  {
1634  if (!IsSmart())
1635  break;
1636 
1637  float attackDistance = float(e.action.setRangedMovement.distance);
1638  float attackAngle = float(e.action.setRangedMovement.angle) / 180.0f * float(M_PI);
1639 
1640  ObjectList* targets = GetTargets(e, unit);
1641  if (targets)
1642  {
1643  for (ObjectList::iterator itr = targets->begin(); itr != targets->end(); ++itr)
1644  if (Creature* target = (*itr)->ToCreature())
1645  if (IsSmart(target) && target->GetVictim())
1646  if (CAST_AI(SmartAI, target->AI())->CanCombatMove())
1647  target->GetMotionMaster()->MoveChase(target->GetVictim(), attackDistance, attackAngle);
1648 
1649  delete targets;
1650  }
1651  break;
1652  }
1654  {
1655  if (e.GetTargetType() == SMART_TARGET_NONE)
1656  {
1657  sLog.outError("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());
1658  break;
1659  }
1660 
1661  if (ObjectList* targets = GetTargets(e, unit))
1662  {
1663  for (ObjectList::iterator itr = targets->begin(); itr != targets->end(); ++itr)
1664  {
1665  if (Creature* target = (*itr)->ToCreature())
1666  {
1667  if (IsSmart(target))
1668  CAST_AI(SmartAI, target->AI())->SetScript9(e, e.action.timedActionList.id, GetLastInvoker());
1669  }
1670  else if (GameObject* goTarget = (*itr)->ToGameObject())
1671  {
1672  if (IsSmartGO(goTarget))
1673  CAST_AI(SmartGameObjectAI, goTarget->AI())->SetScript9(e, e.action.timedActionList.id, GetLastInvoker());
1674  }
1675  }
1676 
1677  delete targets;
1678  }
1679  break;
1680  }
1682  {
1683  ObjectList* targets = GetTargets(e, unit);
1684  if (!targets)
1685  break;
1686 
1687  for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr)
1688  if (IsCreature(*itr))
1689  (*itr)->ToUnit()->SetUInt32Value(UNIT_NPC_FLAGS, e.action.unitFlag.flag);
1690 
1691  delete targets;
1692  break;
1693  }
1695  {
1696  ObjectList* targets = GetTargets(e, unit);
1697  if (!targets)
1698  break;
1699 
1700  for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr)
1701  if (IsCreature(*itr))
1702  (*itr)->ToUnit()->SetFlag(UNIT_NPC_FLAGS, e.action.unitFlag.flag);
1703 
1704  delete targets;
1705  break;
1706  }
1708  {
1709  ObjectList* targets = GetTargets(e, unit);
1710  if (!targets)
1711  break;
1712 
1713  for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr)
1714  if (IsCreature(*itr))
1715  (*itr)->ToUnit()->RemoveFlag(UNIT_NPC_FLAGS, e.action.unitFlag.flag);
1716 
1717  delete targets;
1718  break;
1719  }
1721  {
1722  ObjectList* casters = GetTargets(CreateEvent(SMART_EVENT_UPDATE_IC, 0, 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);
1723  if (!casters)
1724  break;
1725 
1726  ObjectList* targets = GetTargets(e, unit);
1727  if (!targets)
1728  {
1729  delete casters; // casters already validated, delete now
1730  break;
1731  }
1732 
1733  for (ObjectList::const_iterator itr = casters->begin(); itr != casters->end(); ++itr)
1734  {
1735  if (!IsUnit(*itr))
1736  continue;
1737 
1738  Unit* targetUnit = (*itr)->ToUnit();
1739 
1740  bool interruptedSpell = false;
1741 
1742  for (ObjectList::const_iterator it = targets->begin(); it != targets->end(); ++it)
1743  {
1744  if (!IsUnit(*it))
1745  continue;
1746 
1747  if (!(e.action.cast.flags & SMARTCAST_AURA_NOT_PRESENT) || !(*it)->ToUnit()->HasAura(e.action.cast.spell))
1748  {
1749  if (!interruptedSpell && e.action.cast.flags & SMARTCAST_INTERRUPT_PREVIOUS)
1750  {
1751  targetUnit->InterruptNonMeleeSpells(false);
1752  interruptedSpell = true;
1753  }
1754 
1755  targetUnit->CastSpell((*it)->ToUnit(), e.action.cast.spell, (e.action.cast.flags & SMARTCAST_TRIGGERED) != 0);
1756  }
1757  else
1758  sLog.outDebug("Spell %u not cast because it has flag SMARTCAST_AURA_NOT_PRESENT and the target (%s) already has the aura", e.action.cast.spell, (*it)->GetObjectGUID().GetString().c_str());
1759  }
1760  }
1761 
1762  delete targets;
1763  delete casters;
1764  break;
1765  }
1767  {
1769  actions[0] = e.action.randTimedActionList.entry1;
1770  actions[1] = e.action.randTimedActionList.entry2;
1771  actions[2] = e.action.randTimedActionList.entry3;
1772  actions[3] = e.action.randTimedActionList.entry4;
1773  actions[4] = e.action.randTimedActionList.entry5;
1774  actions[5] = e.action.randTimedActionList.entry6;
1776  uint32 count = 0;
1777  for (uint8 i = 0; i < SMART_ACTION_PARAM_COUNT; i++)
1778  {
1779  if (actions[i] > 0)
1780  {
1781  temp[count] = actions[i];
1782  ++count;
1783  }
1784  }
1785 
1786  if (count == 0)
1787  break;
1788 
1789  uint32 id = temp[urand(0, count - 1)];
1790  if (e.GetTargetType() == SMART_TARGET_NONE)
1791  {
1792  sLog.outError("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());
1793  break;
1794  }
1795 
1796  ObjectList* targets = GetTargets(e, unit);
1797  if (targets)
1798  {
1799  for (ObjectList::iterator itr = targets->begin(); itr != targets->end(); ++itr)
1800  {
1801  if (Creature* target = (*itr)->ToCreature())
1802  {
1803  if (IsSmart(target))
1804  CAST_AI(SmartAI, target->AI())->SetScript9(e, id, GetLastInvoker());
1805  }
1806  else if (GameObject* goTarget = (*itr)->ToGameObject())
1807  {
1808  if (IsSmartGO(goTarget))
1809  CAST_AI(SmartGameObjectAI, goTarget->AI())->SetScript9(e, id, GetLastInvoker());
1810  }
1811  }
1812 
1813  delete targets;
1814  }
1815  break;
1816  }
1818  {
1820  if (e.GetTargetType() == SMART_TARGET_NONE)
1821  {
1822  sLog.outError("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());
1823  break;
1824  }
1825 
1826  ObjectList* targets = GetTargets(e, unit);
1827  if (targets)
1828  {
1829  for (ObjectList::iterator itr = targets->begin(); itr != targets->end(); ++itr)
1830  {
1831  if (Creature* target = (*itr)->ToCreature())
1832  {
1833  if (IsSmart(target))
1834  CAST_AI(SmartAI, target->AI())->SetScript9(e, id, GetLastInvoker());
1835  }
1836  else if (GameObject* goTarget = (*itr)->ToGameObject())
1837  {
1838  if (IsSmartGO(goTarget))
1839  CAST_AI(SmartGameObjectAI, goTarget->AI())->SetScript9(e, id, GetLastInvoker());
1840  }
1841  }
1842 
1843  delete targets;
1844  }
1845  break;
1846  }
1848  {
1849  ObjectList* targets = GetTargets(e, unit);
1850  if (!targets)
1851  break;
1852 
1853  for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr)
1854  if (IsPlayer(*itr))
1855  (*itr)->ToPlayer()->ActivateTaxiPathTo(e.action.taxi.id);
1856 
1857  delete targets;
1858  break;
1859  }
1861  {
1862  ObjectList* targets = GetTargets(e, unit);
1863  if (!targets)
1864  break;
1865 
1866  bool foundTarget = false;
1867 
1868  for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr)
1869  {
1870  if (IsCreature((*itr)))
1871  {
1872  foundTarget = true;
1873 
1874  if (e.action.moveRandom.distance)
1875  (*itr)->ToCreature()->GetMotionMaster()->MoveRandom((float)e.action.moveRandom.distance);
1876  else
1877  (*itr)->ToCreature()->GetMotionMaster()->MoveIdle();
1878  }
1879  }
1880 
1881  if (!foundTarget && me && IsCreature(me))
1882  {
1883  if (e.action.moveRandom.distance)
1884  me->GetMotionMaster()->MoveRandom((float)e.action.moveRandom.distance);
1885  else
1886  me->GetMotionMaster()->MoveIdle();
1887  }
1888 
1889  delete targets;
1890  break;
1891  }
1893  {
1894  ObjectList* targets = GetTargets(e, unit);
1895  if (!targets)
1896  break;
1897  for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr)
1898  if (IsUnit(*itr))
1899  (*itr)->ToUnit()->SetByteFlag(UNIT_FIELD_BYTES_1, e.action.setunitByte.type, e.action.setunitByte.byte1);
1900 
1901  delete targets;
1902  break;
1903  }
1905  {
1906  ObjectList* targets = GetTargets(e, unit);
1907  if (!targets)
1908  break;
1909 
1910  for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr)
1911  if (IsUnit(*itr))
1912  (*itr)->ToUnit()->RemoveByteFlag(UNIT_FIELD_BYTES_1, e.action.delunitByte.type, e.action.delunitByte.byte1);
1913 
1914  delete targets;
1915  break;
1916  }
1918  {
1919  ObjectList* targets = GetTargets(e, unit);
1920  if (!targets)
1921  break;
1922 
1923  for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr)
1924  if (IsUnit(*itr))
1925  (*itr)->ToUnit()->InterruptNonMeleeSpells(e.action.interruptSpellCasting.withDelayed != 0, e.action.interruptSpellCasting.spell_id, e.action.interruptSpellCasting.withInstant != 0);
1926 
1927  delete targets;
1928  break;
1929  }
1931  {
1932  ObjectList* targets = GetTargets(e, unit);
1933  if (!targets)
1934  break;
1935 
1936  for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr)
1937  if (IsGameObject(*itr))
1938  (*itr)->ToGameObject()->SendObjectCustomAnim((*itr)->ToGameObject()->GetGUID(), e.action.sendGoCustomAnim.anim);
1939 
1940  delete targets;
1941  break;
1942  }
1944  {
1945  ObjectList* targets = GetTargets(e, unit);
1946  if (!targets)
1947  break;
1948 
1949  for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr)
1950  if (IsUnit(*itr))
1951  (*itr)->ToUnit()->SetUInt32Value(UNIT_DYNAMIC_FLAGS, e.action.unitFlag.flag);
1952 
1953  delete targets;
1954  break;
1955  }
1957  {
1958  ObjectList* targets = GetTargets(e, unit);
1959  if (!targets)
1960  break;
1961 
1962  for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr)
1963  if (IsUnit(*itr))
1964  (*itr)->ToUnit()->SetFlag(UNIT_DYNAMIC_FLAGS, e.action.unitFlag.flag);
1965 
1966  delete targets;
1967  break;
1968  }
1970  {
1971  ObjectList* targets = GetTargets(e, unit);
1972  if (!targets)
1973  break;
1974 
1975  for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr)
1976  if (IsUnit(*itr))
1977  (*itr)->ToUnit()->RemoveFlag(UNIT_DYNAMIC_FLAGS, e.action.unitFlag.flag);
1978 
1979  delete targets;
1980  break;
1981  }
1983  {
1984  // no exist in tbc
1985 
1986  break;
1987  }
1989  {
1990  ObjectList* targets = GetTargets(e, unit);
1991 
1992  if (!targets)
1993  break;
1994 
1995  for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr)
1996  if (IsGameObject(*itr))
1997  (*itr)->ToGameObject()->SetLootState((LootState)e.action.setGoLootState.state);
1998 
1999  delete targets;
2000  break;
2001  }
2003  {
2004  ObjectList* targets = GetTargets(e, unit);
2005  if (!targets)
2006  break;
2007 
2008  ObjectList* storedTargets = GetTargetList(e.action.sendTargetToTarget.id);
2009  if (!storedTargets)
2010  {
2011  delete targets;
2012  break;
2013  }
2014 
2015  for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr)
2016  {
2017  if (IsCreature(*itr))
2018  {
2019  if (SmartAI* ai = CAST_AI(SmartAI, (*itr)->ToCreature()->AI()))
2020  ai->GetScript()->StoreTargetList(new ObjectList(*storedTargets), e.action.sendTargetToTarget.id); // store a copy of target list
2021  else
2022  sLog.outError("SmartScript: Action target for SMART_ACTION_SEND_TARGET_TO_TARGET is not using SmartAI, skipping");
2023  }
2024  else if (IsGameObject(*itr))
2025  {
2026  if (SmartGameObjectAI* ai = CAST_AI(SmartGameObjectAI, (*itr)->ToGameObject()->AI()))
2027  ai->GetScript()->StoreTargetList(new ObjectList(*storedTargets), e.action.sendTargetToTarget.id); // store a copy of target list
2028  else
2029  sLog.outError("SmartScript: Action target for SMART_ACTION_SEND_TARGET_TO_TARGET is not using SmartGameObjectAI, skipping");
2030  }
2031  }
2032 
2033  delete targets;
2034  break;
2035  }
2037  {
2038  if (!GetBaseObject())
2039  break;
2040 
2041  sLog.outDebug("SmartScript::ProcessAction:: SMART_ACTION_SEND_GOSSIP_MENU: gossipMenuId %d, gossipNpcTextId %d",
2042  e.action.sendGossipMenu.gossipMenuId, e.action.sendGossipMenu.gossipNpcTextId);
2043 
2044  ObjectList* targets = GetTargets(e, unit);
2045  if (!targets)
2046  break;
2047 
2048  for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr)
2049  {
2050  if (Player* player = (*itr)->ToPlayer())
2051  {
2052  if (e.action.sendGossipMenu.gossipMenuId)
2053  player->PrepareGossipMenu(GetBaseObject(), e.action.sendGossipMenu.gossipMenuId);
2054  else
2055  player->PlayerTalkClass->ClearMenus();
2056 
2057  player->SEND_GOSSIP_MENU(e.action.sendGossipMenu.gossipNpcTextId, GetBaseObject()->GetGUID());
2058  }
2059  }
2060 
2061  delete targets;
2062  break;
2063  }
2065  {
2066  ObjectList* targets = GetTargets(e, unit);
2067  if (!targets)
2068  break;
2069 
2070  for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr)
2071  {
2072  if (IsCreature(*itr))
2073  {
2074  if (e.GetTargetType() == SMART_TARGET_SELF)
2075  (*itr)->ToCreature()->SetHomePosition(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), me->GetOrientation());
2076  else if (e.GetTargetType() == SMART_TARGET_POSITION)
2077  (*itr)->ToCreature()->SetHomePosition(e.target.x, e.target.y, e.target.z, e.target.o);
2084  {
2085  (*itr)->ToCreature()->SetHomePosition((*itr)->GetPositionX(), (*itr)->GetPositionY(), (*itr)->GetPositionZ(), (*itr)->GetOrientation());
2086  }
2087  else
2088  sLog.outError("SmartScript: Action target for SMART_ACTION_SET_HOME_POS is invalid, skipping");
2089  }
2090  }
2091 
2092  delete targets;
2093  break;
2094  }
2096  {
2097  ObjectList* targets = GetTargets(e, unit);
2098  if (!targets)
2099  break;
2100 
2101  for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr)
2102  if (IsCreature(*itr))
2103  (*itr)->ToCreature()->setRegeneratingHealth(e.action.setHealthRegen.regenHealth != 0);
2104 
2105  delete targets;
2106  break;
2107  }
2108  case SMART_ACTION_SET_ROOT:
2109  {
2110  ObjectList* targets = GetTargets(e, unit);
2111  if (!targets)
2112  break;
2113 
2114  for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr)
2115  if (IsCreature(*itr))
2116  (*itr)->ToCreature()->SetControlled(e.action.setRoot.root != 0, UNIT_STATE_ROOT);
2117 
2118  delete targets;
2119  break;
2120  }
2122  {
2123  ObjectList* targets = GetTargets(e, unit);
2124  if (!targets)
2125  break;
2126 
2127  for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr)
2128  if (IsGameObject(*itr))
2129  (*itr)->ToGameObject()->SetUInt32Value(GAMEOBJECT_FLAGS, e.action.goFlag.flag);
2130 
2131  delete targets;
2132  break;
2133  }
2135  {
2136  ObjectList* targets = GetTargets(e, unit);
2137  if (!targets)
2138  break;
2139 
2140  for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr)
2141  if (IsGameObject(*itr))
2142  (*itr)->ToGameObject()->SetFlag(GAMEOBJECT_FLAGS, e.action.goFlag.flag);
2143 
2144  delete targets;
2145  break;
2146  }
2148  {
2149  ObjectList* targets = GetTargets(e, unit);
2150  if (!targets)
2151  break;
2152 
2153  for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr)
2154  if (IsGameObject(*itr))
2155  (*itr)->ToGameObject()->RemoveFlag(GAMEOBJECT_FLAGS, e.action.goFlag.flag);
2156 
2157  delete targets;
2158  break;
2159  }
2161  {
2162  std::list<TempSummon*> summonList;
2163  GetBaseObject()->SummonCreatureGroup(e.action.creatureGroup.group, &summonList);
2164 
2165  for (std::list<TempSummon*>::const_iterator itr = summonList.begin(); itr != summonList.end(); ++itr)
2166  if (unit && e.action.creatureGroup.attackInvoker)
2167  (*itr)->AI()->AttackStart(unit);
2168 
2169  break;
2170  }
2172  {
2173  ObjectList* targets = GetTargets(e, unit);
2174 
2175  if (targets)
2176  for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr)
2177  if (IsUnit(*itr))
2178  (*itr)->ToUnit()->SetPower(Powers(e.action.power.powerType), e.action.power.newPower);
2179 
2180  delete targets;
2181  break;
2182  }
2184  {
2185  ObjectList* targets = GetTargets(e, unit);
2186 
2187  if (targets)
2188  for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr)
2189  if (IsUnit(*itr))
2190  (*itr)->ToUnit()->SetPower(Powers(e.action.power.powerType), (*itr)->ToUnit()->GetPower(Powers(e.action.power.powerType)) + e.action.power.newPower);
2191 
2192  delete targets;
2193  break;
2194  }
2196  {
2197  ObjectList* targets = GetTargets(e, unit);
2198 
2199  if (targets)
2200  for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr)
2201  if (IsUnit(*itr))
2202  (*itr)->ToUnit()->SetPower(Powers(e.action.power.powerType), (*itr)->ToUnit()->GetPower(Powers(e.action.power.powerType)) - e.action.power.newPower);
2203 
2204  delete targets;
2205  break;
2206  }
2208  {
2209  uint32 eventId = e.action.gameEventStop.id;
2210  if (!sGameEventMgr.IsActiveEvent(eventId))
2211  {
2212  sLog.outError("SmartScript::ProcessAction: At case SMART_ACTION_GAME_EVENT_STOP, inactive event (id: %u)", eventId);
2213  break;
2214  }
2215  sGameEventMgr.StopEvent(eventId, true);
2216  break;
2217  }
2219  {
2220  uint32 eventId = e.action.gameEventStart.id;
2221  if (sGameEventMgr.IsActiveEvent(eventId))
2222  {
2223  sLog.outDebug("SmartScript::ProcessAction: At case SMART_ACTION_GAME_EVENT_START, already activated event (id: %u)", eventId);
2224  break;
2225  }
2226  sGameEventMgr.StartEvent(eventId, true);
2227  break;
2228  }
2230  {
2231  uint32 waypoints[SMART_ACTION_PARAM_COUNT];
2232  waypoints[0] = e.action.closestWaypointFromList.wp1;
2233  waypoints[1] = e.action.closestWaypointFromList.wp2;
2234  waypoints[2] = e.action.closestWaypointFromList.wp3;
2235  waypoints[3] = e.action.closestWaypointFromList.wp4;
2236  waypoints[4] = e.action.closestWaypointFromList.wp5;
2237  waypoints[5] = e.action.closestWaypointFromList.wp6;
2238  float distanceToClosest = std::numeric_limits<float>::max();
2239  WayPoint* closestWp = NULL;
2240 
2241  ObjectList* targets = GetTargets(e, unit);
2242  if (targets)
2243  {
2244  for (ObjectList::iterator itr = targets->begin(); itr != targets->end(); ++itr)
2245  {
2246  if (Creature* target = (*itr)->ToCreature())
2247  {
2248  if (IsSmart(target))
2249  {
2250  for (uint8 i = 0; i < SMART_ACTION_PARAM_COUNT; i++)
2251  {
2252  if (!waypoints[i])
2253  continue;
2254 
2255  WPPath* path = sSmartWaypointMgr->GetPath(waypoints[i]);
2256 
2257  if (!path || path->empty())
2258  continue;
2259 
2260  WPPath::const_iterator itrWp = path->find(0);
2261 
2262  if (itrWp != path->end())
2263  {
2264  if (WayPoint* wp = itrWp->second)
2265  {
2266  float distToThisPath = target->GetDistance(wp->x, wp->y, wp->z);
2267 
2268  if (distToThisPath < distanceToClosest)
2269  {
2270  distanceToClosest = distToThisPath;
2271  closestWp = wp;
2272  }
2273  }
2274  }
2275  }
2276 
2277  if (closestWp)
2278  CAST_AI(SmartAI, target->AI())->StartPath(false, closestWp->id, true);
2279  }
2280  }
2281  }
2282 
2283  delete targets;
2284  }
2285  break;
2286  }
2288  {
2289  std::vector<uint32> sounds;
2290 
2291  for (uint8 i = 0; i < SMART_ACTION_PARAM_COUNT - 1; i++)
2292  {
2293  if (e.action.randomSound.sound[i])
2294  sounds.push_back(e.action.randomSound.sound[i]);
2295  }
2296 
2297  bool onlySelf = e.action.randomSound.onlySelf != 0;
2298 
2299  ObjectList* targets = GetTargets(e, unit);
2300  if (targets)
2301  {
2302  for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr)
2303  {
2304  if (IsUnit(*itr))
2305  {
2306  uint32 sound = sounds[urand(0, sounds.size() - 1)];
2307  (*itr)->PlayDirectSound(sound, e.action.randomSound.onlySelf ? (*itr)->ToPlayer() : nullptr);
2308  //sLog.outDebug("SmartScript::ProcessAction:: SMART_ACTION_RANDOM_SOUND: target: %s (%s), sound: %u, onlyself: %u",
2309  // (*itr)->GetName().c_str(), (*itr)->GetGUID().c_str(), sound, e.action.randomSound.onlySelf);
2310  }
2311  }
2312 
2313  delete targets;
2314  break;
2315  }
2316  }
2317  default:
2318  sLog.outError("SmartScript::ProcessAction: Entry %d SourceType %u, Event %u, Unhandled Action type %u", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType());
2319  break;
2320  }
2321 
2322  if (e.link && e.link != e.event_id)
2323  {
2324  SmartScriptHolder& linked = SmartAIMgr::FindLinkedEvent(mEvents, e.link);
2325  if (linked)
2326  ProcessEvent(linked, unit, var0, var1, bvar, spell, gob);
2327  else
2328  sLog.outDebug("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);
2329  }
2330 }
2331 
2332 void SmartScript::ProcessTimedAction(SmartScriptHolder& e, uint32 const& min, uint32 const& max, Unit* unit, uint32 var0, uint32 var1, bool bvar, const SpellEntry* spell, GameObject* gob)
2333 {
2334  ConditionList const conds = sConditionMgr.GetConditionsForSmartEvent(e.entryOrGuid, e.event_id, e.source_type);
2335  ConditionSourceInfo info = ConditionSourceInfo(unit, GetBaseObject());
2336 
2337  if (sConditionMgr.IsObjectMeetToConditions(info, conds))
2338  ProcessAction(e, unit, var0, var1, bvar, spell, gob);
2339 
2340  RecalcTimer(e, min, max);
2341 }
2342 
2344 {
2345  if (!GetBaseObject())
2346  return;
2347  if (mTemplate)
2348  {
2349  sLog.outError("SmartScript::InstallTemplate: Entry %d SourceType %u AI Template can not be set more then once, skipped.", e.entryOrGuid, e.GetScriptType());
2350  return;
2351  }
2352  mTemplate = (SMARTAI_TEMPLATE)e.action.installTtemplate.id;
2354  {
2356  {
2357  AddEvent(SMART_EVENT_UPDATE_IC, 0, 0, 0, e.action.installTtemplate.param2, e.action.installTtemplate.param3, 0, SMART_ACTION_CAST, e.action.installTtemplate.param1, e.target.raw.param1, 0, 0, 0, 0, SMART_TARGET_VICTIM, 0, 0, 0, 1);
2358  AddEvent(SMART_EVENT_RANGE, 0, e.action.installTtemplate.param4, 300, 0, 0, 0, SMART_ACTION_ALLOW_COMBAT_MOVEMENT, 1, 0, 0, 0, 0, 0, SMART_TARGET_NONE, 0, 0, 0, 1);
2359  AddEvent(SMART_EVENT_RANGE, 0, 0, e.action.installTtemplate.param4>10?e.action.installTtemplate.param4-10:0, 0, 0, 0, SMART_ACTION_ALLOW_COMBAT_MOVEMENT, 0, 0, 0, 0, 0, 0, SMART_TARGET_NONE, 0, 0, 0, 1);
2360  AddEvent(SMART_EVENT_MANA_PCT, 0, e.action.installTtemplate.param5-15>100?100:e.action.installTtemplate.param5+15, 100, 1000, 1000, 0, SMART_ACTION_SET_EVENT_PHASE, 1, 0, 0, 0, 0, 0, SMART_TARGET_NONE, 0, 0, 0, 0);
2361  AddEvent(SMART_EVENT_MANA_PCT, 0, 0, e.action.installTtemplate.param5, 1000, 1000, 0, SMART_ACTION_SET_EVENT_PHASE, 0, 0, 0, 0, 0, 0, SMART_TARGET_NONE, 0, 0, 0, 0);
2362  AddEvent(SMART_EVENT_MANA_PCT, 0, 0, e.action.installTtemplate.param5, 1000, 1000, 0, SMART_ACTION_ALLOW_COMBAT_MOVEMENT, 1, 0, 0, 0, 0, 0, SMART_TARGET_NONE, 0, 0, 0, 0);
2363  break;
2364  }
2366  {
2367  AddEvent(SMART_EVENT_UPDATE_IC, 0, 0, 0, e.action.installTtemplate.param2, e.action.installTtemplate.param3, 0, SMART_ACTION_CAST, e.action.installTtemplate.param1, e.target.raw.param1, 0, 0, 0, 0, SMART_TARGET_VICTIM, 0, 0, 0, 0);
2368  AddEvent(SMART_EVENT_JUST_CREATED, 0, 0, 0, 0, 0, 0, SMART_ACTION_ALLOW_COMBAT_MOVEMENT, 0, 0, 0, 0, 0, 0, SMART_TARGET_NONE, 0, 0, 0, 0);
2369  break;
2370  }
2372  {
2373  if (!me)
2374  return;
2375  //store cage as id1
2376  AddEvent(SMART_EVENT_DATA_SET, 0, 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);
2377 
2378  //reset(close) cage on hostage(me) respawn
2380 
2381  AddEvent(SMART_EVENT_DATA_SET, 0, 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);
2382  AddEvent(SMART_EVENT_DATA_SET, 0, 0, 0, 0, 0, 0, SMART_ACTION_SET_EVENT_PHASE, 1, 0, 0, 0, 0, 0, SMART_TARGET_NONE, 0, 0, 0, 0);
2383 
2384  AddEvent(SMART_EVENT_UPDATE, SMART_EVENT_FLAG_NOT_REPEATABLE, 1000, 1000, 0, 0, 0, SMART_ACTION_MOVE_FORWARD, e.action.installTtemplate.param4, 0, 0, 0, 0, 0, SMART_TARGET_NONE, 0, 0, 0, 1);
2385  //phase 1: give quest credit on movepoint reached
2386  AddEvent(SMART_EVENT_MOVEMENTINFORM, 0, POINT_MOTION_TYPE, SMART_RANDOM_POINT, 0, 0, 0, SMART_ACTION_SET_DATA, 0, 0, 0, 0, 0, 0, SMART_TARGET_STORED, 1, 0, 0, 1);
2387  //phase 1: despawn after time on movepoint reached
2389 
2390  if (sCreatureTextMgr->TextExist(me->GetEntry(), (uint8)e.action.installTtemplate.param5))
2391  AddEvent(SMART_EVENT_MOVEMENTINFORM, 0, POINT_MOTION_TYPE, SMART_RANDOM_POINT, 0, 0, 0, SMART_ACTION_TALK, e.action.installTtemplate.param5, 0, 0, 0, 0, 0, SMART_TARGET_NONE, 0, 0, 0, 1);
2392  break;
2393  }
2395  {
2396  if (!go)
2397  return;
2398  //store hostage as id1
2399  AddEvent(SMART_EVENT_GO_STATE_CHANGED, 0, 2, 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);
2400  //store invoker as id2
2401  AddEvent(SMART_EVENT_GO_STATE_CHANGED, 0, 2, 0, 0, 0, 0, SMART_ACTION_STORE_TARGET_LIST, 2, 0, 0, 0, 0, 0, SMART_TARGET_NONE, 0, 0, 0, 0);
2402  //signal hostage
2403  AddEvent(SMART_EVENT_GO_STATE_CHANGED, 0, 2, 0, 0, 0, 0, SMART_ACTION_SET_DATA, 0, 0, 0, 0, 0, 0, SMART_TARGET_STORED, 1, 0, 0, 0);
2404  //when hostage raeched end point, give credit to invoker
2405  if (e.action.installTtemplate.param2)
2406  AddEvent(SMART_EVENT_DATA_SET, 0, 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);
2407  else
2408  AddEvent(SMART_EVENT_GO_STATE_CHANGED, 0, 2, 0, 0, 0, 0, SMART_ACTION_CALL_KILLEDMONSTER, e.action.installTtemplate.param1, 0, 0, 0, 0, 0, SMART_TARGET_STORED, 2, 0, 0, 0);
2409  break;
2410  }
2412  default:
2413  return;
2414  }
2415 }
2416 
2417 void SmartScript::AddEvent(SMART_EVENT e, uint32 event_flags, uint32 event_param1, uint32 event_param2, uint32 event_param3, uint32 event_param4, uint32 event_param5, SMART_ACTION action, uint32 action_param1, uint32 action_param2, uint32 action_param3, uint32 action_param4, uint32 action_param5, uint32 action_param6, SMARTAI_TARGETS t, uint32 target_param1, uint32 target_param2, uint32 target_param3, uint32 phaseMask)
2418 {
2419  mInstallEvents.push_back(CreateEvent(e, event_flags, event_param1, event_param2, event_param3, event_param4, event_param5, action, action_param1, action_param2, action_param3, action_param4, action_param5, action_param6, t, target_param1, target_param2, target_param3, phaseMask));
2420 }
2421 
2422 SmartScriptHolder SmartScript::CreateEvent(SMART_EVENT e, uint32 event_flags, uint32 event_param1, uint32 event_param2, uint32 event_param3, uint32 event_param4, uint32 event_param5, SMART_ACTION action, uint32 action_param1, uint32 action_param2, uint32 action_param3, uint32 action_param4, uint32 action_param5, uint32 action_param6, SMARTAI_TARGETS t, uint32 target_param1, uint32 target_param2, uint32 target_param3, uint32 phaseMask)
2423 {
2424  SmartScriptHolder script;
2425  script.event.type = e;
2426  script.event.raw.param1 = event_param1;
2427  script.event.raw.param2 = event_param2;
2428  script.event.raw.param3 = event_param3;
2429  script.event.raw.param4 = event_param4;
2430  script.event.raw.param5 = event_param5;
2431  script.event.event_phase_mask = phaseMask;
2432  script.event.event_flags = event_flags;
2433  script.event.event_chance = 100;
2434 
2435  script.action.type = action;
2436  script.action.raw.param1 = action_param1;
2437  script.action.raw.param2 = action_param2;
2438  script.action.raw.param3 = action_param3;
2439  script.action.raw.param4 = action_param4;
2440  script.action.raw.param5 = action_param5;
2441  script.action.raw.param6 = action_param6;
2442 
2443  script.target.type = t;
2444  script.target.raw.param1 = target_param1;
2445  script.target.raw.param2 = target_param2;
2446  script.target.raw.param3 = target_param3;
2447 
2449  InitTimer(script);
2450  return script;
2451 }
2452 
2454 {
2455  Unit* scriptTrigger = NULL;
2456  if (invoker)
2457  scriptTrigger = invoker;
2458  else if (Unit* tempLastInvoker = GetLastInvoker())
2459  scriptTrigger = tempLastInvoker;
2460 
2461  WorldObject* baseObject = GetBaseObject();
2462 
2463  ObjectList* l = new ObjectList();
2464  switch (e.GetTargetType())
2465  {
2466  case SMART_TARGET_SELF:
2467  if (baseObject)
2468  l->push_back(baseObject);
2469  break;
2470  case SMART_TARGET_VICTIM:
2471  if (me)
2472  if (Unit* victim = me->GetVictim())
2473  l->push_back(victim);
2474  break;
2476  if (me)
2477  if (Unit* u = me->AI()->SelectTarget(SELECT_TARGET_TOPAGGRO, 1))
2478  l->push_back(u);
2479  break;
2481  if (me)
2482  if (Unit* u = me->AI()->SelectTarget(SELECT_TARGET_BOTTOMAGGRO, 0))
2483  l->push_back(u);
2484  break;
2486  if (me)
2487  if (Unit* u = me->AI()->SelectTarget(SELECT_TARGET_RANDOM, 0))
2488  l->push_back(u);
2489  break;
2491  if (me)
2492  if (Unit* u = me->AI()->SelectTarget(SELECT_TARGET_RANDOM, 1))
2493  l->push_back(u);
2494  break;
2496  if (scriptTrigger)
2497  l->push_back(scriptTrigger);
2498  break;
2500  // no exist in tbc
2501  break;
2503  if (scriptTrigger)
2504  {
2505  if (Player* player = scriptTrigger->ToPlayer())
2506  {
2507  if (Group* group = player->GetGroup())
2508  {
2509  for (GroupReference* groupRef = group->GetFirstMember(); groupRef != NULL; groupRef = groupRef->next())
2510  if (Player* member = groupRef->GetSource())
2511  if (member->IsInMap(player))
2512  l->push_back(member);
2513  }
2514  // We still add the player to the list if there is no group. If we do
2515  // this even if there is a group (thus the else-check), it will add the
2516  // same player to the list twice. We don't want that to happen.
2517  else
2518  l->push_back(scriptTrigger);
2519  }
2520  }
2521  break;
2523  {
2524  // will always return a valid pointer, even if empty list
2525  ObjectList* units = GetWorldObjectsInDist((float)e.target.unitRange.maxDist);
2526  for (ObjectList::const_iterator itr = units->begin(); itr != units->end(); ++itr)
2527  {
2528  if (!IsCreature(*itr))
2529  continue;
2530 
2531  if (me && me->GetGUID() == (*itr)->GetGUID())
2532  continue;
2533 
2534  if ((!e.target.unitRange.creature || (*itr)->ToCreature()->GetEntry() == e.target.unitRange.creature) && baseObject->IsInRange(*itr, float(e.target.unitRange.minDist), float(e.target.unitRange.maxDist)))
2535  l->push_back(*itr);
2536  }
2537 
2538  delete units;
2539  break;
2540  }
2542  {
2543  // will always return a valid pointer, even if empty list
2544  ObjectList* units = GetWorldObjectsInDist((float)e.target.unitDistance.dist);
2545  for (ObjectList::const_iterator itr = units->begin(); itr != units->end(); ++itr)
2546  {
2547  if (!IsCreature(*itr))
2548  continue;
2549 
2550  if (me && me->GetGUID() == (*itr)->GetGUID())
2551  continue;
2552 
2553  if (!e.target.unitDistance.creature || (*itr)->ToCreature()->GetEntry() == e.target.unitDistance.creature)
2554  l->push_back(*itr);
2555  }
2556 
2557  delete units;
2558  break;
2559  }
2561  {
2562  // will always return a valid pointer, even if empty list
2563  ObjectList* units = GetWorldObjectsInDist((float)e.target.goDistance.dist);
2564  for (ObjectList::const_iterator itr = units->begin(); itr != units->end(); ++itr)
2565  {
2566  if (!IsGameObject(*itr))
2567  continue;
2568 
2569  if (go && go->GetGUID() == (*itr)->GetGUID())
2570  continue;
2571 
2572  if (!e.target.goDistance.entry || (*itr)->ToGameObject()->GetEntry() == e.target.goDistance.entry)
2573  l->push_back(*itr);
2574  }
2575 
2576  delete units;
2577  break;
2578  }
2580  {
2581  // will always return a valid pointer, even if empty list
2582  ObjectList* units = GetWorldObjectsInDist((float)e.target.goRange.maxDist);
2583  for (ObjectList::const_iterator itr = units->begin(); itr != units->end(); ++itr)
2584  {
2585  if (!IsGameObject(*itr))
2586  continue;
2587 
2588  if (go && go->GetGUID() == (*itr)->GetGUID())
2589  continue;
2590 
2591  if ((!e.target.goRange.entry && (*itr)->ToGameObject()->GetEntry() == e.target.goRange.entry) && baseObject->IsInRange(*itr, float(e.target.goRange.minDist), float(e.target.goRange.maxDist)))
2592  l->push_back(*itr);
2593  }
2594 
2595  delete units;
2596  break;
2597  }
2599  {
2600  if (!scriptTrigger && !baseObject)
2601  {
2602  sLog.outError("SMART_TARGET_CREATURE_GUID can not be used without invoker");
2603  break;
2604  }
2605 
2606  if (Creature* target = FindCreatureNear(scriptTrigger ? scriptTrigger : baseObject, e.target.unitGUID.dbGuid))
2607  if (!e.target.unitGUID.entry || target->GetEntry() == e.target.unitGUID.entry)
2608  l->push_back(target);
2609  break;
2610  }
2612  {
2613  if (!scriptTrigger && !baseObject)
2614  {
2615  sLog.outError("SMART_TARGET_GAMEOBJECT_GUID can not be used without invoker");
2616  break;
2617  }
2618 
2619  if (GameObject* target = FindGameObjectNear(scriptTrigger ? scriptTrigger : baseObject, e.target.goGUID.dbGuid))
2620  if (!e.target.goGUID.entry || target->GetEntry() == e.target.goGUID.entry)
2621  l->push_back(target);
2622  break;
2623  }
2625  {
2626  // will always return a valid pointer, even if empty list
2627  ObjectList* units = GetWorldObjectsInDist((float)e.target.playerRange.maxDist);
2628  if (!units->empty() && baseObject)
2629  for (ObjectList::const_iterator itr = units->begin(); itr != units->end(); ++itr)
2630  if (IsPlayer(*itr) && baseObject->IsInRange(*itr, (float)e.target.playerRange.minDist, (float)e.target.playerRange.maxDist))
2631  l->push_back(*itr);
2632 
2633  delete units;
2634  break;
2635  }
2637  {
2638  // will always return a valid pointer, even if empty list
2639  ObjectList* units = GetWorldObjectsInDist((float)e.target.playerDistance.dist);
2640  for (ObjectList::const_iterator itr = units->begin(); itr != units->end(); ++itr)
2641  if (IsPlayer(*itr))
2642  l->push_back(*itr);
2643 
2644  delete units;
2645  break;
2646  }
2647  case SMART_TARGET_STORED:
2648  {
2649  ObjectListMap::iterator itr = mTargetStorage->find(e.target.stored.id);
2650  if (itr != mTargetStorage->end())
2651  {
2652  ObjectList* objectList = itr->second->GetObjectList();
2653  l->assign(objectList->begin(), objectList->end());
2654  }
2655 
2656  return l;
2657  }
2659  {
2660  if (Creature* target = GetClosestCreatureWithEntry(baseObject, e.target.closest.entry, float(e.target.closest.dist ? e.target.closest.dist : 100), !e.target.closest.dead))
2661  l->push_back(target);
2662  break;
2663  }
2665  {
2666  if (GameObject* target = GetClosestGameObjectWithEntry(baseObject, e.target.closest.entry, float(e.target.closest.dist ? e.target.closest.dist : 100)))
2667  l->push_back(target);
2668  break;
2669  }
2671  {
2672  if (me)
2673  if (Player* target = me->SelectNearestPlayer(float(e.target.playerDistance.dist)))
2674  l->push_back(target);
2675  break;
2676  }
2678  {
2679  if (me)
2680  {
2681  ObjectGuid charmerOrOwnerGuid = me->GetCharmerOrOwnerGUID();
2682 
2683  if (!charmerOrOwnerGuid)
2684  charmerOrOwnerGuid = me->GetCreatorGUID();
2685 
2686  if (Unit* owner = ObjectAccessor::GetUnit(*me, charmerOrOwnerGuid))
2687  l->push_back(owner);
2688  }
2689  break;
2690  }
2692  {
2693  if (me)
2694  {
2695  ThreatContainer::StorageType threatList = me->getThreatManager().getThreatList();
2696  for (ThreatContainer::StorageType::const_iterator i = threatList.begin(); i != threatList.end(); ++i)
2697  if (Unit* temp = ObjectAccessor::GetUnit(*me, (*i)->getUnitGuid()))
2698  l->push_back(temp);
2699  }
2700  break;
2701  }
2703  {
2704  if (me)
2705  if (Unit* target = me->SelectNearestTarget(e.target.closestAttackable.maxDist, e.target.closestAttackable.playerOnly != 0))
2706  l->push_back(target);
2707  break;
2708  }
2710  {
2711  if (me)
2712  if (Unit* target = DoFindClosestFriendlyInRange(e.target.closestFriendly.maxDist, e.target.closestFriendly.playerOnly != 0))
2713  l->push_back(target);
2714  break;
2715  }
2716  case SMART_TARGET_POSITION:
2717  case SMART_TARGET_NONE:
2718  default:
2719  break;
2720  }
2721 
2722  if (l->empty())
2723  {
2724  delete l;
2725  l = NULL;
2726  }
2727 
2728  return l;
2729 }
2730 
2732 {
2733  ObjectList* targets = new ObjectList();
2734  WorldObject* obj = GetBaseObject();
2735 
2736  if (obj)
2737  {
2738  Oregon::AllWorldObjectsInRange u_check(obj, dist);
2739  Oregon::WorldObjectListSearcher<Oregon::AllWorldObjectsInRange> searcher(obj, *targets, u_check);
2740  obj->VisitNearbyObject(dist, searcher);
2741  }
2742  return targets;
2743 }
2744 
2745 void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, uint32 var1, bool bvar, const SpellEntry* spell, GameObject* gob)
2746 {
2747  if (!e.active && e.GetEventType() != SMART_EVENT_LINK)
2748  return;
2749 
2751  return;
2752 
2753  switch (e.GetEventType())
2754  {
2755  case SMART_EVENT_LINK://special handling
2756  ProcessAction(e, unit, var0, var1, bvar, spell, gob);
2757  break;
2758  //called from Update tick
2759  case SMART_EVENT_UPDATE:
2760  ProcessTimedAction(e, e.event.minMaxRepeat.repeatMin, e.event.minMaxRepeat.repeatMax);
2761  break;
2763  if (me && me->IsInCombat())
2764  return;
2765  ProcessTimedAction(e, e.event.minMaxRepeat.repeatMin, e.event.minMaxRepeat.repeatMax);
2766  break;
2767  case SMART_EVENT_UPDATE_IC:
2768  if (!me || !me->IsInCombat())
2769  return;
2770  ProcessTimedAction(e, e.event.minMaxRepeat.repeatMin, e.event.minMaxRepeat.repeatMax);
2771  break;
2772  case SMART_EVENT_HEALT_PCT:
2773  {
2774  if (!me || !me->IsInCombat() || !me->GetMaxHealth())
2775  return;
2776  uint32 perc = (uint32)me->GetHealthPct();
2777  if (perc > e.event.minMaxRepeat.max || perc < e.event.minMaxRepeat.min)
2778  return;
2779  ProcessTimedAction(e, e.event.minMaxRepeat.repeatMin, e.event.minMaxRepeat.repeatMax);
2780  break;
2781  }
2783  {
2784  if (!me || !me->IsInCombat() || !me->GetVictim() || !me->GetVictim()->GetMaxHealth())
2785  return;
2786  uint32 perc = (uint32)me->GetVictim()->GetHealthPct();
2787  if (perc > e.event.minMaxRepeat.max || perc < e.event.minMaxRepeat.min)
2788  return;
2789  ProcessTimedAction(e, e.event.minMaxRepeat.repeatMin, e.event.minMaxRepeat.repeatMax, me->GetVictim());
2790  break;
2791  }
2792  case SMART_EVENT_MANA_PCT:
2793  {
2794  if (!me || !me->IsInCombat() || !me->GetMaxPower(POWER_MANA))
2795  return;
2796  uint32 perc = uint32(100.0f * me->GetPower(POWER_MANA) / me->GetMaxPower(POWER_MANA));
2797  if (perc > e.event.minMaxRepeat.max || perc < e.event.minMaxRepeat.min)
2798  return;
2799  ProcessTimedAction(e, e.event.minMaxRepeat.repeatMin, e.event.minMaxRepeat.repeatMax);
2800  break;
2801  }
2803  {
2804  if (!me || !me->IsInCombat() || !me->GetVictim() || !me->GetVictim()->GetMaxPower(POWER_MANA))
2805  return;
2806  uint32 perc = uint32(100.0f * me->GetVictim()->GetPower(POWER_MANA) / me->GetVictim()->GetMaxPower(POWER_MANA));
2807  if (perc > e.event.minMaxRepeat.max || perc < e.event.minMaxRepeat.min)
2808  return;
2809  ProcessTimedAction(e, e.event.minMaxRepeat.repeatMin, e.event.minMaxRepeat.repeatMax, me->GetVictim());
2810  break;
2811  }
2812  case SMART_EVENT_RANGE:
2813  {
2814  if (!me || !me->IsInCombat() || !me->GetVictim())
2815  return;
2816 
2817  if (me->IsInRange(me->GetVictim(), (float)e.event.minMaxRepeat.min, (float)e.event.minMaxRepeat.max))
2818  ProcessTimedAction(e, e.event.minMaxRepeat.repeatMin, e.event.minMaxRepeat.repeatMax, me->GetVictim());
2819  break;
2820  }
2822  {
2823  if (!me || !me->IsInCombat())
2824  return;
2825 
2826  Unit* victim = me->GetVictim();
2827 
2828  if (!victim || !victim->IsNonMeleeSpellCast(false, false, true))
2829  return;
2830 
2831  if (e.event.targetCasting.spellId > 0)
2832  if (Spell* currSpell = victim->GetCurrentSpell(CURRENT_GENERIC_SPELL))
2833  if (currSpell->m_spellInfo->Id != e.event.targetCasting.spellId)
2834  return;
2835 
2836  ProcessTimedAction(e, e.event.targetCasting.repeatMin, e.event.targetCasting.repeatMax, me->GetVictim());
2837  break;
2838  }
2840  {
2841  if (!me || !me->IsInCombat())
2842  return;
2843 
2844  Unit* target = DoSelectLowestHpFriendly((float)e.event.friendlyHealth.radius, e.event.friendlyHealth.hpDeficit);
2845  if (!target || !target->IsInCombat())
2846  return;
2847  ProcessTimedAction(e, e.event.friendlyHealth.repeatMin, e.event.friendlyHealth.repeatMax, target);
2848  break;
2849  }
2851  {
2852  if (!me || !me->IsInCombat())
2853  return;
2854 
2855  std::list<Creature*> pList;
2856  DoFindFriendlyCC(pList, (float)e.event.friendlyCC.radius);
2857  if (pList.empty())
2858  return;
2859  ProcessTimedAction(e, e.event.friendlyCC.repeatMin, e.event.friendlyCC.repeatMax, *pList.begin());
2860  break;
2861  }
2863  {
2864  std::list<Creature*> pList;
2865  DoFindFriendlyMissingBuff(pList, (float)e.event.missingBuff.radius, e.event.missingBuff.spell);
2866 
2867  if (pList.empty())
2868  return;
2869 
2870  ProcessTimedAction(e, e.event.missingBuff.repeatMin, e.event.missingBuff.repeatMax, *pList.begin());
2871  break;
2872  }
2873  case SMART_EVENT_HAS_AURA:
2874  {
2875  if (!me)
2876  return;
2877  uint32 count = me->GetAuraCount(e.event.aura.spell);
2878  if ((!e.event.aura.count && !count) || (e.event.aura.count && count >= e.event.aura.count))
2879  ProcessTimedAction(e, e.event.aura.repeatMin, e.event.aura.repeatMax);
2880  break;
2881  }
2883  {
2884  if (!me || !me->GetVictim())
2885  return;
2886  uint32 count = me->GetVictim()->GetAuraCount(e.event.aura.spell);
2887  if (count < e.event.aura.count)
2888  return;
2889  ProcessTimedAction(e, e.event.aura.repeatMin, e.event.aura.repeatMax);
2890  break;
2891  }
2892  //no params
2893  case SMART_EVENT_AGGRO:
2894  case SMART_EVENT_DEATH:
2895  case SMART_EVENT_EVADE:
2897  case SMART_EVENT_CHARMED:
2900  case SMART_EVENT_AI_INIT:
2909  case SMART_EVENT_RESET:
2914  ProcessAction(e, unit, var0, var1, bvar, spell, gob);
2915  break;
2917  {
2918  if (!me)
2919  return;
2920 
2921  if (Unit* victim = me->GetVictim())
2922  {
2923  if (!victim->HasInArc(static_cast<float>(M_PI), me))
2924  ProcessTimedAction(e, e.event.behindTarget.cooldownMin, e.event.behindTarget.cooldownMax, victim);
2925  }
2926  break;
2927  }
2929  if (e.event.emote.emote == var0)
2930  {
2931  RecalcTimer(e, e.event.emote.cooldownMin, e.event.emote.cooldownMax);
2932  ProcessAction(e, unit);
2933  }
2934  break;
2935  case SMART_EVENT_KILL:
2936  {
2937  if (!me || !unit)
2938  return;
2939  if (e.event.kill.playerOnly && unit->GetTypeId() != TYPEID_PLAYER)
2940  return;
2941  if (e.event.kill.creature && unit->GetEntry() != e.event.kill.creature)
2942  return;
2943  RecalcTimer(e, e.event.kill.cooldownMin, e.event.kill.cooldownMax);
2944  ProcessAction(e, unit);
2945  break;
2946  }
2948  case SMART_EVENT_SPELLHIT:
2949  {
2950  if (!spell)
2951  return;
2952  if ((!e.event.spellHit.spell || spell->Id == e.event.spellHit.spell) &&
2953  (!e.event.spellHit.school || (spell->SchoolMask & e.event.spellHit.school)))
2954  {
2955  RecalcTimer(e, e.event.spellHit.cooldownMin, e.event.spellHit.cooldownMax);
2956  ProcessAction(e, unit, 0, 0, bvar, spell);
2957  }
2958  break;
2959  }
2960  case SMART_EVENT_OOC_LOS:
2961  {
2962  if (!me || me->IsInCombat())
2963  return;
2964  //can trigger if closer than fMaxAllowedRange
2965  float range = (float)e.event.los.maxDist;
2966 
2967  //if range is ok and we are actually in LOS
2968  if (me->IsWithinDistInMap(unit, range) && me->IsWithinLOSInMap(unit))
2969  {
2970  //if friendly event&&who is not hostile OR hostile event&&who is hostile
2971  if ((e.event.los.noHostile && !me->IsHostileTo(unit)) ||
2972  (!e.event.los.noHostile && me->IsHostileTo(unit)))
2973  {
2974  RecalcTimer(e, e.event.los.cooldownMin, e.event.los.cooldownMax);
2975  ProcessAction(e, unit);
2976  }
2977  }
2978  break;
2979  }
2980  case SMART_EVENT_IC_LOS:
2981  {
2982  if (!me || !me->IsInCombat())
2983  return;
2984  //can trigger if closer than fMaxAllowedRange
2985  float range = (float)e.event.los.maxDist;
2986 
2987  //if range is ok and we are actually in LOS
2988  if (me->IsWithinDistInMap(unit, range) && me->IsWithinLOSInMap(unit))
2989  {
2990  //if friendly event&&who is not hostile OR hostile event&&who is hostile
2991  if ((e.event.los.noHostile && !me->IsHostileTo(unit)) ||
2992  (!e.event.los.noHostile && me->IsHostileTo(unit)))
2993  {
2994  RecalcTimer(e, e.event.los.cooldownMin, e.event.los.cooldownMax);
2995  ProcessAction(e, unit);
2996  }
2997  }
2998  break;
2999  }
3000  case SMART_EVENT_RESPAWN:
3001  {
3002  if (!GetBaseObject())
3003  return;
3004  if (e.event.respawn.type == SMART_SCRIPT_RESPAWN_CONDITION_MAP && GetBaseObject()->GetMapId() != e.event.respawn.map)
3005  return;
3006  if (e.event.respawn.type == SMART_SCRIPT_RESPAWN_CONDITION_AREA && GetBaseObject()->GetZoneId() != e.event.respawn.area)
3007  return;
3008  ProcessAction(e);
3009  break;
3010  }
3012  {
3013  if (!IsCreature(unit))
3014  return;
3015  if (e.event.summoned.creature && unit->GetEntry() != e.event.summoned.creature)
3016  return;
3017  RecalcTimer(e, e.event.summoned.cooldownMin, e.event.summoned.cooldownMax);
3018  ProcessAction(e, unit);
3019  break;
3020  }
3022  case SMART_EVENT_DAMAGED:
3024  {
3025  if (var0 > e.event.minMaxRepeat.max || var0 < e.event.minMaxRepeat.min)
3026  return;
3027  RecalcTimer(e, e.event.minMaxRepeat.repeatMin, e.event.minMaxRepeat.repeatMax);
3028  ProcessAction(e, unit);
3029  break;
3030  }
3032  {
3033  if ((e.event.movementInform.type && var0 != e.event.movementInform.type) || (e.event.movementInform.id && var1 != e.event.movementInform.id))
3034  return;
3035  ProcessAction(e, unit, var0, var1);
3036  break;
3037  }
3040  {
3041  if (e.event.waypoint.pathID && var0 != e.event.waypoint.pathID)
3042  return;
3043  ProcessAction(e, unit, var0);
3044  break;
3045  }
3051  {
3052  if (!me || (e.event.waypoint.pointID && var0 != e.event.waypoint.pointID) || (e.event.waypoint.pathID && GetPathId() != e.event.waypoint.pathID))
3053  return;
3054  ProcessAction(e, unit);
3055  break;
3056  }
3059  {
3060  if (e.event.instancePlayerEnter.team && var0 != e.event.instancePlayerEnter.team)
3061  return;
3062  RecalcTimer(e, e.event.instancePlayerEnter.cooldownMin, e.event.instancePlayerEnter.cooldownMax);
3063  ProcessAction(e, unit, var0);
3064  break;
3065  }
3068  {
3069  if (e.event.quest.quest && var0 != e.event.quest.quest)
3070  return;
3071  ProcessAction(e, unit, var0);
3072  break;
3073  }
3075  {
3076  if (e.event.transportAddCreature.creature && var0 != e.event.transportAddCreature.creature)
3077  return;
3078  ProcessAction(e, unit, var0);
3079  break;
3080  }
3082  {
3083  if (e.event.areatrigger.id && var0 != e.event.areatrigger.id)
3084  return;
3085  ProcessAction(e, unit, var0);
3086  break;
3087  }
3088  case SMART_EVENT_TEXT_OVER:
3089  {
3090  if (var0 != e.event.textOver.textGroupID || (e.event.textOver.creatureEntry && e.event.textOver.creatureEntry != var1))
3091  return;
3092  ProcessAction(e, unit, var0);
3093  break;
3094  }
3095  case SMART_EVENT_DATA_SET:
3096  {
3097  if (e.event.dataSet.id != var0 || e.event.dataSet.value != var1)
3098  return;
3099  RecalcTimer(e, e.event.dataSet.cooldownMin, e.event.dataSet.cooldownMax);
3100  ProcessAction(e, unit, var0, var1);
3101  break;
3102  }
3105  {
3106  if (!unit)
3107  return;
3108  RecalcTimer(e, e.event.minMax.repeatMin, e.event.minMax.repeatMax);
3109  ProcessAction(e, unit);
3110  break;
3111  }
3113  {
3114  if (e.event.timedEvent.id == var0)
3115  ProcessAction(e, unit);
3116  break;
3117  }
3119  {
3120  sLog.outDebug("SmartScript: Gossip Select: menu %u action %u", var0, var1);//little help for scripters
3121  if (e.event.gossip.sender != var0 || e.event.gossip.action != var1)
3122  return;
3123  ProcessAction(e, unit, var0, var1);
3124  break;
3125  }
3127  {
3128  if (e.event.dummy.spell != var0 || e.event.dummy.effIndex != var1)
3129  return;
3130  ProcessAction(e, unit, var0, var1);
3131  break;
3132  }
3135  {
3136  if (e.event.gameEvent.gameEventId != var0)
3137  return;
3138  ProcessAction(e, NULL, var0);
3139  break;
3140  }
3142  {
3143  if (e.event.goStateChanged.state != var0)
3144  return;
3145  ProcessAction(e, unit, var0, var1);
3146  break;
3147  }
3149  {
3150  if (e.event.eventInform.eventId != var0)
3151  return;
3152  ProcessAction(e, NULL, var0);
3153  break;
3154  }
3156  {
3157  if (e.event.doAction.eventId != var0)
3158  return;
3159  ProcessAction(e, unit, var0);
3160  break;
3161  }
3163  {
3164  if (!me || !me->IsInCombat())
3165  return;
3166 
3167  ObjectList* _targets = NULL;
3168 
3169  switch (e.GetTargetType())
3170  {
3178  _targets = GetTargets(e);
3179  break;
3180  default:
3181  return;
3182  }
3183 
3184  if (!_targets)
3185  return;
3186 
3187  Unit* target = NULL;
3188 
3189  for (ObjectList::const_iterator itr = _targets->begin(); itr != _targets->end(); ++itr)
3190  {
3191  if (IsUnit(*itr) && me->IsFriendlyTo((*itr)->ToUnit()) && (*itr)->ToUnit()->IsAlive() && (*itr)->ToUnit()->IsInCombat())
3192  {
3193  uint32 healthPct = uint32((*itr)->ToUnit()->GetHealthPct());
3194 
3195  if (healthPct > e.event.friendlyHealthPct.maxHpPct || healthPct < e.event.friendlyHealthPct.minHpPct)
3196  continue;
3197 
3198  target = (*itr)->ToUnit();
3199  break;
3200  }
3201  }
3202 
3203  delete _targets;
3204 
3205  if (!target)
3206  return;
3207 
3208  ProcessTimedAction(e, e.event.friendlyHealthPct.repeatMin, e.event.friendlyHealthPct.repeatMax, target);
3209  break;
3210  }
3212  {
3213  if (!me)
3214  return;
3215 
3216  WorldObject* creature = NULL;
3217 
3218  if (e.event.distance.guid != 0)
3219  {
3220  creature = FindCreatureNear(me, e.event.distance.guid);
3221 
3222  if (!creature)
3223  return;
3224 
3225  if (!me->IsInRange(creature, 0, (float)e.event.distance.dist))
3226  return;
3227  }
3228  else if (e.event.distance.entry != 0)
3229  {
3230  std::list<Creature*> list;
3231  me->GetCreatureListWithEntryInGrid(list, e.event.distance.entry, (float)e.event.distance.dist);
3232 
3233  if (!list.empty())
3234  creature = list.front();
3235  }
3236 
3237  if (creature)
3238  ProcessTimedAction(e, e.event.distance.repeat, e.event.distance.repeat);
3239 
3240  break;
3241  }
3243  {
3244  if (!me)
3245  return;
3246 
3247  WorldObject* gameobject = NULL;
3248 
3249  if (e.event.distance.guid != 0)
3250  {
3251  gameobject = FindGameObjectNear(me, e.event.distance.guid);
3252 
3253  if (!gameobject)
3254  return;
3255 
3256  if (!me->IsInRange(gameobject, 0, (float)e.event.distance.dist))
3257  return;
3258  }
3259  else if (e.event.distance.entry != 0)
3260  {
3261  std::list<GameObject*> list;
3262  me->GetGameObjectListWithEntryInGrid(list, e.event.distance.entry, (float)e.event.distance.dist);
3263 
3264  if (!list.empty())
3265  gameobject = list.front();
3266  }
3267 
3268  if (gameobject)
3269  ProcessTimedAction(e, e.event.distance.repeat, e.event.distance.repeat);
3270 
3271  break;
3272  }
3274  if (GetCounterId(e.event.counter.id) != 0 && GetCounterValue(e.event.counter.id) == e.event.counter.value)
3275  ProcessTimedAction(e, e.event.counter.cooldownMin, e.event.counter.cooldownMax);
3276  break;
3277  default:
3278  sLog.outError("SmartScript::ProcessEvent: Unhandled Event type %u", e.GetEventType());
3279  break;
3280  }
3281 }
3282 
3284 {
3285  switch (e.GetEventType())
3286  {
3287  //set only events which have initial timers
3288  case SMART_EVENT_UPDATE:
3289  case SMART_EVENT_UPDATE_IC:
3291  RecalcTimer(e, e.event.minMaxRepeat.min, e.event.minMaxRepeat.max);
3292  break;
3295  RecalcTimer(e, e.event.distance.repeat, e.event.distance.repeat);
3296  break;
3297  default:
3298  e.active = true;
3299  break;
3300  }
3301 }
3303 {
3304  // min/max was checked at loading!
3305  e.timer = urand(min, max);
3306  e.active = e.timer ? false : true;
3307 }
3308 
3310 {
3311  if (e.GetEventType() == SMART_EVENT_LINK)
3312  return;
3313 
3314  if (e.event.event_phase_mask && !IsInPhase(e.event.event_phase_mask))
3315  return;
3316 
3317  if (e.GetEventType() == SMART_EVENT_UPDATE_IC && (!me || !me->IsInCombat()))
3318  return;
3319 
3320  if (e.GetEventType() == SMART_EVENT_UPDATE_OOC && (me && me->IsInCombat())) //can be used with me=NULL (go script)
3321  return;
3322 
3323  if (e.timer < diff)
3324  {
3325  // delay spell cast event if another spell is being cast
3326  if (e.GetActionType() == SMART_ACTION_CAST)
3327  {
3328  if (!(e.action.cast.flags & SMARTCAST_INTERRUPT_PREVIOUS))
3329  {
3330  if (me && me->HasUnitState(UNIT_STATE_CASTING))
3331  {
3332  e.timer = 1;
3333  return;
3334  }
3335  }
3336  }
3337 
3338  // Delay flee for assist event if stunned or rooted
3340  {
3341  if (me && me->HasUnitState(UNIT_STATE_ROOT | UNIT_STATE_STUNNED))
3342  {
3343  e.timer = 1;
3344  return;
3345  }
3346  }
3347 
3348  e.active = true;//activate events with cooldown
3349  switch (e.GetEventType())//process ONLY timed events
3350  {
3351  case SMART_EVENT_UPDATE:
3353  case SMART_EVENT_UPDATE_IC:
3354  case SMART_EVENT_HEALT_PCT:
3356  case SMART_EVENT_MANA_PCT:
3358  case SMART_EVENT_RANGE:
3363  case SMART_EVENT_HAS_AURA:
3369  {
3370  ProcessEvent(e);
3372  {
3373  e.enableTimed = false;//disable event if it is in an ActionList and was processed once
3374  for (SmartAIEventList::iterator i = mTimedActionList.begin(); i != mTimedActionList.end(); ++i)
3375  {
3376  //find the first event which is not the current one and enable it
3377  if (i->event_id > e.event_id)
3378  {
3379  i->enableTimed = true;
3380  break;
3381  }
3382  }
3383  }
3384  break;
3385  }
3386  }
3387  }
3388  else
3389  e.timer -= diff;
3390 }
3391 
3393 {
3394  return e.active;
3395 }
3396 
3398 {
3399  if (!mInstallEvents.empty())
3400  {
3401  for (SmartAIEventList::iterator i = mInstallEvents.begin(); i != mInstallEvents.end(); ++i)
3402  mEvents.push_back(*i);//must be before UpdateTimers
3403 
3404  mInstallEvents.clear();
3405  }
3406 }
3407 
3409 {
3410  if ((mScriptType == SMART_SCRIPT_TYPE_CREATURE || mScriptType == SMART_SCRIPT_TYPE_GAMEOBJECT) && !GetBaseObject())
3411  return;
3412 
3413  InstallEvents();//before UpdateTimers
3414 
3415  for (SmartAIEventList::iterator i = mEvents.begin(); i != mEvents.end(); ++i)
3416  UpdateTimer(*i, diff);
3417 
3418  if (!mStoredEvents.empty())
3419  for (SmartAIEventList::iterator i = mStoredEvents.begin(); i != mStoredEvents.end(); ++i)
3420  UpdateTimer(*i, diff);
3421 
3422  bool needCleanup = true;
3423  if (!mTimedActionList.empty())
3424  {
3425  isProcessingTimedActionList = true;
3426  for (SmartAIEventList::iterator i = mTimedActionList.begin(); i != mTimedActionList.end(); ++i)
3427  {
3428  if ((*i).enableTimed)
3429  {
3430  UpdateTimer(*i, diff);
3431  needCleanup = false;
3432  }
3433  }
3434 
3435  isProcessingTimedActionList = false;
3436  }
3437  if (needCleanup)
3438  mTimedActionList.clear();
3439 
3440  if (!mRemIDs.empty())
3441  {
3442  for (std::list<uint32>::iterator i = mRemIDs.begin(); i != mRemIDs.end(); ++i)
3443  {
3444  RemoveStoredEvent((*i));
3445  }
3446  }
3447  if (mUseTextTimer && me)
3448  {
3449  if (mTextTimer < diff)
3450  {
3451  uint32 textID = mLastTextID;
3452  mLastTextID = 0;
3453  uint32 entry = mTalkerEntry;
3454  mTalkerEntry = 0;
3455  mTextTimer = 0;
3456  mUseTextTimer = false;
3457  ProcessEventsFor(SMART_EVENT_TEXT_OVER, NULL, textID, entry);
3458  } else mTextTimer -= diff;
3459  }
3460 }
3461 
3463 {
3464  if (e.empty())
3465  {
3466  if (obj)
3467  sLog.outDebug("SmartScript: EventMap for Entry %u is empty but is using SmartScript.", obj->GetEntry());
3468  if (at)
3469  sLog.outDebug("SmartScript: EventMap for AreaTrigger %u is empty but is using SmartScript.", at->id);
3470  return;
3471  }
3472  for (SmartAIEventList::iterator i = e.begin(); i != e.end(); ++i)
3473  {
3474  #ifndef TRINITY_DEBUG
3475  if ((*i).event.event_flags & SMART_EVENT_FLAG_DEBUG_ONLY)
3476  continue;
3477  #endif
3478 
3479  if ((*i).event.event_flags & SMART_EVENT_FLAG_DIFFICULTY_ALL)//if has instance flag add only if in it
3480  {
3481  if (obj && obj->GetMap()->IsDungeon())
3482  {
3483  if ((1 << (obj->GetMap()->GetSpawnMode()+1)) & (*i).event.event_flags)
3484  {
3485  mEvents.push_back((*i));
3486  }
3487  }
3488  continue;
3489  }
3490  mEvents.push_back((*i));//NOTE: 'world(0)' events still get processed in ANY instance mode
3491  }
3492 }
3493 
3495 {
3496  SmartAIEventList e;
3497  if (me)
3498  {
3499  e = sSmartScriptMgr->GetScript(-((int32)me->GetDBTableGUIDLow()), mScriptType);
3500  if (e.empty())
3501  e = sSmartScriptMgr->GetScript((int32)me->GetEntry(), mScriptType);
3502  FillScript(e, me, NULL);
3503  }
3504  else if (go)
3505  {
3506  e = sSmartScriptMgr->GetScript(-((int32)go->GetDBTableGUIDLow()), mScriptType);
3507  if (e.empty())
3508  e = sSmartScriptMgr->GetScript((int32)go->GetEntry(), mScriptType);
3509  FillScript(e, go, NULL);
3510  }
3511  else if (trigger)
3512  {
3513  e = sSmartScriptMgr->GetScript((int32)trigger->id, mScriptType);
3514  FillScript(e, NULL, trigger);
3515  }
3516 }
3517 
3519 {
3520  if (obj)//handle object based scripts
3521  {
3522  switch (obj->GetTypeId())
3523  {
3524  case TYPEID_UNIT:
3525  mScriptType = SMART_SCRIPT_TYPE_CREATURE;
3526  me = obj->ToCreature();
3527  sLog.outDebug("SmartScript::OnInitialize: source is Creature %u", me->GetEntry());
3528  break;
3529  case TYPEID_GAMEOBJECT:
3530  mScriptType = SMART_SCRIPT_TYPE_GAMEOBJECT;
3531  go = obj->ToGameObject();
3532  sLog.outDebug("SmartScript::OnInitialize: source is GameObject %u", go->GetEntry());
3533  break;
3534  default:
3535  sLog.outError("SmartScript::OnInitialize: Unhandled TypeID !WARNING!");
3536  return;
3537  }
3538  } else if (at)
3539  {
3540  mScriptType = SMART_SCRIPT_TYPE_AREATRIGGER;
3541  trigger = at;
3542  sLog.outDebug("SmartScript::OnInitialize: source is AreaTrigger %u", trigger->id);
3543  }
3544  else
3545  {
3546  sLog.outError("SmartScript::OnInitialize: !WARNING! Initialized objects are NULL.");
3547  return;
3548  }
3549 
3550  GetScript();//load copy of script
3551 
3552  for (SmartAIEventList::iterator i = mEvents.begin(); i != mEvents.end(); ++i)
3553  InitTimer((*i));//calculate timers for first time use
3554 
3555  ProcessEventsFor(SMART_EVENT_AI_INIT);
3556  InstallEvents();
3557  ProcessEventsFor(SMART_EVENT_JUST_CREATED);
3558 }
3559 
3561 {
3562  if (!me)
3563  return;
3564 
3565  ProcessEventsFor(me->IsInCombat() ? SMART_EVENT_IC_LOS : SMART_EVENT_OOC_LOS, who);
3566 }
3567 
3568 /*
3569 void SmartScript::UpdateAIWhileCharmed(const uint32 diff) { }
3570 
3571 void SmartScript::DoAction(const int32 param) { }
3572 
3573 uint32 SmartScript::GetData(uint32 id)
3574 {
3575  return 0;
3576 }
3577 
3578 void SmartScript::SetData(uint32 id, uint32 value) { }
3579 
3580 void SmartScript::SetGUID(uint64 guid, int32 id) { }
3581 
3582 uint64 SmartScript::GetGUID(int32 id)
3583 {
3584  return 0;
3585 }
3586 
3587 void SmartScript::MovepointStart(uint32 id) { }
3588 
3589 void SmartScript::SetRun(bool run) { }
3590 
3591 void SmartScript::SetMovePathEndAction(SMART_ACTION action) { }
3592 
3593 uint32 SmartScript::DoChat(int8 id, uint64 whisperGuid)
3594 {
3595  return 0;
3596 }*/
3597 // SmartScript end
3598 
3600 {
3601  if (!me)
3602  return NULL;
3603 
3604  CellCoord p(Oregon::ComputeCellCoord(me->GetPositionX(), me->GetPositionY()));
3605  Cell cell(p);
3606  cell.SetNoCreate();
3607 
3608  Unit* unit = NULL;
3609 
3610  Oregon::MostHPMissingInRange u_check(me, range, MinHPDiff);
3611  Oregon::UnitLastSearcher<Oregon::MostHPMissingInRange> searcher(me, unit, u_check);
3612 
3614 
3615  cell.Visit(p, grid_unit_searcher, *me->GetMap(), *me, range);
3616  return unit;
3617 }
3618 
3619 void SmartScript::DoFindFriendlyCC(std::list<Creature*>& _list, float range)
3620 {
3621  if (!me)
3622  return;
3623 
3624  CellCoord p(Oregon::ComputeCellCoord(me->GetPositionX(), me->GetPositionY()));
3625  Cell cell(p);
3626  cell.SetNoCreate();
3627 
3628  Oregon::FriendlyCCedInRange u_check(me, range);
3629  Oregon::CreatureListSearcher<Oregon::FriendlyCCedInRange> searcher(me, _list, u_check);
3630 
3632 
3633  cell.Visit(p, grid_creature_searcher, *me->GetMap(), *me, range);
3634 }
3635 
3636 void SmartScript::DoFindFriendlyMissingBuff(std::list<Creature*>& list, float range, uint32 spellid)
3637 {
3638  if (!me)
3639  return;
3640 
3641  CellCoord p(Oregon::ComputeCellCoord(me->GetPositionX(), me->GetPositionY()));
3642  Cell cell(p);
3643  cell.SetNoCreate();
3644 
3645  Oregon::FriendlyMissingBuffInRange u_check(me, range, spellid);
3647 
3649 
3650  cell.Visit(p, grid_creature_searcher, *me->GetMap(), *me, range);
3651 }
3652 
3653 Unit* SmartScript::DoFindClosestFriendlyInRange(float range, bool playerOnly)
3654 {
3655  if (!me)
3656  return NULL;
3657 
3658  Unit* unit = NULL;
3659  Oregon::AnyFriendlyUnitInObjectRangeCheck u_check(me, me, range, playerOnly);
3661  me->VisitNearbyObject(range, searcher);
3662  return unit;
3663 }
3664 
3666 {
3667  //do NOT clear mTimedActionList if it's being iterated because it will invalidate the iterator and delete
3668  // any SmartScriptHolder contained like the "e" parameter passed to this function
3669  if (isProcessingTimedActionList)
3670  {
3671  sLog.outError("Entry %d SourceType %u Event %u Action %u is trying to overwrite timed action list from a timed action, this is not allowed!.", e.entryOrGuid, e.GetScriptType(), e.GetEventType(), e.GetActionType());
3672  return;
3673  }
3674 
3675  mTimedActionList.clear();
3676  mTimedActionList = sSmartScriptMgr->GetScript(entry, SMART_SCRIPT_TYPE_TIMED_ACTIONLIST);
3677  if (mTimedActionList.empty())
3678  return;
3679  for (SmartAIEventList::iterator i = mTimedActionList.begin(); i != mTimedActionList.end(); ++i)
3680  {
3681  i->enableTimed = i == mTimedActionList.begin();//enable processing only for the first action
3682 
3683  if (e.action.timedActionList.timerType == 0)
3684  i->event.type = SMART_EVENT_UPDATE_OOC;
3685  else if (e.action.timedActionList.timerType == 1)
3686  i->event.type = SMART_EVENT_UPDATE_IC;
3687  else if (e.action.timedActionList.timerType > 1)
3688  i->event.type = SMART_EVENT_UPDATE;
3689 
3690  InitTimer((*i));
3691  }
3692 }
3693 
3695 {
3696  return ObjectAccessor::FindUnit(mLastInvoker);
3697 }
void ProcessTimedAction(SmartScriptHolder &e, uint32 const &min, uint32 const &max, Unit *unit=NULL, uint32 var0=0, uint32 var1=0, bool bvar=false, const SpellEntry *spell=NULL, GameObject *gob=NULL)
struct SmartTarget::@241::@249 goRange
void OnUpdate(const uint32 diff)
struct SmartAction::@162::@209 setCounter
struct SmartAction::@162::@196 visibility
void FillScript(SmartAIEventList e, WorldObject *obj, AreaTriggerEntry const *at)
uint8 GetSpawnMode() const
Definition: Map.h:394
struct SmartEvent::@125::@136 missingBuff
struct SmartAction::@162::@199 taxi
struct SmartAction::@162::@197 summonGO
struct SmartTarget::@241::@248 stored
uint32 event_phase_mask
uint32 CalculatePowerCost(SpellEntry const *spellInfo, Unit const *caster, SpellSchoolMask schoolMask)
Definition: SpellMgr.cpp:303
struct SmartEvent::@125::@130 los
struct SmartEvent::@125::@156 eventInform
struct SmartAction::@162::@184 randomPhaseRange
void InstallTemplate(SmartScriptHolder const &e)
LootState
Definition: GameObject.h:580
Map * GetMap() const
Definition: Object.h:817
struct SmartAction::@162::@231 setHealthRegen
struct SmartAction::@162::@187 setInstanceData64
struct SmartEvent::@125::@154 gameEvent
static Unit * FindUnit(uint64)
struct SmartAction::@162::@236 gameEventStop
SMARTAI_TARGETS type
struct SmartAction::@162::@216 setunitByte
struct SmartAction::@162::@198 active
bool IsNonMeleeSpellCast(bool withDelayed, bool skipChanneled=false, bool skipAutorepeat=false) const
Definition: Unit.cpp:3578
std::vector< SmartScriptHolder > SmartAIEventList
bool CheckTimer(SmartScriptHolder const &e) const
struct SmartAction::@162::@179 setEventPhase
struct SmartEvent::@125::@142 movementInform
std::list< Condition * > ConditionList
Definition: ConditionMgr.h:223
#define CAST_AI(a, b)
struct SmartEvent::@125::@132 minMax
size_t operator()(WorldPacket *data, int locale) const
Definition: SmartScript.cpp:47
TempSummon * SummonCreature(uint32 id, const Position &pos, TempSummonType spwtype=TEMPSUMMON_MANUAL_DESPAWN, uint32 despwtime=0)
Definition: Object.cpp:2118
bool IsInCombat() const
Definition: Unit.h:1243
struct SmartTarget::@241::@250 goGUID
struct SmartAction::@162::@237 gameEventStart
virtual void SetData64(uint32, uint64)
Definition: ZoneScript.h:54
uint32 GetEventType() const
struct SmartAction::@162::@226 MoveToPos
struct SmartAction::@162::@201 wpPause
#define sLog
Log class singleton.
Definition: Log.h:187
void OnReset()
Definition: SmartScript.cpp:87
ChatMsg
struct SmartAction::@162::@228 setGoLootState
struct SmartAction::@162::@221 interruptSpellCasting
ACE_INT32 int32
Definition: Define.h:67
void InitTimer(SmartScriptHolder &e)
SMART_ACTION
void GroupEventHappens(uint32 questId, WorldObject const *pEventObject)
Definition: Player.cpp:13750
OregonStringTextBuilder(WorldObject *obj, ChatMsg msgtype, int32 id, uint32 language, WorldObject *target)
Definition: SmartScript.cpp:42
bool IsDungeon() const
Definition: Map.h:427
VirtualItemSlot
Definition: Creature.h:434
SMARTAI_TEMPLATE
static size_t BuildMonsterChat(WorldPacket *data, WorldObject *source, ChatMsg msgtype, std::string text, Language language, WorldObject *whisperTarget, int loc_idx)
void SetNoCreate()
Definition: Cell.h:76
struct SmartAction::@162::@225 RespawnTarget
struct SmartAction::@162::@204 installTtemplate
struct SmartEvent::@125::@131 respawn
struct SmartAction::@162::@205 setRun
Player * SelectNearestPlayer(float distance=0) const
Definition: Unit.cpp:12156
struct SmartAction::@162::@238 closestWaypointFromList
uint32 GetGUIDLow() const
Definition: Object.h:178
ObjectList * GetTargets(SmartScriptHolder const &e, Unit *invoker=NULL)
struct SmartAction::@162::@203 item
struct SmartEvent::@125::@151 gossip
void DoFindFriendlyMissingBuff(std::list< Creature * > &list, float range, uint32 spellid)
struct SmartAction::@162::@232 setRoot
struct SmartAction::@162::@195 moveRandom
struct SmartAction::@162::@191 forceDespawn
uint32 event_flags
void AddEvent(SMART_EVENT e, uint32 event_flags, uint32 event_param1, uint32 event_param2, uint32 event_param3, uint32 event_param4, uint32 event_param5, SMART_ACTION action, uint32 action_param1, uint32 action_param2, uint32 action_param3, uint32 action_param4, uint32 action_param5, uint32 action_param6, SMARTAI_TARGETS t, uint32 target_param1, uint32 target_param2, uint32 target_param3, uint32 phaseMask=0)
#define sObjectMgr
Definition: ObjectMgr.h:1317
struct SmartEvent::@125::@143 dataSet
GameObject * ToGameObject()
Definition: Object.h:377
struct SmartEvent::@125::@145 transportAddCreature
struct SmartTarget::@241::@256 raw
DBCStorage< SpellEntry > sSpellStore(SpellEntryfmt)
struct SmartEvent::@125::@134 friendlyHealth
uint32 rangeIndex
Definition: DBCStructure.h:714
void ProcessAction(SmartScriptHolder &e, Unit *unit=NULL, uint32 var0=0, uint32 var1=0, bool bvar=false, const SpellEntry *spell=NULL, GameObject *gob=NULL)
void VisitNearbyObject(float const &radius, NOTIFIER &notifier) const
Definition: Object.h:884
struct SmartEvent::@125::@159 distance
Player * ToPlayer()
Definition: Object.h:368
struct SmartEvent::@125::@129 spellHit
struct SmartAction::@162::@215 unitFlag
uint32 id
SpellSchoolMask GetSpellSchoolMask(SpellEntry const *spellInfo)
Definition: SpellMgr.h:481
struct SmartEvent::@125::@155 goStateChanged
struct SmartAction::@162::@185 killedMonster
struct SmartEvent::@125::@150 timedEvent
SheathState
Definition: Unit.h:220
uint64 GetGUID() const
Definition: Object.h:177
struct SmartAction::@162::@165 faction
uint8 GetTypeId() const
Definition: Object.h:192
void InstallEvents()
bool roll_chance_i(int chance)
Definition: Util.h:67
std::list< WorldObject * > ObjectList
struct SmartEvent::@125::@152 dummy
struct SmartAction::@162::@171 randomEmote
struct SmartAction::@162::@220 randTimedActionList
ACE_UINT8 uint8
Definition: Define.h:73
Powers
float GetOrientation() const
Definition: Position.h:100
void OnInitialize(WorldObject *obj, AreaTriggerEntry const *at=NULL)
Language
Unit * DoSelectLowestHpFriendly(float range, uint32 MinHPDiff)
struct SmartAction::@162::@234 creatureGroup
struct SmartAction::@162::@164 talk
struct SmartAction::@162::@212 timeEvent
struct SmartAction::@162::@183 randomPhase
struct SmartEvent::@125::@157 doAction
struct SmartEvent::@125::@128 kill
void GetScript()
UNORDERED_MAP< uint32, ObjectGuidList * > ObjectListMap
struct SmartAction::@162::@217 delunitByte
struct SmartEvent::@125::@147 instancePlayerEnter
Unit * GetVictim() const
Definition: Unit.h:1013
struct SmartAction::@162::@200 wpStart
float GetPositionY() const
Definition: Position.h:98
virtual void SetData(uint32, uint32)
Definition: ZoneScript.h:61
void CastSpell(Unit *Victim, uint32 spellId, bool triggered, Item *castItem=NULL, Aura *triggeredByAura=NULL, uint64 originalCaster=0)
Definition: Unit.cpp:1260
struct SmartAction::@162::@186 setInstanceData
GameObject * GetClosestGameObjectWithEntry(WorldObject *pSource, uint32 uiEntry, float fMaxSearchRange)
void GetPosition(float &x, float &y) const
Definition: Position.h:102
struct SmartAction::@162::@178 combatMove
void RecalcTimer(SmartScriptHolder &e, uint32 min, uint32 max)
struct SmartTarget::@241::@246 playerDistance
Spell * GetCurrentSpell(CurrentSpellTypes spellType) const
Definition: Unit.h:1593
void ProcessEvent(SmartScriptHolder &e, Unit *unit=NULL, uint32 var0=0, uint32 var1=0, bool bvar=false, const SpellEntry *spell=NULL, GameObject *gob=NULL)
float GetPositionZ() const
Definition: Position.h:99
#define sCreatureTextMgr
SMART_EVENT
struct SmartAction::@162::@211 storeTargets
TempSummonType
struct SmartEvent::@125::@158 friendlyHealthPct
#define sSmartWaypointMgr
Creature * GetClosestCreatureWithEntry(WorldObject *pSource, uint32 uiEntry, float fMaxSearchRange, bool bAlive)
#define sConditionMgr
Definition: ConditionMgr.h:312
struct SmartAction::@162::@214 equip
struct SmartAction::@162::@188 updateTemplate
struct SmartAction::@162::@172 cast
SMART_EVENT type
struct SmartAction::@162::@224 flee
uint32 SchoolMask
Definition: DBCStructure.h:772
struct SmartEvent::@125::@140 aura
void OnMoveInLineOfSight(Unit *who)
struct SmartAction::@162::@189 callHelp
struct SmartAction::@162::@174 threatPCT
void UpdateTimer(SmartScriptHolder &e, uint32 const diff)
struct SmartTarget::@241::@253 closest
ReactStates
Pet&#39;s behavior.
Definition: Unit.h:758
struct SmartAction::@162::@227 sendGossipMenu
struct SmartAction::@162::@239 randomSound
GroupReference * next()
struct SmartTarget::@241::@243 unitRange
Unit * GetLastInvoker()
struct SmartAction::@162::@192 invincHP
CellCoord ComputeCellCoord(float x, float y)
Definition: GridDefines.h:167
struct SmartEvent::@125::@149 textOver
ObjectList * GetWorldObjectsInDist(float dist)
struct SmartEvent::@125::@135 friendlyCC
struct SmartAction::@162::@177 autoAttack
const char * GetName() const
Definition: Object.h:680
Definition: Cell.h:46
bool IsInRange(WorldObject const *obj, float minRange, float maxRange, bool is3D=true) const
Definition: Object.cpp:1322
#define sGameEventMgr
Definition: GameEventMgr.h:179
SmartScriptHolder CreateEvent(SMART_EVENT e, uint32 event_flags, uint32 event_param1, uint32 event_param2, uint32 event_param3, uint32 event_param4, uint32 event_param5, SMART_ACTION action, uint32 action_param1, uint32 action_param2, uint32 action_param3, uint32 action_param4, uint32 action_param5, uint32 action_param6, SMARTAI_TARGETS t, uint32 target_param1, uint32 target_param2, uint32 target_param3, uint32 phaseMask=0)
struct SmartEvent::@125::@161 raw
UNORDERED_MAP< uint32, WayPoint * > WPPath
uint32 GetActionType() const
std::list< HostileReference * > StorageType
struct SmartTarget::@241::@251 goDistance
void SetScript9(SmartScriptHolder &e, uint32 entry)
uint32 GetScriptType() const
struct SmartAction::@162::@170 react
Creature * ToCreature()
Definition: Object.h:371
struct SmartEvent::@125::@137 summoned
void InterruptNonMeleeSpells(bool withDelayed, uint32 spellid=0, bool withInstant=true)
Definition: Unit.cpp:3607
struct SmartTarget::@241::@254 closestAttackable
struct SmartEvent::@125::@160 counter
void ProcessEventsFor(SMART_EVENT e, Unit *unit=NULL, uint32 var0=0, uint32 var1=0, bool bvar=false, const SpellEntry *spell=NULL, GameObject *gob=NULL)
struct SmartAction::@162::@222 sendGoCustomAnim
struct SmartAction::@162::@235 power
struct SmartAction::@162::@173 summonCreature
void DoFindFriendlyCC(std::list< Creature * > &_list, float range)
struct SmartAction::@162::@206 setFly
SmartScriptType source_type
struct SmartAction::@162::@190 setSheath
uint32 GetTargetType() const
static Unit * GetUnit(WorldObject const &, uint64 guid)
struct SmartEvent::@125::@144 waypoint
struct SmartAction::@162::@181 removeAura
uint32 GetEntry() const
Definition: Object.h:186
struct SmartEvent::@125::@153 behindTarget
uint32 event_chance
struct SmartAction::@162::@219 timedActionList
struct SmartAction::@162::@166 morphOrMount
#define MAX_VIRTUAL_ITEM_SLOT
Definition: Creature.h:441
ACE_UINT32 uint32
Definition: Define.h:71
float GetPositionX() const
Definition: Position.h:97
void SetInvincibilityHpLevel(uint32 level)
Definition: SmartAI.h:172
struct SmartAction::@162::@182 follow
struct SmartAction::@162::@240 raw
struct SmartAction::@162::@202 wpStop
Definition: Unit.h:908
struct SmartAction::@162::@233 goFlag
struct SmartAction::@162::@230 setRangedMovement
struct SmartEvent::@125::@133 targetCasting
struct SmartAction::@162::@229 sendTargetToTarget
Definition: Player.h:923
void Visit(CellCoord const &, TypeContainerVisitor< T, CONTAINER > &visitor, Map &, WorldObject const &, float) const
Definition: CellImpl.h:121
struct SmartTarget::@241::@244 unitGUID
DBCStorage< SpellRangeEntry > sSpellRangeStore(SpellRangefmt)
struct SmartAction::@162::@180 incEventPhase
Unit * ToUnit()
Definition: Object.h:374
struct SmartTarget::@241::@247 playerRange
struct SmartEvent::@125::@127 minMaxRepeat
struct SmartEvent::@125::@148 areatrigger
SMARTAI_TARGETS
struct SmartTarget::@241::@255 closestFriendly
struct SmartAction::@162::@207 setSwim
SMART_ACTION type
struct SmartAction::@162::@208 teleport
struct SmartAction::@162::@194 setData
Definition: Group.h:154
struct SmartTarget::@241::@245 unitDistance
#define sSmartScriptMgr
Unit * DoFindClosestFriendlyInRange(float range, bool playerOnly)
uint32 urand(uint32 min, uint32 max)
Definition: Util.cpp:33
static SmartScriptHolder & FindLinkedEvent(SmartAIEventList &list, uint32 link)
uint32 equipentry[3]
Definition: Creature.h:258
InstanceData * GetInstanceData()
Definition: Object.cpp:1212
Definition: Spell.h:249