Skip to content
This repository has been archived by the owner on Jan 18, 2024. It is now read-only.

Commit

Permalink
Core/Movement: implement smooth waypoints
Browse files Browse the repository at this point in the history
* delays can now be negative to support sniffed transition times from one waypoint path to another
* early transitions will now pick up the ongoing spline destination and start calculating their path from that point on
* waypoints may now use db side spline pathings in a new db table to support special spline shapes are not generated by normal pathfinding (e.g. scripted flight paths)
* current waypoints will still the work the way they did before for legacy and custom support
  • Loading branch information
Ovahlord committed Jan 15, 2021
1 parent 4a158fd commit d5f9b8c
Show file tree
Hide file tree
Showing 11 changed files with 264 additions and 162 deletions.
11 changes: 11 additions & 0 deletions sql/updates/world/4.3.4/2020_99_99_00_world.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
DROP TABLE IF EXISTS `waypoint_data_addon`;
CREATE TABLE `waypoint_data_addon` (
`PathID` INT(10) UNSIGNED NOT NULL DEFAULT 0,
`PointID` INT(10) UNSIGNED NOT NULL DEFAULT 0,
`SplinePointIndex` TINYINT(3) UNSIGNED NOT NULL DEFAULT 0,
`PositionX` FLOAT NOT NULL DEFAULT 0,
`PositionY` FLOAT NOT NULL DEFAULT 0,
`PositionZ` FLOAT NOT NULL DEFAULT 0
);

ALTER TABLE `waypoint_data` CHANGE `delay` `delay` INT(10) DEFAULT 0 NOT NULL;
280 changes: 148 additions & 132 deletions src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -54,23 +54,24 @@ class WaypointMovementGenerator<Creature> : public MovementGeneratorMedium<Creat
void UnitSpeedChanged() override { _recalculateSpeed = true; }
void Pause(uint32 timer = 0) override;
void Resume(uint32 overrideTimer = 0) override;

void MovementInform(Creature*);

bool GetResetPos(Creature*, float& x, float& y, float& z);
bool GetResetPosition(Unit*, float& x, float& y, float& z) override;

private:
void OnArrived(Creature*);
void HandleMovementInformationHooks(Creature*);
void StartMove(Creature*, bool relaunch = false);
static bool CanMove(Creature*);
bool IsAllowedToMove(Creature*);

TimeTrackerSmall _nextMoveTime;
bool _recalculateSpeed;
bool _isArrivalDone;
TimeTrackerSmall _nextMoveTimer;
TimeTrackerSmall _movementInformTimer;

uint32 _lastSplineId;
uint32 _pathId;
bool _waypointReached;
bool _recalculateSpeed;
bool _repeating;
bool _loadedFromDB;
bool _stalled;
bool _hasBeenStalled;
bool _done;
};

Expand Down
22 changes: 11 additions & 11 deletions src/server/game/Movement/PathGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "PathGenerator.h"
#include "Map.h"
#include "Creature.h"
#include "G3DPosition.hpp"
#include "MMapFactory.h"
#include "MMapManager.h"
#include "Log.h"
Expand Down Expand Up @@ -55,21 +56,20 @@ PathGenerator::~PathGenerator()
TC_LOG_DEBUG("maps.mmaps", "++ PathGenerator::~PathGenerator() for %u", _source->GetGUID().GetCounter());
}

bool PathGenerator::CalculatePath(float destX, float destY, float destZ, bool forceDest)
bool PathGenerator::CalculatePath(float destX, float destY, float destZ, bool forceDest /*= false*/)
{
float x, y, z;
_source->GetPosition(x, y, z);
return CalculatePath(PositionToVector3(_source->GetPosition()), G3D::Vector3(destX, destY, destZ), forceDest);
}

