NS/main/source/mod/AvHAIMath.h
RGreenlees eba41379e3 Improve bot vision, bug fixes
* Re-added the view frustum for bots
* Hopefully stopped bots getting permanently stuck trying to evolve an upgrade in an invalid place
* Bots will now leave the game after 2 hours if no humans playing (ignores human spectators)
2024-04-08 10:01:46 -04:00

210 lines
No EOL
10 KiB
C

//
// EvoBot - Neoptolemus' Natural Selection bot, based on Botman's HPB bot template
//
// bot_math.h
//
// Contains all useful math functions for bot stuff
//
#pragma once
#ifndef AVH_AI_MATH_H
#define AVH_AI_MATH_H
#include "../dlls/extdll.h"
static const Vector ZERO_VECTOR = Vector(0.0f, 0.0f, 0.0f);
static const Vector UP_VECTOR = Vector(0.0f, 0.0f, 1.0f); // Normalized "up" direction
static const Vector RIGHT_VECTOR = Vector(1.0f, 0.0f, 0.0f); // Normalized "right" direction
static const Vector FWD_VECTOR = Vector(0.0f, 1.0f, 0.0f); // Normalized "forward" direction
static const float MATH_PI = 3.141592654f;
static const float DEGREES_RADIANS_CONV = (MATH_PI / 180.0f);
static const float GOLDSRC_GRAVITY = 400.0f; // Default speed of gravity in GoldSrc units per second squared
// Defines a frustum plane
typedef struct _FRUSTUM_PLANE_T
{
Vector normal;
Vector point;
float d;
} frustum_plane_t;
// GENERAL MATH
// Is the input string a valid integer?
bool isNumber(const char* line);
// Is the input string a valid floating point number?
bool isFloat(const char* line);
// Square the input
float sqrf(float input);
// Return the sign (-1 if number is negative, 1 if positive, 0 if 0)
float signf(float input);
// Clamp float value between min and max
float clampf(float input, float inMin, float inMax);
// Clamp int value between min and max
float clampi(int input, int inMin, int inMax);
// For any given view angle, ensure that the angle is expressed as a value between -180 and 180
float UTIL_WrapAngle(float angle);
// For view angles, ensures that the angles do not exceed -180 or 180
Vector UTIL_WrapAngles(Vector angles);
// Spherical linear interpolation of float from start to end at interp speed
float fInterpTo(float start, float end, float DeltaTime, float InterpSpeed);
// Linear interpolation of float from start to end at interp speed
float fInterpConstantTo(float start, float end, float DeltaTime, float InterpSpeed);
// Random float between min value and max value
float frandrange(float MinValue, float MaxValue);
// Random integer between min and max values
int irandrange(int MinValue, int MaxValue);
// Convert degrees to radians
float fDegreesToRadians(const float Degrees);
// Return random boolean
bool randbool();
// Returns the max of two integers
int imaxi(const int a, const int b);
// Returns the min of two integers
int imini(const int a, const int b);
// VECTOR MATH
// 2D (ignore Z axis) distance between v1 and v2
float vDist2D(const Vector v1, const Vector v2);
// 3D distance between v1 and v2
float vDist3D(const Vector v1, const Vector v2);
// Squared (no sqrt) 2D distance (ignore Z axis) between v1 and v2
float vDist2DSq(const Vector v1, const Vector v2);
// Squared (no sqrt) 3D distance between v1 and v2
float vDist3DSq(const Vector v1, const Vector v2);
// 3D length of vector
float vSize3D(const Vector V);
// 2D length (no Z axis) of vector
float vSize2D(const Vector V);
// Squared 3D length of vector
float vSize3DSq(const Vector V);
// Squared 2D length (no Z axis) of vector
float vSize2DSq(const Vector V);
// Are two vectors equal, using default epsilon of 0.1f
bool vEquals(const Vector v1, const Vector v2);
bool vEquals2D(const Vector v1, const Vector v2);
// Are two vectors equal, using custom epsilon
bool vEquals(const Vector v1, const Vector v2, const float epsilon);
bool vEquals2D(const Vector v1, const Vector v2, const float epsilon);
bool vIsZero(const Vector v1);
bool fNearlyEqual(const float f1, const float f2);
// Returns the dot product of two unit vectors
inline float UTIL_GetDotProduct(const Vector v1, const Vector v2) { return ((v1.x * v2.x) + (v1.y * v2.y) + (v1.z * v2.z)); }
// Returns the dot product of two unit vectors excluding Z axis
float UTIL_GetDotProduct2D(const Vector v1, const Vector v2);
// Normalize the unit vector (modifies input)
void UTIL_NormalizeVector(Vector* vec);
// Normalize the unit vector without the Z axis (modifies input)
void UTIL_NormalizeVector2D(Vector* vec);
// Returns a normalized copy of the input unit vector
Vector UTIL_GetVectorNormal(const Vector vec);
// Returns a normalized 2D copy of the input vector without Z axis
Vector UTIL_GetVectorNormal2D(const Vector vec);
//Returns the cross product of v1 and v2
Vector UTIL_GetCrossProduct(const Vector v1, const Vector v2);
// Returns the surface normal of a poly defined at points v1, v2 and v3 (clockwise)
Vector UTIL_GetSurfaceNormal(const Vector v1, const Vector v2, const Vector v3);
bool vPointOverlaps3D(const Vector Point, const Vector MinBB, const Vector MaxBB);
bool vPointOverlaps2D(const Vector Point, const Vector MinBB, const Vector MaxBB);
bool vBBOverlaps2D(const Vector MinBBA, const Vector MaxBBA, const Vector MinBBB, const Vector MaxBBB);
// For the two lines provided, returns true if they cross each other on the X and Y axis
bool vIntersects2D(const Vector LineAStart, const Vector LineAEnd, const Vector LineBStart, const Vector LineBEnd);
Vector vClosestPointOnBB(const Vector Point, const Vector MinBB, const Vector MaxBB);
void vScaleBB(Vector& MinBB, Vector& MaxBB, const float Scale);
// WIP: Trying to get a working random unit vector in cone. Not currently used
Vector UTIL_GetRandomUnitVectorInCone(const Vector ConeDirection, const float HalfAngleRadians);
Vector random_unit_vector_within_cone(const Vector Direction, double HalfAngleRadians);
// Takes in a bot's current view angle and a target direction to look in, and returns the appropriate view angles. Eases into the target
Vector ViewInterpTo(const Vector CurrentViewAngles, const Vector& TargetDirection, const float DeltaTime, const float InterpSpeed);
// LINE MATH
// For given line defined by lineFrom -> lineTo, how far away from that line is CheckPoint?
float vDistanceFromLine3D(const Vector lineFrom, const Vector lineTo, const Vector CheckPoint);
// For given line defined by lineFrom -> lineTo, how far away from that line is CheckPoint? Ignores Z axis
float vDistanceFromLine2D(const Vector lineFrom, const Vector lineTo, const Vector CheckPoint);
// For given line defined by lineFrom -> lineTo, get squared distance from that line of CheckPoint. Ignores Z axis
float vDistanceFromLine2DSq(const Vector lineFrom, const Vector lineTo, const Vector CheckPoint);
// Returns 0 if point sits right on the line defined by lineFrom -> lineTo, -1 if it sits to the left, 1 if it sits to the right. Ignores Z axis
int vPointOnLine(const Vector lineFrom, const Vector lineTo, const Vector point);
// Finds the closest point along a line to the input point
Vector vClosestPointOnLine(const Vector lineFrom, const Vector lineTo, const Vector point);
// Finds the closest point along a line to the input point, ignores Z axis
Vector vClosestPointOnLine2D(const Vector lineFrom, const Vector lineTo, const Vector point);
// Finds the closest point along a line to the input point, assumes infinite line
Vector vClosestPointOnInfiniteLine3D(const Vector PointOnLine, const Vector NormalisedLineDir, const Vector TestPoint);
// Finds the closest point along a line to the input point, assumes infinite line. Ignores Z axis
Vector vClosestPointOnInfiniteLine2D(const Vector PointOnLine, const Vector NormalisedLineDir, const Vector TestPoint);
// CONVERSIONS
// Converts input metres to GoldSrc units (approx 1 metres = 52.5 units)
float UTIL_MetresToGoldSrcUnits(const float Metres);
// Converts input GoldSrc units to metres (approx 52.5 units = 1 metre)
float UTIL_GoldSrcUnitsToMetres(const float GoldSrcUnits);
// Converts angles to unit vector
void UTIL_AnglesToVector(const Vector angles, Vector* fwd, Vector* right, Vector* up);
// Returns unit vector pointing in direction of input angles
Vector UTIL_GetForwardVector(const Vector angles);
// Returns 2D unit vector pointing in direction of input view angles, ignoring Z axis
Vector UTIL_GetForwardVector2D(const Vector angles);
// GEOMETRY STUFF
// Returns random point on a circle, assuming circle normal is (0, 0, 1)
Vector UTIL_RandomPointOnCircle(const Vector origin, const float radius);
// Returns the required pitch needed to hit the target point from launch point, taking projectile speed and gravity into account
Vector GetPitchForProjectile(Vector LaunchPoint, Vector TargetPoint, const float ProjectileSpeed, const float Gravity);
// Confirms if the given point is on the inside of a frustum plane or not
bool UTIL_PointInsidePlane(const frustum_plane_t* plane, const Vector point);
/* Tests to see if the defined cylinder is intersecting with the supplied frustum plane.
Since players are always upright, it is reasonable to assume that it is impossible for both the
top and bottom of the cylinder to be outside the plane if it is intersecting, therefore
we only need to test the top and bottom cylinder at the closest point to the plane.*/
bool UTIL_CylinderInsidePlane(const frustum_plane_t* plane, const Vector centre, float height, float radius);
// Set the normal and position for the plane based on the 3 points defining it
void UTIL_SetFrustumPlane(frustum_plane_t* plane, Vector v1, Vector v2, Vector v3);
// Finds the closest point to the polygon, defined by segments (edges)
float UTIL_GetDistanceToPolygon2DSq(const Vector TestPoint, const Vector* Segments, const int NumSegments);
// Based on the target's motion and the weapon's projectile speed, where should the bot aim to lead the target and hit them?
Vector UTIL_GetAimLocationToLeadTarget(const Vector ShooterLocation, const Vector TargetLocation, const Vector TargetVelocity, const float ProjectileVelocity);
// If flying through the air (e.g. blink), what velocity does the bot need to land on the target spot?
float UTIL_GetVelocityRequiredToReachTarget(const Vector StartLocation, const Vector TargetLocation, float Gravity);
Vector UTIL_GetRandomPointInBoundingBox(const Vector BoxMin, const Vector BoxMax);
// OTHER STUFF
// Function to get number of set bits in a positive integer n
unsigned int UTIL_CountSetBitsInInteger(unsigned int n);
float UTIL_CalculateSlopeAngleBetweenPoints(const Vector StartPoint, const Vector EndPoint);
bool vlineIntersectsAABB(Vector lineStart, Vector lineEnd, Vector BoxMinPosition, Vector BoxMaxPosition);
#endif