Skip to content

Library

FrostSource edited this page Sep 17, 2024 · 19 revisions

Controls

gesture.lua

Provides a system for tracking simple hand poses and gestures.

Gestures are added with a unique name and a [0-1] curl range for each finger, or nil if the finger shouldn't be taken into consideration.

Gesture:AddGesture("AllFingersNoThumb", 1, 1, 1, 1, 0)

Gestures can be removed, including built-in gestures, can be removed to lower a small amount of processing cost, however this might produce undesirable results for other mods using the same gesture script if you plan to use a system like Scalable Init.

Gesture:RemoveGestures({"OpenHand", "ClosedFist"})

Recommended usage for tracking gestures is to register a callback function with a given set of conditions:

Gesture:RegisterCallback("start", 1, "ThumbsUp", nil, function(gesture)
    ---@cast gesture GESTURE_CALLBACK
    print(("Player made %s gesture at %d"):format(gesture.name, gesture.time))
end)

Generic gesture functions exist for all other times:

local g = Gesture:GetGesture(Player.PrimaryHand)
if g.name == "ThumbsUp" then
    print("Player did thumbs up")
end

local g = Gesture:GetGestureRaw(Player.PrimaryHand)
if g.index > 0.5 then
    print("Player has index more than half extended")
end

haptics.lua

Haptic sequences allow for more complex vibrations than the one-shot pulses that the base API provides.

A HapticSequence is created with a total duration, vibration strength, and pulse interval. The following sequence lasts for 1 second and vibrates at half strength every 10th of a second. This will pulse 10 times in total.

local hapticSeq = HapticSequence(1, 0.5, 0.1)

After creating the sequence we can fire it at any point. If the sequence is fired again before finishing it will cancel the currently running sequence and start again.

hapticSeq:Fire()

input.lua

Simplifies the tracking of button presses/releases

By default the input system is turned off to minimize the amount of processing done for addons which don't use it. If your script is a mod/init script you can simply start the system by setting its AutoStart property before the player spawns.

Input.AutoStart = false

You can also start and stop the system at any point.

-- If you don't provide a thinking entity (as below) the player MUST exist when calling Start
Input:Start()

-- All tracking will stop immediately, but registered listeners will still exist when you start the system again
Input:Stop()

The system will only listen to the digital actions you tell it to track, which can be done in a variety of ways. You may track/untrack actions at any point but it must be done at least before you listen to or test the action.

-- Track a single button
Input:TrackButton(DIGITAL_INPUT_FIRE)

-- Track multiple buttons at once by passing a table list
Input:TrackButtons({DIGITAL_INPUT_FIRE, DIGITAL_INPUT_ARM_GRENADE})

-- All buttons can be tracked, but this can come with a performance cost in complex addons
Input:TrackAllButtons()

-- The inverse for untracking
Input:StopTrackingButton(DIGITAL_INPUT_FIRE)
Input:StopTrackingButtons({DIGITAL_INPUT_FIRE, DIGITAL_INPUT_ARM_GRENADE})
Input:StopTrackingAllButtons()

Common usage is to register a callback function which will fire whenever the conditions are met.

---Print a message every time the primary hand presses the grenade arm button 3 times in a row
---@param params INPUT_PRESS_CALLBACK
Input:ListenToButton("press", INPUT_HAND_PRIMARY, DIGITAL_INPUT_ARM_GRENADE, 3, function(params)
    print(("Button %s pressed at %.2f on %s"):format(
        Input:GetButtonDescription(params.button),
        params.press_time,
        Input:GetHandName(params.hand)
    ))
end)

---Print a message whenever a fire trigger has been released after being held for at least 1 second
---@param params INPUT_RELEASE_CALLBACK
Input:ListenToButton("release", INPUT_HAND_BOTH, DIGITAL_INPUT_FIRE, nil, function(params)
    if params.held_time >= 1 then
        print(("Button %s charged for %d seconds on %s"):format(
            Input:GetButtonDescription(params.button),
            params.held_time, 
            Input:GetHandName(params.hand)
        ))
    end
end)

-- You can also give any context value which will be sent as the first argument to the callback function

---@param params INPUT_PRESS_CALLBACK
function thisEntity:Callback(self, params)
    print(self:GetName() .. " pressed button " .. Input:GetButtonDescription(params.button))
end

Input:ListenToButton("press", INPUT_HAND_BOTH, DIGITAL_INPUT_ARM_GRENADE, 1, thisEntity.Callback, thisEntity)

Other general use functions exist for checking presses and are extended to the hand class for ease of use:

if Player.PrimaryHand:Pressed(3) then end
if Player.PrimaryHand:Released(3) then end
if Player.PrimaryHand:Button(3) then end
if Player.PrimaryHand:ButtonTime(3) >= 5 then end