if (!Trinity::IsValidMapCoord(destX, destY, destZ) || !Trinity::IsValidMapCoord(x, y, z))
bool PathGenerator::CalculatePath(G3D::Vector3 const& startPoint, G3D::Vector3 const& endPoint, bool forceDest /*= false*/)
{
if (!Trinity::IsValidMapCoord(startPoint.x, startPoint.y, startPoint.z) || !Trinity::IsValidMapCoord(endPoint.x, endPoint.y, endPoint.z))
return false;

TC_METRIC_EVENT("mmap_events", "CalculatePath", "");

G3D::Vector3 dest(destX, destY, destZ);
SetEndPosition(dest);

G3D::Vector3 start(x, y, z);
SetStartPosition(start);
SetEndPosition(endPoint);
SetStartPosition(startPoint);

_forceDestination = forceDest;

Expand All @@ -79,7 +79,7 @@ bool PathGenerator::CalculatePath(float destX, float destY, float destZ, bool fo
// check if the start and end point have a .mmtile loaded (can we pass via not loaded tile on the way?)
const Unit* _sourceUnit = _source->ToUnit();
if (!_navMesh || !_navMeshQuery || (_sourceUnit && _sourceUnit->HasUnitState(UNIT_STATE_IGNORE_PATHFINDING)) ||
!HaveTile(start) || !HaveTile(dest))
!HaveTile(startPoint) || !HaveTile(endPoint))
{
BuildShortcut();
_type = PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH);
Expand All @@ -88,7 +88,7 @@ bool PathGenerator::CalculatePath(float destX, float destY, float destZ, bool fo

UpdateFilter();

BuildPolyPath(start, dest);
BuildPolyPath(startPoint, endPoint);
return true;
}

Expand Down
2 changes: 2 additions & 0 deletions src/server/game/Movement/PathGenerator.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ class TC_GAME_API PathGenerator
// Calculate the path from owner to given destination
// return: true if new path was calculated, false otherwise (no change needed)
bool CalculatePath(float destX, float destY, float destZ, bool forceDest = false);
// Calculates the path from start point to given destination
bool CalculatePath(G3D::Vector3 const& startPoint, G3D::Vector3 const& endPoint, bool forceDest = false);
bool IsInvalidDestinationZ(Unit const* target) const;

// option setters - use optional
Expand Down
20 changes: 13 additions & 7 deletions src/server/game/Movement/Spline/MoveSplineInit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "MoveSpline.h"
#include "MovementPacketBuilder.h"
#include "Creature.h"
#include "G3DPosition.hpp"
#include "Unit.h"
#include "PathGenerator.h"
#include "Transport.h"
Expand Down Expand Up @@ -242,17 +243,12 @@ namespace Movement
std::transform(controls.begin(), controls.end(), args.path.begin(), TransportPathTransform(unit, args.TransformForTransport));
}

void MoveSplineInit::MoveTo(float x, float y, float z, bool generatePath, bool forceDestination)
{
MoveTo(G3D::Vector3(x, y, z), generatePath, forceDestination);
}

