A lightweight, circular-buffer based GPS navigation system for open.mp.
Drawing a line from LS to LV takes way more than the 1024 gangzones SA-MP gives us per player. Most scripts just hit the limit and break.
It simply bumps the pointer. When the buffer is full (default 600), it pauses rendering the path ahead until you move forward and free up slots in the tail. It essentially "streams" the path to the client.
You need the pathfinding plugin to calculate the nodes This library just handles the rendering logic.
- open.mp
- omp-stdlib
- samp-gps-plugin (Handles the A* math on a separate thread so the server doesn't choke)
It should theoretically also work with SA-MP's standard library/server, but you will need YSF for player gangzones.
I haven't tested it myself, so you're on your own. If you run into any SA-MP issues while testing, feel free to open an issue or submit a PR, and I'll surely have a look.
If you are using the latest open.mp includes, you are going to get a compiler error that looks like this: GPS.inc(12) : error 020: invalid symbol name ""
The GPS plugin include defines a constant named INVALID_PATH_ID.
The latest open.mp standard library also introduced a constant named INVALID_PATH_ID (for the NPC component). Since Pawn has a global namespace, they conflict.
Open your GPS.inc file (from the plugin), find the definition, and rename it to avoid the collision:
// Inside GPS.inc (line 10)
// Change this line:
#define INVALID_PATH_ID (0)
// To this:
#define INVALID_GPS_PATH_ID (0)This library (gps-nav) expects the path ID to be passed around anyway, so just make sure your plugin include doesn't conflict with the stdlib.
You can tweak the settings at the top of your script before including the file.
// 600 is a good sweetspot. Sufficient for buffer, saves memory.
// Going higher than 800 risks hitting the per-player gangzone limit if you use zones elsewhere.
#define MAX_GPS_ZONES 600
#define GPS_LINE_WIDTH 15.0
#define GPS_COLOR 0xA850E6FF
#define GPS_UPDATE_INTERVAL 400 // MillisecondsIt's plug-and-play.
#include <gps-nav>
// Start navigation
// Returns 1 if path found, 0 if failed.
GPS_Start(playerid, targetX, targetY, targetZ);
// Stop navigation
GPS_Stop(playerid);
// Check if active
if(GPS_IsActive(playerid)) {
// ...
}These are useful events to handle UI elements (like setting the map marker).
Called immediately when GPS_Start is initialized.
Example:
public OnPlayerGPSActivate(playerid, Float:X, Float:Y, Float:Z) {
// Set a global waypoint icon (ID 0) so they can see where they are going
SetPlayerMapIcon(playerid, 0, X, Y, Z, 41, 0, MAPICON_GLOBAL);
return 1;
}Called when the player is within range of the destination.
Example:
public OnPlayerGPSArrival(playerid) {
RemovePlayerMapIcon(playerid, 0);
GameTextForPlayer(playerid, "~g~Arrived", 3000, 3);
return 1;
}Note
The pathfinding happens on a separate thread (thanks to the plugin), but the rendering happens in the update tick. The circular buffer keeps it cheap, as long as you don't set GPS_UPDATE_INTERVAL to something like 10ms.