β Requirements#
- ESX Legacy (1.9.0+) or ESX Infinity
- ox_lib
- oxmysql
- A compatible inventory
- A compatible clothing script (skinchanger or alternatives)
π Quick Setup#
Step 1: Enable Multicharacter in ESX#
Edit es_extended/config.lua:
Config.Multichar = true -- Enable multicharacter support
Step 2: Disable Default Multicharacter#
# server.cfg
# ensure esx_multicharacter <-- Comment out or remove
ensure 0r-multicharacterv3
Step 3: Start Order#
ensure oxmysql
ensure ox_lib
ensure es_extended
ensure ox_inventory # or qs-inventory
ensure skinchanger # or bl_appearance
ensure 0r-multicharacterv3
ποΈ Database#
ESX uses the users table for character storage:
| Column | Usage |
|---|---|
| identifier | Character identifier (char1:license, char2:license) |
| firstname | First name |
| lastname | Last name |
| dateofbirth | Birth date |
| sex | Gender (m/f) |
| job | Job name |
| job_grade | Job grade |
| accounts | Money accounts (JSON) |
| position | Last position (JSON) |
| skin | Appearance data (JSON) |
π§ Character Identifier Format#
ESX multicharacter uses a specific identifier format:
char{number}:{license}
Examples:
char1:abc123def456- First characterchar2:abc123def456- Second characterchar3:abc123def456- Third character
Configure the prefix in config/config.lua:
Config.Prefix = 'char' -- Creates char1:, char2:, etc.
π Data Conversion#
The script converts ESX data to a standardized format:
-- ESX format
{
identifier = 'char1:license123',
firstname = 'John',
lastname = 'Doe',
dateofbirth = '1990-01-15',
sex = 'm',
job = 'unemployed',
job_grade = 0,
accounts = '{"money":500,"bank":5000}',
position = '{"x":0,"y":0,"z":0}',
}
-- Converted format
{
cid = 1,
citizenid = 'char1:license123',
charinfo = {
firstname = 'John',
lastname = 'Doe',
birthdate = '1990-01-15',
gender = 'm',
nationality = 'N/A',
},
job = {
name = 'Unemployed',
label = 'Unemployed',
grade = { name = 'Unemployed' }
},
money = {
cash = 500,
bank = 5000,
},
position = {
x = 0.0,
y = 0.0,
z = 0.0,
w = 0.0,
}
}
β‘ Events#
Server Events#
-- When player loads character
RegisterNetEvent('esx:playerLoaded', function(player, xPlayer, isNew)
-- Triggered after character selection
end)
-- When player disconnects
RegisterNetEvent('esx:playerDropped', function(playerId, reason)
-- Cleanup
end)
Client Events#
-- After spawning
TriggerServerEvent('esx:onPlayerSpawn')
TriggerEvent('esx:onPlayerSpawn')
TriggerEvent('playerSpawned')
TriggerEvent('esx:restoreLoadout')
π Character Deletion & Reindexing#
When a character is deleted, remaining characters are reindexed:
-- Before deletion: char1, char2, char3
-- Delete char2
-- After reindex: char1, char2 (was char3)
Configure tables in config/database.lua:
Database.List = {
['es_extended'] = {
{ table = 'users', column = 'identifier', type = 'citizenid' },
{ table = 'user_accounts', column = 'identifier', type = 'citizenid' },
{ table = 'user_inventory', column = 'identifier', type = 'citizenid' },
{ table = 'owned_vehicles', column = 'owner', type = 'citizenid' },
{ table = 'user_licenses', column = 'owner', type = 'citizenid' },
-- Add more tables as needed
}
}
π Complete Configuration#
-- config/config.lua for ESX
Config.Debug = false
Config.DeveloperMode = false
Config.Locale = 'en'
Config.HideRadar = true
Config.Prefix = 'char' -- ESX character prefix
Config.DefaultCharacterSlots = 2
Config.SkipWarning = false
Config.DisableDeleteCharacter = false
-- Spawn configuration
Config.SkipSpawnSelector = true
Config.SpawnSelector = '0r-spawn'
Config.ApartmentStart = false
Config.NewPlayerSpawnCoords = vec4(195.17, -933.77, 29.7, 144.5)
π ESX vs QBCore Differences#
| Feature | ESX | QBCore |
|---|---|---|
| Identifier | char1:license | citizenid |
| Gender | m/f | 0/1 |
| Money Storage | JSON accounts | JSON money |
| Skin Storage | users.skin | playerskins |
| Player Object | xPlayer | Player |
β Troubleshooting#
"Multichar not enabled" error#
Ensure in es_extended/config.lua:
Config.Multichar = true
Skin not loading#
- Check
users.skincolumn has data - Verify skinchanger is started
- Ensure skin format is correct
Character reindex issues#
If characters are out of order after deletion:
-- Manual reindex query
UPDATE users
SET identifier = CONCAT('char', @row := @row + 1, ':', SUBSTRING_INDEX(identifier, ':', -1))
WHERE identifier LIKE 'char%:your-license-here'
ORDER BY identifier;
Job not showing correctly#
The script reads job labels from ESX's job system. Ensure jobs are properly configured in your database.