aboutsummaryrefslogtreecommitdiff
path: root/src/server/game/AI
diff options
context:
space:
mode:
authorTreeston <treeston.mmoc@gmail.com>2019-07-21 01:49:58 +0200
committerShauren <shauren.trinity@gmail.com>2021-12-17 00:23:33 +0100
commitc13d83796f7b2111c5dcf8546bdd84eccd232ae3 (patch)
tree03c4220a955113e46b3aa2f9cc270574ba3a79c4 /src/server/game/AI
parentf9fe00bf8c4c913bcfedd8df7d8e1001129962a0 (diff)
Core/AI: Finally move the "is creature engaged" flag to be a property of the creature AI, where it honestly always belonged. Fixes #17981 and #23602 for real this time.
(cherry picked from commit 0e7c66cb4c7ff7d44e232d0b50703a48605ffd24)
Diffstat (limited to 'src/server/game/AI')
-rw-r--r--src/server/game/AI/CoreAI/GuardAI.cpp4
-rw-r--r--src/server/game/AI/CoreAI/PassiveAI.h5
-rw-r--r--src/server/game/AI/CoreAI/TotemAI.cpp11
-rw-r--r--src/server/game/AI/CoreAI/TotemAI.h6
-rw-r--r--src/server/game/AI/CoreAI/UnitAI.cpp2
-rw-r--r--src/server/game/AI/CreatureAI.cpp44
-rw-r--r--src/server/game/AI/CreatureAI.h15
-rw-r--r--src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp3
-rw-r--r--src/server/game/AI/ScriptedAI/ScriptedFollowerAI.cpp6
9 files changed, 73 insertions, 23 deletions
diff --git a/src/server/game/AI/CoreAI/GuardAI.cpp b/src/server/game/AI/CoreAI/GuardAI.cpp
index 214c8df86f7..aa6ea0e93c4 100644
--- a/src/server/game/AI/CoreAI/GuardAI.cpp
+++ b/src/server/game/AI/CoreAI/GuardAI.cpp
@@ -52,7 +52,7 @@ void GuardAI::EnterEvadeMode(EvadeReason /*why*/)
{
me->GetMotionMaster()->MoveIdle();
me->CombatStop(true);
- me->GetThreatManager().NotifyDisengaged();
+ EngagementOver();
return;
}
@@ -60,7 +60,7 @@ void GuardAI::EnterEvadeMode(EvadeReason /*why*/)
me->RemoveAllAuras();
me->CombatStop(true);
- me->GetThreatManager().NotifyDisengaged();
+ EngagementOver();
me->GetMotionMaster()->MoveTargetedHome();
}
diff --git a/src/server/game/AI/CoreAI/PassiveAI.h b/src/server/game/AI/CoreAI/PassiveAI.h
index 582fb737d41..039a5293036 100644
--- a/src/server/game/AI/CoreAI/PassiveAI.h
+++ b/src/server/game/AI/CoreAI/PassiveAI.h
@@ -39,6 +39,9 @@ class TC_GAME_API PossessedAI : public CreatureAI
void MoveInLineOfSight(Unit*) override { }
void AttackStart(Unit* target) override;
+ void JustEnteredCombat(Unit* who) override { EngagementStart(who); }
+ void JustExitedCombat() override { EngagementOver(); }
+ void JustStartedThreateningMe(Unit*) override { }
void UpdateAI(uint32) override;
void EnterEvadeMode(EvadeReason /*why*/) override { }
@@ -55,6 +58,8 @@ class TC_GAME_API NullCreatureAI : public CreatureAI
void MoveInLineOfSight(Unit*) override { }
void AttackStart(Unit*) override { }
+ void JustStartedThreateningMe(Unit*) override { }
+ void JustEnteredCombat(Unit*) override { }
void UpdateAI(uint32) override { }
void JustAppeared() override { }
void EnterEvadeMode(EvadeReason /*why*/) override { }
diff --git a/src/server/game/AI/CoreAI/TotemAI.cpp b/src/server/game/AI/CoreAI/TotemAI.cpp
index 48940a1412b..64741e5993a 100644
--- a/src/server/game/AI/CoreAI/TotemAI.cpp
+++ b/src/server/game/AI/CoreAI/TotemAI.cpp
@@ -33,16 +33,9 @@ int32 TotemAI::Permissible(Creature const* creature)
return PERMIT_BASE_NO;
}
-TotemAI::TotemAI(Creature* creature, uint32 scriptId) : CreatureAI(creature, scriptId), _victimGUID()
+TotemAI::TotemAI(Creature* creature, uint32 scriptId) : NullCreatureAI(creature, scriptId), _victimGUID()
{
- ASSERT(creature->IsTotem(), "TotemAI: AI assigned to a no-totem creature (%s)!", creature->GetGUID().ToString().c_str());
-}
-
-void TotemAI::MoveInLineOfSight(Unit* /*who*/) { }
-
-void TotemAI::EnterEvadeMode(EvadeReason /*why*/)
-{
- me->CombatStop(true);
+ ASSERT(creature->IsTotem(), "TotemAI: AI assigned to a non-totem creature (%s)!", creature->GetGUID().ToString().c_str());
}
void TotemAI::UpdateAI(uint32 /*diff*/)
diff --git a/src/server/game/AI/CoreAI/TotemAI.h b/src/server/game/AI/CoreAI/TotemAI.h
index dcc14e963ee..80f387f6a22 100644
--- a/src/server/game/AI/CoreAI/TotemAI.h
+++ b/src/server/game/AI/CoreAI/TotemAI.h
@@ -19,20 +19,18 @@
#define TRINITY_TOTEMAI_H
#include "CreatureAI.h"
+#include "PassiveAI.h"
#include "Timer.h"
class Creature;
class Totem;
-class TC_GAME_API TotemAI : public CreatureAI
+class TC_GAME_API TotemAI : public NullCreatureAI
{
public:
explicit TotemAI(Creature* creature, uint32 scriptId = {});
- void MoveInLineOfSight(Unit* who) override;
void AttackStart(Unit* victim) override;
- void JustAppeared() override { }
- void EnterEvadeMode(EvadeReason /*why*/) override;
void UpdateAI(uint32 diff) override;
static int32 Permissible(Creature const* creature);
diff --git a/src/server/game/AI/CoreAI/UnitAI.cpp b/src/server/game/AI/CoreAI/UnitAI.cpp
index df37aa94f03..642ac34a675 100644
--- a/src/server/game/AI/CoreAI/UnitAI.cpp
+++ b/src/server/game/AI/CoreAI/UnitAI.cpp
@@ -318,7 +318,7 @@ std::string UnitAI::GetDebugInfo() const
}
DefaultTargetSelector::DefaultTargetSelector(Unit const* unit, float dist, bool playerOnly, bool withTank, int32 aura)
- : _me(unit), _dist(dist), _playerOnly(playerOnly), _exception(!withTank ? _me->GetThreatManager().GetCurrentVictim() : nullptr), _aura(aura)
+ : _me(unit), _dist(dist), _playerOnly(playerOnly), _exception(!withTank ? unit->GetThreatManager().GetLastVictim() : nullptr), _aura(aura)
{
}
diff --git a/src/server/game/AI/CreatureAI.cpp b/src/server/game/AI/CreatureAI.cpp
index e1d53238c89..7d617a9c384 100644
--- a/src/server/game/AI/CreatureAI.cpp
+++ b/src/server/game/AI/CreatureAI.cpp
@@ -43,7 +43,7 @@ AISpellInfoType* GetAISpellInfo(uint32 spellId, Difficulty difficulty)
CreatureAI::CreatureAI(Creature* creature, uint32 scriptId)
: UnitAI(creature), me(creature), _boundary(nullptr),
- _negateBoundary(false), _scriptId(scriptId ? scriptId : creature->GetScriptId()), _moveInLOSLocked(false)
+ _negateBoundary(false), _scriptId(scriptId ? scriptId : creature->GetScriptId()), _isEngaged(false), _moveInLOSLocked(false)
{
ASSERT(_scriptId, "A CreatureAI was initialized with an invalid scriptId!");
}
@@ -207,6 +207,12 @@ void CreatureAI::JustAppeared()
}
}
+void CreatureAI::JustEnteredCombat(Unit* who)
+{
+ if (!IsEngaged() && !me->CanHaveThreatList())
+ EngagementStart(who);
+}
+
void CreatureAI::EnterEvadeMode(EvadeReason why)
{
if (!_EnterEvadeMode(why))
@@ -235,7 +241,7 @@ void CreatureAI::EnterEvadeMode(EvadeReason why)
bool CreatureAI::UpdateVictim()
{
- if (!me->IsEngaged())
+ if (!IsEngaged())
return false;
if (!me->HasReactState(REACT_PASSIVE))
@@ -257,22 +263,52 @@ bool CreatureAI::UpdateVictim()
return true;
}
+void CreatureAI::EngagementStart(Unit* who)
+{
+ if (_isEngaged)
+ {
+ TC_LOG_ERROR("scripts.ai", "CreatureAI::EngagementStart called even though creature is already engaged. Creature debug info:\n%s", me->GetDebugInfo().c_str());
+ return;
+ }
+ _isEngaged = true;
+
+ me->AtEngage(who);
+}
+
+void CreatureAI::EngagementOver()
+{
+ if (!_isEngaged)
+ {
+ TC_LOG_ERROR("scripts.ai", "CreatureAI::EngagementOver called even though creature is not currently engaged. Creature debug info:\n%s", me->GetDebugInfo().c_str());
+ return;
+ }
+ _isEngaged = false;
+
+ me->AtDisengage();
+}
+
bool CreatureAI::_EnterEvadeMode(EvadeReason /*why*/)
{
+ if (me->IsInEvadeMode())
+ return false;
+
if (!me->IsAlive())
+ {
+ EngagementOver();
return false;
+ }
me->RemoveAurasOnEvade();
me->CombatStop(true);
- me->GetThreatManager().NotifyDisengaged();
me->SetLootRecipient(nullptr);
me->ResetPlayerDamageReq();
me->SetLastDamagedTime(0);
me->SetCannotReachTarget(false);
me->DoNotReacquireTarget();
+ EngagementOver();
- return !me->IsInEvadeMode();
+ return true;
}
Optional<QuestGiverStatus> CreatureAI::GetDialogStatus(Player* /*player*/)
diff --git a/src/server/game/AI/CreatureAI.h b/src/server/game/AI/CreatureAI.h
index 165b905803e..eef2cc0bd6b 100644
--- a/src/server/game/AI/CreatureAI.h
+++ b/src/server/game/AI/CreatureAI.h
@@ -84,6 +84,8 @@ class TC_GAME_API CreatureAI : public UnitAI
// Gets the id of the AI (script id)
uint32 GetId() const { return _scriptId; }
+ bool IsEngaged() const { return _isEngaged; }
+
void Talk(uint8 id, WorldObject const* whisperTarget = nullptr);
/// == Reactions At =================================
@@ -97,11 +99,17 @@ class TC_GAME_API CreatureAI : public UnitAI
// Called for reaction at stopping attack at no attackers or targets
virtual void EnterEvadeMode(EvadeReason why = EVADE_REASON_OTHER);
+ // Called for reaction whenever we start being in combat (overridden from base UnitAI)
+ void JustEnteredCombat(Unit* /*who*/) override;
+
+ // Called for reaction whenever a new non-offline unit is added to the threat list
+ virtual void JustStartedThreateningMe(Unit* who) { if (!IsEngaged()) EngagementStart(who); }
+
// Called for reaction when initially engaged - this will always happen _after_ JustEnteredCombat
virtual void JustEngagedWith(Unit* /*who*/) { }
// Called when the creature is killed
- virtual void JustDied(Unit* /*killer*/) { }
+ virtual void JustDied(Unit* /*killer*/) { if (IsEngaged()) EngagementOver(); }
// Called when the creature kills a unit
virtual void KilledUnit(Unit* /*victim*/) { }
@@ -227,6 +235,8 @@ class TC_GAME_API CreatureAI : public UnitAI
// intended for encounter design/debugging. do not use for other purposes. expensive.
int32 VisualizeBoundary(uint32 duration, Unit* owner = nullptr, bool fill = false) const;
+
+ // boundary system methods
virtual bool CheckInRoom();
CreatureBoundary const* GetBoundary() const { return _boundary; }
void SetBoundary(CreatureBoundary const* boundary, bool negativeBoundaries = false);
@@ -235,6 +245,8 @@ class TC_GAME_API CreatureAI : public UnitAI
bool IsInBoundary(Position const* who = nullptr) const;
protected:
+ void EngagementStart(Unit* who);
+ void EngagementOver();
virtual void MoveInLineOfSight(Unit* /*who*/);
bool _EnterEvadeMode(EvadeReason why = EVADE_REASON_OTHER);
@@ -246,6 +258,7 @@ class TC_GAME_API CreatureAI : public UnitAI
void OnOwnerCombatInteraction(Unit* target);
uint32 const _scriptId;
+ bool _isEngaged;
bool _moveInLOSLocked;
};
diff --git a/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp b/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp
index 91efe5d5312..63592dd30ba 100644
--- a/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp
+++ b/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp
@@ -94,8 +94,9 @@ void EscortAI::EnterEvadeMode(EvadeReason /*why*/)
{
me->RemoveAllAuras();
me->CombatStop(true);
- me->GetThreatManager().NotifyDisengaged();
me->SetLootRecipient(nullptr);
+
+ EngagementOver();
if (HasEscortState(STATE_ESCORT_ESCORTING))
{
diff --git a/src/server/game/AI/ScriptedAI/ScriptedFollowerAI.cpp b/src/server/game/AI/ScriptedAI/ScriptedFollowerAI.cpp
index 669022d8420..d8f0d972cd1 100644
--- a/src/server/game/AI/ScriptedAI/ScriptedFollowerAI.cpp
+++ b/src/server/game/AI/ScriptedAI/ScriptedFollowerAI.cpp
@@ -103,14 +103,18 @@ void FollowerAI::JustAppeared()
void FollowerAI::EnterEvadeMode(EvadeReason /*why*/)
{
if (!me->IsAlive())
+ {
+ EngagementOver();
return;
+ }
me->RemoveAllAuras();
me->CombatStop(true);
- me->GetThreatManager().NotifyDisengaged();
me->SetLootRecipient(nullptr);
me->SetCannotReachTarget(false);
me->DoNotReacquireTarget();
+
+ EngagementOver();
if (HasFollowState(STATE_FOLLOW_INPROGRESS))
{