Craft and Progression

Version 1.0.1. The listing, or pick it up in the shop and run it.

Craft and Progression

Craft and Progression gives you crafting stations, recipes and skills with XP curves you can tune, plus a balancing screen that tells you in real hours how long each level takes before you ship it. Most crafting scripts give you a recipe list and a level number, then leave you to guess how long anything takes, and a month later you find out nobody passed level 5, or that one player maxed out in a weekend.

Crafting menu

What you get

  • Crafting stations anywhere on the map, each offering the recipe groups you pick, optionally limited to certain jobs, with an optional map blip.
  • Recipes with inputs, outputs, craft time, a required skill level and XP. Also an optional failure chance that only costs part of the inputs, and tool inputs that are needed but never used up.
  • Skills with real curves: linear, power or exponential, each with its own parameters and max level.
  • A balancing screen (/craftadmin) that shows, per skill, the XP for every level, the running total, the number of crafts and the real hours to get there at your expected pace. Change the pace on screen to try other numbers. A leaderboard of top players sits right next to it.
  • A crafting menu that shows every recipe at the station, the locked ones with the level they need, and what you carry against what each recipe needs.
  • Server-side everything: distance to the station, job, skill level and items are checked on the server, the craft timer runs on the server, and a player can only craft one thing at a time.
  • Exports so jobs, quests and other scripts can read levels and grant XP.
  • Framework support: ESX Legacy, Qbox and QBCore, with ox_inventory, qb-inventory or the ESX inventory.

Balancing screen

Requirements

  • ESX Legacy, Qbox or QBCore
  • oxmysql
  • OneSync (the server checks how far players stand from the station)
  • ox_inventory, qb-inventory or the ESX inventory. An inventory that keeps its own item list and answers ox_inventory's Items export (for example ak47_qb_inventory) is checked against its own list.
  • ox_lib is optional. When it runs, prompts and notifications use it.

