220 lines
7.2 KiB
JavaScript
220 lines
7.2 KiB
JavaScript
(function () {
|
|
'use strict';
|
|
|
|
// ============================================================
|
|
// ELEMENTS
|
|
// ============================================================
|
|
|
|
const $screen = $('#deathscreen');
|
|
const $icon = $('#death-icon');
|
|
const $statusText = $('#status-text');
|
|
const $timerBar = $('#timer-bar');
|
|
const $timerLabel = $('#timer-label');
|
|
const $timerValue = $('#timer-value');
|
|
const $timerContainer = $('#timer-container');
|
|
const $actionText = $('#action-text');
|
|
const $dispatch = $('#dispatch');
|
|
const $dispatchStreet = $('#dispatch-street');
|
|
const $dispatchTitle = $('#dispatch-title');
|
|
const $dispatchSound = document.getElementById('dispatch-sound');
|
|
|
|
// ============================================================
|
|
// STATE
|
|
// ============================================================
|
|
|
|
let locale = {};
|
|
let maxTimer = 0;
|
|
let currentState = '';
|
|
let dispatchTimeout = null;
|
|
let giveUpEnabled = false;
|
|
let emsCalledFlag = false;
|
|
|
|
// ============================================================
|
|
// HELPERS
|
|
// ============================================================
|
|
|
|
function formatTime(seconds) {
|
|
if (seconds < 0) seconds = 0;
|
|
const m = Math.floor(seconds / 60);
|
|
const s = seconds % 60;
|
|
return (m < 10 ? '0' + m : m) + ':' + (s < 10 ? '0' + s : s);
|
|
}
|
|
|
|
function getIconForState(state) {
|
|
switch (state) {
|
|
case 'UNCONSCIOUS': return 'fa-heartbeat';
|
|
case 'BLEEDING_OUT': return 'fa-heart-crack';
|
|
case 'DEAD': return 'fa-skull-crossbones'; // fallback
|
|
default: return 'fa-heartbeat';
|
|
}
|
|
}
|
|
|
|
function getStatusClass(state) {
|
|
switch (state) {
|
|
case 'UNCONSCIOUS': return '';
|
|
case 'BLEEDING_OUT': return 'bleeding';
|
|
case 'DEAD': return 'dead';
|
|
default: return '';
|
|
}
|
|
}
|
|
|
|
function getStatusText(state) {
|
|
switch (state) {
|
|
case 'UNCONSCIOUS': return locale.unconscious || 'Bewusstlos';
|
|
case 'BLEEDING_OUT': return locale.bleedingOut || 'Verblutung';
|
|
case 'DEAD': return locale.dead || 'Verstorben';
|
|
default: return '';
|
|
}
|
|
}
|
|
|
|
// ============================================================
|
|
// UI UPDATES
|
|
// ============================================================
|
|
|
|
function updateActionText() {
|
|
$actionText.removeClass('respawn-ready ems-called');
|
|
|
|
if (emsCalledFlag && giveUpEnabled) {
|
|
$actionText.html(
|
|
'<span class="ems-called">' + (locale.callingEMS || 'Rettungsdienst wird gerufen...') + '</span>' +
|
|
'<br>' +
|
|
'<span class="respawn-ready">' + (locale.giveUpAvailable || 'Drücke [E] zum Aufgeben') + '</span>'
|
|
);
|
|
} else if (emsCalledFlag) {
|
|
$actionText.text(locale.callingEMS || 'Rettungsdienst wird gerufen...');
|
|
$actionText.addClass('ems-called');
|
|
} else if (giveUpEnabled) {
|
|
$actionText.html(
|
|
(locale.callEMS || 'Halte [G] um den Rettungsdienst zu rufen') +
|
|
'<br>' +
|
|
'<span class="respawn-ready">' + (locale.giveUpAvailable || 'Drücke [E] zum Aufgeben') + '</span>'
|
|
);
|
|
} else {
|
|
$actionText.text(locale.callEMS || 'Halte [G] um den Rettungsdienst zu rufen');
|
|
}
|
|
}
|
|
|
|
function applyState(state) {
|
|
currentState = state;
|
|
const cls = getStatusClass(state);
|
|
|
|
// Icon
|
|
$icon.find('i').attr('class', 'fas ' + getIconForState(state));
|
|
$icon.removeClass('bleeding dead').addClass(cls);
|
|
|
|
// Status text
|
|
$statusText.text(getStatusText(state));
|
|
$statusText.removeClass('bleeding dead').addClass(cls);
|
|
|
|
// Timer bar
|
|
$timerBar.removeClass('bleeding dead').addClass(cls);
|
|
|
|
// Action text — Flags beibehalten beim State-Wechsel
|
|
if (state === 'UNCONSCIOUS' || state === 'BLEEDING_OUT') {
|
|
updateActionText();
|
|
}
|
|
|
|
// Timer container wieder einblenden
|
|
if (state === 'UNCONSCIOUS' || state === 'BLEEDING_OUT') {
|
|
$timerContainer.show();
|
|
}
|
|
|
|
// Timer label
|
|
$timerLabel.text(locale.timerLabel || 'Verblutung in');
|
|
}
|
|
|
|
function updateTimer(seconds) {
|
|
$timerValue.text(formatTime(seconds));
|
|
|
|
if (maxTimer > 0) {
|
|
const percent = (seconds / maxTimer) * 100;
|
|
$timerBar.css('width', percent + '%');
|
|
}
|
|
}
|
|
|
|
// ============================================================
|
|
// ACTIONS
|
|
// ============================================================
|
|
|
|
function showDeathscreen(data) {
|
|
locale = data.locale || {};
|
|
maxTimer = data.timer || 0;
|
|
giveUpEnabled = false;
|
|
emsCalledFlag = false;
|
|
|
|
applyState(data.state);
|
|
updateTimer(data.timer);
|
|
|
|
$screen.removeClass('hidden');
|
|
|
|
// Trigger reflow, dann visible setzen für Transition
|
|
void $screen[0].offsetWidth;
|
|
$screen.addClass('visible');
|
|
}
|
|
|
|
function hideDeathscreen() {
|
|
$screen.removeClass('visible');
|
|
|
|
setTimeout(function () {
|
|
$screen.addClass('hidden');
|
|
currentState = '';
|
|
}, 800);
|
|
}
|
|
|
|
// ============================================================
|
|
// NUI MESSAGE HANDLER
|
|
// ============================================================
|
|
|
|
window.addEventListener('message', function (event) {
|
|
var data = event.data;
|
|
|
|
switch (data.action) {
|
|
case 'show':
|
|
showDeathscreen(data);
|
|
break;
|
|
|
|
case 'update':
|
|
if (data.state !== currentState) {
|
|
maxTimer = data.timer;
|
|
applyState(data.state);
|
|
}
|
|
updateTimer(data.timer);
|
|
break;
|
|
|
|
case 'emsCalled':
|
|
emsCalledFlag = true;
|
|
updateActionText();
|
|
break;
|
|
|
|
case 'enableGiveUp':
|
|
giveUpEnabled = true;
|
|
updateActionText();
|
|
break;
|
|
|
|
case 'showDispatch':
|
|
$dispatchTitle.text(data.title || 'Notruf');
|
|
$dispatchStreet.text(data.street || 'Unbekannter Standort');
|
|
$dispatch.removeClass('hidden');
|
|
if ($dispatchSound) {
|
|
$dispatchSound.currentTime = 0;
|
|
$dispatchSound.volume = 0.5;
|
|
$dispatchSound.play().catch(function () {});
|
|
}
|
|
if (dispatchTimeout) clearTimeout(dispatchTimeout);
|
|
dispatchTimeout = setTimeout(function () {
|
|
$dispatch.addClass('hidden');
|
|
}, 15000);
|
|
break;
|
|
|
|
case 'hideDispatch':
|
|
$dispatch.addClass('hidden');
|
|
if (dispatchTimeout) clearTimeout(dispatchTimeout);
|
|
break;
|
|
|
|
case 'hide':
|
|
hideDeathscreen();
|
|
break;
|
|
}
|
|
});
|
|
})();
|