Exports, eventos y hooks
El código Lua va encriptado con escrow, pero estos exports, eventos y hooks de la config dejan que tus otros scripts trabajen con ZAIDERS Appearance.
Exports del cliente
openShop
Abre un menú donde esté el jugador: el armario de una casa, el vestuario de un trabajo, una zona de ox_target en una tienda.
exports.zaiders_appearance:openShop('clothing') -- la tienda de ropa
exports.zaiders_appearance:openShop('barber') -- la barbería
exports.zaiders_appearance:openShop('tattoo') -- la tienda de tatuajes
exports.zaiders_appearance:openShop('wardrobe') -- outfits y uniformes
exports.zaiders_appearance:openShop('wardrobe', { tab = 'job' }) -- directo a los uniformes del trabajo
exports.zaiders_appearance:openShop('wardrobe', { tab = 'gang' }) -- directo a los uniformes de la bandaDevuelve true cuando el tipo es válido y el menú va en camino, y false con un tipo desconocido. Las reglas de siempre se mantienen: el jugador no puede estar muerto, caído ni esposado, se consulta Config.CanOpenMenu, y el servidor revisa cada pago y cada guardado, abra donde abra el menú.
-- Una zona de ox_target que abre el guardarropa de una comisaría
exports.ox_target:addBoxZone({
coords = vec3(461.5, -998.1, 30.6),
size = vec3(2, 2, 2),
options = {
{
label = 'Vestuario',
icon = 'fa-solid fa-shirt',
groups = 'police',
onSelect = function()
exports.zaiders_appearance:openShop('wardrobe', { tab = 'job' })
end,
},
},
})isOpen
if exports.zaiders_appearance:isOpen() then
-- hay un menú abierto, o abriéndose
endsyncsTattoos
Si ZAIDERS Appearance les está mostrando a los demás los tatuajes de cada jugador (ver Lo que ven los demás jugadores). Un pack de tatuajes con su propio script de sincronización puede hacerse a un lado mientras diga true, así los dos no les ponen tatuajes a los mismos jugadores:
local ok, on = pcall(function() return exports.zaiders_appearance:syncsTattoos() end)
if ok and on then
-- ZAIDERS Appearance muestra los tatuajes de todos, con sus capas: no tocar los peds de los demás
endsetTattooBusy
Para la tienda de tatuajes de otro recurso, cuando este menú no está a cargo de los tatuajes: mientras diga true (60 segundos como mucho), lo que el jugador se prueba ahí no se les manda a los demás. Los menús con el foco del NUI o una cámara de script ya se detectan solos; llámalo si el tuyo no tiene ninguno de los dos.
exports.zaiders_appearance:setTattooBusy(true) -- se abrió tu tienda de tatuajes
exports.zaiders_appearance:setTattooBusy(false) -- y se cerrógetAppearance, setAppearance y reloadSkin
Un menú de personajes o de outfits guardados puede leer y poner la apariencia entera (cara, pelo, maquillaje y ropa) en el formato que guarda el servidor. Lo que se pone así no se guarda: lo que un jugador se queda pasa por las tiendas.
local look = exports.zaiders_appearance:getAppearance() -- la apariencia del jugador (o getAppearance(ped))
local ok = exports.zaiders_appearance:setAppearance(look) -- con su modelo, y los tatuajes guardados de vuelta
local ok2 = exports.zaiders_appearance:reloadSkin() -- vuelve a poner la apariencia guardada del jugadorsetAppearance y reloadSkin devuelven true si la apariencia se puso. Mientras este menú (o el estudio de fotos) está abierto, los dos contestan false: en ese momento el ped del jugador es del menú.
Altura del personaje
La altura del personaje viene apagada de fábrica. Así, getHeight devuelve nil, pauseHeight no hace nada y zaiders_appearance:heightChanged nunca se dispara.
getHeight
La altura de un jugador en cm, como la puso el servidor, para el ped que ve este juego (nil: no está cerca, no es el hombre o la mujer freemode, o la altura está apagada):
local cm = exports.zaiders_appearance:getHeight(GetPlayerServerId(PlayerId())) -- 172pauseHeight
Tu personaje con la altura del juego en todas las pantallas mientras algún recurso lo tenga en pausa: para un emote de sentarse, así nadie se hunde en una silla. Ver Altura del personaje.
exports.zaiders_appearance:pauseHeight(true) -- se sienta
exports.zaiders_appearance:pauseHeight(false) -- se levantabaseCoords
Dónde está parado un ped sin la bajada de la altura. Un personaje bajo se dibuja más abajo, así que usa esto en vez de GetEntityCoords para guardar una posición:
local coords = exports.zaiders_appearance:baseCoords(PlayerPedId())Exports del servidor
ownsPed
Si el personaje actual de un jugador tiene un ped de la tienda de peds (comprado, regalado o canjeado con un código):
local tiene = exports.zaiders_appearance:ownsPed(source, 'a_c_chop') -- true o falseisInStudio
Si un jugador está ahora en el estudio de fotos, según el servidor. Úsalo para exceptuar a ese admin de los controles del anticheat y del AFK: ver El estudio de fotos.
local enEstudio = exports.zaiders_appearance:isInStudio(source) -- true o falsewearOutfit
Para otro guardarropa o menú de outfits (su lado del servidor): uno de sus outfits que el jugador tiene se pone como uno de este guardarropa. Su ropa va sobre la apariencia guardada (la cara y el pelo quedan) y se guarda, con la misma revisión de las prendas solo para un trabajo, una banda o VIP. Tu script responde de que el outfit es del jugador: léelo de tu base de datos, no del juego del jugador.
-- outfit: { model, components, props }, como tabla o texto JSON; el nombre es para el log
local result = exports.zaiders_appearance:wearOutfit(source, outfit, 'Fiesta')
if result.ok then
-- result.skin: la apariencia guardada (JSON). Pónsela en el juego del jugador con setAppearance
else
-- result.message: por qué no, en el idioma del servidor (result.reason dice qué caso es)
endgetHeight (servidor)
La altura del personaje de un jugador, para el sexo de su ped ahora (nil sin personaje o con la altura apagada):
local h = exports.zaiders_appearance:getHeight(source) -- { cm = 172, scale = 0.95, sex = 'f' }Eventos del cliente
HUD
Se dispara al abrir y al cerrar un menú o el panel. Tu HUD lo puede escuchar para esconderse:
-- hidden: true al abrir un menú, false al cerrarlo
-- menu: 'clothing', 'barber', 'tattoo', 'wardrobe', 'creator' o 'panel'
AddEventHandler('zaiders_appearance:hud', function(hidden, menu)
-- tu HUD acá
end)Si tu HUD tiene un export para mostrarse y esconderse, no hace falta código: agrégalo en Config.HideHud.resources. Ver la Referencia de la config.
Creador cerrado
Se dispara cuando se cierra el creador de personaje, normalmente justo después de guardar el personaje nuevo:
AddEventHandler('zaiders_appearance:creator:closed', function()
-- por ejemplo, mostrar tu selector de aparición
end)Modelo cambiado
Se dispara cuando este menú cambia el modelo del jugador para quedarse: un ped o el otro sexo que se lleva de una tienda, una apariencia cargada con otro modelo, el sexo de un personaje nuevo. No mientras solo se prueba un modelo. El ped nuevo no tiene tatuajes, así otro recurso de tatuajes le puede volver a poner los suyos:
AddEventHandler('zaiders_appearance:modelChanged', function(ped, model)
TriggerEvent('my_tattoos:applyOwnedTattoos') -- el evento propio de tu recurso de tatuajes
end)En ESX, mientras otro recurso está a cargo de los tatuajes y skinchanger no está prendido, también dispara el skinchanger:modelLoaded del propio skinchanger, que las tiendas de tatuajes de ESX ya escuchan (no con Config.Compat.exports = false).
Cambió la altura
Solo con la altura del personaje prendida. Se dispara cuando cambia la altura de un jugador (el creador, un pedido aceptado), en cada juego que se entera:
AddEventHandler('zaiders_appearance:heightChanged', function(serverId, value)
-- value = { m = cm o nil, f = cm o nil }: nil es la altura normal de ese sexo
end)El estudio de fotos
Mientras un admin saca las fotos del catálogo, su personaje queda invisible, invencible y quieto, lejos y alto sobre el mar, muchas veces durante horas. Los anticheats, los kicks por AFK y otros scripts pueden saberlo y dejar en paz a ese jugador.
Para exceptuar a ese jugador, pregúntale al servidor. isInStudio es true mientras el servidor tiene a ese jugador en el estudio, y solo el servidor lo decide:
-- servidor
if exports.zaiders_appearance:isInStudio(source) then
return -- en el estudio de fotos: saltear los controles de teletransporte, godmode, invisibilidad y AFK
endO lleva tu propia lista con el evento del servidor, que se dispara cuando el admin entra (true) y cuando sale o se desconecta (false):
-- servidor
AddEventHandler('zaiders_appearance:studio', function(src, inside)
-- src: el ID de servidor del jugador
end)El juego del propio admin también recibe un evento del cliente, para lo que pasa solo en ese juego (un HUD, un script de clima):
-- cliente, en el juego del propio admin
AddEventHandler('zaiders_appearance:studio', function(inside)
end)El state bag del jugador Player(source).state.zaidersStudio también dice true mientras está en el estudio, pero es solo informativo: el juego de un jugador puede escribir su propio state bag, así que nunca lo uses para exceptuar a nadie de un anticheat o de un control de AFK.
Scripts de clima y de hora
El estudio mantiene su propia luz de mediodía. Para pausar mientras tanto tu script de clima o de hora, agrega sus eventos del cliente en Config.Studio.syncPause: enter se dispara cuando el admin entra al estudio y leave cuando sale.
Config.Studio = {
-- ...
syncPause = {
{ enter = 'qb-weathersync:client:DisableSync', leave = 'qb-weathersync:client:EnableSync' }, -- el de fábrica
{ enter = 'mi-clima:pausar', leave = 'mi-clima:seguir' },
},
}A un script sin ese evento, como vSync, hay que apagarlo mientras sacas fotos, o hacer que deje en paz al admin (por ejemplo, con el evento del cliente de arriba). F8 avisa cuando otro script le pelea la luz al estudio.
Hooks de la config
shared/config.lua está abierto, así que puedes escribir ahí funciones chicas que corren en el juego del jugador.
Tus notificaciones
Config.Notify = function(text, kind)
-- kind: 'inform', 'success' o 'error'
exports['mis_avisos']:Notify(text, kind)
endTu propia regla para abrir los menús
Config.CanOpenMenu = function()
-- devuelve false para no abrir el menú, por ejemplo en una persecución
return not LocalPlayer.state.enPersecucion
endTu HUD
Config.HideHud = {
enabled = true,
resources = {
{ resource = 'mi-hud', export = 'SetHudVisible' }, -- recibe false al abrir, true al cerrar
{ resource = 'otro-hud', event = 'otro-hud:toggle', hide = false, show = true },
{ resource = 'tercer-hud', export = 'SetVisible', changed = 'tercer-hud:changed' },
},
custom = function(hidden, menu)
-- cualquier otra cosa
end,
}Exports de otros menús de ropa
ZAIDERS Appearance también contesta los exports y eventos de illenium-appearance, fivem-appearance, qb-clothing y de skinchanger y esx_skin de ESX, mientras esos recursos no están prendidos. Los scripts hechos para ellos funcionan sin cambios. Ver Frameworks y compatibilidad.
El formato de la apariencia
La apariencia se guarda en el formato de apariencia de QBCore, el mismo JSON que usan illenium-appearance y qb-clothing, en playerskins.skin (QBCore y Qbox), o en el formato de skinchanger en users.skin (ESX). En el menú, Peds → JSON del personaje copia la apariencia de un personaje en ese formato. Los admins también pueden pegar uno ahí.
