Difference between revisions of "HPL2/HPL2 Helper Scripts/Math"

From Frictional Wiki
Jump to navigation Jump to search
(First version of page, WIP)
 
(Added more methods, and began organising into categories.)
Line 48: Line 48:
 
</syntaxhighlight>
 
</syntaxhighlight>
  
==Methods==
+
==Arithmetic Methods==
Math provides the following methods:
+
Math provides the following miscellaneous methods for working with numbers:
  
 
===Math.NearlyEqual()===
 
===Math.NearlyEqual()===
Line 67: Line 67:
 
// The condition succeeds if the score is near to the target by 0.1.
 
// The condition succeeds if the score is near to the target by 0.1.
 
</syntaxhighlight><br>
 
</syntaxhighlight><br>
 +
 +
===Math.SafeDivide()===
 +
<syntaxhighlight lang="cpp">
 +
float SafeDivide(float afA, float afB)
 +
double SafeDivide(double adA, double adB)
 +
int SafeDivide(int alA, int alB)
 +
uint SafeDivide(uint aulA, uint aulB)
 +
cVector SafeDivide(cVector avA, float afB)
 +
cPoint SafeDivide(cPoint avA, float alB)
 +
</syntaxhighlight>
 +
Avoids divide by zero by checking for zeros first. If either value is zero, it just returns zero.
 +
<br>Accepts a pair of numbers of the same type, or a vector and an appropriate number type.
 +
#''float afA, double adA, int alA, uint aulA, cVector avA, or cPoint avA'' - The value to be divided.
 +
#''float afB, double adB, int alB, or uint aulB'' - The value to be divided by.
 +
<syntaxhighlight lang="cpp">
 +
// Example:
 +
int risky = 10 / Math.RandomInt(0, 3); // 1 in 3 chance of "divide by zero" error.
 +
int safe = Math.SafeDivide(10, Math.RandomInt(0, 3)); // zero chance of "divide by zero" error.
 +
</syntaxhighlight><br>
 +
 +
===Math.DegreesToRadians()===
 +
<syntaxhighlight lang="cpp">
 +
float DegreesToRadians(float afD)
 +
double DegreesToRadians(double adD)
 +
</syntaxhighlight>
 +
Converts degrees to radians and returns the result. (360 degrees is equal to 2*Pi radians.)
 +
#''float afD, double adD'' - An angle in degrees, to be converted to radians.
 +
<syntaxhighlight lang="cpp">
 +
// Example 1:
 +
if (Math.DegreesToRadians(fDeg) == Math.Pi / 2.0f) DoStuff();
 +
// The condition will succeed if fDeg is 90.
 +
</syntaxhighlight><br>
 +
 +
===Math.RadiansToDegrees()===
 +
<syntaxhighlight lang="cpp">
 +
float RadiansToDegrees(float afD)
 +
double RadiansToDegrees(double adD)
 +
</syntaxhighlight>
 +
Converts radians to degrees and returns the result. (360 degrees is equal to 2*Pi radians.)
 +
#''float afD, double adD'' - An angle in radians, to be converted to degrees.
 +
<syntaxhighlight lang="cpp">
 +
// Example 1:
 +
if (Math.DegreesToRadians(Math.Tau * fX) == 90) DoStuff();
 +
// The condition will succeed if fX is 0.25f.
 +
</syntaxhighlight><br>
 +
 +
==Interpolation Methods==
 +
Math provides the following methods for interpolating between values:
  
 
===Math.Lerp()===
 
===Math.Lerp()===
Line 139: Line 187:
 
<br>
 
<br>
  
===Math.SafeDivide()===
+
==Vector Methods==
<syntaxhighlight lang="cpp">
+
Math provides the following methods for working with vectors:
float SafeDivide(float afA, float afB)
 
double SafeDivide(double adA, double adB)
 
int SafeDivide(int alA, int alB)
 
uint SafeDivide(uint aulA, uint aulB)
 
cVector SafeDivide(cVector avA, float afB)
 
cPoint SafeDivide(cPoint avA, float alB)
 
</syntaxhighlight>
 
Avoids divide by zero by checking for zeros first. If either value is zero, it just returns zero.
 
<br>Accepts a pair of numbers of the same type, or a vector and an appropriate number type.
 
#''float afA, double adA, int alA, uint aulA, cVector avA, or cPoint avA'' - The value to be divided.
 
#''float afB, double adB, int alB, or uint aulB'' - The value to be divided by.
 
<syntaxhighlight lang="cpp">
 
// Example:
 
int risky = 10 / Math.RandomInt(0, 3); // 1 in 3 chance of "divide by zero" error.
 
int safe = Math.SafeDivide(10, Math.RandomInt(0, 3)); // zero chance of "divide by zero" error.
 
</syntaxhighlight><br>
 
  
 
===Math.Length()===
 
===Math.Length()===
Line 350: Line 382:
 
vVelocity *= 3.0f;
 
vVelocity *= 3.0f;
 
// This example has the same result as the previous one, for Math.Normal().
 
// This example has the same result as the previous one, for Math.Normal().
 +
</syntaxhighlight><br>
 +
 +
===Math.DotProduct()===
 +
float DotProduct(cVector avA, cVector avB)
 +
</syntaxhighlight>
 +
Returns the dot product (a.k.a. inner product) of two vectors. The * operator between two vectors also returns the dot product.
 +
#''cVector avA'' - The first vector to use in the dot product calculation.
 +
#''cVector avB'' - The second vector to use in the dot product calculation.
 +
<syntaxhighlight lang="cpp">
 +
// Example:
 +
float fDotMath = Math.DotProduct(vMyVecA, vMyVecB);
 +
float fDotStar = vMyVecA * vMyVecB;
 +
// fDotMath is equal to fDotStar
 +
</syntaxhighlight><br>
 +
 +
===Math.CrossProduct3d()===
 +
<syntaxhighlight lang="cpp">
 +
cVector CrossProduct3d(cVector avA, cVector avB)
 +
</syntaxhighlight>
 +
Returns the cross product of two 3d vectors.
 +
#''cVector avA'' - The first vector to use in the cross product calculation.
 +
