HPL2/HPL2 Helper Scripts/Math

From Frictional Wiki
< HPL2‎ | HPL2 Helper Scripts
Revision as of 19:57, 19 November 2023 by Mrbehemo (talk | contribs) (First version of page, WIP)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

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);

Methods

Math provides the following methods:

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.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)


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.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().