aerghe
This commit is contained in:
parent
5940dfb01a
commit
3fd04e2211
@ -35,6 +35,9 @@ export async function loadArena() {
|
|||||||
<div class="arena-title" style="margin:0;">⚔️ 2v2 Team-Lobby</div>
|
<div class="arena-title" style="margin:0;">⚔️ 2v2 Team-Lobby</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Fehlermeldung auf dem 2v2-Screen -->
|
||||||
|
<div id="arena-2v2-error" style="display:none;"></div>
|
||||||
|
|
||||||
<!-- Team-Panel (erscheint nach Beitritt) -->
|
<!-- Team-Panel (erscheint nach Beitritt) -->
|
||||||
<div id="arena-team-panel" style="display:none;">
|
<div id="arena-team-panel" style="display:none;">
|
||||||
<div class="arena-team-box">
|
<div class="arena-team-box">
|
||||||
@ -62,7 +65,7 @@ export async function loadArena() {
|
|||||||
initArenaModes();
|
initArenaModes();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── Styles ────────────────────────────────────────────────────────────────── */
|
/* ── Styles ─────────────────────────────────────────────────────────────────── */
|
||||||
function injectArenaStyles() {
|
function injectArenaStyles() {
|
||||||
if (document.getElementById("arena-popup-styles")) return;
|
if (document.getElementById("arena-popup-styles")) return;
|
||||||
|
|
||||||
@ -105,8 +108,19 @@ function injectArenaStyles() {
|
|||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
animation: none;
|
animation: none;
|
||||||
}
|
}
|
||||||
#arena-queue-status .qs-cancel:hover {
|
#arena-queue-status .qs-cancel:hover { color: #e74c3c; }
|
||||||
|
|
||||||
|
/* ── 2v2 Fehlermeldung ── */
|
||||||
|
#arena-2v2-error {
|
||||||
|
padding: 10px 14px;
|
||||||
|
border-radius: 8px;
|
||||||
|
background: rgba(231,76,60,0.12);
|
||||||
|
border: 1px solid rgba(231,76,60,0.4);
|
||||||
color: #e74c3c;
|
color: #e74c3c;
|
||||||
|
font-family: "Cinzel", serif;
|
||||||
|
font-size: 12px;
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── Backdrop ── */
|
/* ── Backdrop ── */
|
||||||
@ -152,21 +166,6 @@ function injectArenaStyles() {
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 10px;
|
gap: 10px;
|
||||||
}
|
}
|
||||||
#arena-popup-titlebar .ap-dots {
|
|
||||||
display: flex;
|
|
||||||
gap: 7px;
|
|
||||||
}
|
|
||||||
#arena-popup-titlebar .ap-dot {
|
|
||||||
width: 13px;
|
|
||||||
height: 13px;
|
|
||||||
border-radius: 50%;
|
|
||||||
cursor: pointer;
|
|
||||||
transition: filter 0.15s;
|
|
||||||
}
|
|
||||||
#arena-popup-titlebar .ap-dot:hover { filter: brightness(1.3); }
|
|
||||||
#arena-popup-titlebar .ap-dot.close { background: #e74c3c; border: 1px solid rgba(0,0,0,0.25); }
|
|
||||||
#arena-popup-titlebar .ap-dot.min { background: #f1c40f; border: 1px solid rgba(0,0,0,0.25); }
|
|
||||||
#arena-popup-titlebar .ap-dot.expand { background: #2ecc71; border: 1px solid rgba(0,0,0,0.25); }
|
|
||||||
#arena-popup-titlebar .ap-title {
|
#arena-popup-titlebar .ap-title {
|
||||||
font-family: "Cinzel", serif;
|
font-family: "Cinzel", serif;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
@ -381,13 +380,12 @@ function injectArenaStyles() {
|
|||||||
document.head.appendChild(style);
|
document.head.appendChild(style);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── Socket-Referenz holen ─────────────────────────────────────────────────── */
|
/* ── Socket-Referenz holen ──────────────────────────────────────────────────── */
|
||||||
function getSocket() {
|
function getSocket() {
|
||||||
// Wird von der Haupt-App als window._socket bereitgestellt
|
|
||||||
return window._socket || null;
|
return window._socket || null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── Klick-Handler initialisieren ─────────────────────────────────────────── */
|
/* ── Klick-Handler initialisieren ──────────────────────────────────────────── */
|
||||||
function initArenaModes() {
|
function initArenaModes() {
|
||||||
document.querySelectorAll(".arena-mode-card").forEach((card) => {
|
document.querySelectorAll(".arena-mode-card").forEach((card) => {
|
||||||
card.addEventListener("click", () => {
|
card.addEventListener("click", () => {
|
||||||
@ -411,26 +409,35 @@ let myArenaData = null;
|
|||||||
|
|
||||||
async function open2v2Lobby() {
|
async function open2v2Lobby() {
|
||||||
const socket = getSocket();
|
const socket = getSocket();
|
||||||
if (!socket) { showArenaError("Keine Verbindung zum Server."); return; }
|
|
||||||
|
// Screen ZUERST wechseln – so sind Fehlermeldungen sichtbar
|
||||||
|
document.getElementById("arena-mode-screen").style.display = "none";
|
||||||
|
document.getElementById("arena-2v2-screen").style.display = "flex";
|
||||||
|
|
||||||
|
if (!socket) {
|
||||||
|
console.error("[2v2] Kein Socket – window._socket:", window._socket);
|
||||||
|
show2v2Error("Keine Verbindung zum Server. Bitte Seite neu laden.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Spielerdaten laden
|
// Spielerdaten laden
|
||||||
if (!myArenaData) {
|
if (!myArenaData) {
|
||||||
try {
|
try {
|
||||||
|
console.log("[2v2] Lade Spielerdaten…");
|
||||||
const res = await fetch("/arena/me");
|
const res = await fetch("/arena/me");
|
||||||
if (!res.ok) throw new Error(res.status);
|
if (!res.ok) throw new Error("HTTP " + res.status);
|
||||||
myArenaData = await res.json();
|
myArenaData = await res.json();
|
||||||
} catch {
|
console.log("[2v2] Spielerdaten:", myArenaData);
|
||||||
showArenaError("Spielerdaten konnten nicht geladen werden.");
|
} catch (err) {
|
||||||
|
console.error("[2v2] Spielerdaten Fehler:", err);
|
||||||
|
show2v2Error("Spielerdaten konnten nicht geladen werden. (Eingeloggt?)");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Screen wechseln
|
|
||||||
document.getElementById("arena-mode-screen").style.display = "none";
|
|
||||||
document.getElementById("arena-2v2-screen").style.display = "flex";
|
|
||||||
|
|
||||||
// Lobbyliste anfordern
|
// Lobbyliste anfordern
|
||||||
socket.emit("get_2v2_lobbies");
|
socket.emit("get_2v2_lobbies");
|
||||||
|
console.log("[2v2] get_2v2_lobbies gesendet");
|
||||||
|
|
||||||
// Zurück-Button
|
// Zurück-Button
|
||||||
document.getElementById("arena-2v2-back").onclick = () => {
|
document.getElementById("arena-2v2-back").onclick = () => {
|
||||||
@ -442,6 +449,7 @@ async function open2v2Lobby() {
|
|||||||
|
|
||||||
// Team erstellen
|
// Team erstellen
|
||||||
document.getElementById("arena-create-team-btn").onclick = () => {
|
document.getElementById("arena-create-team-btn").onclick = () => {
|
||||||
|
console.log("[2v2] Team erstellen geklickt – sende create_2v2_team mit:", myArenaData);
|
||||||
socket.emit("create_2v2_team", myArenaData);
|
socket.emit("create_2v2_team", myArenaData);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -454,12 +462,17 @@ async function open2v2Lobby() {
|
|||||||
socket.off("match_found_2v2");
|
socket.off("match_found_2v2");
|
||||||
socket.off("2v2_error");
|
socket.off("2v2_error");
|
||||||
|
|
||||||
socket.on("2v2_lobbies", (list) => render2v2LobbyList(list, socket));
|
socket.on("2v2_lobbies", (list) => {
|
||||||
|
console.log("[2v2] Lobbies empfangen:", list);
|
||||||
|
render2v2LobbyList(list, socket);
|
||||||
|
});
|
||||||
|
|
||||||
socket.on("2v2_team_joined", (data) => {
|
socket.on("2v2_team_joined", (data) => {
|
||||||
|
console.log("[2v2] Team joined:", data);
|
||||||
my2v2TeamId = data.teamId;
|
my2v2TeamId = data.teamId;
|
||||||
document.getElementById("arena-team-panel").style.display = "block";
|
document.getElementById("arena-team-panel").style.display = "block";
|
||||||
document.getElementById("arena-lobby-section").style.display = "none";
|
document.getElementById("arena-lobby-section").style.display = "none";
|
||||||
|
hide2v2Error();
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on("2v2_team_update", (data) => render2v2TeamPanel(data, socket));
|
socket.on("2v2_team_update", (data) => render2v2TeamPanel(data, socket));
|
||||||
@ -467,7 +480,6 @@ async function open2v2Lobby() {
|
|||||||
socket.on("2v2_partner_left", (data) => {
|
socket.on("2v2_partner_left", (data) => {
|
||||||
const status = document.getElementById("arena-team-status");
|
const status = document.getElementById("arena-team-status");
|
||||||
if (status) status.innerHTML = `<span style="color:#e74c3c;">⚠️ ${data.name} hat das Team verlassen.</span>`;
|
if (status) status.innerHTML = `<span style="color:#e74c3c;">⚠️ ${data.name} hat das Team verlassen.</span>`;
|
||||||
// Bereit-Button zurücksetzen
|
|
||||||
render2v2TeamPanel({ teamId: my2v2TeamId, players: [{ name: myArenaData.name, level: myArenaData.level, ready: false }], count: 1 }, socket);
|
render2v2TeamPanel({ teamId: my2v2TeamId, players: [{ name: myArenaData.name, level: myArenaData.level, ready: false }], count: 1 }, socket);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -496,8 +508,8 @@ async function open2v2Lobby() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
socket.on("2v2_error", (data) => {
|
socket.on("2v2_error", (data) => {
|
||||||
const status = document.getElementById("arena-team-status");
|
console.warn("[2v2] Fehler vom Server:", data.message);
|
||||||
if (status) { status.innerHTML = `<span style="color:#e74c3c;">❌ ${data.message}</span>`; }
|
show2v2Error(data.message);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -572,7 +584,21 @@ function leave2v2Team(socket) {
|
|||||||
socket.off("2v2_error");
|
socket.off("2v2_error");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── 1v1: Hauptlogik ───────────────────────────────────────────────────────── */
|
/* ── 2v2 Fehlermeldung ──────────────────────────────────────────────────────── */
|
||||||
|
function show2v2Error(msg) {
|
||||||
|
const el = document.getElementById("arena-2v2-error");
|
||||||
|
if (!el) return;
|
||||||
|
el.textContent = "❌ " + msg;
|
||||||
|
el.style.display = "block";
|
||||||
|
setTimeout(() => { el.style.display = "none"; }, 4000);
|
||||||
|
}
|
||||||
|
|
||||||
|
function hide2v2Error() {
|
||||||
|
const el = document.getElementById("arena-2v2-error");
|
||||||
|
if (el) el.style.display = "none";
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ── 1v1: Hauptlogik ────────────────────────────────────────────────────────── */
|
||||||
async function handle1v1Click(card) {
|
async function handle1v1Click(card) {
|
||||||
const socket = getSocket();
|
const socket = getSocket();
|
||||||
if (!socket) {
|
if (!socket) {
|
||||||
@ -580,30 +606,25 @@ async function handle1v1Click(card) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bereits in Suche?
|
|
||||||
if (card.classList.contains("searching")) return;
|
if (card.classList.contains("searching")) return;
|
||||||
|
|
||||||
// Spielerdaten laden
|
|
||||||
let me;
|
let me;
|
||||||
try {
|
try {
|
||||||
const res = await fetch("/arena/me");
|
const res = await fetch("/arena/me");
|
||||||
if (!res.ok) throw new Error("Status " + res.status);
|
if (!res.ok) throw new Error("Status " + res.status);
|
||||||
me = await res.json();
|
me = await res.json();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error("[1v1] Spielerdaten konnten nicht geladen werden:", err);
|
console.error("[1v1] Spielerdaten Fehler:", err);
|
||||||
showArenaError("Spielerdaten konnten nicht geladen werden. (Eingeloggt?)");
|
showArenaError("Spielerdaten konnten nicht geladen werden. (Eingeloggt?)");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// UI: Suche läuft
|
|
||||||
setCardSearching(card, true);
|
setCardSearching(card, true);
|
||||||
showQueueStatus(me.level);
|
showQueueStatus(me.level);
|
||||||
|
|
||||||
// Sicherstellen, dass keine alten Listener hängen
|
|
||||||
socket.off("match_found");
|
socket.off("match_found");
|
||||||
socket.off("queue_status");
|
socket.off("queue_status");
|
||||||
|
|
||||||
// Queue-Status empfangen
|
|
||||||
socket.on("queue_status", (data) => {
|
socket.on("queue_status", (data) => {
|
||||||
if (data.status === "waiting") {
|
if (data.status === "waiting") {
|
||||||
showQueueStatus(me.level, data.poolSize);
|
showQueueStatus(me.level, data.poolSize);
|
||||||
@ -613,7 +634,6 @@ async function handle1v1Click(card) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Match gefunden
|
|
||||||
socket.once("match_found", (data) => {
|
socket.once("match_found", (data) => {
|
||||||
socket.off("queue_status");
|
socket.off("queue_status");
|
||||||
setCardSearching(card, false);
|
setCardSearching(card, false);
|
||||||
@ -628,7 +648,6 @@ async function handle1v1Click(card) {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// Matchmaking starten
|
|
||||||
socket.emit("join_1v1", {
|
socket.emit("join_1v1", {
|
||||||
id: me.id,
|
id: me.id,
|
||||||
name: me.name,
|
name: me.name,
|
||||||
@ -636,7 +655,7 @@ async function handle1v1Click(card) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── Queue abbrechen ───────────────────────────────────────────────────────── */
|
/* ── Queue abbrechen ────────────────────────────────────────────────────────── */
|
||||||
function cancelQueue(card) {
|
function cancelQueue(card) {
|
||||||
const socket = getSocket();
|
const socket = getSocket();
|
||||||
if (socket) {
|
if (socket) {
|
||||||
@ -648,9 +667,8 @@ function cancelQueue(card) {
|
|||||||
hideQueueStatus();
|
hideQueueStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── Match-Found Splash ────────────────────────────────────────────────────── */
|
/* ── Match-Found Splash ─────────────────────────────────────────────────────── */
|
||||||
function showMatchFoundOverlay(myName, opponentName, onDone) {
|
function showMatchFoundOverlay(myName, opponentName, onDone) {
|
||||||
// Verhindert doppeltes Öffnen
|
|
||||||
if (document.getElementById("match-found-overlay")) return;
|
if (document.getElementById("match-found-overlay")) return;
|
||||||
|
|
||||||
const overlay = document.createElement("div");
|
const overlay = document.createElement("div");
|
||||||
@ -662,22 +680,19 @@ function showMatchFoundOverlay(myName, opponentName, onDone) {
|
|||||||
`;
|
`;
|
||||||
document.body.appendChild(overlay);
|
document.body.appendChild(overlay);
|
||||||
|
|
||||||
// Ladebalken animieren
|
|
||||||
requestAnimationFrame(() => {
|
requestAnimationFrame(() => {
|
||||||
const bar = document.getElementById("mfBar");
|
const bar = document.getElementById("mfBar");
|
||||||
if (bar) bar.style.width = "100%";
|
if (bar) bar.style.width = "100%";
|
||||||
});
|
});
|
||||||
|
|
||||||
// Nach 1.6s zum Spielfeld
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
overlay.remove();
|
overlay.remove();
|
||||||
onDone();
|
onDone();
|
||||||
}, 1600);
|
}, 1600);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── Popup öffnen ──────────────────────────────────────────────────────────── */
|
/* ── Popup öffnen ───────────────────────────────────────────────────────────── */
|
||||||
function openArenaPopup(src, opponentName, matchId) {
|
function openArenaPopup(src, opponentName, matchId) {
|
||||||
// Vorhandenen Popup schließen (falls mehrfach)
|
|
||||||
document.getElementById("arena-backdrop")?.remove();
|
document.getElementById("arena-backdrop")?.remove();
|
||||||
document.getElementById("arena-popup")?.remove();
|
document.getElementById("arena-popup")?.remove();
|
||||||
|
|
||||||
@ -688,8 +703,8 @@ function openArenaPopup(src, opponentName, matchId) {
|
|||||||
popup.id = "arena-popup";
|
popup.id = "arena-popup";
|
||||||
|
|
||||||
const title = opponentName
|
const title = opponentName
|
||||||
? `⚔️ 1v1 · vs ${opponentName}`
|
? `⚔️ Arena · vs ${opponentName}`
|
||||||
: "⚔️ Arena · 1v1";
|
: "⚔️ Arena";
|
||||||
|
|
||||||
popup.innerHTML = `
|
popup.innerHTML = `
|
||||||
<div id="arena-popup-titlebar">
|
<div id="arena-popup-titlebar">
|
||||||
@ -703,11 +718,9 @@ function openArenaPopup(src, opponentName, matchId) {
|
|||||||
|
|
||||||
document.body.appendChild(backdrop);
|
document.body.appendChild(backdrop);
|
||||||
document.body.appendChild(popup);
|
document.body.appendChild(popup);
|
||||||
|
|
||||||
// Backdrop-Klick deaktiviert – Fenster nur über Aufgeben/Spielende schließbar
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── UI Hilfsfunktionen ────────────────────────────────────────────────────── */
|
/* ── UI Hilfsfunktionen ─────────────────────────────────────────────────────── */
|
||||||
function setCardSearching(card, searching) {
|
function setCardSearching(card, searching) {
|
||||||
const label = card.querySelector(".arena-mode-label");
|
const label = card.querySelector(".arena-mode-label");
|
||||||
const desc = card.querySelector(".arena-mode-desc");
|
const desc = card.querySelector(".arena-mode-desc");
|
||||||
@ -727,9 +740,8 @@ function showQueueStatus(myLevel, poolSize) {
|
|||||||
const box = document.getElementById("arena-queue-status");
|
const box = document.getElementById("arena-queue-status");
|
||||||
if (!box) return;
|
if (!box) return;
|
||||||
|
|
||||||
const range = 5;
|
const min = Math.max(1, myLevel - 5);
|
||||||
const min = Math.max(1, myLevel - range);
|
const max = myLevel + 5;
|
||||||
const max = myLevel + range;
|
|
||||||
const pool = poolSize ? ` · ${poolSize} Spieler im Pool` : "";
|
const pool = poolSize ? ` · ${poolSize} Spieler im Pool` : "";
|
||||||
|
|
||||||
box.style.display = "block";
|
box.style.display = "block";
|
||||||
@ -739,7 +751,6 @@ function showQueueStatus(myLevel, poolSize) {
|
|||||||
<span class="qs-cancel" id="qs-cancel-btn">Suche abbrechen</span>
|
<span class="qs-cancel" id="qs-cancel-btn">Suche abbrechen</span>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
// Cancel-Button – Card-Referenz über data-attribute
|
|
||||||
document.getElementById("qs-cancel-btn")?.addEventListener("click", () => {
|
document.getElementById("qs-cancel-btn")?.addEventListener("click", () => {
|
||||||
const card = document.querySelector(".arena-mode-card[data-mode='1v1']");
|
const card = document.querySelector(".arena-mode-card[data-mode='1v1']");
|
||||||
if (card) cancelQueue(card);
|
if (card) cancelQueue(card);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user