#''cVector avB'' - The second vector to use in the cross product calculation.
 +
<syntaxhighlight lang="cpp">
 +
// Example:
 +
cVector vMyVecC = Math.CrossProduct3d(vMyVecA, vMyVecB);
 +
</syntaxhighlight><br>
 +
 +
===Math.ParallelVectors()===
 +
<syntaxhighlight lang="cpp">
 +
float ParallelVectors(cVector avA, cVector avB, bool abAbsolute = true)
 +
</syntaxhighlight>
 +
Given two vectors or two 3d vectors, ParallelVectors will return a float indicating how parallel they are. If the returned float is 0 (or nearly 0), then the vectors are perpendicular (or nearly perpendicular). If the returned float is 1 (or nearly 1), then the vectors are parallel (or nearly parallel).
 +
<br> abAbsolute is optional. If omitted, it defaults to true. If true, the return value will always be positive and indicates whether the vectors are parallel. If abAbsolute is false, the return value may be negative. A value of -1 would indicate that the vectors are
 +
parallel, but pointing in the opposite direction.
 +
#''cVector avA'' - First vector to compare.
 +
#''cVector avB'' - Second vector to compare.
 +
#''bool abAbsolute'' - If false, a negative return value indicates parallel-but-opposite. '''(Optional, default = true)'''
 +
<syntaxhighlight lang="cpp">
 +
// Example 1:
 +
float fRighthand = Math.ParallelVectors(cVector(0.0f, 0.0f, 1.0f), cVector(-1.0f, 0.0f, 0.0f));
 +
float fBackDiagonal = Math.ParallelVectors(cVector(0.0f, 0.0f, 1.0f), cVector(0.5f, 0.0f, -1.0f), false);
 +
// The value of fRighthand will be 0. The value of fBackDiagonal will be -0.894427.
 +
 +
// Example 2:
 +
bfollowingPath =  ParallelVectors(vPlayerPosCurr - vPlayerPosPrev, vPathDir, false) > 0.75f;
 +
// Assuming vPlayerPosCurr is the current position of the player, and vPlayerPosPrev is the previous position of the player, and vPathDir is some direction we want the player to move along, then the bool bFollowingPath becomes true if the player is moving roughly in the direction of the path.
 +
</syntaxhighlight><br>
 +
 +
===Math.IsParallel()===
 +
<syntaxhighlight lang="cpp">
 +
bool IsParallel(cVector avA, cVector avB)
 +
</syntaxhighlight>
 +
Given two vectors, IsParallel() returns true if they are parallel, allowing for a small margin of error.
 +
#''cVector avA'' - First vector to compare.
 +
#''cVector avB'' - Second vector to compare.
 +
<syntaxhighlight lang="cpp">
 +
// Example 1:
 +
bool bPar = Math.IsParallel(cVector(1.0f, 0.0f, 0.0f), cVector(0.0f, 0.0f, 0.1f));
 +
// The value of bPar will be false.
 +
 +
// Example 2:
 +
if (Math.IsParallel(Math.GetEntityPosVec("puzzlePieceA") - Math.GetEntityPosVec("puzzlePieceB"), Math.GetEntityPosVec("puzzlePieceB") - Math.GetEntityPosVec("puzzlePieceC"))) PuzzleSolved();
 +
// The condition succeeds when the three puzzle pieces have been placed in a line.
 +
</syntaxhighlight><br>
 +
 +
===Math.IsPerpendicular()===
 +
<syntaxhighlight lang="cpp">
 +
bool IsPerpendicular(cVector avA, cVector avB)
 +
</syntaxhighlight>
 +
Given two vectors, IsPerpendicular() returns true if they are are perpendicular, allowing for a small margin of error.
 +
#''cVector avA'' - First vector to compare.
 +
#''cVector avB'' - Second vector to compare.
 +
<syntaxhighlight lang="cpp">
 +
// Example 1:
 +
bool bPar = Math.IsPerpendicular(cVector(1.0f, 0.0f, 0.0f), cVector(0.0f, 0.0f, 0.1f));
 +
// The value of bPar will be true.
 +
 +
// Example 2:
 +
if (Math.IsPerpendicular(Math.GetEntityPosVec("puzzlePieceA") - Math.GetEntityPosVec("puzzlePieceB"), Math.GetEntityPosVec("puzzlePieceB") - Math.GetEntityPosVec("puzzlePieceC"))) PuzzleSolved();
 +
// The condition succeeds when the three puzzle pieces have been placed in a right-angled triangle.
 +
</syntaxhighlight><br>
 +
 +
===Math.RotateVector2d()===
 +
<syntaxhighlight lang="cpp">
 +
cVector RotateVector2d(cVector avA, float afB, enumAngleUnits aUnits = angleDegrees)
 +
</syntaxhighlight>
 +
Given a 2d vector and an angle, this rotates the vector by the specified amount and returns the new rotated 2d vector. A positive angle is a clockwise rotation, negative is anticlockwise.
 +
<br>aUnits can be omitted, or optionally it can be angleDegrees or angleRadians. With angleDegrees (default), the given angle afB is taken as degrees. With angleRadians, the given angle afB is taken as radians.
 +
#''cVector avA'' - The vector to be rotated.
 +
#''float afB'' - The angle to rotate by.
 +
#''enumAngleUnits aUnits'' - angleDegrees or angleRadians. '''(Optional, default = angleDegrees)'''
 +
<syntaxhighlight lang="cpp">
 +
// Example 1:
 +
cVector vVecA = cVector(1.0f, 0.0f);
 +
cVector vVecB = cVector(0.0f, 1.0f);
 +
cVector vVecC = Math.RotateVector2d(vVecA, 90.0f);
 +
// vVecB and vVecC are equal.
 +
 +
// Example 2:
 +
cVector vDirOnPlane = Math.RotateVector2d(cVector(-1.0f, 0.0f), Math.Pi * Math.RandomFloat(-0.125f, 0.125f));
 +
// vDirOnPlane becomes a random 2d vector pointing roughly rightwards.
 +
</syntaxhighlight><br>
 +
 +
