gunsmith
Last updated on
Armouries made of a crafting bench, a stash chest and a job gate, all declared in one config file.
Each config entry becomes an armoury: a workbench where players craft ammunition, weapons or tools, and a chest (a shared stash) beside it, both as rows on the target eye. An armoury can be public or limited to jobs, a minimum grade and on-duty status; each recipe can ask for a higher grade. The bench is run by crafting, the chest by inventory. Gives a job or a district its own armoury without code.
| Side | both |
| Requires | crafting, character (hard) |
| Optional | inventory (the chest), target (the bench and chest rows) |
| Contract | none |
| Config | config/gunsmith.lua (shared) |
| Data | none of its own. Orders in opx77_crafting_orders; chests are stash rows in opx77_inventories. |
The shipped armoury positions in config/gunsmith.lua are placeholders and have not been surveyed. A bench more than REACH metres from where players stand can never be used, and nothing reports it. Set real positions before going live.
How an armoury works
- At start one crafting bench is registered per armoury, keyed
gunsmith:<armouryKey>,owner = 'gunsmith'. Recipes use the crafting recipe fields plusGRADE. - The bench gate reads the character's job from the
charactercontract. A gated armoury refuses when the job record is older thanJOB_MAX_AGE_MS. An armoury with noJOBSis open to everyone, andGRADEis then ignored. - A recipe's
GRADEis a minimum on top of the armoury's ownJOBSgrades. - The chest opens through the inventory
OpenStashcontract with the chest's position, so inventory checks reach with its ownREACH.DISTANCE. Same job gate as the bench (without recipe grades). Opening it is audited (gunsmith.chest). - Without
inventory, benches work and no chest opens. Withoutcrafting, no armoury has a bench.
Configuration
config/gunsmith.lua sets OPX.Config.MODULES.gunsmith. Shared script (the client draws the target spheres).
An armoury entry
| Field | Effect |
|---|---|
LABEL | Bench menu title. Defaults to the key. |
JOBS | { job = minimumGrade }. Absent or empty = public. |
ON_DUTY | true = the job must be the one worked, on duty. |
BENCH | { X, Y, Z, BUCKET? }. Without a valid position the armoury has no bench. |
CHEST | { NAME, LABEL?, SLOTS? (50), MAX_WEIGHT? (100000), X, Y, Z, BUCKET? (0) }. NAME is the stash key: letters, digits, _, -, ., up to 48. Never rename it: a new name is an empty chest. |
QUEUE | Orders per character on this bench (crafting caps it at its MAX_QUEUE). |
RECIPES | List of crafting recipes, each with an optional GRADE (0–255). |
Refusal codes
Chest refusals use gunsmith.<code>. Bench gate refusals use crafting.<code>; this module adds those four keys to the locales.
| Code | Where | Meaning |
|---|---|---|
job_required | chest, bench | The character does not hold a listed job. |
grade_too_low | chest, bench | Grade below the armoury's or the recipe's minimum. |
off_duty | chest, bench | ON_DUTY is set and the character is off duty. |
job_stale | chest, bench | The job record is older than JOB_MAX_AGE_MS. |
no_character | chest, bench | No character loaded (gated armouries only). |
no_such_chest | chest | Unknown armoury, or it has no chest. A refusal names back the chest key only when it names a known chest. |
dead | chest | The player is down (Not while you are down.). |
not_for_you | chest | Gate refused with no code. |
unavailable | chest | No inventory contract, or an inventory code with no gunsmith.* text (for example a failed load). The real code goes to the log. |
too_far, not_ready, not_loaded, bad_argument | chest | Passed through from inventory OpenStash. |
The chest accepts one open request per 750 ms per player.