- aether-medical: Stationen/Belegung, Intensivstation, Blutbank, Fuhrpark, Nachrichten/Aushänge, Berichte und Textbausteine (server + NUI) - aether-admin: vollständiges Server-Admin-Panel als echtes FiveM-Resource, an aether-core gekoppelt (Rechte über aether_users.admin_group), mit WebRTC-Live-Kameras (Bildschirmfreigabe) und separatem Media-Server (SFU) - Prototypen admin/ vervollständigt - SQL-Schema aether_admin.sql - Docker-Compose mit MariaDB und idempotenter Auto-Migration (schema_migrations) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
406 lines
20 KiB
HTML
406 lines
20 KiB
HTML
<!doctype html>
|
||
<html lang="de">
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||
<meta name="color-scheme" content="dark">
|
||
<title>Aether — Tod / Respawn</title>
|
||
<style>
|
||
:root{
|
||
--fg:#f2eef0; /* Standard-Textfarbe */
|
||
--muted:#a7a0ac; /* gedämpfter Text */
|
||
--panel:rgba(20,10,14,0.72); /* halbtransparente Fläche */
|
||
--panel2:rgba(30,16,20,0.9); /* dichtere Fläche */
|
||
--border:rgba(255,255,255,0.1);/* dezente Rahmen */
|
||
--danger:#f0506e; /* Warn-/Blutrot (Leitfarbe des Screens) */
|
||
--danger2:#ff2e57; /* kräftigeres Rot für Akzente */
|
||
--accent:#7c5cf6; /* Aether-Akzent (Violett) für Sekundäres */
|
||
--good:#34d39a; /* Erfolg (behandelt) */
|
||
--ems:#f5a742; /* Rettungsdienst-Orange */
|
||
}
|
||
*{box-sizing:border-box;}
|
||
html,body{margin:0;height:100%;overflow:hidden;background:transparent;
|
||
font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;color:var(--fg);}
|
||
|
||
/* In FiveM liegt die echte Spielwelt dahinter: Kulisse und Demo entfallen. */
|
||
body.ingame .scene{display:none;}
|
||
body.ingame .demo{display:none;}
|
||
|
||
/* ============================================================
|
||
ENTSÄTTIGTE HINTERGRUND-KULISSE (Boden-Perspektive)
|
||
============================================================ */
|
||
.scene{position:fixed;inset:0;z-index:0;overflow:hidden;filter:grayscale(0.85) brightness(0.45);
|
||
background:linear-gradient(180deg,#14121a 0%,#1e1a26 40%,#2a2430 60%,#171320 60%);}
|
||
.scene .city{position:absolute;left:0;right:0;bottom:32%;height:26%;
|
||
background:linear-gradient(90deg,#1c1826 0 9%,transparent 9% 14%,#241f30 14% 22%,transparent 22% 27%,
|
||
#1a1624 27% 35%,transparent 35% 41%,#241f30 41% 48%,transparent 48% 55%,#1c1826 55% 63%,transparent 63% 69%,
|
||
#201a2c 69% 78%,transparent 78% 84%,#241f30 84% 92%,transparent 92%);}
|
||
.scene .ground{position:absolute;left:0;right:0;bottom:0;height:32%;background:linear-gradient(180deg,#0f0c14,#000);}
|
||
|
||
/* Pulsierende blutrote Vignette über allem */
|
||
.vignette{position:fixed;inset:0;z-index:1;pointer-events:none;
|
||
background:radial-gradient(120% 100% at 50% 60%,transparent 20%,rgba(90,0,15,0.55) 75%,rgba(50,0,8,0.85) 100%);
|
||
animation:blut 3.2s ease-in-out infinite;}
|
||
@keyframes blut{50%{opacity:0.72;}}
|
||
.vignette.kritisch{animation-duration:1.1s;background:radial-gradient(120% 100% at 50% 60%,transparent 8%,rgba(140,0,20,0.6) 65%,rgba(70,0,10,0.92) 100%);}
|
||
|
||
/* ============================================================
|
||
ZENTRALER INHALTSBLOCK (wechselt je nach Phase)
|
||
============================================================ */
|
||
.wrap{position:relative;z-index:2;height:100%;display:grid;place-items:center;padding:24px;}
|
||
.center{width:min(560px,94vw);text-align:center;animation:auf .5s ease;}
|
||
@keyframes auf{from{opacity:0;transform:translateY(14px);}to{opacity:1;transform:none;}}
|
||
|
||
.status-label{font-size:13px;font-weight:800;letter-spacing:0.32em;text-transform:uppercase;color:var(--danger);
|
||
margin-bottom:10px;animation:flackern 2.4s ease-in-out infinite;}
|
||
@keyframes flackern{45%{opacity:1;}50%{opacity:0.45;}55%{opacity:1;}}
|
||
.title{font-size:clamp(44px,9vw,74px);font-weight:900;letter-spacing:-0.02em;line-height:0.95;margin:0;
|
||
color:#fff;text-shadow:0 0 30px rgba(240,80,110,0.45);}
|
||
.subtitle{color:var(--muted);font-size:15.5px;margin:14px auto 0;max-width:400px;line-height:1.55;}
|
||
|
||
/* EKG-Streifen */
|
||
.ecg{margin:26px auto 6px;width:min(440px,86vw);height:80px;border-radius:14px;overflow:hidden;position:relative;
|
||
background:rgba(0,0,0,0.4);border:1px solid var(--border);}
|
||
.ecg .track{display:flex;width:200%;height:100%;animation:ecgScroll var(--beat,1s) linear infinite;}
|
||
.ecg .track svg{width:50%;height:100%;flex:none;}
|
||
.ecg .line{fill:none;stroke:var(--danger2);stroke-width:2.4;filter:drop-shadow(0 0 6px rgba(255,46,87,0.8));}
|
||
@keyframes ecgScroll{to{transform:translateX(-50%);}}
|
||
.ecg.flat .track{animation:none;transform:none;}
|
||
.ecg.flat .line{stroke:#8a2740;filter:none;}
|
||
|
||
/* Countdown-Anzeige */
|
||
.timer{margin-top:8px;}
|
||
.timer .l{font-size:10px;color:var(--muted);text-transform:uppercase;letter-spacing:0.1em;font-weight:800;}
|
||
.timer .v{font-size:40px;font-weight:900;font-variant-numeric:tabular-nums;letter-spacing:0.02em;}
|
||
.timer.warnung .v{color:var(--danger);}
|
||
|
||
/* Statuszeile zum Rettungsdienst */
|
||
.emsline{margin:16px auto 0;display:inline-flex;align-items:center;gap:9px;background:var(--panel);
|
||
border:1px solid var(--border);border-radius:999px;padding:8px 16px;font-size:13px;font-weight:700;backdrop-filter:blur(8px);}
|
||
.emsline .dot{width:8px;height:8px;border-radius:50%;background:var(--muted);flex:none;}
|
||
.emsline.aktiv .dot{background:var(--ems);box-shadow:0 0 8px var(--ems);animation:blink 1s steps(2) infinite;}
|
||
.emsline.da .dot{background:var(--good);box-shadow:0 0 8px var(--good);animation:none;}
|
||
@keyframes blink{50%{opacity:0.3;}}
|
||
|
||
/* Aktions-Buttons */
|
||
.actions{display:flex;gap:10px;justify-content:center;flex-wrap:wrap;margin-top:24px;}
|
||
.btn{border:1px solid var(--border);background:var(--panel2);color:var(--fg);border-radius:12px;padding:13px 20px;
|
||
font-family:inherit;font-size:14px;font-weight:800;cursor:pointer;transition:.12s;display:inline-flex;align-items:center;gap:8px;backdrop-filter:blur(8px);}
|
||
.btn:hover:not(:disabled){transform:translateY(-2px);border-color:rgba(255,255,255,0.25);}
|
||
.btn:disabled{opacity:0.4;cursor:not-allowed;}
|
||
.btn.ems{background:linear-gradient(150deg,var(--ems),#d97b1a);color:#231603;border-color:transparent;}
|
||
.btn.give{background:var(--panel2);}
|
||
.btn.good{background:linear-gradient(150deg,var(--good),#1f9e77);color:#052018;border-color:transparent;}
|
||
.btn:active:not(:disabled){transform:scale(0.98);}
|
||
.hint{font-size:11.5px;color:var(--muted);margin-top:14px;}
|
||
|
||
/* Große Ikone für Ergebnis-Screens (behandelt / verstorben) */
|
||
.bigicon{font-size:64px;margin-bottom:6px;}
|
||
.infocard{margin:20px auto 0;background:var(--panel);border:1px solid var(--border);border-radius:14px;
|
||
padding:14px 18px;max-width:340px;text-align:left;backdrop-filter:blur(8px);}
|
||
.infocard .r{display:flex;justify-content:space-between;gap:14px;font-size:13px;padding:5px 0;}
|
||
.infocard .r .k{color:var(--muted);} .infocard .r .val{font-weight:800;font-variant-numeric:tabular-nums;}
|
||
.infocard .r .val.kosten{color:var(--ems);}
|
||
|
||
/* Demo-Hinweisleiste unten (nur Prototyp) */
|
||
.demo{position:fixed;left:50%;bottom:16px;transform:translateX(-50%);z-index:3;display:flex;gap:8px;align-items:center;
|
||
background:var(--panel2);border:1px solid var(--border);border-radius:12px;padding:7px 10px;backdrop-filter:blur(10px);}
|
||
.demo span{font-size:10.5px;color:var(--muted);font-weight:700;text-transform:uppercase;letter-spacing:0.06em;margin:0 4px;}
|
||
.demo button{border:1px solid var(--border);background:rgba(255,255,255,0.05);color:var(--fg);border-radius:8px;
|
||
padding:6px 11px;font-family:inherit;font-size:11.5px;font-weight:700;cursor:pointer;transition:.12s;}
|
||
.demo button:hover{border-color:var(--accent);color:#fff;}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
|
||
<!-- Kulisse + Vignette -->
|
||
<div class="scene"><div class="city"></div><div class="ground"></div></div>
|
||
<div class="vignette" id="vignette"></div>
|
||
|
||
<!-- Wechselnder Inhaltsbereich -->
|
||
<div class="wrap"><div class="center" id="center"></div></div>
|
||
|
||
<!-- Demo-Steuerung (nur Prototyp — in FiveM entfällt sie) -->
|
||
<div class="demo">
|
||
<span>Demo</span>
|
||
<button id="dRevive">🚑 Sanitäter behandelt sofort</button>
|
||
<button id="dReset">↺ Zurücksetzen</button>
|
||
</div>
|
||
|
||
<script>
|
||
"use strict";
|
||
/* Kurzer Zugriffshelfer auf Elemente per ID */
|
||
const $=id=>document.getElementById(id);
|
||
/* Sekunden als M:SS formatieren */
|
||
const mmss=s=>Math.floor(s/60)+":"+String(Math.max(0,s)%60).padStart(2,"0");
|
||
/* Betrag als Euro formatieren */
|
||
const euro=n=>Math.round(n).toLocaleString("de-DE")+" €";
|
||
|
||
/* =====================================================================
|
||
KONSTANTEN
|
||
===================================================================== */
|
||
let BLEEDOUT_START=300; // Verblutungs-Countdown in Sekunden (5:00)
|
||
let RESPAWN_SPERRE=45; // Mindestwartezeit, bevor „Aufgeben" möglich ist
|
||
const BEHANDLUNG_DAUER=6; // Dauer der Behandlung durch den Sanitäter
|
||
let KRANKENHAUS_KOSTEN=1500; // Behandlungspauschale beim Aufwachen im Krankenhaus
|
||
|
||
/* Ein Heartbeat-Segment (PQRST) als SVG-Pfad für den EKG-Streifen */
|
||
const EKG_PFAD="M0,40 L70,40 L82,40 L90,16 L98,60 L106,26 L114,40 L150,40 L200,40";
|
||
|
||
/* =====================================================================
|
||
ZUSTAND (im echten Betrieb per NUI vom Client gesetzt / gesteuert)
|
||
Bewusst vom UI getrennt gehalten.
|
||
===================================================================== */
|
||
const tod={
|
||
phase:"down", // down | behandelt | krankenhaus
|
||
restBleed:BLEEDOUT_START, // verbleibende Zeit bis zum Verbluten
|
||
respawnSperre:RESPAWN_SPERRE, // Restsperre für „Aufgeben"
|
||
emsGerufen:false, // wurde der Rettungsdienst gerufen?
|
||
emsEta:0, // verbleibende Zeit bis der Sanitäter eintrifft
|
||
sanitaeterDa:false, // ist der Sanitäter am Einsatzort?
|
||
behandlungRest:0, // Restzeit der laufenden Behandlung
|
||
};
|
||
|
||
/* =====================================================================
|
||
RENDERING JE PHASE
|
||
===================================================================== */
|
||
/* Baut den „Verwundet"-Screen einmalig auf (EKG-Animation soll durchlaufen) */
|
||
function renderDown(){
|
||
$("center").innerHTML=`
|
||
<div class="status-label">● Schwer verletzt</div>
|
||
<h1 class="title">VERWUNDET</h1>
|
||
<p class="subtitle">Du liegst am Boden und verlierst Blut. Ruf den Rettungsdienst — oder warte auf Hilfe.</p>
|
||
<div class="ecg" id="ecg"><div class="track">
|
||
<svg viewBox="0 0 200 80" preserveAspectRatio="none"><path class="line" d="${EKG_PFAD}"></path></svg>
|
||
<svg viewBox="0 0 200 80" preserveAspectRatio="none"><path class="line" d="${EKG_PFAD}"></path></svg>
|
||
</div></div>
|
||
<div class="timer" id="timer"><div class="l">Verbleibende Zeit</div><div class="v" id="timerV">${mmss(tod.restBleed)}</div></div>
|
||
<div class="emsline" id="emsline"><span class="dot"></span><span id="emsText">Kein Notruf abgesetzt</span></div>
|
||
<div class="actions">
|
||
<button class="btn ems" id="btnEms">🚑 Rettungsdienst rufen</button>
|
||
<button class="btn" id="btnHelp">🆘 Um Hilfe rufen</button>
|
||
<button class="btn give" id="btnGive" disabled>🏳️ Aufgeben</button>
|
||
</div>
|
||
<div class="hint" id="hint"></div>`;
|
||
// Button-Ereignisse verknüpfen
|
||
$("btnEms").addEventListener("click",rufeEms);
|
||
$("btnHelp").addEventListener("click",rufeHilfe);
|
||
$("btnGive").addEventListener("click",aufgeben);
|
||
updateDown();
|
||
}
|
||
|
||
/* Aktualisiert die dynamischen Teile des „Verwundet"-Screens (jede Sekunde) */
|
||
function updateDown(){
|
||
// Countdown + Warnfärbung bei wenig Restzeit
|
||
$("timerV").textContent=mmss(tod.restBleed);
|
||
$("timer").classList.toggle("warnung",tod.restBleed<=60);
|
||
$("vignette").classList.toggle("kritisch",tod.restBleed<=60);
|
||
|
||
// EKG-Takt an die Restzeit koppeln (weniger Zeit = langsamerer Herzschlag)
|
||
const anteil=Math.max(0,tod.restBleed/BLEEDOUT_START);
|
||
$("ecg").style.setProperty("--beat",(2.2-1.3*anteil).toFixed(2)+"s");
|
||
|
||
// Statuszeile zum Rettungsdienst
|
||
const emsline=$("emsline");
|
||
if(!tod.emsGerufen){emsline.className="emsline";$("emsText").textContent="Kein Notruf abgesetzt";}
|
||
else if(!tod.sanitaeterDa){emsline.className="emsline aktiv";$("emsText").textContent="🚑 Rettungsdienst unterwegs · Eintreffen in "+mmss(tod.emsEta);}
|
||
else {emsline.className="emsline da";$("emsText").textContent="🩹 Sanitäter behandelt dich … ("+tod.behandlungRest+"s)";}
|
||
|
||
// „Aufgeben" erst nach Ablauf der Respawn-Sperre freigeben
|
||
const btnGive=$("btnGive");
|
||
btnGive.disabled=tod.respawnSperre>0||tod.sanitaeterDa;
|
||
btnGive.innerHTML=tod.respawnSperre>0?`🔒 Aufgeben in ${tod.respawnSperre}s`:"🏳️ Aufgeben";
|
||
}
|
||
|
||
/* Zeigt den „Behandelt"-Screen nach erfolgreicher Wiederbelebung */
|
||
function renderBehandelt(){
|
||
$("vignette").className="vignette";
|
||
$("center").innerHTML=`
|
||
<div class="bigicon">🩹</div>
|
||
<div class="status-label" style="color:var(--good)">● Stabilisiert</div>
|
||
<h1 class="title" style="text-shadow:0 0 30px rgba(52,211,153,0.4)">BEHANDELT</h1>
|
||
<p class="subtitle">Ein Sanitäter hat dich rechtzeitig erreicht und wiederbelebt. Du bist wieder auf den Beinen.</p>
|
||
<div class="infocard">
|
||
<div class="r"><span class="k">Leben</span><span class="val" style="color:var(--good)">100 %</span></div>
|
||
<div class="r"><span class="k">Behandelt von</span><span class="val">EMS · Los Santos</span></div>
|
||
</div>
|
||
<div class="actions"><button class="btn good" id="btnWeiter">✔ Weiterspielen</button></div>
|
||
<div class="hint">Tipp: Trag Verletzungen aus, statt sie zu ignorieren — gutes Rollenspiel zahlt sich aus.</div>`;
|
||
$("btnWeiter").addEventListener("click",neustart);
|
||
}
|
||
|
||
/* Zeigt den „Im Krankenhaus aufgewacht"-Screen (nach Aufgeben oder Verbluten) */
|
||
function renderKrankenhaus(grund){
|
||
$("vignette").className="vignette";
|
||
$("center").innerHTML=`
|
||
<div class="bigicon">🏥</div>
|
||
<div class="status-label" style="color:var(--accent)">● Notaufnahme</div>
|
||
<h1 class="title" style="text-shadow:0 0 30px rgba(124,92,246,0.4)">KRANKENHAUS</h1>
|
||
<p class="subtitle">${grund} Das Pflegepersonal hat dich versorgt — die Behandlung ist allerdings nicht umsonst.</p>
|
||
<div class="infocard">
|
||
<div class="r"><span class="k">Grund</span><span class="val">${tod.emsGerufen?'Kein Sanitäter rechtzeitig':'Aufgegeben'}</span></div>
|
||
<div class="r"><span class="k">Behandlungskosten</span><span class="val kosten">− ${euro(KRANKENHAUS_KOSTEN)}</span></div>
|
||
<div class="r"><span class="k">Leben</span><span class="val" style="color:var(--good)">100 %</span></div>
|
||
</div>
|
||
<div class="actions"><button class="btn" id="btnWeiter">➜ Krankenhaus verlassen</button></div>
|
||
<div class="hint">Die Kosten gehen als Rechnung an dich (EMS-Finanzen im Fraktions-CAD).</div>`;
|
||
$("btnWeiter").addEventListener("click",neustart);
|
||
}
|
||
|
||
/* =====================================================================
|
||
AKTIONEN
|
||
===================================================================== */
|
||
/* Rettungsdienst rufen: Notruf absetzen und Eintreff-Zeit starten */
|
||
function rufeEms(){
|
||
if(tod.emsGerufen)return;
|
||
if(IST_FIVEM){ nui("emsRufen",{}); $("btnEms").disabled=true; return; }
|
||
tod.emsGerufen=true;
|
||
tod.emsEta=rndInt(30,60); // zufällige Eintreffzeit 0:30–1:00
|
||
$("btnEms").disabled=true;
|
||
$("hint").textContent="Notruf abgesetzt — ein Sanitäter wurde alarmiert.";
|
||
updateDown();
|
||
}
|
||
/* Um Hilfe rufen: rein kosmetischer Ruf an Umstehende */
|
||
function rufeHilfe(){
|
||
if(IST_FIVEM){ nui("hilfeRufen",{}); return; }
|
||
$("hint").textContent="Du schreist um Hilfe … vielleicht hört dich jemand in der Nähe.";
|
||
}
|
||
/* Aufgeben: im Krankenhaus aufwachen */
|
||
function aufgeben(){
|
||
if(tod.respawnSperre>0||tod.sanitaeterDa)return;
|
||
if(IST_FIVEM){ nui("aufgeben",{}); return; }
|
||
tod.phase="krankenhaus";
|
||
renderKrankenhaus("Du hast aufgegeben und wachst in der Notaufnahme wieder auf.");
|
||
}
|
||
/* Sanitäter beginnt die Behandlung (durch Eintreffen oder Demo-Button) */
|
||
function starteBehandlung(){
|
||
if(tod.sanitaeterDa||tod.phase!=="down")return;
|
||
tod.sanitaeterDa=true;
|
||
tod.emsGerufen=true; // Demo-Sofortbehandlung setzt „gerufen" mit
|
||
tod.behandlungRest=BEHANDLUNG_DAUER;
|
||
updateDown();
|
||
}
|
||
/* Behandlung erfolgreich abgeschlossen → wiederbelebt */
|
||
function wiederbelebt(){
|
||
tod.phase="behandelt";
|
||
renderBehandelt();
|
||
}
|
||
/* Verbluten ohne rechtzeitige Hilfe → Krankenhaus */
|
||
function verblutet(){
|
||
tod.phase="krankenhaus";
|
||
renderKrankenhaus("Niemand hat dich rechtzeitig erreicht — du bist verblutet.");
|
||
}
|
||
|
||
/* Alles auf Anfang zurücksetzen (für erneutes Durchspielen) */
|
||
function neustart(){
|
||
Object.assign(tod,{phase:"down",restBleed:BLEEDOUT_START,respawnSperre:RESPAWN_SPERRE,
|
||
emsGerufen:false,emsEta:0,sanitaeterDa:false,behandlungRest:0});
|
||
renderDown();
|
||
}
|
||
|
||
/* Ganzzahl-Zufall zwischen a und b (inklusive) */
|
||
function rndInt(a,b){return a+Math.floor(Math.random()*(b-a+1));}
|
||
|
||
/* =====================================================================
|
||
SEKUNDEN-TAKT (treibt alle Countdowns; in FiveM von echten Events ersetzt)
|
||
===================================================================== */
|
||
setInterval(()=>{
|
||
if(IST_FIVEM)return; // In FiveM führt der Server den Countdown
|
||
if(tod.phase!=="down")return; // in den Ergebnis-Screens läuft nichts weiter
|
||
|
||
// Respawn-Sperre herunterzählen
|
||
if(tod.respawnSperre>0)tod.respawnSperre--;
|
||
|
||
if(tod.sanitaeterDa){
|
||
// Laufende Behandlung: bei 0 wiederbeleben
|
||
tod.behandlungRest--;
|
||
if(tod.behandlungRest<=0){wiederbelebt();return;}
|
||
} else {
|
||
// Verblutungs-Countdown
|
||
tod.restBleed--;
|
||
// Sanitäter unterwegs: ETA herunterzählen, bei 0 Behandlung starten
|
||
if(tod.emsGerufen&&tod.emsEta>0){tod.emsEta--; if(tod.emsEta<=0)starteBehandlung();}
|
||
// Zeit abgelaufen ohne Rettung → verblutet
|
||
if(tod.restBleed<=0){verblutet();return;}
|
||
}
|
||
updateDown();
|
||
},1000);
|
||
|
||
/* Demo-Buttons */
|
||
$("dRevive").addEventListener("click",()=>{if(tod.phase==="down")starteBehandlung();});
|
||
$("dReset").addEventListener("click",neustart);
|
||
|
||
/* =====================================================================
|
||
NUI-BRÜCKE — Verbindung zum FiveM-Client
|
||
===================================================================== */
|
||
const IST_FIVEM = (typeof GetParentResourceName === "function");
|
||
const RESSOURCE = IST_FIVEM ? GetParentResourceName() : "aether-death";
|
||
|
||
function nui(aktion, daten){
|
||
if(!IST_FIVEM) return Promise.resolve();
|
||
return fetch(`https://${RESSOURCE}/${aktion}`, {
|
||
method: "POST",
|
||
headers: { "Content-Type": "application/json; charset=UTF-8" },
|
||
body: JSON.stringify(daten || {}),
|
||
}).catch(() => {});
|
||
}
|
||
|
||
window.addEventListener("message", (ereignis) => {
|
||
const n = ereignis.data || {};
|
||
|
||
if(n.aktion === "oeffnen"){
|
||
document.body.style.display = "";
|
||
if(n.bleedoutMax) BLEEDOUT_START = n.bleedoutMax;
|
||
Object.assign(tod, {
|
||
phase: "down",
|
||
restBleed: n.restBleed,
|
||
respawnSperre: n.respawnSperre,
|
||
emsGerufen: false,
|
||
sanitaeterDa: false,
|
||
});
|
||
renderDown();
|
||
}
|
||
else if(n.aktion === "zustand"){
|
||
/* Der Server ist die Wahrheit: Countdown und Sperre kommen von dort. */
|
||
if(tod.phase !== "down") return;
|
||
tod.restBleed = n.restBleed;
|
||
tod.respawnSperre = n.respawnSperre;
|
||
tod.emsGerufen = n.emsGerufen;
|
||
updateDown();
|
||
}
|
||
else if(n.aktion === "hinweis"){
|
||
const el = document.getElementById("hint");
|
||
if(el) el.textContent = n.text || "";
|
||
}
|
||
else if(n.aktion === "behandelt"){
|
||
tod.phase = "behandelt";
|
||
renderBehandelt();
|
||
}
|
||
else if(n.aktion === "krankenhaus"){
|
||
tod.phase = "krankenhaus";
|
||
if(n.kosten) KRANKENHAUS_KOSTEN = n.kosten;
|
||
const grund = (n.grund === "verblutet")
|
||
? "Niemand hat dich rechtzeitig erreicht — du bist verblutet."
|
||
: "Du hast aufgegeben und wachst in der Notaufnahme wieder auf.";
|
||
renderKrankenhaus(grund + (n.klinik ? " (" + n.klinik + ")" : ""));
|
||
// In FiveM übernimmt der Client das Weiterspielen — Knopf ausblenden
|
||
const weiter = document.getElementById("btnWeiter");
|
||
if(weiter) weiter.style.display = "none";
|
||
}
|
||
else if(n.aktion === "schliessen"){
|
||
document.body.style.display = "none";
|
||
}
|
||
});
|
||
|
||
/* In FiveM zunächst verstecken — die Seite wartet auf "oeffnen" */
|
||
if(IST_FIVEM){ document.body.classList.add("ingame"); document.body.style.display = "none"; }
|
||
|
||
/* =====================================================================
|
||
START
|
||
===================================================================== */
|
||
if(!IST_FIVEM) renderDown();
|
||
</script>
|
||
|
||
</body>
|
||
</html>
|