===Math.AngleToVector2d()===
 +
<syntaxhighlight lang="cpp">
 +
cVector AngleToVector2d(float afA, enumAngleUnits aUnits = angleDegrees)
 +
</syntaxhighlight>
 +
Converts an angle on a 2d plane to a 2d forward vector, using either degrees or radians.
 +
<br>Note that 0d rotation is pointing upward, and in the returned vector the origin is in the top-left: 0 degrees = 12 o'clock = (0, -1); 90 degrees = 3 o'clock = (1, 0)
 +
<br>aUnits can be omitted, or optionally it can be angleDegrees or angleRadians. With angleDegrees (default), the given angle afB is taken as degrees. With angleRadians, the given angle afB is taken as radians.
 +
#''float afR, float afD'' - The angle to convert to a 2d vector.
 +
#''enumAngleUnits aUnits'' - angleDegrees or angleRadians. '''(Optional, default = angleDegrees)'''
 +
<syntaxhighlight lang="cpp">
 +
// Example:
 +
cVector vVecA = Math.AngleToVector2d(90.0f);
 +
cVector vVecB = Math.AngleToVector2d(180.0f);
 +
cVector vVecC = Math.RotateVector2d(vVecA, 90.0f);
 +
// vVecB and vVecC are equal.
 +
</syntaxhighlight><br>
 +
 +
===Math.Vector2dToAngle()===
 +
<syntaxhighlight lang="cpp">
 +
float Vector2dToAngle(cVector avA, enumAngleUnits aUnits = angleDegrees)
 +
</syntaxhighlight>
 +
Converts a 2d forward vector to an angle on the 2d plane, using either degrees or radians.
 +
<br>Note that 0d rotation is pointing upward, and in the returned vector the origin is in the top-left: 0 degrees = 12 o'clock = (0, -1); 90 degrees = 3 o'clock = (1, 0)
 +
<br>aUnits can be omitted, or optionally it can be angleDegrees or angleRadians. With angleDegrees (default), the given angle afB is taken as degrees. With angleRadians, the given angle afB is taken as radians.
 +
#''cVector avA'' - A 2d vector to convert to an angle.
 +
#''enumAngleUnits aUnits'' - angleDegrees or angleRadians. '''(Optional, default = angleDegrees)'''
 +
<syntaxhighlight lang="cpp">
 +
// Example:
 +
float fRad = Math.Vector2dToAngle(cVector(3.0f, 1.5f));
 +
// fRad is equal to 3/8*Pi.
 +
</syntaxhighlight><br>
 +
 +
===Math.RotateVector3d()===
 +
<syntaxhighlight lang="cpp">
 +
cVector RotateVector3d(cVector avA, cRotator arB)
 +
</syntaxhighlight>
 +
Given a 3d vector and a pitch-yaw-roll rotator, this rotates the vector by the specified amount, and returns the new rotated vector.
 +
<br>Note that HPL2 uses a "right-handed, x=left" coordinate system, so the forward direction is considered to be 0,0,1.
 +
#''cVector avA'' - The vector to be rotated.
 +
#''cRotator arB'' - The rotator containing the pitch, yaw and roll angles.
 +
<syntaxhighlight lang="cpp">
 +
// Example 1:
 +
cVector vForward = cVector(0.0f, 0.0f 1.0f);
 +
cRotator vPitchDown = cRotator(5.0f, 0.0f, 5.0f, angleDegrees);
 +
vForward = Math.RotateVector3d(vForward, vPitchDown);
 +
// vForward has been tilted slightly downwards and leaned slightly rightwards.
 +
 +
// Example 2:
 +
cVector vForward = cVector(0.0f, 0.0f 1.0f);
 +
cRotator vBarrelRoll = cRotator(0.0f, 0.0f, 180.0f, angleDegrees);
 +
vForward = Math.RotateVector3d(vForward, vBarrelRoll);
 +
// vForward hasn't changed. Roll on it's own does nothing to a vector, since a vector has no sense of "orientation", only "forward".
 +
</syntaxhighlight><br>
 +
 +
===Math.RotatorToVector3d()===
 +
<syntaxhighlight lang="cpp">
 +
cVector RotatorToVector3d(cRotator arRot, enumOrthoDir aDirectionOption = dirForward)
 +
</syntaxhighlight>
 +
Converts a rotator with pitch, yaw and roll angles into a 3d directional vector. This is basically the same as RotateVector3d() but perhaps more convenient.
 +
<br>aDirectionOption is optional and specifies an orthogonal world vector to use. It can be dirForward, dirBackward, dirLeft, dirRight, dirUp or dirDown. If omitted it defaults to dirForward.
 +
<br>Note that HPL2 uses a "right-handed, x=left" coordinate system, so the forward direction is considered to be 0,0,1. If an entity was facing 0,0,1 before rotation, then RotatorToVector3d() with dirForward would return it's facing direction after rotation.
 +
#''cRotator arRot'' - Rotator containing pitch, yaw, roll values to convert to a vector.
 +
#''enumOrthoDir aDirectionOption'' - Which orthoginal world vector to rotate. '''(Optional, default = dirForward)'''
 +
<syntaxhighlight lang="cpp">
 +
// Example:
 +
cRotator vPitchUp = cRotator(-0.25f * Math.Pi, 0.0f, 0.0f, angleRadians);
 +
cVector vForwardUp = Math.RotatorToVector3d(vPitchDown);
 +
cVector vRightUp = Math.RotatorToVector3d(vPitchDown, dirRight);
 +
// vForwardUp points forward, tilted up by 45 degrees. vRightUp points rightward, tilted up by 45 degrees.
 +
</syntaxhighlight><br>
 +
 +
===Math.Vector3dToRotator()===
 +
<syntaxhighlight lang="cpp">
 +
cRotator Vector3dToRotator(cVector avForward)
 +
cRotator Vector3dToRotator(cVector avForward, cVector avUp)
 +
</syntaxhighlight>
 +
Converts a 3d directional vector to pitch, yaw and roll, and returns the result as a rotator.
 +
<br>If only one vector is given then it represents the forward direction, and the returned rotator will have a yaw and pitch rotated to that forward direction. The roll will be zero.
 +