void MoveSplineInit::MoveTo(Vector3 const& dest, bool generatePath, bool forceDestination)
void MoveSplineInit::MoveTo(Vector3 const& start, Vector3 const& dest, bool generatePath, bool forceDestination)
{
if (generatePath)
{
PathGenerator path(unit);
bool result = path.CalculatePath(dest.x, dest.y, dest.z, forceDestination);
bool result = path.CalculatePath(start, dest, forceDestination);
if (result && !(path.GetPathType() & PATHFIND_NOPATH))
{
MovebyPath(path.GetPath());
Expand All @@ -266,6 +262,16 @@ namespace Movement
args.path[1] = transform(dest);
}

void MoveSplineInit::MoveTo(float x, float y, float z, bool generatePath, bool forceDestination)
{
MoveTo(PositionToVector3(unit->GetPosition()), G3D::Vector3(x, y, z), generatePath, forceDestination);
}

void MoveSplineInit::MoveTo(Vector3 const& dest, bool generatePath, bool forceDestination)
{
MoveTo(PositionToVector3(unit->GetPosition()), dest, generatePath, forceDestination);
}

void MoveSplineInit::SetFall()
{
args.flags.EnableFalling();
Expand Down
1 change: 1 addition & 0 deletions src/server/game/Movement/Spline/MoveSplineInit.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ namespace Movement

/* Initializes simple A to B motion, A is current unit's position, B is destination
*/
void MoveTo(Vector3 const& start, Vector3 const& destination, bool generatePath = true, bool forceDestination = false);
void MoveTo(Vector3 const& destination, bool generatePath = true, bool forceDestination = false);
void MoveTo(float x, float y, float z, bool generatePath = true, bool forceDestination = false);

Expand Down
4 changes: 3 additions & 1 deletion src/server/game/Movement/Waypoints/WaypointDefines.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#define TRINITY_WAYPOINTDEFINES_H

#include "Define.h"
#include "G3D/Vector3.h"
#include <vector>

enum WaypointMoveType
Expand All @@ -45,10 +46,11 @@ struct WaypointNode
uint32 Id;
float X, Y, Z, Orientation;
float Velocity;
uint32 Delay;
int32 Delay;
uint32 EventId;
uint32 MoveType;
uint8 EventChance;
std::vector<G3D::Vector3> SplinePoints;
};

struct WaypointPath
Expand Down
59 changes: 58 additions & 1 deletion src/server/game/Movement/Waypoints/WaypointManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ void WaypointMgr::Load()
continue;
}

waypoint.Delay = fields[8].GetUInt32();
waypoint.Delay = fields[8].GetInt32();
waypoint.EventId = fields[9].GetUInt32();
waypoint.EventChance = fields[10].GetInt16();

Expand All @@ -78,6 +78,63 @@ void WaypointMgr::Load()
TC_LOG_INFO("server.loading", ">> Loaded %u waypoints in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
}

void WaypointMgr::LoadWaypointAddons()
{
uint32 oldMSTime = getMSTime();

// 0 1 2 3 4 5
QueryResult result = WorldDatabase.Query("SELECT PathID, PointID, SplinePointIndex, PositionX, PositionY, PositionZ FROM waypoint_data_addon ORDER BY PathID, PointID, SplinePointIndex");

if (!result)
{
TC_LOG_INFO("server.loading", ">> Loaded 0 waypoints. DB table `waypoint_data_addon` is empty!");
return;
}

uint32 count = 0;

do
{
Field* fields = result->Fetch();
uint32 pathId = fields[0].GetUInt32();

std::unordered_map<uint32, WaypointPath>::iterator it = _waypointStore.find(pathId);
if (it == _waypointStore.end())
{
TC_LOG_ERROR("sql.sql", "Tried to load waypoint_data_addon data for PathID %u but there is no such path in waypoint_data. Ignoring.", pathId);
continue;
}

WaypointPath& path = it->second;
uint32 pointId = fields[1].GetUInt32();


std::vector<WaypointNode>::iterator itr = std::find_if(path.Nodes.begin(), path.Nodes.end(), [pointId](WaypointNode const& node)
{
return node.Id == pointId;
});

if (itr == path.Nodes.end())
{
TC_LOG_ERROR("sql.sql", "Tried to load waypoint_data_addon data for PointID %u of PathID %u but there is no such point in waypoint_data. Ignoring.", pointId, pathId);
continue;
}

float x = fields[3].GetFloat();
float y = fields[4].GetFloat();
float z = fields[5].GetFloat();

Trinity::NormalizeMapCoord(x);
Trinity::NormalizeMapCoord(y);

itr->SplinePoints.push_back(G3D::Vector3(x, y, z));

++count;
} while (result->NextRow());

TC_LOG_INFO("server.loading", ">> Loaded %u waypoint addon data in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
}

WaypointMgr* WaypointMgr::instance()
{
static WaypointMgr instance;
Expand Down
5 changes: 4 additions & 1 deletion src/server/game/Movement/Waypoints/WaypointManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,12 @@ class TC_GAME_API WaypointMgr
// Attempts to reload a single path from database
void ReloadPath(uint32 id);

// Loads all paths from database, should only run on startup
// Loads all base waypoint data from database. Should only be called on startup.
void Load();

// Loads additional path data for waypoints from database. Should only be called on startup.
void LoadWaypointAddons();

// Returns the path from a given id
WaypointPath const* GetPath(uint32 id) const;

Expand Down
3 changes: 3 additions & 0 deletions src/server/game/World/World.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2108,6 +2108,9 @@ void World::SetInitialWorldSettings()
TC_LOG_INFO("server.loading", "Loading Waypoints...");
sWaypointMgr->Load();

TC_LOG_INFO("server.loading", "Loading Waypoint Addons...");
sWaypointMgr->LoadWaypointAddons();

TC_LOG_INFO("server.loading", "Loading SmartAI Waypoints...");
sSmartWaypointMgr->LoadFromDB();

Expand Down

0 comments on commit d5f9b8c

Please sign in to comment.