aboutsummaryrefslogtreecommitdiff
path: root/src/server/game/AI/SmartScripts
diff options
context:
space:
mode:
Diffstat (limited to 'src/server/game/AI/SmartScripts')
-rw-r--r--src/server/game/AI/SmartScripts/SmartAI.cpp299
-rw-r--r--src/server/game/AI/SmartScripts/SmartAI.h15
-rw-r--r--src/server/game/AI/SmartScripts/SmartScript.cpp58
-rw-r--r--src/server/game/AI/SmartScripts/SmartScriptMgr.cpp35
-rw-r--r--src/server/game/AI/SmartScripts/SmartScriptMgr.h25
5 files changed, 203 insertions, 229 deletions
diff --git a/src/server/game/AI/SmartScripts/SmartAI.cpp b/src/server/game/AI/SmartScripts/SmartAI.cpp
index e1c3d879265..d0b9a9b23b0 100644
--- a/src/server/game/AI/SmartScripts/SmartAI.cpp
+++ b/src/server/game/AI/SmartScripts/SmartAI.cpp
@@ -26,33 +26,30 @@
#include "PetDefines.h"
#include "Player.h"
#include "ScriptMgr.h"
+#include "WaypointMovementGenerator.h"
SmartAI::SmartAI(Creature* c) : CreatureAI(c)
{
mIsCharmed = false;
// copy script to local (protection for table reload)
- mWayPoints = nullptr;
mEscortState = SMART_ESCORT_NONE;
mCurrentWPID = 0;//first wp id is 1 !!
mWPReached = false;
mWPPauseTimer = 0;
- mLastWP = nullptr;
+ mOOCReached = false;
+ mEscortNPCFlags = 0;
mCanRepeatPath = false;
- // spawn in run mode
- me->SetWalk(false);
- mRun = false;
- mEvadeDisabled = false;
-
- mLastOOCPos = me->GetPosition();
+ // Spawn in run mode
+ mRun = true;
+ m_Ended = false;
mCanAutoAttack = true;
mCanCombatMove = true;
mForcedPaused = false;
- mLastWPIDReached = 0;
mEscortQuestID = 0;
@@ -72,6 +69,10 @@ SmartAI::SmartAI(Creature* c) : CreatureAI(c)
mJustReset = false;
}
+SmartAI::~SmartAI()
+{
+}
+
bool SmartAI::IsAIControlled() const
{
return !mIsCharmed;
@@ -95,63 +96,79 @@ void SmartAI::UpdateDespawn(const uint32 diff)
} else mDespawnTime -= diff;
}
-WayPoint* SmartAI::GetNextWayPoint()
-{
- if (!mWayPoints || mWayPoints->empty())
- return nullptr;
-
- mCurrentWPID++;
- WPPath::const_iterator itr = mWayPoints->find(mCurrentWPID);
- if (itr != mWayPoints->end())
- {
- mLastWP = (*itr).second;
- if (mLastWP->id != mCurrentWPID)
- {
- TC_LOG_ERROR("misc", "SmartAI::GetNextWayPoint: Got not expected waypoint id %u, expected %u", mLastWP->id, mCurrentWPID);
- }
- return (*itr).second;
- }
- return nullptr;
-}
-
-void SmartAI::StartPath(bool run, uint32 path, bool repeat, Unit* /*invoker*/)
+void SmartAI::StartPath(bool run, uint32 path, bool repeat, Unit* invoker)
{
if (me->IsInCombat())// no wp movement in combat
{
TC_LOG_ERROR("misc", "SmartAI::StartPath: Creature entry %u wanted to start waypoint movement while in combat, ignoring.", me->GetEntry());
return;
}
+
if (HasEscortState(SMART_ESCORT_ESCORTING))
StopPath();
+
+ SetRun(run);
+
if (path)
if (!LoadPath(path))
return;
- if (!mWayPoints || mWayPoints->empty())
+
+ if (_path.nodes.empty())
return;
- AddEscortState(SMART_ESCORT_ESCORTING);
- mCanRepeatPath = repeat;
+ mCurrentWPID = 1;
+ m_Ended = false;
- SetRun(run);
+ // Do not use AddEscortState, removing everything from previous cycle
+ mEscortState = SMART_ESCORT_ESCORTING;
+ mCanRepeatPath = repeat;
- if (WayPoint* wp = GetNextWayPoint())
+ if (invoker && invoker->GetTypeId() == TYPEID_PLAYER)
{
- mLastOOCPos = me->GetPosition();
- me->GetMotionMaster()->MovePoint(wp->id, wp->x, wp->y, wp->z);
- GetScript()->ProcessEventsFor(SMART_EVENT_WAYPOINT_START, nullptr, wp->id, GetScript()->GetPathId());
+ mEscortNPCFlags = me->GetUInt32Value(UNIT_NPC_FLAGS);
+ me->SetFlag(UNIT_NPC_FLAGS, 0);
}
+
+ GetScript()->ProcessEventsFor(SMART_EVENT_WAYPOINT_START, nullptr, mCurrentWPID, GetScript()->GetPathId());
+
+ me->GetMotionMaster()->MovePath(_path, mCanRepeatPath);
}
bool SmartAI::LoadPath(uint32 entry)
{
if (HasEscortState(SMART_ESCORT_ESCORTING))
return false;
- mWayPoints = sSmartWaypointMgr->GetPath(entry);
- if (!mWayPoints)
+
+ WPPath const* path = sSmartWaypointMgr->GetPath(entry);
+ if (!path || path->empty())
{
GetScript()->SetPathId(0);
return false;
}
+
+ for (WayPoint const &waypoint : *path)
+ {
+ float x = waypoint.x;
+ float y = waypoint.y;
+ float z = waypoint.z;
+
+ Trinity::NormalizeMapCoord(x);
+ Trinity::NormalizeMapCoord(y);
+
+ WaypointNode wp;
+ wp.id = waypoint.id;
+ wp.x = x;
+ wp.y = y;
+ wp.z = z;
+ wp.orientation = 0.f;
+ wp.moveType = mRun ? WAYPOINT_MOVE_TYPE_RUN : WAYPOINT_MOVE_TYPE_WALK;
+ wp.delay = 0;
+ wp.eventId = 0;
+ wp.eventChance = 100;
+
+ _path.nodes.push_back(std::move(wp));
+ }
+
GetScript()->SetPathId(entry);
return true;
}
@@ -160,22 +177,22 @@ void SmartAI::PausePath(uint32 delay, bool forced)
{
if (!HasEscortState(SMART_ESCORT_ESCORTING))
return;
+
if (HasEscortState(SMART_ESCORT_PAUSED))
{
- TC_LOG_ERROR("misc", "SmartAI::PausePath: Creature entry %u wanted to pause waypoint movement while already paused, ignoring.", me->GetEntry());
+ TC_LOG_ERROR("misc", "SmartAI::PausePath: Creature entry %u wanted to pause waypoint (current waypoint: %u) movement while already paused, ignoring.", me->GetEntry(), mCurrentWPID);
return;
}
- mForcedPaused = forced;
- mLastOOCPos = me->GetPosition();
+
AddEscortState(SMART_ESCORT_PAUSED);
mWPPauseTimer = delay;
- if (forced)
+ if (forced && !mWPReached)
{
+ mForcedPaused = forced;
SetRun(mRun);
- me->StopMoving();//force stop
- me->GetMotionMaster()->MoveIdle();//force stop
+ me->StopMoving();
}
- GetScript()->ProcessEventsFor(SMART_EVENT_WAYPOINT_PAUSED, nullptr, mLastWP->id, GetScript()->GetPathId());
+ GetScript()->ProcessEventsFor(SMART_EVENT_WAYPOINT_PAUSED, nullptr, mCurrentWPID, GetScript()->GetPathId());
}
void SmartAI::StopPath(uint32 DespawnTime, uint32 quest, bool fail)
@@ -185,33 +202,28 @@ void SmartAI::StopPath(uint32 DespawnTime, uint32 quest, bool fail)
if (quest)
mEscortQuestID = quest;
- SetDespawnTime(DespawnTime);
- //mDespawnTime = DespawnTime;
- mLastOOCPos = me->GetPosition();
- me->StopMoving();//force stop
+ if (mDespawnState != 2)
+ SetDespawnTime(DespawnTime);
+
+ me->StopMoving();
+ me->GetMotionMaster()->MovementExpired(false);
me->GetMotionMaster()->MoveIdle();
- GetScript()->ProcessEventsFor(SMART_EVENT_WAYPOINT_STOPPED, nullptr, mLastWP->id, GetScript()->GetPathId());
+ GetScript()->ProcessEventsFor(SMART_EVENT_WAYPOINT_STOPPED, nullptr, mCurrentWPID, GetScript()->GetPathId());
EndPath(fail);
}
void SmartAI::EndPath(bool fail)
{
- GetScript()->ProcessEventsFor(SMART_EVENT_WAYPOINT_ENDED, nullptr, mLastWP->id, GetScript()->GetPathId());
-
RemoveEscortState(SMART_ESCORT_ESCORTING | SMART_ESCORT_PAUSED | SMART_ESCORT_RETURNING);
- mWayPoints = nullptr;
- mCurrentWPID = 0;
+ _path.nodes.clear();
mWPPauseTimer = 0;
- mLastWP = nullptr;
- if (mCanRepeatPath)
+ if (mEscortNPCFlags)
{
- if (IsAIControlled())
- StartPath(mRun, GetScript()->GetPathId(), true);
+ me->SetFlag(UNIT_NPC_FLAGS, mEscortNPCFlags);
+ mEscortNPCFlags = 0;
}
- else
- GetScript()->SetPathId(0);
ObjectList* targets = GetScript()->GetTargetList(SMART_ESCORT_TARGETS);
if (targets && mEscortQuestID)
@@ -253,15 +265,36 @@ void SmartAI::EndPath(bool fail)
}
}
}
+
+ // End Path events should be only processed if it was SUCCESSFUL stop or stop called by SMART_ACTION_WAYPOINT_STOP
+ if (fail)
+ return;
+
+ GetScript()->ProcessEventsFor(SMART_EVENT_WAYPOINT_ENDED, nullptr, mCurrentWPID, GetScript()->GetPathId());
+
+ if (mCanRepeatPath)
+ {
+ if (IsAIControlled())
+ StartPath(mRun, GetScript()->GetPathId(), mCanRepeatPath);
+ }
+ else
+ GetScript()->SetPathId(0);
+
if (mDespawnState == 1)
StartDespawn();
}
void SmartAI::ResumePath()
{
+ GetScript()->ProcessEventsFor(SMART_EVENT_WAYPOINT_RESUMED, NULL, mCurrentWPID, GetScript()->GetPathId());
+ RemoveEscortState(SMART_ESCORT_PAUSED);
+ mForcedPaused = false;
+ mWPReached = false;
+ mWPPauseTimer = 0;
SetRun(mRun);
- if (mLastWP)
- me->GetMotionMaster()->MovePoint(mLastWP->id, mLastWP->x, mLastWP->y, mLastWP->z);
+
+ if (WaypointMovementGenerator<Creature>* move = dynamic_cast<WaypointMovementGenerator<Creature>*>(me->GetMotionMaster()->top()))
+ move->GetTrackerTimer().Reset(1);
}
void SmartAI::ReturnToLastOOCPos()
@@ -269,69 +302,61 @@ void SmartAI::ReturnToLastOOCPos()
if (!IsAIControlled())
return;
- SetRun(mRun);
- me->GetMotionMaster()->MovePoint(SMART_ESCORT_LAST_OOC_POINT, mLastOOCPos);
+ me->SetWalk(false);
+ float x, y, z, o;
+ me->GetHomePosition(x, y, z, o);
+ me->GetMotionMaster()->MovePoint(SMART_ESCORT_LAST_OOC_POINT, x, y, z);
}
void SmartAI::UpdatePath(const uint32 diff)
{
if (!HasEscortState(SMART_ESCORT_ESCORTING))
return;
+
if (mEscortInvokerCheckTimer < diff)
{
if (!IsEscortInvokerInRange())
{
- StopPath(mDespawnTime, mEscortQuestID, true);
+ StopPath(0, mEscortQuestID, true);
+
+ // allow to properly hook out of range despawn action, which in most cases should perform the same operation as dying
+ GetScript()->ProcessEventsFor(SMART_EVENT_DEATH, me);
+ me->DespawnOrUnsummon(1);
+ return;
}
mEscortInvokerCheckTimer = 1000;
- } else mEscortInvokerCheckTimer -= diff;
+ }
+ else
+ mEscortInvokerCheckTimer -= diff;
+
// handle pause
if (HasEscortState(SMART_ESCORT_PAUSED))
{
- if (mWPPauseTimer < diff)
+ if (mWPPauseTimer <= diff)
{
- if (!me->IsInCombat() && !HasEscortState(SMART_ESCORT_RETURNING) && (mWPReached || mLastWPIDReached == SMART_ESCORT_LAST_OOC_POINT || mForcedPaused))
+ if (!me->IsInCombat() && !HasEscortState(SMART_ESCORT_RETURNING) && (mWPReached || mForcedPaused))
{
- GetScript()->ProcessEventsFor(SMART_EVENT_WAYPOINT_RESUMED, nullptr, mLastWP->id, GetScript()->GetPathId());
- RemoveEscortState(SMART_ESCORT_PAUSED);
- if (mForcedPaused)// if paused between 2 wps resend movement
- {
- ResumePath();
- mWPReached = false;
- mForcedPaused = false;
- }
- if (mLastWPIDReached == SMART_ESCORT_LAST_OOC_POINT)
- mWPReached = true;
+ ResumePath();
}
- mWPPauseTimer = 0;
- } else {
- mWPPauseTimer -= diff;
}
+ else
+ mWPPauseTimer -= diff;
}
+ else if (m_Ended) // end path
+ {
+ m_Ended = false;
+ StopPath();
+ return;
+ }
+
if (HasEscortState(SMART_ESCORT_RETURNING))
{
- if (mWPReached)//reached OOC WP
+ if (mOOCReached)//reached OOC WP
{
+ mOOCReached = false;
RemoveEscortState(SMART_ESCORT_RETURNING);
if (!HasEscortState(SMART_ESCORT_PAUSED))
ResumePath();
- mWPReached = false;
- }
- }
- if ((!me->HasReactState(REACT_PASSIVE) && me->IsInCombat()) || HasEscortState(SMART_ESCORT_PAUSED | SMART_ESCORT_RETURNING))
- return;
- // handle next wp
- if (mWPReached)//reached WP
- {
- mWPReached = false;
- if (mCurrentWPID == GetWPCount())
- {
- EndPath();
- }
- else if (WayPoint* wp = GetNextWayPoint())
- {
- SetRun(mRun);
- me->GetMotionMaster()->MovePoint(wp->id, wp->x, wp->y, wp->z);
}
}
}
@@ -408,22 +433,44 @@ bool SmartAI::IsEscortInvokerInRange()
void SmartAI::MovepointReached(uint32 id)
{
- if (id != SMART_ESCORT_LAST_OOC_POINT && mLastWPIDReached != id)
- GetScript()->ProcessEventsFor(SMART_EVENT_WAYPOINT_REACHED, nullptr, id);
+ // override the id, path can be resumed any time and counter will reset
+ // mCurrentWPID holds proper id
+
+ // both point movement and escort generator can enter this function
+ if (id == SMART_ESCORT_LAST_OOC_POINT)
+ {
+ mOOCReached = true;
+ return;
+ }
+
+ mCurrentWPID = id + 1; // in SmartAI increase by 1
- mLastWPIDReached = id;
mWPReached = true;
+ GetScript()->ProcessEventsFor(SMART_EVENT_WAYPOINT_REACHED, nullptr, mCurrentWPID, GetScript()->GetPathId());
+
+ if (HasEscortState(SMART_ESCORT_PAUSED))
+ me->StopMoving();
+ else if (HasEscortState(SMART_ESCORT_ESCORTING) && me->GetMotionMaster()->GetCurrentMovementGeneratorType() == WAYPOINT_MOTION_TYPE)
+ {
+ mWPReached = false;
+ if (mCurrentWPID == _path.nodes.size())
+ m_Ended = true;
+ else
+ SetRun(mRun);
+ }
}
void SmartAI::MovementInform(uint32 MovementType, uint32 Data)
{
- if ((MovementType == POINT_MOTION_TYPE && Data == SMART_ESCORT_LAST_OOC_POINT) || MovementType == FOLLOW_MOTION_TYPE)
+ if (MovementType == POINT_MOTION_TYPE && Data == SMART_ESCORT_LAST_OOC_POINT)
me->ClearUnitState(UNIT_STATE_EVADE);
GetScript()->ProcessEventsFor(SMART_EVENT_MOVEMENTINFORM, nullptr, MovementType, Data);
- if (MovementType != POINT_MOTION_TYPE || !HasEscortState(SMART_ESCORT_ESCORTING))
+ if (!HasEscortState(SMART_ESCORT_ESCORTING))
return;
- MovepointReached(Data);
+
+ if (MovementType == WAYPOINT_MOTION_TYPE || (MovementType == POINT_MOTION_TYPE && Data == SMART_ESCORT_LAST_OOC_POINT))
+ MovepointReached(Data);
}
void SmartAI::EnterEvadeMode(EvadeReason /*why*/)
@@ -451,6 +498,7 @@ void SmartAI::EnterEvadeMode(EvadeReason /*why*/)
me->GetMotionMaster()->MoveFollow(target, mFollowDist, mFollowAngle);
// evade is not cleared in MoveFollow, so we can't keep it
me->ClearUnitState(UNIT_STATE_EVADE);
+ GetScript()->OnReset();
}
else if (Unit* owner = me->GetCharmerOrOwner())
{
@@ -460,8 +508,8 @@ void SmartAI::EnterEvadeMode(EvadeReason /*why*/)
else
me->GetMotionMaster()->MoveTargetedHome();
- if (!HasEscortState(SMART_ESCORT_ESCORTING)) //dont mess up escort movement after combat
- SetRun(mRun);
+ if (!me->HasUnitState(UNIT_STATE_EVADE))
+ GetScript()->OnReset();
}
void SmartAI::MoveInLineOfSight(Unit* who)
@@ -574,24 +622,13 @@ void SmartAI::EnterCombat(Unit* enemy)
me->InterruptNonMeleeSpells(false); // must be before ProcessEvents
GetScript()->ProcessEventsFor(SMART_EVENT_AGGRO, enemy);
-
- if (!IsAIControlled())
- return;
- mLastOOCPos = me->GetPosition();
- SetRun(mRun);
- if (me->GetMotionMaster()->GetMotionSlotType(MOTION_SLOT_ACTIVE) == POINT_MOTION_TYPE)
- me->GetMotionMaster()->MovementExpired();
}
void SmartAI::JustDied(Unit* killer)
{
GetScript()->ProcessEventsFor(SMART_EVENT_DEATH, killer);
if (HasEscortState(SMART_ESCORT_ESCORTING))
- {
EndPath(true);
- me->StopMoving();//force stop
- me->GetMotionMaster()->MoveIdle();
- }
}
void SmartAI::KilledUnit(Unit* victim)
@@ -606,10 +643,26 @@ void SmartAI::JustSummoned(Creature* creature)
void SmartAI::AttackStart(Unit* who)
{
+ // dont allow charmed npcs to act on their own
+ if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED))
+ {
+ if (who && mCanAutoAttack)
+ me->Attack(who, true);
+ return;
+ }
+
if (who && me->Attack(who, me->IsWithinMeleeRange(who)))
{
if (mCanCombatMove)
+ {
+ SetRun(mRun);
+
+ MovementGeneratorType type = me->GetMotionMaster()->GetMotionSlotType(MOTION_SLOT_ACTIVE);
+ if (type == WAYPOINT_MOTION_TYPE || type == POINT_MOTION_TYPE)
+ me->StopMoving();
+
me->GetMotionMaster()->MoveChase(who);
+ }
}
}
@@ -777,6 +830,7 @@ void SmartAI::SetCombatMove(bool on)
{
if (mCanCombatMove == on)
return;
+
mCanCombatMove = on;
if (!IsAIControlled())
return;
@@ -793,12 +847,9 @@ void SmartAI::SetCombatMove(bool on)
}
else
{
- if (me->HasUnitState(UNIT_STATE_CONFUSED_MOVE | UNIT_STATE_FLEEING_MOVE))
- return;
-
- me->GetMotionMaster()->MovementExpired();
- me->GetMotionMaster()->Clear(true);
me->StopMoving();
+ if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == CHASE_MOTION_TYPE)
+ me->GetMotionMaster()->Clear(false);
me->GetMotionMaster()->MoveIdle();
}
}
diff --git a/src/server/game/AI/SmartScripts/SmartAI.h b/src/server/game/AI/SmartScripts/SmartAI.h
index fbfa2783db8..4e46339bcaa 100644
--- a/src/server/game/AI/SmartScripts/SmartAI.h
+++ b/src/server/game/AI/SmartScripts/SmartAI.h
@@ -23,8 +23,7 @@
#include "GameObjectAI.h"
#include "Position.h"
#include "SmartScript.h"
-
-struct WayPoint;
+#include "WaypointDefines.h"
enum SmartEscortState
{
@@ -43,7 +42,7 @@ enum SmartEscortVars
class TC_GAME_API SmartAI : public CreatureAI
{
public:
- ~SmartAI(){ }
+ ~SmartAI();
explicit SmartAI(Creature* c);
// Check whether we are currently permitted to make the creature take action
@@ -56,7 +55,6 @@ class TC_GAME_API SmartAI : public CreatureAI
void StopPath(uint32 DespawnTime = 0, uint32 quest = 0, bool fail = false);
void EndPath(bool fail = false);
void ResumePath();
- WayPoint* GetNextWayPoint();
bool HasEscortState(uint32 uiEscortState) const { return (mEscortState & uiEscortState) != 0; }
void AddEscortState(uint32 uiEscortState) { mEscortState |= uiEscortState; }
void RemoveEscortState(uint32 uiEscortState) { mEscortState &= ~uiEscortState; }
@@ -209,15 +207,13 @@ class TC_GAME_API SmartAI : public CreatureAI
void ReturnToLastOOCPos();
void UpdatePath(const uint32 diff);
SmartScript mScript;
- WPPath* mWayPoints;
uint32 mEscortState;
uint32 mCurrentWPID;
- uint32 mLastWPIDReached;
bool mWPReached;
+ bool mOOCReached;
+ bool m_Ended;
uint32 mWPPauseTimer;
- WayPoint* mLastWP;
- Position mLastOOCPos;//set on enter combat
- uint32 GetWPCount() const { return mWayPoints ? uint32(mWayPoints->size()) : 0; }
+ uint32 mEscortNPCFlags;
bool mCanRepeatPath;
bool mRun;
bool mEvadeDisabled;
@@ -227,6 +223,7 @@ class TC_GAME_API SmartAI : public CreatureAI
uint32 mInvincibilityHpLevel;
bool AssistPlayerInCombatAgainst(Unit* who);
+ WaypointPath _path;
uint32 mDespawnTime;
uint32 mRespawnTime;
uint32 mDespawnState;
diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp
index b20329cd319..f5ccf93006b 100644
--- a/src/server/game/AI/SmartScripts/SmartScript.cpp
+++ b/src/server/game/AI/SmartScripts/SmartScript.cpp
@@ -2461,64 +2461,6 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
sGameEventMgr->StartEvent(eventId, true);
break;
}
- case SMART_ACTION_START_CLOSEST_WAYPOINT:
- {
- uint32 waypoints[SMART_ACTION_PARAM_COUNT];
- waypoints[0] = e.action.closestWaypointFromList.wp1;
- waypoints[1] = e.action.closestWaypointFromList.wp2;
- waypoints[2] = e.action.closestWaypointFromList.wp3;
- waypoints[3] = e.action.closestWaypointFromList.wp4;
- waypoints[4] = e.action.closestWaypointFromList.wp5;
- waypoints[5] = e.action.closestWaypointFromList.wp6;
- float distanceToClosest = std::numeric_limits<float>::max();
- WayPoint* closestWp = nullptr;
-
- ObjectList* targets = GetTargets(e, unit);
- if (targets)
- {
- for (ObjectList::iterator itr = targets->begin(); itr != targets->end(); ++itr)
- {
- if (Creature* target = (*itr)->ToCreature())
- {
- if (IsSmart(target))
- {
- for (uint8 i = 0; i < SMART_ACTION_PARAM_COUNT; i++)
- {
- if (!waypoints[i])
- continue;
-
- WPPath* path = sSmartWaypointMgr->GetPath(waypoints[i]);
-
- if (!path || path->empty())
- continue;
-
- WPPath::const_iterator itrWp = path->find(0);
-
- if (itrWp != path->end())
- {
- if (WayPoint* wp = itrWp->second)
- {
- float distToThisPath = target->GetDistance(wp->x, wp->y, wp->z);
-
- if (distToThisPath < distanceToClosest)
- {
- distanceToClosest = distToThisPath;
- closestWp = wp;
- }
- }
- }
- }
-
- if (closestWp)
- CAST_AI(SmartAI, target->AI())->StartPath(false, closestWp->id, true);
- }
- }
- }
-
- delete targets;
- }
- break;
- }
case SMART_ACTION_RANDOM_SOUND:
{
std::vector<uint32> sounds;
diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp
index 30433bc328b..60b5e63936b 100644
--- a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp
+++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp
@@ -41,14 +41,6 @@ void SmartWaypointMgr::LoadFromDB()
{
uint32 oldMSTime = getMSTime();
- for (std::unordered_map<uint32, WPPath*>::iterator itr = waypoint_map.begin(); itr != waypoint_map.end(); ++itr)
- {
- for (WPPath::iterator pathItr = itr->second->begin(); pathItr != itr->second->end(); ++pathItr)
- delete pathItr->second;
-
- delete itr->second;
- }
-
waypoint_map.clear();
PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_SMARTAI_WP);
@@ -76,9 +68,10 @@ void SmartWaypointMgr::LoadFromDB()
y = fields[3].GetFloat();
z = fields[4].GetFloat();
+ WPPath& path = waypoint_map[entry];
+
if (last_entry != entry)
{
- waypoint_map[entry] = new WPPath();
last_id = 1;
count++;
}
@@ -87,7 +80,14 @@ void SmartWaypointMgr::LoadFromDB()
TC_LOG_ERROR("sql.sql", "SmartWaypointMgr::LoadFromDB: Path entry %u, unexpected point id %u, expected %u.", entry, id, last_id);
last_id++;
- (*waypoint_map[entry])[id] = new WayPoint(id, x, y, z);
+
+ WayPoint point;
+ point.id = id;
+ point.x = x;
+ point.y = y;
+ point.z = z;
+
+ path.push_back(std::move(point));
last_entry = entry;
total++;
@@ -97,17 +97,6 @@ void SmartWaypointMgr::LoadFromDB()
TC_LOG_INFO("server.loading", ">> Loaded %u SmartAI waypoint paths (total %u waypoints) in %u ms", count, total, GetMSTimeDiffToNow(oldMSTime));
}
-SmartWaypointMgr::~SmartWaypointMgr()
-{
- for (std::unordered_map<uint32, WPPath*>::iterator itr = waypoint_map.begin(); itr != waypoint_map.end(); ++itr)
- {
- for (WPPath::iterator pathItr = itr->second->begin(); pathItr != itr->second->end(); ++pathItr)
- delete pathItr->second;
-
- delete itr->second;
- }
-}
-
SmartAIMgr* SmartAIMgr::instance()
{
static SmartAIMgr instance;
@@ -1249,7 +1238,8 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
break;
case SMART_ACTION_WP_START:
{
- if (!sSmartWaypointMgr->GetPath(e.action.wpStart.pathID))
+ WPPath const* path = sSmartWaypointMgr->GetPath(e.action.wpStart.pathID);
+ if (!path || path->empty())
{
TC_LOG_ERROR("sql.sql", "SmartAIMgr: Creature " SI64FMTD " Event %u Action %u uses non-existent WaypointPath id %u, skipped.", e.entryOrGuid, e.event_id, e.GetActionType(), e.action.wpStart.pathID);
return false;
@@ -1411,7 +1401,6 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
break;
}
- case SMART_ACTION_START_CLOSEST_WAYPOINT:
case SMART_ACTION_FOLLOW:
case SMART_ACTION_SET_ORIENTATION:
case SMART_ACTION_STORE_TARGET_LIST:
diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.h b/src/server/game/AI/SmartScripts/SmartScriptMgr.h
index 2c2768830fd..87d142aa0ab 100644
--- a/src/server/game/AI/SmartScripts/SmartScriptMgr.h
+++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.h
@@ -29,13 +29,7 @@ enum SpellEffIndex : uint8;
struct WayPoint
{
- WayPoint(uint32 _id, float _x, float _y, float _z)
- {
- id = _id;
- x = _x;
- y = _y;
- z = _z;
- }
+ WayPoint() : id(0), x(0.0f), y(0.0f), z(0.0f) { }
uint32 id;
float x;
@@ -563,7 +557,7 @@ enum SMART_ACTION
SMART_ACTION_REMOVE_POWER = 110, // PowerType, newPower
SMART_ACTION_GAME_EVENT_STOP = 111, // GameEventId
SMART_ACTION_GAME_EVENT_START = 112, // GameEventId
- SMART_ACTION_START_CLOSEST_WAYPOINT = 113, // wp1, wp2, wp3, wp4, wp5, wp6, wp7
+ // Not used = 113,
SMART_ACTION_MOVE_OFFSET = 114,
SMART_ACTION_RANDOM_SOUND = 115, // soundId1, soundId2, soundId3, soundId4, soundId5, onlySelf
SMART_ACTION_SET_CORPSE_DELAY = 116, // timer
@@ -1460,7 +1454,7 @@ struct SmartScriptHolder
operator bool() const { return entryOrGuid != 0; }
};
-typedef std::unordered_map<uint32, WayPoint*> WPPath;
+typedef std::vector<WayPoint> WPPath;
typedef std::list<WorldObject*> ObjectList;
@@ -1492,22 +1486,23 @@ class TC_GAME_API SmartWaypointMgr
{
private:
SmartWaypointMgr() { }
- ~SmartWaypointMgr();
+ ~SmartWaypointMgr() { }
public:
static SmartWaypointMgr* instance();
void LoadFromDB();
- WPPath* GetPath(uint32 id)
+ WPPath const* GetPath(uint32 id)
{
- if (waypoint_map.find(id) != waypoint_map.end())
- return waypoint_map[id];
- else return nullptr;
+ auto itr = waypoint_map.find(id);
+ if (itr != waypoint_map.end())
+ return &itr->second;
+ return nullptr;
}
private:
- std::unordered_map<uint32, WPPath*> waypoint_map;
+ std::unordered_map<uint32, WPPath> waypoint_map;
};
// all events for a single entry