<br>An optional second vector can be provided in order to calculate roll. If the second vector is given then the first represents the forward direction and the second represents the upward direction. The returned rotator will include a roll angle calculated using the upward direction.
 +
#''cVector avForward'' - The forward directional vector to be converted to a rotator.
 +
#''cVector avUp'' - Optional upward directional vector used to calculate roll. '''(Optional, default = no roll)'''
 +
<syntaxhighlight lang="cpp">
 +
// Example:
 +
cRotator vMyRot = Math.Vector3dToRotator(cVector(-1.0f, 0.0f, -1.0f));
 +
if (vMyRot.YawDeg > 90.0f) DoStuff();
 +
// The condition succeeds because vMyRot becomes a yaw rotation of 135 degrees clockwise.
 
</syntaxhighlight><br>
 
</syntaxhighlight><br>
  

Revision as of 10:42, 20 November 2023

This page documents "HelperScripts_Math.hps" - part of HPL2 Helper Scripts, a modder-made package of .hps files by mrbehemo, containing script classes and functions that may be useful to HPL2 modders and custom story creators. See the main page for more information.

Note icon.png This page is WIP. Full documentation will be available soon.

Math

The script file "HelperScripts_Math.hps" provides some extended maths functionality for modders. This script defines an object called Math, of the new script class cDebug. To access its properties and methods, just use "Math." followed by the function call or property. E.g.:

Math.Lerp(a, b, 0.75f);
x = Math.Pi;

Math contains additional functions for a variety of purposes including interpolation, vectors, and more.

Set-up

For Math to function, the file "HelperScripts_Math.hps" must be added using the #include directive in the level's .hps file. There are three ways to do this.

// 1. If using the full feature-set package, (in MyLevel.hps):
#include "HelperScripts_FullPackage.hps"

// 2. Or, if using the utilities-only package, (in MyLevel.hps):
#include "HelperScripts_UtilitiesOnly.hps"

// 3. Or, for advanced users adding individual scripts only, (in MyLevel.hps):
#include "HelperScripts_Math.hps"

Properties

Math provides the following properties:

Math.Pi

float Pi

The read-only property Pi returns Pi as a float.

// Examples:
float fRightAngleRadians = Math.Pi / 2.0f;
float fOneEightyDegrees = Math.RadiansToDegrees(Math.Pi);

Math.Tau

float Tau

The read-only proerpty Tau returns Tau as a float. (Tau = 2*Pi)

// Examples:
float fRightAngleRadians = Math.Tau / 4.0f;
float fThreeSixtyDegrees = Math.RadiansToDegrees(Math.Tau);

Arithmetic Methods

Math provides the following miscellaneous methods for working with numbers:

Math.NearlyEqual()

bool NearlyEqual(float afA, float afB, float afT = 0.00001f)
bool NearlyEqual(double adA, double adB, double adT = 0.00001)
bool NearlyEqual(cVector avA, cVector avB, float afT = 0.00001f)

Returns true if A and B are equal within a tolerance of T. If omitted, afT defaults to 0.00001.
Accepts either float, double, or cVector. For vectors, avA and avB must have the same number of dimensions, and each pair of dimensions must be nearly equal,

  1. float afA, double adA, or cVector avA - The first value to compare.
  2. float afB, double adB, or cVector avB - The second value to compare.
  3. float afT, double afT - A tolerance with which to compare the values. (Optional, default = 0.00001)
// Example:
if(Math.NearlyEqual(afScore, fTarget, 0.1f))
// The condition succeeds if the score is near to the target by 0.1.


Math.SafeDivide()

float SafeDivide(float afA, float afB)
double SafeDivide(double adA, double adB)
int SafeDivide(int alA, int alB)
uint SafeDivide(uint aulA, uint aulB)
cVector SafeDivide(cVector avA, float afB)
cPoint SafeDivide(cPoint avA, float alB)

Avoids divide by zero by checking for zeros first. If either value is zero, it just returns zero.
Accepts a pair of numbers of the same type, or a vector and an appropriate number type.

  1. float afA, double adA, int alA, uint aulA, cVector avA, or cPoint avA - The value to be divided.
  2. float afB, double adB, int alB, or uint aulB - The value to be divided by.
// Example:
int risky = 10 / Math.RandomInt(0, 3); // 1 in 3 chance of "divide by zero" error.
int safe = Math.SafeDivide(10, Math.RandomInt(0, 3)); // zero chance of "divide by zero" error.


Math.DegreesToRadians()

float DegreesToRadians(float afD)
double DegreesToRadians(double adD)

Converts degrees to radians and returns the result. (360 degrees is equal to 2*Pi radians.)

  1. float afD, double adD - An angle in degrees, to be converted to radians.
// Example 1:
if (Math.DegreesToRadians(fDeg) == Math.Pi / 2.0f) DoStuff();
// The condition will succeed if fDeg is 90.


Math.RadiansToDegrees()

float RadiansToDegrees(float afD)
double RadiansToDegrees(double adD)

Converts radians to degrees and returns the result. (360 degrees is equal to 2*Pi radians.)

  1. float afD, double adD - An angle in radians, to be converted to degrees.
// Example 1:
if (Math.DegreesToRadians(Math.Tau * fX) == 90) DoStuff();
// The condition will succeed if fX is 0.25f.


Interpolation Methods

Math provides the following methods for interpolating between values:

Math.Lerp()

float Lerp(float afA, float afB, float afAlpha, enumLimitType aLimitOption = limitFree)
double Lerp(double adA, double adB, double adAlpha, enumLimitType aLimitOption = limitFree)
cVector Lerp(cVector avA, cVector avB, float afAlpha, enumLimitType aLimitOption = limitFree)
int Lerp(int alA, int alB, float afAlpha, enumLimitType aLimitOption = limitFree)

Linear interpolation: maps an alpha of 0.0-1.0, between values A and B.

