Reputation System
Complete guide to the RSG Framework flexible reputation tracking system
Introduction
The RSG Framework includes a built-in reputation system that allows you to track player progress, achievements, and standing across various activities. The system is completely flexible - you can create any reputation types you need for your server, from hunting skills to lawman standing.
Version: 2.3.6+
Reputation is stored in player metadata and persists across sessions. Create unlimited custom reputation types!
Core Features
Flexible Reputation Types
- Unlimited Types: Create any reputation categories you need
- Server-Specific: Define reputations that fit your gameplay
- Persistent Storage: Saved in player metadata (database)
- Integer-Based: Whole numbers from 0 to unlimited
Simple API
- Add Reputation: Increase reputation points
- Remove Reputation: Decrease reputation points (minimum 0)
- Get Reputation: Check current reputation level
- No Maximum: Reputation can grow indefinitely
Common Use Cases
- Skill Tracking: hunting, fishing, crafting, mining
- Faction Standing: lawman, outlaw, trader reputation
- Activity Progress: deliveries, arrests, bounties
- Social Standing: town reputations, gang loyalty
- Achievement Systems: milestones and progression
How It Works
Reputation Storage
Reputation is stored in PlayerData.metadata.rep as a key-value table:
PlayerData.metadata = {
-- ... other metadata
rep = {
hunting = 150,
fishing = 75,
lawman = 200,
outlaw = 0,
crafting = 50,
trading = 100
-- Add any custom types
}
}Reputation Structure
-- Reputation table structure
metadata.rep = {
[reputationType] = points -- Integer value (0+)
}
-- Examples:
metadata.rep.hunting = 150 -- 150 hunting reputation
metadata.rep.fishing = 75 -- 75 fishing reputation
metadata.rep.blacksmith = 200 -- 200 blacksmith reputationData Flow
┌─────────────────────┐
│ Player Action │
│ (Hunt animal) │
└──────────┬──────────┘
│
▼
┌─────────────────────┐
│ Server Event │
│ AddRep('hunting') │
└──────────┬──────────┘
│
▼
┌─────────────────────┐
│ Metadata Updated │
│ rep.hunting += 10 │
└──────────┬──────────┘
│
▼
┌─────────────────────┐
│ Database Save │
│ (auto every 5min) │
└─────────────────────┘Player Reputation Functions
Add Reputation
Add reputation points to a specific type.
Player.Functions.AddRep(rep, amount)Parameters:
rep(string) - Reputation type nameamount(number) - Points to add
Example:
-- SERVER SIDE
local Player = RSGCore.Functions.GetPlayer(source)
-- Add hunting reputation
Player.Functions.AddRep('hunting', 10)
-- Add fishing reputation
Player.Functions.AddRep('fishing', 5)
-- Add custom reputation
Player.Functions.AddRep('blacksmith', 15)
Player.Functions.AddRep('doctor', 20)Reputation types are created automatically when first used. No need to pre-define them!
Remove Reputation
Remove reputation points from a specific type.
Player.Functions.RemoveRep(rep, amount)Parameters:
rep(string) - Reputation type nameamount(number) - Points to remove
Example:
-- SERVER SIDE
local Player = RSGCore.Functions.GetPlayer(source)
-- Remove hunting reputation (penalty for poaching)
Player.Functions.RemoveRep('hunting', 25)
-- Remove lawman reputation (caught breaking law)
Player.Functions.RemoveRep('lawman', 50)Reputation cannot go below 0. If you try to remove more than available, it will be set to 0.
Behavior:
-- Player has 30 lawman reputation
Player.Functions.RemoveRep('lawman', 50)
-- Result: lawman reputation = 0 (not -20)
-- Player has 100 hunting reputation
Player.Functions.RemoveRep('hunting', 25)
-- Result: hunting reputation = 75Get Reputation
Get the current reputation points for a specific type.
Player.Functions.GetRep(rep)Parameters:
rep(string) - Reputation type name
Returns:
number- Current reputation points (returns 0 if type doesn't exist)
Example:
-- SERVER SIDE
local Player = RSGCore.Functions.GetPlayer(source)
-- Get hunting reputation
local huntingRep = Player.Functions.GetRep('hunting')
print('Player has '.. huntingRep ..' hunting reputation')
-- Check if player meets requirement
local requiredRep = 100
if Player.Functions.GetRep('fishing') >= requiredRep then
print('Player is a master fisherman!')
end
-- Get non-existent reputation type
local unknownRep = Player.Functions.GetRep('nonexistent')
-- Returns: 0 (safe to use without checks)Common Reputation Types
Skill-Based Reputations
Track player proficiency in various activities:
-- Gathering/Harvesting
'hunting' -- Hunting animals, tracking, pelts
'fishing' -- Fishing, legendary fish
'mining' -- Mining ore, finding gems
'herbalism' -- Gathering herbs, plants
'foraging' -- Collecting materials
-- Crafting/Production
'crafting' -- General crafting
'blacksmith' -- Metalworking, weapon repair
'cooking' -- Food preparation
'leatherwork' -- Working with pelts/leather
'alchemy' -- Potion/medicine making
-- Combat/Skills
'marksmanship' -- Shooting accuracy
'melee' -- Close combat
'horsemanship' -- Horse handling
'stealth' -- Sneaking, pickpocketingFaction/Standing Reputations
Track relationships with groups:
-- Law Enforcement
'lawman' -- Standing with law enforcement
'bounty_hunter' -- Bounty hunting reputation
'detective' -- Investigation work
-- Criminal
'outlaw' -- Criminal reputation
'gang_loyalty' -- Gang standing
'smuggler' -- Smuggling operations
'thief' -- Theft reputation
-- Towns/Regions
'valentine' -- Valentine town reputation
'rhodes' -- Rhodes town reputation
'saint_denis' -- Saint Denis reputation
'blackwater' -- Blackwater reputation
-- Professions
'trader' -- Trading reputation
'doctor' -- Medical reputation
'rancher' -- Ranching reputationImplementation Examples
Example 1: Hunting Reputation System
-- SERVER SIDE
-- Award reputation based on pelt quality
RegisterNetEvent('hunting:server:sellPelt', function(peltType, quality)
local src = source
local Player = RSGCore.Functions.GetPlayer(src)
if not Player then return end
local repGain = 0
local basePrice = 10
-- Quality affects reputation gain
if quality == 'perfect' then
repGain = 5
basePrice = basePrice * 1.5
elseif quality == 'good' then
repGain = 3
basePrice = basePrice * 1.2
elseif quality == 'poor' then
repGain = 1
basePrice = basePrice * 0.8
end
-- Get current hunting reputation
local huntingRep = Player.Functions.GetRep('hunting')
-- Bonus payment based on reputation
local repBonus = math.floor(huntingRep / 10) -- 1% per 10 rep
local finalPrice = math.floor(basePrice * (1 + repBonus / 100))
-- Award money and reputation
Player.Functions.AddMoney('cash', finalPrice, 'pelt-sale')
Player.Functions.AddRep('hunting', repGain)
-- Check for reputation milestones
local newRep = Player.Functions.GetRep('hunting')
if newRep >= 100 and huntingRep < 100 then
TriggerClientEvent('ox_lib:notify', src, {
title = 'Master Hunter',
description = 'You have become a Master Hunter!',
type = 'success',
duration = 10000
})
end
TriggerClientEvent('ox_lib:notify', src, {
description = 'Sold '.. quality ..' pelt for $'.. finalPrice ..' (+' .. repGain ..' hunting rep)',
type = 'success'
})
end)Example 2: Lawman vs Outlaw System
-- SERVER SIDE
-- Arrest increases lawman rep, decreases outlaw rep
RegisterNetEvent('police:server:arrestPlayer', function(targetId)
local src = source
local Officer = RSGCore.Functions.GetPlayer(src)
local Criminal = RSGCore.Functions.GetPlayer(targetId)
if not Officer or not Criminal then return end
-- Check officer is law enforcement
if Officer.PlayerData.job.type ~= 'leo' then return end
-- Award lawman reputation to officer
Officer.Functions.AddRep('lawman', 10)
-- Reduce outlaw reputation for criminal
Criminal.Functions.RemoveRep('outlaw', 25)
-- Check officer's reputation tier
local lawmanRep = Officer.Functions.GetRep('lawman')
local tier = GetReputationTier(lawmanRep)
TriggerClientEvent('ox_lib:notify', src, {
description = 'Arrested criminal (+10 lawman rep) - '.. tier,
type = 'success'
})
end)
-- Crime increases outlaw rep, decreases lawman rep
RegisterNetEvent('crime:server:commitCrime', function(crimeType)
local src = source
local Player = RSGCore.Functions.GetPlayer(src)
if not Player then return end
local outlawGain = 0
if crimeType == 'robbery' then
outlawGain = 15
elseif crimeType == 'murder' then
outlawGain = 25
elseif crimeType == 'theft' then
outlawGain = 5
end
-- Increase outlaw reputation
Player.Functions.AddRep('outlaw', outlawGain)
-- Decrease lawman reputation
Player.Functions.RemoveRep('lawman', outlawGain * 2)
TriggerClientEvent('ox_lib:notify', src, {
description = 'Crime committed (+' .. outlawGain ..' outlaw rep)',
type = 'error'
})
end)
-- Helper function for reputation tiers
function GetReputationTier(rep)
if rep >= 500 then return 'Legendary' end
if rep >= 300 then return 'Master' end
if rep >= 200 then return 'Expert' end
if rep >= 100 then return 'Skilled' end
if rep >= 50 then return 'Apprentice' end
return 'Novice'
endExample 3: Reputation-Locked Content
-- SERVER SIDE
-- Shop that requires reputation to access
RegisterNetEvent('shop:server:openSpecialShop', function()
local src = source
local Player = RSGCore.Functions.GetPlayer(src)
if not Player then return end
local requiredRep = 100
local huntingRep = Player.Functions.GetRep('hunting')
if huntingRep < requiredRep then
TriggerClientEvent('ox_lib:notify', src, {
description = 'You need '.. requiredRep ..' hunting reputation (you have '.. huntingRep ..')',
type = 'error'
})
return
end
-- Open special shop with rare items
local shopItems = {
{ name = 'legendary_bow', price = 500, amount = 1 },
{ name = 'master_lure', price = 100, amount = 5 },
{ name = 'tracking_scope', price = 250, amount = 1 }
}
exports['rsg-inventory']:OpenShop(src, 'master_hunter_shop', shopItems)
end)
-- Job promotion based on reputation
RegisterNetEvent('job:server:requestPromotion', function()
local src = source
local Player = RSGCore.Functions.GetPlayer(src)
if not Player then return end
local job = Player.PlayerData.job.name
local currentGrade = Player.PlayerData.job.grade.level
-- Check job-specific reputation
local jobRep = Player.Functions.GetRep(job)
local requiredRep = (currentGrade + 1) * 50 -- 50, 100, 150, etc.
if jobRep < requiredRep then
TriggerClientEvent('ox_lib:notify', src, {
description = 'Need '.. requiredRep ..' '.. job ..' reputation for promotion',
type = 'error'
})
return
end
-- Grant promotion
local newGrade = currentGrade + 1
if Player.Functions.SetJob(job, tostring(newGrade)) then
TriggerClientEvent('ox_lib:notify', src, {
title = 'Promotion!',
description = 'Promoted to grade '.. newGrade,
type = 'success'
})
end
end)Example 4: Reputation Decay Over Time
-- SERVER SIDE
-- Decrease reputation over time if inactive
CreateThread(function()
while true do
Wait(3600000) -- Every hour
for _, playerId in pairs(RSGCore.Functions.GetPlayers()) do
local Player = RSGCore.Functions.GetPlayer(playerId)
if Player then
-- Decay outlaw reputation slowly
local outlawRep = Player.Functions.GetRep('outlaw')
if outlawRep > 0 then
Player.Functions.RemoveRep('outlaw', 1) -- Lose 1 per hour
end
-- Decay skill reputations very slowly
for _, skill in ipairs({'hunting', 'fishing', 'mining'}) do
local skillRep = Player.Functions.GetRep(skill)
if skillRep > 100 then
-- Only decay if above 100
Player.Functions.RemoveRep(skill, 1)
end
end
end
end
end
end)Example 5: Reputation Rewards and Perks
-- SERVER SIDE
-- Grant perks based on reputation thresholds
function ApplyReputationPerks(source)
local Player = RSGCore.Functions.GetPlayer(source)
if not Player then return end
local huntingRep = Player.Functions.GetRep('hunting')
-- Hunting perks
if huntingRep >= 200 then
-- Master hunter - better loot chance
TriggerClientEvent('hunting:client:setLootBonus', source, 1.5)
elseif huntingRep >= 100 then
-- Expert hunter - moderate loot bonus
TriggerClientEvent('hunting:client:setLootBonus', source, 1.25)
end
local tradingRep = Player.Functions.GetRep('trading')
-- Trading perks
if tradingRep >= 150 then
-- Master trader - 20% better prices
TriggerClientEvent('trading:client:setPriceBonus', source, 0.20)
elseif tradingRep >= 75 then
-- Skilled trader - 10% better prices
TriggerClientEvent('trading:client:setPriceBonus', source, 0.10)
end
end
-- Call when player loads
RegisterNetEvent('RSGCore:Server:PlayerLoaded', function(Player)
ApplyReputationPerks(Player.PlayerData.source)
end)Example 6: Reputation Leaderboard
-- SERVER SIDE
-- Get top players by reputation type
RegisterNetEvent('reputation:server:getLeaderboard', function(repType)
local src = source
MySQL.query('SELECT citizenid, charinfo, metadata FROM players ORDER BY JSON_EXTRACT(metadata, "$.rep.'.. repType ..'") DESC LIMIT 10', {}, function(result)
if not result then return end
local leaderboard = {}
for i = 1, #result do
local charinfo = json.decode(result[i].charinfo)
local metadata = json.decode(result[i].metadata)
local rep = metadata.rep and metadata.rep[repType] or 0
leaderboard[#leaderboard + 1] = {
rank = i,
name = charinfo.firstname ..' '.. charinfo.lastname,
reputation = rep
}
end
TriggerClientEvent('reputation:client:showLeaderboard', src, repType, leaderboard)
end)
end)
-- CLIENT SIDE
RegisterNetEvent('reputation:client:showLeaderboard', function(repType, leaderboard)
-- Display leaderboard in UI
SendNUIMessage({
action = 'showLeaderboard',
type = repType,
data = leaderboard
})
end)Example 7: Multi-Reputation Requirements
-- SERVER SIDE
-- Quest that requires multiple reputation types
RegisterNetEvent('quest:server:startMasterQuest', function()
local src = source
local Player = RSGCore.Functions.GetPlayer(src)
if not Player then return end
local requirements = {
hunting = 150,
fishing = 100,
crafting = 100,
trading = 75
}
-- Check all requirements
local meetsRequirements = true
local missingReps = {}
for repType, required in pairs(requirements) do
local current = Player.Functions.GetRep(repType)
if current < required then
meetsRequirements = false
missingReps[#missingReps + 1] = {
type = repType,
required = required,
current = current,
needed = required - current
}
end
end
if not meetsRequirements then
local message = 'Missing reputation requirements:\n'
for _, missing in ipairs(missingReps) do
message = message .. missing.type ..': '.. missing.current ..'/'.. missing.required ..' (need '.. missing.needed ..' more)\n'
end
TriggerClientEvent('ox_lib:notify', src, {
title = 'Quest Locked',
description = message,
type = 'error',
duration = 10000
})
return
end
-- Start the master quest
TriggerEvent('quest:server:startQuest', src, 'master_quest')
TriggerClientEvent('ox_lib:notify', src, {
title = 'Master Quest',
description = 'You have unlocked the Master Quest!',
type = 'success'
})
end)Reputation Tier Systems
Creating Reputation Tiers
-- SERVER SIDE
-- Define reputation tiers
local ReputationTiers = {
hunting = {
{ min = 0, max = 49, label = 'Novice Hunter', color = '#808080' },
{ min = 50, max = 99, label = 'Apprentice Hunter', color = '#00ff00' },
{ min = 100, max = 199, label = 'Skilled Hunter', color = '#0080ff' },
{ min = 200, max = 299, label = 'Expert Hunter', color = '#8000ff' },
{ min = 300, max = 499, label = 'Master Hunter', color = '#ff8000' },
{ min = 500, max = 9999, label = 'Legendary Hunter', color = '#ff0000' }
},
lawman = {
{ min = 0, max = 49, label = 'Recruit', color = '#808080' },
{ min = 50, max = 99, label = 'Deputy', color = '#00ff00' },
{ min = 100, max = 199, label = 'Sheriff', color = '#0080ff' },
{ min = 200, max = 299, label = 'US Marshal', color = '#8000ff' },
{ min = 300, max = 9999, label = 'Legendary Lawman', color = '#ff0000' }
}
}
-- Get tier for reputation
function GetReputationTier(repType, repAmount)
local tiers = ReputationTiers[repType]
if not tiers then return nil end
for _, tier in ipairs(tiers) do
if repAmount >= tier.min and repAmount <= tier.max then
return tier
end
end
return nil
end
-- Usage
RegisterNetEvent('reputation:server:checkTier', function(repType)
local src = source
local Player = RSGCore.Functions.GetPlayer(src)
if not Player then return end
local rep = Player.Functions.GetRep(repType)
local tier = GetReputationTier(repType, rep)
if tier then
TriggerClientEvent('ox_lib:notify', src, {
title = tier.label,
description = 'You have '.. rep ..' '.. repType ..' reputation',
type = 'info'
})
end
end)Best Practices
Tip
Use descriptive reputation names: Choose clear, lowercase names like 'hunting', 'lawman', not abbreviations
Don't use special characters: Stick to letters, numbers, and underscores for reputation type names
Provide feedback: Always notify players when they gain or lose reputation
Design Guidelines
-
Meaningful Gains: Make reputation gains feel rewarding
- Small tasks: 1-5 rep
- Medium tasks: 5-15 rep
- Large tasks: 15-50 rep
- Milestones: 50+ rep
-
Clear Thresholds: Set clear milestones for unlocks
- Tier 1: 0-49 (Novice)
- Tier 2: 50-99 (Apprentice)
- Tier 3: 100-199 (Skilled)
- Tier 4: 200-299 (Expert)
- Tier 5: 300-499 (Master)
- Tier 6: 500+ (Legendary)
-
Balance Gains vs Losses:
- Easier to gain than lose (2:1 ratio recommended)
- Protect new players from excessive reputation loss
- Consider reputation decay for inactive skills
-
Multiple Paths: Allow different activities to earn same reputation
- Hunting: killing animals, selling pelts, completing challenges
- Lawman: arrests, patrols, investigations
- Trading: sales, deliveries, negotiations
Troubleshooting
Possible causes:
- Player data not saving to database
- Metadata corruption
- Server crash before save
Solution:
- Check auto-save interval (default: 5 minutes)
- Verify database connection
- Manually trigger save:
Player.Functions.Save()
Explanation: This is normal!
GetRep()returns 0 for non-existent reputation types- Reputation types are created on first
AddRep()call - No need to initialize reputation types
Solution: Just use GetRep() - it handles missing types automatically
Explanation: This cannot happen!
RemoveRep()clamps at 0 minimum- Even removing more than available sets it to 0
- Negative reputation is not supported
Workaround: Use separate reputation types for opposing factions (lawman vs outlaw)
Possible causes:
- Database not saving metadata properly
- Metadata JSON corruption
- Auto-save not running
Solution:
- Check
playerstablemetadatacolumn - Verify JSON format is valid
- Ensure RSGCore.Config.UpdateInterval is set
Technical Details
Database Storage
Reputation is stored in the metadata JSON column:
-- players table
metadata = '{
"hunger": 100,
"thirst": 100,
"rep": {
"hunting": 150,
"fishing": 75,
"lawman": 200
}
}'Implementation Location
Reputation functions are in rsg-core/server/player.lua:
-- Lines 236-242: AddRep
function self.Functions.AddRep(rep, amount)
if not rep or not amount then return end
local addAmount = tonumber(amount)
local currentRep = self.PlayerData.metadata['rep'][rep] or 0
self.PlayerData.metadata['rep'][rep] = currentRep + addAmount
self.Functions.UpdatePlayerData()
end
-- Lines 244-254: RemoveRep
function self.Functions.RemoveRep(rep, amount)
if not rep or not amount then return end
local removeAmount = tonumber(amount)
local currentRep = self.PlayerData.metadata['rep'][rep] or 0
if currentRep - removeAmount < 0 then
self.PlayerData.metadata['rep'][rep] = 0
else
self.PlayerData.metadata['rep'][rep] = currentRep - removeAmount
end
self.Functions.UpdatePlayerData()
end
-- Lines 256-259: GetRep
function self.Functions.GetRep(rep)
if not rep then return end
return self.PlayerData.metadata['rep'][rep] or 0
endPerformance Considerations
- Reputation operations are O(1) - very fast
- Changes saved to database every 5 minutes (auto-save)
- No network overhead (server-side only)
- Minimal memory footprint (integer storage)
Next Steps
- Player Data Reference - Complete player data structure
- StateBags System - Real-time data synchronization
- Server Functions - All server functions
Need help? Join the RSG Framework Discord!

