Ersetzt die qbx.drawText2d-Anzeige (rohe Zahl plus Uhr-Emoji in der Ecke, jeden Frame neu gezeichnet) durch ein NUI-Overlay. - Luft als Ring mit mm:ss, Farbstufen aus config.warnAtSeconds abgeleitet, Pulsieren im kritischen Bereich - Tiefe in Metern ueber GetWaterHeight, geglaettet damit Wellengang die Zahl nicht zappeln laesst; Einfaerbung ab config.deepWarningDepth - Platz fuer den Lampen-Status, wird in Phase 5 befuellt - Sichtbar nur mit angelegter Ausruestung unter Wasser, mit Fade - Updates gedrosselt auf 4/s statt jeden Frame - Kein backdrop-filter (bekannter FiveM-Bug) Die geglaettete Tiefe speist auch den tiefenabhaengigen Verbrauch, der bisher bei jedem Tick neu und ungeglaettet gemessen wurde. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,66 @@
|
||||
// Das HUD ist reine Anzeige - es sendet nichts zurueck an den Client.
|
||||
// Der Lua-Client schickt den kompletten Zustand, damit die Locale-Texte an einer
|
||||
// Stelle bleiben und hier nichts uebersetzt werden muss.
|
||||
|
||||
const RING = 327; // 2 * PI * 52, muss zu --ring in style.css passen
|
||||
|
||||
const hud = document.getElementById('hud');
|
||||
const gaugeFill = document.getElementById('gauge-fill');
|
||||
const airValue = document.getElementById('air-value');
|
||||
const depthValue = document.getElementById('depth-value');
|
||||
const lamp = document.getElementById('lamp');
|
||||
|
||||
const labels = {
|
||||
air: document.getElementById('air-label'),
|
||||
depth: document.getElementById('depth-label'),
|
||||
lamp: document.getElementById('lamp-label')
|
||||
};
|
||||
|
||||
function formatTime(seconds) {
|
||||
const total = Math.max(0, Math.floor(seconds));
|
||||
const mm = String(Math.floor(total / 60)).padStart(2, '0');
|
||||
const ss = String(total % 60).padStart(2, '0');
|
||||
return `${mm}:${ss}`;
|
||||
}
|
||||
|
||||
function render(state) {
|
||||
hud.classList.toggle('hidden', !state.visible);
|
||||
|
||||
if (!state.visible) return;
|
||||
|
||||
const capacity = state.capacity > 0 ? state.capacity : 1;
|
||||
const ratio = Math.min(1, Math.max(0, state.oxygen / capacity));
|
||||
|
||||
gaugeFill.style.strokeDashoffset = String(RING * (1 - ratio));
|
||||
airValue.textContent = formatTime(state.oxygen);
|
||||
depthValue.textContent = state.depth.toFixed(1);
|
||||
|
||||
// Warnstufen kommen als Restsekunden vom Client, damit sie zu
|
||||
// config.warnAtSeconds passen statt hier nochmal definiert zu werden.
|
||||
hud.classList.toggle('warn', state.level === 'warn');
|
||||
hud.classList.toggle('danger', state.level === 'danger');
|
||||
hud.classList.toggle('deep', !!state.deep);
|
||||
|
||||
lamp.classList.toggle('hidden', !state.hasLamp);
|
||||
lamp.classList.toggle('on', !!state.lamp);
|
||||
}
|
||||
|
||||
window.addEventListener('message', (event) => {
|
||||
const data = event.data;
|
||||
|
||||
if (!data) return;
|
||||
|
||||
if (data.action === 'labels') {
|
||||
labels.air.textContent = data.air;
|
||||
labels.depth.textContent = data.depth;
|
||||
labels.lamp.textContent = data.lamp;
|
||||
return;
|
||||
}
|
||||
|
||||
if (data.action === 'state') render(data);
|
||||
});
|
||||
|
||||
// Damit sich das HUD im Browser ohne FiveM anschauen laesst.
|
||||
if (typeof GetParentResourceName !== 'function') {
|
||||
render({ visible: true, oxygen: 372, capacity: 600, depth: 12.4, level: 'ok', hasLamp: true, lamp: true });
|
||||
}
|
||||
Reference in New Issue
Block a user