Skip to main content

Flujo y eventos

Flujo general

sequenceDiagram
participant P as Jugador
participant L as Loadingscreen
participant C as Client
participant S as Server
participant DB as MySQL

P->>L: Conecta
L-->>L: Barra de progreso (eventos FiveM)
L->>C: Carga completa → ShutdownLoadingScreen
C->>C: spawnmanager:setAutoSpawn(false)
C->>P: Muestra Menú Principal (NUI)
P->>C: Click "JUGAR"
C->>S: getCharacters
S->>DB: SELECT * FROM fiverank_intro_characters
DB-->>S: rows
S-->>C: Lista de slots (5)
C->>P: Char select + preview ped
P->>C: Selecciona slot
C->>S: selectCharacter(slot)
S->>DB: UPDATE last_played
S-->>C: { character, position }
C->>C: Cinematic.run() — descenso desde el cielo
C->>P: Control del personaje

Eventos del servidor

Llamados por el cliente

EventoPayloadQué hace
fiverank_intro:server:getCharactersDevuelve los 5 slots del jugador
fiverank_intro:server:createCharacter{slot, firstname, lastname, dob, gender, nationality}Crea/sobrescribe un slot
fiverank_intro:server:deleteCharacterslot:intBorra un slot
fiverank_intro:server:selectCharacterslot:intMarca el slot como activo y devuelve sus datos
fiverank_intro:server:savePositionslot, {x,y,z,h}Guarda posición actual (auto cada 30 s)

Disparados por el servidor

EventoPayload
fiverank_intro:client:receiveCharactersslots[]
fiverank_intro:client:createResult{ok, error?}
fiverank_intro:client:deleteResult{ok, slot}
fiverank_intro:client:selectResult{ok, character}

Engancharse desde otros scripts

"El jugador acaba de entrar al mundo"

Al terminar la cinemática, FR Intro dispara el evento estándar de FiveM:

-- En cualquier client script:
AddEventHandler('playerSpawned', function()
print('El jugador completó la cinemática y tiene el control')
end)

Saber qué personaje eligió

-- client side
RegisterNetEvent('fiverank_intro:client:selectResult', function(res)
if res.ok then
print('Slot elegido:', res.character.slot)
print('Nombre:', res.character.firstname, res.character.lastname)
print('Modelo:', res.character.pedModel)
end
end)

Forzar abrir el menú de nuevo (ej. comando /cambiarpersonaje)

Esto no viene de caja, pero es trivial añadirlo en client/main.lua:

RegisterCommand('cambiarpersonaje', function()
TriggerServerEvent('fiverank_intro:server:getCharacters')
CharSelect.show(nil)
SendNUIMessage({ action = 'show', screen = 'charselect' })
SetNuiFocus(true, true)
end)

Persistencia

  • Cada 30 segundos el cliente envía la posición actual al servidor.
  • Se guarda en fiverank_intro_characters.position como JSON.
  • La próxima vez que el jugador entre a ese slot, la cinemática terminará en esas coordenadas.

Si quieres desactivar el auto-save y manejarlo tú, comenta el CreateThread al final de client/main.lua.

Integración con ESX / QBCore / qbx

FR Intro no reemplaza la lógica de personajes de tu framework. Guarda metadatos paralelos (slot, nombre cosmético, last_played, position) para controlar el flujo de entrada.

Si quieres que cada slot esté ligado a un citizenid (QB) o identifier (ESX) específico, edita server/main.luaselectCharacter:

RegisterNetEvent('fiverank_intro:server:selectCharacter', function(slot)
local src = source
-- ... existing code ...
if res.ok then
-- Carga el personaje en tu framework:
if Framework.name == 'qb' then
Framework.core.Player.Login(src, row.citizenid)
elseif Framework.name == 'esx' then
-- xPlayer.set('character', row.citizenid) etc.
end
end
end)

(Necesitarás añadir una columna citizenid a la tabla.)

Siguiente paso

➡️ Personalización visual