Configuration
Overview
shared/config.lua: language, ranges, features, community projects, progression, blueprints, portable stations, model benches, fuel, base building and displayshared/config_models.lua: station model presets, bench prop, screen placement and cameraserver/config_server.lua: battlepass and Discord webhooks
Stations, recipes, categories, blueprints, projects and custom station models live in the database and are built from the admin panel (/craftadmin). When the same setting exists in both places, such as fuel, durability, pickup rules and queue limits, the value saved in the panel wins.
General
1Config.Debug = false
2Config.Language = 'en'
3Config.Command = 'craftadmin'Debug: prints extra console outputLanguage: language file loaded from thelocales/folderCommand: opens the admin panel
UI Theme
1Config.UITheme = {
2 preset = nil,
3 colors = {
4 primary = nil,
5 accent = nil,
6 background = nil,
7 surface = nil,
8 text = nil,
9 },
10}preset: theme preset for this resource.'default','wasteland','cyberpunk','noir'or'fantasy'.nilfollows the shared theme set inml_bridgecolors: CSS hex values for single colors. Anynilvalue follows the shared theme. Each bench can also get its own tint in the admin panel
Interaction and Streaming
1Config.Interaction = {
2 TargetDistance = 2.5,
3 SpawnDistance = 80.0,
4 MaxOperationRange = 5.0,
5}
6
7Config.Stream = {
8 Radius = 200.0,
9 OutRadius = 250.0,
10 ReloadDistance = 100.0,
11 PollMinInterval = 1500,
12 PollMaxInterval = 4000,
13}TargetDistance: meters to interact with a benchSpawnDistance: meters at which bench props spawn and despawnMaxOperationRange: highest distance the server accepts for any crafting actionRadius,OutRadius: benches insideRadiusare loaded on the client, benches beyondOutRadiusare dropped. KeepOutRadiuslargerReloadDistance: meters the player moves before the client asks the server for benches againPollMinInterval,PollMaxInterval: position check interval in milliseconds, faster while moving and slower while standing
Features
1Config.Features = {
2 Spotlight = true,
3 PortableStations = true,
4 Blueprints = true,
5 QueuedCrafting = true,
6 PropPreview = true,
7 CraftAnimations = true,
8 DamageInterrupt = true,
9 MultipleCrafters = false,
10 Invincibility = false,
11 CommunityProjects = true,
12}Spotlight: soft light above the bench while a player uses it, so the screen reads at night. Tuned inConfig.WorkLightPortableStations: benches players place with an itemBlueprints: recipes can need a blueprint, as an item or a permanent unlockQueuedCrafting: start a craft, walk away and collect it laterPropPreview: 3D preview of the result while craftingCraftAnimations: player animation while craftingDamageInterrupt: taking damage stops the craftMultipleCrafters: several players on the same bench at once. Withfalse, one player at a timeInvincibility: the player takes no damage while crafting. Only withMultipleCrafters = falseCommunityProjects: server-wide goals players give materials to
Community Projects
The whole server works toward a goal. Players donate materials at a station, or advance the goal by crafting the item it asks for. At 100% the project pays rewards and can unlock recipes, categories or station types for everyone. Projects are created in the admin panel with no restart.
1Config.CommunityProjects = {
2 MaxPerDonation = 1000,
3 AnnounceAt = { 25, 50, 75 },
4 InstantReward = true,
5 RewardTiers = true,
6 Leaderboard = true,
7 ShowInAttract = true,
8 XpPerUnit = 1,
9 PlayerNameFormat = 'rp_full',
10 BoardRange = 25.0,
11 BoardTint = '',
12}MaxPerDonation: highest amount one donation can giveAnnounceAt: progress percentages announced to the whole serverInstantReward: gives the XP of each donation at once instead of only at completionRewardTiers: completion rewards by tier: top contributors, everyone above a share, or anyone who took partLeaderboard: shows the contributor board. Each project can also hide its contributorsShowInAttract: shows the running project on idle station screensXpPerUnit: XP for each donated unitPlayerNameFormat: name on the board.'fivem'(account name),'rp_first'(character first name) or'rp_full'(first and last name, or the first name when there is no last name)BoardRange: meters at which a community board screen turns on. Other stations useConfig.DUI.RangeBoardTint: accent color of community boards. Empty uses the same accent as every other station. A tint set on the station in the panel wins
A community board is a placed station whose type is set to Community board in the admin panel. It opens the project list instead of the crafting menu, and skips fuel, wear and the queue. Other stations of the same bench type keep working as workbenches.
Internal Progression
Used only with Config.ExternalSkills.Enabled = false. Levels and XP are saved per player in the database.
1Config.Progression = {
2 Enabled = false,
3 GlobalXp = {
4 Base = 100,
5 Scaling = 1.4,
6 MaxLevel = 50,
7 },
8 CategoryXp = {
9 Base = 50,
10 Scaling = 1.3,
11 MaxLevel = 30,
12 },
13 Points = {
14 PerLevelUp = 1,
15 PerCategoryLevelUp = 1,
16 },
17}Enabled: turns the built-in levels onGlobalXp: XP needed per level isBase * (Scaling ^ (level - 1)), up toMaxLevel.Scaling = 1.0is linearCategoryXp: same formula for each recipe categoryPoints: points given on a level up
Skills
1Config.ExternalSkills = {
2 Enabled = true,
3 Resource = 'ml_skills',
4 Mapping = {
5 Category = '',
6 XpMultiplier = 1.0,
7 PerCategory = {},
8 },
9}Enabled: levels, skill checks and XP come fromml_skills.falseuses the internal progressionResource: name of the skills resourceMapping.Category: skill category used when a recipe has neither a required skill nor a category. XP goes first to the category of the required skill, then to thePerCategorymatch, then to the recipe categoryMapping.XpMultiplier: multiplier on recipe XP sent toml_skillsMapping.PerCategory: map of crafting category ID to skill category UID, when the names differ
Recipes and Queue
1Config.Recipes = {
2 HideUnavailable = true,
3 HideMissingBlueprint = true,
4 ShowLockedPreview = false,
5 MaxQueueSize = 3,
6 MaxBatchSize = 0,
7}
8
9Config.Queue = {
10 CleanupEnabled = true,
11 CleanupAfterDays = 7,
12 CleanupCheckInterval = 3600,
13 SharedView = true,
14 AllowSteal = true,
15}HideUnavailable: hides recipes the player cannot craft yetHideMissingBlueprint: hides recipes whose blueprint the player lacksShowLockedPreview: shows locked recipes as a preview the player cannot craftMaxQueueSize: queued crafts per player, counted over all benches together.0for no limit. Bench types can set their own limit in the panelMaxBatchSize: highest quantity of one craft.0for no limitCleanupEnabled,CleanupAfterDays: removes finished crafts nobody collected after this many daysCleanupCheckInterval: seconds between two cleanup checksSharedView: everyone at the bench sees the queue of every playerAllowSteal: players can collect the finished crafts of others. Each one is logged
Blueprints
1Config.Blueprints = {
2 GenericItemName = 'ml_blueprint',
3 DynamicPrefix = 'blueprint_',
4 StrictMode = false,
5 ConsumeOnCraft = false,
6 Durability = {
7 Enabled = false,
8 DefaultUses = 5,
9 },
10}GenericItemName: one shared item that carriesmetadata.blueprint = '<blueprint id>'. Needs an inventory with metadataDynamicPrefix: one item per blueprint, namedblueprint_<label>. A custom item name can also be set per blueprint in the panelStrictMode: every recipe needs a blueprintConsumeOnCraft: removes the blueprint item after craftingDurability: gives blueprints a number of uses. Works withConsumeOnCraft = true. Permanent unlocks are never used up
Portable Stations
1Config.PortableStations = {
2 GenericItemName = 'ml_workstation',
3 DynamicSuffix = '_workstation',
4 MaxPerPlayer = 5,
5 PlacementRange = 5.0,
6 DefaultPickupRule = 'owner',
7 DefaultPickupTimeOwner = 5,
8 DefaultPickupTimeTheft = 15,
9 TheftAnimation = 'mini@repair',
10 TheftAnimationName = 'fixing_a_ped',
11 LogTheft = true,
12 DeleteOld = 10,
13 DeleteOptions = {
14 DeleteOnlyIfNotCrafting = true,
15 DeleteOnlyIfNoFuel = true,
16 DeleteOnlyIfBroken = false,
17 },
18 RequireAnchor = {
19 Enabled = false,
20 Radius = 5.0,
21 Props = {
22 2139035592,
23 -1933224451,
24 -1924811947,
25 -1668132370,
26 },
27 },
28 PickupCooldown = 0,
29}GenericItemName: base station item. The bench type comes frommetadata.stationType. Bench types can also have an item of their own in the panelDynamicSuffix: suffix of per-type station items, such asmedic_workstationMaxPerPlayer: placed stations per playerPlacementRange: highest placement distance from the playerDefaultPickupRule: who can pick a station up.'owner','everyone'or a list of jobs. Bench types can change it in the panelDefaultPickupTimeOwner,DefaultPickupTimeTheft: seconds to pick up your own station or someone else'sTheftAnimation,TheftAnimationName: animation played while stealing a stationLogTheft: logs theft attemptsDeleteOld: days without use before an abandoned station is deleted.falseturns it offDeleteOptions: keeps a station that still has a queue, fuel or durability leftRequireAnchor: placement needs one of the listed prop models withinRadius, for example to keep stations inside a base. Hashes are signed numbers as returned byGetEntityModelPickupCooldown: seconds after placement before pickup is allowed.0turns it off
Model Benches
Every world prop of a bound model becomes a bench of that type, with no coordinates to place.
1Config.ModelBenches = {
2 Enabled = true,
3 RequireVerification = false,
4 CleanupDays = 30,
5 Bindings = {
6 },
7}Enabled: turns model benches onRequireVerification: registers a prop only whenHandlers.VerifyWorldBenchconfirms it.falseaccepts any bound prop a player usesCleanupDays: days without use before a model bench forgets its fuel, durability and queue.falsekeeps themBindings:modelis the prop,benchTypethe bench type name or ID from the panel,stationModelan optional preset fromconfig_models.luafor the screen and camera. The list ships empty, for example{ model = 'prop_tool_bench02', benchType = 'Weapons Bench' }
Admin
1Config.Admin = {
2 Permission = 'admin',
3 AcePermission = nil,
4 FullAccess = true,
5 MinimizeKey = 'F9',
6}Permission: framework group needed for the admin panelAcePermission: set an ACE permission, such as'mlcraft.admin', to check it instead of the groupFullAccess: admins can use every bench and recipeMinimizeKey: hides and restores the admin panel. F1 to F12, or a single letter or digit
Screen, Camera and Light
1Config.DUI = {
2 Range = 8.0,
3 MaxActive = 8,
4}
5
6Config.Camera = {
7 OffsetX = 0.0,
8 OffsetY = -1.10,
9 OffsetZ = 0.65,
10 LookZ = -1.05,
11 Fov = 58.0,
12 TransitionMs = 500,
13}
14
15Config.WorkLight = {
16 Color = { r = 255, g = 240, b = 220 },
17 Height = 2.0,
18 Range = 7.0,
19 Intensity = 3.0,
20}DUI.Range: meters at which a bench screen turns on and offDUI.MaxActive: screen browsers kept ready and reused. Each one holds memory, so raise it only if many benches stand close togetherCamera: default camera when a player uses a bench: offsets from the bench, look pitch, field of view and transition time. Station presets and single benches can override itWorkLight: color, height, falloff range and brightness of the spotlight above the bench
Live Craft Prop
A hologram of the result above the bench while crafting. It uses the prop set on the recipe, or the model of the first result item.
1Config.LiveCraftProp = {
2 Enabled = true,
3 Alpha = 150,
4 ResultAnchor = {
5 RightFraction = 0.33,
6 VertFraction = -0.07,
7 Hover = 0.14,
8 },
9 OffsetRight = 0.16,
10 OffsetForward = 0.46,
11 OffsetZ = 0.18,
12 DefaultRotX = 0.0,
13 DefaultRotY = 0.0,
14 DefaultRotZ = 0.0,
15 Spin = 25.0,
16 DefaultScale = 1.0,
17 AutoFit = true,
18 AutoFitMode = 'both',
19 AutoFitThreshold = 0.30,
20 AutoFitTarget = 0.22,
21 AutoFitMinScale = 0.10,
22 AutoFitPushPerM = 0.35,
23 AutoFitGroundZ = 0.0,
24}Alpha: transparency from0to255. About150looks like a hologramResultAnchor: where the prop floats over the screen, next to the result image.Hoveris the height above the screenOffsetRight,OffsetForward,OffsetZ: position used when the bench has no screen prop. Each recipe can set its ownprop_offsetDefaultRotX,DefaultRotY,DefaultRotZ: default rotation in degrees. Each recipe can setprop_rotationSpin: degrees per second of spin.0turns it offDefaultScale: starting scale of the 3D test in the recipe editor. Aprop_scaleon the recipe skips auto-fitAutoFit,AutoFitMode: shrinks or pushes back large props so they fit.'scale','push'or'both'AutoFitThreshold,AutoFitTarget,AutoFitMinScale,AutoFitPushPerM,AutoFitGroundZ: size that triggers auto-fit, size after shrinking, smallest scale, push per meter of leftover size, and height of the prop base
Fuel and Durability
Fuel and durability are optional per bench type and usually set in the admin panel, which wins over these defaults.
1Config.Fuel = {
2 mlFuel = {
3 enabled = false,
4 hintItems = {},
5 acceptedFuelTypes = {
6 'diesel',
7 },
8 typeLabels = {
9 ['fuel'] = 'Gasoline',
10 ['diesel'] = 'Diesel',
11 ['biofuel'] = 'Biofuel',
12 ['ethanol'] = 'Ethanol',
13 ['kerosene'] = 'Kerosene',
14 ['electricity'] = 'Electricity',
15 },
16 litersToSeconds = 60,
17 },
18}
19
20Config.Durability = {}A bench type default can be added to either table by its ID:
1Config.Fuel['campfire'] = {
2 enabled = true,
3 max_fuel = 1800,
4 items = {
5 ['wood'] = { required = 1, amount = 300 },
6 ['charcoal'] = { required = 1, amount = 600 },
7 },
8}
9
10Config.Durability['campfire'] = {
11 enabled = true,
12 max_health = 72,
13 repair_items = {
14 ['steel'] = { required = 1, repair = 50 },
15 ['wood'] = { required = 3, repair = 25 },
16 },
17}Config.Fuel['<bench_type>']: fuel for that bench type.max_fuelis the capacity in seconds,itemslists each fuel item and the seconds it addsmlFuel.enabled: accepts refillable jerrycans. Any item withmetadata.fuelAmountandmetadata.fuelTypeworks. The item stays and only its fuel goes downmlFuel.hintItems: container items listed on the bench even when empty, so players know what to refillmlFuel.acceptedFuelTypes: fuel types the bench accepts. They must match the fuel types ofml_fuelmlFuel.typeLabels: label of each fuel typemlFuel.litersToSeconds: seconds of bench time per litermax_healthinConfig.Durability: hours of crafting before the station stops workingrepair_items: items that repair the station and the percentage each one restores
Each bench type also has a fuel mode in the panel: items only, jerrycans only, or both.
Base Building
These settings do nothing when Outpost (ml_base_building) is not running.
1Config.BaseBuilding = {
2 enabled = 'auto',
3 canPlaceOutsideBase = true,
4 permission = false,
5 blockDuringRaid = false,
6 whileLoading = 'deny',
7}
8
9Config.BaseMachines = {
10 Enabled = true,
11 Defaults = {
12 category = 'production',
13 model = 'xm3_prop_xm3_bench_04b',
14 stationModel = 'basemachine_toolbench',
15 tier = 2,
16 life = 6000.0,
17 bbox = vec3(1.6, 0.8, 1.0),
18 cost = { wood = 200, metal = 80 },
19 upkeep = { wood = 5 },
20 useRange = 3.0,
21 power = {
22 use = 900,
23 priority = 3,
24 offset = vec3(0.0, 0.0, 1.1),
25 maxConnections = 4,
26 },
27 },
28}enabled:'auto'follows the base rules when the base resource runs.truedoes the same and warns once if it is missing.falseturns it offcanPlaceOutsideBase:trueallows portable stations anywhere except inside another player's base.falseallows them only inside a base the player can build inpermission:falseaccepts any crew member in a base the player does not own.'canBuild'also needs the build permission of the crewblockDuringRaid:trueblocks placing inside a base under raidwhileLoading: answer while bases are still loading after a restart.'deny'makes the player retry,'allow'lets the placement throughBaseMachines: bench types can be built as machines inside a base. The base owns the prop and the crafting script runs the machine.Defaultsonly fills in the fields a bench type leaves empty in the panel: build cost, upkeep, health, size, use range and power use
Station Models
shared/config_models.lua holds the model presets offered when creating a bench. Each preset sets a bench prop, the screen placement and an optional camera.
1Config.StationModels = {
2 ["woodbench"] = {
3 Title = 'Wood Bench',
4 SpawnMode = 'bench_screen',
5 Bench = {
6 Model = 'prop_tool_bench02_ld',
7 },
8 Screen = {
9 Texture = 'script_rt_sturm1',
10 Offset = vec3(0.12, 0.01, 0.959),
11 Rotation = vec3(0.0, 0.0, 88.8),
12 Scale = 0.8,
13 },
14 Camera = {
15 OffsetX = 0.0,
16 OffsetY = -0.31,
17 OffsetZ = 0.7,
18 AimMode = 'lookat',
19 LookAtX = -0.01,
20 LookAtY = 0.0,
21 LookAtZ = 0.0,
22 Fov = 78.0,
23 },
24 },
25}SpawnMode:'screen_only'is a floating screen with no bench,'bench_only'draws the interface on a texture of the bench itself,'bench_screen'is a bench with a screen above itBench.Model: any prop modelScreen.Texture: texture the interface replaces.'script_rt_sturm1'on the shipped screen. For'bench_only', a texture of the bench modelScreen.Offset,Rotation,Scale: screen placement on the benchCamera: camera of this preset.nilusesConfig.Camera
The screen prop ships with the resource. New presets can also be built in game with the model builder of the admin panel, which saves them in the database.
Battlepass
1Config.Battlepass = { Enabled = true }Enabled: withml_battlepassrunning, finished crafts advance the battlepass objectives thatml_battlepassties to the recipe.falseturns it off. Withoutml_battlepassthis setting does nothing
Discord Webhooks
1Config.Webhooks = {
2 crafting = '',
3 craft_start = '',
4 craft_complete = '',
5 craft_failed = '',
6 craft_refund = '',
7 theft = '',
8 exploit = '',
9 admin_editor = '',
10 admin_bench = '',
11 admin_recipe = '',
12 admin_blueprint = '',
13 admin_import = '',
14}crafting: fallback channel of the four craft logs below when their own webhook is emptycraft_start,craft_complete,craft_failed,craft_refund: craft start, completion, failure and ingredient refundstheft: station thefts and queue stealsexploit: refused requests and distance violations. Denied admin actions go to the matching admin channel, or here when that one is emptyadmin_editor,admin_bench,admin_recipe,admin_blueprint,admin_import: admin panel changes, with before and after values
Leave a webhook empty to skip that log. Craft logs fall back to crafting first.