Zum Inhalt springen

UI-/NUI-Konventionen

Jede Ressource hat ihre eigene NUI-Seite (ui_page 'html/index.html'). bs_ui ist das HUD, die Benachrichtigungen und die gemeinsamen Teile.

Wenn dein Panel aufgeht, kündigst du es an. Jedes andere Panel hört das und schließt sich. Wenn deins schließt, kündigst du das auch an. Echter Code aus bs_config:

local function close()
if not isOpen then return end
isOpen = false
SetNuiFocus(false, false)
SendNUIMessage({ action = 'close' })
TriggerEvent('bs:ui:closed', 'config')
end
local function open()
if isOpen then return close() end
isOpen = true
SetNuiFocus(true, true)
SendNUIMessage({ action = 'open', data = data })
TriggerEvent('bs:ui:opened', 'config')
end
-- another UI took over: step aside
AddEventHandler('bs:ui:opened', function(what)
if what ~= 'config' and isOpen then close() end
end)
AddEventHandler('onResourceStop', function(res)
if res == GetCurrentResourceName() and isOpen then
SetNuiFocus(false, false)
TriggerEvent('bs:ui:closed', 'config')
end
end)

Regeln:

  • Übergib den Namen deines Panels in beiden Events. Handler prüfen ihn; ein Handler, der auf jedes Schließen reagierte, hat die Feldkarte monatelang kaputt gemacht.
  • Paare sie an jedem Ausgang: Schließen-Button, Esc, Umschalttaste, eine andere UI öffnet sich, Ressource stoppt. Verpasst du einen, steckt der Spieler mit Mauszeiger und ohne Spiel fest.
  • Melde opened, nachdem du offen bist, und schließe dich aus deinem eigenen Handler, nimm nicht an, dass andere es tun.

/refreshui (bs_ui) ist der Panikknopf: Er schließt alles, gibt den Fokus frei und löst bs:ui:closed mit nil aus.

-- client
TriggerEvent('bs:ui:notify', { type = 'info', title = 'Radio', message = 'Signal found.', duration = 3000 })
-- server
TriggerClientEvent('bs:ui:notify', src, { type = 'error', title = 'Denied', message = 'Nope.' })

Im Code verwendete Typen: info, success, error.

Seiten sind für 1920x1080 gelayoutet. Binde den gemeinsamen Scaler ein, damit sie auf jede Auflösung passen:

<script src="https://cfx-nui-bs_ui/html/shared/scale.js"></script>

Er skaliert <body> mit einem Transform: --ui-scale = clamp(min(w/1920, h/1080), 0.6, 1.25). Spieler können ihn in den Einstellungen überschreiben (0.6 bis 1.4).

Was du bei der Nutzung wissen musst:

  • Schreibe im Seiten-CSS vh/vw als calc(Nvh / var(--ui-scale, 1)), damit sie echte Viewport-Anteile bleiben.
  • JS, das style.left/top aus clientX/clientY oder einem Bounding Rect setzt, muss durch BSScale.get() teilen. BSScale.w() / BSScale.h() liefern den lokalen Viewport.
  • Abwählen mit <html data-bs-noscale>.
  • html, body { background: transparent !important; } auf jeder Seite. Sonst liegt ein schwarzer Bildschirm über dem Spiel.
  • Keine NUI-Nachrichten pro Frame im Leerlauf. Bei Änderung senden oder drosseln (das Drohnen-HUD sendet im Flug alle 150 ms, das ist ungefähr das Maximum).
  • Die Palette ist Bernstein / Rost / Knochen / Staub auf fast Schwarz. Nutze die CSS-Tokens von bs_ui und bs_menu/html/css/faction-hub.css wieder. Keine externen Schriften oder CDNs, Spieler haben dafür womöglich keinen Internetzugang, und es ist ohnehin eine Datenschutzfrage.
  • Icons: Linien-Icons in bs_ui/html/js/icons.js.
  • Sounds: bs_ui/html/js/sound.js kümmert sich um positionale Sounds (maxDistance, Panning).