Skip to content

Modules

The require() function lets you import shared utility scripts into your plugins. This keeps common code in one place instead of duplicating it across scripts.

How It Works

Modules live in the scripts/libs/ folder. Any script can load them with require():

lua
local utils = require("utils")
  • The module file scripts/libs/utils.lua is read and executed
  • Whatever the module returns becomes the value of require()
  • Results are cached — calling require("utils") again returns the same table without re-executing the file

Module Structure

A module is just a .lua file that returns a table of functions/values:

lua
-- scripts/libs/utils.lua
local M = {}

function M.distance(pos1, pos2)
    local dx = pos1.x - pos2.x
    local dy = pos1.y - pos2.y
    return math.sqrt(dx * dx + dy * dy)
end

function M.find_closest_mob(player_pos, map)
    local closest = nil
    local closest_dist = math.huge

    for _, mob in ipairs(map:get_mobs()) do
        if mob and mob:is_valid() then
            local mpos = mob:get_position()
            if mpos then
                local dist = M.distance(player_pos, mpos)
                if dist < closest_dist then
                    closest_dist = dist
                    closest = mob
                end
            end
        end
    end

    return closest, closest_dist
end

return M

Using Modules in Scripts

lua
plugin = {
    name = "Mob Hunter",
    version = "1.0.0",
    author = "You",
    description = "Hunts the closest mob using shared utilities",
    load = true
}

local utils = require("utils")

function on_tick()
    local player = core.object_manager.get_local_player()
    if not player or not player:is_valid() then return end

    local map = core.object_manager.get_current_map()
    if not map or not map:is_valid() then return end

    local pos = player:get_position()
    local mob, dist = utils.find_closest_mob(pos, map)

    if mob and dist < 300 then
        local mpos = mob:get_position()
        core.input.teleport_safe(mpos.x, mpos.y)
        core.input.use_skill(2001004)
    end
end

Submodules

Use dots in the module name to organize into subdirectories:

lua
local combat = require("combat.targeting")
-- Loads: scripts/libs/combat/targeting.lua

File Layout

scripts/
├── libs/                        -- Shared modules go here
│   ├── utils.lua                -- require("utils")
│   ├── cooldowns.lua            -- require("cooldowns")
│   └── combat/
│       └── targeting.lua        -- require("combat.targeting")
├── my_script.lua                -- Your scripts
└── another_script.lua

Rules

Module Names

Module names can only contain letters, numbers, underscores, and dots. Names like ../secrets or my module will be rejected.

  • Modules cannot use io, os, dofile, or loadfile — the same sandbox rules apply
  • Modules run in the global environment, not a script's sandbox — so all scripts share the same cached module instance
  • Modules are cached until any script is enabled or disabled — toggling a script clears the cache so the next require() re-reads from disk
  • Modules do not need a plugin table — they are not scripts, just libraries
  • require() calls can go at the top of your script (outside callbacks) since they only run once at load time

Examples

Cooldown Manager Module

lua
-- scripts/libs/cooldowns.lua
local M = {}
local timers = {}

function M.ready(key, cooldown_ms)
    local now = core.get_update_time()
    if not timers[key] or now - timers[key] >= cooldown_ms then
        timers[key] = now
        return true
    end
    return false
end

function M.reset(key)
    timers[key] = nil
end

return M

Usage:

lua
local cd = require("cooldowns")

function on_tick()
    if cd.ready("attack", 1000) then
        core.input.use_skill(2001004)
    end

    if cd.ready("potion", 5000) then
        core.input.use_item(2000001)
    end
end

Logging Helpers Module

lua
-- scripts/libs/log.lua
local M = {}

function M.info(fmt, ...)
    core.log(string.format(fmt, ...))
end

function M.warn(fmt, ...)
    core.log_warning(string.format(fmt, ...))
end

function M.err(fmt, ...)
    core.log_error(string.format(fmt, ...))
end

return M

Usage:

lua
local log = require("log")

function on_tick()
    local player = core.object_manager.get_local_player()
    if not player or not player:is_valid() then return end

    log.info("HP: %d/%d", player:get_health(), player:get_max_health())
end