aLimitOption is optional and can be omitted, or it can be limitFree, limitClamped or limitWrapped.
With limitFree (default) the alpha is not clamped.
With limitClamped, the alpha value is limited to 0.0f-1.0f. E.g., -0.5f is the same as 0.0f, 3.0f is the same as 1.0f.
With limitWrapped, the alpha values over 1 wrap around to zero. E.g., 1.5f is the same as 0.5f, -1.25f is the same as 0.75f.

Accepts either float, double, or cVector. Can also work with two int values (and a float alpha), but note that the result will be truncated towards zero.

  1. float afA, double adA, cVector avA, or int alA - The value corresponding to alpha 0.
  2. float afB, double adB, cVector avB, or int alB - The value corresponding to alpha 1.
  3. float afAlpha, double afAlpha - The alpha value of the interpolation.
  4. enumLimitType aLimitOption - limitFree, limitClamped or limitWrapped (Optional, default = limitFree)
// Example 1:
float fA = 5.0f;
float fB = 10.0f;
float fC = Math.Lerp(fA, fB, 2.0f/3.0f);
// fC is 8 1/3, which is 2/3 of the way from 5 to 10.

// Example 2:
FadeGlobalSoundSpeed(Math.Lerp(0.5f, 1.0f, GetPlayerSanity() / 100.0f) 1.0f);
// As the player loses sanity, sounds get slower.

// Example 3:
cVector vPlayerPos = Math.GetPlayerPosVec();
cVector vTargetPos = cVector(10.0f, 3.0f, 5.5f);
cVector vHalfwayToTarget = Math.Lerp(vPlayerPos, vTargetPos, 0.5f);
// vHalfwayToTarget is the midpoint between the player's location and the target location


Math.WeightedAvg()

float WeightAvg(float afA, float afB, float afWeight = 0.5f)
double WeightAvg(double afA, double afB, double adWeight = 0.5)
cVector WeightAvg(cVector afA, cVector afB, float afWeight = 0.5f)

Weighted average: returns a value interpolated between A and B, where weight defines how much "drag" there is. A common usage is to smooth out a number that is changing over time.
The weight value can be thought of a how much A is "worth" compared to B (if B is "worth" 1.0). The lower the weight value, the closer to B the result will be. If weight is omitted it defaults to 0.5. Accepts pairs of float, double, or cVector.

  1. float afA, double adA, or cVector avA - The current value of the interpolation.
  2. float afB, double adB, or cVector avB - The target value of the interpolation.
  3. float afWeight, double adWeight - The weight of the current value on the interpolation. (Optional, default = 0.5)
// Example 1:
float fA = 100.0f;
float fB = 200.0f;
float fC = Math.WeightAvg(fA, fB, 2.0f);
// fC is 133 1/3, which is 1/3 of the way from 100 to 200.

// Example 2:
vFollowPos = Math.Lerp(Math.GetPlayerPosVec(), vFollowPos, 0.25f);
// An item placed at vFollowPos every frame will smoothly follow the player.


Math.SnappingWeightedAvg()

float SnappingWeightedAvg(float afA, float afB, float afWeight, float afSnapSize = 0.001f)
double SnappingWeightedAvg(double afA, double afB, double adWeight, double adSnapSize = 0.001)
cVector SnappingWeightedAvg(cVector afA, cVector afB, float afWeight, float afSnapSize = 0.001f)

Same as weighted average, but the new value will snap to A or B if it is in range. This can help to reduce slowly trailing values that don't noticebly change. If it is omitted, asSnapSize defaults to 0.001.

  1. float afA, double adA, or cVector avA - The current value of the interpolation.
  2. float afB, double adB, or cVector avB - The target value of the interpolation.
  3. float afWeight, double adWeight - The weight of the current value on the interpolation.
  4. float afSnapSize, double adSnapSize - The tolerance for snapping to A or B. (Optional, default = 0.001)


Vector Methods

Math provides the following methods for working with vectors:

Math.Length()

float Length(cVector aVector, enumLengthType aSquaredOption = lengthFinal)
int Length(cPoint aVector, enumLengthType aSquaredOption = lengthFinal)

Returns the length a vector, i.e. it's displacement from 0,0,0.
You can also use a cPoint to get the length as an int, but note that the result will be truncated. E.g. cVector(1.0f, 3.0f) has a length equal to the square root of 10, but cPoint(1, 3) has a length of 3 exactly.
aSquaredOption can be omitted, or optionally can be either lengthFinal, lengthSquared. With lengthFinal (default), the value returned is the actual length. With lengthSquared, the value returned is length^2. This is much cheaper to calculate and good enough for a lot of situations. E.g. if you want to know which vector is longer but the actual length doesn't matter.
Note: you can also use the Length() method of the vector classes. (e.g. myVec.Length() )

  1. cVector aVector, cPoint aPoint - The vector to calculate the length of.
  2. enumLengthType aSquaredOption - lengthFinal or lengthSquared (Optional, default = lengthFinal)
// Example 1:
cVector vMyRectangle = cVector(10.0f, 15.0f);
float fMyHypoteneous = Math.Length(myRectangle);

// Example 2:
bool bIsVecALonger = Math.Length(vVecA, lengthSquared) > Math.Length(vVecB, lengthSquared);


Math.Distance()

float Distance(cVector avA, cVector avB, enumLengthType aSquaredOption = lengthFinal)

Returns the displacement between two vectors, e.g. the distance between two points in space.
aSquaredOption can be omitted, or optionally can be either lengthFinal, lengthSquared. With lengthFinal (default), the value returned is the actual length. With lengthSquared, the value returned is length^2. This is much cheaper to calculate and good enough for a lot of situations. E.g. if you want to know which vector is longer but the actual length doesn't matter.

  1. cVector avA - The start position of the distance.
  2. cVector avB - The end position of the distance.
  3. enumLengthType aSquaredOption - lengthFinal or lengthSquared (Optional, default = lengthFinal)
// Example:
cVector vSomeplace = cVector(10.0f, 0.0f 15.0f);
cVector vSomeplaceElse = cVector(20.0f, 2.0f 25.0f);
float fDistance = Math.Distance(vSomeplace, vSomeplaceElse);


Math.DistToPlayer()

float Distance(string asEntity, enumLengthType aSquaredOption = lengthFinal)

