https://github.com/y-less/samp-distance
https://github.com/y-less/samp-distance
Last synced: about 2 months ago
JSON representation
- Host: GitHub
- URL: https://github.com/y-less/samp-distance
- Owner: Y-Less
- Created: 2019-03-23T16:09:46.000Z (about 6 years ago)
- Default Branch: master
- Last Pushed: 2022-11-28T11:20:08.000Z (over 2 years ago)
- Last Synced: 2025-01-30T17:39:22.682Z (4 months ago)
- Language: Pawn
- Size: 124 KB
- Stars: 19
- Watchers: 3
- Forks: 3
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# SA-MP Distance Functions
[](https://github.com/kristoisberg/samp-distance)
This library offers a bunch of functions for getting the distance between various entities (2D/3D points, players, vehicles), performing proximity/distance checks between them and finding the closest entities to other entities. The idea for this library came after seeing a discussion on this topic on the forums and realising that there is no widely adopted library for performing these tasks and the homebrewed implementations often have major issues. Some of the issues this library addresses:
* **Incorrect return values** - If a distance check fails because an entity does not exist, the result of the check is `NaN`, not `0.0` as the standard library would return, `9999.9999`, `-1.0` or any other nonsense. As you might know, comparing `NaN` to any value, even itself, always returns `false`, making it easy to distinguish if the function failed and avoiding incorrect behaviour in code using those functions.
* **Inconsistent and non-descriptive function names** - A function name I saw in the topic mentioned above is `IsCoordNearCoord`, which has a similar behaviour to `IsPlayerInRangeOfPoint` from the standard library, but a completely different name structure. Some other examples are `GetClosestPlayer` and `GetClosestVehicle`, commonly used names for functions returning the closest player/vehicle to a player. The more you read the previous sentence, the more you will realise that the names are missing something...Huge thanks to Y_Less for his contributions to this library and the productive conversations with him!
## Installation
Simply install to your project:
```bash
sampctl package install kristoisberg/samp-distance
```Include in your code and begin using the library:
```pawn
#include
```## Changes to the standard library
This library hooks the `GetPlayerDistanceFromPoint` and `GetVehicleDistanceFromPoint` functions to return `NaN` instead of `0.0` when the functions fail (the player/vehicle does not exist). These changes should not affect any existing code since it should be checking for invalid players/vehicles before using these functions anyway.
## Function Naming
The functions in this library have several basic forms:
* `GetDistanceTo` - Get the distance between `A` and `B`.
* `IsInRangeOf` - Is the distance between `A` and `B` lower than some threshold?
* `GetClosestTo` - Get the closest `A` to `B`.Plus a few "Point" functions which take an `x/y` pair or `x/y/z` triple instead of another entity:
* `GetDistanceToPoint2D` - Get the distance between `A` and an `x/y` point.
* `IsInRangeOfPoint2D` - Is the distance between `A` and an `x/y` point lower than some threshold?
* `GetDistanceToPoint3D` - Get the distance between `A` and an `x/y/z` point.
* `IsInRangeOfPoint3D` - Is the distance between `A` and an `x/y/z` point lower than some threshold?And the overloaded versions that are determined by parameter count:
* `GetDistanceToPoint` - Get the distance between `A` and an `x/y(/z)` point.
* `IsInRangeOfPoint` - Is the distance between `A` and an `x/y(/z)` point lower than some threshold?For each of these functions `A` and `B` can be any of the following entity types:
* `Player`
* `Vehicle`
* `Object`
* `DynObject` (with the streamer plugin).
* `Actor`So for example, to check if a vehicle (`A`) is near a given streamer object (`B`) use:
```pawn
if (IsVehicleInRangeOfDynObject(vehicleid, objectid, 50.0))
{
// Yes.
}
```There are also two generic point functions:
```pawn
stock Float:GetPointDistanceToPoint(Float:x1, Float:y1, Float:z1, Float:x2, Float:y2 = FLOAT_NAN, Float:z2 = FLOAT_NAN);
stock bool:IsPointInRangeOfPoint(Float:range, Float:x1, Float:y1, Float:z1, Float:x2, Float:y2 = FLOAT_NAN, Float:z2 = FLOAT_NAN);
```These can be invoked as 2D (with four/five parameters) or 3D (with six/seven parameters).
In many cases a function is overloaded on the number of parameters:
```pawn
if (IsVehicleInRangeOfPoint(vehicleid, 4.0, 5.0, 10.0)) // 2D check.
{
}if (IsVehicleInRangeOfPoint(vehicleid, 4.0, 5.0, 6.0, 10.0)) // 3D check.
{
}
```You can specify which with `IsVehicleInRangeOfPoint2D` and `IsVehicleInRangeOfPoint3D`, the underlying implementations, as listed below.
## All Functions
Functions that return `Float:` will return `FLOAT_NAN` if they fail. If, for example, one of the input entities doesn't exist.
### Point - Point
```pawn
Float:GetPointDistanceToPoint(Float:x1, Float:y1, Float:z1, Float:x2, Float:y2 = FLOAT_NAN, Float:z2 = FLOAT_NAN);bool:IsPointInRangeOfPoint(Float:range, Float:x1, Float:y1, Float:z1, Float:x2, Float:y2 = FLOAT_NAN, Float:z2 = FLOAT_NAN);
```### Player - Point
```pawn
Float:GetPlayerDistanceToPoint2D(playerid, Float:x, Float:y);bool:IsPlayerInRangeOfPoint2D(playerid, Float:range, Float:x, Float:y);
Float:GetPlayerDistanceToPoint3D(playerid, Float:x, Float:y, Float:z);
bool:IsPlayerInRangeOfPoint3D(playerid, Float:range, Float:x, Float:y, Float:z);
```### Player - Player
```pawn
Float:GetPlayerDistanceToPlayer(playerid, targetid);bool:IsPlayerInRangeOfPlayer(playerid, targetid, Float:range, bool:ignoreVW = false, bool:ignoreInterior = false);
GetClosestPlayerToPlayer(playerid, bool:ignoreVW = false, bool:ignoreInterior = false);
```### Vehicle - Point
```pawn
Float:GetVehicleDistanceToPoint2D(vehicleid, Float:x, Float:y);bool:IsVehicleInRangeOfPoint2D(vehicleid, Float:range, Float:x, Float:y);
Float:GetVehicleDistanceToPoint3D(vehicleid, Float:x, Float:y, Float:z);
bool:IsVehicleInRangeOfPoint3D(vehicleid, Float:range, Float:x, Float:y, Float:z);
```### Vehicle - Vehicle
```pawn
Float:GetVehicleDistanceToVehicle(vehicleid, targetid);bool:IsVehicleInRangeOfVehicle(vehicleid, targetid, Float:range, bool:ignoreVW = false);
GetClosestVehicleToVehicle(vehicleid, bool:ignoreVW = false);
```### Object - Point
```pawn
Float:GetObjectDistanceToPoint2D(objectid, Float:x, Float:y);bool:IsObjectInRangeOfPoint2D(objectid, Float:range, Float:x, Float:y);
Float:GetObjectDistanceToPoint3D(objectid, Float:x, Float:y, Float:z);
bool:IsObjectInRangeOfPoint3D(objectid, Float:range, Float:x, Float:y, Float:z);
```### Object - Object
```pawn
Float:GetObjectDistanceToObject(objectid, targetid);bool:IsObjectInRangeOfObject(objectid, targetid, Float:range);
GetClosestObjectToObject(objectid);
```### DynObject - Point
```pawn
Float:GetDynObjectDistanceToPoint2D(STREAMER_TAG_OBJECT:objectid, Float:x, Float:y);bool:IsDynObjectInRangeOfPoint2D(STREAMER_TAG_OBJECT:objectid, Float:range, Float:x, Float:y);
Float:GetDynObjectDistanceToPoint3D(STREAMER_TAG_OBJECT:objectid, Float:x, Float:y, Float:z);
bool:IsDynObjectInRangeOfPoint3D(STREAMER_TAG_OBJECT:objectid, Float:range, Float:x, Float:y, Float:z);
```### DynObject - DynObject
```pawn
Float:GetDynObjectDistanceToDynObject(STREAMER_TAG_OBJECT:objectid, STREAMER_TAG_OBJECT:targetid);bool:IsDynObjectInRangeOfDynObject(STREAMER_TAG_OBJECT:objectid, STREAMER_TAG_OBJECT:targetid, Float:range);
STREAMER_TAG_OBJECT:GetClosestDynObjectToDynObject(STREAMER_TAG_OBJECT:objectid);
```### Player - Vehicle
```pawn
Float:GetVehicleDistanceToPlayer(vehicleid, playerid);bool:IsVehicleInRangeOfPlayer(vehicleid, playerid, Float:range, bool:ignoreVW = false);
GetClosestVehicleToPlayer(playerid, bool:ignoreVW = false);
Float:GetPlayerDistanceToVehicle(playerid, vehicleid);
bool:IsPlayerInRangeOfVehicle(playerid, vehicleid, Float:range, bool:ignoreVW = false);
GetClosestPlayerToVehicle(vehicleid, bool:ignoreVW = false);
```### Player - Object
```pawn
Float:GetPlayerDistanceToObject(playerid, objectid);bool:IsPlayerInRangeOfObject(playerid, objectid, Float:range);
GetClosestPlayerToObject(objectid);
Float:GetObjectDistanceToPlayer(objectid, playerid);
bool:IsObjectInRangeOfPlayer(objectid, playerid, Float:range);
GetClosestObjectToPlayer(playerid);
```### Object - Vehicle
```pawn
Float:GetObjectDistanceToVehicle(objectid, vehicleid);bool:IsObjectInRangeOfVehicle(objectid, vehicleid, Float:range);
GetClosestObjectToVehicle(vehicleid);
Float:GetVehicleDistanceToObject(vehicleid, objectid);
bool:IsVehicleInRangeOfObject(vehicleid, objectid, Float:range);
GetClosestVehicleToObject(objectid);
```### DynObject - Player
```pawn
Float:GetDynObjectDistanceToPlayer(STREAMER_TAG_OBJECT:objectid, playerid);bool:IsDynObjectInRangeOfPlayer(STREAMER_TAG_OBJECT:objectid, playerid, Float:range);
STREAMER_TAG_OBJECT:GetClosestDynObjectToPlayer(playerid);
Float:GetPlayerDistanceToDynObject(playerid, STREAMER_TAG_OBJECT:objectid);
bool:IsPlayerInRangeOfDynObject(playerid, STREAMER_TAG_OBJECT:objectid, Float:range);
GetClosestPlayerToDynObject(STREAMER_TAG_OBJECT:objectid);
```### DynObject - Object
```pawn
Float:GetDynObjectDistanceToObject(STREAMER_TAG_OBJECT:objectid, targetid);bool:IsDynObjectInRangeOfObject(STREAMER_TAG_OBJECT:objectid, targetid, Float:range);
STREAMER_TAG_OBJECT:GetClosestDynObjectToObject(objectid);
Float:GetObjectDistanceToDynObject(objectid, STREAMER_TAG_OBJECT:targetid);
bool:IsObjectInRangeOfDynObject(objectid, STREAMER_TAG_OBJECT:targetid, Float:range);
GetClosestObjectToDynObject(STREAMER_TAG_OBJECT:objectid);
```### DynObject - Vehicle
```pawn
Float:GetDynObjectDistanceToVehicle(STREAMER_TAG_OBJECT:objectid, vehicleid);bool:IsDynObjectInRangeOfVehicle(STREAMER_TAG_OBJECT:objectid, vehicleid, Float:range);
STREAMER_TAG_OBJECT:GetClosestDynObjectToVehicle(vehicleid);
Float:GetVehicleDistanceToDynObject(vehicleid, STREAMER_TAG_OBJECT:objectid);
bool:IsVehicleInRangeOfDynObject(vehicleid, STREAMER_TAG_OBJECT:objectid, Float:range);
GetClosestVehicleToDynObject(STREAMER_TAG_OBJECT:objectid);
```### Actor - Point
```pawn
Float:GetActorDistanceToPoint2D(actorid, Float:x, Float:y);bool:IsActorInRangeOfPoint2D(actorid, Float:range, Float:x, Float:y);
Float:GetActorDistanceToPoint3D(actorid, Float:x, Float:y, Float:z);
bool:IsActorInRangeOfPoint3D(actorid, Float:range, Float:x, Float:y, Float:z);
```### Actor - Actor
```pawn
Float:GetActorDistanceToActor(actorid, targetid);bool:IsActorInRangeOfActor(actorid, targetid, Float:range, bool:ignoreVW = false);
GetClosestActorToActor(actorid, bool:ignoreVW = false);
```### Player - Actor
```pawn
Float:GetActorDistanceToPlayer(actorid, playerid);bool:IsActorInRangeOfPlayer(actorid, playerid, Float:range, bool:ignoreVW = false);
GetClosestActorToPlayer(playerid, bool:ignoreVW = false);
Float:GetPlayerDistanceToActor(playerid, actorid);
bool:IsPlayerInRangeOfActor(playerid, actorid, Float:range, bool:ignoreVW = false);
GetClosestPlayerToActor(actorid, bool:ignoreVW = false);
```### Object - Actor
```pawn
Float:GetObjectDistanceToActor(objectid, actorid);bool:IsObjectInRangeOfActor(objectid, actorid, Float:range);
GetClosestObjectToActor(actorid);
Float:GetActorDistanceToObject(actorid, objectid);
bool:IsActorInRangeOfObject(actorid, objectid, Float:range);
GetClosestActorToObject(objectid);
```### Actor - Vehicle
```pawn
Float:GetActorDistanceToVehicle(vehicleid, targetid);bool:IsActorInRangeOfVehicle(vehicleid, targetid, Float:range);
GetClosestActorToVehicle(vehicleid);
Float:GetVehicleDistanceToActor(vehicleid, targetid);
bool:IsVehicleInRangeOfActor(vehicleid, targetid, Float:range);
GetClosestVehicleToActor(vehicleid);
```### DynObject - Actor
```pawn
Float:GetDynObjectDistanceToActor(STREAMER_TAG_OBJECT:objectid, actorid);bool:IsDynObjectInRangeOfActor(STREAMER_TAG_OBJECT:objectid, actorid, Float:range);
STREAMER_TAG_OBJECT:GetClosestDynObjectToActor(actorid);
Float:GetActorDistanceToDynObject(actorid, STREAMER_TAG_OBJECT:objectid);
bool:IsActorInRangeOfDynObject(actorid, STREAMER_TAG_OBJECT:objectid, Float:range);
GetClosestActorToDynObject(STREAMER_TAG_OBJECT:objectid);
```**Note:** The functions with an asterisk (*) next to them only support the `ignoreInterior` argument if the `GetVehicleInterior` function is available (added by YSF, some other library or by a new SA-MP version (yeah, right)).
## Examples
```pawn
CMD:pay(playerid, params[])
{
new playerid2, amount;if (sscanf(params, "ui", playerid2, amount))
{
return SendClientMessage(playerid, COLOR_WHITE, "USAGE: /pay ");
}if (!IsPlayerInRangeOfPlayer(playerid, playerid2, 5.0))
{
// fails if the other player is not connected or not near enough to the player
return SendClientMessage(playerid, COLOR_RED, "The specified player is not near you!");
}GivePlayerMoney(playerid, -amount);
GivePlayerMoney(playerid2, amount);
return 1;
}
``````pawn
CMD:fixtires(playerid)
{
new vehicleid = GetClosestVehicleToPlayer(playerid);if (!IsPlayerInRangeOfVehicle(playerid, vehicleid, 10.0))
{
// fails if no vehicle was found in the same interior and virtual world as the player or the closest one is not near enough to the player
return SendClientMessage(playerid, COLOR_RED, "You are not near any vehicle!");
}new panels, doors, lights, tires;
GetVehicleDamageStatus(vehicleid, panels, doors, lights, tires);
SetVehicleDamageStatus(vehicleid, panels, doors, lights, 0);
return 1;
}
```## Testing
The library is not fully tested as of now because there is no fully working version of `ut_mock_player`/`y_mock` right now (I will be working on one soon). Right now, the tests only check whether the library compiles and the functions in the `Point-Point` section return the correct values. To test, simply run the package:
```bash
sampctl package run
```