Skip to content

RedM Phonograph Configuration ​

Everything a server owner touches lives in config/. Four files:

FileWhat it holds
settings.luaBehaviour, keys, audio, access, limits, webhooks
cabinets.luaThe carryable phonograph models
spots.luaCabinets bolted to the map
records.luaThe record catalogue

All four stay editable in the escrowed package.

settings.lua ​

General ​

SettingDefaultMeaning
language'en'Locale code; must match a file in locales/ (en, de, es, fr, it, pt)
framework'auto''auto' sniffs vorp_core → rsg-core → redem_roleplay, else standalone. Or pin one: 'vorp', 'rsg', 'redem', 'standalone'
standalone.placeCommand'phonograph'With no usable-item system, /phonograph starts placement instead
debug.enabledfalseVerbose console tracing
debug.log{}Silence one channel while debugging, e.g. { mixer = false }

Notifications — bridge ​

SettingDefaultMeaning
notice'builtin''builtin' = the resource's own themed toasts; 'framework' = hand off to your framework's notification; 'off' = silence
noticeTime3500Toast duration in milliseconds

Keys — keys ​

Control hashes. Defaults:

KeyDefault inputUsed for
tune[R]Open the deck panel
pack[Backspace] (hold)Pick a placed cabinet up
affirm[R] (hold)Placement: set it down
abort[Backspace]Placement: put it away
swingL / swingRArrow keysPlacement: rotate

Placement — placing ​

SettingDefaultMeaning
reach1.3Metres in front of the player the ghost sits
step1.5Degrees of rotation per frame while a swing key is held
alpha160Ghost transparency (0–255)
holdMs750How long the confirm key must be held

World streaming — world ​

SettingDefaultMeaning
streamSpan40.0Metres at which cabinet props appear
touchSpan2.0Metres at which the prompts light up
scanMs500Slow world-scan interval, in ms

Audio — audio ​

SettingDefaultMeaning
range15.0Metres at which a track fades to silence
defaultVolume0.40–1, starting volume of a fresh track
rolloff1.4Above 1 hugs the cabinet, below 1 carries further
maxUrl300Longest link the server accepts
crackle.enabledtrueProcedural vinyl-crackle bed, generated in the overlay — no file
crackle.level0.350–1, relative to the track's own volume; 0 disables

Access — access ​

SettingDefaultMeaning
ownerOnlyfalseWhen true, a player-placed cabinet obeys only its owner (and staff)
admins{}Character identifiers that count as staff everywhere
aceFlag'rm_phonograph.admin'Holders of this ace are staff too
reachSpan4.0Server-side arm's length for every action
packBlockSpan5.0Another player this close blocks a pickup

Who may paste a raw link into the panel. Catalogue records are always available to anyone the deck answers to — this gate is only for arbitrary URLs.

ValueMeaning
'everyone'Any player the deck answers to
'owners' (default)The deck's owner; for map spots, whoever the spot's access names — so a public 'none' spot becomes records-only
'staff'Staff only

Panel sections — panel ​

SettingDefaultMeaning
shelftrueShow the record shelf. When false, record items also refuse to play — enforced server-side
urlBoxtrueShow the link box. When false, no link is accepted from anyone, staff included

Limits — limits ​

SettingDefaultMeaning
queueCap8Tracks a deck's queue holds
queuePerPlayer3How many of those one player may own
playCooldownMs4000Between play/queue requests per player; staff exempt
maxTrackMinutes0Auto-advance after this much played time — pauses don't count. 0 = off
domains{}Allowed URL hosts; empty = any. e.g. { 'youtube.com', 'youtu.be' } — subdomains match automatically

Discord webhooks — audit ​

Shipped off. Fill a url and flip enabled per channel:

ChannelFires on
decksA cabinet placed or packed up
tracksA track played or queued — includes who, the resolved title, and the video thumbnail

Treat webhook URLs as secrets

Anyone holding the URL can post to that channel. Redact them before sharing a config.

cabinets.lua ​

The cabinets players can carry, keyed by name.

lua
brass = {
    item  = 'phonograph',    -- inventory item that plants one
    label = 'Phonograph',    -- shown on prompts and the panel
    prop  = 'p_phonograph01x',
    carry = {                -- how the prop rides the hand while carried
        bone = 'XH_R_Hand01',
        pos  = { x = 0.30, y = -0.04, z = -0.31 },
        rot  = { x = -239.0, y = 13.0, z = 217.0 },
    },
},

The key is what the database stores

Renaming a cabinet orphans every deck already placed with it. Orphaned rows are kept and reported at boot, never deleted — but treat keys as permanent once players have placed cabinets.

Add more cabinets with different props and items; each needs its own usable item registered in your framework.

spots.lua ​

Cabinets bolted to the map. They exist without anyone placing them and cannot be packed up.

lua
valentine_saloon = {
    cabinet = 'brass',
    access  = 'none',
    pos     = vector3(-817.682, -1392.679, 43.345),
    rot     = vector3(0.0, 0.0, -111.448),
},

access values:

ValueMeaning
'none'Anyone may use the deck
'ABCD1234...'One character identifier
{ 'saloon', 'bartender' }A list of jobs

This interacts with records.urlAccess

With the default urlAccess = 'owners', a 'none' spot is usable by everyone but accepts no raw links from non-staff — while a spot with an access list treats those people as its owners, and they can.

records.lua ​

The record catalogue. Each key is an inventory item; the deck shows the ones in the player's bags as sleeves on a shelf.

lua
record_camptown = {
    label  = 'Camptown Races',   -- on the sleeve and while playing
    artist = 'Stephen Foster',   -- optional second line
    url    = 'https://...',      -- YouTube link or direct audio file
},
  • The URL is read from this table on the server — never from the client — so records cannot be forged.
  • An entry with an empty url is skipped and named in the server console at boot.
  • To add your own: create the item in your framework, add an entry here, and drop a matching <item_name>.png into your inventory's image folder.

Documentation for RedMorrow. Scripts are licensed per server — redistribution is not permitted.