Skip to content

Lua API

ESTONlA edited this page Sep 6, 2026 · 5 revisions

Lua API

Events

htf.on("fish_hooked", function(fish_name)
end)

Register one callback per event per Lua mod. Registering the same event again replaces that mod's previous callback.

Commands

htf.command("reward", function(args)
  htf.money(50)
end)

Commands are typed by the host as /reward. args is a one-indexed Lua table containing words after the command.

Scheduling

htf.after(5, function()
  htf.chat("Five seconds passed.")
end)

htf.every(60, function()
  htf.chat("Minute check.")
end)

Host Actions

htf.chat("Hello crew")
htf.money(100)

htf.chat broadcasts a prefixed game chat message. htf.money awards shared money and only acts while hosting.

Messages are limited to 200 characters including the mod-name prefix. Money must be finite, nonnegative, and at most 1,000,000 per call; amounts are rounded to integers and capped at the balance limit. htf.money returns true when the host economy is available, false otherwise. These are shared funds, not a private player balance.

Persistent Data

local score = tonumber(htf.get_data("score", "0"))
score = score + 1
htf.set_data("score", tostring(score))

Values are strings. Use Lua tonumber and tostring for numeric values.

Keys accept 1-64 letters, digits, underscores, or hyphens. Values are limited to 4096 characters. Data is saved in BepInEx/config/HowToLua.<id>.cfg, shared across that installation's worlds. It is not JSON storage.

Native Buttons

htf.button("Show catch count", function()
  htf.chat("Catches: " .. htf.get_data("catches", "0"))
end)

Buttons appear in Pause > Lua Mods > Mods / Actions. Host-only mod actions are disabled on clients. Labels allow 1-48 characters, with up to 16 actions per mod.

Limits and Errors

Each entry/callback has a 50,000 Lua instruction budget. Runtime failures disable the mod, its timers, commands, and action buttons. Reload after fixing the file. The sandbox exposes math, string and table operations, but not io, os, debug, require, dofile, loadfile, or coroutine.

Timers accept 0.05-86400 seconds, with up to 64 pending timers per mod. They use unscaled game time, including pauses. When a host-only timer becomes eligible after time spent outside a hosted session, it runs once rather than replaying every missed interval. Callbacks cannot yield; split longer work across timers.

Utility

if htf.is_host() then
  htf.log("Host is active")
end

Clone this wiki locally