Returns the distance from an entity to the player.
aSquaredOption can be omitted, or optionally can be either lengthFinal, lengthSquared. With lengthFinal (default), the value returned is the actual length. With lengthSquared, the value returned is length^2. This is much cheaper to calculate and good enough for a lot of situations. E.g. if you want to know which vector is longer but the actual length doesn't matter.

  1. string asEntity - The entity whose location to compare to the player.
  2. enumLengthType aSquaredOption - lengthFinal or lengthSquared (Optional, default = lengthFinal)
// Example:
if (Math.DistanceToPlayer("Orb") < 12.0f) SetPlayerSanity(0.0f);
// When the player is less than 12 units away from the orb, they lose all sanity points.


Math.GetPlayerPosVec()

cVector GetPlayerPosVec()

Returns the player's location as a 3d cVector, instead of GetPlayerPosX/Y/Z(), which only return a single float.)

// Example:
cVector vPlayerCurrPos = Math.GetPlayerPosVec();
// Stores the player's current location in a cVector.


Math.SetPlayerPosVec()

void SetPlayerPosVec(cVector avPos)

Moves the player to a location given as a 3d cVector, instead of SetPlayerPos(), which takes separate 3 floats.

  1. cVector avPos - The new location for the player.
// Example:
Math.SetPlayerPosVec(0.0f, 0.0f, 0.0f);
// Teleports the player to the world origin.


Math.GetEntityPosVec()

cVector GetEntityPosVec(string asEntity)

Returns the named entity's location as a 3d cVector, instead of GetEntityPosX/Y/Z(), which only return a single float.

  1. string asEntity - The entity to be moved.
// Example:
cVector vHammerCurrPos = Math.GetEntityPosVec("hammer");
// Stores the hammer's current location in a cVector.


Math.SetEntityPosVec()

void SetEntityPosVec(string asEntity, cVector avPos)

Moves the named entity to a location given as a 3d cVector, instead of SetEntityPos(), which takes separate 3 floats.

  1. string asEntity - The entity to be moved.
  2. cVector avPos - The new location for the entity.
// Example:
Math.SetEntityPosVec("anvil", Math.GetPlayerPosVec() + cVector(0.0f, 3.0f, 0.0f));
// Teleports the entity "anvil" to 3 units above the player.


Math.AddPropForceVec etc

void AddPropForceVec(string asName, cVector avForce, string asCoordSystem = "world")
void AddPropImpulseVec(string asName, cVector avImpulse, string asCoordSystem = "world")
void AddBodyForceVec(string asName, cVector avForce, string asCoordSystem = "world")
void AddBodyImpulseVec(string asName, cVector avImpulse, string asCoordSystem = "world")

These functions are provided as a way to use the global functions AddPropForce() etc., with a vector specifying the force or impulse, rather than floats. Could be useful if you want to use it with e.g. RandomVector3d(). See the documentation for the original functions for more information. The asCoordSystem string argument is optional in these versions.

  1. string asName - The name of the entity or body to push.
  2. cVector avForce, cVector avImpulse - A 3d vector to use for the force or impulse.
  3. string asCoordSystem - Frame of reference for the force. (Optional, default = "world")


Math.RotatePropToSpeedVec

void RotatePropToSpeedVec(string asName, float afAcc, float afGoalSpeed, cVector avAxes, bool abResetSpeed = false, string& asOffsetArea = "")

This function is provided as a way to use the global function RotatePropToSpeed() with a vector as the axis multiplier, instead of floats. Could be useful if you want to use it with e.g. RandomVector3d(). See the documentation for the original function for more information. The asOffsetArea string and abResetSpeed bool arguments are optional in this version.

  1. string asName - Name of the prop to rotate.
  2. float afAcc - Acceleration used to reach desired speed.
  3. float afGoalSpeed - The desired speed.
  4. cVector avAxes - The 3d vector to use as the axis multiplier.
  5. bool abResetSpeed - Whether to reset the speed after the goal is reached. (Optional, default = false)
  6. string asOffsetArea - The area to rotate around. If empty, the center of the body is used. (Optional, default = "")


Math.GetRelative()

cVector GetRelative(cVector avPosition, cVector avOriginA, cVector avOriginB)
cPoint GetRelative(cPoint avPosition, cPoint avOriginA, cPoint avOriginB)

Given a world position vector in relation to origin A, this will return a world position with the same displacement from origin B. See also: TeleportPlayerRelative() and TeleportEntityRelative().

  1. cVector avPosition or cPoint avPosition - A vector defining a start position.
  2. cVector avOriginA or cPoint avOriginA - A position in relation to the start position.
  3. cVector avOriginB or cPoint avOriginB - A position in relation to the output position.
// Example:
cVector vMirrorWorldPlayerPos = Math.GetRelative(Math.GetPlayerPosVec(), vNormalWorldCentre, vMirrorWorldCentre) * cVector(1.0f, 1.0f, -1.0f);
// This convoluted example is something you might be interested in if you were trying to make a fake mirror, perhaps.


Math.TeleportPlayerRelative()

void TeleportPlayerRelative(string asAreaA, string asAreaB)

Moves the player to a location relative to a named area B, whilst maintaining their position relative to area A.

  1. string asAreaA - Name of an area (or other entity) in relation to the player's current position.
  2. string asAreaB - Name of an area (or other entity) in relation to the player's new position.
// Example:
Math.TeleportPlayerRelative("Room1Area", "Room2Area");
// Assuming Room1Area and Room2Area are the same size/shape, if the player is inside Room1Area, they will teleport to the same position inside Room2Area.


Math.TeleportEntityRelative()

void TeleportPlayerRelative(string asEntity, string asAreaA, string asAreaB)

Moves the named entity to a location relative to a named area B, whilst maintaining its position relative to area A.

  1. string asEntity - Name of the entity to teleport.
  2. string asAreaA - Name of an area (or other entity) in relation to the player's current position.
  3. string asAreaB - Name of an area (or other entity) in relation to the player's new position.
