Cómo funcionan las integraciones#
Nada dentro de Appearance sabe qué framework, target o inventario usas. Cada uno de ellos está detrás de un pequeño archivo puente, y el puente correcto se elige al arrancar buscando los recursos iniciados.
Capa | Compatibles | Sin ella |
|---|---|---|
Framework |
| El recurso se detiene con un error. No hay modo standalone. |
Target |
| Las tiendas usan en su lugar una zona y un aviso [E]. Es la opción por defecto. |
Inventario |
| Los jugadores pueden abrir su inventario mientras el menú de ropa está abierto. No cambia nada más. |
Notificaciones |
| Recurre a las notificaciones y barras de progreso de ox_lib. |
Aviso de texto |
| Recurre al TextUI de ox_lib y, después, a texto 3D dibujado en el mundo. |
Tatuajes |
| Appearance gestiona sus propias tiendas de tatuajes desde config/tattoos.lua. Con Tattoo Creator instalado, sus tatuajes en tiempo de ejecución se suman a ellas. |
Ropa personalizada |
| La ropa que publicas con Clothing Creator la encuentra el escáner de packs como cualquier otro pack add-on. No hay nada que configurar. |
Fotografía |
| No puedes fotografiar tu propia ropa add-on. El catálogo incluido no se ve afectado. |
Clima |
| Solo se usa durante una sesión de fotos, para congelar la hora y el clima. Congélalos a mano o las fotos variarán. |
Cada integración opcional se degrada en silencio. Si falta un recurso, su función recurre al comportamiento integrado; nunca da error y nunca bloquea el inicio.
Forzar la detección#
La detección lee la lista de recursos iniciados y toma la primera coincidencia. Ambas listas están cerca del principio de config/main.lua y ambas se pueden reemplazar por un valor fijo.
-- config/main.lua — auto, the default
local frameworks = {
['es_extended'] = 'esx',
['qb-core'] = 'qb',
['qbx_core'] = 'qb'
}
Config.Framework = DependencyCheck(frameworks) or 'none' -- [AUTO]
local inventories = { ['qs-inventory'] = 'qs-inventory' }
Config.Inventory = DependencyCheck(inventories) or 'standalone' -- [AUTO]
-- Forced: skip detection entirely
Config.Framework = 'esx'
Config.Inventory = 'standalone'Vale la pena hacerlo cuando un recurso se ha renombrado en tu servidor, o cuando hay dos candidatos en ejecución a la vez: la detección recorre la tabla sin orden, así que con dos cores iniciados el ganador es realmente impredecible.
Frameworks#
Dónde termina una apariencia guardada depende del framework:
Framework | La apariencia se guarda en | Clave |
|---|---|---|
ESX | La columna skin de la tabla users de ESX |
|
QBCore / Qbox | playerskins, una fila activa por modelo de ped |
|
En QB un personaje guarda un aspecto por modelo de ped, con exactamente uno marcado como activo. Cambia de modelo y vuelve al anterior, y regresa el aspecto que tenías con ese modelo. ESX guarda un único blob sin variantes por modelo.
Multipersonaje#
Appearance usa como clave el identificador que le pase tu framework, así que el multipersonaje funciona sin configuración adicional, siempre que ese identificador sea por personaje. Los prefijos de ESX multicharacter y los citizenid de QB lo son. Una instalación básica de ESX que identifica a los usuarios por la licencia sin más le da a cada personaje de esa licencia la misma apariencia, y nada en Appearance puede distinguirlos.
Un framework que no está en la lista#
Dar soporte a tu propio core es deliberadamente sencillo: dos archivos, ambos legibles y editables incluso en una versión con escrow. Duplica custom/esx/ como custom/<yourcore>/ y trabaja desde ahí.
Cada archivo devuelve una tabla. types.lua enumera exactamente qué funciones deben implementar el lado del servidor y el del cliente: identificadores, cuentas de dinero, ítems, nombre y rango del trabajo, la comprobación de administrador, y la carga y el guardado de una apariencia. Después, registra la carpeta:
-- config/main.lua
local frameworks = {
['es_extended'] = 'esx',
['qb-core'] = 'qb',
['qbx_core'] = 'qb',
['my_core'] = 'mycore', -- loads custom/mycore/{client,server}.lua
}La última pieza: el lado del cliente del puente debe establecer la variable global PlayerData y llamar a InitAppearance() en cuanto tu core indique que el jugador se ha cargado. Todo lo demás parte de ahí.
Todo custom/, config/, locales/, types.lua y las carpetas de proveedores siguen siendo legibles y editables en una versión con escrow, por diseño.
La ropa no es un ítem#
Conviene decirlo claramente, porque es la pregunta más frecuente. Appearance no convierte las prendas en ítems del inventario ni registra ítems de ropa en ningún inventario. La integración con el inventario hace exactamente una cosa: impide que un jugador abra su inventario mientras el menú de ropa está abierto.
El dinero solo se toca al pagar, a través de las cuentas de efectivo, banco o dinero negro de tu framework. Para dar soporte a otro inventario, copia client/custom/inventory/standalone.lua, protégelo con tu propio nombre, implementa ToggleInventoryClothing(state) y añade el recurso a la tabla inventories.
Compatibilidad directa#
Appearance responde a la interfaz pública de los tres scripts que más a menudo reemplaza, así que no tienes que reescribir tus scripts existentes. Son capas de compatibilidad (escribe el código nuevo con la API real), pero el código antiguo sigue funcionando.
illenium-appearance
Cada export que registra Appearance también se registra con el nombre illenium-appearance, y se responde a los eventos de su menú de outfits.
-- all of these keep working unchanged
exports['illenium-appearance']:getPedAppearance(PlayerPedId())
exports['illenium-appearance']:startPlayerCustomization(cb, cfg)
TriggerEvent('illenium-appearance:client:openOutfitMenu')
TriggerEvent('illenium-appearance:client:openJobOutfitsMenu')
TriggerServerEvent('illenium-appearance:server:saveAppearance', skin)Una configuración de menú al estilo de illenium que se pase a startPlayerCustomization se traduce automáticamente, incluidos sus alias de propConfig.
esx_skin y skinchanger (solo ESX)
TriggerEvent('skinchanger:getSkin', function(skin) print(skin.model) end)
TriggerEvent('skinchanger:loadSkin', skin)
TriggerEvent('skinchanger:loadClothes', nil, clothes) -- legacy tshirt_1 keys
TriggerEvent('esx_skin:openSaveableMenu', onSubmit, onCancel)
exports['skinchanger']:GetSkin()
exports['skinchanger']:LoadSkin(skin)
exports['skinchanger']:LoadClothes(nil, clothes)El antiguo formato plano de skin se convierte al recibirse, así que un script de trabajo que viste a un jugador con claves al estilo de tshirt_1 sigue funcionando.
qb-clothing y qb-clothes (solo QB)
TriggerEvent('qb-clothing:client:openMenu') -- the new-character creator
TriggerEvent('qb-clothes:client:CreateFirstCharacter')
TriggerEvent('qb-clothing:client:openOutfitMenu')
TriggerEvent('qb-clothing:client:loadOutfit', { outfitData = data, name = 'Uniform' })Appearance también dispara qb-clothing:client:onMenuClose cuando se cierra su menú, y reacciona a qb-multicharacter:client:chooseChar borrando los tatuajes y los outfits en caché.
Migrar desde otro script de ropa#
Las apariencias guardadas se trasladan con un solo comando. Ejecútalo una vez y luego elimina el recurso antiguo y el grupo de administración que podía ejecutarlo.
Si vienes de | Comando | Necesita |
|---|---|---|
|
| group.admin, ESX |
|
| group.god, QB/Qbox |
|
| group.god, QB/Qbox |
|
| group.admin |
|
| group.admin |
Skins de Appearance 1.x |
| Consola del servidor, o el ace command.convert |
/migrateskins significa dos cosas distintas
Solo se carga una versión del comando, según tu framework, y sus firmas son diferentes. En ESX no recibe argumentos y convierte la columna skin de cada fila de users que todavía parezca un blob antiguo de esx_skin. En QB necesita el origen como argumento y está protegido por group.god, no por group.admin.
/migrateskins qb-clothing se ejecuta a través de tu propio cliente
Las filas antiguas de qb-clothing guardan el modelo del ped como hash, y la única forma fiable de leerlo es ponérselo. El comando aplica cada skin afectada al administrador que lo ejecutó, una por una, lee el resultado y lo guarda en el nuevo formato. Quédate en el juego y deja la ventana enfocada hasta que termine. Las filas cuyo modelo ya es un nombre se omiten y se informan.
/migrate_rcore vacía primero playerskins en QB
En QBCore el comando borra toda la tabla playerskins antes de insertar las apariencias de rcore convertidas. En ESX, en cambio, actualiza users.skin por identificador. El propio texto de ayuda del comando dice que hagas una copia de seguridad; hazla.
Los modelos de ped que no puede resolver recurren a mp_m_freemode_01 con un aviso en la consola, así que inicia los recursos que cargan tus peds personalizados antes de ejecutarlo.
Los outfits de illenium normalmente no necesitan migración
illenium-appearance ya guarda sus outfits en player_outfits, la misma tabla que lee Appearance, en un formato compatible. En la mayoría de los casos los jugadores simplemente encuentran sus outfits esperándolos. Ejecuta /migrateoutfits solo si no aparecen, y recuerda que importar [sql]/main.sql en un servidor existente elimina esa tabla, que es el motivo habitual por el que los outfits desaparecen durante una migración.
De dónde salen las imágenes del catálogo#
Cada fila del catálogo guarda la dirección de su propia imagen. Las aproximadamente 28.900 filas incluidas apuntan a la CDN de Quasar y ya están fotografiadas, así que un servidor nuevo no necesita ningún tipo de alojamiento de imágenes.
El alojamiento solo importa para la ropa que añades tú. Cuando fotografías un pack add-on, la imagen se recorta en la interfaz y se sube a FiveManage con el token de config/fivemanage.lua, y la dirección devuelta se escribe en la fila del catálogo. El archivo trae un token de ejemplo: reemplázalo por el tuyo antes de la primera ejecución.
Junto al script vienen tres piezas auxiliares. greenscreen-map es el estudio al que te teletransporta la captura, y es la única que la mayoría de los dueños llega a iniciar. clothing-image-saver y el servicio de etiquetado son herramientas internas usadas para crear el catálogo incluido: un host de imágenes local y un servicio de etiquetado sin conexión. Ninguna es necesaria para tener un servidor, y el bloque de etiquetado de la configuración está marcado solo para desarrollo y viene desactivado.
Idiomas#
En locales/ vienen 41 traducciones: árabe, búlgaro, bengalí, catalán, checo, danés, alemán, griego, inglés, español, estonio, persa, finés, francés, hebreo, hindi, croata, húngaro, indonesio, italiano, japonés, coreano, lituano, letón, malayo, neerlandés, noruego, polaco, portugués, rumano, ruso, eslovaco, esloveno, sueco, suajili, tailandés, turco, ucraniano, urdu, vietnamita y chino.
Config.Locale = 'es' -- the filename in locales/, without .jsonSi falta un archivo, se usa el inglés con un aviso en la consola, y lo mismo ocurre con cualquier clave individual que una traducción todavía no tenga, así que una traducción personalizada a medias nunca muestra una etiqueta vacía. Muestra la inglesa y te dice qué clave añadir.



