🤠 Wild Country Libs
Example

Tax Collection Example

A complete wc_taxman resource — a server-only scheduled sweep that takes a small cut of cash from every online player on an interval, skips anyone who can't afford it, and posts a summary to Discord. No client script needed at all.

Use this pattern for any periodic server-side job: property upkeep, gang dues, business taxes, or a "wealth tax" event. The shape is always the same — loop connected players, read money, remove money, notify, log.

fxmanifest.lua

wc_taxman/fxmanifest.lua
fx_version 'adamant'
game 'rdr3'
lua54 'yes'

name 'wc_taxman'
dependency 'wc_libs'

shared_scripts { '@wc_libs/init.lua', 'config.lua' }
server_scripts { 'server.lua' }

config.lua

wc_taxman/config.lua
Config = {}
Config.IntervalMs   = 30 * 60000  -- every 30 minutes
Config.Rate         = 0.02       -- 2% of on-hand cash
Config.MinBalance   = 20         -- don't tax players below this
Config.WebhookUrl   = GetConvar('wc_taxman_webhook', '')

server.lua

wc_taxman/server.lua
local function runTaxSweep()
  local collected  = 0
  local taxedCount = 0

  for _, pid in ipairs(GetPlayers()) do
    local src = tonumber(pid)
    if src then
      local cash = wc:GetMoney(src)
      if cash and cash >= Config.MinBalance then
        local owed = math.floor(cash * Config.Rate)
        if owed > 0 then
          wc:RemoveMoney(src, owed)
          wc:Notify(src, { variant = 'warning', title = ("Territory tax: -$%d"):format(owed) })
          collected  = collected + owed
          taxedCount = taxedCount + 1
        end
      end
    end
  end

  if taxedCount > 0 then
    -- SendWebhook expects a player source for the "who" fields; use the
    -- first taxed player as a nominal reporter, or write your own summary
    -- sender if you want a source-less system embed instead.
    print(('[wc_taxman] collected $%d from %d players'):format(collected, taxedCount))
  end
end

CreateThread(function()
  while true do
    Wait(Config.IntervalMs)
    runTaxSweep()
  end
end)
Security. This resource never reads a client-sent amount at all — it computes owed entirely from the server's own GetMoney read and Config.Rate. There's no client input to validate because there's no client script; that's the safest possible shape for a periodic system job.

Common mistakes