module "name" { ... } is the one global a module file uses. Everything else is a verb on m, a bag, a table or rf. Which optional verbs a version has is on its own page: Dragonborn, Age of Patron, RF Online 1.5 and Golden Age.
Rules for Every Verb
rfverbs take a character id, never a player table:rf.notice(ev.player.id, ...). Them:bags take either.- Codes are the server's own. Item, monster, map and effect codes come from your version's content and differ between RF versions. A setting with
ofchecks them for you, andrf.item_name(code) == nilmeans no such item. - Most actions need the character online and raise an error otherwise.
rf.maildoes not. - A line of text is at most 200 bytes. Longer text is cut.
Items and Names
rf.give_itemraises an error when the bag is full.rf.item_nameand an item table'snameare the item's real name, or its code where the content has no name for it.rf.mailreaches a character online or not. A title is at most 20 bytes, a body 200 and a sender 16. Each entry initemsgoes in its own letter, and a mail may carry more than one of an item only if the item stacks.
Currency
rf.give_currency and rf.take_currency go through the server's own ledger for each balance, with a positive amount. Zero, negative or fractional amounts are an error. Cash is the account's cash-shop credit and needs an accounts database, and dalant and gold stop at their cap. Every movement is recorded with the module's name and your reason in the game database's mod_grant table, so you can always see what a module paid out or took.
rf.take_currency returns true, or false, why when nothing moved: the balance is short, or the character is busy or offline. It waits at most 250 ms. false means nothing moved, so a module can branch on it:
local ok, why = rf.take_currency(id, "pvp", 100, "penalty")
if not ok then m:log("nothing taken: " .. why) end
Buffs
rf.buff(id, code, seconds) applies an effect that is beneficial and continuous. Which codes it takes is on your version's page.
The m Handle
| verb | does |
|---|---|
m:account(player) | the bag of one account (a player table or the account id) |
m:after(seconds, fn) | run fn(m) once on the server clock; returns a timer id |
m:cancel(id) | cancel a timer |
m:char(player) | the bag of one character (a player table or its id) |
m:clock() | { hour, min, wday, yday } on the server clock and zone |
m.db.<table> | a declared custom table: get, put, delete, find, count |
m:disable(reason) | switch this module off until an operator enables it |
m:global() | the module's server-wide bag |
m:item(item) | the bag of one item instance (an item table or its uid), never a slot |
m:log(text) | one rate-limited line in the server log |
m:name() | this module's name |
m:now() | the server clock, in unix seconds |
m:send(player, message, fields) | a declared message to one player; false when their client never said hello |
m:setting(key) | a declared setting's current value (a set is a lookup table) |
Bag Verbs
| verb | does |
|---|---|
bag:delete(key) | delete a stored value |
bag:get(key) | a stored value, or nil |
bag:keys() | every key this bag holds |
bag:set(key, value) | store a value (nil deletes); tables up to four deep |
Custom Table Verbs
| verb | does |
|---|---|
t:count{ where = {col = v} } | how many rows match |
t:delete{ key columns } | delete one row |
t:find{ where = {col = v}, order = "col" or "-col", limit = n } | up to 500 rows |
t:get{ key columns } | one row, or nil |
t:put{ columns } | insert or replace one row |
rf Verbs
| verb | does |
|---|---|
rf.announce("text") | a notice to every online character |
rf.announce_race("accretia", "text") | a notice to one race |
rf.buff(id, "effect code", seconds) | apply a timed effect |
rf.clock() | the server's local time as {year, month, day, hour, min, sec, wday (1 = Sunday), yday} |
rf.get("character", id, "key") or rf.get("server", "key") | this module's stored value, or nil |
rf.give_currency(id, "dalant", amount [, reason]) | credit a positive amount through the ledger |
rf.give_exp(id, exp) | grant experience |
rf.give_item(id, "ipbhp01" [, count]) | give an item; returns its uid |
rf.item_name("ipbhp01") | an item code's display name, or nil |
rf.items(id) | everything the character holds as {uid, code, name, count}, empty when offline; reads the database, so a gate may not call it |
rf.kick(id [, "reason"]) | disconnect a character |
rf.mail(id, {title=, body=, from=, items={{code=, count=}}}) | post a letter, online or not |
rf.monster_name("02E00") | a monster code's display name, or nil |
rf.monsters(code or codes) | the monsters of those codes standing in the open world, as {code, name, serial, map, pos}; takes a code, a list or a set setting |
rf.notice(id, "text") | a system notice to one character |
rf.now() | the server clock in Unix seconds |
rf.online() | the ids of every online character |
rf.pickup(id, ev.box) | put a ground item in the character's bag under the game's own take rules and the loot gate; returns true and the item, or false and why it stayed on the ground |
rf.player(id) | {id, name, level, race, class, map, guild, account, staff}, or nil when offline |
rf.players_by_race("cora") | the ids of one race's online characters |
rf.send(id, "message", {field = value}) | send one of this module's declared messages |
rf.set("item", uid, "key", value) or rf.set("server", "key", value) | store a value; nil deletes it |
rf.spawn("map", "02E00", x, y, z [, count]) | place up to 20 non-respawning monsters in the open world; returns true, or false and why when a live limit refused them all |
rf.take_currency(id, "dalant", amount [, reason]) | debit a positive amount through the ledger; returns true, or false and why when nothing moved (the balance is short, the character is busy or offline) |
rf.warp(id, "map", x, y, z) | move a character |
Currencies and Storage Scopes
rf.give_currency and rf.take_currency take cash, dalant, gold, pvp. rf.get and rf.set take the scopes account, character, item, server.