diff options
Diffstat (limited to 'src/server/game/AI/SmartScripts')
| -rw-r--r-- | src/server/game/AI/SmartScripts/SmartAI.cpp | 299 | ||||
| -rw-r--r-- | src/server/game/AI/SmartScripts/SmartAI.h | 15 | ||||
| -rw-r--r-- | src/server/game/AI/SmartScripts/SmartScript.cpp | 58 | ||||
| -rw-r--r-- | src/server/game/AI/SmartScripts/SmartScriptMgr.cpp | 35 | ||||
| -rw-r--r-- | src/server/game/AI/SmartScripts/SmartScriptMgr.h | 25 |
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 |