Data

color.lua

Easy modification of colors between RGB and HSL systems

This class registers with Storage for easy saving/loading

-- Create a red color with full alpha
local red = Color(255, 0, 0, 255)

-- Or by just providing the red. Blue and green will implicitly be 0, and alpha will implicitly be 255
red = Color(255)

-- Same implicit values but with green
local green = Color(nil, 255)

-- Make the color 50% darker
green:SetHSL(nil, nil, green.lightness * 0.5)

-- Get/Set any value individually
green.r = 128 -- Accepts a range of [0-255]
green.g = 0 -- Accepts a range of [0-255]
green.b = 255 -- Accepts a range of [0-255]
green.a = 0 -- Accepts a range of [0-255]
green.hue = 300 -- Accepts a range of [0-360]
green.saturation = 50 -- Accepts a range of [0-100]%
green.lightness = 25 -- Accepts a range of [0-100]%

-- Get the hexadecimal version of a color
print(green:ToHexString())

-- Check if any value is an instance of the color class
if IsColor(green) then
    print("Is a color")
end

inventory.lua

An inventory is a table where each key has an integer value assigned to it. When a value hits 0 the key is removed from the table.

This class registers with Storage for easy saving/loading

-- The inventory table may use any type that Lua allows as a key, including other tables, but the value part MUST be a number type
-- Create an inventory with 2 initial keys.
local inv = Inventory({
    gun = 1,
    metal = 4
})

-- Remove 1 from metal, returns the new value after removal
print(inv:Remove("metal")) -- Prints "3"

-- Add 3 to gun, returns the new value after adding
print(inv:Add("gun", 3)) -- Prints "4"

-- Get the highest key/value pair in the inventory
local key, val = inv:Highest()
print(key, val) -- Prints "gun  4"

-- To loop over the items you can reference the inventory `items` property directly
for key, value in pairs(inv.items) do
    print(key, value)
end

-- Or use the `pairs` helper method:
for key, value in inv:pairs() do
    print(key, value)
end

This class supports storage with Storage.SaveInventory Inventories are also natively saved using Storage.Save() or if encountered in a table being saved.

Storage:SaveInventory('inv', inv)
inv = Storage:LoadInventory('inv')

queue.lua

A queue is a data structure where items are added at one end and removed from the other, so the first item added is the first one taken out.

This class registers with Storage for easy saving/loading

-- Create a queue with 3 initial values.
-- 3 is the front of the queue.
local queue = Queue(1, 2, 3)

-- Remove the item from the front of the queue and return it
print(queue:Dequeue()) -- Prints "3"

-- Remove multiple values at a time
local a, b = queue:Dequeue(2)

print(a, b) -- Prints "2   1"

-- Add any values to the queue in the order given
stack:Enqueue('a', 'b', 'c') -- Queue is now { 'a', 'b', 'c' }

-- To loop over the items you can reference the `items` property directly
for index, value in ipairs(queue.items) do
    print(index, value)
end

-- Or use the `pairs` helper method
for index, value in queue:pairs() do
    print(index, value)
end

This class supports storage with Storage.SaveQueue. Queues are also natively saved using Storage.Save() or if encountered in a table being saved.

Storage:SaveQueue('queue', queue)
queue = Storage:LoadQueue('queue')

stack.lua

A stack is a data structure where elements are added to the top and removed from the top, with the most recently added item being the first to be removed.

This class registers with Storage for easy saving/loading

-- Create a stack with 3 initial values.
-- 1 is the top of the stack.
local stack = Stack(1, 2, 3)

-- Pop the top value off the stack and return it
print(stack:Pop()) -- Prints "1"

-- Pop multiple values and return them
local a, b = stack:Pop(2)

print(a, b) -- Prints "2   3"

-- Push any values onto the stack in the order given
stack:Push('a', 'b', 'c') -- Stack is now has 'a' at the top and 'c' at the bottom

-- To loop over the items you can reference the `items` property directly
for index, value in ipairs(stack.items) do
    print(index, value)
end

-- Or use the `pairs` helper function
for index, value in stack:pairs() do
    print(index, value)
end

This class supports storage with Storage.SaveStack. Stacks are also natively saved using Storage.Save or if encountered in a table being saved.

Storage:SaveStack('stack', stack)
stack = Storage:LoadStack('stack')

Debug

common.lua

Debug utility functions.

controller.lua

Allows quick debugging of VR controllers.

novr.lua


Extensions

entities.lua

Extensions for the Entities class.

entity.lua

Provides base entity extension methods.

npc.lua

Extension for NPC entities. Some functions are specific to only one entity class such as npc_combine_s, check the individual function descriptions.

qangle.lua

Provides QAngle class extension methods.

string.lua

template.lua

Clone this wiki locally