// Example:
Math.TeleportEntityRelative("FatSackOfThalers", "Room1Area", "Room2Area");
// Assuming Room1Area and Room2Area are the same size/shape, if FatSackOfThalers is inside Room1Area, it will teleport to the same position inside Room2Area.


Math.Normal()

cVector Normal(cVector avX)
cPoint Normal(cPoint avX)

Returns a normalized copy of a vector, without changing the original. (A normalized vector has the same direction, but with a length forced to 1.) Accepts a cVector or cPoint. Uses SafeDivide() to avoid ...impossible geometry!

  1. cVector avX or cPoint avX - The vector to calculate the normal off.
// Example:
vVelocity = Math.Normal(vDirection) * fSpeed;
// If vDirection is a vector of unknown length pointing in some direction, this would set vVelocity to be a vector pointing in the same direction, but with a length of exactly fSpeed.


Math.Normalize()

void Normal(cVector avX)
void Normal(cPoint avX)

Normalizes the specified vector in place, replacing the original. (A normalized vector has the same direction, but with a length forced to 1.) Accepts a cVector or cPoint. Uses SafeDivide() to avoid ...impossible geometry!

  1. cVector avX or cPoint avX - The vector to be replaced with its normal.
// Example:
vVelocity = vDirection;
Math.Normalize(vVelocity); // Length of vVelocity has now become 1.
vVelocity *= 3.0f;
// This example has the same result as the previous one, for Math.Normal().


Math.DotProduct()

float DotProduct(cVector avA, cVector avB) </syntaxhighlight> Returns the dot product (a.k.a. inner product) of two vectors. The * operator between two vectors also returns the dot product.

  1. cVector avA - The first vector to use in the dot product calculation.
  2. cVector avB - The second vector to use in the dot product calculation.
// Example:
float fDotMath = Math.DotProduct(vMyVecA, vMyVecB);
float fDotStar = vMyVecA * vMyVecB;
// fDotMath is equal to fDotStar


Math.CrossProduct3d()

cVector CrossProduct3d(cVector avA, cVector avB)

Returns the cross product of two 3d vectors.

  1. cVector avA - The first vector to use in the cross product calculation.
  2. cVector avB - The second vector to use in the cross product calculation.
// Example:
cVector vMyVecC = Math.CrossProduct3d(vMyVecA, vMyVecB);


Math.ParallelVectors()

float ParallelVectors(cVector avA, cVector avB, bool abAbsolute = true)

Given two vectors or two 3d vectors, ParallelVectors will return a float indicating how parallel they are. If the returned float is 0 (or nearly 0), then the vectors are perpendicular (or nearly perpendicular). If the returned float is 1 (or nearly 1), then the vectors are parallel (or nearly parallel).
abAbsolute is optional. If omitted, it defaults to true. If true, the return value will always be positive and indicates whether the vectors are parallel. If abAbsolute is false, the return value may be negative. A value of -1 would indicate that the vectors are parallel, but pointing in the opposite direction.

  1. cVector avA - First vector to compare.
  2. cVector avB - Second vector to compare.
  3. bool abAbsolute - If false, a negative return value indicates parallel-but-opposite. (Optional, default = true)
// Example 1:
float fRighthand = Math.ParallelVectors(cVector(0.0f, 0.0f, 1.0f), cVector(-1.0f, 0.0f, 0.0f));
float fBackDiagonal = Math.ParallelVectors(cVector(0.0f, 0.0f, 1.0f), cVector(0.5f, 0.0f, -1.0f), false);
// The value of fRighthand will be 0. The value of fBackDiagonal will be -0.894427.

// Example 2:
bfollowingPath =  ParallelVectors(vPlayerPosCurr - vPlayerPosPrev, vPathDir, false) > 0.75f;
// Assuming vPlayerPosCurr is the current position of the player, and vPlayerPosPrev is the previous position of the player, and vPathDir is some direction we want the player to move along, then the bool bFollowingPath becomes true if the player is moving roughly in the direction of the path.


Math.IsParallel()

bool IsParallel(cVector avA, cVector avB)

Given two vectors, IsParallel() returns true if they are parallel, allowing for a small margin of error.

  1. cVector avA - First vector to compare.
  2. cVector avB - Second vector to compare.
// Example 1:
bool bPar = Math.IsParallel(cVector(1.0f, 0.0f, 0.0f), cVector(0.0f, 0.0f, 0.1f));
// The value of bPar will be false.

// Example 2:
if (Math.IsParallel(Math.GetEntityPosVec("puzzlePieceA") - Math.GetEntityPosVec("puzzlePieceB"), Math.GetEntityPosVec("puzzlePieceB") - Math.GetEntityPosVec("puzzlePieceC"))) PuzzleSolved();
// The condition succeeds when the three puzzle pieces have been placed in a line.


Math.IsPerpendicular()

bool IsPerpendicular(cVector avA, cVector avB)

Given two vectors, IsPerpendicular() returns true if they are are perpendicular, allowing for a small margin of error.

  1. cVector avA - First vector to compare.
  2. cVector avB - Second vector to compare.
// Example 1:
bool bPar = Math.IsPerpendicular(cVector(1.0f, 0.0f, 0.0f), cVector(0.0f, 0.0f, 0.1f));
// The value of bPar will be true.

// Example 2:
if (Math.IsPerpendicular(Math.GetEntityPosVec("puzzlePieceA") - Math.GetEntityPosVec("puzzlePieceB"), Math.GetEntityPosVec("puzzlePieceB") - Math.GetEntityPosVec("puzzlePieceC"))) PuzzleSolved();
// The condition succeeds when the three puzzle pieces have been placed in a right-angled triangle.


Math.RotateVector2d()

cVector RotateVector2d(cVector avA, float afB, enumAngleUnits aUnits = angleDegrees)

Given a 2d vector and an angle, this rotates the vector by the specified amount and returns the new rotated 2d vector. A positive angle is a clockwise rotation, negative is anticlockwise.
aUnits can be omitted, or optionally it can be angleDegrees or angleRadians. With angleDegrees (default), the given angle afB is taken as degrees. With angleRadians, the given angle afB is taken as radians.

  1. cVector avA - The vector to be rotated.
  2. float afB - The angle to rotate by.
  3. enumAngleUnits aUnits - angleDegrees or angleRadians. (Optional, default = angleDegrees)
