Documentation Index Fetch the complete documentation index at: https://mythicframework.mintlify.app/llms.txt
Use this file to discover all available pages before exploring further.
Character events fire at key moments in the character lifecycle, allowing other resources to react to character creation, selection, updates, and deletion.
Server Events
All character events fire on the server-side .
Lifecycle Events Created, Selected, Deleted
State Changes Job changes, money changes, updates
Persistent Save and load events
Hookable Add custom logic to character operations
Lifecycle Events
Fired when a new character is successfully created.
AddEventHandler ( 'mythic-characters:server:CharacterCreated' , function ( source , character )
-- Handler code
end )
Parameters:
Player server ID who created the character
Newly created character object with all fields
Examples:
-- Give starter items
AddEventHandler ( 'mythic-characters:server:CharacterCreated' , function ( source , character )
-- Create inventory
Inventory : Create ( character . SID )
-- Give starter items
Inventory : AddItem ( character . SID , 'phone' , 1 , {
number = character . Phone
})
Inventory : AddItem ( character . SID , 'water' , 2 )
Inventory : AddItem ( character . SID , 'sandwich' , 2 )
Inventory : AddItem ( character . SID , 'id_card' , 1 , {
name = character . First .. ' ' .. character . Last ,
dob = character . DOB ,
gender = character . Gender
})
Logger : Info ( 'Characters' , 'New character created' , {
console = true ,
file = true
}, {
player = source ,
character = character . SID ,
name = character . First .. ' ' .. character . Last
})
end )
-- Set default job
AddEventHandler ( 'mythic-characters:server:CharacterCreated' , function ( source , character )
Jobs : GiveJob ( character . SID , 'unemployed' )
end )
-- Send welcome notification
AddEventHandler ( 'mythic-characters:server:CharacterCreated' , function ( source , character )
TriggerClientEvent ( 'mythic-notifications:client:Send' , source , {
message = 'Welcome to the city, ' .. character . First .. '!' ,
type = 'success' ,
duration = 5000
})
end )
-- Create default bank account
AddEventHandler ( 'mythic-characters:server:CharacterCreated' , function ( source , character )
Database . Game : insertOne ({
collection = 'bank_accounts' ,
document = {
owner = character . SID ,
type = 'checking' ,
balance = 5000 , -- Starting balance
accountNumber = GenerateAccountNumber (),
createdAt = os.time ()
}
})
end )
Fired when a player selects and loads a character.
AddEventHandler ( 'mythic-characters:server:CharacterSelected' , function ( source , character )
-- Handler code
end )
Parameters:
Selected character object
Examples:
-- Load character data for other systems
AddEventHandler ( 'mythic-characters:server:CharacterSelected' , function ( source , character )
-- Inventory is loaded automatically by the Inventory component on character select
-- Load vehicles
Database . Game : find ({
collection = 'vehicles' ,
query = { owner = character . SID }
}, function ( success , vehicles )
if success then
TriggerClientEvent ( 'mythic-vehicles:client:SetVehicles' , source , vehicles )
end
end )
-- Load properties
Database . Game : find ({
collection = 'properties' ,
query = { owner = character . SID }
}, function ( success , properties )
if success then
TriggerClientEvent ( 'mythic-properties:client:SetProperties' , source , properties )
end
end )
-- Jobs are loaded automatically by the Jobs component on character select
end )
-- Log character selection
AddEventHandler ( 'mythic-characters:server:CharacterSelected' , function ( source , character )
Logger : Info ( 'Characters' , 'Character selected' , {
console = true ,
file = true
}, {
player = source ,
playerName = GetPlayerName ( source ),
character = character . SID ,
characterName = character . First .. ' ' .. character . Last
})
-- Update last login
Characters : UpdateCharacter ( character . SID , {
[ 'metadata.lastLogin' ] = os.time ()
})
end )
-- Check for pending notifications
AddEventHandler ( 'mythic-characters:server:CharacterSelected' , function ( source , character )
Database . Game : find ({
collection = 'notifications' ,
query = { target = character . SID , read = false }
}, function ( success , notifications )
if success and notifications and # notifications > 0 then
TriggerClientEvent ( 'mythic-phone:client:ReceiveNotifications' , source , notifications )
end
end )
end )
Fired when a character is deleted.
AddEventHandler ( 'mythic-characters:server:CharacterDeleted' , function ( source , characterId )
-- Handler code
end )
Parameters:
Player server ID who deleted the character
SID of the deleted character
Examples:
-- Clean up character data
AddEventHandler ( 'mythic-characters:server:CharacterDeleted' , function ( source , characterId )
-- Delete inventory
Inventory : Delete ( characterId )
-- Delete all vehicles
Database . Game : delete ({
collection = 'vehicles' ,
query = { owner = characterId }
})
-- Delete properties
Database . Game : delete ({
collection = 'property_ownership' ,
query = { owner = characterId }
})
-- Delete phone data
Database . Game : delete ({
collection = 'phone_messages' ,
query = {
[ '$or' ] = {
{ sender = characterId },
{ receiver = characterId }
}
}
})
-- Delete bank accounts
Database . Game : delete ({
collection = 'bank_accounts' ,
query = { owner = characterId }
})
Logger : Info ( 'Characters' , 'Character data cleaned up' , {
console = true , file = true
}, { character = characterId })
end )
-- Log deletion for audit
AddEventHandler ( 'mythic-characters:server:CharacterDeleted' , function ( source , characterId )
Database . Game : insertOne ({
collection = 'audit_log' ,
document = {
type = 'character_deleted' ,
player = GetPlayerIdentifier ( source , 0 ),
character = characterId ,
timestamp = os.time ()
}
})
end )
State Change Events
Fired when a character’s job or job grade changes.
AddEventHandler ( 'mythic-characters:server:JobChanged' , function ( characterId , newJob , newGrade , oldJob , oldGrade )
-- Handler code
end )
Parameters:
Examples:
-- Give job-specific items
AddEventHandler ( 'mythic-characters:server:JobChanged' , function ( characterId , newJob , newGrade , oldJob , oldGrade )
if newJob == 'police' then
-- Give police equipment
Inventory : AddItem ( characterId , 'weapon_pistol' , 1 )
Inventory : AddItem ( characterId , 'radio' , 1 )
Inventory : AddItem ( characterId , 'handcuffs' , 1 )
elseif newJob == 'ems' then
-- Give EMS equipment
Inventory : AddItem ( characterId , 'medkit' , 5 )
Inventory : AddItem ( characterId , 'bandage' , 10 )
end
-- Remove old job items
if oldJob == 'police' then
Inventory . Items : Remove ( characterId , 1 , 'weapon_pistol' , 999 )
Inventory . Items : Remove ( characterId , 1 , 'handcuffs' , 999 )
end
end )
-- Update permissions
AddEventHandler ( 'mythic-characters:server:JobChanged' , function ( characterId , newJob , newGrade , oldJob , oldGrade )
local player = Fetch : SID ( characterId )
if player then
local source = player : GetData ( 'Source' )
-- Update Discord roles or permissions
TriggerEvent ( 'discord:updateRoles' , source , newJob )
end
end )
-- Notify player
AddEventHandler ( 'mythic-characters:server:JobChanged' , function ( characterId , newJob , newGrade , oldJob , oldGrade )
local player = Fetch : SID ( characterId )
if player then
local source = player : GetData ( 'Source' )
local jobLabel = newJob
local gradeLabel = Jobs : GetGradeLabel ( newJob , newGrade )
TriggerClientEvent ( 'mythic-notifications:client:Send' , source , {
message = 'Job changed to ' .. jobLabel .. ' - ' .. gradeLabel ,
type = 'info'
})
end
end )
Fired when a character’s cash or bank balance changes.
AddEventHandler ( 'mythic-characters:server:MoneyChanged' , function ( characterId , account , amount , newBalance , reason )
-- Handler code
end )
Parameters:
Account type: 'cash' or 'bank'
Change amount (positive = added, negative = removed)
Examples:
-- Update client HUD
AddEventHandler ( 'mythic-characters:server:MoneyChanged' , function ( characterId , account , amount , newBalance , reason )
local player = Fetch : SID ( characterId )
if player then
local source = player : GetData ( 'Source' )
TriggerClientEvent ( 'mythic-hud:client:UpdateMoney' , source , {
account = account ,
balance = newBalance ,
change = amount
})
end
end )
-- Log large transactions
AddEventHandler ( 'mythic-characters:server:MoneyChanged' , function ( characterId , account , amount , newBalance , reason )
if math.abs ( amount ) >= 10000 then -- Log transactions $10k+
Logger : Info ( 'Economy' , 'Large transaction' , {
character = characterId ,
account = account ,
amount = amount ,
newBalance = newBalance ,
reason = reason
}, { file = true })
end
end )
-- Achievement tracking
AddEventHandler ( 'mythic-characters:server:MoneyChanged' , function ( characterId , account , amount , newBalance , reason )
if account == 'bank' and newBalance >= 1000000 then
-- Unlock millionaire achievement
Achievements : Unlock ( characterId , 'millionaire' )
end
end )
-- Transaction log
AddEventHandler ( 'mythic-characters:server:MoneyChanged' , function ( characterId , account , amount , newBalance , reason )
Database . Game : insertOne ({
collection = 'transactions' ,
document = {
character = characterId ,
account = account ,
amount = amount ,
balance = newBalance ,
reason = reason ,
timestamp = os.time ()
}
})
end )
Client Events
mythic-characters:client:Spawned
Fired on the client when the character spawns in the world.
AddEventHandler ( 'mythic-characters:client:Spawned' , function ( character , location )
-- Handler code
end )
Parameters:
Spawn location {x, y, z, heading}
Examples:
-- Client-side initialization
AddEventHandler ( 'mythic-characters:client:Spawned' , function ( character , location )
-- Initialize HUD
SendNUIMessage ({
type = 'INIT_CHARACTER' ,
character = {
name = character . First .. ' ' .. character . Last ,
cash = character . Cash ,
jobs = character . Jobs
}
})
-- Load player appearance
TriggerEvent ( 'mythic-appearance:client:LoadAppearance' , character . metadata . appearance )
-- Enable controls
FreezeEntityPosition ( PlayerPedId (), false )
print ( 'Spawned as' , character . First , character . Last , 'at' , location . x , location . y , location . z )
end )
-- Camera transition
AddEventHandler ( 'mythic-characters:client:Spawned' , function ( character , location )
-- Fade out character selection screen
DoScreenFadeOut ( 500 )
Wait ( 500 )
-- Spawn player
SetEntityCoords ( PlayerPedId (), location . x , location . y , location . z )
SetEntityHeading ( PlayerPedId (), location . heading )
-- Fade in game world
Wait ( 1000 )
DoScreenFadeIn ( 1000 )
end )
mythic-characters:client:CharacterUpdated
Fired on the client when character data is updated.
AddEventHandler ( 'mythic-characters:client:CharacterUpdated' , function ( character )
-- Handler code
end )
Examples:
-- Update HUD
AddEventHandler ( 'mythic-characters:client:CharacterUpdated' , function ( character )
SendNUIMessage ({
type = 'UPDATE_CHARACTER' ,
character = character
})
end )
Using Events for Custom Logic
Hook Into Character Creation
-- Add custom welcome package
AddEventHandler ( 'mythic-characters:server:CharacterCreated' , function ( source , character )
-- Custom welcome logic
local welcomePackage = {
{ item = 'phone' , count = 1 },
{ item = 'water' , count = 5 },
{ item = 'sandwich' , count = 5 },
{ item = 'starter_pack' , count = 1 }
}
for _ , item in ipairs ( welcomePackage ) do
Inventory : AddItem ( character . SID , item . item , item . count )
end
-- Starting cash is set automatically via character defaults
end )
Track Playtime
local playtime = {}
-- Start tracking on character select
AddEventHandler ( 'mythic-characters:server:CharacterSelected' , function ( source , character )
playtime [ character . SID ] = os.time ()
end )
-- Save playtime on disconnect
AddEventHandler ( 'playerDropped' , function ( reason )
local player = Fetch : Source ( source )
if player then
local char = player : GetData ( 'Character' )
if char and playtime [ char : GetData ( 'SID' )] then
local stateId = char : GetData ( 'SID' )
local sessionTime = os.time () - playtime [ stateId ]
local metadata = char : GetData ( 'MetaData' ) or {}
local totalPlaytime = ( metadata . playtime or 0 ) + sessionTime
-- Update database directly as player is disconnecting
Database . Game : updateOne ({
collection = 'characters' ,
query = { SID = stateId },
update = {
[ '$set' ] = {[ 'MetaData.playtime' ] = totalPlaytime }
}
})
playtime [ stateId ] = nil
end
end
end )
Custom Job Logic
-- Custom logic when becoming police
AddEventHandler ( 'mythic-characters:server:JobChanged' , function ( characterId , newJob , newGrade , oldJob , oldGrade )
if newJob == 'police' then
-- Grant police access
local player = Fetch : SID ( characterId )
if player then
local source = player : GetData ( 'Source' )
-- Give police permissions
ExecuteCommand ( 'add_principal identifier.' .. GetPlayerIdentifier ( source , 0 ) .. ' group.police' )
-- Notify
TriggerClientEvent ( 'mythic-notifications:client:Send' , source , {
message = 'You are now a police officer' ,
type = 'success'
})
end
elseif oldJob == 'police' then
-- Remove police access when leaving
local player = Fetch : SID ( characterId )
if player then
local source = player : GetData ( 'Source' )
ExecuteCommand ( 'remove_principal identifier.' .. GetPlayerIdentifier ( source , 0 ) .. ' group.police' )
end
end
end )
Best Practices
Don't Block Event Handlers
❌ Bad: AddEventHandler ( 'mythic-characters:server:CharacterCreated' , function ( source , character )
-- Long synchronous operation
for i = 1 , 1000000 do
-- Heavy work
end
})
✅ Good: AddEventHandler ( 'mythic-characters:server:CharacterCreated' , function ( source , character )
-- Use thread for heavy work
CreateThread ( function ()
-- Heavy work
end )
})
Validate Character Exists
AddEventHandler ( 'mythic-characters:server:JobChanged' , function ( characterId , ...)
-- Validate character exists (check if online)
local player = Fetch : SID ( characterId )
if not player then
Logger : Warn ( 'Characters' , 'JobChanged for offline character' , {
console = true ,
file = true
}, {
characterId = characterId
})
return
end
-- Process event
end )
local sessionData = {}
AddEventHandler ( 'mythic-characters:server:CharacterSelected' , function ( source , character )
sessionData [ character . SID ] = {
loginTime = os.time (),
source = source
}
end )
AddEventHandler ( 'playerDropped' , function ()
local player = Fetch : Source ( source )
if player then
local char = player : GetData ( 'Character' )
if char then
sessionData [ char : GetData ( 'SID' )] = nil -- Clean up
end
end
end )
Next Steps
Characters - Exports Character management methods
Characters - Data Structure Character data schema
Event System Understanding the event system
Inventory Events Inventory-related events
Event Timing: Character events fire in a specific order. Use this to your advantage - for example, CharacterCreated fires before CharacterSelected, so you can set up initial data in the creation handler.