-
Notifications
You must be signed in to change notification settings - Fork 55
Utilities and Debugging
Relevant files: utils.lua, lib folder, vars.lua
Kristal implements the Timer, Class, and Vector-light libraries from hump libraries for use within mods. Kristal does make some slight alterations, however; this section will detail these changes.
As the Objects page said previously, Kristal makes heavy usage of the Class
library. Kristal also adds functionality to this library; in addition to the special methods of extending other files already detailed in the Objects page, there are functions all Classes can use:
includes(other)
: Returns whether a class extends other
. For example, Sprite:includes(Object)
will return true. Classes that extend an extension will also be considered to extend their original class; if something were to extend Sprite, it will still return true for includes(Object)
.
Timer is implemented as an Object instead of a simple class; this means that you create new instances of timers through Timer()
instead of Timer.new()
, and you need to parent the Timer to an Object for it to update. This also means you can't use the global Timer
variable as a timer instance itself, like the hump documentation says; instead, you'll likely want to use existing timers already parented to objects. Game.battle.timer
Game.world.timer
, and Game.stage.timer
are examples of easily accessible Timer objects.
In addition to this change, Kristal's implementation of Timer adds and changes functions. These edits are:
-
Timer:everyInstant(delay, func, count)
is a function added that behaves similarly toTimer:every()
, except it also callsfunc()
immediately upon being called, instead of waiting fordelay
to pass. This first call does not subtract fromcount
if it is provided; for example,Timer:everyInstant(0.5, function() print("called") end, 2)
will printcalled
immediately, then again after 0.5 and 1 seconds, for a total of 3 times. - The implementation of the
wait()
function forTimer:script(func)
is altered slightly; in addition to calling it with a number to wait a specified amount of seconds, you can call it with no arguments, which will cause the game to wait for a single frame, regardless of framerate.
This library's functions can be utilized through the global Vector
table. Kristal does not change the library.
Kristal implements an Easing table containing functions to ease between 2 values. Each function can be referred to in 2 ways: with lower camel case, e.g. Ease.inOutQuad()
, or snake case with dashes, e.g. Ease["in-out-quad"]()
. The values each function takes, in order, are:
- 1: The elapsed time since starting the easing.
- 2: The starting value of the easing.
- 3: How much the value should change.
- 4: The total duration of the easing.
For example, to find the eased value after 2 seconds of a 5 second long transformation from the value 10 to the value 16, you would call Ease.easeType(2, 10, 6, 5)
. 2
refers to how long the transformation has been occurring, 10
refers to the starting value of the transformation, 6
refers to how much the value 10
needs to change by to reach its final value, and 5
is how long the transformation will last in total.
A visual representation of all ease types is available here. For an alternative method of using easing, more consistent with other code in Kristal, see Utils.ease()
below.
Kristal contains a Utils library with many functions that can be used to assist coding. The rest of this page details functions defined by Kristal. All of the following functions in this section are contained within the global Utils
table, and can be called universally.
copy(table, deep)
: Returns a copy of a table. If deep
is true, all tables within the table will be copies of themselves as well.
dump(table)
: Returns a string detailing the contents of a table. Useful for debugging.
split(str, sep, remove_empty)
: Splits str
with sep
as a separator, and returns a table of the new strings. If remove_empty
is true, empty strings (""
) won't be added to the table.
join(tbl, sep, start, len)
: Joins a table of strings together into 1 string. tbl
is the table of strings to combine, sep
is an optional string that will be put between each string if defined, start
is an optional number defining the index to start with, and len
is an optional number defining how many values to combine before stopping.
titleCase(str)
: Returns string str
converted to Title Case.
hook(target, name, func)
: Hooks a function, allowing you to add code to existing functions. target
is the table that holds the function, name
is the name of the function you're hooking, and func
is the new function that you're replacing the old with, passing in the original function as the first argument. For example, if you want to hook Object.getRelativePos, you would do something like:
Utils.hook(Object, "getRelativePos", function(orig, object, x, y, other)
-- the original arguments of the function are x, y, and other
-- but since the function comes from a class, that means we need to pass in
-- the object instance into the original function as well
-- code here gets executed before the original
-- since getRelativePos returns something, your code should also return something
-- usually you'd want to return the results that the original function returns
-- so you can keep the values the original returns as variables, then return them later
-- getRelativePos returns 2 values, so we'll want to store both of them
local orig_x, orig_y = orig(object, x, y, other)
-- code here gets executed after the original
-- return the result gotten earlier
return orig_x, orig_y
end)
equal(a, b, deep)
: If a
and b
are tables, the function returns whether their contents are the same (and if deep
is true, it checks this for all tables within the table as well). Otherwise, it simply returns whether a
and b
are equal.
hslToRgb(h, s, l)
: Returns 3 values between 0 and 1, converting HSL values between 0 and 1 to RGB.
rgbToHsl(r, g, b)
: Returns 3 values between 0 and 1, converting RGB values between 0 and 1 to HSL.
hexToRgb(hex, value)
: Returns a table of values between 0 and 1, converting a hex code ("#" required) to RGB. If value
is provided, that will be passed in as the 4th value in the table; otherwise, the 4th value of the table will be 1.
rgbToHex(rgb)
: Returns a hex value string ("#" included), converting a table of RGB values to a hex code.
merge(tbl, other, deep)
: Merges 2 tables, returning a new one containing the values from both. If deep
is true and it finds that both tables have a table value at the same index, it will merge those tables as well.
removeFromTable(tbl, value)
: Removes val
from a numerically indexed table.
containsValue(tbl, value)
: Returns whether a numerically indexed table contains val
.
round(value, to)
: Returns the value rounded to the nearest integer, or, if to
is provided, to the nearest multiple of to
.
clamp(value, min, max)
: Returns value
if it is between min
and max
; otherwise, returns min
if value
is less than it, or max
if value
is greater than it.
absClamp(value, min, max)
: Returns value
if its absolute value is between min
and max
; otherwise, return min
with the sign of value
if the absolute value of value
is less than it, or max
with the sign of value
if the absolute value of value
is greater than it. min
and max
must be positive numbers.
sign(value)
: Returns -1, 0, or 1, based on the polarity of the value.
approach(value, target, amount)
: If value
is less than target
, returns value + amount
, otherwise it returns value - amount
. amount
should always be a positive number. If value ± amount
goes past target
, it returns target
instead. In simple terms, it moves value
towards target
by amount
, not allowing it to exceed it.
lerp(a, b, t, oob)
: Returns a value between a
and b
, by 100*t
%. For example, if t
is 0.5, the function will return the value halfway between a
and b
. If a
and b
are both tables with the same number of values, return a new table with each value being lerped between a
and b
. If oob
is not true, then t
will be clamped between 0 and 1.
lerpPoint(x1, y1, x2, y2, t, oob)
: Returns coordinates by lerping between the provided points.
ease(a, b, t, mode)
: Returns a value between a
and b
, eased by 100*t
%. The easing methods available are specified above.
clampMap(value, min_a, max_a, min_b, max_b, mode)
: Gets the ratio value
is at between min_a
and max_a
, and returns a new value with the same ratio between min_b
and max_b
. For example, Utils.clampMap(5, 0,10, 20,40)
would give 30, since 5 is 50% between 0 and 10, so it returns the value 50% between 20 and 40. mode
is an optional argument referring to an easing method; if not specified, the function assumes linear.
between(val, a, b)
: Returns whether val
is between the numbers a
and b
.
mergeColor(start_color, end_color, amount)
: Lerps between start_color
and end_color
by amount
, where start_color
and end_color
are tables with 3 or 4 values defining RGB(A), and amount
is a number between 0 and 1.
random()
: Returns a random decimal between 0 and 1.
random(val)
: Returns a random decimal between 0 and val
.
random(a, b)
: Returns a random decimal between a
and b
.
random(a, b, round)
: Returns a random decimal between a
and b
, rounded to the nearest multiple of round
.
randomSign()
: Returns either -1 or 1 randomly.
randomAxis()
: Returns a table of 2 values, representing a random polarity. The table can be either {1,0}
, {0,1}
, {-1,0}
, or {0,-1}
.
filter(tbl, filter)
: Takes a table and a function(value)
that should return a bool. Returns a new table, containing the values from tbl
that filter(value)
returns true for.
pick(tbl, filter)
: Returns a random value from tbl
. If filter
is provided, returns a random value from tbl
filtered through filter
.
pickMultiple(tbl, amount, filter)
: Returns multiple random values from tbl
, not returning the same value more than once. If filter
is provided, it filters the table before choosing.
shuffle(tbl)
: Returns a new table with the values of tbl
in a random order.
reverse(tbl)
: Returns a new table with the values of tbl
in reversed order.
angle(x1, y1, x2, y2)
: Return the angle, in radians, between the points specified.
angle(obj1, obj2)
: Returns the angle, in radians, between two objects.
angleDiff(a, b)
: Returns the difference between 2 angles, accounting for wrap-around. Will be a value between -pi
and pi
.
approachAngle(value, target, amount)
: Similar to approach()
, but always approaches accounting for wrapping around, opting to go for the shortest distance.
dist(x1, y1, x2, y2)
: Returns the distance between 2 points.
startsWith(value, prefix)
: If value
and prefix
are strings, it returns whether value
starts with the string prefix
, followed by the substring of value
with that prefix removed. If value
and prefix
are numerically indexed tables, it returns whether the first values of value
are equal to the values in prefix
, followed by a copy of value
with the values in prefix
removed.
tableLength(tbl)
: Returns how many indexes are defined for a table, including non-numerical indexes.
facingFromAngle(angle)
: Returns right
, down
, left
or up
depending on the direction angle faces. angle
is an angle measure, in radians.
isFacingAngle(facing, angle)
: Returns whether the specified facing direction matches the direction of the specified angle. facing
is a string being either right
, down
, left
or up
, and angle
is an angle measure, in radians.
Outside of the Utils library, Kristal also has several global variables that can be used to help with code. These variables always exist, and can be read from anywhere. These variables are:
SCREEN_WIDTH
, SCREEN_HEIGHT
: Refers to the current window size.
SCREEN_CANVAS
: A reference to the canvas used to render the entire screen.
DT
: The time that has elapsed since the last game update. Usually approximately equal to the framerate.
DTMULT
: DT
multiplied by 30 (the default FPS of Deltarune). At 30fps, this value will be approximately equal to 1. When changing values over the course of time, the change should be multiplied by DTMULT
so that it's consistent across different framerates.
COLORS
: A table of default colors available. Each index contains a table of 4 values, referring to R, G, B, and alpha of a color. The available colors are aqua
, black
, blue
, dkgray
, fuchsia
, gray
, green
, lime
, ltgray
, maroon
, navy
, olive
, orange
, purple
, red
, silver
, teal
, white
, and yellow
.
BATTLE_LAYERS
: A table of constants that refer to the layer values of objects in battles. The indexes, from bottom to top, are:
-
bottom
: -1000 -
below_battlers
: -200 -
battlers
: -100 -
above_battlers
,below_ui
: 0 -
ui
: 100 -
above_ui
,below_arena
: 200 -
arena
: 300 -
above_arena
,below_soul
: 400 -
soul
: 500 -
above_soul
,below_bullets
: 600 -
bullets
: 700 -
above_bullets
: 800 -
top
: 1000
WORLD_LAYERS
: A table of constants that refer to the layer values of objects in the overworld. The indexes, from bottom to top, are:
-
bottom
: -100 -
below_soul
: 100 -
soul
: 200 -
above_soul
,below_bullets
: 300 -
bullets
: 400 -
above_bullets
,below_ui
: 500 -
ui
: 600 -
above_ui
,below_textbox
: 700 -
textbox
: 800 -
above_textbox
: 900 -
top
: 1000
SHOP_LAYERS
: A table of constants that refer to the layer values of objects in shops. The indexes, from bottom to top, are:
-
background
: -100 -
below_shopkeeper
: 100 -
shopkeeper
: 200 -
above_shopkeeper
, `below_boxes: 300 -
cover
: 400 -
large_box
: 450 -
left_box
: 500 -
info_box
: 550 -
right_box
: 600 -
above_boxes
,below_dialogue
: 700 -
dialogue
: 800 -
above_dialogue
: 900 -
top
: 1000
PALETTE
: A table of colors used throughout the game. The colors defined are as follows:
-
action_strip
: Used by the Action Bar during battles.
DEBUG_RENDER
: A boolean toggled by a debug keybind that enables showing hitboxes of bullets, the player, and the arena. Can be used in code to render things for debug purposes.
Enabling Debug Hotkeys in the main menu enables several debug keybinds to use for debugging and coding purposes. These include:
Ctrl+M
: Pauses or resumes music.
Ctrl+R
: Makes a quicksave and reloads the mod, allowing you to reload any changes to code or assets.
Ctrl+Shift+R
: Reloads the mod without making a quicksave.
F1
: Toggles an FPS display.
F2
: Toggles VSync.
F3
: Prints performance information to the console.
F5
: Toggles speed-up for the game.
F6
: Toggles DEBUG_RENDER
, a global variable that can be checked in code. By default, DEBUG_RENDER
is checked to render text describing the current gamestate and draw hitboxes for most objects.
Ctrl+H
: Heals every party member to full health.
Ctrl+K
: Sets current TP to 200%.
Ctrl+F
: Ends the current wave if one is active.
Ctrl+B
: Kills every party member.
Ctrl+J
: Shatters the player's soul if a wave is active.
Beyond the previously listed shortcuts, Kristal also implements some larger, more general debug menus that can be used anywhere in a mod. By default, the shortcuts to open these are: `
for the console; Shift+`
for the debug command menu; and Ctrl+O
for the object selection menu, though these can all be rebinded in the Controls menu.
The console allows the user to input any Lua code they want and run it. Additionally, if the user prints a value, it will appear directly in the console. This can be used to quickly see the values of variables while debugging, or perform arbitrary code on the fly to test something.
This menu contains a list of commands that can run code that can be helpful for testing mods, such as starting an arbitrary cutscene or entering an encounter, or blowing up the player (helpful). Additionally, it's possible for mods to define their own debug commands, by using functions within the Kristal.DebugSystem
class. It's recommended to register debug commands in Mod:registerDebugOptions()
(see mod.lua for more detail). The following are functions that can be used to register debug commands:
registerOption(menu, name, description, func, state)
: Registers a debug command. menu
is the ID of the submenu the command should be in ("main"
refers to the main debug command menu), name
is a string defining the name of the command that is displayed, description
is a string defining the description that appears at the bottom of the screen when hovering over the command, func
is the function that will be run when the command is selected, and state
is the Game state that the command is allowed to be used in (being either OVERWORLD
, BATTLE
, SHOP
, GAMEOVER
, or ALL
). name
and description
can alternatively be functions that return strings; this can be used to make names or descriptions that change depending on certain conditions.
registerMenu(menu, name)
: Registers a submenu for debug commands. menu
is the ID of the submenu to create, and name
is either a string or a function that returns a string, defining the display name of the menu.
enterMenu(menu, index, skip_history)
: Enters a submenu. menu
is a string referring to the ID of the submenu to enter, index
is an optional number what option index the player should start on (defaulting to 1), and skip_history
is an optional boolean, that, if true, will make it so exiting this menu puts the player at the menu that preceded the current submenu. This function should be used to set up debug commands that enter submenus so they can be accessed.
appendBool(text, bool)
: Returns a string, combining the given text
string with (ON)
or (OFF)
depending on the state of bool
.
This mode allows the user to click on objects to select them, which can display certain information about objects. Clicking and dragging an object will also move its position. The information that is displayed for an object is customizable, as well; see Object:getDebugInfo()
for more detail. Additionally, when selecting an object, the debug console gains more features; referencing the variables selected
or _
will both refer to the currently selected object.
Downloading Kristal
Installing and playing mods
Game options
File structure
mod.json and mod.lua
Libraries
Save data
Game and Kristal variables and functions
Important tips
Using objects
Creating new objects
Extra notes
Collision
DrawFX
Sprites and the Sprite object
Custom fonts
Sounds and music
External libraries
Utility functions
Global variables
Debug shortcuts
Debug menus
Making an actor
ActorSprite
Default animations
Creating a party member
Using and overriding functions
Types of Items
Default items
Inventory
Defining a spell
Making rooms
Using rooms in your mod
The Map class
Game.world functions
Events and Controllers
Existing events
Characters
Types of Characters
Battle areas and World bullets
Making a cutscene
Starting cutscenes
The Text object
In-text modifiers
Creating a shop
Overridable functions
Shop states
Shopkeepers
Making an encounter
Game.battle functions
Battle and PartyBattler states
PartyBattlers and EnemyBattlers
Creating an enemy
Overridable functions
Misc. functions and variables