EndCore Framework

en-crafting

Recipes by hand, at workbenches and at campfires, with tools, blueprints, skill locks and skill-based speed and refunds.

en-crafting lets survivors turn scavenged junk into useful gear. Every recipe belongs to a station:

  • By hand: anywhere, default key J.
  • Workbench: any world prop with a workbench model, plus benches this resource spawns.
  • Campfire: fire props. Standing near one also warms you.

The crafting page lists the station's recipes. For each one it shows the ingredients (and how many you have), tools you need but keep, blueprint requirements, skill or level locks, and how many you can afford. Crafting runs a progress bar with the station's animation. Ingredients are only taken when it finishes, and skill bonuses make crafting faster and sometimes save materials.

At a glance

Depends onen-core, en-ui, en-inventory
Start afterAll of the above
Database tablesNone (recipes are config; placed benches are stored by the content system)
Config filesconfig/shared.lua
Key bindsen_crafting_hand (J)
In-game builderContent kind bench in en-admin

How it works

Stations and benches

A station is defined in Config.stations. Any prop whose model is in a station's models list acts as that station, targeted through encore.target.addModel. Benches listed in Config.benches, or placed with en-admin, are spawned client-side as frozen props within 60 m.

When a station has heat = true, standing within 4 m of one of its props sets LocalPlayer.state.nearHeat, which en-weathersync uses to warm you.

Crafting time

lua
duration = recipe.time * amount * (1 - math.min(0.6, craftSpeedBonus))

Material refunds

When a craft finishes, each ingredient unit has a min(0.9, craftRefund bonus) chance of being saved.

Server checks

On finish, the server checks everything again: you're still within distance + 2 of the station, at least 90% of the time has passed, and you have the ingredients, tools, blueprint and room to carry the result. If you drop ingredients mid-craft, the craft fails.

Bonuses and XP come from en-skills.

Configuration

KeyDefaultWhat it does
Config.keys.hand'J'Hand-crafting key bind
Config.stationshand, workbench, campfireStation definitions: label, icon, models (props that act as this station), anim = { dict, clip, flag }, heat (bool)
Config.benches2 workbenchesProps this resource spawns: { id?, station, model, coords = vec4 }. id defaults to config:<index>
Config.distance2.5Reach to a station
Config.maxBatch10Most of one recipe per craft
Config.recipes9 recipesRecipe definitions

Recipe fields

FieldWhat it does
idUnique id
stationKey in Config.stations
result{ item, count }
ingredients{ { item, count }, ... }, taken on finish
tools{ 'item', ... }, needed but kept
blueprintItem that must be carried; kept
timeMilliseconds for one, before the speed bonus
requires{ skill = 'name', level = n } or { level = n } (character level)
xp{ [skill] = amount } per craft, multiplied by the amount crafted
categoryList grouping; defaults to the result item's category

Adding a station and recipes

lua
Config.stations.stove = {
    label = 'Camp Stove', icon = 'temperature', heat = true,
    models = { 'prop_cooker_03' },
    anim = { dict = 'amb@prop_human_bbq@male@idle_a', clip = 'idle_b', flag = 1 },
}

Config.recipes[#Config.recipes + 1] = {
    id = 'cook_beans', station = 'campfire', result = { item = 'canned_beans', count = 1 },
    ingredients = { { item = 'garbage', count = 1 } }, time = 6000, xp = { crafting = 1 },
}

Config.recipes[#Config.recipes + 1] = {
    id = 'ammo_shotgun', station = 'workbench', result = { item = 'ammo_shotgun', count = 6 },
    ingredients = { { item = 'scrapmetal', count = 4 }, { item = 'garbage', count = 2 } },
    tools = { 'WEAPON_CROWBAR' }, blueprint = 'blueprint_ammo',
    time = 11000, requires = { skill = 'crafting', level = 4 }, xp = { crafting = 10 },
}

Every item a recipe uses must exist in en-inventory's item list; see Add an item.

Note

A placed bench's model must be one of its station's models. A blank model uses the first one, and anything else is rejected. Stations with no models, such as hand, can't be placed.

Exports

All exports are server-side. There are no client exports.

ExportArgumentsReturns
GetRecipeidThe recipe table from config, or nil
IsCraftingsourceboolean
BuilderListkindFor 'bench': { id, label, subtitle, coords, placed, inConfig }[] (label is the station label, subtitle the model)
BuilderGetkind, id{ station, model, coords }
BuilderValidatekind, id, dataok, err
BuilderSchemakindFields station, model, coords
BuilderTemplatekind{ station = 'workbench', model = 'prop_tool_bench02' }

Events

EventSidePayload
en-crafting:server:craftedServer-localsource, recipeId, amount

en-quests uses this event for craft objectives.

State bags

KeyMeaning
nearHeatPlayer state, replicated. true within 4 m of a prop of a heat = true station

Examples

Reward a milestone for crafting ammunition:

lua
AddEventHandler('en-crafting:server:crafted', function(source, recipeId, amount)
    local recipe = exports['en-crafting']:GetRecipe(recipeId)

    if recipe and recipe.result.item == 'ammo_shotgun' then
        exports['en-core']:AddXP(source, amount * 5)
    end
end)

Don't let a player teleport or start a job while crafting:

lua
if exports['en-crafting']:IsCrafting(source) then
    return false, 'Finish crafting first.'
end