🤠 Wild Country Libs
Guide

VORP And RSG Compatibility

wc_libs exists so your resource calls wc:AddMoney(source, 50) once and it works on both frameworks — no if framework == 'vorp' branches scattered through your code. This page explains exactly what's normalized, what's asymmetric on purpose, and what genuinely has no equivalent on one side.

How normalization works

Every module is split into a public function (in server/modules/*.lua or client/modules/*.lua) and an adapter (in server/adapters/vorp.lua/rsg.lua or the client equivalents). The public function never contains framework-specific code — it just calls whichever adapter server/init.lua/client/init.lua wired up after detecting the running core. All the VORP/RSG differences live in exactly two files per side.

your resource — identical on both frameworks
wc:AddMoney(source, 50, 0)
wc:Notify(source, { title = "+$50" })

Fully normalized — safe to use identically on both

AreaNotes
Player / character / jobGetPlayer, GetCharacter, GetJob return the same table shape on both.
Money reads/writesGetMoney, AddMoney, RemoveMoney — cash works identically; see the asymmetric section below for gold/bank.
InventoryGetItemCount, HasItem, CanCarryItem, AddItem, RemoveItem return the same boolean/number shapes on both.
CallbacksRegisterCallback/TriggerCallback — same namespacing and signature on both, despite very different underlying APIs (VORP promises vs RSG callback functions).
Lifecycle — player loadedOnPlayerLoaded fires reliably on both.
Webhook, nearby players, battlepassFramework-agnostic by construction — pure FiveM natives or pcall-guarded external exports.

Asymmetric by design — works on both, looks different

AreaWhat differs
NotifyVORP gets all 17 native visual styles. RSG collapses every style to ox_lib's inform/success/error types. Both show a notification — they just don't look identical.
Revive / HealNative on VORP. On RSG, delegates to a configurable ambulance job export — no-ops with a console warning if that resource isn't running.
SkillsVORP-only. RSG has no skill system at all — calls return safe defaults and log a warning rather than erroring.

Genuine gaps — no confirmed equivalent

FunctionGap
GetBankMoneyWarns + returns nil on VORP — VORP has no bank currency (money/gold/rol only).
GetGoldWarns + returns 0 on RSG unless WCLibConfig.Money.rsg.gold is configured — RSG has no native gold currency.
OnPlayerUnloadFires reliably on RSG. Registers but never fires on VORP — no confirmed dedicated server-side "unload" event exists. Use AddEventHandler('playerDropped', ...) on VORP instead.
OnJobUpdateFires on VORP via vorp:playerJobChange. No confirmed server-side equivalent on RSG — registers but never fires there.

Writing code that targets both frameworks

Use Framework.Is only for the genuine gaps above — not for things wc_libs already normalizes.

correct — guard only the real gap
-- Skills is VORP-only, so this guard is necessary:
if wc:Framework_Is('vorp') then
  wc:ApplySkillBonus(source, 'trading', 15)
end
wrong — unnecessary, AddMoney already works on both
if wc:Framework_Is('vorp') then
  wc:AddMoney(source, 50, 0)
else
  wc:AddMoney(source, 50, 'cash') -- unnecessary — AddMoney already defaults to cash on both
end

Escape hatch when wc_libs doesn't cover something yet

Reach past the bridge with WCLib.Raw.VORP()/WCLib.Raw.RSG() for a one-off. If you find yourself doing it more than once or twice for the same thing, wrap it in _custom/ instead so every resource gets the clean version.

Current limitation. Raw.VORP()/Raw.RSG() aren't exported to other resources in the current build — only usable from _custom/client.lua/_custom/server.lua, which load inside wc_libs' own Lua state. See the full explanation on the Framework & Raw page.

Common mistakes