Install wc_libs
Three steps: drop the resource in, ensure it before anything that depends on it, optionally pin the framework. That's the whole setup.
1. Add the resource
Copy the wc_libs folder into your server's resources directory, alongside your other resources — not nested inside one of them.
resources/
├── [core]/
│ └── vorp_core/
├── [standalone]/
│ └── wc_libs/ ← here
└── [wc]/
├── wc_encounter/
└── wc_death/
2. Ensure it before dependent resources
wc_libs needs to start before any resource that uses it. Add it to your server.cfg ahead of everything else with a "wc_" prefix or anything else you plan to migrate.
ensure vorp_core
ensure wc_libs
ensure wc_encounter
ensure wc_death
wc:GetMoney(...) starts before wc_libs has finished initializing, the export won't resolve. Keep ensure wc_libs directly after your core framework and before anything that uses it.
3. Confirm it picked up your framework
On start, wc_libs auto-detects which core is running by checking for vorp_core or rsg-core as a started resource. Check your server console for a line like:
[wc_libs] server ready — framework: vorp — version: 1.0.0
[wc_libs] client ready — framework: vorp — version: 1.0.0
If you see NONE DETECTED instead, your core framework either isn't installed or started after wc_libs. Check your ensure order, or set the framework explicitly — see below.
Optional: force the framework
Auto-detection covers almost every setup. The one case it doesn't is running both cores side by side mid-migration — wc_libs will default to VORP and print a warning if it sees both. Override it explicitly in shared/config.lua:
-- leave as nil to auto-detect (the default)
WCLibConfig.ForceFramework = 'vorp' -- or 'rsg'
Calling wc_libs from your own resource
Add '@wc_libs/init.lua' to your resource's shared_scripts — that sets the wc shorthand global. Then call any wc_libs function as wc:FunctionName(...), same syntax on client and server.
shared_scripts {
'@wc_libs/init.lua',
'config.lua',
}
local money = wc:GetMoney(source)
wc:AddMoney(source, 50)
wc:Notify(source, { title = "+$50" })
local prompt = wc:CreatePrompt("Talk [G]")
wc:SetPromptVisible(prompt, true)
wc is a live proxy. init.lua sets wc = exports['wc_libs'] — it resolves at call time, not load time, so it works correctly on both client and server without any extra setup.
Common patterns
A handful of shapes show up in nearly every Green Studio resource built on wc_libs. Recognizing them makes new resources fast to write and easy for teammates to review.
-- client: only requests the action
TriggerServerEvent('my_resource:start')
-- server: validates and owns the outcome
RegisterNetEvent('my_resource:start', function()
local src = source
if ActiveJobs[src] then return end -- reject double-starts
ActiveJobs[src] = { reward = 50 } -- server decides the reward, never the client
end)
if wc:GetMoney(source) < price then
wc:Notify(source, { variant = 'fail', title = "Not enough cash." })
return
end
wc:RemoveMoney(source, price)
wc:Notify(source, { variant = 'avanced', title = "Purchased!" })
local bag = wc:CreateCleanupBag()
bag:AddPed(wc:SpawnPed(hash, x, y, z))
bag:AddPrompt(wc:CreatePrompt("Talk [G]"))
-- ... on every exit path (success, timeout, resource stop):
bag:Clean()