Install

  1. Unzip so that resources/craft_progression/fxmanifest.lua exists (not resources/craft_progression-v1.0.0/craft_progression/..., which Windows "Extract All" creates), then add ensure craft_progression. Start order doesn't matter for the framework, it waits up to 30 seconds for it and prints what it found.
  2. Give staff the balancing screen in server.cfg:
    add_ace group.admin craftprogression.admin allow
    
  3. Check that the item names in Config.Recipes exist in your inventory. They ship with the QBCore defaults, and on start the server prints any item your inventory doesn't know.
  4. Start the server. The table creates itself (sql/install.sql is there if your database user can't create tables).
  5. Walk up to a station and press E. Staff open the balancing screen with /craftadmin.

Setting it up

Everything lives in config.lua, with a comment next to each setting.

Skills and curves

crafting = {
    label = 'Crafting',
    maxLevel = 20,
    curve = { type = 'power', base = 100, exponent = 1.5 },
    pace = { xpPerCraft = 20, craftsPerHour = 45 },
},

Every skill starts at level 1. The curve sets the XP each level costs, where n is the level being bought minus one:

Curve Cost of a level Feels like
linear (base, step) base + step x (n - 1) Steady, every level a bit longer than the last
power (base, exponent) base x n ^ exponent Quick early levels, a long tail at the top
exponential (base, growth) base x growth ^ (n - 1) Each level costs growth times the last, gets steep fast

pace is how you expect people to play: XP per craft and crafts per real hour. The balancing screen turns that into hours. Leave it out and it gets worked out from the skill's recipes (average XP and craft time, plus Config.PaceOverhead seconds between crafts for walking and menus).

With the shipped Crafting skill at 20 XP per craft and 45 crafts an hour, level 10 takes about 12 hours of crafting and level 20 about 75 hours. If that's too slow or too fast for your server, change the curve and look again.

Recipes

repairkit = {
    label = 'Repair kit', group = 'tools', skill = 'crafting', level = 4, xp = 30, time = 10,
    inputs = { { item = 'metalscrap', qty = 4 }, { item = 'rubber', qty = 2 }, { item = 'screwdriverset', qty = 1, keep = true } },
    outputs = { { item = 'repairkit', qty = 1 } },
    failChance = 0.15, failLoss = 0.5,
},
  • group decides which stations offer it.
  • keep = true marks a tool. The player needs it, but it's never used up.
  • failChance is the chance a craft fails. A failed craft makes nothing and loses failLoss of each input, rounded down (0.5 by default), and still gives Config.FailXpShare of the XP.
  • Players can queue up to Config.MaxBatch at once. Time, inputs, outputs and XP scale with the amount, and each craft in the batch rolls on its own.

Stations

{
    id = 'ammunation_bench', label = 'Gunsmith bench',
    coords = vector3(15.91, -1106.84, 29.80),
    groups = { 'weapons', 'tools' },
    job = { 'police', 'ammunation' },          -- optional
    blip = { sprite = 566, color = 47, scale = 0.7 },   -- optional
},

Balancing before you ship

  • In game: /craftadmin (needs the ace above). Pick a skill, read the hours, and change XP per craft or crafts per hour to try another pace. Nothing on that screen is saved, so edit config.lua once you're happy.
  • In the server console: craftbalance crafting prints the same table, which is handy before anyone has joined.
  • On start the server checks the config and prints anything that doesn't add up, IE a recipe needing a level above the skill's max, or a recipe group no station offers.

How crafting works

  1. The player opens a station. The server checks they're close enough and have the job, if the station needs one.
  2. They pick a recipe and an amount. The server checks the level and the inputs, locks the player so they can't start a second craft, and starts its own timer. The client only shows a progress bar.
  3. Walking away, pressing X, switching character or disconnecting cancels the craft. Nothing is taken until the end.
  4. When the timer ends the server checks the inputs again, takes them, makes sure the outputs fit and gives them. If the outputs don't fit, or the inventory refuses one, the inputs come back and no XP is given.

Exports

exports.craft_progression:GetLevel(source, 'crafting')               -- level, or nil
exports.craft_progression:GetXP(source, 'crafting')                  -- total XP, or nil
exports.craft_progression:AddXP(source, 'crafting', 50, 'delivered parts')   -- true, new level
  • nil means the player has no character loaded or the skill doesn't exist. In the first moment after a character loads, before their XP has come back from the database, GetLevel reads as 1 and GetXP as 0.
  • AddXP only takes positive whole numbers. A string, nil, NaN, zero or a negative returns false and changes nothing. One call grants at most Config.MaxXpPerCall, and XP stops at the max level. XP granted while a character is still loading is kept and added once it loads.
  • Set Config.Debug = true to print every AddXP call with the calling resource and the reason.

Commands

Command Who What
/craftadmin ace craftprogression.admin Balancing screen and leaderboard
/craftxp <id> <skill> <amount> ace craftprogression.admin or console Give XP, negative amounts take it away
craftbalance <skill> console The balancing table as text

Troubleshooting

  • Nothing happens and there's no [craft_progression] line in the console: the folder is most likely nested. Check that resources/craft_progression/fxmanifest.lua exists, and not resources/craft_progression/craft_progression/fxmanifest.lua.
  • "No framework finished starting within 30s": your framework isn't running or it has a different resource name. The line lists what it found. Set Config.Framework if you run a renamed core.
  • "doesn't know these items": rename those items in Config.Recipes to ones your inventory has, or add them to your inventory. The line names the item list it checked. Case doesn't matter, so WEAPON_PISTOL and weapon_pistol count as the same item.
  • Every craft says "Get closer to the station": OneSync is off. The console says so on start.
  • "Database setup failed": oxmysql isn't connected or your database user can't create tables. Run sql/install.sql by hand.
  • The menu opens but a recipe shows "Missing materials" while you have the items: the recipe asks for an item name your inventory spells differently.

Escrow

The core is encrypted with Cfx asset escrow. These stay open so you can adapt them: config.lua, server/bridge.lua (all the framework and inventory code lives there) and sql/install.sql.

Support

Open a ticket in the Discord with your framework, inventory, oxmysql version and the server console output from startup.