Framework: RSG Core (RedM)
License: GPL-3.0
- Overview
- Features
- Dependencies
- Installation
- Configuration
- Database Schema
- Client-Side Architecture
- Server-Side Architecture
- Commands & Keybinds
- Item System
- Horse XP & Leveling
- Bonding System
- Customization System
- Horse Trading
- Horse Death & Aging
- API & Exports
- Localization
- Troubleshooting
rsg-horses is a comprehensive horse management system for RedM servers using the RSG Framework. It provides full ownership, persistent data, customization, XP progression, bonding mechanics, and interactive horse behaviors.
- Persistent Horse Ownership - horses are saved per player with unique IDs
- Dynamic Spawning - horses spawn at stables with proper distance-based culling
- XP & Leveling - 10 levels affecting health, stamina, speed, acceleration, and inventory
- Bonding System - 4 bonding levels that unlock abilities
- Component System - saddles, blankets, stirrups, horns, saddlebags, manes, tails, masks, bedrolls, mustaches
- Interactive Actions - horses can drink from troughs/water, graze on hay, play, and lay down
- Horse Aging - horses die after a configurable number of days
- Trading - players can trade horses with each other
- Death & Revival - horses can die and be revived with horse reviver items
- ✅ Multiple Stables - 9 pre-configured stable locations (Valentine, Blackwater, Saint Denis, Rhodes, Strawberry, Tumbleweed, Van Horn, Emerald Ranch, Colter)
- ✅ Horse Customization - 10 customizable component categories
- ✅ Horse Inventory - saddlebags with level-based weight/slots
- ✅ Usable Items - brush, lantern, feed items, stimulant, reviver
- ✅ Dynamic Stats - health/stamina/speed scale with XP
- ✅ Horse Actions - lay down, play tricks, drink, graze (XP-gated)
- ✅ Horse Gender - male (gelding) or female (mare)
- ✅ Fleeing - horses can flee and optionally auto-store
- ✅ Blips - horses show on map with their name
- ✅ Target Support - ox_target integration for NPC horses
- ✅ Prompt System - native RedM prompts for actions
- ✅ Server-Side Validation - ownership, component, and trade security
- ✅ Routing Buckets - customization happens in isolated instances
- ✅ Upkeep System - automatic age checking and death handling
- ✅ Telegram Integration - death notifications via in-game telegrams
- ✅ Grace Period - 60-second window to revive dead horses
- ✅ Road Spawning - optional spawn-on-road-only mode
- ✅ Auto-Mount - optional auto-mount on spawn
- ✅ Persistent Stock - shop stock can persist across restarts
| Resource | Purpose | Link |
|---|---|---|
| rsg-core | Core framework | GitHub |
| rsg-inventory | Inventory system & horse saddlebags | GitHub |
| ox_lib | Menus, prompts, callbacks, locales | GitHub |
| oxmysql | MySQL wrapper | GitHub |
| Resource | Purpose |
|---|---|
| ox_target | Targeting for stable NPCs and horses |
| rsg-menubase | Legacy menu system (used for customization UI) |
- Place
rsg-horsesintoresources/[rsg]/ - Ensure folder name is exactly
rsg-horses
# Import SQL file
mysql -u username -p database_name < installation/rsg-horses.sqlOr manually execute:
CREATE TABLE IF NOT EXISTS `player_horses` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`stable` varchar(50) NOT NULL,
`citizenid` varchar(50) NOT NULL,
`horseid` varchar(11) NOT NULL,
`name` varchar(255) NOT NULL,
`horse` varchar(50) DEFAULT NULL,
`dirt` int(11) DEFAULT 0,
`horsexp` int(11) DEFAULT 0,
`components` LONGTEXT NOT NULL DEFAULT '{}',
`gender` varchar(11) NOT NULL,
`wild` varchar(11) DEFAULT NULL,
`active` tinyint(4) DEFAULT 0,
`born` int(11) NOT NULL DEFAULT 0,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;Add these to your rsg-inventory/shared/items.lua:
['horse_brush'] = { name = 'horse_brush', label = 'Horse Brush', weight = 200, type = 'item', image = 'horse_brush.png', unique = false, useable = true, shouldClose = true, description = 'Brush your horse' },
['horse_lantern'] = { name = 'horse_lantern', label = 'Horse Lantern', weight = 500, type = 'item', image = 'horse_lantern.png', unique = false, useable = true, shouldClose = true, description = 'Light for your horse' },
['sugarcube'] = { name = 'sugarcube', label = 'Sugar Cube', weight = 50, type = 'item', image = 'sugarcube.png', unique = false, useable = true, shouldClose = true, description = 'Sweet treat' },
['horse_carrot'] = { name = 'horse_carrot', label = 'Horse Carrot', weight = 100, type = 'item', image = 'horse_carrot.png', unique = false, useable = true, shouldClose = true, description = 'Feed your horse' },
['horse_apple'] = { name = 'horse_apple', label = 'Horse Apple', weight = 100, type = 'item', image = 'horse_apple.png', unique = false, useable = true, shouldClose = true, description = 'Feed your horse' },
['haysnack'] = { name = 'haysnack', label = 'Hay Snack', weight = 200, type = 'item', image = 'haysnack.png', unique = false, useable = true, shouldClose = true, description = 'Hay for your horse' },
['horsemeal'] = { name = 'horsemeal', label = 'Horse Meal', weight = 300, type = 'item', image = 'horsemeal.png', unique = false, useable = true, shouldClose = true, description = 'Full meal for horse' },
['horse_stimulant'] = { name = 'horse_stimulant', label = 'Horse Stimulant', weight = 100, type = 'item', image = 'horse_stimulant.png', unique = false, useable = true, shouldClose = true, description = 'Boosts horse stamina' },
['horse_reviver'] = { name = 'horse_reviver', label = 'Horse Reviver', weight = 200, type = 'item', image = 'horse_reviver.png', unique = false, useable = true, shouldClose = true, description = 'Revive a dead horse' },ensure ox_lib
ensure oxmysql
ensure rsg-core
ensure rsg-inventory
ensure rsg-horsesrestart rsg-horses
# or full restart
restartConfiguration is split across multiple files in shared/:
Config.horsesShopItems = {
{ name = 'horse_brush', amount = 10, price = 5 },
{ name = 'horse_lantern', amount = 10, price = 10 },
{ name = 'sugarcube', amount = 50, price = 0.05 },
-- ... more items
}
Config.PersistStock = false -- Persist shop stock in databaseConfig.EnableTarget = true -- Use ox_target instead of prompts
Config.TargetHelp = false -- Show target help (L-ALT)
Config.Automount = false -- Auto-mount horse on spawn
Config.SpawnOnRoadOnly = false -- Force horse spawn near roads
Config.HorseInvWeight = 16000 -- Max inventory weight (level 10)
Config.HorseInvSlots = 25 -- Max inventory slots (level 10)
Config.CheckCycle = 30 -- Upkeep check interval (minutes)
Config.StarterHorseDieAge = 7 -- Starter horse lifespan (days)
Config.HorseDieAge = 365 -- Normal horse lifespan (days)
Config.StoreFleedHorse = false -- Auto-store when fleeing
Config.EnableServerNotify = false -- Console notifications
Config.KeyBind = 'J' -- Horse call keybind
Config.AllowTwoPlayersRide = true -- Allow multiple riders
Config.DeathGracePeriod = 60000 -- Death grace period (ms)Config.Level1InvWeight = 4000 -- Level 1
Config.Level1InvSlots = 4
Config.Level10InvWeight = 16000 -- Level 10
Config.Level10InvSlots = 25Config.Level1 = 100 -- Health/Stamina/Speed for level 1
Config.Level10 = 2000 -- Health/Stamina/Speed for level 10Config.HorseFeed = {
['horse_carrot'] = { health = 10, stamina = 10, ismedicine = false },
['horse_apple'] = { health = 15, stamina = 15, ismedicine = false },
['sugarcube'] = { health = 25, stamina = 25, ismedicine = false },
['horsemeal'] = { health = 75, stamina = 75, ismedicine = false },
['horse_stimulant'] = { health = 100, stamina = 100, ismedicine = true, medicineHash = 'consumable_horse_stimulant' },
}Config.MaxBondingLevel = 5000 -- Max bonding XPConfig.StableSettings = {
{
stableid = 'valentine',
coords = vector3(-365.2, 791.94, 116.18),
npcmodel = `u_m_m_bwmstablehand_01`,
npccoords = vector4(-365.2, 791.94, 116.18, 180.9),
horsecustom = vec4(-388.5212, 784.0562, 115.8154, 150.4135),
showblip = true
},
-- ... 8 more stables
}Config.TrickXp = {
Lay = 1000, -- XP needed to lay down
Play = 2000 -- XP needed to play tricks
}Config.PriceComponent = {
Blankets = 5,
Saddles = 2,
Horns = 10,
Saddlebags = 3,
Stirrups = 4,
Bedrolls = 5,
Tails = 4,
Manes = 3,
Masks = 3,
Mustaches = 2,
}Defines which horses appear at which stables:
return {
{
horsecoords = vector4(-371.9695, 787.4564, 116.1761, 96.6926),
horsemodel = `a_c_horse_americanpaint_greyovero`,
horseprice = 50,
horsename = "American Paint Grey Overo",
stableid = "valentine"
},
-- ... hundreds more horses
}Defines all customization components (saddles, blankets, etc.). Each entry has:
hashid- Unique IDcategory- Component typecategory_hash- Game hash for categoryhash- Game hash for specific variant
Example:
{
hashid = 1,
category = "saddles",
category_hash = 0xBAA7E618,
hash = 0xC5913F48,
}| Column | Type | Description |
|---|---|---|
id |
INT(11) AUTO_INCREMENT | Primary key |
stable |
VARCHAR(50) | Stable ID where horse is stored |
citizenid |
VARCHAR(50) | Player citizen ID (foreign key) |
horseid |
VARCHAR(11) | Unique horse identifier (e.g. "ABC123") |
name |
VARCHAR(255) | Custom horse name |
horse |
VARCHAR(50) | Horse model hash/name |
dirt |
INT(11) DEFAULT 0 | Dirtiness level (0-100) |
horsexp |
INT(11) DEFAULT 0 | Horse experience points |
components |
LONGTEXT DEFAULT '{}' | JSON of applied components |
gender |
VARCHAR(11) | 'male' or 'female' |
wild |
VARCHAR(11) | Reserved for future use |
active |
TINYINT(4) DEFAULT 0 | 1 if currently active |
born |
INT(11) DEFAULT 0 | Unix timestamp of creation |
Indexes:
- Primary key on
id - Suggested indexes:
citizenid,horseid,active
client/
├── client.lua # Main client logic (spawn, menu, prompts)
├── horses.lua # Stable horse spawning & purchase
├── action.lua # Interactive actions (drink, graze)
├── horseinfo.lua # Horse info display
├── npcs.lua # Stable NPC spawning
└── dataview.lua # Native data handling
Spawns the player's active horse with all stats, components, and XP applied.
Process:
- Fetch active horse data from server
- Validate spawn location (road check if enabled)
- Create horse ped with model
- Apply flags (behavior, personality, ownership)
- Load and apply components from database
- Set XP-based attributes (health, stamina, speed, etc.)
- Calculate bonding level
- Apply gender appearance
- Create blip
- Setup prompts
- Move horse to player
Creates native prompts for horse interaction:
- Lay - Requires XP >= 1000
- Play - Requires XP >= 2000
- Saddlebag - Always available
Opens customization menu using rsg-menubase:
- Component selection
- Real-time preview
- Price calculation
- Purchase confirmation
Component selection submenu with sliders for each category.
Pathfinds horse to player and stops when within 7 meters.
server/
├── server.lua # Main server logic
└── versionchecker.lua # Version checking
Ensures player owns the horse before any operation.
Validates component data against horse_comp.lua to prevent exploits.
- Distance checks (max 5.0 units)
- Expiration timers (30 seconds)
- Ownership verification
- Atomic transfers
Security:
- Name validation (alphanumeric, 1-50 chars)
- Atomic money removal (remove first, then create)
- Generates unique
horseid
Process:
- Validate horse model exists
- Remove money
- Generate unique horse ID
- Insert into database
- Notify player
Security:
- Component validation
- Ownership verification
- Price calculation
Process:
- Fetch current components
- Calculate price difference
- Remove money
- Update database
Flow:
- Sender triggers trade with player ID and horse ID
- Server validates ownership & distance
- Trade request stored with 30s expiration
- Target receives notification
- Target runs
/accepttrade - Server validates trade still valid
- Ownership transferred atomically
- Both players notified
Flow:
- Client detects death (after grace period)
- Server verifies active horse
- Delete horse inventory
- Delete horse from database
- Send telegram notification
- Log to rsg-log
Runs every Config.CheckCycle minutes:
- Fetch all horses from database
- Calculate age in days
- Check if:
- Starter horse (
a_c_horse_mp_mangy_backup) >=Config.StarterHorseDieAgedays - Normal horse >=
Config.HorseDieAgedays
- Starter horse (
- Delete horse & inventory
- Send telegram to owner
- Log death
| Command | Description | Permission |
|---|---|---|
/sethorsename |
Rename your active horse | Player |
/findhorse |
Show locations of all your horses | Player |
/accepttrade |
Accept a pending horse trade | Player |
| Key | Action | Notes |
|---|---|---|
| H | Call/Whistle Horse | Default RSGCore keybind |
| G | Open Horse Inventory | Config.HorseInvKey |
| J | Alternative Call | Config.KeyBind (configurable) |
| Left/Right Arrow | Rotate Horse | During customization |
| Prompt | Control | Requirement |
|---|---|---|
| Lay | Config.Prompt.HorseLay | XP >= 1000 |
| Play | Config.Prompt.HorsePlay | XP >= 2000 |
| Saddlebag | Config.Prompt.HorseSaddleBag | Always |
| Drink | Config.Prompt.HorseDrink | Leading horse near water/trough |
| Graze | Config.Prompt.HorseGraze | Leading horse near hay |
RSGCore.Functions.CreateUseableItem('horse_brush', function(source, item)
TriggerClientEvent('rsg-horses:client:playerbrushhorse', source, item.name)
end)- Effect: Reduces horse dirt
- Requirement: Must be near horse
- Animation: Brushing animation
RSGCore.Functions.CreateUseableItem('horse_lantern', function(source, item)
TriggerClientEvent('rsg-horses:client:equipHorseLantern', source, item.name)
end)- Effect: Toggles lantern on horse
- Visual: Attaches lantern prop
RSGCore.Functions.CreateUseableItem('sugarcube', function(source, item)
if Player.Functions.RemoveItem(item.name, 1, item.slot) then
TriggerClientEvent('rsg-horses:client:playerfeedhorse', source, item.name)
end
end)- Effect: Restores health/stamina based on
Config.HorseFeed - Consumption: Item is removed on use
- Medicine Items: Apply special effects (e.g., stimulant uses game consumable)
RSGCore.Functions.CreateUseableItem('horse_reviver', function(source, item)
TriggerClientEvent('rsg-horses:client:revivehorse', src, item, result[1])
end)- Effect: Revives dead horse
- Requirement: Horse must be dead but within grace period
- Consumption: Item is removed on successful revival
| Level | XP Range | Health | Stamina | Speed | Accel | Inv Weight | Inv Slots |
|---|---|---|---|---|---|---|---|
| 1 | 0-99 | 100 | 100 | 100 | 100 | 4000 | 4 |
| 2 | 100-199 | 200 | 200 | 200 | 200 | 6000 | 6 |
| 3 | 200-299 | 300 | 300 | 300 | 300 | 8000 | 8 |
| 4 | 300-399 | 400 | 400 | 400 | 400 | 9000 | 10 |
| 5 | 400-499 | 500 | 500 | 500 | 500 | 10000 | 12 |
| 6 | 500-999 | 900 | 900 | 900 | 900 | 12000 | 14 |
| 7 | 1000-1999 | 1000 | 1000 | 1000 | 1000 | 13000 | 16 |
| 8 | 2000-2999 | 1500 | 1500 | 1500 | 1500 | 14000 | 18 |
| 9 | 3000-3999 | 1750 | 1750 | 1750 | 1750 | 15000 | 20 |
| 10 | 4000+ | 2000 | 2000 | 2000 | 2000 | 16000 | 25 |
When XP >= 4000, horses enter "overpower" mode:
EnableAttributeOverpower(horsePed, 0, 5000.0) -- health
EnableAttributeOverpower(horsePed, 1, 5000.0) -- staminaHealth and stamina scale directly with XP value.
Note: XP gain requires integration with rsg-horsetrainer or similar resource. Base script tracks XP but doesn't provide native earning methods.
Common XP sources (via other resources):
- Horse trainer NPC interaction
- Riding time
- Completing missions
- Trick performance
- Horse races
Bonding is separate from XP and ranges from 1-4:
| Level | XP Range | Bonding Points | Abilities Unlocked |
|---|---|---|---|
| 1 | 0-1249 | 1-817 | Basic riding |
| 2 | 1250-2499 | 817-1634 | Rearing (hold Ctrl+Space) |
| 3 | 2500-3749 | 1634-2450 | Skidding, Drifting |
| 4 | 3750+ | 2450+ | All abilities |
local bond = Config.MaxBondingLevel -- 5000
local bond1 = bond * 0.25 -- 1250
local bond2 = bond * 0.50 -- 2500
local bond3 = bond * 0.75 -- 3750
if horsexp > bond3 then
horseBonding = 2450 -- Level 4
endBonding affects:
- Rearing ability
- Turn radius
- Responsiveness
- Skid/drift capability
| Category | Hash | Price | Count |
|---|---|---|---|
| Blankets | 0x17CEB41A | $5 | Varies |
| Saddles | 0xBAA7E618 | $2 | Varies |
| Horns | 0x05447332 | $10 | Varies |
| Saddlebags | 0x80451C25 | $3 | Varies |
| Stirrups | 0xDA6DADCA | $4 | Varies |
| Bedrolls | 0xEFB31921 | $5 | Varies |
| Tails | 0xA63CAE10 | $4 | Varies |
| Manes | 0xAA0217AB | $3 | Varies |
| Masks | 0xD3500E5D | $3 | Varies |
| Mustaches | 0x30DEFDDF | $2 | Varies |
Native: ApplyShopItemToPed
Citizen.InvokeNative(0xD3A7B003ED343FD9, horsePed, hash, true, true, true)function CalculatePrice(comp, initial)
local price = 0
for category, value in pairs(comp) do
if Config.PriceComponent[category] and value > 0 and (not initial or initial[category] ~= value) then
price = price + Config.PriceComponent[category]
end
end
return price
endExample:
- Change saddle (index 0 → 5): $2
- Change blanket (index 0 → 3): $5
- Change stirrups (index 2 → 8): $4
- Total: $11
- Proximity Check: Players must be within 5.0 units
- Ownership Verification: Horse must be owned and active
- Expiration: Trade requests expire after 30 seconds
- Atomic Transfer: Ownership changes in single transaction
- Active State Reset: Traded horse becomes inactive
sequenceDiagram
Player A->>Server: TriggerEvent('rsg-horses:server:TradeHorse', playerB_id, horse_id)
Server->>Server: Verify ownership & distance
Server->>Player B: Notify trade request (30s timer)
Player B->>Server: /accepttrade
Server->>Server: Validate trade not expired
Server->>Database: UPDATE player_horses SET citizenid = playerB
Server->>Player A: Notify trade success
Server->>Player B: Notify received horse
-- Send trade (from stable menu or command)
TriggerServerEvent('rsg-horses:server:TradeHorse', targetPlayerId, horseId)
-- Accept trade
/accepttradeWhen a horse reaches 0 health:
- 60-second grace period begins (
Config.DeathGracePeriod) - Player receives critical health warning
- Player can use horse reviver to restore horse
- If grace period expires, horse is permanently dead
-- Client detects death
if IsEntityDead(horsePed) and not IsBeingRevived then
Wait(Config.DeathGracePeriod)
if IsEntityDead(horsePed) then
TriggerServerEvent('rsg-horses:server:HorseDied', horseid, horsename)
end
end- Horse deleted from database
- Inventory cleared (all items in saddlebags deleted)
- Telegram sent to owner
- Log created (via rsg-log)
- Client cleanup (blip removed, ped deleted)
local currentTime = os.time()
local timeDifference = currentTime - horse.born
local daysPassed = math.floor(timeDifference / (24 * 60 * 60))| Horse Type | Model | Max Age | Notes |
|---|---|---|---|
| Starter Horse | a_c_horse_mp_mangy_backup |
7 days | Low-quality free horse |
| Normal Horse | All others | 365 days | Standard horses |
SetTimeout(Config.CheckCycle * (60 * 1000), UpkeepInterval)Default: Every 30 minutes, checks all horses for age death.
MySQL.insert('INSERT INTO telegrams (citizenid, recipient, sender, sendername, subject, sentDate, message) VALUES (?, ?, ?, ?, ?, ?, ?)', {
citizenid,
locale('sv_telegram_owner'),
'22222222',
locale('sv_telegram_stables'),
horsename..' '..locale('sv_telegram_away'),
os.date('%x'),
locale('sv_telegram_inform')..' '..horsename..' '..locale('sv_telegram_has_passed'),
})Returns the current horse's XP level (1-10).
local level = exports['rsg-horses']:CheckHorseLevel()
print("Horse is level: " .. level)Returns the current bonding level (1-4).
local bonding = exports['rsg-horses']:CheckHorseBondingLevel()
print("Bonding level: " .. bonding)Returns the horse ped entity.
local horsePed = exports['rsg-horses']:CheckActiveHorse()
if horsePed ~= 0 then
print("Horse entity: " .. horsePed)
endFetch all horses for a player.
RSGCore.Functions.TriggerCallback('rsg-horses:server:GetAllHorses', function(horses)
for i, horse in ipairs(horses) do
print(horse.name, horse.horsexp, horse.stable)
end
end)Fetch the active horse.
RSGCore.Functions.TriggerCallback('rsg-horses:server:GetActiveHorse', function(horse)
if horse then
print("Active horse:", horse.name)
end
end)Fetch active horse components.
RSGCore.Functions.TriggerCallback('rsg-horses:server:CheckComponents', function(horse)
local components = json.decode(horse.components)
print("Saddle:", components.saddles)
end)local horses = lib.callback.await('rsg-horses:server:GetHorse', false, 'valentine')en- Englishfr- Frenches- Spanishpt-br- Brazilian Portuguesept- Portugueseel- Greekit- Italianpl- Polish (partial)de- German (partial)
- Create
locales/xx.json(e.g.,jp.jsonfor Japanese) - Copy structure from
locales/en.json - Translate all strings
- Reload resource
lib.locale('cl_success_horse_active') -- Client
locale('sv_success_horse_owned') -- ServerSymptoms: Pressing H does nothing
Causes:
- No active horse set
- Horse died
- In jail (
metadata.injail ~= 0) - Player is dead (
metadata.isdead)
Solution:
-- Check active horse in database
SELECT * FROM player_horses WHERE citizenid='CITIZEN_ID' AND active=1;
-- Set a horse active
UPDATE player_horses SET active=1 WHERE id=HORSE_ID;Symptoms: Customization resets after spawn
Causes:
- Server validation failure
- Insufficient funds
- Ownership mismatch
Solution:
- Check server console for validation errors
- Verify player has cash
- Ensure horse is owned by player
Symptoms: Pressing G does nothing
Causes:
rsg-inventorynot started- Horse not spawned
- Inventory key conflict
Solution:
-- Check if rsg-inventory is running
ensure rsg-inventory
-- Verify horse exists
local horse = exports['rsg-horses']:CheckActiveHorse()
print(horse) -- Should not be 0Symptoms: Horse spawns but dies immediately
Causes:
- Age exceeded threshold
- Starter horse past 7 days
- Corrupted horse data
Solution:
-- Check horse age
SELECT name, FROM_UNIXTIME(born) as birth_date,
TIMESTAMPDIFF(DAY, FROM_UNIXTIME(born), NOW()) as age_days
FROM player_horses
WHERE citizenid='CITIZEN_ID';
-- Reset age
UPDATE player_horses SET born=UNIX_TIMESTAMP() WHERE id=HORSE_ID;Symptoms: /accepttrade says no pending request
Causes:
- Trade expired (>30s)
- Players too far apart
- Horse no longer exists
Solution:
- Stay within 5 units
- Accept within 30 seconds
- Verify horse still exists
Enable debug in shared/config.lua:
Config.Debug = true-- View all horses
SELECT * FROM player_horses;
-- Find horses by player
SELECT * FROM player_horses WHERE citizenid='ABC123';
-- Delete old horses
DELETE FROM player_horses WHERE born < UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL 365 DAY));
-- Reset all horses to level 1
UPDATE player_horses SET horsexp=0;
-- Make all horses clean
UPDATE player_horses SET dirt=0;- Humanity Is Insanity#3505 & Zee#2115 - The Crossroads RP (system design)
- RedEM-RP - Menu base inspiration
- Goghor#9453 - Bonding mechanics
- RSG / Rexshack-RedM - Framework & maintenance
- Community Contributors - Translations, testing, feedback
GPL-3.0 License
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
- Issues: GitHub Issues
- Pull Requests: Welcome! Follow existing code style
- Discord: Join RSG Discord for support
End of Documentation
Last Updated: 2025