OregonCore  revision fb2a440-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 <http://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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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
2387  //phase 1: despawn after time on movepoint reached
2389 
2390  if (sCreatureTextMgr->TextExist(me->GetEntry(), (uint8)e.action.installTtemplate.param5))
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, 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, 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, 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, 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, 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, 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, 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, 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.event_phase_mask = phaseMask;
2431  script.event.event_flags = event_flags;
2432  script.event.event_chance = 100;
2433 
2434  script.action.type = action;
2435  script.action.raw.param1 = action_param1;
2436  script.action.raw.param2 = action_param2;
2437  script.action.raw.param3 = action_param3;
2438  script.action.raw.param4 = action_param4;
2439  script.action.raw.param5 = action_param5;
2440  script.action.raw.param6 = action_param6;
2441 
2442  script.target.type = t;
2443  script.target.raw.param1 = target_param1;
2444  script.target.raw.param2 = target_param2;
2445  script.target.raw.param3 = target_param3;
2446 
2448  InitTimer(script);
2449  return script;
2450 }
2451 
2453 {
2454  Unit* scriptTrigger = NULL;
2455  if (invoker)
2456  scriptTrigger = invoker;
2457  else if (Unit* tempLastInvoker = GetLastInvoker())
2458  scriptTrigger = tempLastInvoker;
2459 
2460  WorldObject* baseObject = GetBaseObject();
2461 
2462  ObjectList* l = new ObjectList();
2463  switch (e.GetTargetType())
2464  {
2465  case SMART_TARGET_SELF:
2466  if (baseObject)
2467  l->push_back(baseObject);
2468  break;
2469  case SMART_TARGET_VICTIM:
2470  if (me)
2471  if (Unit* victim = me->GetVictim())
2472  l->push_back(victim);
2473  break;
2475  if (me)
2476  if (Unit* u = me->AI()->SelectTarget(SELECT_TARGET_TOPAGGRO, 1))
2477  l->push_back(u);
2478  break;
2480  if (me)
2481  if (Unit* u = me->AI()->SelectTarget(SELECT_TARGET_BOTTOMAGGRO, 0))
2482  l->push_back(u);
2483  break;
2485  if (me)
2486  if (Unit* u = me->AI()->SelectTarget(SELECT_TARGET_RANDOM, 0))
2487  l->push_back(u);
2488  break;
2490  if (me)
2491  if (Unit* u = me->AI()->SelectTarget(SELECT_TARGET_RANDOM, 1))
2492  l->push_back(u);
2493  break;
2495  if (scriptTrigger)
2496  l->push_back(scriptTrigger);
2497  break;
2499  // no exist in tbc
2500  break;
2502  if (scriptTrigger)
2503  {
2504  if (Player* player = scriptTrigger->ToPlayer())
2505  {
2506  if (Group* group = player->GetGroup())
2507  {
2508  for (GroupReference* groupRef = group->GetFirstMember(); groupRef != NULL; groupRef = groupRef->next())
2509  if (Player* member = groupRef->GetSource())
2510  if (member->IsInMap(player))
2511  l->push_back(member);
2512  }
2513  // We still add the player to the list if there is no group. If we do
2514  // this even if there is a group (thus the else-check), it will add the
2515  // same player to the list twice. We don't want that to happen.
2516  else
2517  l->push_back(scriptTrigger);
2518  }
2519  }
2520  break;
2522  {
2523  // will always return a valid pointer, even if empty list
2524  ObjectList* units = GetWorldObjectsInDist((float)e.target.unitRange.maxDist);
2525  for (ObjectList::const_iterator itr = units->begin(); itr != units->end(); ++itr)
2526  {
2527  if (!IsCreature(*itr))
2528  continue;
2529 
2530  if (me && me->GetGUID() == (*itr)->GetGUID())
2531  continue;
2532 
2533  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)))
2534  l->push_back(*itr);
2535  }
2536 
2537  delete units;
2538  break;
2539  }
2541  {
2542  // will always return a valid pointer, even if empty list
2543  ObjectList* units = GetWorldObjectsInDist((float)e.target.unitDistance.dist);
2544  for (ObjectList::const_iterator itr = units->begin(); itr != units->end(); ++itr)
2545  {
2546  if (!IsCreature(*itr))
2547  continue;
2548 
2549  if (me && me->GetGUID() == (*itr)->GetGUID())
2550  continue;
2551 
2552  if (!e.target.unitDistance.creature || (*itr)->ToCreature()->GetEntry() == e.target.unitDistance.creature)
2553  l->push_back(*itr);
2554  }
2555 
2556  delete units;
2557  break;
2558  }
2560  {
2561  // will always return a valid pointer, even if empty list
2562  ObjectList* units = GetWorldObjectsInDist((float)e.target.goDistance.dist);
2563  for (ObjectList::const_iterator itr = units->begin(); itr != units->end(); ++itr)
2564  {
2565  if (!IsGameObject(*itr))
2566  continue;
2567 
2568  if (go && go->GetGUID() == (*itr)->GetGUID())
2569  continue;
2570 
2571  if (!e.target.goDistance.entry || (*itr)->ToGameObject()->GetEntry() == e.target.goDistance.entry)
2572  l->push_back(*itr);
2573  }
2574 
2575  delete units;
2576  break;
2577  }
2579  {
2580  // will always return a valid pointer, even if empty list
2581  ObjectList* units = GetWorldObjectsInDist((float)e.target.goRange.maxDist);
2582  for (ObjectList::const_iterator itr = units->begin(); itr != units->end(); ++itr)
2583  {
2584  if (!IsGameObject(*itr))
2585  continue;
2586 
2587  if (go && go->GetGUID() == (*itr)->GetGUID())
2588  continue;
2589 
2590  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)))
2591  l->push_back(*itr);
2592  }
2593 
2594  delete units;
2595  break;
2596  }
2598  {
2599  if (!scriptTrigger && !baseObject)
2600  {
2601  sLog.outError("SMART_TARGET_CREATURE_GUID can not be used without invoker");
2602  break;
2603  }
2604 
2605  if (Creature* target = FindCreatureNear(scriptTrigger ? scriptTrigger : baseObject, e.target.unitGUID.dbGuid))
2606  if (!e.target.unitGUID.entry || target->GetEntry() == e.target.unitGUID.entry)
2607  l->push_back(target);
2608  break;
2609  }
2611  {
2612  if (!scriptTrigger && !baseObject)
2613  {
2614  sLog.outError("SMART_TARGET_GAMEOBJECT_GUID can not be used without invoker");
2615  break;
2616  }
2617 
2618  if (GameObject* target = FindGameObjectNear(scriptTrigger ? scriptTrigger : baseObject, e.target.goGUID.dbGuid))
2619  if (!e.target.goGUID.entry || target->GetEntry() == e.target.goGUID.entry)
2620  l->push_back(target);
2621  break;
2622  }
2624  {
2625  // will always return a valid pointer, even if empty list
2626  ObjectList* units = GetWorldObjectsInDist((float)e.target.playerRange.maxDist);
2627  if (!units->empty() && baseObject)
2628  for (ObjectList::const_iterator itr = units->begin(); itr != units->end(); ++itr)
2629  if (IsPlayer(*itr) && baseObject->IsInRange(*itr, (float)e.target.playerRange.minDist, (float)e.target.playerRange.maxDist))
2630  l->push_back(*itr);
2631 
2632  delete units;
2633  break;
2634  }
2636  {
2637  // will always return a valid pointer, even if empty list
2638  ObjectList* units = GetWorldObjectsInDist((float)e.target.playerDistance.dist);
2639  for (ObjectList::const_iterator itr = units->begin(); itr != units->end(); ++itr)
2640  if (IsPlayer(*itr))
2641  l->push_back(*itr);
2642 
2643  delete units;
2644  break;
2645  }
2646  case SMART_TARGET_STORED:
2647  {
2648  ObjectListMap::iterator itr = mTargetStorage->find(e.target.stored.id);
2649  if (itr != mTargetStorage->end())
2650  {
2651  ObjectList* objectList = itr->second->GetObjectList();
2652  l->assign(objectList->begin(), objectList->end());
2653  }
2654 
2655  return l;
2656  }
2658  {
2659  if (Creature* target = GetClosestCreatureWithEntry(baseObject, e.target.closest.entry, float(e.target.closest.dist ? e.target.closest.dist : 100), !e.target.closest.dead))
2660  l->push_back(target);
2661  break;
2662  }
2664  {
2665  if (GameObject* target = GetClosestGameObjectWithEntry(baseObject, e.target.closest.entry, float(e.target.closest.dist ? e.target.closest.dist : 100)))
2666  l->push_back(target);
2667  break;
2668  }
2670  {
2671  if (me)
2672  if (Player* target = me->SelectNearestPlayer(float(e.target.playerDistance.dist)))
2673  l->push_back(target);
2674  break;
2675  }
2677  {
2678  if (me)
2679  {
2680  ObjectGuid charmerOrOwnerGuid = me->GetCharmerOrOwnerGUID();
2681 
2682  if (!charmerOrOwnerGuid)
2683  charmerOrOwnerGuid = me->GetCreatorGUID();
2684 
2685  if (Unit* owner = ObjectAccessor::GetUnit(*me, charmerOrOwnerGuid))
2686  l->push_back(owner);
2687  }
2688  break;
2689  }
2691  {
2692  if (me)
2693  {
2694  ThreatContainer::StorageType threatList = me->getThreatManager().getThreatList();
2695  for (ThreatContainer::StorageType::const_iterator i = threatList.begin(); i != threatList.end(); ++i)
2696  if (Unit* temp = ObjectAccessor::GetUnit(*me, (*i)->getUnitGuid()))
2697  l->push_back(temp);
2698  }
2699  break;
2700  }
2702  {
2703  if (me)
2704  if (Unit* target = me->SelectNearestTarget(e.target.closestAttackable.maxDist, e.target.closestAttackable.playerOnly != 0))
2705  l->push_back(target);
2706  break;
2707  }
2709  {
2710  if (me)
2711  if (Unit* target = DoFindClosestFriendlyInRange(e.target.closestFriendly.maxDist, e.target.closestFriendly.playerOnly != 0))
2712  l->push_back(target);
2713  break;
2714  }
2715  case SMART_TARGET_POSITION:
2716  case SMART_TARGET_NONE:
2717  default:
2718  break;
2719  }
2720 
2721  if (l->empty())
2722  {
2723  delete l;
2724  l = NULL;
2725  }
2726 
2727  return l;
2728 }
2729 
2731 {
2732  ObjectList* targets = new ObjectList();
2733  WorldObject* obj = GetBaseObject();
2734 
2735  if (obj)
2736  {
2737  Oregon::AllWorldObjectsInRange u_check(obj, dist);
2738  Oregon::WorldObjectListSearcher<Oregon::AllWorldObjectsInRange> searcher(obj, *targets, u_check);
2739  obj->VisitNearbyObject(dist, searcher);
2740  }
2741  return targets;
2742 }
2743 
2744 void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, uint32 var1, bool bvar, const SpellEntry* spell, GameObject* gob)
2745 {
2746  if (!e.active && e.GetEventType() != SMART_EVENT_LINK)
2747  return;
2748 
2750  return;
2751 
2752  switch (e.GetEventType())
2753  {
2754  case SMART_EVENT_LINK://special handling
2755  ProcessAction(e, unit, var0, var1, bvar, spell, gob);
2756  break;
2757  //called from Update tick
2758  case SMART_EVENT_UPDATE:
2759  ProcessTimedAction(e, e.event.minMaxRepeat.repeatMin, e.event.minMaxRepeat.repeatMax);
2760  break;
2762  if (me && me->IsInCombat())
2763  return;
2764  ProcessTimedAction(e, e.event.minMaxRepeat.repeatMin, e.event.minMaxRepeat.repeatMax);
2765  break;
2766  case SMART_EVENT_UPDATE_IC:
2767  if (!me || !me->IsInCombat())
2768  return;
2769  ProcessTimedAction(e, e.event.minMaxRepeat.repeatMin, e.event.minMaxRepeat.repeatMax);
2770  break;
2771  case SMART_EVENT_HEALT_PCT:
2772  {
2773  if (!me || !me->IsInCombat() || !me->GetMaxHealth())
2774  return;
2775  uint32 perc = (uint32)me->GetHealthPct();
2776  if (perc > e.event.minMaxRepeat.max || perc < e.event.minMaxRepeat.min)
2777  return;
2778  ProcessTimedAction(e, e.event.minMaxRepeat.repeatMin, e.event.minMaxRepeat.repeatMax);
2779  break;
2780  }
2782  {
2783  if (!me || !me->IsInCombat() || !me->GetVictim() || !me->GetVictim()->GetMaxHealth())
2784  return;
2785  uint32 perc = (uint32)me->GetVictim()->GetHealthPct();
2786  if (perc > e.event.minMaxRepeat.max || perc < e.event.minMaxRepeat.min)
2787  return;
2788  ProcessTimedAction(e, e.event.minMaxRepeat.repeatMin, e.event.minMaxRepeat.repeatMax, me->GetVictim());
2789  break;
2790  }
2791  case SMART_EVENT_MANA_PCT:
2792  {
2793  if (!me || !me->IsInCombat() || !me->GetMaxPower(POWER_MANA))
2794  return;
2795  uint32 perc = uint32(100.0f * me->GetPower(POWER_MANA) / me->GetMaxPower(POWER_MANA));
2796  if (perc > e.event.minMaxRepeat.max || perc < e.event.minMaxRepeat.min)
2797  return;
2798  ProcessTimedAction(e, e.event.minMaxRepeat.repeatMin, e.event.minMaxRepeat.repeatMax);
2799  break;
2800  }
2802  {
2803  if (!me || !me->IsInCombat() || !me->GetVictim() || !me->GetVictim()->GetMaxPower(POWER_MANA))
2804  return;
2805  uint32 perc = uint32(100.0f * me->GetVictim()->GetPower(POWER_MANA) / me->GetVictim()->GetMaxPower(POWER_MANA));
2806  if (perc > e.event.minMaxRepeat.max || perc < e.event.minMaxRepeat.min)
2807  return;
2808  ProcessTimedAction(e, e.event.minMaxRepeat.repeatMin, e.event.minMaxRepeat.repeatMax, me->GetVictim());
2809  break;
2810  }
2811  case SMART_EVENT_RANGE:
2812  {
2813  if (!me || !me->IsInCombat() || !me->GetVictim())
2814  return;
2815 
2816  if (me->IsInRange(me->GetVictim(), (float)e.event.minMaxRepeat.min, (float)e.event.minMaxRepeat.max))
2817  ProcessTimedAction(e, e.event.minMaxRepeat.repeatMin, e.event.minMaxRepeat.repeatMax, me->GetVictim());
2818  break;
2819  }
2821  {
2822  if (!me || !me->IsInCombat())
2823  return;
2824 
2825  Unit* victim = me->GetVictim();
2826 
2827  if (!victim || !victim->IsNonMeleeSpellCast(false, false, true))
2828  return;
2829 
2830  if (e.event.targetCasting.spellId > 0)
2831  if (Spell* currSpell = victim->GetCurrentSpell(CURRENT_GENERIC_SPELL))
2832  if (currSpell->m_spellInfo->Id != e.event.targetCasting.spellId)
2833  return;
2834 
2835  ProcessTimedAction(e, e.event.targetCasting.repeatMin, e.event.targetCasting.repeatMax, me->GetVictim());
2836  break;
2837  }
2839  {
2840  if (!me || !me->IsInCombat())
2841  return;
2842 
2843  Unit* target = DoSelectLowestHpFriendly((float)e.event.friendlyHealth.radius, e.event.friendlyHealth.hpDeficit);
2844  if (!target || !target->IsInCombat())
2845  return;
2846  ProcessTimedAction(e, e.event.friendlyHealth.repeatMin, e.event.friendlyHealth.repeatMax, target);
2847  break;
2848  }
2850  {
2851  if (!me || !me->IsInCombat())
2852  return;
2853 
2854  std::list<Creature*> pList;
2855  DoFindFriendlyCC(pList, (float)e.event.friendlyCC.radius);
2856  if (pList.empty())
2857  return;
2858  ProcessTimedAction(e, e.event.friendlyCC.repeatMin, e.event.friendlyCC.repeatMax, *pList.begin());
2859  break;
2860  }
2862  {
2863  std::list<Creature*> pList;
2864  DoFindFriendlyMissingBuff(pList, (float)e.event.missingBuff.radius, e.event.missingBuff.spell);
2865 
2866  if (pList.empty())
2867  return;
2868 
2869  ProcessTimedAction(e, e.event.missingBuff.repeatMin, e.event.missingBuff.repeatMax, *pList.begin());
2870  break;
2871  }
2872  case SMART_EVENT_HAS_AURA:
2873  {
2874  if (!me)
2875  return;
2876  uint32 count = me->GetAuraCount(e.event.aura.spell);
2877  if ((!e.event.aura.count && !count) || (e.event.aura.count && count >= e.event.aura.count))
2878  ProcessTimedAction(e, e.event.aura.repeatMin, e.event.aura.repeatMax);
2879  break;
2880  }
2882  {
2883  if (!me || !me->GetVictim())
2884  return;
2885  uint32 count = me->GetVictim()->GetAuraCount(e.event.aura.spell);
2886  if (count < e.event.aura.count)
2887  return;
2888  ProcessTimedAction(e, e.event.aura.repeatMin, e.event.aura.repeatMax);
2889  break;
2890  }
2891  //no params
2892  case SMART_EVENT_AGGRO:
2893  case SMART_EVENT_DEATH:
2894  case SMART_EVENT_EVADE:
2896  case SMART_EVENT_CHARMED:
2899  case SMART_EVENT_AI_INIT:
2908  case SMART_EVENT_RESET:
2913  ProcessAction(e, unit, var0, var1, bvar, spell, gob);
2914  break;
2916  {
2917  if (!me)
2918  return;
2919 
2920  if (Unit* victim = me->GetVictim())
2921  {
2922  if (!victim->HasInArc(static_cast<float>(M_PI), me))
2923  ProcessTimedAction(e, e.event.behindTarget.cooldownMin, e.event.behindTarget.cooldownMax, victim);
2924  }
2925  break;
2926  }
2928  if (e.event.emote.emote == var0)
2929  {
2930  RecalcTimer(e, e.event.emote.cooldownMin, e.event.emote.cooldownMax);
2931  ProcessAction(e, unit);
2932  }
2933  break;
2934  case SMART_EVENT_KILL:
2935  {
2936  if (!me || !unit)
2937  return;
2938  if (e.event.kill.playerOnly && unit->GetTypeId() != TYPEID_PLAYER)
2939  return;
2940  if (e.event.kill.creature && unit->GetEntry() != e.event.kill.creature)
2941  return;
2942  RecalcTimer(e, e.event.kill.cooldownMin, e.event.kill.cooldownMax);
2943  ProcessAction(e, unit);
2944  break;
2945  }
2947  case SMART_EVENT_SPELLHIT:
2948  {
2949  if (!spell)
2950  return;
2951  if ((!e.event.spellHit.spell || spell->Id == e.event.spellHit.spell) &&
2952  (!e.event.spellHit.school || (spell->SchoolMask & e.event.spellHit.school)))
2953  {
2954  RecalcTimer(e, e.event.spellHit.cooldownMin, e.event.spellHit.cooldownMax);
2955  ProcessAction(e, unit, 0, 0, bvar, spell);
2956  }
2957  break;
2958  }
2959  case SMART_EVENT_OOC_LOS:
2960  {
2961  if (!me || me->IsInCombat())
2962  return;
2963  //can trigger if closer than fMaxAllowedRange
2964  float range = (float)e.event.los.maxDist;
2965 
2966  //if range is ok and we are actually in LOS
2967  if (me->IsWithinDistInMap(unit, range) && me->IsWithinLOSInMap(unit))
2968  {
2969  //if friendly event&&who is not hostile OR hostile event&&who is hostile
2970  if ((e.event.los.noHostile && !me->IsHostileTo(unit)) ||
2971  (!e.event.los.noHostile && me->IsHostileTo(unit)))
2972  {
2973  RecalcTimer(e, e.event.los.cooldownMin, e.event.los.cooldownMax);
2974  ProcessAction(e, unit);
2975  }
2976  }
2977  break;
2978  }
2979  case SMART_EVENT_IC_LOS:
2980  {
2981  if (!me || !me->IsInCombat())
2982  return;
2983  //can trigger if closer than fMaxAllowedRange
2984  float range = (float)e.event.los.maxDist;
2985 
2986  //if range is ok and we are actually in LOS
2987  if (me->IsWithinDistInMap(unit, range) && me->IsWithinLOSInMap(unit))
2988  {
2989  //if friendly event&&who is not hostile OR hostile event&&who is hostile
2990  if ((e.event.los.noHostile && !me->IsHostileTo(unit)) ||
2991  (!e.event.los.noHostile && me->IsHostileTo(unit)))
2992  {
2993  RecalcTimer(e, e.event.los.cooldownMin, e.event.los.cooldownMax);
2994  ProcessAction(e, unit);
2995  }
2996  }
2997  break;
2998  }
2999  case SMART_EVENT_RESPAWN:
3000  {
3001  if (!GetBaseObject())
3002  return;
3003  if (e.event.respawn.type == SMART_SCRIPT_RESPAWN_CONDITION_MAP && GetBaseObject()->GetMapId() != e.event.respawn.map)
3004  return;
3005  if (e.event.respawn.type == SMART_SCRIPT_RESPAWN_CONDITION_AREA && GetBaseObject()->GetZoneId() != e.event.respawn.area)
3006  return;
3007  ProcessAction(e);
3008  break;
3009  }
3011  {
3012  if (!IsCreature(unit))
3013  return;
3014  if (e.event.summoned.creature && unit->GetEntry() != e.event.summoned.creature)
3015  return;
3016  RecalcTimer(e, e.event.summoned.cooldownMin, e.event.summoned.cooldownMax);
3017  ProcessAction(e, unit);
3018  break;
3019  }
3021  case SMART_EVENT_DAMAGED:
3023  {
3024  if (var0 > e.event.minMaxRepeat.max || var0 < e.event.minMaxRepeat.min)
3025  return;
3026  RecalcTimer(e, e.event.minMaxRepeat.repeatMin, e.event.minMaxRepeat.repeatMax);
3027  ProcessAction(e, unit);
3028  break;
3029  }
3031  {
3032  if ((e.event.movementInform.type && var0 != e.event.movementInform.type) || (e.event.movementInform.id && var1 != e.event.movementInform.id))
3033  return;
3034  ProcessAction(e, unit, var0, var1);
3035  break;
3036  }
3039  {
3040  if (e.event.waypoint.pathID && var0 != e.event.waypoint.pathID)
3041  return;
3042  ProcessAction(e, unit, var0);
3043  break;
3044  }
3050  {
3051  if (!me || (e.event.waypoint.pointID && var0 != e.event.waypoint.pointID) || (e.event.waypoint.pathID && GetPathId() != e.event.waypoint.pathID))
3052  return;
3053  ProcessAction(e, unit);
3054  break;
3055  }
3058  {
3059  if (e.event.instancePlayerEnter.team && var0 != e.event.instancePlayerEnter.team)
3060  return;
3061  RecalcTimer(e, e.event.instancePlayerEnter.cooldownMin, e.event.instancePlayerEnter.cooldownMax);
3062  ProcessAction(e, unit, var0);
3063  break;
3064  }
3067  {
3068  if (e.event.quest.quest && var0 != e.event.quest.quest)
3069  return;
3070  ProcessAction(e, unit, var0);
3071  break;
3072  }
3074  {
3075  if (e.event.transportAddCreature.creature && var0 != e.event.transportAddCreature.creature)
3076  return;
3077  ProcessAction(e, unit, var0);
3078  break;
3079  }
3081  {
3082  if (e.event.areatrigger.id && var0 != e.event.areatrigger.id)
3083  return;
3084  ProcessAction(e, unit, var0);
3085  break;
3086  }
3087  case SMART_EVENT_TEXT_OVER:
3088  {
3089  if (var0 != e.event.textOver.textGroupID || (e.event.textOver.creatureEntry && e.event.textOver.creatureEntry != var1))
3090  return;
3091  ProcessAction(e, unit, var0);
3092  break;
3093  }
3094  case SMART_EVENT_DATA_SET:
3095  {
3096  if (e.event.dataSet.id != var0 || e.event.dataSet.value != var1)
3097  return;
3098  RecalcTimer(e, e.event.dataSet.cooldownMin, e.event.dataSet.cooldownMax);
3099  ProcessAction(e, unit, var0, var1);
3100  break;
3101  }
3104  {
3105  if (!unit)
3106  return;
3107  RecalcTimer(e, e.event.minMax.repeatMin, e.event.minMax.repeatMax);
3108  ProcessAction(e, unit);
3109  break;
3110  }
3112  {
3113  if (e.event.timedEvent.id == var0)
3114  ProcessAction(e, unit);
3115  break;
3116  }
3118  {
3119  sLog.outDebug("SmartScript: Gossip Select: menu %u action %u", var0, var1);//little help for scripters
3120  if (e.event.gossip.sender != var0 || e.event.gossip.action != var1)
3121  return;
3122  ProcessAction(e, unit, var0, var1);
3123  break;
3124  }
3126  {
3127  if (e.event.dummy.spell != var0 || e.event.dummy.effIndex != var1)
3128  return;
3129  ProcessAction(e, unit, var0, var1);
3130  break;
3131  }
3134  {
3135  if (e.event.gameEvent.gameEventId != var0)
3136  return;
3137  ProcessAction(e, NULL, var0);
3138  break;
3139  }
3141  {
3142  if (e.event.goStateChanged.state != var0)
3143  return;
3144  ProcessAction(e, unit, var0, var1);
3145  break;
3146  }
3148  {
3149  if (e.event.eventInform.eventId != var0)
3150  return;
3151  ProcessAction(e, NULL, var0);
3152  break;
3153  }
3155  {
3156  if (e.event.doAction.eventId != var0)
3157  return;
3158  ProcessAction(e, unit, var0);
3159  break;
3160  }
3162  {
3163  if (!me || !me->IsInCombat())
3164  return;
3165 
3166  ObjectList* _targets = NULL;
3167 
3168  switch (e.GetTargetType())
3169  {
3177  _targets = GetTargets(e);
3178  break;
3179  default:
3180  return;
3181  }
3182 
3183  if (!_targets)
3184  return;
3185 
3186  Unit* target = NULL;
3187 
3188  for (ObjectList::const_iterator itr = _targets->begin(); itr != _targets->end(); ++itr)
3189  {
3190  if (IsUnit(*itr) && me->IsFriendlyTo((*itr)->ToUnit()) && (*itr)->ToUnit()->IsAlive() && (*itr)->ToUnit()->IsInCombat())
3191  {
3192  uint32 healthPct = uint32((*itr)->ToUnit()->GetHealthPct());
3193 
3194  if (healthPct > e.event.friendlyHealthPct.maxHpPct || healthPct < e.event.friendlyHealthPct.minHpPct)
3195  continue;
3196 
3197  target = (*itr)->ToUnit();
3198  break;
3199  }
3200  }
3201 
3202  delete _targets;
3203 
3204  if (!target)
3205  return;
3206 
3207  ProcessTimedAction(e, e.event.friendlyHealthPct.repeatMin, e.event.friendlyHealthPct.repeatMax, target);
3208  break;
3209  }
3211  {
3212  if (!me)
3213  return;
3214 
3215  WorldObject* creature = NULL;
3216 
3217  if (e.event.distance.guid != 0)
3218  {
3219  creature = FindCreatureNear(me, e.event.distance.guid);
3220 
3221  if (!creature)
3222  return;
3223 
3224  if (!me->IsInRange(creature, 0, (float)e.event.distance.dist))
3225  return;
3226  }
3227  else if (e.event.distance.entry != 0)
3228  {
3229  std::list<Creature*> list;
3230  me->GetCreatureListWithEntryInGrid(list, e.event.distance.entry, (float)e.event.distance.dist);
3231 
3232  if (!list.empty())
3233  creature = list.front();
3234  }
3235 
3236  if (creature)
3237  ProcessTimedAction(e, e.event.distance.repeat, e.event.distance.repeat);
3238 
3239  break;
3240  }
3242  {
3243  if (!me)
3244  return;
3245 
3246  WorldObject* gameobject = NULL;
3247 
3248  if (e.event.distance.guid != 0)
3249  {
3250  gameobject = FindGameObjectNear(me, e.event.distance.guid);
3251 
3252  if (!gameobject)
3253  return;
3254 
3255  if (!me->IsInRange(gameobject, 0, (float)e.event.distance.dist))
3256  return;
3257  }
3258  else if (e.event.distance.entry != 0)
3259  {
3260  std::list<GameObject*> list;
3261  me->GetGameObjectListWithEntryInGrid(list, e.event.distance.entry, (float)e.event.distance.dist);
3262 
3263  if (!list.empty())
3264  gameobject = list.front();
3265  }
3266 
3267  if (gameobject)
3268  ProcessTimedAction(e, e.event.distance.repeat, e.event.distance.repeat);
3269 
3270  break;
3271  }
3273  if (GetCounterId(e.event.counter.id) != 0 && GetCounterValue(e.event.counter.id) == e.event.counter.value)
3274  ProcessTimedAction(e, e.event.counter.cooldownMin, e.event.counter.cooldownMax);
3275  break;
3276  default:
3277  sLog.outError("SmartScript::ProcessEvent: Unhandled Event type %u", e.GetEventType());
3278  break;
3279  }
3280 }
3281 
3283 {
3284  switch (e.GetEventType())
3285  {
3286  //set only events which have initial timers
3287  case SMART_EVENT_UPDATE:
3288  case SMART_EVENT_UPDATE_IC:
3290  RecalcTimer(e, e.event.minMaxRepeat.min, e.event.minMaxRepeat.max);
3291  break;
3294  RecalcTimer(e, e.event.distance.repeat, e.event.distance.repeat);
3295  break;
3296  default:
3297  e.active = true;
3298  break;
3299  }
3300 }
3302 {
3303  // min/max was checked at loading!
3304  e.timer = urand(min, max);
3305  e.active = e.timer ? false : true;
3306 }
3307 
3309 {
3310  if (e.GetEventType() == SMART_EVENT_LINK)
3311  return;
3312 
3313  if (e.event.event_phase_mask && !IsInPhase(e.event.event_phase_mask))
3314  return;
3315 
3316  if (e.GetEventType() == SMART_EVENT_UPDATE_IC && (!me || !me->IsInCombat()))
3317  return;
3318 
3319  if (e.GetEventType() == SMART_EVENT_UPDATE_OOC && (me && me->IsInCombat())) //can be used with me=NULL (go script)
3320  return;
3321 
3322  if (e.timer < diff)
3323  {
3324  // delay spell cast event if another spell is being cast
3325  if (e.GetActionType() == SMART_ACTION_CAST)
3326  {
3327  if (!(e.action.cast.flags & SMARTCAST_INTERRUPT_PREVIOUS))
3328  {
3329  if (me && me->HasUnitState(UNIT_STATE_CASTING))
3330  {
3331  e.timer = 1;
3332  return;
3333  }
3334  }
3335  }
3336 
3337  // Delay flee for assist event if stunned or rooted
3339  {
3340  if (me && me->HasUnitState(UNIT_STATE_ROOT | UNIT_STATE_STUNNED))
3341  {
3342  e.timer = 1;
3343  return;
3344  }
3345  }
3346 
3347  e.active = true;//activate events with cooldown
3348  switch (e.GetEventType())//process ONLY timed events
3349  {
3350  case SMART_EVENT_UPDATE:
3352  case SMART_EVENT_UPDATE_IC:
3353  case SMART_EVENT_HEALT_PCT:
3355  case SMART_EVENT_MANA_PCT:
3357  case SMART_EVENT_RANGE:
3362  case SMART_EVENT_HAS_AURA:
3368  {
3369  ProcessEvent(e);
3371  {
3372  e.enableTimed = false;//disable event if it is in an ActionList and was processed once
3373  for (SmartAIEventList::iterator i = mTimedActionList.begin(); i != mTimedActionList.end(); ++i)
3374  {
3375  //find the first event which is not the current one and enable it
3376  if (i->event_id > e.event_id)
3377  {
3378  i->enableTimed = true;
3379  break;
3380  }
3381  }
3382  }
3383  break;
3384  }
3385  }
3386  }
3387  else
3388  e.timer -= diff;
3389 }
3390 
3392 {
3393  return e.active;
3394 }
3395 
3397 {
3398  if (!mInstallEvents.empty())
3399  {
3400  for (SmartAIEventList::iterator i = mInstallEvents.begin(); i != mInstallEvents.end(); ++i)
3401  mEvents.push_back(*i);//must be before UpdateTimers
3402 
3403  mInstallEvents.clear();
3404  }
3405 }
3406 
3408 {
3409  if ((mScriptType == SMART_SCRIPT_TYPE_CREATURE || mScriptType == SMART_SCRIPT_TYPE_GAMEOBJECT) && !GetBaseObject())
3410  return;
3411 
3412  InstallEvents();//before UpdateTimers
3413 
3414  for (SmartAIEventList::iterator i = mEvents.begin(); i != mEvents.end(); ++i)
3415  UpdateTimer(*i, diff);
3416 
3417  if (!mStoredEvents.empty())
3418  for (SmartAIEventList::iterator i = mStoredEvents.begin(); i != mStoredEvents.end(); ++i)
3419  UpdateTimer(*i, diff);
3420 
3421  bool needCleanup = true;
3422  if (!mTimedActionList.empty())
3423  {
3424  isProcessingTimedActionList = true;
3425  for (SmartAIEventList::iterator i = mTimedActionList.begin(); i != mTimedActionList.end(); ++i)
3426  {
3427  if ((*i).enableTimed)
3428  {
3429  UpdateTimer(*i, diff);
3430  needCleanup = false;
3431  }
3432  }
3433 
3434  isProcessingTimedActionList = false;
3435  }
3436  if (needCleanup)
3437  mTimedActionList.clear();
3438 
3439  if (!mRemIDs.empty())
3440  {
3441  for (std::list<uint32>::iterator i = mRemIDs.begin(); i != mRemIDs.end(); ++i)
3442  {
3443  RemoveStoredEvent((*i));
3444  }
3445  }
3446  if (mUseTextTimer && me)
3447  {
3448  if (mTextTimer < diff)
3449  {
3450  uint32 textID = mLastTextID;
3451  mLastTextID = 0;
3452  uint32 entry = mTalkerEntry;
3453  mTalkerEntry = 0;
3454  mTextTimer = 0;
3455  mUseTextTimer = false;
3456  ProcessEventsFor(SMART_EVENT_TEXT_OVER, NULL, textID, entry);
3457  } else mTextTimer -= diff;
3458  }
3459 }
3460 
3462 {
3463  if (e.empty())
3464  {
3465  if (obj)
3466  sLog.outDebug("SmartScript: EventMap for Entry %u is empty but is using SmartScript.", obj->GetEntry());
3467  if (at)
3468  sLog.outDebug("SmartScript: EventMap for AreaTrigger %u is empty but is using SmartScript.", at->id);
3469  return;
3470  }
3471  for (SmartAIEventList::iterator i = e.begin(); i != e.end(); ++i)
3472  {
3473  #ifndef TRINITY_DEBUG
3474  if ((*i).event.event_flags & SMART_EVENT_FLAG_DEBUG_ONLY)
3475  continue;
3476  #endif
3477 
3478  if ((*i).event.event_flags & SMART_EVENT_FLAG_DIFFICULTY_ALL)//if has instance flag add only if in it
3479  {
3480  if (obj && obj->GetMap()->IsDungeon())
3481  {
3482  if ((1 << (obj->GetMap()->GetSpawnMode()+1)) & (*i).event.event_flags)
3483  {
3484  mEvents.push_back((*i));
3485  }
3486  }
3487  continue;
3488  }
3489  mEvents.push_back((*i));//NOTE: 'world(0)' events still get processed in ANY instance mode
3490  }
3491 }
3492 
3494 {
3495  SmartAIEventList e;
3496  if (me)
3497  {
3498  e = sSmartScriptMgr->GetScript(-((int32)me->GetDBTableGUIDLow()), mScriptType);
3499  if (e.empty())
3500  e = sSmartScriptMgr->GetScript((int32)me->GetEntry(), mScriptType);
3501  FillScript(e, me, NULL);
3502  }
3503  else if (go)
3504  {
3505  e = sSmartScriptMgr->GetScript(-((int32)go->GetDBTableGUIDLow()), mScriptType);
3506  if (e.empty())
3507  e = sSmartScriptMgr->GetScript((int32)go->GetEntry(), mScriptType);
3508  FillScript(e, go, NULL);
3509  }
3510  else if (trigger)
3511  {
3512  e = sSmartScriptMgr->GetScript((int32)trigger->id, mScriptType);
3513  FillScript(e, NULL, trigger);
3514  }
3515 }
3516 
3518 {
3519  if (obj)//handle object based scripts
3520  {
3521  switch (obj->GetTypeId())
3522  {
3523  case TYPEID_UNIT:
3524  mScriptType = SMART_SCRIPT_TYPE_CREATURE;
3525  me = obj->ToCreature();
3526  sLog.outDebug("SmartScript::OnInitialize: source is Creature %u", me->GetEntry());
3527  break;
3528  case TYPEID_GAMEOBJECT:
3529  mScriptType = SMART_SCRIPT_TYPE_GAMEOBJECT;
3530  go = obj->ToGameObject();
3531  sLog.outDebug("SmartScript::OnInitialize: source is GameObject %u", go->GetEntry());
3532  break;
3533  default:
3534  sLog.outError("SmartScript::OnInitialize: Unhandled TypeID !WARNING!");
3535  return;
3536  }
3537  } else if (at)
3538  {
3539  mScriptType = SMART_SCRIPT_TYPE_AREATRIGGER;
3540  trigger = at;
3541  sLog.outDebug("SmartScript::OnInitialize: source is AreaTrigger %u", trigger->id);
3542  }
3543  else
3544  {
3545  sLog.outError("SmartScript::OnInitialize: !WARNING! Initialized objects are NULL.");
3546  return;
3547  }
3548 
3549  GetScript();//load copy of script
3550 
3551  for (SmartAIEventList::iterator i = mEvents.begin(); i != mEvents.end(); ++i)
3552  InitTimer((*i));//calculate timers for first time use
3553 
3554  ProcessEventsFor(SMART_EVENT_AI_INIT);
3555  InstallEvents();
3556  ProcessEventsFor(SMART_EVENT_JUST_CREATED);
3557 }
3558 
3560 {
3561  if (!me)
3562  return;
3563 
3564  ProcessEventsFor(me->IsInCombat() ? SMART_EVENT_IC_LOS : SMART_EVENT_OOC_LOS, who);
3565 }
3566 
3567 /*
3568 void SmartScript::UpdateAIWhileCharmed(const uint32 diff) { }
3569 
3570 void SmartScript::DoAction(const int32 param) { }
3571 
3572 uint32 SmartScript::GetData(uint32 id)
3573 {
3574  return 0;
3575 }
3576 
3577 void SmartScript::SetData(uint32 id, uint32 value) { }
3578 
3579 void SmartScript::SetGUID(uint64 guid, int32 id) { }
3580 
3581 uint64 SmartScript::GetGUID(int32 id)
3582 {
3583  return 0;
3584 }
3585 
3586 void SmartScript::MovepointStart(uint32 id) { }
3587 
3588 void SmartScript::SetRun(bool run) { }
3589 
3590 void SmartScript::SetMovePathEndAction(SMART_ACTION action) { }
3591 
3592 uint32 SmartScript::DoChat(int8 id, uint64 whisperGuid)
3593 {
3594  return 0;
3595 }*/
3596 // SmartScript end
3597 
3599 {
3600  if (!me)
3601  return NULL;
3602 
3603  CellCoord p(Oregon::ComputeCellCoord(me->GetPositionX(), me->GetPositionY()));
3604  Cell cell(p);
3605  cell.SetNoCreate();
3606 
3607  Unit* unit = NULL;
3608 
3609  Oregon::MostHPMissingInRange u_check(me, range, MinHPDiff);
3610  Oregon::UnitLastSearcher<Oregon::MostHPMissingInRange> searcher(me, unit, u_check);
3611 
3613 
3614  cell.Visit(p, grid_unit_searcher, *me->GetMap(), *me, range);
3615  return unit;
3616 }
3617 
3618 void SmartScript::DoFindFriendlyCC(std::list<Creature*>& _list, float range)
3619 {
3620  if (!me)
3621  return;
3622 
3623  CellCoord p(Oregon::ComputeCellCoord(me->GetPositionX(), me->GetPositionY()));
3624  Cell cell(p);
3625  cell.SetNoCreate();
3626 
3627  Oregon::FriendlyCCedInRange u_check(me, range);
3628  Oregon::CreatureListSearcher<Oregon::FriendlyCCedInRange> searcher(me, _list, u_check);
3629 
3631 
3632  cell.Visit(p, grid_creature_searcher, *me->GetMap(), *me, range);
3633 }
3634 
3635 void SmartScript::DoFindFriendlyMissingBuff(std::list<Creature*>& list, float range, uint32 spellid)
3636 {
3637  if (!me)
3638  return;
3639 
3640  CellCoord p(Oregon::ComputeCellCoord(me->GetPositionX(), me->GetPositionY()));
3641  Cell cell(p);
3642  cell.SetNoCreate();
3643 
3644  Oregon::FriendlyMissingBuffInRange u_check(me, range, spellid);
3646 
3648 
3649  cell.Visit(p, grid_creature_searcher, *me->GetMap(), *me, range);
3650 }
3651 
3652 Unit* SmartScript::DoFindClosestFriendlyInRange(float range, bool playerOnly)
3653 {
3654  if (!me)
3655  return NULL;
3656 
3657  Unit* unit = NULL;
3658  Oregon::AnyFriendlyUnitInObjectRangeCheck u_check(me, me, range, playerOnly);
3660  me->VisitNearbyObject(range, searcher);
3661  return unit;
3662 }
3663 
3665 {
3666  //do NOT clear mTimedActionList if it's being iterated because it will invalidate the iterator and delete
3667  // any SmartScriptHolder contained like the "e" parameter passed to this function
3668  if (isProcessingTimedActionList)
3669  {
3670  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());
3671  return;
3672  }
3673 
3674  mTimedActionList.clear();
3675  mTimedActionList = sSmartScriptMgr->GetScript(entry, SMART_SCRIPT_TYPE_TIMED_ACTIONLIST);
3676  if (mTimedActionList.empty())
3677  return;
3678  for (SmartAIEventList::iterator i = mTimedActionList.begin(); i != mTimedActionList.end(); ++i)
3679  {
3680  i->enableTimed = i == mTimedActionList.begin();//enable processing only for the first action
3681 
3682  if (e.action.timedActionList.timerType == 0)
3683  i->event.type = SMART_EVENT_UPDATE_OOC;
3684  else if (e.action.timedActionList.timerType == 1)
3685  i->event.type = SMART_EVENT_UPDATE_IC;
3686  else if (e.action.timedActionList.timerType > 1)
3687  i->event.type = SMART_EVENT_UPDATE;
3688 
3689  InitTimer((*i));
3690  }
3691 }
3692 
3694 {
3695  return ObjectAccessor::FindUnit(mLastInvoker);
3696 }
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
void AddEvent(SMART_EVENT e, uint32 event_flags, uint32 event_param1, uint32 event_param2, uint32 event_param3, uint32 event_param4, SMART_ACTION action, uint32 action_param1, uint32 action_param2, uint32 action_param3, uint32 action_param4, uint32 action_param5, uint32 action_param6, SMARTAI_TARGETS t, uint32 target_param1, uint32 target_param2, uint32 target_param3, uint32 phaseMask=0)
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:563
Map * GetMap() const
Definition: Object.h:841
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:3547
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:2091
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:13749
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:426
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:12101
struct SmartAction::@162::@238 closestWaypointFromList
uint32 GetGUIDLow() const
Definition: Object.h:166
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
#define sObjectMgr
Definition: ObjectMgr.h:1285
struct SmartEvent::@125::@143 dataSet
GameObject * ToGameObject()
Definition: Object.h:401
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:921
struct SmartEvent::@125::@159 distance
Player * ToPlayer()
Definition: Object.h:392
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
struct SmartAction::@162::@165 faction
uint8 GetTypeId() const
Definition: Object.h:210
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
SmartScriptHolder CreateEvent(SMART_EVENT e, uint32 event_flags, uint32 event_param1, uint32 event_param2, uint32 event_param3, uint32 event_param4, SMART_ACTION action, uint32 action_param1, uint32 action_param2, uint32 action_param3, uint32 action_param4, uint32 action_param5, uint32 action_param6, SMARTAI_TARGETS t, uint32 target_param1, uint32 target_param2, uint32 target_param3, uint32 phaseMask=0)
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:1223
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:704
Definition: Cell.h:46
bool IsInRange(WorldObject const *obj, float minRange, float maxRange, bool is3D=true) const
Definition: Object.cpp:1299
#define sGameEventMgr
Definition: GameEventMgr.h:179
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:395
struct SmartEvent::@125::@137 summoned
void InterruptNonMeleeSpells(bool withDelayed, uint32 spellid=0, bool withInstant=true)
Definition: Unit.cpp:3576
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:192
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:433
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:922
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:398
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)
const uint64 & GetGUID() const
Definition: Object.h:162
uint32 equipentry[3]
Definition: Creature.h:253
InstanceData * GetInstanceData()
Definition: Object.cpp:1189
Definition: Spell.h:249