UNPKG

isaacscript-common

Version:

Helper functions and features for IsaacScript mods.

150 lines (149 loc) 6.17 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.copyVector = copyVector; exports.deserializeVector = deserializeVector; exports.doesVectorHaveLength = doesVectorHaveLength; exports.getClosestVectorTo = getClosestVectorTo; exports.getRandomVector = getRandomVector; exports.isSerializedVector = isSerializedVector; exports.isVector = isVector; exports.serializeVector = serializeVector; exports.vectorEquals = vectorEquals; exports.vectorToDirection = vectorToDirection; exports.vectorToString = vectorToString; const SerializationBrand_1 = require("../enums/private/SerializationBrand"); const direction_1 = require("./direction"); const isaacAPIClass_1 = require("./isaacAPIClass"); const random_1 = require("./random"); const rng_1 = require("./rng"); const table_1 = require("./table"); const types_1 = require("./types"); const utils_1 = require("./utils"); const OBJECT_NAME = "Vector"; const KEYS = ["X", "Y"]; /** Helper function to copy a `Vector` Isaac API class. */ function copyVector(vector) { if (!isVector(vector)) { error(`Failed to copy a ${OBJECT_NAME} object since the provided object was not a userdata ${OBJECT_NAME} class.`); } return Vector(vector.X, vector.Y); } /** * Helper function to convert a `SerializedVector` object to a normal `RNG` object. (This is used by * the save data manager when reading data from the "save#.dat" file.) */ function deserializeVector(vector) { if (!(0, types_1.isTable)(vector)) { error(`Failed to deserialize a ${OBJECT_NAME} object since the provided object was not a Lua table.`); } const [x, y] = (0, table_1.getNumbersFromTable)(vector, OBJECT_NAME, ...KEYS); (0, utils_1.assertDefined)(x, `Failed to deserialize a ${OBJECT_NAME} object since the provided object did not have a value for: X`); (0, utils_1.assertDefined)(y, `Failed to deserialize a ${OBJECT_NAME} object since the provided object did not have a value for: Y`); return Vector(x, y); } /** * Helper function to measure a vector to see if it has a non-zero length using a threshold to * ignore extremely small values. * * Use this function instead of explicitly checking if the length is 0 because vectors in the game * are unlikely to ever be exactly set to 0. Instead, they will always have some miniscule length. * * @param vector The vector to measure. * @param threshold Optional. The threshold from 0 to consider to be a non-zero vector. Default is * 0.01. */ function doesVectorHaveLength(vector, threshold = 0.01) { return vector.Length() >= threshold; } /** * Given an array of vectors, this helper function returns the closest one to a provided reference * vector. * * @param referenceVector The vector to compare against. * @param vectors The array of vectors to look through. */ function getClosestVectorTo(referenceVector, vectors) { let closestVector; let closestDistance = Number.POSITIVE_INFINITY; for (const vector of vectors) { const distance = referenceVector.Distance(vector); if (distance < closestDistance) { closestVector = vector; closestDistance = distance; } } return closestVector; } /** * Helper function to get a random vector between (-1, -1) and (1, 1). * * To get random vectors with a bigger length, multiply this with a number. * * Use this over the `RandomVector` function when you need the vector to be seeded. * * If you want to generate an unseeded vector, you must explicitly pass `undefined` to the * `seedOrRNG` parameter. * * @param seedOrRNG The `Seed` or `RNG` object to use. If an `RNG` object is provided, the * `RNG.Next` method will be called. If `undefined` is provided, it will default to * a random seed. */ function getRandomVector(seedOrRNG) { const rng = (0, rng_1.isRNG)(seedOrRNG) ? seedOrRNG : (0, rng_1.newRNG)(seedOrRNG); const x = (0, random_1.getRandomFloat)(-1, 1, rng); const y = (0, random_1.getRandomFloat)(-1, 1, rng); return Vector(x, y); } /** * Used to determine is the given table is a serialized `Vector` object created by the `deepCopy` * function. */ function isSerializedVector(object) { if (!(0, types_1.isTable)(object)) { return false; } return (0, table_1.tableHasKeys)(object, ...KEYS) && object.has(SerializationBrand_1.SerializationBrand.VECTOR); } /** Helper function to check if something is an instantiated `Vector` object. */ function isVector(object) { return (0, isaacAPIClass_1.isIsaacAPIClassOfType)(object, OBJECT_NAME); } /** * Helper function to convert a `Vector` object to a `SerializedVector` object. (This is used by the * save data manager when writing data from the "save#.dat" file.) */ function serializeVector(vector) { if (!isVector(vector)) { error(`Failed to serialize a ${OBJECT_NAME} object since the provided object was not a userdata ${OBJECT_NAME} class.`); } const vectorTable = new LuaMap(); (0, table_1.copyUserdataValuesToTable)(vector, KEYS, vectorTable); vectorTable.set(SerializationBrand_1.SerializationBrand.VECTOR, ""); return vectorTable; } /** * Helper function to compare two vectors for equality. * * This function is useful because vectors are not directly comparable. In other words, `Vector(1.2) * === Vector(1.2)` will be equal to false. */ function vectorEquals(vector1, vector2) { return (0, isaacAPIClass_1.isaacAPIClassEquals)(vector1, vector2, KEYS); } /** Helper function for finding out which way a vector is pointing. */ function vectorToDirection(vector) { const angleDegrees = vector.GetAngleDegrees(); return (0, direction_1.angleToDirection)(angleDegrees); } /** * Helper function to convert a vector to a string. * * @param vector The vector to convert. * @param round Optional. If true, will round the vector values to the nearest integer. Default is * false. */ function vectorToString(vector, round = false) { const x = round ? Math.round(vector.X) : vector.X; const y = round ? Math.round(vector.Y) : vector.Y; return `(${x}, ${y})`; }