RedM Crayfish Configuration
Everything is in config/. Do not edit those files.
Put your changes in local/overrides.lua instead. They are folded over the defaults at load, which means you can drop a new version of the resource over the top of your server and not lose a single setting. Edits to config/ are overwritten by the next update.
-- local/overrides.lua
RmCrayfish.Local = {
language = 'de',
respawn = { day = 20, night = 12 },
}Only name what you are changing. Everything you leave out keeps the shipped value.
Three rules worth knowing before you start:
- Lists are replaced, not merged. A two-entry
lureslist gives you two lures, not two plus the nine you did not mention. - An empty table clears.
bonus = {}means "no extra drops", not "change nothing about the extra drops". - Turn debug on to check your work. With
debug = { enabled = true }the console prints every setting your overrides actually changed at start-up, so an override that quietly failed is visible rather than something you discover three weeks later.
The settings you will actually change
Making beds easier to reach
reach is the interaction radius in metres — how close a player stands before the prompt appears.
RmCrayfish.Local = {
bedDefaults = { reach = 3.5 },
}2.5 is shipped. The closest two beds are 9.65m apart, so anything up to about 4.8 is safe — past half the distance between two beds their radii overlap. The client picks the nearest bed in that case so it still behaves, but the prompt starts appearing further from its hole than looks right.
bedDefaults reaches all 43 beds at once. A bed that names the same field in config/beds.lua still wins over it.
How often crayfish appear
Three separate things control this, and they multiply:
| Where | What it does | |
|---|---|---|
seed | per bed | Whether the bed exists at all this server session. Rolled once at start-up. |
odds.day / odds.night | per bed | Whether something is sitting in it. Re-rolled on the clock. |
odds | per lure | Whether your bait works. |
So a player walking up to a bed in daylight with corn faces 45% × 3% = 1.4%.
People forget the first two gates and set the lure odds far too low
See balancing below.
Respawn and cooldown
RmCrayfish.Local = {
respawn = { day = 28, night = 20 }, -- minutes between stocking passes
bedDefaults = { rest = 120 }, -- minutes a worked bed rests
}rest is the real supply cap. With ~33 beds and a two-hour rest, no amount of grinding produces more than about 33 crayfish every two hours server-wide, whatever the lure odds are.
Set rest = false to make a bed one-shot for the whole session.
Balancing
The two levers do different jobs, and this is the part worth getting right.
Lure odds control cost — how many lures burn per crayfish. At 10%, that is about ten pieces of meat each.
Cooldown and bed count control the ceiling — how many exist per hour no matter how hard anyone grinds.
If you want crayfish scarce, use the ceiling, not the failure rate. Low odds do not stop a determined player; they hunt more meat and keep going. What low odds reliably produce is nine dud animations in a row, which is how a feature gets a reputation for being broken.
Rough yields for one player working ~30 beds in an hour:
| Lure odds | Night | Day |
|---|---|---|
| 100 / 50 / 30 | ~30/hr | ~13/hr |
| 65 / 35 / 18 | ~19/hr | ~9/hr |
| 30 / 15 / 8 | ~9/hr | ~4/hr |
| 10 / 5 / 3 | ~3/hr | ~1.4/hr |
A balanced starting point, with scarcity coming from the cooldown:
RmCrayfish.Local = {
lures = {
{ item = 'meat', label = 'Raw Meat', odds = 65 },
{ item = 'biggame', label = 'Big Game Meat', odds = 65 },
{ item = 'bison_meat', label = 'Bison Meat', odds = 65 },
{ item = 'chicken_meat', label = 'Chicken Meat', odds = 65 },
{ item = 'birdmeat', label = 'Bird Meat', odds = 65 },
{ item = 'spoiled_biggame_meat', label = 'Spoiled Big Game Meat', odds = 35 },
{ item = 'spoiled_bison_meat', label = 'Spoiled Bison Meat', odds = 35 },
{ item = 'spoiled_meat', label = 'Spoiled Meat', odds = 35 },
{ item = 'corn', label = 'Corn', odds = 18 },
{ item = 'consumable_bread', label = 'Bread Piece', odds = 18 },
{ item = 'potato', label = 'Potatoes', odds = 18 },
},
bedDefaults = { rest = 180 },
}The whole lure list has to be present because lists replace rather than merge.
- Crayfish are a cheap cooking ingredient? 80 / 50 / 25 and
rest = 60. - Crayfish are a valuable trade good? Keep 65 / 35 / 18 and
rest = 240.
Full reference
Framework
bridge = {
framework = 'auto', -- auto | vorp | rsg | redemrp | standalone
notice = 'builtin', -- builtin | framework | ox | off
noticeMs = 3500,
rpcTimeoutMs = 10000,
itemAliases = {},
}framework | auto takes the first of vorp, rsg, redemrp whose resource is running, else standalone. Pin it if you would rather it did not guess. |
notice | Where short lines are drawn. builtin is this resource's own overlay and needs nothing installed. |
noticeMs | How long a notice stays up, in milliseconds. 3500 is three and a half seconds. |
rpcTimeoutMs | How long a client waits for the server, in milliseconds. Not a knob worth tuning — anything under a second means every request gives up before its answer can arrive. |
itemAliases | Map the names in config/ to whatever your item table calls them, e.g. { p_crawdad01x = 'crawdad' }. |
Interaction
prompt = { control = 0x760A9C6F, holdMs = 1000 },
approach = 5.0,
solitude = { enabled = true, span = 3.0 },prompt.control | The key hash. holdMs is how long it must be held. |
approach | How far out the world loop wakes up. Not the interaction radius — that is reach. Raised automatically if a bed's reach exceeds it. |
solitude | Refuse a bed while another player is within span metres, so two people cannot race one hole. |
Streaming
stream = {
span = 50.0,
mounds = { 'mp005_p_dirtpile_sca02_unburied' },
marker = { enabled = true, span = 20.0 },
},span is where dirt piles fade in. marker.span is where the map blip appears. Extra dirt-pile variants are commented out in config/settings.lua — uncomment any you want in the rotation.
The harvest
harvest = {
seconds = 5, -- length of the on-screen meter
graceSeconds = 15, -- slack before the server voids an unclaimed ticket
},World clock
clock = { dawn = 6, dusk = 20, refreshSeconds = 60 },
respawn = { day = 28, night = 20 },Night runs from dusk to dawn and wraps past midnight, so 20/6 means 20:00–05:59.
Staff
admin = {
enabled = true,
groups = { 'admin' },
ace = 'rm_crayfish.staff',
},Both are checked, and either passing is enough. The server console always passes. See Commands.
Discord
audit = {
username = 'rm_crayfish',
channels = {
abuse = { enabled = false, url = '', colour = 10038562 },
harvest = { enabled = false, url = '', colour = 3066993 },
},
},abuse logs refused requests, harvest logs successful catches. Both off until you fill in a URL.
Weather
weather = { enabled = false, rejected = { 'THUNDER', 'STORM', 'SNOW' } },Optional, needs the weathersync resource. While the weather is on the list, every bed refuses to open.
Beds
config/beds.lua. Each bed is { x, y, z, <overrides> } — anything you leave out falls back to BedDefaults, so a bare { x, y, z } is complete.
| Field | |
|---|---|
reach | Interaction radius in metres |
seed | Percent chance the bed exists this session |
odds | { day = 45, night = 100 } — chance something is in it |
rest | Cooldown in minutes after a pull; false for one-shot |
yield | Item given on a successful pull |
bonus | Extra rolled drops |
requiresLure | false lets players reach in bare-handed at 100% |
mound | true drops a dirt-pile prop so the bed can be found |
Extra drops:
bonus = {
{ item = 'moss', label = 'River Moss', min = 0, max = 2 },
},Adding your own beds is covered in Commands — /crayfish_here prints the line to paste.
Languages
en de es fr ja nl ru
RmCrayfish.Local = { language = 'fr' },Add one by copying locales/en.lua to locales/<code>.lua and translating the right-hand side, leaving the keys alone. A key you miss falls back to English rather than showing a raw key, and an unknown language code falls back to English with a console warning.
One caveat worth knowing
The client picks phrases per player, but the server writes the reward line and has to choose a single language for it. If your players do not all read the same one, set bridge.notice = 'off' and the overlay phrases it client-side instead.
Debugging
Set debug.enabled = true in local/overrides.lua and restart. Channels can be silenced individually in debug.log.
With it on, the merge also prints every config path your overrides actually changed — so an override that quietly failed to apply is visible rather than something you find out about weeks later.
guards.verbose is separate and on by default: it prints refused requests to the server console whether or not the Discord webhook is configured.
guards.slack is metres of tolerance over a bed's reach when the server checks how far away the asking player is. Lower it and players on a bad connection start getting refused; raise it and you widen the window for reaching a hole from further away than it looks.