TrinityCore
Loading...
Searching...
No Matches
SmartAI.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 "SmartAI.h"
19#include "Creature.h"
20#include "CreatureGroups.h"
21#include "DBCStructure.h"
22#include "GameObject.h"
23#include "Group.h"
24#include "Log.h"
25#include "MotionMaster.h"
26#include "ObjectAccessor.h"
27#include "PetDefines.h"
28#include "Player.h"
29#include "ScriptMgr.h"
30#include "SpellAuras.h"
31#include "Vehicle.h"
32#include "WaypointManager.h"
33
34SmartAI::SmartAI(Creature* creature) : CreatureAI(creature), _charmed(false), _followCreditType(0), _followArrivedTimer(0), _followCredit(0), _followArrivedEntry(0), _followDistance(0.f), _followAngle(0.f),
35 _escortState(SMART_ESCORT_NONE), _escortNPCFlags(0), _escortInvokerCheckTimer(1000), _currentWaypointNode(0), _waypointReached(false), _waypointPauseTimer(0), _waypointPauseForced(false), _repeatWaypointPath(false),
36 _OOCReached(false), _waypointPathEnded(false), _run(true), _evadeDisabled(false), _canAutoAttack(true), _canCombatMove(true), _invincibilityHPLevel(0), _despawnTime(0), _despawnState(0), _vehicleConditionsTimer(0),
37 _gossipReturn(false), _escortQuestId(0)
38{
40}
41
43{
44 return !_charmed;
45}
46
47void SmartAI::StartPath(uint32 pathId/* = 0*/, bool repeat/* = false*/, Unit* invoker/* = nullptr*/, uint32 nodeId/* = 1*/)
48{
50 StopPath();
51
52 if (!pathId)
53 return;
54
55 WaypointPath const* path = LoadPath(pathId);
56 if (!path)
57 return;
58
59 _currentWaypointNode = nodeId;
60 _waypointPathEnded = false;
61
62 _repeatWaypointPath = repeat;
63
64 // Do not use AddEscortState, removing everything from previous
66
67 if (invoker && invoker->GetTypeId() == TYPEID_PLAYER)
68 {
71 }
72
74}
75
77{
79 return nullptr;
80
81 WaypointPath const* path = sWaypointMgr->GetPath(entry);
82 if (!path || path->nodes.empty())
83 {
84 GetScript()->SetPathId(0);
85 return nullptr;
86 }
87
88 GetScript()->SetPathId(entry);
89 return path;
90}
91
92void SmartAI::PausePath(uint32 delay, bool forced)
93{
95 {
96 me->PauseMovement(delay, MOTION_SLOT_DEFAULT, forced);
98 {
99 std::pair<uint32, uint32> waypointInfo = me->GetCurrentWaypointInfo();
100 GetScript()->ProcessEventsFor(SMART_EVENT_WAYPOINT_PAUSED, nullptr, waypointInfo.first, waypointInfo.second);
101 }
102 return;
103 }
104
106 {
107 TC_LOG_ERROR("scripts.ai.sai", "SmartAI::PausePath: Creature wanted to pause waypoint (current waypoint: {}) movement while already paused, ignoring. ({})", _currentWaypointNode, me->GetGUID().ToString());
108 return;
109 }
110
111 _waypointPauseTimer = delay;
112
113 if (forced)
114 {
115 _waypointPauseForced = forced;
116 SetRun(_run);
117 me->PauseMovement();
119 }
120 else
121 _waypointReached = false;
122
125}
126
128{
130 {
131 // The whole resume logic doesn't support this case
132 return false;
133 }
134
136}
137
138void SmartAI::StopPath(uint32 DespawnTime, uint32 quest, bool fail)
139{
141 {
142 std::pair<uint32, uint32> waypointInfo = { 0, 0 };
144 waypointInfo = me->GetCurrentWaypointInfo();
145
146 if (_despawnState != 2)
147 SetDespawnTime(DespawnTime);
148
150
151 if (waypointInfo.first)
152 GetScript()->ProcessEventsFor(SMART_EVENT_WAYPOINT_STOPPED, nullptr, waypointInfo.first, waypointInfo.second);
153
154 if (!fail)
155 {
156 if (waypointInfo.first)
157 GetScript()->ProcessEventsFor(SMART_EVENT_WAYPOINT_ENDED, nullptr, waypointInfo.first, waypointInfo.second);
158 if (_despawnState == 1)
159 StartDespawn();
160 }
161 return;
162 }
163
164 if (quest)
165 _escortQuestId = quest;
166
167 if (_despawnState != 2)
168 SetDespawnTime(DespawnTime);
169
171
173
174 EndPath(fail);
175}
176
177void SmartAI::EndPath(bool fail)
178{
180
182
183 if (_escortNPCFlags)
184 {
186 _escortNPCFlags = 0;
187 }
188
190 if (targets && _escortQuestId)
191 {
192 if (targets->size() == 1 && GetScript()->IsPlayer((*targets->begin())))
193 {
194 Player* player = targets->front()->ToPlayer();
195 if (!fail && player->IsAtGroupRewardDistance(me) && !player->HasCorpse())
197
198 if (fail)
199 player->FailQuest(_escortQuestId);
200
201 if (Group* group = player->GetGroup())
202 {
203 for (GroupReference* groupRef = group->GetFirstMember(); groupRef != nullptr; groupRef = groupRef->next())
204 {
205 Player* groupGuy = groupRef->GetSource();
206 if (!groupGuy->IsInMap(player))
207 continue;
208
209 if (!fail && groupGuy->IsAtGroupRewardDistance(me) && !groupGuy->HasCorpse())
211 else if (fail)
212 groupGuy->FailQuest(_escortQuestId);
213 }
214 }
215 }
216 else
217 {
218 for (WorldObject* target : *targets)
219 {
220 if (GetScript()->IsPlayer(target))
221 {
222 Player* player = target->ToPlayer();
223 if (!fail && player->IsAtGroupRewardDistance(me) && !player->HasCorpse())
225 else if (fail)
226 player->FailQuest(_escortQuestId);
227 }
228 }
229 }
230 }
231
232 // End Path events should be only processed if it was SUCCESSFUL stop or stop called by SMART_ACTION_WAYPOINT_STOP
233 if (fail)
234 return;
235
236 uint32 pathid = GetScript()->GetPathId();
238
240 {
241 if (IsAIControlled())
242 StartPath(GetScript()->GetPathId(), _repeatWaypointPath);
243 }
244 else if (pathid == GetScript()->GetPathId()) // if it's not the same pathid, our script wants to start another path; don't override it
245 GetScript()->SetPathId(0);
246
247 if (_despawnState == 1)
248 StartDespawn();
249}
250
264
273
275{
276 if (!me->IsAlive())
277 {
278 if (IsEngaged())
280 return;
281 }
282
283 CheckConditions(diff);
284
285 bool hasVictim = UpdateVictim();
286
287 GetScript()->OnUpdate(diff);
288
289 UpdatePath(diff);
290 UpdateFollow(diff);
291 UpdateDespawn(diff);
292
293 if (!IsAIControlled())
294 return;
295
296 if (!hasVictim)
297 return;
298
299 if (_canAutoAttack)
301}
302
304{
305 if (ObjectVector const* targets = GetScript()->GetStoredTargetVector(SMART_ESCORT_TARGETS, *me))
306 {
308 if (targets->size() == 1 && GetScript()->IsPlayer((*targets->begin())))
309 {
310 Player* player = (*targets->begin())->ToPlayer();
311 if (me->GetDistance(player) <= checkDist)
312 return true;
313
314 if (Group* group = player->GetGroup())
315 {
316 for (GroupReference* groupRef = group->GetFirstMember(); groupRef != nullptr; groupRef = groupRef->next())
317 {
318 Player* groupGuy = groupRef->GetSource();
319 if (groupGuy->IsInMap(player) && me->GetDistance(groupGuy) <= checkDist)
320 return true;
321 }
322 }
323 }
324 else
325 {
326 for (WorldObject* target : *targets)
327 {
328 if (GetScript()->IsPlayer(target))
329 {
330 if (me->GetDistance(target->ToPlayer()) <= checkDist)
331 return true;
332 }
333 }
334 }
335
336 // no valid target found
337 return false;
338 }
339
340 // no player invoker was stored, just ignore range check
341 return true;
342}
343
345{
347 {
348 GetScript()->ProcessEventsFor(SMART_EVENT_WAYPOINT_REACHED, nullptr, nodeId, pathId);
349 return;
350 }
351
352 _currentWaypointNode = nodeId;
353
355
357 {
358 _waypointReached = true;
359 me->PauseMovement();
361 }
363 {
364 WaypointPath const* path = sWaypointMgr->GetPath(pathId);
365 if (path && _currentWaypointNode == path->nodes.size())
366 _waypointPathEnded = true;
367 else
368 SetRun(_run);
369 }
370}
371
374{
376 {
377 GetScript()->ProcessEventsFor(SMART_EVENT_WAYPOINT_ENDED, nullptr, nodeId, pathId);
378 return;
379 }
380}
381
383{
386
388
390 return;
391
393 _OOCReached = true;
394}
395
397{
398 if (_evadeDisabled)
399 {
401 return;
402 }
403
404 if (!IsAIControlled())
405 {
406 me->AttackStop();
407 return;
408 }
409
410 if (!_EnterEvadeMode())
411 return;
412
414
415 GetScript()->ProcessEventsFor(SMART_EVENT_EVADE); // must be after _EnterEvadeMode (spells, auras, ...)
416
417 SetRun(_run);
418
419 if (Unit* owner = me->GetCharmerOrOwner())
420 {
423 }
425 {
428 }
429 else if (Unit* target = !_followGUID.IsEmpty() ? ObjectAccessor::GetUnit(*me, _followGUID) : nullptr)
430 {
432 // evade is not cleared in MoveFollow, so we can't keep it
434 }
435 else
437
439 GetScript()->OnReset();
440}
441
443{
444 if (!who)
445 return;
446
448
449 if (!IsAIControlled())
450 return;
451
453 return;
454
456}
457
459{
461 return false;
462
463 if (!who || !who->GetVictim())
464 return false;
465
466 // experimental (unknown) flag not present
468 return false;
469
470 // not a player
472 return false;
473
474 if (!who->isInAccessiblePlaceFor(me))
475 return false;
476
477 if (!CanAIAttack(who))
478 return false;
479
480 // we cannot attack in evade mode
481 if (me->IsInEvadeMode())
482 return false;
483
484 // or if enemy is in evade mode
485 if (who->GetTypeId() == TYPEID_UNIT && who->ToCreature()->IsInEvadeMode())
486 return false;
487
488 if (!me->IsValidAssistTarget(who->GetVictim()))
489 return false;
490
491 // too far away and no free sight
493 {
494 me->EngageWithTarget(who);
495 return true;
496 }
497
498 return false;
499}
500
502{
504
505 _despawnTime = 0;
506 _despawnState = 0;
508 _followGUID.Clear(); // do not reset follower on Reset(), we need it after combat evade
509 _followDistance = 0;
510 _followAngle = 0;
511 _followCredit = 0;
512 _followArrivedTimer = 1000;
515}
516
518{
520
521 if (me->isDead())
522 return;
523
525 GetScript()->OnReset();
526}
527
529{
530 GetScript()->OnReset();
532
533 CreatureGroup* formation = me->GetFormation();
534 if (!formation || formation->GetLeader() == me || !formation->IsFormed())
535 {
537 {
538 if (me->GetWaypointPath())
540 }
541
543 }
544 else if (formation->IsFormed())
545 me->GetMotionMaster()->MoveIdle(); // wait the order of leader
546}
547
549{
550 if (IsAIControlled())
551 me->InterruptNonMeleeSpells(false); // must be before ProcessEvents
552
554}
555
557{
559 EndPath(true);
560
562}
563
565{
567}
568
573
578
580{
581 // dont allow charmed npcs to act on their own
582 if (!IsAIControlled())
583 {
584 if (who)
585 me->Attack(who, _canAutoAttack);
586 return;
587 }
588
589 if (who && me->Attack(who, _canAutoAttack))
590 {
592 me->PauseMovement();
593
594 if (_canCombatMove)
595 {
596 SetRun(_run);
598 }
599 }
600}
601
602void SmartAI::SpellHit(WorldObject* caster, SpellInfo const* spellInfo)
603{
604 GetScript()->ProcessEventsFor(SMART_EVENT_SPELLHIT, caster->ToUnit(), 0, 0, false, spellInfo, caster->ToGameObject());
605}
606
607void SmartAI::SpellHitTarget(WorldObject* target, SpellInfo const* spellInfo)
608{
609 GetScript()->ProcessEventsFor(SMART_EVENT_SPELLHIT_TARGET, target->ToUnit(), 0, 0, false, spellInfo, target->ToGameObject());
610}
611
612void SmartAI::OnSpellCast(SpellInfo const* spellInfo)
613{
614 GetScript()->ProcessEventsFor(SMART_EVENT_ON_SPELL_CAST, nullptr, 0, 0, false, spellInfo);
615}
616
617void SmartAI::OnSpellFailed(SpellInfo const* spellInfo)
618{
619 GetScript()->ProcessEventsFor(SMART_EVENT_ON_SPELL_FAILED, nullptr, 0, 0, false, spellInfo);
620}
621
622void SmartAI::OnSpellStart(SpellInfo const* spellInfo)
623{
624 GetScript()->ProcessEventsFor(SMART_EVENT_ON_SPELL_START, nullptr, 0, 0, false, spellInfo);
625}
626
628{
629 GetScript()->ProcessEventsFor(SMART_EVENT_ON_AURA_APPLIED, nullptr, 0, 0, false, aurApp->GetBase()->GetSpellInfo());
630}
631
633{
634 GetScript()->ProcessEventsFor(SMART_EVENT_ON_AURA_REMOVED, nullptr, 0, 0, false, aurApp->GetBase()->GetSpellInfo());
635}
636
637void SmartAI::DamageTaken(Unit* doneBy, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/)
638{
640
641 if (!IsAIControlled()) // don't allow players to use unkillable units
642 return;
643
645 damage = me->GetHealth() - _invincibilityHPLevel; // damage should not be nullified, because of player damage req.
646}
647
648void SmartAI::HealReceived(Unit* doneBy, uint32& addhealth)
649{
651}
652
653void SmartAI::ReceiveEmote(Player* player, uint32 textEmote)
654{
656}
657
659{
660 GetScript()->ProcessEventsFor(SMART_EVENT_JUST_SUMMONED, summoner->ToUnit(), 0, 0, false, nullptr, summoner->ToGameObject());
661}
662
663void SmartAI::DamageDealt(Unit* doneTo, uint32& damage, DamageEffectType /*damagetype*/)
664{
666}
667
672
674{
675 GetScript()->ProcessEventsFor(SMART_EVENT_CORPSE_REMOVED, nullptr, respawnDelay);
676}
677
682
683void SmartAI::PassengerBoarded(Unit* who, int8 seatId, bool apply)
684{
686}
687
688void SmartAI::OnCharmed(bool isNew)
689{
690 bool const charmed = me->IsCharmed();
691 if (charmed) // do this before we change charmed state, as charmed state might prevent these things from processing
692 {
694 EndPath(true);
695 }
696
697 _charmed = charmed;
698
699 if (charmed && !me->isPossessed() && !me->IsVehicle())
701
702 if (!charmed && !me->IsInEvadeMode())
703 {
705 StartPath(GetScript()->GetPathId(), true);
706 else
707 me->SetWalk(!_run);
708
709 if (!me->LastCharmerGUID.IsEmpty())
710 {
712 if (Unit* lastCharmer = ObjectAccessor::GetUnit(*me, me->LastCharmerGUID))
713 me->EngageWithTarget(lastCharmer);
715
716 if (!me->IsInCombat())
718 }
719 }
720
721 GetScript()->ProcessEventsFor(SMART_EVENT_CHARMED, nullptr, 0, 0, charmed);
722
723 if (!GetScript()->HasAnyEventWithFlag(SMART_EVENT_FLAG_WHILE_CHARMED)) // we can change AI if there are no events with this flag
724 UnitAI::OnCharmed(isNew);
725}
726
728{
730}
731
733{
734 return 0;
735}
736
737void SmartAI::SetData(uint32 id, uint32 value, Unit* invoker)
738{
739 GetScript()->ProcessEventsFor(SMART_EVENT_DATA_SET, invoker, id, value);
740}
741
742void SmartAI::SetGUID(ObjectGuid const& /*guid*/, int32 /*id*/) { }
743
745{
746 return ObjectGuid::Empty;
747}
748
749void SmartAI::SetRun(bool run)
750{
751 me->SetWalk(!run);
752 _run = run;
753}
754
756{
757 me->SetDisableGravity(fly);
758}
759
761{
762 _evadeDisabled = disable;
763}
764
766{
767 _gossipReturn = false;
769 return _gossipReturn;
770}
771
772bool SmartAI::OnGossipSelect(Player* player, uint32 menuId, uint32 gossipListId)
773{
774 _gossipReturn = false;
775 GetScript()->ProcessEventsFor(SMART_EVENT_GOSSIP_SELECT, player, menuId, gossipListId);
776 return _gossipReturn;
777}
778
779bool SmartAI::OnGossipSelectCode(Player* /*player*/, uint32 /*menuId*/, uint32 /*gossipListId*/, char const* /*code*/)
780{
781 return false;
782}
783
784void SmartAI::OnQuestAccept(Player* player, Quest const* quest)
785{
787}
788
789void SmartAI::OnQuestReward(Player* player, Quest const* quest, uint32 opt)
790{
792}
793
794void SmartAI::SetCombatMove(bool on, bool stopMoving)
795{
796 if (_canCombatMove == on)
797 return;
798
799 _canCombatMove = on;
800
801 if (!IsAIControlled())
802 return;
803
804 if (me->IsEngaged())
805 {
806 if (on)
807 {
808 if (!me->HasReactState(REACT_PASSIVE) && me->GetVictim() && !me->GetMotionMaster()->HasMovementGenerator([](MovementGenerator const* movement) -> bool
809 {
810 return movement->GetMovementGeneratorType() == CHASE_MOTION_TYPE && movement->Priority == MOTION_PRIORITY_NORMAL;
811 }))
812 {
813 SetRun(_run);
815 }
816 }
817 else if (MovementGenerator* movement = me->GetMotionMaster()->GetMovementGenerator([](MovementGenerator const* a) -> bool
818 {
819 return a->GetMovementGeneratorType() == CHASE_MOTION_TYPE && a->Priority == MOTION_PRIORITY_NORMAL;
820 }))
821 {
822 me->GetMotionMaster()->Remove(movement);
823 if (stopMoving)
824 me->StopMoving();
825 }
826 }
827}
828
829void SmartAI::SetFollow(Unit* target, float dist, float angle, uint32 credit, uint32 end, uint32 creditType)
830{
831 if (!target)
832 {
833 StopFollow(false);
834 return;
835 }
836
837 _followGUID = target->GetGUID();
838 _followDistance = dist;
839 _followAngle = angle;
840 _followArrivedTimer = 1000;
841 _followCredit = credit;
843 _followCreditType = creditType;
844 SetRun(_run);
846}
847
848void SmartAI::StopFollow(bool complete)
849{
851 _followDistance = 0;
852 _followAngle = 0;
853 _followCredit = 0;
854 _followArrivedTimer = 1000;
859
860 if (!complete)
861 return;
862
864 if (player)
865 {
868 else
870 }
871
872 SetDespawnTime(5000);
873 StartDespawn();
875}
876
878{
879 GetScript()->SetTimedActionList(e, entry, invoker);
880}
881
882void SmartAI::OnGameEvent(bool start, uint16 eventId)
883{
885}
886
887void SmartAI::OnSpellClick(Unit* clicker, bool spellClickHandled)
888{
889 if (!spellClickHandled)
890 return;
891
893}
894
896{
898 return;
899
900 if (_vehicleConditionsTimer <= diff)
901 {
902 if (Vehicle* vehicleKit = me->GetVehicleKit())
903 {
904 for (std::pair<int8 const, VehicleSeat>& seat : vehicleKit->Seats)
905 if (Unit* passenger = ObjectAccessor::GetUnit(*me, seat.second.Passenger.Guid))
906 {
907 if (Player* player = passenger->ToPlayer())
908 {
909 if (!sConditionMgr->IsObjectMeetingNotGroupedConditions(CONDITION_SOURCE_TYPE_CREATURE_TEMPLATE_VEHICLE, me->GetEntry(), player, me))
910 {
911 player->ExitVehicle();
912 return; // check other pessanger in next tick
913 }
914 }
915 }
916 }
917
919 }
920 else
922}
923
925{
927 return;
928
929 if (_escortInvokerCheckTimer < diff)
930 {
932 {
933 StopPath(0, _escortQuestId, true);
934
935 // allow to properly hook out of range despawn action, which in most cases should perform the same operation as dying
938 return;
939 }
941 }
942 else
944
945 // handle pause
947 {
948 // Resume only if there was a pause timer set
950 {
951 if (_waypointPauseTimer <= diff)
952 ResumePath();
953 else
954 _waypointPauseTimer -= diff;
955 }
956 }
957 else if (_waypointPathEnded) // end path
958 {
959 _waypointPathEnded = false;
960 StopPath();
961 return;
962 }
963
965 {
966 if (_OOCReached) // reached OOC WP
967 {
968 _OOCReached = false;
972 ResumePath();
973 }
974 }
975}
976
978{
979 if (!_followGUID.IsEmpty())
980 {
981 if (_followArrivedTimer < diff)
982 {
984 {
985 StopFollow(true);
986 return;
987 }
988
989 _followArrivedTimer = 1000;
990 }
991 else
992 _followArrivedTimer -= diff;
993 }
994}
995
997{
998 if (_despawnState <= 1 || _despawnState > 3)
999 return;
1000
1001 if (_despawnTime < diff)
1002 {
1003 if (_despawnState == 2)
1004 {
1005 me->SetVisible(false);
1006 _despawnTime = 5000;
1007 _despawnState++;
1008 }
1009 else
1011 }
1012 else
1013 _despawnTime -= diff;
1014}
1015
1017{
1018 GetScript()->OnUpdate(diff);
1019}
1020
1022{
1024 // do not call respawn event if go is not spawned
1025 if (me->isSpawned())
1027 //Reset();
1028}
1029
1031{
1032 GetScript()->OnReset();
1033}
1034
1035// Called when a player opens a gossip dialog with the gameobject.
1037{
1038 _gossipReturn = false;
1039 GetScript()->ProcessEventsFor(SMART_EVENT_GOSSIP_HELLO, player, 0, 0, false, nullptr, me);
1040 return _gossipReturn;
1041}
1042
1043// Called when a player selects a gossip item in the gameobject's gossip menu.
1045{
1046 _gossipReturn = false;
1047 GetScript()->ProcessEventsFor(SMART_EVENT_GOSSIP_SELECT, player, sender, action, false, nullptr, me);
1048 return _gossipReturn;
1049}
1050
1051// Called when a player selects a gossip with a code in the gameobject's gossip menu.
1052bool SmartGameObjectAI::OnGossipSelectCode(Player* /*player*/, uint32 /*menuId*/, uint32 /*gossipListId*/, char const* /*code*/)
1053{
1054 return false;
1055}
1056
1057// Called when a player accepts a quest from the gameobject.
1059{
1060 GetScript()->ProcessEventsFor(SMART_EVENT_ACCEPTED_QUEST, player, quest->GetQuestId(), 0, false, nullptr, me);
1061}
1062
1063// Called when a player selects a quest reward.
1064void SmartGameObjectAI::OnQuestReward(Player* player, Quest const* quest, uint32 opt)
1065{
1066 GetScript()->ProcessEventsFor(SMART_EVENT_REWARD_QUEST, player, quest->GetQuestId(), opt, false, nullptr, me);
1067}
1068
1070{
1071 _gossipReturn = false;
1072 GetScript()->ProcessEventsFor(SMART_EVENT_GOSSIP_HELLO, player, 1, 0, false, nullptr, me);
1073 return _gossipReturn;
1074}
1075
1076// Called when the gameobject is destroyed (destructible buildings only).
1078{
1079 GetScript()->ProcessEventsFor(SMART_EVENT_DEATH, attacker ? attacker->ToUnit() : nullptr, eventId, 0, false, nullptr, me);
1080}
1081
1083{
1084 GetScript()->ProcessEventsFor(SMART_EVENT_DATA_SET, invoker, id, value);
1085}
1086
1088{
1089 GetScript()->SetTimedActionList(e, entry, invoker);
1090}
1091
1093{
1095}
1096
1101
1106
1108{
1109 GetScript()->ProcessEventsFor(SMART_EVENT_SPELLHIT, caster->ToUnit(), 0, 0, false, spellInfo);
1110}
1111
1116
1121
1126
1128{
1129 public:
1130
1131 SmartTrigger() : AreaTriggerScript("SmartTrigger") { }
1132
1133 bool OnTrigger(Player* player, AreaTriggerEntry const* trigger) override
1134 {
1135 if (!player->IsAlive())
1136 return false;
1137
1138 TC_LOG_DEBUG("scripts.ai", "AreaTrigger {} is using SmartTrigger script", trigger->ID);
1139 SmartScript script;
1140 script.OnInitialize(player, trigger);
1141 script.ProcessEventsFor(SMART_EVENT_AREATRIGGER_ONTRIGGER, player, trigger->ID);
1142 return true;
1143 }
1144};
1145
1147{
1148 new SmartTrigger();
1149}
#define sConditionMgr
@ CONDITION_SOURCE_TYPE_CREATURE_TEMPLATE_VEHICLE
int8_t int8
Definition Define.h:131
int32_t int32
Definition Define.h:129
uint16_t uint16
Definition Define.h:134
uint32_t uint32
Definition Define.h:133
#define TC_LOG_DEBUG(filterType__,...)
Definition Log.h:156
#define TC_LOG_ERROR(filterType__,...)
Definition Log.h:165
@ MOTION_PRIORITY_NORMAL
@ MOTION_SLOT_DEFAULT
@ WAYPOINT_MOTION_TYPE
@ POINT_MOTION_TYPE
#define INTERACTION_DISTANCE
@ TYPEID_UNIT
Definition ObjectGuid.h:38
@ TYPEID_PLAYER
Definition ObjectGuid.h:39
#define PET_FOLLOW_ANGLE
Definition PetDefines.h:86
#define PET_FOLLOW_DIST
Definition PetDefines.h:85
@ CREATURE_TYPE_FLAG_CAN_ASSIST
void AddSC_SmartScripts()
Registers scripts required by the SAI scripting system.
Definition SmartAI.cpp:1146
static float constexpr SMART_MAX_AID_DIST
Definition SmartAI.h:37
@ SMART_ESCORT_ESCORTING
Definition SmartAI.h:31
@ SMART_ESCORT_PAUSED
Definition SmartAI.h:33
@ SMART_ESCORT_RETURNING
Definition SmartAI.h:32
@ SMART_ESCORT_NONE
Definition SmartAI.h:30
static float constexpr SMART_ESCORT_MAX_PLAYER_DIST
Definition SmartAI.h:36
@ SMART_EVENT_FLAG_WHILE_CHARMED
std::vector< WorldObject * > ObjectVector
@ SMART_EVENT_EVADE
@ SMART_EVENT_ACTION_DONE
@ SMART_EVENT_SUMMON_DESPAWNED
@ SMART_EVENT_SPELLHIT
@ SMART_EVENT_RECEIVE_EMOTE
@ SMART_EVENT_ON_AURA_APPLIED
@ SMART_EVENT_DATA_SET
@ SMART_EVENT_RECEIVE_HEAL
@ SMART_EVENT_AREATRIGGER_ONTRIGGER
@ SMART_EVENT_ON_SPELLCLICK
@ SMART_EVENT_MOVEMENTINFORM
@ SMART_EVENT_PASSENGER_REMOVED
@ SMART_EVENT_ON_AURA_REMOVED
@ SMART_EVENT_WAYPOINT_PAUSED
@ SMART_EVENT_REACHED_HOME
@ SMART_EVENT_REWARD_QUEST
@ SMART_EVENT_GO_EVENT_INFORM
@ SMART_EVENT_GO_LOOT_STATE_CHANGED
@ SMART_EVENT_JUST_SUMMONED
@ SMART_EVENT_CHARMED
@ SMART_EVENT_ON_SPELL_CAST
@ SMART_EVENT_SPELLHIT_TARGET
@ SMART_EVENT_GAME_EVENT_START
@ SMART_EVENT_KILL
@ SMART_EVENT_GOSSIP_HELLO
@ SMART_EVENT_GOSSIP_SELECT
@ SMART_EVENT_CORPSE_REMOVED
@ SMART_EVENT_PASSENGER_BOARDED
@ SMART_EVENT_WAYPOINT_ENDED
@ SMART_EVENT_ACCEPTED_QUEST
@ SMART_EVENT_WAYPOINT_RESUMED
@ SMART_EVENT_ON_SPELL_FAILED
@ SMART_EVENT_WAYPOINT_REACHED
@ SMART_EVENT_RESPAWN
@ SMART_EVENT_DEATH
@ SMART_EVENT_GAME_EVENT_END
@ SMART_EVENT_DAMAGED
@ SMART_EVENT_FOLLOW_COMPLETED
@ SMART_EVENT_WAYPOINT_STOPPED
@ SMART_EVENT_SUMMONED_UNIT_DIES
@ SMART_EVENT_ON_SPELL_START
@ SMART_EVENT_ON_DESPAWN
@ SMART_EVENT_AGGRO
@ SMART_EVENT_DAMAGED_TARGET
@ SMART_EVENT_SUMMONED_UNIT
@ SMART_ESCORT_LAST_OOC_POINT
@ SMART_ESCORT_TARGETS
@ REACT_PASSIVE
NPCFlags
Non Player Character flags.
@ UNIT_NPC_FLAG_NONE
@ UNIT_STATE_EVADE
Definition Unit.h:242
DamageEffectType
Definition Unit.h:352
#define sWaypointMgr
Aura * GetBase() const
Definition SpellAuras.h:67
SpellInfo const * GetSpellInfo() const
Definition SpellAuras.h:115
virtual void MoveInLineOfSight(Unit *)
bool IsEngaged() const
Definition CreatureAI.h:105
@ EVADE_REASON_NO_HOSTILES
Definition CreatureAI.h:94
bool _EnterEvadeMode(EvadeReason why=EVADE_REASON_OTHER)
virtual void JustAppeared()
bool UpdateVictim()
Creature *const me
Definition CreatureAI.h:82
void EngagementOver()
Creature * GetLeader() const
bool IsFormed() const
void SetHomePosition(float x, float y, float z, float o)
Definition Creature.h:293
void GetHomePosition(float &x, float &y, float &z, float &ori) const
Definition Creature.h:295
uint32 GetWaypointPath() const
Definition Creature.h:303
bool HasReactState(ReactStates state) const
Definition Creature.h:121
bool IsEngaged() const override
void DespawnOrUnsummon(Milliseconds timeToDespawn=0s, Seconds forceRespawnTime=0s)
std::pair< uint32, uint32 > GetCurrentWaypointInfo() const
Definition Creature.h:307
CreatureTemplate const * GetCreatureTemplate() const
Definition Creature.h:186
CreatureGroup * GetFormation()
Definition Creature.h:313
bool IsInEvadeMode() const
Definition Creature.h:146
GameObject *const me
bool isSpawned() const
Definition GameObject.h:155
GroupReference * next()
Definition Group.h:165
bool HasMovementGenerator(std::function< bool(MovementGenerator const *)> const &filter, MovementSlot slot=MOTION_SLOT_ACTIVE) const
MovementGeneratorType GetCurrentMovementGeneratorType() const
void MoveChase(Unit *target, Optional< ChaseRange > dist={}, Optional< ChaseAngle > angle={})
void MovePoint(uint32 id, Position const &pos, bool generatePath=true, Optional< float > finalOrient={})
void MovePath(uint32 pathId, bool repeatable)
void MoveFollow(Unit *target, float dist, ChaseAngle angle, MovementSlot slot=MOTION_SLOT_ACTIVE)
void MoveTargetedHome()
MovementGenerator * GetMovementGenerator(std::function< bool(MovementGenerator const *)> const &filter, MovementSlot slot=MOTION_SLOT_ACTIVE) const
void Remove(MovementGenerator *movement, MovementSlot slot=MOTION_SLOT_ACTIVE)
static ObjectGuid const Empty
Definition ObjectGuid.h:140
bool IsEmpty() const
Definition ObjectGuid.h:172
std::string ToString() const
void Clear()
Definition ObjectGuid.h:150
static Creature * ToCreature(Object *o)
Definition Object.h:186
static Unit * ToUnit(Object *o)
Definition Object.h:192
static GameObject * ToGameObject(Object *o)
Definition Object.h:198
TypeID GetTypeId() const
Definition Object.h:93
uint32 GetEntry() const
Definition Object.h:81
static ObjectGuid GetGUID(Object const *o)
Definition Object.h:78
static Player * ToPlayer(Object *o)
Definition Object.h:180
bool HasCorpse() const
Definition Player.h:1757
void GroupEventHappens(uint32 questId, WorldObject const *pEventObject)
Definition Player.cpp:16032
bool IsAtGroupRewardDistance(WorldObject const *pRewardSource) const
Definition Player.cpp:23664
Group * GetGroup()
Definition Player.h:2171
void AreaExploredOrEventHappens(uint32 questId)
Definition Player.cpp:16008
void FailQuest(uint32 quest_id)
Definition Player.cpp:15040
void RewardPlayerAndGroupAtEvent(uint32 creature_id, WorldObject *pRewardSource)
Definition Player.cpp:23636
uint32 GetQuestId() const
Definition QuestDef.h:229
uint32 _escortQuestId
Definition SmartAI.h:290
void OnGameEvent(bool start, uint16 eventId) override
Definition SmartAI.cpp:882
void AddEscortState(uint32 escortState)
Definition SmartAI.h:63
void SpellHitTarget(WorldObject *target, SpellInfo const *spellInfo) override
Definition SmartAI.cpp:607
void OnSpellStart(SpellInfo const *spellInfo) override
Definition SmartAI.cpp:622
bool OnGossipSelect(Player *player, uint32 menuId, uint32 gossipListId) override
Definition SmartAI.cpp:772
void AttackStart(Unit *who) override
Definition SmartAI.cpp:579
bool _charmed
Definition SmartAI.h:254
void IsSummonedBy(WorldObject *summoner) override
Definition SmartAI.cpp:658
void WaypointPathEnded(uint32 nodeId, uint32 pathId) override
Definition SmartAI.cpp:373
bool CanResumePath()
Definition SmartAI.cpp:127
bool HasEscortState(uint32 escortState) const
Definition SmartAI.h:59
void OnQuestReward(Player *player, Quest const *quest, uint32 opt) override
Definition SmartAI.cpp:789
uint32 _followArrivedEntry
Definition SmartAI.h:258
float _followDistance
Definition SmartAI.h:260
void PausePath(uint32 delay, bool forced=false)
Definition SmartAI.cpp:92
void PassengerBoarded(Unit *who, int8 seatId, bool apply) override
== Fields =======================================
Definition SmartAI.cpp:683
void SetGUID(ObjectGuid const &guid, int32 id=0) override
Definition SmartAI.cpp:742
bool OnGossipHello(Player *player) override
Definition SmartAI.cpp:765
void DamageDealt(Unit *doneTo, uint32 &damage, DamageEffectType) override
Definition SmartAI.cpp:663
void OnSpellClick(Unit *clicker, bool spellClickHandled) override
Definition SmartAI.cpp:887
void OnCharmed(bool isNew) override
Definition SmartAI.cpp:688
bool _run
Definition SmartAI.h:274
uint32 _vehicleConditionsTimer
Definition SmartAI.h:285
bool AssistPlayerInCombatAgainst(Unit *who)
Definition SmartAI.cpp:458
uint32 _escortInvokerCheckTimer
Definition SmartAI.h:265
void OnSpellCast(SpellInfo const *spellInfo) override
Definition SmartAI.cpp:612
bool _waypointPathEnded
Definition SmartAI.h:272
void StopPath(uint32 DespawnTime=0, uint32 quest=0, bool fail=false)
Definition SmartAI.cpp:138
void SetDespawnTime(uint32 t)
Definition SmartAI.h:218
void StartDespawn()
Definition SmartAI.h:223
void OnQuestAccept(Player *player, Quest const *quest) override
Definition SmartAI.cpp:784
void JustReachedHome() override
Definition SmartAI.cpp:528
bool _canCombatMove
Definition SmartAI.h:277
void EndPath(bool fail=false)
Definition SmartAI.cpp:177
bool _vehicleConditions
Definition SmartAI.h:284
bool _waypointReached
Definition SmartAI.h:267
void SetFollow(Unit *target, float dist=0.0f, float angle=0.0f, uint32 credit=0, uint32 end=0, uint32 creditType=0)
Definition SmartAI.cpp:829
uint32 _despawnTime
Definition SmartAI.h:280
void DamageTaken(Unit *doneBy, uint32 &damage, DamageEffectType, SpellInfo const *) override
Definition SmartAI.cpp:637
void OnAuraRemoved(AuraApplication const *aurApp) override
Definition SmartAI.cpp:632
uint32 _despawnState
Definition SmartAI.h:281
void JustEngagedWith(Unit *enemy) override
Definition SmartAI.cpp:548
void UpdateAI(uint32 diff) override
Definition SmartAI.cpp:274
void OnDespawn() override
Definition SmartAI.cpp:678
bool OnGossipSelectCode(Player *player, uint32 menuId, uint32 gossipListId, char const *code) override
Definition SmartAI.cpp:779
void UpdateDespawn(uint32 diff)
Definition SmartAI.cpp:996
void SetCombatMove(bool on, bool stopMoving=false)
Definition SmartAI.cpp:794
bool _gossipReturn
Definition SmartAI.h:288
float _followAngle
Definition SmartAI.h:261
void StopFollow(bool complete)
Definition SmartAI.cpp:848
void JustDied(Unit *killer) override
Definition SmartAI.cpp:556
void RemoveEscortState(uint32 escortState)
Definition SmartAI.h:67
uint32 _currentWaypointNode
Definition SmartAI.h:266
WaypointPath const * LoadPath(uint32 entry)
Definition SmartAI.cpp:76
void InitializeAI() override
Definition SmartAI.cpp:501
ObjectGuid GetGUID(int32 id=0) const override
Definition SmartAI.cpp:744
uint32 _escortNPCFlags
Definition SmartAI.h:264
bool _waypointPauseForced
Definition SmartAI.h:269
uint32 _followArrivedTimer
Definition SmartAI.h:256
void OnAuraApplied(AuraApplication const *aurApp) override
Definition SmartAI.cpp:627
uint32 GetData(uint32 id=0) const override
Definition SmartAI.cpp:732
void WaypointReached(uint32 nodeId, uint32 pathId) override
Definition SmartAI.cpp:344
bool IsAIControlled() const
Definition SmartAI.cpp:42
SmartAI(Creature *creature)
Definition SmartAI.cpp:34
void EnterEvadeMode(EvadeReason why=EVADE_REASON_OTHER) override
Definition SmartAI.cpp:396
ObjectGuid _followGUID
Definition SmartAI.h:259
void OnSpellFailed(SpellInfo const *spellInfo) override
Definition SmartAI.cpp:617
void StartPath(uint32 pathId=0, bool repeat=false, Unit *invoker=nullptr, uint32 nodeId=1)
Definition SmartAI.cpp:47
void SummonedCreatureDespawn(Creature *unit) override
Definition SmartAI.cpp:668
void SetDisableGravity(bool disable=true)
Definition SmartAI.cpp:755
void JustAppeared() override
Definition SmartAI.cpp:517
void HealReceived(Unit *doneBy, uint32 &addhealth) override
Definition SmartAI.cpp:648
bool _evadeDisabled
Definition SmartAI.h:275
void ReturnToLastOOCPos()
Definition SmartAI.cpp:265
uint32 _waypointPauseTimer
Definition SmartAI.h:268
void CorpseRemoved(uint32 &respawnDelay) override
== Triggered Actions Requested ==================
Definition SmartAI.cpp:673
bool _OOCReached
Definition SmartAI.h:271
void SummonedCreatureDies(Creature *summon, Unit *killer) override
Definition SmartAI.cpp:574
uint32 _followCredit
Definition SmartAI.h:257
void JustSummoned(Creature *creature) override
Definition SmartAI.cpp:569
uint32 _followCreditType
Definition SmartAI.h:255
void SetEvadeDisabled(bool disable=true)
Definition SmartAI.cpp:760
void CheckConditions(uint32 diff)
Definition SmartAI.cpp:895
bool _canAutoAttack
Definition SmartAI.h:276
void DoAction(int32 param=0) override
Definition SmartAI.cpp:727
SmartScript * GetScript()
Definition SmartAI.h:88
void SetTimedActionList(SmartScriptHolder &e, uint32 entry, Unit *invoker)
Definition SmartAI.cpp:877
void SetData(uint32 id, uint32 value) override
Definition SmartAI.h:190
void SetRun(bool run=true)
Definition SmartAI.cpp:749
void MoveInLineOfSight(Unit *who) override
Definition SmartAI.cpp:442
void ReceiveEmote(Player *player, uint32 textEmote) override
Definition SmartAI.cpp:653
void UpdatePath(uint32 diff)
Definition SmartAI.cpp:924
uint32 _escortState
Definition SmartAI.h:263
void KilledUnit(Unit *victim) override
Definition SmartAI.cpp:564
void MovementInform(uint32 MovementType, uint32 Data) override
Definition SmartAI.cpp:382
void ResumePath()
Definition SmartAI.cpp:251
uint32 _invincibilityHPLevel
Definition SmartAI.h:278
void UpdateFollow(uint32 diff)
Definition SmartAI.cpp:977
bool _repeatWaypointPath
Definition SmartAI.h:270
void SpellHit(WorldObject *caster, SpellInfo const *spellInfo) override
Definition SmartAI.cpp:602
bool IsEscortInvokerInRange()
Definition SmartAI.cpp:303
bool OnGossipSelect(Player *player, uint32 menuId, uint32 gossipListId) override
Definition SmartAI.cpp:1044
void OnQuestReward(Player *player, Quest const *quest, uint32 opt) override
Definition SmartAI.cpp:1064
void InitializeAI() override
Definition SmartAI.cpp:1021
void OnGameEvent(bool start, uint16 eventId) override
Definition SmartAI.cpp:1092
void UpdateAI(uint32 diff) override
Definition SmartAI.cpp:1016
void SetTimedActionList(SmartScriptHolder &e, uint32 entry, Unit *invoker)
Definition SmartAI.cpp:1087
void EventInform(uint32 eventId) override
Definition SmartAI.cpp:1102
bool OnGossipHello(Player *player) override
Definition SmartAI.cpp:1036
SmartScript * GetScript()
Definition SmartAI.h:302
void OnLootStateChanged(uint32 state, Unit *unit) override
Definition SmartAI.cpp:1097
void SpellHit(WorldObject *caster, SpellInfo const *spellInfo) override
Definition SmartAI.cpp:1107
bool OnReportUse(Player *player) override
Definition SmartAI.cpp:1069
void Destroyed(WorldObject *attacker, uint32 eventId) override
Definition SmartAI.cpp:1077
void OnQuestAccept(Player *player, Quest const *quest) override
Definition SmartAI.cpp:1058
void SetData(uint32 id, uint32 value, Unit *invoker)
Definition SmartAI.cpp:1082
void SummonedCreatureDespawn(Creature *unit) override
Definition SmartAI.cpp:1122
bool OnGossipSelectCode(Player *player, uint32 menuId, uint32 gossipListId, char const *code) override
Definition SmartAI.cpp:1052
void SummonedCreatureDies(Creature *summon, Unit *killer) override
Definition SmartAI.cpp:1117
void Reset() override
Definition SmartAI.cpp:1030
void JustSummoned(Creature *creature) override
Definition SmartAI.cpp:1112
void OnUpdate(const uint32 diff)
void ProcessEventsFor(SMART_EVENT e, Unit *unit=nullptr, uint32 var0=0, uint32 var1=0, bool bvar=false, SpellInfo const *spell=nullptr, GameObject *gob=nullptr)
static bool IsPlayer(WorldObject *obj)
void OnMoveInLineOfSight(Unit *who)
uint32 GetPathId() const
Definition SmartScript.h:54
void OnInitialize(WorldObject *obj, AreaTriggerEntry const *at=nullptr)
ObjectVector const * GetStoredTargetVector(uint32 id, WorldObject const &ref) const
void SetTimedActionList(SmartScriptHolder &e, uint32 entry, Unit *invoker)
void SetPathId(uint32 id)
Definition SmartScript.h:53
bool OnTrigger(Player *player, AreaTriggerEntry const *trigger) override
Definition SmartAI.cpp:1133
void DoMeleeAttackIfReady()
Definition UnitAI.cpp:54
virtual bool CanAIAttack(Unit const *) const
Definition UnitAI.h:139
virtual void OnCharmed(bool isNew)
Definition UnitAI.cpp:42
Definition Unit.h:769
void ClearUnitState(uint32 f)
Definition Unit.h:877
bool IsVehicle() const
Definition Unit.h:887
bool IsCharmed() const
Definition Unit.h:1280
void SetVisible(bool x)
Definition Unit.cpp:8513
NPCFlags GetNpcFlags() const
Definition Unit.h:1095
void StopMoving(bool force=false)
Definition Unit.cpp:10312
Unit * GetCharmer() const
Definition Unit.h:1253
void InterruptNonMeleeSpells(bool withDelayed, uint32 spellid=0, bool withInstant=true)
Definition Unit.cpp:3093
MotionMaster * GetMotionMaster()
Definition Unit.h:1667
void ResumeMovement(uint32 timer=0, uint8 slot=0)
Definition Unit.cpp:10339
void PauseMovement(uint32 timer=0, uint8 slot=0, bool forced=true)
Definition Unit.cpp:10327
bool IsAlive() const
Definition Unit.h:1234
bool SetDisableGravity(bool disable, bool updateAnimTier=true)
Definition Unit.cpp:13286
void AddUnitState(uint32 f)
Definition Unit.h:875
bool isInAccessiblePlaceFor(Creature const *c) const
Definition Unit.cpp:3154
Unit * EnsureVictim() const
Definition Unit.h:861
Unit * GetCharmerOrOwner() const
Definition Unit.h:1265
bool Attack(Unit *victim, bool meleeAttack)
Definition Unit.cpp:5535
bool isPossessed() const
Definition Unit.h:1282
uint32 GetHealth() const
Definition Unit.h:913
bool SetWalk(bool enable)
Definition Unit.cpp:13268
void EngageWithTarget(Unit *who)
Definition Unit.cpp:8292
virtual float GetFollowAngle() const
Definition Unit.h:1782
Unit * GetVictim() const
Definition Unit.h:859
bool HasUnitState(const uint32 f) const
Definition Unit.h:876
ObjectGuid LastCharmerGUID
Definition Unit.h:1732
Vehicle * GetVehicleKit() const
Definition Unit.h:1735
void ReplaceAllNpcFlags(NPCFlags flags)
Definition Unit.h:1099
bool AttackStop()
Definition Unit.cpp:5645
bool IsInCombat() const
Definition Unit.h:1144
bool isDead() const
Definition Unit.h:1236
InstanceScript * GetInstanceScript() const
Definition Object.cpp:1087
bool IsWithinLOSInMap(WorldObject const *obj, LineOfSightChecks checks=LINEOFSIGHT_ALL_CHECKS, VMAP::ModelIgnoreFlags ignoreFlags=VMAP::ModelIgnoreFlags::Nothing) const
Definition Object.cpp:1226
Creature * FindNearestCreature(uint32 entry, float range, bool alive=true) const
Definition Object.cpp:2099
Player * GetCharmerOrOwnerPlayerOrPlayerItself() const
Definition Object.cpp:2203
bool IsWithinDistInMap(WorldObject const *obj, float dist2compare, bool is3D=true, bool incOwnRadius=true, bool incTargetRadius=true) const
Definition Object.cpp:1192
bool IsValidAssistTarget(WorldObject const *target, SpellInfo const *bySpell=nullptr) const
Definition Object.cpp:3000
float GetDistance(WorldObject const *obj) const
Definition Object.cpp:1123
bool IsInMap(WorldObject const *obj) const
Definition Object.cpp:1160
TC_GAME_API Unit * GetUnit(WorldObject const &, ObjectGuid const &guid)
TC_GAME_API Player * GetPlayer(Map const *, ObjectGuid const &guid)
void GetPosition(float &x, float &y) const
Definition Position.h:84
std::vector< WaypointNode > nodes