Cómo funcionan las integraciones#
Crosshair Creator no se comunica en absoluto con tu framework. Una mira es un ajuste visual personal, así que los jugadores se reconocen por su identificador license: y los administradores por un ace. Por eso la misma instalación funciona sin cambios en cualquier servidor:
Capa | Compatible | Sin ella |
|---|---|---|
Framework | Cualquiera — QBCore, Qbox, ESX, ox_core, ND_Core, vRP o ninguno | No cambia nada. |
Base de datos |
| Los jugadores reciben la cruz predeterminada en cada conexión; la mira activa, los códigos para compartir y los ajustes de administración no se guardan. |
Notificaciones | Integradas, | Se usa el aviso integrado. |
Acceso de administrador | Aces de FiveM — | Nadie ve la pestaña Admin; se aplican los valores predeterminados. |
Discord | Un webhook para el registro de auditoría de administración | No se publica nada. |
Notificaciones#
Config.NotificationType decide cómo se muestran mensajes como "Crosshair received from …" o "Server unreachable":
Valor | Muestra el mensaje con |
|---|---|
| El aviso propio del script, arriba en el centro, con el mismo estilo que el panel. La opción predeterminada y recomendada. |
| El centro de notificaciones de qs-interface. Recurre a ox_lib si qs-interface no está iniciado. |
| qs-notify. Recurre a ox_lib si no está iniciado. |
|
|
| El evento de notificación de ESX. |
| Tu propio sistema, mediante |
-- config/main.lua
Config.NotificationType = 'custom'
Config.NotificationDuration = 5000 -- ms
-- client/custom/main.lua
function OnCustomNotify(title, description, nType, duration, icon)
-- nType is 'success' | 'error' | 'inform' | 'warning'
exports['okokNotify']:Alert(title, description, duration, nType)
endUn valor mal escrito, o 'custom' sin un OnCustomNotify, nunca pierde el mensaje: se muestra con ox_lib y se imprime un aviso en la consola F8.
Registro de auditoría en Discord#
Cada cambio hecho en la pestaña Admin se puede publicar en un canal de Discord como embed, con el nombre y el id de servidor del administrador, qué cambió y cuándo. Actívalo en dos sitios:
-- config/main.lua
Config.Admin = {
-- ...
EnableWebhookLog = true,
}
-- config/webhooks.lua
Config.Webhooks = {
AdminAuditLog = 'https://discord.com/api/webhooks/<id>/<token>',
}Embed | Se envía cuando |
|---|---|
Feature Enabled / Disabled — verde / rojo | Se cambia un interruptor de función. Muestra qué función y su nuevo estado. |
Official Crosshair Updated / Cleared — azul / naranja | Se establece o se quita la mira oficial. Muestra su código para compartir. |
Server Identity Updated — morado | Cambia el nombre del servidor, el logo o el color de tema predeterminado. Enumera cada campo modificado. |
Los embeds se escriben en el idioma configurado en Config.Locale. El pequeño avatar en la parte superior de cada mensaje es el del propio webhook — configúralo una vez en Discord en Edit Webhook. Si Discord rechaza una publicación, la consola del servidor imprime el estado HTTP y la respuesta de Discord.
Hooks#
Los archivos de client/custom/ y server/custom/ están abiertos, no cifrados. Cada uno contiene funciones vacías que el script llama en el momento adecuado — rellena las que necesites.
Hooks del cliente#
Función | Se llama |
|---|---|
| Antes de que se abra el panel. Devuelve |
| Justo después de mostrarse el panel. |
| Cada vez que una mira pasa a estar activa — un preset, un diseño de la biblioteca, el creador o un export. |
| Para cada mensaje, cuando |
-- client/custom/main.lua — only on-duty players may open the panel (QBCore)
function OnBeforeOpen()
local PlayerData = exports['qb-core']:GetCoreObject().Functions.GetPlayerData()
if PlayerData.job and PlayerData.job.onduty then return true end
Notify('Unavailable', 'You must be on duty to open the crosshair panel.', 'warning')
return false
end
-- A sound every time a crosshair is applied
function OnApply(cfg)
PlaySoundFrontend(-1, 'SELECT', 'HUD_FRONTEND_DEFAULT_SOUNDSET', true)
endHay más ejemplos en client/custom/examples.lua. Notify(title, description, nType, duration) está disponible en cualquiera de ellas y pasa por tu sistema de notificaciones configurado.
Hooks del servidor#
Función | Se llama |
|---|---|
| Cuando un jugador envía un diseño a un jugador cercano. |
| Después de cada cambio de administración. |
server/custom/commands.lua es el lugar para cualquier comando de chat propio, como uno que otorgue administración de la mira a un id de jugador.
Ajustar las dinámicas#
Cómo se siente cada comportamiento dinámico lo decide el servidor, en config/dynamics.lua. Los jugadores deciden si un comportamiento está activado; el servidor decide cómo se comporta.
Config.Dynamics.FireFeedback = {
ExpandPerShot = 0.5, -- how much the gap and arms grow per shot (0.5 = 50%)
ExpandMax = 2.0, -- the cap, as a multiple of the base size
HoldDurationMs = 200, -- how long it stays open after the last shot
DecayPerMs = 0.005, -- how fast it shrinks back afterwards
RateLimitMs = 50,
PollIntervalMs = 50,
}
Config.Dynamics.LowAmmo = {
HalfMagRatio = 0.5, -- orange at or below this share of a full magazine
CriticalRounds = 5, -- red at or below this many rounds (empty included)
PollIntervalMs = 250,
}
Config.Dynamics.TargetDetect = {
PollIntervalMs = 100, -- how often the reticle checks what it is on
}Cada valor se limita a un rango seguro cuando se inicia el recurso, así que una errata no puede hacer que una comprobación se ejecute cada frame ni romper los cálculos. Los valores marcados con [ADV] en el archivo tienen que ver con el coste, no con la sensación: más bajo significa más reactivo y algo más de CPU.
Nada de esto se ejecuta mientras el jugador no apunta. Cuando apunta, solo se ejecutan los comportamientos activados, juntos en una única comprobación compartida — y si la retícula está oculta para el arma actual, no se ejecuta nada.
Límites para compartir#
Todo lo que protege al servidor del spam de diseños compartidos está en Config.Share:
Config.Share = {
DefaultRadiusM = 30, -- how far "nearby" reaches, in metres
MaxRadiusM = 100, -- the most a player can ask for; the server clamps it
CooldownMs = 2000, -- how often one player may refresh the nearby list
TTLSeconds = 60, -- how long an incoming build waits before it expires
MaxPerMinute = 5, -- builds one player may send per minute
CodeTTLDays = 30, -- how long a QSR code keeps working
MaxCodesPerLicensePerDay = 100, -- new codes one player may register per day
}Idiomas#
Se incluyen 21 traducciones en locales/: árabe (ar, de derecha a izquierda), búlgaro, checo, danés, alemán, inglés, español, francés, hindi, húngaro, italiano, japonés, coreano, neerlandés, noruego, portugués, rumano, ruso, sueco, turco y chino simplificado (zh-CN). Config.Locale establece a la vez el idioma del panel, las notificaciones y los embeds de Discord.
Para añadir un idioma, copia locales/en.json a locales/<code>.json, traduce los valores y pon Config.Locale con ese código. No hace falta tocar nada más. Cualquier clave que falte en una traducción recurre al inglés en lugar de mostrar la clave sin procesar.



