Theme
Characters & money (wf_core)
Accounts and identity
A player is an account identified by a string:
wfx:<username>— the WFX.re account linked in the launcher, verified by the server (lower-case);guest:<name>— only with"identity": "wfx+guest", for LAN servers and bots.
Guests are not authenticated
A guest identifier is derived from the player name. Anyone using the same name gets the same characters and items. Never use wfx+guest on a public server.
The same account cannot be connected twice. Accounts are created on first join.
Account verification is not live yet
Today the launcher does not send a WFX.re proof to game servers. Sending the account's session token would let a server operator steal the account, so the plan is a single-use, per-server ticket issued by the master server and checked by the game server. Until it exists, use wfx+guest for tests; wfx refuses everyone.
Characters
Each account has up to maxCharacters characters. One character is played at a time.
| Field | Rule |
|---|---|
firstname, lastname | 1–24 letters, spaces, ' and -; must start with a letter |
dob | YYYY-MM-DD, a real date, age 18 to 100 |
sex | "m", "f" or "" |
Deleting a character is a soft delete (kept in the database, hidden). A character in use cannot be deleted or loaded by a second player.
When a character is loaded, the server sends its saved position (wf:spawn) so the client can put the player back where they left. Positions come from the server's own player sync, are saved every savePositionSeconds and on leave.
In game (v1, before the character menu exists):
text
/perso your character
/perso liste list your characters
/perso creer Ana Lopez 1991-02-03
/perso jouer 1
/perso quitter back to character selectionMoney
Two accounts per character: cash and bank. Amounts are positive integers (no cents); 1.5, "10", NaN, negative numbers or values above 2^53 are refused with invalid_amount. A balance can never go below zero (insufficient_funds). Each movement is written to the money_log table with the new balance and a reason.
lua
-- server script (Lua)
local balance, err = exports.wf_core:AddMoney(source, "bank", 250, "fishing")
if not balance then print("refused:", err) end
local ok = exports.wf_core:RemoveMoney(source, "cash", 40, "taxi")
exports.wf_core:TransferBank(source, target, 1000, "rent") -- atomic: both or nothingJobs and grades
Jobs are data, in wf_core/data/jobs.json:
json
"police": {
"label": "Police de Bolivie",
"grades": [
{ "label": "Cadet", "salary": 200 },
{ "label": "Capitaine", "salary": 550, "boss": true }
]
}A character has one job and a grade (index in grades, from 0). unemployed always exists.
Duty. A character is off duty when loaded (unless the job sets "defaultDuty": true) and goes back off duty when it changes job. Job scripts call exports.wf_core:SetDuty(source, true) (for example at the police station) and listen to wf:dutyChanged. Every paycheckMinutes, each loaded character on duty receives the salary of its grade in the bank; the unemployed allowance is always paid. Set paycheckRequiresDuty to false in config.json to pay everyone.
Needs (hunger, thirst)
Each character has needs from 0 to 100, defined in wf_core/config.json:
json
"status": { "hunger": { "decayPerMinute": 0.5 }, "thirst": { "decayPerMinute": 0.8 } }- New characters start at 100. Every minute the server lowers each need by
decayPerMinute; values are saved per character. - Food and drink restore them through the item definition:
"use": { "consume": 1, "status": { "thirst": 35 } }. - Scripts use
GetStatus,SetStatus,AddStatusand listen towf:statusChanged/wf:statusEmpty(a need reached 0 — what happens then is up to your scripts). - The client shows them in the WildM HUD with
SetHudStat(id, value): the bar ids inwildm-hud/hud.json(status.items) must match the need names. Add a need ("stress": { "decayPerMinute": 0 }) and a bar with the same id to display it.
Groups (factions)
A character can belong to any number of groups, each with a grade: SetGroup(source, "cartel_sb", 2). Group names are lower-case letters, digits and _. Stashes can require a job or group grade (see Inventory).
Permissions
Permission groups belong to the account, defined in wf_core/data/groups.json:
json
"mod": { "inherits": "user", "permissions": ["wf.kick", "wf.inventory.open_any"] },
"admin": { "inherits": "mod", "permissions": ["*"] }* matches everything, wf.* matches every permission starting with wf.. Every account is in user. The server console (source 0) has every permission.
One permission system with the server ACE. HasPermission also accepts what the server's ACE allow (add_ace / add_principal, FiveM-style), and each WFramework account group is pushed as an ACE principal: an account in admin makes identifier.wfx:<name> inherit group.admin. So add_ace group.police wf.inventory.open_any allow works for WFramework, and IsPlayerAceAllowed(src, "command.kick") sees WFramework groups.
| Permission | Used by |
|---|---|
wf.money.give, wf.money.set | /givemoney, /setmoney |
wf.job.set | /setjob |
wf.group.add | /addgroup, /removegroup |
wf.inventory.give | /giveitem |
wf.inventory.open_any | open any inventory, including other players' |
Admin commands
text
givemoney <id> <cash|bank> <amount>
setmoney <id> <cash|bank> <amount>
setjob <id> <job> [grade]
addgroup <id> <group> removegroup <id> <group>
giveitem <id> <item> [count]