Skip to content

Frameworks

Detection is automatic. The framework is used for exactly two things: notifications, and resolving a player's job for the restricted column.

Everything else — favourites, key binds, the library, adjust mode, sitting, props — is framework-independent, because player identity comes from the steam identifier with a license fallback.

Detection order

OrderTestResult
0RM.Framework is not 'auto'That value is used verbatim, with no validation
1vorp_core is starting or startedvorp
2rsg-core is starting or startedrsg
3redem_roleplay is starting or startedredemrp
4None of the abovestandalone

Detection runs once, at script load

A core that starts after RedM Emotes is never re-detected, and the resource silently behaves as standalone for the rest of its lifetime — no job restrictions, and notifications in chat instead of your framework's notify.

ensure your framework before ensure rm_emotes, or set RM.Framework explicitly.

Both starting and started count, so a core mid-boot is detected correctly.

What actually differs

VORP CoreRSG CoreRedEM:RPStandalone
Detected byvorp_corersg-coreredem_roleplaynothing matched
Notificationvorp:TipRightRSGCore:Notifyredem_roleplay:Tipchat:addMessage
Job sourcecharacter .jobPlayerData.job.nameGetJob(), else .jobnone — ACE only
Re-sync on character loadclientclient and serverservernone — pulls once at start
Extra server.cfg linesnonenonenonenone

That is the complete list. There is nothing else.

VORP Core

cfg
ensure oxmysql
ensure vorp_core
ensure rm_emotes

add_ace group.admin rm_emotes.admin allow

config.lua can stay untouched — RM.Framework = 'auto' detects it, notifications use vorp:TipRight, and favourites sync on vorp:SelectedCharacter.

Restricted emotes: put a VORP job name (e.g. sheriff) or an ACE in the emote's Restriction field.

Keep RM.Showcase.clonePlayer = false

That is the shipped default and it should stay that way. RedM cannot clone a component-built mp_male / mp_female character cleanly — the mannequin renders as detached clothing. The configured RM.Showcase.models are used instead, picked by character gender.

The same applies to RM.Adjust.ghostClone.

RSG Core

cfg
ensure oxmysql
ensure rsg-core
ensure rm_emotes

add_ace group.admin rm_emotes.admin allow

Notifications use RSGCore:Notify, which is the one pipe that receives the error / primary kind. Favourites sync on RSGCore:Client:OnPlayerLoaded and RSGCore:Server:OnPlayerLoaded.

Servers without Steam are handled — identity falls back to the license: identifier, so favourites and key binds persist either way.

Restricted emotes: use the job name as it appears in PlayerData.job.name, not the label. vallaw, not "Valentine Law".

If your admins are managed through RSG groups rather than cfg ACEs, grant the editor per identifier:

cfg
add_ace identifier.license:xxxxxxxxxxxxxxxxxxxx rm_emotes.admin allow

RedEM:RP

cfg
ensure oxmysql
ensure redem_roleplay
ensure rm_emotes

add_ace group.admin rm_emotes.admin allow

oxmysql is still required

RedEM:RP has its own database layer, but RedM Emotes uses oxmysql regardless. It must be started even if nothing else on your server uses it. It can point at the same database.

Notifications use redem_roleplay:Tip. Favourites sync on the server-side redemrp:playerLoaded event, one second after it fires.

Restricted emotes: the job returned by GetJob(), falling back to .job.

Standalone

The only hard dependency is oxmysql.

cfg
ensure oxmysql
ensure rm_emotes

add_ace group.admin rm_emotes.admin allow

Everything works except job-based restrictions. The job lookup returns nothing, so restricted degrades to a pure ACE check. Express your access rules as ACE principals:

cfg
add_ace group.vip rm_emotes.vip allow
add_principal identifier.license:xxxxxxxxxxxxxxxxxxxx group.vip

Then put rm_emotes.vip in the emote's Restriction field.

Notifications are plain chat lines. Prefer silence, or your own system:

lua
RM.NotifyMode = 'none'   -- suppress entirely
RM.NotifyMode = 'ctrl'   -- route to a resource handling ctrl:cAvancedNotify

Favourites and key binds keep working — they key off the player's Steam or license identifier, not the framework.

No character-load hook fires

On an unknown or absent framework the client pulls once when the resource starts. If your setup has its own character-select step, trigger a re-pull yourself — see Developer API.

Running something else entirely

Anything not in the four lists above falls through to standalone behaviour without erroring. Set it explicitly rather than relying on the fallback:

lua
RM.Framework  = 'standalone'
RM.NotifyMode = 'ctrl'

RM.Framework is not validated — an unrecognised string behaves exactly like standalone except for the string itself.

Adding a real bridge

A genuine fifth framework means editing RMBridge.jobOf in server/framework.lua and RMBridge.notify in client/framework.lua. Those files are encrypted in the escrow edition, so this is only possible on the Open Source edition.

Escrow customers are limited to the RM.Framework and RM.NotifyMode values above, plus ACE-based restrictions — which, since ACE works identically on all four setups, covers most of what job restrictions would have given you.

The notification contract

RM.NotifyMode picks the pipe. 'ctrl' is the one that hands you the full payload:

ModeTriggersGets titleGets kind
vorpvorp:TipRight(message, 3000)nono
rsgRSGCore:Notify(message, 'error'|'primary', 3000)noyes
redemrpredem_roleplay:Tip(message, 3000)nono
ctrlctrl:cAvancedNotify(kind, title, message, 3000)yesyes
nonenothing
text or anything unknownchat:addMessage({ args = { title, message } })yesno
lua
-- my_notify/client.lua
-- kind is 'default' or 'error'; duration is always 3000 ms
AddEventHandler('ctrl:cAvancedNotify', function(kind, title, message, duration)
    MyNotify(title, message, kind == 'error' and 'error' or 'info', duration)
end)

The duration is hard-coded on every branch. Several strings bypass the locale system and stay English regardless of RM.Lang: the /e and /adjustanim chat suggestions, the preview-model failure notice, and the key-binding label "RM Emotes: toggle adjust gizmo" shown in the RedM key settings. See Languages for the full list.

Troubleshooting detection

Notifications appear as chat lines on a framework server. Detection fell through to standalone because your core started after RedM Emotes. Fix the ensure order, or set RM.Framework and RM.NotifyMode explicitly.

Job-restricted emotes are invisible to everyone, including the right job. Either the same detection failure, or the job string does not match exactly — the comparison is case-sensitive. Check the order first, then compare against the exact name your framework returns.

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