Player & Character
Read player data without caring whether it lives on a VORP character object or an RSG PlayerData table. Always call these fresh — never cache the result across a Wait() or a new thread.
Returns a flat snapshot table of player data. Built fresh on every call.
| Param | Type | Description |
|---|---|---|
| source | integer | The player's server ID. |
Returns nil if the player isn't loaded yet. Otherwise:
{
source = 1,
charid = "ABC123",
firstname = "John",
lastname = "Marston",
job = {
name = "marshal",
label = "Marshal",
grade = 1,
onduty = true, -- nil on VORP, see note below
},
money = 250.0,
gold = 0, -- always nil on RSG
rol = 0, -- always nil on RSG
xp = 1200, -- always nil on RSG
age = 34,
gender = "male",
group = "user",
}
local user = Core.getUser(source)
local ch = user.getUsedCharacter
-- ch.money, ch.gold, ch.rol, ch.job, ch.jobLabel, ch.jobGrade ...
local Player = RSGCore.Functions.GetPlayer(source)
local pd = Player.PlayerData
-- pd.money.cash, pd.job.name, pd.job.label, pd.job.grade.level ...
job.onduty is always nil on VORP. It works correctly on RSG. If your VORP server tracks duty separately, wire it in via _custom/server.lua.
Returns the raw underlying character/player object for whichever framework is active — VORP's character, RSG's Player.
Use this when you need to call a framework-native method that GetPlayer()'s flat table doesn't expose — for example VORP's character.setSkills(...). This is the exact object server.lua and webhook.lua in wc_encounter used to resolve by hand, twice, with duplicated logic. wc_libs does it once.
| Param | Type | Description |
|---|---|---|
| source | integer | The player's server ID. |
local function getCharacter(src)
local user = VorpCore.getUser(src)
if not user then return nil end
local c = user.getUsedCharacter
if type(c) == "function" then c = c(user) end
return c
end
local ch = wc:GetCharacter(source)
Returns just the job slice of player data.
| Param | Type | Description |
|---|---|---|
| source | integer | The player's server ID. |
{
name = "marshal",
label = "Marshal",
grade = 1,
onduty = true,
}
local job = wc:GetJob(source)
if job and job.name == "bandit" then
return -- bandits don't get roadside encounters
end
Real Wild County example — job-gated trader access
wc_trader uses GetJob on every open-shop request to decide whether a player is allowed to see trader-only stock (e.g. a fence buying stolen goods only from the "outlaw" job), instead of trusting a client-sent flag.
RegisterNetEvent('wc_trader:openFence', function()
local src = source
local job = wc:GetJob(src)
if not job or job.name ~= 'outlaw' then
wc:Notify(src, { variant = 'fail', title = "The fence doesn't trust you." })
return
end
TriggerClientEvent('wc_trader:showFenceMenu', src)
end)
Common mistakes
- Caching
wc:GetPlayer(source)in a variable and reusing it across aWait()or the next player tick — always fetch fresh right before you use it. - Reading
job.ondutyon a VORP server and assuming it works — it's alwaysnilon VORP (see the note above). Track duty yourself if you need it there. - Calling
GetPlayer/GetJobfrom the client — these are server-only. Use a callback (see Callbacks) to ask the server instead. - Assuming
gold,rol, orxpare populated on RSG — they're alwaysnilthere by design, not a bug.
Troubleshooting
- If
GetPlayer/GetJobreturnsnil: the player probably hasn't finished character selection yet — call this from insideOnPlayerLoaded, not on connect. - If every field comes back
nil: check the server console for[wc_libs] server ready — framework: NONE DETECTED— that means neithervorp_corenorrsg-corewas running when wc_libs started. - If
job.gradeis missing on RSG: confirm the job actually has grades configured in your RSG job data — a job with no grade table returnsnilhere, not0.