TrinityCore
Loading...
Searching...
No Matches
SmartScriptMgr.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore 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 "SmartScriptMgr.h"
19#include "CreatureTextMgr.h"
20#include "DatabaseEnv.h"
21#include "DBCStores.h"
22#include "GameEventMgr.h"
23#include "InstanceScript.h"
24#include "Log.h"
25#include "MovementDefines.h"
26#include "ObjectAccessor.h"
27#include "ObjectMgr.h"
28#include "SpellInfo.h"
29#include "SpellMgr.h"
30#include "Timer.h"
31#include "UnitDefines.h"
32#include "Unit.h"
33#include "WaypointDefines.h"
34#include "WaypointManager.h"
35
36#define TC_SAI_IS_BOOLEAN_VALID(e, value) \
37{ \
38 if (value > 1) \
39 { \
40 TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} uses param {} of type Boolean with value {}, valid values are 0 or 1, skipped.", \
41 e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), STRINGIZE(value), value); \
42 return false; \
43 } \
44}
45
51
53{
55
56 uint32 oldMSTime = getMSTime();
57
58 for (SmartAIEventMap& eventmap : mEventMap)
59 eventmap.clear(); //Drop Existing SmartAI List
60
62 PreparedQueryResult result = WorldDatabase.Query(stmt);
63
64 if (!result)
65 {
66 TC_LOG_INFO("server.loading", ">> Loaded 0 SmartAI scripts. DB table `smartai_scripts` is empty.");
67 return;
68 }
69
70 uint32 count = 0;
71
72 do
73 {
74 Field* fields = result->Fetch();
75
77
78 temp.entryOrGuid = fields[0].GetInt32();
79 if (!temp.entryOrGuid)
80 {
81 TC_LOG_ERROR("sql.sql", "SmartAIMgr::LoadSmartAIFromDB: invalid entryorguid (0), skipped loading.");
82 continue;
83 }
84
85 SmartScriptType source_type = (SmartScriptType)fields[1].GetUInt8();
86 if (source_type >= SMART_SCRIPT_TYPE_MAX)
87 {
88 TC_LOG_ERROR("sql.sql", "SmartAIMgr::LoadSmartAIFromDB: invalid source_type ({}), skipped loading.", uint32(source_type));
89 continue;
90 }
91 if (temp.entryOrGuid >= 0)
92 {
93 switch (source_type)
94 {
96 {
97 CreatureTemplate const* creatureInfo = sObjectMgr->GetCreatureTemplate((uint32)temp.entryOrGuid);
98 if (!creatureInfo)
99 {
100 TC_LOG_ERROR("sql.sql", "SmartAIMgr::LoadSmartAIFromDB: Creature entry ({}) does not exist, skipped loading.", uint32(temp.entryOrGuid));
101 continue;
102 }
103
104 if (creatureInfo->AIName != "SmartAI")
105 {
106 TC_LOG_ERROR("sql.sql", "SmartAIMgr::LoadSmartAIFromDB: Creature entry ({}) is not using SmartAI, skipped loading.", uint32(temp.entryOrGuid));
107 continue;
108 }
109 break;
110 }
112 {
113 GameObjectTemplate const* gameObjectInfo = sObjectMgr->GetGameObjectTemplate((uint32)temp.entryOrGuid);
114 if (!gameObjectInfo)
115 {
116 TC_LOG_ERROR("sql.sql", "SmartAIMgr::LoadSmartAIFromDB: GameObject entry ({}) does not exist, skipped loading.", uint32(temp.entryOrGuid));
117 continue;
118 }
119
120 if (gameObjectInfo->AIName != "SmartGameObjectAI")
121 {
122 TC_LOG_ERROR("sql.sql", "SmartAIMgr::LoadSmartAIFromDB: GameObject entry ({}) is not using SmartGameObjectAI, skipped loading.", uint32(temp.entryOrGuid));
123 continue;
124 }
125 break;
126 }
128 {
129 if (!sAreaTriggerStore.LookupEntry((uint32)temp.entryOrGuid))
130 {
131 TC_LOG_ERROR("sql.sql", "SmartAIMgr::LoadSmartAIFromDB: AreaTrigger entry ({}) does not exist, skipped loading.", uint32(temp.entryOrGuid));
132 continue;
133 }
134 break;
135 }
137 break;//nothing to check, really
138 default:
139 TC_LOG_ERROR("sql.sql", "SmartAIMgr::LoadSmartAIFromDB: not yet implemented source_type {}", (uint32)source_type);
140 continue;
141 }
142 }
143 else
144 {
145 switch (source_type)
146 {
148 {
149 CreatureData const* creature = sObjectMgr->GetCreatureData(uint32(-temp.entryOrGuid));
150 if (!creature)
151 {
152 TC_LOG_ERROR("sql.sql", "SmartAIMgr::LoadSmartAIFromDB: Creature guid ({}) does not exist, skipped loading.", -temp.entryOrGuid);
153 continue;
154 }
155
156 CreatureTemplate const* creatureInfo = sObjectMgr->GetCreatureTemplate(creature->id);
157 if (!creatureInfo)
158 {
159 TC_LOG_ERROR("sql.sql", "SmartAIMgr::LoadSmartAIFromDB: Creature entry ({}) guid ({}) does not exist, skipped loading.", creature->id, -temp.entryOrGuid);
160 continue;
161 }
162
163 if (creatureInfo->AIName != "SmartAI")
164 {
165 TC_LOG_ERROR("sql.sql", "SmartAIMgr::LoadSmartAIFromDB: Creature entry ({}) guid ({}) is not using SmartAI, skipped loading.", creature->id, -temp.entryOrGuid);
166 continue;
167 }
168 break;
169 }
171 {
172 GameObjectData const* gameObject = sObjectMgr->GetGameObjectData(uint32(std::abs(temp.entryOrGuid)));
173 if (!gameObject)
174 {
175 TC_LOG_ERROR("sql.sql", "SmartAIMgr::LoadSmartAIFromDB: GameObject guid ({}) does not exist, skipped loading.", -temp.entryOrGuid);
176 continue;
177 }
178
179 GameObjectTemplate const* gameObjectInfo = sObjectMgr->GetGameObjectTemplate(gameObject->id);
180 if (!gameObjectInfo)
181 {
182 TC_LOG_ERROR("sql.sql", "SmartAIMgr::LoadSmartAIFromDB: GameObject entry ({}) guid ({}) does not exist, skipped loading.", gameObject->id, -temp.entryOrGuid);
183 continue;
184 }
185
186 if (gameObjectInfo->AIName != "SmartGameObjectAI")
187 {
188 TC_LOG_ERROR("sql.sql", "SmartAIMgr::LoadSmartAIFromDB: GameObject entry ({}) guid ({}) is not using SmartGameObjectAI, skipped loading.", gameObject->id, -temp.entryOrGuid);
189 continue;
190 }
191 break;
192 }
193 default:
194 TC_LOG_ERROR("sql.sql", "SmartAIMgr::LoadSmartAIFromDB: GUID-specific scripting not yet implemented for source_type {}", (uint32)source_type);
195 continue;
196 }
197 }
198
199 temp.source_type = source_type;
200 temp.event_id = fields[2].GetUInt16();
201 temp.link = fields[3].GetUInt16();
202 temp.event.type = (SMART_EVENT)fields[4].GetUInt8();
203 temp.event.event_phase_mask = fields[5].GetUInt16();
204 temp.event.event_chance = fields[6].GetUInt8();
205 temp.event.event_flags = fields[7].GetUInt16();
206
207 temp.event.raw.param1 = fields[8].GetUInt32();
208 temp.event.raw.param2 = fields[9].GetUInt32();
209 temp.event.raw.param3 = fields[10].GetUInt32();
210 temp.event.raw.param4 = fields[11].GetUInt32();
211 temp.event.raw.param5 = fields[12].GetUInt32();
212
213 temp.action.type = (SMART_ACTION)fields[13].GetUInt8();
214 temp.action.raw.param1 = fields[14].GetUInt32();
215 temp.action.raw.param2 = fields[15].GetUInt32();
216 temp.action.raw.param3 = fields[16].GetUInt32();
217 temp.action.raw.param4 = fields[17].GetUInt32();
218 temp.action.raw.param5 = fields[18].GetUInt32();
219 temp.action.raw.param6 = fields[19].GetUInt32();
220
221 temp.target.type = (SMARTAI_TARGETS)fields[20].GetUInt8();
222 temp.target.raw.param1 = fields[21].GetUInt32();
223 temp.target.raw.param2 = fields[22].GetUInt32();
224 temp.target.raw.param3 = fields[23].GetUInt32();
225 temp.target.raw.param4 = fields[24].GetUInt32();
226 temp.target.x = fields[25].GetFloat();
227 temp.target.y = fields[26].GetFloat();
228 temp.target.z = fields[27].GetFloat();
229 temp.target.o = fields[28].GetFloat();
230
231 //check target
232 if (!IsTargetValid(temp))
233 continue;
234
235 // check all event and action params
236 if (!IsEventValid(temp))
237 continue;
238
239 // specific check for timed events
240 switch (temp.event.type)
241 {
253 {
255 TC_LOG_ERROR("sql.sql", "SmartAIMgr::LoadSmartAIFromDB: Entry {} SourceType {}, Event {}, Missing Repeat flag.",
256 temp.entryOrGuid, temp.GetScriptType(), temp.event_id);
257 }
258 break;
261 {
263 TC_LOG_ERROR("sql.sql", "SmartAIMgr::LoadSmartAIFromDB: Entry {} SourceType {}, Event {}, Missing Repeat flag.",
264 temp.entryOrGuid, temp.GetScriptType(), temp.event_id);
265 }
266 break;
269 {
271 TC_LOG_ERROR("sql.sql", "SmartAIMgr::LoadSmartAIFromDB: Entry {} SourceType {}, Event {}, Missing Repeat flag.",
272 temp.entryOrGuid, temp.GetScriptType(), temp.event_id);
273 }
274 break;
275 default:
276 break;
277 }
278
279 // creature entry / guid not found in storage, create empty event list for it and increase counters
280 if (mEventMap[source_type].find(temp.entryOrGuid) == mEventMap[source_type].end())
281 {
282 ++count;
283 SmartAIEventList eventList;
284 mEventMap[source_type][temp.entryOrGuid] = eventList;
285 }
286 // store the new event
287 mEventMap[source_type][temp.entryOrGuid].push_back(temp);
288 }
289 while (result->NextRow());
290
291 // Post Loading Validation
292 for (SmartAIEventMap& eventmap : mEventMap)
293 {
294 for (std::pair<int32 const, SmartAIEventList>& eventlistpair : eventmap)
295 {
296 for (SmartScriptHolder const& e : eventlistpair.second)
297 {
298 if (e.link)
299 {
300 if (!FindLinkedEvent(eventlistpair.second, e.link))
301 {
302 TC_LOG_ERROR("sql.sql", "SmartAIMgr::LoadSmartAIFromDB: Entry {} SourceType {}, Event {}, Link Event {} not found or invalid.",
303 e.entryOrGuid, e.GetScriptType(), e.event_id, e.link);
304 }
305 }
306
307 if (e.GetEventType() == SMART_EVENT_LINK)
308 {
309 if (!FindLinkedSourceEvent(eventlistpair.second, e.event_id))
310 {
311 TC_LOG_ERROR("sql.sql", "SmartAIMgr::LoadSmartAIFromDB: Entry {} SourceType {}, Event {}, Link Source Event not found or invalid. Event will never trigger.",
312 e.entryOrGuid, e.GetScriptType(), e.event_id);
313 }
314 }
315 }
316 }
317 }
318
319 TC_LOG_INFO("server.loading", ">> Loaded {} SmartAI scripts in {} ms", count, GetMSTimeDiffToNow(oldMSTime));
320
322}
323
325{
326 SmartAIEventList temp;
327 if (mEventMap[uint32(type)].find(entry) != mEventMap[uint32(type)].end())
328 return mEventMap[uint32(type)][entry];
329 else
330 {
331 if (entry > 0)//first search is for guid (negative), do not drop error if not found
332 TC_LOG_DEBUG("scripts.ai", "SmartAIMgr::GetScript: Could not load Script for Entry {} ScriptType {}.", entry, uint32(type));
333 return temp;
334 }
335}
336
338{
339 SmartAIEventList::iterator itr = std::find_if(list.begin(), list.end(),
340 [eventId](SmartScriptHolder& source) { return source.link == eventId; });
341
342 if (itr != list.end())
343 return *itr;
344
345 static SmartScriptHolder SmartScriptHolderDummy;
346 return SmartScriptHolderDummy;
347}
348
350{
351 SmartAIEventList::iterator itr = std::find_if(list.begin(), list.end(),
352 [link](SmartScriptHolder& linked) { return linked.event_id == link && linked.GetEventType() == SMART_EVENT_LINK; });
353
354 if (itr != list.end())
355 return *itr;
356
357 static SmartScriptHolder SmartScriptHolderDummy;
358 return SmartScriptHolderDummy;
359}
360
362{
363 switch (event)
364 { // white list of events that actually have an invoker passed to them
367 case SMART_EVENT_KILL:
401 return true;
402 default:
403 return false;
404 }
405}
406
408{
409 if (std::abs(e.target.o) > 2 * float(M_PI))
410 TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} has abs(`target.o` = {}) > 2*PI (orientation is expressed in radians)",
412
413 switch (e.GetTargetType())
414 {
417 {
418 if (e.target.unitDistance.creature && !sObjectMgr->GetCreatureTemplate(e.target.unitDistance.creature))
419 {
420 TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} uses non-existent Creature entry {} as target_param1, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.target.unitDistance.creature);
421 return false;
422 }
423 break;
424 }
427 {
428 if (e.target.goDistance.entry && !sObjectMgr->GetGameObjectTemplate(e.target.goDistance.entry))
429 {
430 TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} uses non-existent GameObject entry {} as target_param1, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.target.goDistance.entry);
431 return false;
432 }
433 break;
434 }
436 {
438 return false;
439 break;
440 }
442 {
444 return false;
445 break;
446 }
449 {
450 if (e.target.playerDistance.dist == 0)
451 {
452 TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} has maxDist 0 as target_param1, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType());
453 return false;
454 }
455 break;
456 }
461 {
462 TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} has invoker target, but event does not provide any invoker!", e.entryOrGuid, e.GetScriptType(), e.GetEventType(), e.GetActionType());
463 return false;
464 }
465 break;
471 break;
475 break;
478 break;
481 break;
484 break;
487 break;
499 break;
500 default:
501 TC_LOG_ERROR("sql.sql", "SmartAIMgr: Not handled target_type({}), Entry {} SourceType {} Event {} Action {}, skipped.", e.GetTargetType(), e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType());
502 return false;
503 }
504
506 return false;
507
508 return true;
509}
510
512{
513 if (max < min)
514 {
515 TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} uses min/max params wrong ({}/{}), skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), min, max);
516 return false;
517 }
518 return true;
519}
520
522{
523 if (!data)
524 {
525 TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} Parameter can not be NULL, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType());
526 return false;
527 }
528 return true;
529}
530
532{
533 if (!sObjectMgr->GetCreatureTemplate(entry))
534 {
535 TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} uses non-existent Creature entry {}, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), entry);
536 return false;
537 }
538 return true;
539}
540
542{
543 if (!sObjectMgr->GetQuestTemplate(entry))
544 {
545 TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} uses non-existent Quest entry {}, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), entry);
546 return false;
547 }
548 return true;
549}
550
552{
553 if (!sObjectMgr->GetGameObjectTemplate(entry))
554 {
555 TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} uses non-existent GameObject entry {}, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), entry);
556 return false;
557 }
558 return true;
559}
560
562{
563 if (!sSpellMgr->GetSpellInfo(entry))
564 {
565 TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} uses non-existent Spell entry {}, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), entry);
566 return false;
567 }
568 return true;
569}
570
572{
573 if (!sItemStore.LookupEntry(entry))
574 {
575 TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} uses non-existent Item entry {}, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), entry);
576 return false;
577 }
578 return true;
579}
580
582{
583 if (!sEmotesTextStore.LookupEntry(entry))
584 {
585 TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} uses non-existent Text Emote entry {}, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), entry);
586 return false;
587 }
588 return true;
589}
590
592{
593 if (!sEmotesStore.LookupEntry(entry))
594 {
595 TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} uses non-existent Emote entry {}, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), entry);
596 return false;
597 }
598 return true;
599}
600
602{
603 if (!sAreaTriggerStore.LookupEntry(entry))
604 {
605 TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} uses non-existent AreaTrigger entry {}, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), entry);
606 return false;
607 }
608 return true;
609}
610
612{
613 if (!sSoundEntriesStore.LookupEntry(entry))
614 {
615 TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} uses non-existent Sound entry {}, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), entry);
616 return false;
617 }
618 return true;
619}
620
622{
623 size_t paramsStructSize = [&]() -> size_t
624 {
625 constexpr size_t NO_PARAMS = size_t(0);
626 switch (e.event.type)
627 {
632 case SMART_EVENT_AGGRO: return NO_PARAMS;
633 case SMART_EVENT_KILL: return sizeof(SmartEvent::kill);
634 case SMART_EVENT_DEATH: return NO_PARAMS;
635 case SMART_EVENT_EVADE: return NO_PARAMS;
636 case SMART_EVENT_SPELLHIT: return sizeof(SmartEvent::spellHit);
637 case SMART_EVENT_RANGE: return sizeof(SmartEvent::minMaxRepeat);
638 case SMART_EVENT_OOC_LOS: return sizeof(SmartEvent::los);
639 case SMART_EVENT_RESPAWN: return sizeof(SmartEvent::respawn);
645 case SMART_EVENT_REWARD_QUEST: return sizeof(SmartEvent::quest);
646 case SMART_EVENT_REACHED_HOME: return NO_PARAMS;
647 case SMART_EVENT_RECEIVE_EMOTE: return sizeof(SmartEvent::emote);
648 case SMART_EVENT_HAS_AURA: return sizeof(SmartEvent::aura);
649 case SMART_EVENT_TARGET_BUFFED: return sizeof(SmartEvent::aura);
650 case SMART_EVENT_RESET: return NO_PARAMS;
651 case SMART_EVENT_IC_LOS: return sizeof(SmartEvent::los);
654 case SMART_EVENT_CHARMED: return sizeof(SmartEvent::charm);
660 case SMART_EVENT_CORPSE_REMOVED: return NO_PARAMS;
661 case SMART_EVENT_AI_INIT: return NO_PARAMS;
662 case SMART_EVENT_DATA_SET: return sizeof(SmartEvent::dataSet);
664 case SMART_EVENT_TRANSPORT_ADDPLAYER: return NO_PARAMS;
666 case SMART_EVENT_TRANSPORT_REMOVE_PLAYER: return NO_PARAMS;
670 case SMART_EVENT_QUEST_ACCEPTED: return NO_PARAMS;
671 case SMART_EVENT_QUEST_OBJ_COMPLETION: return NO_PARAMS;
672 case SMART_EVENT_QUEST_COMPLETION: return NO_PARAMS;
673 case SMART_EVENT_QUEST_REWARDED: return NO_PARAMS;
674 case SMART_EVENT_QUEST_FAIL: return NO_PARAMS;
675 case SMART_EVENT_TEXT_OVER: return sizeof(SmartEvent::textOver);
677 case SMART_EVENT_JUST_SUMMONED: return NO_PARAMS;
683 case SMART_EVENT_UPDATE: return sizeof(SmartEvent::minMaxRepeat);
684 case SMART_EVENT_LINK: return NO_PARAMS;
686 case SMART_EVENT_JUST_CREATED: return NO_PARAMS;
688 case SMART_EVENT_FOLLOW_COMPLETED: return NO_PARAMS;
694 case SMART_EVENT_ON_SPELLCLICK: return NO_PARAMS;
698 case SMART_EVENT_COUNTER_SET: return sizeof(SmartEvent::counter);
699 //case SMART_EVENT_SCENE_START: return sizeof(SmartEvent::raw);
700 //case SMART_EVENT_SCENE_TRIGGER: return sizeof(SmartEvent::raw);
701 //case SMART_EVENT_SCENE_CANCEL: return sizeof(SmartEvent::raw);
702 //case SMART_EVENT_SCENE_COMPLETE: return sizeof(SmartEvent::raw);
709 case SMART_EVENT_ON_DESPAWN: return NO_PARAMS;
710 default:
711 TC_LOG_WARN("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} is using an event with no unused params specified in SmartAIMgr::CheckUnusedEventParams(), please report this.",
713 return sizeof(SmartEvent::raw);
714 }
715 }();
716
717 static size_t rawCount = sizeof(SmartEvent::raw) / sizeof(uint32);
718 size_t paramsCount = paramsStructSize / sizeof(uint32);
719
720 for (size_t index = paramsCount; index < rawCount; index++)
721 {
722 uint32 value = ((uint32*)&e.event.raw)[index];
723 if (value != 0)
724 {
725 TC_LOG_WARN("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} has unused event_param{} with value {}, it should be 0.",
726 e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), index + 1, value);
727 }
728 }
729
730 return true;
731}
732
734{
735 size_t paramsStructSize = [&]() -> size_t
736 {
737 constexpr size_t NO_PARAMS = size_t(0);
738 switch (e.action.type)
739 {
740 case SMART_ACTION_NONE: return NO_PARAMS;
741 case SMART_ACTION_TALK: return sizeof(SmartAction::talk);
744 case SMART_ACTION_SOUND: return sizeof(SmartAction::sound);
745 case SMART_ACTION_PLAY_EMOTE: return sizeof(SmartAction::emote);
746 case SMART_ACTION_FAIL_QUEST: return sizeof(SmartAction::quest);
749 case SMART_ACTION_ACTIVATE_GOBJECT: return NO_PARAMS;
751 case SMART_ACTION_CAST: return sizeof(SmartAction::cast);
756 //case SMART_ACTION_RESERVED_16: return sizeof(SmartAction::raw);
762 case SMART_ACTION_EVADE: return sizeof(SmartAction::evade);
765 case SMART_ACTION_COMBAT_STOP: return NO_PARAMS;
767 case SMART_ACTION_FOLLOW: return sizeof(SmartAction::follow);
770 case SMART_ACTION_RESET_GOBJECT: return NO_PARAMS;
775 case SMART_ACTION_DIE: return NO_PARAMS;
776 case SMART_ACTION_SET_IN_COMBAT_WITH_ZONE: return NO_PARAMS;
783 case SMART_ACTION_SET_DATA: return sizeof(SmartAction::setData);
784 case SMART_ACTION_ATTACK_STOP: return NO_PARAMS;
786 case SMART_ACTION_SET_ACTIVE: return sizeof(SmartAction::active);
787 case SMART_ACTION_ATTACK_START: return NO_PARAMS;
789 case SMART_ACTION_KILL_UNIT: return NO_PARAMS;
791 case SMART_ACTION_WP_START: return sizeof(SmartAction::wpStart);
792 case SMART_ACTION_WP_PAUSE: return sizeof(SmartAction::wpPause);
793 case SMART_ACTION_WP_STOP: return sizeof(SmartAction::wpStop);
794 case SMART_ACTION_ADD_ITEM: return sizeof(SmartAction::item);
795 case SMART_ACTION_REMOVE_ITEM: return sizeof(SmartAction::item);
796 case SMART_ACTION_SET_RUN: return sizeof(SmartAction::setRun);
798 case SMART_ACTION_TELEPORT: return sizeof(SmartAction::teleport);
801 case SMART_ACTION_WP_RESUME: return NO_PARAMS;
802 case SMART_ACTION_SET_ORIENTATION: return NO_PARAMS;
804 case SMART_ACTION_PLAYMOVIE: return sizeof(SmartAction::movie);
807 case SMART_ACTION_EQUIP: return sizeof(SmartAction::equip);
808 case SMART_ACTION_CLOSE_GOSSIP: return NO_PARAMS;
811 case SMART_ACTION_CALL_SCRIPT_RESET: return NO_PARAMS;
814 case SMART_ACTION_SET_NPC_FLAG: return sizeof(SmartAction::flag);
815 case SMART_ACTION_ADD_NPC_FLAG: return sizeof(SmartAction::flag);
818 case SMART_ACTION_SELF_CAST: return sizeof(SmartAction::cast);
826 case SMART_ACTION_JUMP_TO_POS: return sizeof(SmartAction::jump);
830 case SMART_ACTION_SET_HOME_POS: return NO_PARAMS;
832 case SMART_ACTION_SET_ROOT: return sizeof(SmartAction::setRoot);
834 case SMART_ACTION_SET_POWER: return sizeof(SmartAction::power);
835 case SMART_ACTION_ADD_POWER: return sizeof(SmartAction::power);
840 case SMART_ACTION_MOVE_OFFSET: return NO_PARAMS;
845 case SMART_ACTION_ADD_THREAT: return sizeof(SmartAction::threat);
849 //case SMART_ACTION_PLAY_ANIMKIT: return sizeof(SmartAction::raw);
850 //case SMART_ACTION_SCENE_PLAY: return sizeof(SmartAction::raw);
851 //case SMART_ACTION_SCENE_CANCEL: return sizeof(SmartAction::raw);
855 case SMART_ACTION_INVOKER_CAST: return sizeof(SmartAction::cast);
858 //case SMART_ACTION_PLAY_SPELL_VISUAL_KIT: return sizeof(SmartAction::raw);
861 //case SMART_ACTION_SET_AI_ANIM_KIT: return sizeof(SmartAction::raw);
864 //case SMART_ACTION_CREATE_CONVERSATION: return sizeof(SmartAction::raw);
871 default:
872 TC_LOG_WARN("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} is using an action with no unused params specified in SmartAIMgr::CheckUnusedActionParams(), please report this.",
874 return sizeof(SmartAction::raw);
875 }
876 }();
877
878 static size_t rawCount = sizeof(SmartAction::raw) / sizeof(uint32);
879 size_t paramsCount = paramsStructSize / sizeof(uint32);
880
881 for (size_t index = paramsCount; index < rawCount; index++)
882 {
883 uint32 value = ((uint32*)&e.action.raw)[index];
884 if (value != 0)
885 {
886 TC_LOG_WARN("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} has unused action_param{} with value {}, it should be 0.",
887 e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), index + 1, value);
888 }
889 }
890
891 return true;
892}
893
895{
896 size_t paramsStructSize = [&]() -> size_t
897 {
898 constexpr size_t NO_PARAMS = size_t(0);
899 switch (e.target.type)
900 {
901 case SMART_TARGET_NONE: return NO_PARAMS;
902 case SMART_TARGET_SELF: return NO_PARAMS;
903 case SMART_TARGET_VICTIM: return NO_PARAMS;
908 case SMART_TARGET_ACTION_INVOKER: return NO_PARAMS;
909 case SMART_TARGET_POSITION: return NO_PARAMS; //uses x,y,z,o
913 case SMART_TARGET_STORED: return sizeof(SmartTarget::stored);
917 case SMART_TARGET_INVOKER_PARTY: return NO_PARAMS;
923 case SMART_TARGET_ACTION_INVOKER_VEHICLE: return NO_PARAMS;
928 case SMART_TARGET_LOOT_RECIPIENTS: return NO_PARAMS;
929 case SMART_TARGET_FARTHEST: return sizeof(SmartTarget::farthest);
932 default:
933 TC_LOG_WARN("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} is using a target with no unused params specified in SmartAIMgr::CheckUnusedTargetParams(), please report this.",
935 return sizeof(SmartTarget::raw);
936 }
937 }();
938
939 static size_t rawCount = sizeof(SmartTarget::raw) / sizeof(uint32);
940 size_t paramsCount = paramsStructSize / sizeof(uint32);
941
942 for (size_t index = paramsCount; index < rawCount; index++)
943 {
944 uint32 value = ((uint32*)&e.target.raw)[index];
945 if (value != 0)
946 {
947 TC_LOG_WARN("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} has unused target_param{} with value {}, it should be 0.",
948 e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), index + 1, value);
949 }
950 }
951
952 return true;
953}
954
956{
957 if (e.event.type >= SMART_EVENT_END)
958 {
959 TC_LOG_ERROR("sql.sql", "SmartAIMgr: EntryOrGuid {} using event({}) has invalid event type ({}), skipped.", e.entryOrGuid, e.event_id, e.GetEventType());
960 return false;
961 }
962
963 // in SMART_SCRIPT_TYPE_TIMED_ACTIONLIST all event types are overriden by core
965 {
966 TC_LOG_ERROR("sql.sql", "SmartAIMgr: EntryOrGuid {}, event type {} can not be used for Script type {}", e.entryOrGuid, e.GetEventType(), e.GetScriptType());
967 return false;
968 }
969
970 if (e.action.type <= 0 || e.action.type >= SMART_ACTION_END)
971 {
972 TC_LOG_ERROR("sql.sql", "SmartAIMgr: EntryOrGuid {} using event({}) has invalid action type ({}), skipped.", e.entryOrGuid, e.event_id, e.GetActionType());
973 return false;
974 }
975
977 {
978 TC_LOG_ERROR("sql.sql", "SmartAIMgr: EntryOrGuid {} using event({}) has invalid phase mask ({}), skipped.", e.entryOrGuid, e.event_id, e.event.event_phase_mask);
979 return false;
980 }
981
983 {
984 TC_LOG_ERROR("sql.sql", "SmartAIMgr: EntryOrGuid {} using event({}) has invalid event flags ({}), skipped.", e.entryOrGuid, e.event_id, e.event.event_flags);
985 return false;
986 }
987
988 if (e.link && e.link == e.event_id)
989 {
990 TC_LOG_ERROR("sql.sql", "SmartAIMgr: EntryOrGuid {} SourceType {}, Event {}, Event is linking self (infinite loop), skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id);
991 return false;
992 }
993
995 {
996 e.event.type = SMART_EVENT_UPDATE_OOC;//force default OOC, can change when calling the script!
998 return false;
999
1001 return false;
1002 }
1003 else
1004 {
1005 switch (e.GetEventType())
1006 {
1007 case SMART_EVENT_UPDATE:
1012 case SMART_EVENT_RANGE:
1017 return false;
1018
1020 return false;
1021 break;
1024 if (e.event.spellHit.spell)
1025 {
1026 SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(e.event.spellHit.spell);
1027 if (!spellInfo)
1028 {
1029 TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} uses non-existent Spell entry {}, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.event.spellHit.spell);
1030 return false;
1031 }
1032 if (e.event.spellHit.school && (e.event.spellHit.school & spellInfo->SchoolMask) != spellInfo->SchoolMask)
1033 {
1034 TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} uses Spell entry {} with invalid school mask, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.event.spellHit.spell);
1035 return false;
1036 }
1037 }
1039 return false;
1040 break;
1046 {
1047 if (!IsSpellValid(e, e.event.spellCast.spell))
1048 return false;
1049
1051 return false;
1052 break;
1053 }
1055 case SMART_EVENT_IC_LOS:
1057 return false;
1059 {
1060 TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} uses hostilityMode with invalid value {} (max allowed value {}), skipped.",
1062 return false;
1063 }
1064
1066 break;
1069 {
1070 TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} uses non-existent Map entry {}, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.event.respawn.map);
1071 return false;
1072 }
1074 {
1075 TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} uses non-existent Area entry {}, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.event.respawn.area);
1076 return false;
1077 }
1078 break;
1081 return false;
1082 break;
1084 {
1086 return false;
1087
1088 if (!NotNULL(e, e.event.missingBuff.radius))
1089 return false;
1090
1092 return false;
1093 break;
1094 }
1095 case SMART_EVENT_KILL:
1097 return false;
1098
1100 return false;
1101
1103 break;
1105 if (e.event.targetCasting.spellId > 0 && !sSpellMgr->GetSpellInfo(e.event.targetCasting.spellId))
1106 {
1107 TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} uses non-existent Spell entry {}, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.event.spellHit.spell);
1108 return false;
1109 }
1110
1112 return false;
1113 break;
1117 return false;
1118 break;
1123 return false;
1124
1126 return false;
1127 break;
1130 if (e.event.quest.quest && !IsQuestValid(e, e.event.quest.quest))
1131 return false;
1132
1133 if (!IsMinMaxValid(e, e.event.quest.cooldownMin, e.event.quest.cooldownMax))
1134 return false;
1135 break;
1137 {
1138 if (e.event.emote.emote && !IsTextEmoteValid(e, e.event.emote.emote))
1139 return false;
1140
1141 if (!IsMinMaxValid(e, e.event.emote.cooldownMin, e.event.emote.cooldownMax))
1142 return false;
1143 break;
1144 }
1147 {
1148 if (!IsSpellValid(e, e.event.aura.spell))
1149 return false;
1150
1152 return false;
1153 break;
1154 }
1156 {
1158 return false;
1159 break;
1160 }
1162 {
1164 {
1165 TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} uses invalid Motion type {}, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.event.movementInform.type);
1166 return false;
1167 }
1168 break;
1169 }
1171 {
1173 return false;
1174 break;
1175 }
1177 {
1179 return false;
1180 break;
1181 }
1184 return false;
1185 break;
1188 {
1189 GameEventMgr::GameEventDataMap const& events = sGameEventMgr->GetEventMap();
1190 if (e.event.gameEvent.gameEventId >= events.size() || !events[e.event.gameEvent.gameEventId].isValid())
1191 return false;
1192 break;
1193 }
1195 {
1197 {
1198 TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} uses invalid event id {}, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.event.doAction.eventId);
1199 return false;
1200 }
1201 break;
1202 }
1205 return false;
1206
1208 {
1209 TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} has pct value above 100, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType());
1210 return false;
1211 }
1212
1213 switch (e.GetTargetType())
1214 {
1222 break;
1225 return false;
1226 break;
1227 default:
1228 TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} uses invalid target_type {}, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.GetTargetType());
1229 return false;
1230 }
1231 break;
1233 if (e.event.distance.guid == 0 && e.event.distance.entry == 0)
1234 {
1235 TC_LOG_ERROR("sql.sql", "SmartAIMgr: Event SMART_EVENT_DISTANCE_CREATURE did not provide creature guid or entry, skipped.");
1236 return false;
1237 }
1238
1239 if (e.event.distance.guid != 0 && e.event.distance.entry != 0)
1240 {
1241 TC_LOG_ERROR("sql.sql", "SmartAIMgr: Event SMART_EVENT_DISTANCE_CREATURE provided both an entry and guid, skipped.");
1242 return false;
1243 }
1244
1245 if (e.event.distance.guid != 0 && !sObjectMgr->GetCreatureData(e.event.distance.guid))
1246 {
1247 TC_LOG_ERROR("sql.sql", "SmartAIMgr: Event SMART_EVENT_DISTANCE_CREATURE using invalid creature guid {}, skipped.", e.event.distance.guid);
1248 return false;
1249 }
1250
1251 if (e.event.distance.entry != 0 && !sObjectMgr->GetCreatureTemplate(e.event.distance.entry))
1252 {
1253 TC_LOG_ERROR("sql.sql", "SmartAIMgr: Event SMART_EVENT_DISTANCE_CREATURE using invalid creature entry {}, skipped.", e.event.distance.entry);
1254 return false;
1255 }
1256 break;
1258 if (e.event.distance.guid == 0 && e.event.distance.entry == 0)
1259 {
1260 TC_LOG_ERROR("sql.sql", "SmartAIMgr: Event SMART_EVENT_DISTANCE_GAMEOBJECT did not provide gameobject guid or entry, skipped.");
1261 return false;
1262 }
1263
1264 if (e.event.distance.guid != 0 && e.event.distance.entry != 0)
1265 {
1266 TC_LOG_ERROR("sql.sql", "SmartAIMgr: Event SMART_EVENT_DISTANCE_GAMEOBJECT provided both an entry and guid, skipped.");
1267 return false;
1268 }
1269
1270 if (e.event.distance.guid != 0 && !sObjectMgr->GetGameObjectData(e.event.distance.guid))
1271 {
1272 TC_LOG_ERROR("sql.sql", "SmartAIMgr: Event SMART_EVENT_DISTANCE_GAMEOBJECT using invalid gameobject guid {}, skipped.", e.event.distance.guid);
1273 return false;
1274 }
1275
1276 if (e.event.distance.entry != 0 && !sObjectMgr->GetGameObjectTemplate(e.event.distance.entry))
1277 {
1278 TC_LOG_ERROR("sql.sql", "SmartAIMgr: Event SMART_EVENT_DISTANCE_GAMEOBJECT using invalid gameobject entry {}, skipped.", e.event.distance.entry);
1279 return false;
1280 }
1281 break;
1284 return false;
1285
1286 if (e.event.counter.id == 0)
1287 {
1288 TC_LOG_ERROR("sql.sql", "SmartAIMgr: Event SMART_EVENT_COUNTER_SET using invalid counter id {}, skipped.", e.event.counter.id);
1289 return false;
1290 }
1291
1292 if (e.event.counter.value == 0)
1293 {
1294 TC_LOG_ERROR("sql.sql", "SmartAIMgr: Event SMART_EVENT_COUNTER_SET using invalid value {}, skipped.", e.event.counter.value);
1295 return false;
1296 }
1297 break;
1298 case SMART_EVENT_RESET:
1300 {
1301 // There might be SMART_TARGET_* cases where this should be allowed, they will be handled if needed
1302 TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} uses event SMART_EVENT_RESET and action SMART_ACTION_CALL_SCRIPT_RESET, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id);
1303 return false;
1304 }
1305 break;
1308 break;
1309 case SMART_EVENT_LINK:
1319 case SMART_EVENT_AGGRO:
1320 case SMART_EVENT_DEATH:
1321 case SMART_EVENT_EVADE:
1340 break;
1341 // Unused
1349 TC_LOG_ERROR("sql.sql", "SmartAIMgr: Unused event_type({}), Entry {} SourceType {} Event {}, skipped.", e.GetEventType(), e.entryOrGuid, e.GetScriptType(), e.event_id);
1350 return false;
1351 default:
1352 TC_LOG_ERROR("sql.sql", "SmartAIMgr: Not handled event_type({}), Entry {} SourceType {} Event {} Action {}, skipped.", e.GetEventType(), e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType());
1353 return false;
1354 }
1355 }
1356
1357 if (!CheckUnusedEventParams(e))
1358 return false;
1359
1360 switch (e.GetActionType())
1361 {
1362 case SMART_ACTION_TALK:
1365 return false;
1366 break;
1369 return false;
1370 break;
1373 {
1374 TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} uses non-existent Faction {}, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.action.faction.factionID);
1375 return false;
1376 }
1377 break;
1381 {
1382 if (e.action.morphOrMount.creature > 0 && !sObjectMgr->GetCreatureTemplate(e.action.morphOrMount.creature))
1383 {
1384 TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} uses non-existent Creature entry {}, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.action.morphOrMount.creature);
1385 return false;
1386 }
1387
1389 {
1391 {
1392 TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} has ModelID set with also set CreatureId, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType());
1393 return false;
1394 }
1395 else if (!sCreatureDisplayInfoStore.LookupEntry(e.action.morphOrMount.model))
1396 {
1397 TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} uses non-existent Model id {}, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.action.morphOrMount.model);
1398 return false;
1399 }
1400 }
1401 }
1402 break;
1403 case SMART_ACTION_SOUND:
1404 if (!IsSoundValid(e, e.action.sound.sound))
1405 return false;
1406 TC_SAI_IS_BOOLEAN_VALID(e, e.action.sound.onlySelf);
1407 break;
1410 if (!IsEmoteValid(e, e.action.emote.emote))
1411 return false;
1412 break;
1415 return false;
1416
1418 break;
1420 if (!IsQuestValid(e, e.action.quest.quest))
1421 return false;
1422 break;
1424 {
1425 if (!sTaxiPathStore.LookupEntry(e.action.taxi.id))
1426 {
1427 TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} uses invalid Taxi path ID {}, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.action.taxi.id);
1428 return false;
1429 }
1430 break;
1431 }
1433 {
1434 if (std::all_of(std::begin(e.action.randomEmote.emotes), std::end(e.action.randomEmote.emotes), [](uint32 emote) { return emote == 0; }))
1435 {
1436 TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} does not have any non-zero emote",
1438 return false;
1439 }
1440
1441 for (uint32 emote : e.action.randomEmote.emotes)
1442 if (emote && !IsEmoteValid(e, emote))
1443 return false;
1444 break;
1445 }
1447 {
1448 if (std::all_of(std::begin(e.action.randTimedActionList.actionLists), std::end(e.action.randTimedActionList.actionLists), [](uint32 actionList) { return actionList == 0; }))
1449 {
1450 TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} does not have any non-zero action list",
1452 return false;
1453 }
1454 break;
1455 }
1457 {
1458 if (std::all_of(std::begin(e.action.closestWaypointFromList.wps), std::end(e.action.closestWaypointFromList.wps), [](uint32 wp) { return wp == 0; }))
1459 {
1460 TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} does not have any non-zero waypoint id",
1462 return false;
1463 }
1464 break;
1465 }
1467 {
1468 if (std::all_of(std::begin(e.action.randomSound.sounds), std::end(e.action.randomSound.sounds), [](uint32 sound) { return sound == 0; }))
1469 {
1470 TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} does not have any non-zero sound",
1472 return false;
1473 }
1474
1475 for (uint32 sound : e.action.randomSound.sounds)
1476 if (sound && !IsSoundValid(e, sound))
1477 return false;
1478
1480 break;
1481 }
1482 case SMART_ACTION_CAST:
1483 {
1484 if (!IsSpellValid(e, e.action.cast.spell))
1485 return false;
1486
1487 for (SpellEffectInfo const& spellEffectInfo : sSpellMgr->AssertSpellInfo(e.action.cast.spell)->GetEffects())
1488 {
1489 if (spellEffectInfo.IsEffect(SPELL_EFFECT_KILL_CREDIT) || spellEffectInfo.IsEffect(SPELL_EFFECT_KILL_CREDIT2))
1490 {
1491 if (spellEffectInfo.TargetA.GetTarget() == TARGET_UNIT_CASTER)
1492 TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} Effect: SPELL_EFFECT_KILL_CREDIT: (SpellId: {} targetA: {} - targetB: {}) has invalid target for this Action",
1493 e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.action.cast.spell, spellEffectInfo.TargetA.GetTarget(), spellEffectInfo.TargetB.GetTarget());
1494 }
1495 }
1496 break;
1497 }
1499 {
1501 return false;
1502 break;
1503 }
1506 {
1507 TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} has invoker cast action, but event does not provide any invoker!", e.entryOrGuid, e.GetScriptType(), e.GetEventType(), e.GetActionType());
1508 return false;
1509 }
1510 [[fallthrough]];
1512 if (!IsSpellValid(e, e.action.cast.spell))
1513 return false;
1514 break;
1517 if (Quest const* qid = sObjectMgr->GetQuestTemplate(e.action.quest.quest))
1518 {
1519 if (!qid->HasSpecialFlag(QUEST_SPECIAL_FLAGS_EXPLORATION_OR_EVENT))
1520 {
1521 TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} SpecialFlags for Quest entry {} does not include FLAGS_EXPLORATION_OR_EVENT(2), skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.action.quest.quest);
1522 return false;
1523 }
1524 }
1525 else
1526 {
1527 TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} uses non-existent Quest entry {}, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.action.quest.quest);
1528 return false;
1529 }
1530 break;
1533 {
1534 TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} attempts to set phase {}. Phase mask cannot be used past phase {}, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.action.setEventPhase.phase, SMART_EVENT_PHASE_MAX-1);
1535 return false;
1536 }
1537 break;
1540 {
1541 TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} is incrementing phase by 0, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType());
1542 return false;
1543 }
1545 {
1546 TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} attempts to increment phase by too large value, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType());
1547 return false;
1548 }
1549 break;
1552 return false;
1553
1555 break;
1557 {
1558 if (std::all_of(std::begin(e.action.randomPhase.phases), std::end(e.action.randomPhase.phases), [](uint32 phase) { return phase == 0; }))
1559 {
1560 TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} does not have any non-zero phase",
1562 return false;
1563 }
1564
1565 if (std::any_of(std::begin(e.action.randomPhase.phases), std::end(e.action.randomPhase.phases), [](uint32 phase) { return phase >= SMART_EVENT_PHASE_MAX; }))
1566 {
1567 TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} attempts to set invalid phase, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType());
1568 return false;
1569 }
1570 break;
1571 }
1572 case SMART_ACTION_RANDOM_PHASE_RANGE: //PhaseMin, PhaseMax
1573 {
1576 {
1577 TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} attempts to set invalid phase, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType());
1578 return false;
1579 }
1580
1582 return false;
1583 break;
1584 }
1586 {
1588 return false;
1589
1591 for (CacheSpellContainer::const_iterator itr = sBounds.first; itr != sBounds.second; ++itr)
1592 TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} creature summon: There is a summon spell for creature entry {} (SpellId: {}, effect: {})",
1593 e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.action.summonCreature.creature, itr->second.first, itr->second.second);
1594
1596 {
1597 TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} uses incorrect TempSummonType {}, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.action.summonCreature.type);
1598 return false;
1599 }
1600
1602 break;
1603 }
1605 {
1607 return false;
1608
1610 for (CacheSpellContainer::const_iterator itr = sBounds.first; itr != sBounds.second; ++itr)
1611 TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} Kill Credit: There is a killcredit spell for creatureEntry {} (SpellId: {} effect: {})",
1612 e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.action.killedMonster.creature, itr->second.first, itr->second.second);
1613
1615 {
1616 TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} uses incorrect TargetType {}, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.GetTargetType());
1617 return false;
1618 }
1619 break;
1620 }
1623 return false;
1624
1626 break;
1629 {
1630 TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} uses incorrect Sheath state {}, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.action.setSheath.sheath);
1631 return false;
1632 }
1633 break;
1635 {
1637 {
1638 TC_LOG_ERROR("sql.sql", "SmartAIMgr: Creature {} Event {} Action {} uses invalid React State {}, skipped.", e.entryOrGuid, e.event_id, e.GetActionType(), e.action.react.state);
1639 return false;
1640 }
1641 break;
1642 }
1644 {
1646 return false;
1647
1649 for (CacheSpellContainer::const_iterator itr = sBounds.first; itr != sBounds.second; ++itr)
1650 TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} gameobject summon: There is a summon spell for gameobject entry {} (SpellId: {}, effect: {})",
1651 e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.action.summonGO.entry, itr->second.first, itr->second.second);
1652 break;
1653 }
1655 if (!IsItemValid(e, e.action.item.entry))
1656 return false;
1657
1658 if (!NotNULL(e, e.action.item.count))
1659 return false;
1660 break;
1662 {
1663 if (!IsItemValid(e, e.action.item.entry))
1664 return false;
1665
1666 if (!NotNULL(e, e.action.item.count))
1667 return false;
1668
1670 for (CacheSpellContainer::const_iterator itr = sBounds.first; itr != sBounds.second; ++itr)
1671 TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} Create Item: There is a create item spell for item {} (SpellId: {} effect: {})",
1672 e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.action.item.entry, itr->second.first, itr->second.second);
1673 break;
1674 }
1676 if (!sMapStore.LookupEntry(e.action.teleport.mapID))
1677 {
1678 TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} uses non-existent Map entry {}, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.action.teleport.mapID);
1679 return false;
1680 }
1681 break;
1684 return false;
1686 break;
1688 {
1689 WaypointPath const* path = sWaypointMgr->GetPath(e.action.wpStart.pathID);
1690 if (!path || path->nodes.empty())
1691 {
1692 TC_LOG_ERROR("sql.sql", "SmartAIMgr: Creature {} Event {} Action {} uses non-existent WaypointPath id {}, skipped.", e.entryOrGuid, e.event_id, e.GetActionType(), e.action.wpStart.pathID);
1693 return false;
1694 }
1696 return false;
1697
1700 break;
1701 }
1703 {
1705 return false;
1706
1708 return false;
1709 break;
1710 }
1712 {
1714 return false;
1715 break;
1716 }
1721 {
1722 TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} uses non-existent Power {}, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.action.power.powerType);
1723 return false;
1724 }
1725 break;
1727 {
1728 uint32 eventId = e.action.gameEventStop.id;
1729
1730 GameEventMgr::GameEventDataMap const& events = sGameEventMgr->GetEventMap();
1731 if (eventId < 1 || eventId >= events.size())
1732 {
1733 TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} uses non-existent event, eventId {}, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.action.gameEventStop.id);
1734 return false;
1735 }
1736
1737 GameEventData const& eventData = events[eventId];
1738 if (!eventData.isValid())
1739 {
1740 TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} uses non-existent event, eventId {}, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.action.gameEventStop.id);
1741 return false;
1742 }
1743 break;
1744 }
1746 {
1747 uint32 eventId = e.action.gameEventStart.id;
1748
1749 GameEventMgr::GameEventDataMap const& events = sGameEventMgr->GetEventMap();
1750 if (eventId < 1 || eventId >= events.size())
1751 {
1752 TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} uses non-existent event, eventId {}, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.action.gameEventStart.id);
1753 return false;
1754 }
1755
1756 GameEventData const& eventData = events[eventId];
1757 if (!eventData.isValid())
1758 {
1759 TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} uses non-existent event, eventId {}, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.action.gameEventStart.id);
1760 return false;
1761 }
1762 break;
1763 }
1764 case SMART_ACTION_EQUIP:
1765 {
1767 {
1768 if (int8 equipId = static_cast<int8>(e.action.equip.entry))
1769 {
1770 EquipmentInfo const* eInfo = sObjectMgr->GetEquipmentInfo(e.entryOrGuid, equipId);
1771 if (!eInfo)
1772 {
1773 TC_LOG_ERROR("sql.sql", "SmartScript: SMART_ACTION_EQUIP uses non-existent equipment info id {} for creature {}, skipped.", equipId, e.entryOrGuid);
1774 return false;
1775 }
1776 }
1777 }
1778 break;
1779 }
1781 {
1782 if (e.action.setInstanceData.type > 1)
1783 {
1784 TC_LOG_ERROR("sql.sql", "Entry {} SourceType {} Event {} Action {} uses invalid data type {} (value range 0-1), skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.action.setInstanceData.type);
1785 return false;
1786 }
1787 else if (e.action.setInstanceData.type == 1)
1788 {
1790 {
1791 TC_LOG_ERROR("sql.sql", "Entry {} SourceType {} Event {} Action {} uses invalid boss state {} (value range 0-5), skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.action.setInstanceData.data);
1792 return false;
1793 }
1794 }
1795 break;
1796 }
1799 {
1800 TC_LOG_ERROR("sql.sql", "Entry {} SourceType {} Event {} Action {} specifies invalid spawn data ({},{})", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.action.respawnData.spawnType, e.action.respawnData.spawnId);
1801 return false;
1802 }
1803 break;
1806 {
1807 TC_LOG_ERROR("sql.sql", "Entry {} SourceType {} Event {} Action {} does not specify duration", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType());
1808 return false;
1809 }
1810 break;
1813 break;
1815 {
1817 {
1818 TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} uses invalid movementType {}, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.action.movementSpeed.movementType);
1819 return false;
1820 }
1821
1823 {
1824 TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} uses speed 0, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType());
1825 return false;
1826 }
1827
1828 break;
1829 }
1831 {
1832 AreaTableEntry const* areaEntry = sAreaTableStore.LookupEntry(e.action.overrideLight.zoneId);
1833 if (!areaEntry)
1834 {
1835 TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} uses non-existent zoneId {}, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.action.overrideLight.zoneId);
1836 return false;
1837 }
1838
1839 if (areaEntry->ParentAreaID != 0)
1840 {
1841 TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} uses subzone (ID: {}) instead of zone, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.action.overrideLight.zoneId);
1842 return false;
1843 }
1844
1845 if (!sLightStore.LookupEntry(e.action.overrideLight.areaLightId))
1846 {
1847 TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} uses non-existent areaLightId {}, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.action.overrideLight.areaLightId);
1848 return false;
1849 }
1850
1852 {
1853 TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} uses non-existent overrideLightId {}, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.action.overrideLight.overrideLightId);
1854 return false;
1855 }
1856
1857 break;
1858 }
1860 {
1861 AreaTableEntry const* areaEntry = sAreaTableStore.LookupEntry(e.action.overrideWeather.zoneId);
1862 if (!areaEntry)
1863 {
1864 TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} uses non-existent zoneId {}, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.action.overrideWeather.zoneId);
1865 return false;
1866 }
1867
1868 if (areaEntry->ParentAreaID != 0)
1869 {
1870 TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} uses subzone (ID: {}) instead of zone, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.action.overrideWeather.zoneId);
1871 return false;
1872 }
1873
1874 break;
1875 }
1877 {
1879 {
1880 TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} is trying to set invalid HP percent {}, skipped.",
1882 return false;
1883 }
1884 break;
1885 }
1887 {
1889 break;
1890 }
1892 {
1894 break;
1895 }
1897 {
1899 break;
1900 }
1902 {
1904 break;
1905 }
1907 {
1909 break;
1910 }
1912 {
1914 break;
1915 }
1917 {
1919 break;
1920 }
1922 {
1924 break;
1925 }
1927 {
1929 break;
1930 }
1932 {
1935 break;
1936 }
1938 {
1940 break;
1941 }
1943 {
1946 break;
1947 }
1949 {
1951 break;
1952 }
1954 {
1956 break;
1957 }
1959 {
1961 break;
1962 }
1964 {
1966 break;
1967 }
1968 case SMART_ACTION_EVADE:
1969 {
1971 break;
1972 }
1974 {
1976 break;
1977 }
1979 {
1981 break;
1982 }
1984 {
1986 break;
1987 }
1989 {
1991 break;
1992 }
1994 {
1996 return false;
1997
1999 {
2000 TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} has gameObjectAction parameter out of range (max allowed {}, current value {}), skipped.",
2002 return false;
2003 }
2004 break;
2005 }
2010 case SMART_ACTION_DIE:
2054 break;
2055 // Unused
2073 case SMART_ACTION_FLEE:
2075 TC_LOG_ERROR("sql.sql", "SmartAIMgr: Unused action_type({}), event_type({}), Entry {} SourceType {} Event {}, skipped.", e.GetActionType(), e.GetEventType(), e.entryOrGuid, e.GetScriptType(), e.event_id);
2076 return false;
2077 default:
2078 TC_LOG_ERROR("sql.sql", "SmartAIMgr: Not handled action_type({}), event_type({}), Entry {} SourceType {} Event {}, skipped.", e.GetActionType(), e.GetEventType(), e.entryOrGuid, e.GetScriptType(), e.event_id);
2079 return false;
2080 }
2081
2083 return false;
2084
2085 return true;
2086}
2087
2089{
2091 return true;
2092
2093 uint32 entry = 0;
2094
2096 {
2097 entry = e.event.textOver.creatureEntry;
2098 }
2099 else
2100 {
2101 switch (e.GetTargetType())
2102 {
2106 return true; // ignore
2107 default:
2108 if (e.entryOrGuid < 0)
2109 {
2111 CreatureData const* data = sObjectMgr->GetCreatureData(guid);
2112 if (!data)
2113 {
2114 TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} using non-existent Creature guid {}, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), guid);
2115 return false;
2116 }
2117 else
2118 entry = data->id;
2119 }
2120 else
2121 entry = uint32(e.entryOrGuid);
2122 break;
2123 }
2124 }
2125
2126 if (!entry || !sCreatureTextMgr->TextExist(entry, uint8(id)))
2127 {
2128 TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} using non-existent Text id {}, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), id);
2129 return false;
2130 }
2131
2132 return true;
2133}
2134
2136{
2137 uint32 oldMSTime = getMSTime();
2138
2139 SpellInfo const* spellInfo = nullptr;
2140 for (uint32 i = 0; i < sSpellMgr->GetSpellInfoStoreSize(); ++i)
2141 {
2142 spellInfo = sSpellMgr->GetSpellInfo(i);
2143 if (!spellInfo)
2144 continue;
2145
2146 for (SpellEffectInfo const& spellEffectInfo : spellInfo->GetEffects())
2147 {
2148 if (spellEffectInfo.IsEffect(SPELL_EFFECT_SUMMON))
2149 SummonCreatureSpellStore.insert(std::make_pair(uint32(spellEffectInfo.MiscValue), std::make_pair(i, spellEffectInfo.EffectIndex)));
2150
2151 else if (spellEffectInfo.IsEffect(SPELL_EFFECT_SUMMON_OBJECT_WILD))
2152 SummonGameObjectSpellStore.insert(std::make_pair(uint32(spellEffectInfo.MiscValue), std::make_pair(i, spellEffectInfo.EffectIndex)));
2153
2154 else if (spellEffectInfo.IsEffect(SPELL_EFFECT_KILL_CREDIT) || spellEffectInfo.IsEffect(SPELL_EFFECT_KILL_CREDIT2))
2155 KillCreditSpellStore.insert(std::make_pair(uint32(spellEffectInfo.MiscValue), std::make_pair(i, spellEffectInfo.EffectIndex)));
2156
2157 else if (spellEffectInfo.IsEffect(SPELL_EFFECT_CREATE_ITEM))
2158 CreateItemSpellStore.insert(std::make_pair(uint32(spellEffectInfo.ItemType), std::make_pair(i, spellEffectInfo.EffectIndex)));
2159 }
2160 }
2161
2162 TC_LOG_INFO("server.loading", ">> Loaded SmartAIMgr Helpers in {} ms", GetMSTimeDiffToNow(oldMSTime));
2163}
2164
2172
2174{
2175 return SummonCreatureSpellStore.equal_range(creatureEntry);
2176}
2177
2179{
2180 return SummonGameObjectSpellStore.equal_range(gameObjectEntry);
2181}
2182
2184{
2185 return KillCreditSpellStore.equal_range(killCredit);
2186}
2187
2192
2193ObjectGuidVector::ObjectGuidVector(ObjectVector const& objectVector) : _objectVector(objectVector)
2194{
2195 _guidVector.reserve(_objectVector.size());
2196 for (WorldObject* obj : _objectVector)
2197 _guidVector.push_back(obj->GetGUID());
2198}
2199
2201{
2202 _objectVector.clear();
2203
2204 for (ObjectGuid const& guid : _guidVector)
2205 if (WorldObject* obj = ObjectAccessor::GetWorldObject(ref, guid))
2206 _objectVector.push_back(obj);
2207}
#define M_PI
Definition Common.h:72
#define sCreatureTextMgr
DBCStorage< ItemEntry > sItemStore(Itemfmt)
DBCStorage< CreatureDisplayInfoEntry > sCreatureDisplayInfoStore(CreatureDisplayInfofmt)
DBCStorage< AreaTriggerEntry > sAreaTriggerStore(AreaTriggerEntryfmt)
DBCStorage< SoundEntriesEntry > sSoundEntriesStore(SoundEntriesfmt)
DBCStorage< EmotesTextEntry > sEmotesTextStore(EmotesTextEntryfmt)
DBCStorage< LightEntry > sLightStore(LightEntryfmt)
DBCStorage< FactionTemplateEntry > sFactionTemplateStore(FactionTemplateEntryfmt)
DBCStorage< TaxiPathEntry > sTaxiPathStore(TaxiPathEntryfmt)
DBCStorage< MapEntry > sMapStore(MapEntryfmt)
DBCStorage< AreaTableEntry > sAreaTableStore(AreaTableEntryfmt)
DBCStorage< EmotesEntry > sEmotesStore(EmotesEntryfmt)
std::shared_ptr< PreparedResultSet > PreparedQueryResult
DatabaseWorkerPool< WorldDatabaseConnection > WorldDatabase
Accessor to the world database.
uint8_t uint8
Definition Define.h:135
int8_t int8
Definition Define.h:131
int32_t int32
Definition Define.h:129
uint32_t uint32
Definition Define.h:133
#define sGameEventMgr
@ TO_BE_DECIDED
#define TC_LOG_WARN(filterType__,...)
Definition Log.h:162
#define TC_LOG_DEBUG(filterType__,...)
Definition Log.h:156
#define TC_LOG_ERROR(filterType__,...)
Definition Log.h:165
#define TC_LOG_INFO(filterType__,...)
Definition Log.h:159
bool IsInvalidMovementGeneratorType(uint8 const type)
@ TEMPSUMMON_MANUAL_DESPAWN
@ TEMPSUMMON_TIMED_OR_DEAD_DESPAWN
#define sObjectMgr
Definition ObjectMgr.h:1721
@ QUEST_SPECIAL_FLAGS_EXPLORATION_OR_EVENT
Definition QuestDef.h:162
@ SPELL_EFFECT_KILL_CREDIT
@ SPELL_EFFECT_SUMMON
@ SPELL_EFFECT_KILL_CREDIT2
@ SPELL_EFFECT_SUMMON_OBJECT_WILD
@ SPELL_EFFECT_CREATE_ITEM
@ TARGET_UNIT_CASTER
@ EVENT_CHARGE
@ MAX_POWERS
#define TC_SAI_IS_BOOLEAN_VALID(e, value)
SmartScriptType
@ SMART_SCRIPT_TYPE_TIMED_ACTIONLIST
@ SMART_SCRIPT_TYPE_MAX
@ SMART_SCRIPT_TYPE_CREATURE
@ SMART_SCRIPT_TYPE_GAMEOBJECT
@ SMART_SCRIPT_TYPE_AREATRIGGER
std::vector< SmartScriptHolder > SmartAIEventList
@ SMART_EVENT_FLAGS_ALL
@ SMART_EVENT_FLAG_NOT_REPEATABLE
SMARTAI_TARGETS
@ SMART_TARGET_LOOT_RECIPIENTS
@ SMART_TARGET_CLOSEST_CREATURE
@ SMART_TARGET_CREATURE_DISTANCE
@ SMART_TARGET_HOSTILE_RANDOM_NOT_TOP
@ SMART_TARGET_INVOKER_PARTY
@ SMART_TARGET_CLOSEST_FRIENDLY
@ SMART_TARGET_CLOSEST_GAMEOBJECT
@ SMART_TARGET_VEHICLE_PASSENGER
@ SMART_TARGET_GAMEOBJECT_RANGE
@ SMART_TARGET_CREATURE_GUID
@ SMART_TARGET_PLAYER_RANGE
@ SMART_TARGET_CLOSEST_UNSPAWNED_GAMEOBJECT
@ SMART_TARGET_VICTIM
@ SMART_TARGET_GAMEOBJECT_DISTANCE
@ SMART_TARGET_CREATURE_RANGE
@ SMART_TARGET_CLOSEST_PLAYER
@ SMART_TARGET_HOSTILE_RANDOM
@ SMART_TARGET_GAMEOBJECT_GUID
@ SMART_TARGET_HOSTILE_SECOND_AGGRO
@ SMART_TARGET_OWNER_OR_SUMMONER
@ SMART_TARGET_SELF
@ SMART_TARGET_ACTION_INVOKER
@ SMART_TARGET_POSITION
@ SMART_TARGET_HOSTILE_LAST_AGGRO
@ SMART_TARGET_ACTION_INVOKER_VEHICLE
@ SMART_TARGET_FARTHEST
@ SMART_TARGET_THREAT_LIST
@ SMART_TARGET_CLOSEST_ENEMY
@ SMART_TARGET_NONE
@ SMART_TARGET_PLAYER_DISTANCE
@ SMART_TARGET_STORED
std::vector< WorldObject * > ObjectVector
const uint32 SmartAIEventMask[SMART_EVENT_END][2]
@ SMART_SCRIPT_RESPAWN_CONDITION_AREA
@ SMART_SCRIPT_RESPAWN_CONDITION_MAP
SMART_ACTION
@ SMART_ACTION_REMOVE_TIMED_EVENT
@ SMART_ACTION_NONE
@ SMART_ACTION_SET_GO_FLAG
@ SMART_ACTION_WP_RESUME
@ SMART_ACTION_UPDATE_TEMPLATE
@ SMART_ACTION_STORE_TARGET_LIST
@ SMART_ACTION_SET_HEALTH_REGEN
@ SMART_ACTION_ACTIVATE_GOBJECT
@ SMART_ACTION_FORCE_DESPAWN
@ SMART_ACTION_GAME_EVENT_START
@ SMART_ACTION_CALL_RANDOM_RANGE_TIMED_ACTIONLIST
@ SMART_ACTION_REMOVE_UNIT_FIELD_BYTES_1
@ SMART_ACTION_SET_DISABLE_GRAVITY
@ SMART_ACTION_SET_INST_DATA64
@ SMART_ACTION_SET_FACTION
@ SMART_ACTION_THREAT_SINGLE_PCT
@ SMART_ACTION_OFFER_QUEST
@ SMART_ACTION_OVERRIDE_LIGHT
@ SMART_ACTION_REMOVE_ALL_GAMEOBJECTS
@ SMART_ACTION_SET_INGAME_PHASE_MASK
@ SMART_ACTION_SET_UNIT_FIELD_BYTES_1
@ SMART_ACTION_CLOSE_GOSSIP
@ SMART_ACTION_DISABLE_EVADE
@ SMART_ACTION_ADD_GO_FLAG
@ SMART_ACTION_ADD_DYNAMIC_FLAG
@ SMART_ACTION_KILL_UNIT
@ SMART_ACTION_LOAD_EQUIPMENT
@ SMART_ACTION_END
@ SMART_ACTION_CALL_AREAEXPLOREDOREVENTHAPPENS
@ SMART_ACTION_ATTACK_START
@ SMART_ACTION_SET_UNIT_FLAG
@ SMART_ACTION_CALL_GROUPEVENTHAPPENS
@ SMART_ACTION_MOUNT_TO_ENTRY_OR_MODEL
@ SMART_ACTION_INVOKER_CAST
@ SMART_ACTION_JUMP_TO_POS
@ SMART_ACTION_CALL_RANDOM_TIMED_ACTIONLIST
@ SMART_ACTION_SEND_GOSSIP_MENU
@ SMART_ACTION_SET_COUNTER
@ SMART_ACTION_FLEE_FOR_ASSIST
@ SMART_ACTION_EQUIP
@ SMART_ACTION_SET_ROOT
@ SMART_ACTION_ATTACK_STOP
@ SMART_ACTION_SUMMON_GO
@ SMART_ACTION_SET_HOVER
@ SMART_ACTION_WP_PAUSE
@ SMART_ACTION_SIMPLE_TALK
@ SMART_ACTION_REMOVE_AURAS_BY_TYPE
@ SMART_ACTION_CAST
@ SMART_ACTION_SPAWN_SPAWNGROUP
@ SMART_ACTION_ALLOW_COMBAT_MOVEMENT
@ SMART_ACTION_ADD_AURA
@ SMART_ACTION_THREAT_ALL_PCT
@ SMART_ACTION_SOUND
@ SMART_ACTION_SET_MOVEMENT_SPEED
@ SMART_ACTION_PLAY_CINEMATIC
@ SMART_ACTION_ADD_NPC_FLAG
@ SMART_ACTION_EVADE
@ SMART_ACTION_FAIL_QUEST
@ SMART_ACTION_INTERRUPT_SPELL
@ SMART_ACTION_ADD_POWER
@ SMART_ACTION_REMOVE_DYNAMIC_FLAG
@ SMART_ACTION_RANDOM_SOUND
@ SMART_ACTION_SET_IMMUNE_PC
@ SMART_ACTION_SET_POWER
@ SMART_ACTION_SEND_TARGET_TO_TARGET
@ SMART_ACTION_REMOVE_POWER
@ SMART_ACTION_SET_DYNAMIC_FLAG
@ SMART_ACTION_RESUME_MOVEMENT
@ SMART_ACTION_GO_SET_GO_STATE
@ SMART_ACTION_MOVE_OFFSET
@ SMART_ACTION_REMOVE_ITEM
@ SMART_ACTION_SEND_GO_CUSTOM_ANIM
@ SMART_ACTION_MORPH_TO_ENTRY_OR_MODEL
@ SMART_ACTION_REMOVE_UNIT_FLAG
@ SMART_ACTION_RANDOM_PHASE
@ SMART_ACTION_SET_EMOTE_STATE
@ SMART_ACTION_CROSS_CAST
@ SMART_ACTION_WP_STOP
@ SMART_ACTION_GAME_EVENT_STOP
@ SMART_ACTION_CALL_KILLEDMONSTER
@ SMART_ACTION_TALK
@ SMART_ACTION_CALL_SCRIPT_RESET
@ SMART_ACTION_SET_DATA
@ SMART_ACTION_WP_START
@ SMART_ACTION_COMBAT_STOP
@ SMART_ACTION_SET_RUN
@ SMART_ACTION_ACTIVATE_GAMEOBJECT
@ SMART_ACTION_ADD_TO_STORED_TARGET_LIST
@ SMART_ACTION_SET_HEALTH_PCT
@ SMART_ACTION_AUTO_ATTACK
@ SMART_ACTION_SET_INVINCIBILITY_HP_LEVEL
@ SMART_ACTION_SET_VISIBILITY
@ SMART_ACTION_RANDOM_PHASE_RANGE
@ SMART_ACTION_GO_SET_LOOT_STATE
@ SMART_ACTION_SELF_CAST
@ SMART_ACTION_SET_SWIM
@ SMART_ACTION_SET_SIGHT_DIST
@ SMART_ACTION_SET_INST_DATA
@ SMART_ACTION_REMOVE_GO_FLAG
@ SMART_ACTION_CALL_FOR_HELP
@ SMART_ACTION_SET_UNINTERACTIBLE
@ SMART_ACTION_OVERRIDE_WEATHER
@ SMART_ACTION_ADD_THREAT
@ SMART_ACTION_TELEPORT
@ SMART_ACTION_PLAYMOVIE
@ SMART_ACTION_TRIGGER_RANDOM_TIMED_EVENT
@ SMART_ACTION_FOLLOW
@ SMART_ACTION_PLAY_EMOTE
@ SMART_ACTION_SET_EVENT_PHASE
@ SMART_ACTION_DESPAWN_SPAWNGROUP
@ SMART_ACTION_SET_CORPSE_DELAY
@ SMART_ACTION_SET_SHEATH
@ SMART_ACTION_SET_ORIENTATION
@ SMART_ACTION_RESPAWN_BY_SPAWNID
@ SMART_ACTION_SET_NPC_FLAG
@ SMART_ACTION_MOVE_TO_POS
@ SMART_ACTION_RANDOM_EMOTE
@ SMART_ACTION_INC_EVENT_PHASE
@ SMART_ACTION_ENABLE_TEMP_GOBJ
@ SMART_ACTION_CREATE_TIMED_EVENT
@ SMART_ACTION_DIE
@ SMART_ACTION_RESET_SCRIPT_BASE_OBJECT
@ SMART_ACTION_REMOVE_NPC_FLAG
@ SMART_ACTION_INSTALL_AI_TEMPLATE
@ SMART_ACTION_SUMMON_CREATURE
@ SMART_ACTION_RESET_GOBJECT
@ SMART_ACTION_CALL_TIMED_ACTIONLIST
@ SMART_ACTION_SET_IN_COMBAT_WITH_ZONE
@ SMART_ACTION_SET_CAN_FLY
@ SMART_ACTION_SET_HOME_POS
@ SMART_ACTION_ADD_ITEM
@ SMART_ACTION_SET_ACTIVE
@ SMART_ACTION_SET_RANGED_MOVEMENT
@ SMART_ACTION_ACTIVATE_TAXI
@ SMART_ACTION_START_CLOSEST_WAYPOINT
@ SMART_ACTION_SUMMON_CREATURE_GROUP
@ SMART_ACTION_SET_REACT_STATE
@ SMART_ACTION_RANDOM_MOVE
@ SMART_ACTION_OVERRIDE_SCRIPT_BASE_OBJECT
@ SMART_ACTION_SET_IMMUNE_NPC
@ SMART_ACTION_TRIGGER_TIMED_EVENT
@ SMART_ACTION_REMOVEAURASFROMSPELL
@ SMART_ACTION_FLEE
@ SMART_ACTION_PAUSE_MOVEMENT
SMART_EVENT
@ SMART_EVENT_IC_LOS
@ SMART_EVENT_EVADE
@ SMART_EVENT_ACTION_DONE
@ SMART_EVENT_SUMMON_DESPAWNED
@ SMART_EVENT_SPELLHIT
@ SMART_EVENT_RECEIVE_EMOTE
@ SMART_EVENT_FRIENDLY_HEALTH_PCT
@ SMART_EVENT_QUEST_FAIL
@ SMART_EVENT_ON_AURA_APPLIED
@ SMART_EVENT_DATA_SET
@ SMART_EVENT_RECEIVE_HEAL
@ SMART_EVENT_TIMED_EVENT_TRIGGERED
@ SMART_EVENT_CHARMED_TARGET
@ SMART_EVENT_TARGET_MANA_PCT
@ SMART_EVENT_QUEST_COMPLETION
@ SMART_EVENT_JUST_CREATED
@ SMART_EVENT_HEALTH_PCT
@ SMART_EVENT_EVENT_PHASE_CHANGE
@ SMART_EVENT_AREATRIGGER_ONTRIGGER
@ SMART_EVENT_DISTANCE_GAMEOBJECT
@ SMART_EVENT_ON_SPELLCLICK
@ SMART_EVENT_MOVEMENTINFORM
@ SMART_EVENT_RANGE
@ SMART_EVENT_MANA_PCT
@ SMART_EVENT_PASSENGER_REMOVED
@ SMART_EVENT_ON_AURA_REMOVED
@ SMART_EVENT_INSTANCE_PLAYER_ENTER
@ SMART_EVENT_LINK
@ SMART_EVENT_WAYPOINT_PAUSED
@ SMART_EVENT_REACHED_HOME
@ SMART_EVENT_TRANSPORT_ADDCREATURE
@ SMART_EVENT_REWARD_QUEST
@ SMART_EVENT_END
@ SMART_EVENT_GO_EVENT_INFORM
@ SMART_EVENT_GO_LOOT_STATE_CHANGED
@ SMART_EVENT_UPDATE_IC
@ SMART_EVENT_RESET
@ SMART_EVENT_JUST_SUMMONED
@ SMART_EVENT_CHARMED
@ SMART_EVENT_AI_INIT
@ SMART_EVENT_WAYPOINT_START
@ SMART_EVENT_ON_SPELL_CAST
@ SMART_EVENT_SPELLHIT_TARGET
@ SMART_EVENT_GAME_EVENT_START
@ SMART_EVENT_KILL
@ SMART_EVENT_TRANSPORT_REMOVE_PLAYER
@ SMART_EVENT_GOSSIP_HELLO
@ SMART_EVENT_GOSSIP_SELECT
@ SMART_EVENT_CORPSE_REMOVED
@ SMART_EVENT_PASSENGER_BOARDED
@ SMART_EVENT_UPDATE
@ SMART_EVENT_TRANSPORT_ADDPLAYER
@ SMART_EVENT_WAYPOINT_ENDED
@ SMART_EVENT_IS_BEHIND_TARGET
@ SMART_EVENT_UPDATE_OOC
@ SMART_EVENT_ACCEPTED_QUEST
@ SMART_EVENT_COUNTER_SET
@ SMART_EVENT_FRIENDLY_MISSING_BUFF
@ SMART_EVENT_WAYPOINT_RESUMED
@ SMART_EVENT_ON_SPELL_FAILED
@ SMART_EVENT_WAYPOINT_REACHED
@ SMART_EVENT_TARGET_BUFFED
@ SMART_EVENT_RESPAWN
@ SMART_EVENT_QUEST_ACCEPTED
@ SMART_EVENT_FRIENDLY_HEALTH
@ SMART_EVENT_QUEST_REWARDED
@ SMART_EVENT_TEXT_OVER
@ SMART_EVENT_DEATH
@ SMART_EVENT_TRANSPORT_RELOCATE
@ SMART_EVENT_GAME_EVENT_END
@ SMART_EVENT_DAMAGED
@ SMART_EVENT_FOLLOW_COMPLETED
@ SMART_EVENT_QUEST_OBJ_COMPLETION
@ SMART_EVENT_DISTANCE_CREATURE
@ SMART_EVENT_WAYPOINT_STOPPED
@ SMART_EVENT_SUMMONED_UNIT_DIES
@ SMART_EVENT_FRIENDLY_IS_CC
@ SMART_EVENT_OOC_LOS
@ SMART_EVENT_ON_SPELL_START
@ SMART_EVENT_ON_DESPAWN
@ SMART_EVENT_AGGRO
@ SMART_EVENT_TARGET_HEALTH_PCT
@ SMART_EVENT_VICTIM_CASTING
@ SMART_EVENT_DAMAGED_TARGET
@ SMART_EVENT_HAS_AURA
@ SMART_EVENT_SUMMONED_UNIT
@ SMART_EVENT_PHASE_ALL
@ SMART_EVENT_PHASE_MAX
std::unordered_map< int32, SmartAIEventList > SmartAIEventMap
const uint32 SmartAITypeMask[SMART_SCRIPT_TYPE_MAX][2]
std::pair< CacheSpellContainer::const_iterator, CacheSpellContainer::const_iterator > CacheSpellContainerBounds
SpawnObjectType
Definition SpawnData.h:30
#define sSpellMgr
Definition SpellMgr.h:738
uint32 GetMSTimeDiffToNow(uint32 oldMSTime)
Definition Timer.h:57
uint32 getMSTime()
Definition Timer.h:33
@ REACT_AGGRESSIVE
#define MAX_MOVE_TYPE
@ MAX_SHEATH_STATE
constexpr std::underlying_type< E >::type AsUnderlyingType(E enumValue)
Definition Util.h:554
#define sWaypointMgr
@ WORLD_SEL_SMART_SCRIPTS
Class used to access individual fields of database query result.
Definition Field.h:92
uint8 GetUInt8() const
Definition Field.cpp:29
uint16 GetUInt16() const
Definition Field.cpp:45
float GetFloat() const
Definition Field.cpp:93
uint32 GetUInt32() const
Definition Field.cpp:61
int32 GetInt32() const
Definition Field.cpp:69
std::vector< GameEventData > GameEventDataMap
ObjectVector _objectVector
void UpdateObjects(WorldObject const &ref) const
ObjectGuidVector(ObjectVector const &objectVector)
uint32 LowType
Definition ObjectGuid.h:142
SmartAIEventMap mEventMap[SMART_SCRIPT_TYPE_MAX]
CacheSpellContainer SummonCreatureSpellStore
void UnLoadHelperStores()
CacheSpellContainerBounds GetSummonCreatureSpellContainerBounds(uint32 creatureEntry) const
SmartAIEventList GetScript(int32 entry, SmartScriptType type)
static bool IsTextEmoteValid(SmartScriptHolder const &e, uint32 entry)
bool IsTargetValid(SmartScriptHolder const &e)
static bool NotNULL(SmartScriptHolder const &e, uint32 data)
CacheSpellContainer CreateItemSpellStore
void LoadHelperStores()
static bool IsSoundValid(SmartScriptHolder const &e, uint32 entry)
static SmartScriptHolder & FindLinkedEvent(SmartAIEventList &list, uint32 link)
bool IsEventValid(SmartScriptHolder &e)
static bool IsGameObjectValid(SmartScriptHolder const &e, uint32 entry)
static bool CheckUnusedTargetParams(SmartScriptHolder const &e)
static bool IsMinMaxValid(SmartScriptHolder const &e, uint32 min, uint32 max)
static bool EventHasInvoker(SMART_EVENT event)
CacheSpellContainerBounds GetCreateItemSpellContainerBounds(uint32 itemId) const
CacheSpellContainer SummonGameObjectSpellStore
static bool IsQuestValid(SmartScriptHolder const &e, uint32 entry)
static bool IsCreatureValid(SmartScriptHolder const &e, uint32 entry)
static bool IsAreaTriggerValid(SmartScriptHolder const &e, uint32 entry)
static bool IsTextValid(SmartScriptHolder const &e, uint32 id)
CacheSpellContainerBounds GetSummonGameObjectSpellContainerBounds(uint32 gameObjectEntry) const
static bool CheckUnusedEventParams(SmartScriptHolder const &e)
static SmartAIMgr * instance()
void LoadSmartAIFromDB()
CacheSpellContainerBounds GetKillCreditSpellContainerBounds(uint32 killCredit) const
static bool CheckUnusedActionParams(SmartScriptHolder const &e)
static bool IsItemValid(SmartScriptHolder const &e, uint32 entry)
CacheSpellContainer KillCreditSpellStore
static SmartScriptHolder & FindLinkedSourceEvent(SmartAIEventList &list, uint32 eventId)
static bool IsEmoteValid(SmartScriptHolder const &e, uint32 entry)
static bool IsSpellValid(SmartScriptHolder const &e, uint32 entry)
uint32 SchoolMask
Definition SpellInfo.h:361
std::array< SpellEffectInfo, MAX_SPELL_EFFECTS > const & GetEffects() const
Definition SpellInfo.h:482
TC_GAME_API WorldObject * GetWorldObject(WorldObject const &, ObjectGuid const &)
std::string AIName
bool isValid() const
struct SmartAction::@65::@144 loadEquipment
struct SmartAction::@65::@97 invincHP
struct SmartAction::@65::@161 raw
uint32 sounds[4]
struct SmartAction::@65::@83 combatMove
struct SmartAction::@65::@102 summonGO
struct SmartAction::@65::@70 morphOrMount
struct SmartAction::@65::@146 pauseMovement
struct SmartAction::@65::@139 closestWaypointFromList
struct SmartAction::@65::@69 faction
struct SmartAction::@65::@130 sendTargetToTarget
uint32 gameObjectAction
struct SmartAction::@65::@119 delunitByte
struct SmartAction::@65::@129 setGoLootState
struct SmartAction::@65::@85 incEventPhase
SAIBool regenHealth
struct SmartAction::@65::@106 wpPause
uint32 wps[SMART_ACTION_PARAM_COUNT]
SAIBool allowOverride
struct SmartAction::@65::@111 teleport
struct SmartAction::@65::@99 setData
struct SmartAction::@65::@137 gameEventStop
struct SmartAction::@65::@157 setUninteractible
struct SmartAction::@65::@134 goState
struct SmartAction::@65::@155 setImmunePC
uint32 emotes[SMART_ACTION_PARAM_COUNT]
SAIBool withDelayed
SAIBool withInstant
struct SmartAction::@65::@92 setInstanceData64
struct SmartAction::@65::@127 moveToPos
struct SmartAction::@65::@152 setHover
struct SmartAction::@65::@118 setunitByte
struct SmartAction::@65::@126 enableTempGO
struct SmartAction::@65::@128 sendGossipMenu
struct SmartAction::@65::@141 corpseDelay
struct SmartAction::@65::@121 randTimedActionList
struct SmartAction::@65::@108 item
struct SmartAction::@65::@140 randomSound
struct SmartAction::@65::@78 crossCast
struct SmartAction::@65::@138 gameEventStart
struct SmartAction::@65::@74 questOffer
SAIBool toRespawnPosition
SAIBool attackInvoker
SAIBool useTalkTarget
struct SmartAction::@65::@110 setDisableGravity
struct SmartAction::@65::@160 resumeMovement
SAIBool uninteractible
struct SmartAction::@65::@153 evade
struct SmartAction::@65::@89 randomPhaseRange
struct SmartAction::@65::@120 timedActionList
struct SmartAction::@65::@115 movie
struct SmartAction::@65::@158 activateGameObject
struct SmartAction::@65::@81 threat
struct SmartAction::@65::@67 talk
struct SmartAction::@65::@114 timeEvent
struct SmartAction::@65::@151 overrideWeather
struct SmartAction::@65::@147 respawnData
struct SmartAction::@65::@100 moveRandom
SAIBool updateLevel
struct SmartAction::@65::@131 setRangedMovement
uint32 actionLists[SMART_ACTION_PARAM_COUNT]
SMART_ACTION type
struct SmartAction::@65::@150 overrideLight
struct SmartAction::@65::@156 setImmuneNPC
struct SmartAction::@65::@125 fleeAssist
struct SmartAction::@65::@148 cinematic
uint32 phases[SMART_ACTION_PARAM_COUNT]
struct SmartAction::@65::@104 taxi
struct SmartAction::@65::@154 setHealthPct
struct SmartAction::@65::@132 setHealthRegen
struct SmartAction::@65::@75 react
struct SmartAction::@65::@123 interruptSpellCasting
SAIBool onlyOwnedAuras
uint32 overrideLightId
struct SmartAction::@65::@88 randomPhase
struct SmartAction::@65::@93 updateTemplate
struct SmartAction::@65::@96 forceDespawn
struct SmartAction::@65::@124 jump
struct SmartAction::@65::@136 power
struct SmartAction::@65::@86 removeAura
SAIBool disablePathfinding
struct SmartAction::@65::@98 ingamePhaseMask
struct SmartAction::@65::@91 setInstanceData
struct SmartAction::@65::@77 cast
struct SmartAction::@65::@68 simpleTalk
struct SmartAction::@65::@133 setRoot
SAIBool withEmote
struct SmartAction::@65::@109 setRun
struct SmartAction::@65::@142 disableEvade
struct SmartAction::@65::@113 storeTargets
struct SmartAction::@65::@76 randomEmote
struct SmartAction::@65::@82 autoAttack
struct SmartAction::@65::@87 follow
SAIBool directAdd
struct SmartAction::@65::@94 callHelp
struct SmartAction::@65::@105 wpStart
struct SmartAction::@65::@101 visibility
struct SmartAction::@65::@116 equip
struct SmartAction::@65::@79 summonCreature
struct SmartAction::@65::@107 wpStop
struct SmartAction::@65::@149 movementSpeed
struct SmartAction::@65::@159 addToStoredTargets
struct SmartAction::@65::@143 groupSpawn
struct SmartAction::@65::@80 threatPCT
struct SmartAction::@65::@103 active
struct SmartAction::@65::@84 setEventPhase
struct SmartAction::@65::@145 randomTimedEvent
struct SmartAction::@65::@112 setCounter
struct SmartAction::@65::@122 randRangeTimedActionList
struct SmartAction::@65::@95 setSheath
struct SmartAction::@65::@90 killedMonster
struct SmartAction::@65::@135 creatureGroup
uint32 event_flags
struct SmartEvent::@29::@62 counter
struct SmartEvent::@29::@36 minMax
struct SmartEvent::@29::@56 gameEvent
struct SmartEvent::@29::@50 instancePlayerEnter
struct SmartEvent::@29::@45 movementInform
uint32 event_phase_mask
struct SmartEvent::@29::@44 charm
struct SmartEvent::@29::@52 textOver
struct SmartEvent::@29::@32 kill
uint32 cooldownMax
struct SmartEvent::@29::@40 summoned
struct SmartEvent::@29::@54 gossipHello
struct SmartEvent::@29::@59 doAction
struct SmartEvent::@29::@37 targetCasting
struct SmartEvent::@29::@48 transportAddCreature
struct SmartEvent::@29::@43 aura
struct SmartEvent::@29::@46 dataSet
struct SmartEvent::@29::@58 eventInform
struct SmartEvent::@29::@39 missingBuff
uint32 hostilityMode
Hostility mode of the event. 0: hostile, 1: not hostile, 2: any.
struct SmartEvent::@29::@49 transportRelocate
struct SmartEvent::@29::@61 distance
struct SmartEvent::@29::@38 friendlyCC
struct SmartEvent::@29::@34 los
uint32 event_chance
struct SmartEvent::@29::@63 spellCast
struct SmartEvent::@29::@35 respawn
struct SmartEvent::@29::@60 friendlyHealthPct
SAIBool playerOnly
uint32 creatureEntry
struct SmartEvent::@29::@57 goLootStateChanged
struct SmartEvent::@29::@33 spellHit
struct SmartEvent::@29::@53 timedEvent
struct SmartEvent::@29::@47 waypoint
uint32 gameEventId
uint32 textGroupID
uint32 cooldownMin
struct SmartEvent::@29::@51 areatrigger
struct SmartEvent::@29::@64 raw
SAIBool onRemove
struct SmartEvent::@29::@55 gossip
struct SmartEvent::@29::@31 minMaxRepeat
SMART_EVENT type
uint32 GetScriptType() const
uint32 GetEventType() const
uint32 GetTargetType() const
SmartScriptType source_type
uint32 GetActionType() const
struct SmartTarget::@162::@180 vehicle
struct SmartTarget::@162::@170 playerRange
struct SmartTarget::@162::@166 unitRange
struct SmartTarget::@162::@179 owner
struct SmartTarget::@162::@175 unitClosest
struct SmartTarget::@162::@171 stored
struct SmartTarget::@162::@167 unitGUID
SAIBool useCharmerOrOwner
struct SmartTarget::@162::@173 goGUID
struct SmartTarget::@162::@181 threatList
struct SmartTarget::@162::@178 closestFriendly
struct SmartTarget::@162::@177 closestAttackable
struct SmartTarget::@162::@172 goRange
struct SmartTarget::@162::@168 unitDistance
struct SmartTarget::@162::@174 goDistance
struct SmartTarget::@162::@182 raw
SMARTAI_TARGETS type
struct SmartTarget::@162::@169 playerDistance
struct SmartTarget::@162::@165 farthest
struct SmartTarget::@162::@176 goClosest
struct SmartTarget::@162::@164 hostilRandom
uint32 id
Definition SpawnData.h:96
std::vector< WaypointNode > nodes