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.luais read and executed - Whatever the module
returns becomes the value ofrequire() - 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 MUsing 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
endSubmodules
Use dots in the module name to organize into subdirectories:
lua
local combat = require("combat.targeting")
-- Loads: scripts/libs/combat/targeting.luaFile 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.luaRules
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, orloadfile— 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
plugintable — 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 MUsage:
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
endLogging 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 MUsage:
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