2026-04-14 15:54:53 +02:00

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;
}
});
})();