// Example 1:
cVector vVecA = cVector(1.0f, 0.0f);
cVector vVecB = cVector(0.0f, 1.0f);
cVector vVecC = Math.RotateVector2d(vVecA, 90.0f);
// vVecB and vVecC are equal.

// Example 2:
cVector vDirOnPlane = Math.RotateVector2d(cVector(-1.0f, 0.0f), Math.Pi * Math.RandomFloat(-0.125f, 0.125f));
// vDirOnPlane becomes a random 2d vector pointing roughly rightwards.


Math.AngleToVector2d()

cVector AngleToVector2d(float afA, enumAngleUnits aUnits = angleDegrees)

Converts an angle on a 2d plane to a 2d forward vector, using either degrees or radians.
Note that 0d rotation is pointing upward, and in the returned vector the origin is in the top-left: 0 degrees = 12 o'clock = (0, -1); 90 degrees = 3 o'clock = (1, 0)
aUnits can be omitted, or optionally it can be angleDegrees or angleRadians. With angleDegrees (default), the given angle afB is taken as degrees. With angleRadians, the given angle afB is taken as radians.

  1. float afR, float afD - The angle to convert to a 2d vector.
  2. enumAngleUnits aUnits - angleDegrees or angleRadians. (Optional, default = angleDegrees)
// Example:
cVector vVecA = Math.AngleToVector2d(90.0f);
cVector vVecB = Math.AngleToVector2d(180.0f);
cVector vVecC = Math.RotateVector2d(vVecA, 90.0f);
// vVecB and vVecC are equal.


Math.Vector2dToAngle()

float Vector2dToAngle(cVector avA, enumAngleUnits aUnits = angleDegrees)

Converts a 2d forward vector to an angle on the 2d plane, using either degrees or radians.
Note that 0d rotation is pointing upward, and in the returned vector the origin is in the top-left: 0 degrees = 12 o'clock = (0, -1); 90 degrees = 3 o'clock = (1, 0)
aUnits can be omitted, or optionally it can be angleDegrees or angleRadians. With angleDegrees (default), the given angle afB is taken as degrees. With angleRadians, the given angle afB is taken as radians.

  1. cVector avA - A 2d vector to convert to an angle.
  2. enumAngleUnits aUnits - angleDegrees or angleRadians. (Optional, default = angleDegrees)
// Example:
float fRad = Math.Vector2dToAngle(cVector(3.0f, 1.5f));
// fRad is equal to 3/8*Pi.


Math.RotateVector3d()

cVector RotateVector3d(cVector avA, cRotator arB)

Given a 3d vector and a pitch-yaw-roll rotator, this rotates the vector by the specified amount, and returns the new rotated vector.
Note that HPL2 uses a "right-handed, x=left" coordinate system, so the forward direction is considered to be 0,0,1.

  1. cVector avA - The vector to be rotated.
  2. cRotator arB - The rotator containing the pitch, yaw and roll angles.
// Example 1:
cVector vForward = cVector(0.0f, 0.0f 1.0f);
cRotator vPitchDown = cRotator(5.0f, 0.0f, 5.0f, angleDegrees);
vForward = Math.RotateVector3d(vForward, vPitchDown);
// vForward has been tilted slightly downwards and leaned slightly rightwards.

// Example 2:
cVector vForward = cVector(0.0f, 0.0f 1.0f);
cRotator vBarrelRoll = cRotator(0.0f, 0.0f, 180.0f, angleDegrees);
vForward = Math.RotateVector3d(vForward, vBarrelRoll);
// vForward hasn't changed. Roll on it's own does nothing to a vector, since a vector has no sense of "orientation", only "forward".


Math.RotatorToVector3d()

cVector RotatorToVector3d(cRotator arRot, enumOrthoDir aDirectionOption = dirForward)

Converts a rotator with pitch, yaw and roll angles into a 3d directional vector. This is basically the same as RotateVector3d() but perhaps more convenient.
aDirectionOption is optional and specifies an orthogonal world vector to use. It can be dirForward, dirBackward, dirLeft, dirRight, dirUp or dirDown. If omitted it defaults to dirForward.
Note that HPL2 uses a "right-handed, x=left" coordinate system, so the forward direction is considered to be 0,0,1. If an entity was facing 0,0,1 before rotation, then RotatorToVector3d() with dirForward would return it's facing direction after rotation.

  1. cRotator arRot - Rotator containing pitch, yaw, roll values to convert to a vector.
  2. enumOrthoDir aDirectionOption - Which orthoginal world vector to rotate. (Optional, default = dirForward)
// Example:
cRotator vPitchUp = cRotator(-0.25f * Math.Pi, 0.0f, 0.0f, angleRadians);
cVector vForwardUp = Math.RotatorToVector3d(vPitchDown);
cVector vRightUp = Math.RotatorToVector3d(vPitchDown, dirRight);
// vForwardUp points forward, tilted up by 45 degrees. vRightUp points rightward, tilted up by 45 degrees.


Math.Vector3dToRotator()

cRotator Vector3dToRotator(cVector avForward)
cRotator Vector3dToRotator(cVector avForward, cVector avUp)

Converts a 3d directional vector to pitch, yaw and roll, and returns the result as a rotator.
If only one vector is given then it represents the forward direction, and the returned rotator will have a yaw and pitch rotated to that forward direction. The roll will be zero.
An optional second vector can be provided in order to calculate roll. If the second vector is given then the first represents the forward direction and the second represents the upward direction. The returned rotator will include a roll angle calculated using the upward direction.

  1. cVector avForward - The forward directional vector to be converted to a rotator.
  2. cVector avUp - Optional upward directional vector used to calculate roll. (Optional, default = no roll)
// Example:
cRotator vMyRot = Math.Vector3dToRotator(cVector(-1.0f, 0.0f, -1.0f));
if (vMyRot.YawDeg > 90.0f) DoStuff();
// The condition succeeds because vMyRot becomes a yaw rotation of 135 degrees clockwise.