diff --git a/public/js/buildings/arena.js b/public/js/buildings/arena.js index 510fd49..8c40510 100644 --- a/public/js/buildings/arena.js +++ b/public/js/buildings/arena.js @@ -4,33 +4,56 @@ export async function loadArena() { ui.innerHTML = `
-
βš”οΈ Kampfarena
-

WΓ€hle deinen Kampfmodus

- -
- -
-
πŸ—‘οΈ
-
1v1
-
Einzelkampf – Beweis deine StΓ€rke im Duell
+ +
+
βš”οΈ Kampfarena
+

WΓ€hle deinen Kampfmodus

+
+
+
πŸ—‘οΈ
+
1v1
+
Einzelkampf – Beweis deine StΓ€rke im Duell
+
+
+
βš”οΈ
+
2v2
+
VerbΓΌnde dich mit einem Kameraden im Kampf
+
+
+
πŸ›‘οΈ
+
4v4
+
Schlachtruf – FΓΌhre deine Truppe zum Sieg
+
- -
-
βš”οΈ
-
2v2
-
VerbΓΌnde dich mit einem Kameraden im Kampf
-
- -
-
πŸ›‘οΈ
-
4v4
-
Schlachtruf – FΓΌhre deine Truppe zum Sieg
-
- +
- - + +
`; @@ -214,6 +237,146 @@ function injectArenaStyles() { pointer-events: none; border-color: rgba(255,215,80,0.5) !important; } + + /* ── 2v2 Lobby Screen ── */ + #arena-2v2-screen { + flex-direction: column; + gap: 14px; + padding: 16px; + height: 100%; + overflow-y: auto; + } + .arena-lobby-header { + display: flex; + align-items: center; + gap: 16px; + } + .arena-back-btn { + background: none; + border: 1px solid rgba(255,200,80,0.3); + color: #c8960c; + font-family: "Cinzel", serif; + font-size: 12px; + padding: 4px 12px; + border-radius: 4px; + cursor: pointer; + } + .arena-back-btn:hover { background: rgba(200,150,12,0.15); } + .arena-lobby-actions { display: flex; gap: 10px; margin-bottom: 4px; } + .arena-btn-create { + background: linear-gradient(#4a3018, #2a1a08); + border: 2px solid #8b6a3c; + border-radius: 7px; + color: #f0d9a6; + font-family: "Cinzel", serif; + font-size: 12px; + padding: 8px 16px; + cursor: pointer; + transition: 0.2s; + } + .arena-btn-create:hover { border-color: #f0d060; } + .arena-lobby-title { + font-family: "Cinzel", serif; + font-size: 13px; + color: #a08060; + letter-spacing: 1px; + margin-bottom: 6px; + } + .arena-lobby-empty { + font-family: "Cinzel", serif; + font-size: 12px; + color: #606060; + padding: 12px 0; + } + .arena-lobby-row { + display: flex; + align-items: center; + justify-content: space-between; + background: linear-gradient(#2a1a08, #1a0f04); + border: 1px solid #6b4b2a; + border-radius: 8px; + padding: 10px 14px; + margin-bottom: 6px; + } + .arena-lobby-row-info { display: flex; align-items: center; gap: 12px; } + .arena-lobby-leader { font-family: "Cinzel", serif; font-size: 13px; color: #f0d9a6; } + .arena-lobby-level { font-size: 11px; color: #a08060; } + .arena-lobby-count { font-size: 11px; color: #6a9a4a; } + .arena-btn-join { + background: linear-gradient(#1a4a18, #0f2a0e); + border: 2px solid #4a8a3c; + border-radius: 6px; + color: #a0e090; + font-family: "Cinzel", serif; + font-size: 11px; + padding: 5px 12px; + cursor: pointer; + transition: 0.2s; + } + .arena-btn-join:hover { border-color: #8ae060; color: #c0f0a0; } + + /* ── Team-Panel ── */ + .arena-team-box { + background: linear-gradient(#2a1a08, #1a0f04); + border: 2px solid #6b4b2a; + border-radius: 10px; + padding: 14px; + } + .arena-team-title { + font-family: "Cinzel", serif; + font-size: 13px; + color: #f0d060; + letter-spacing: 2px; + margin-bottom: 10px; + } + .arena-team-player { + display: flex; + align-items: center; + gap: 10px; + padding: 7px 10px; + border: 1px solid #3a2810; + border-radius: 6px; + margin-bottom: 5px; + background: rgba(255,255,255,0.03); + } + .arena-team-player.ready { border-color: #4a8a3c; background: rgba(74,138,60,0.1); } + .arena-team-player-name { font-family: "Cinzel", serif; font-size: 12px; color: #f0d9a6; flex: 1; } + .arena-team-player-level { font-size: 11px; color: #a08060; } + .arena-team-player-status { font-size: 11px; } + .arena-waiting-partner { + font-family: "Cinzel", serif; + font-size: 11px; + color: #a08060; + text-align: center; + padding: 8px; + animation: pulse 2s ease-in-out infinite; + } + .arena-btn-ready { + width: 100%; + margin-top: 10px; + background: linear-gradient(#1a4a18, #0f2a0e); + border: 2px solid #4a8a3c; + border-radius: 8px; + color: #a0e090; + font-family: "Cinzel", serif; + font-size: 14px; + padding: 10px; + cursor: pointer; + transition: 0.2s; + } + .arena-btn-ready:hover:not([disabled]) { border-color: #8ae060; background: linear-gradient(#2a6a28, #1a3a18); } + .arena-btn-ready.active { border-color: #8ae060; color: #c0f0a0; cursor: default; } + .arena-searching-box { + font-family: "Cinzel", serif; + font-size: 12px; + color: #dceb15; + text-align: center; + padding: 10px; + border: 1px solid rgba(255,215,80,0.3); + border-radius: 8px; + margin-top: 8px; + animation: pulse 2s ease-in-out infinite; + } `; document.head.appendChild(style); } @@ -229,17 +392,186 @@ function initArenaModes() { document.querySelectorAll(".arena-mode-card").forEach((card) => { card.addEventListener("click", () => { const mode = card.dataset.mode; - if (mode === "1v1") { handle1v1Click(card); + } else if (mode === "2v2") { + open2v2Lobby(); } else { console.log("Arena Modus gewΓ€hlt:", mode); - // Platzhalter fΓΌr 2v2 / 4v4 } }); }); } +/* ══════════════════════════════════════════════════════════ + 2v2 LOBBY +══════════════════════════════════════════════════════════ */ +let my2v2TeamId = null; +let myArenaData = null; + +async function open2v2Lobby() { + const socket = getSocket(); + if (!socket) { showArenaError("Keine Verbindung zum Server."); return; } + + // Spielerdaten laden + if (!myArenaData) { + try { + const res = await fetch("/arena/me"); + if (!res.ok) throw new Error(res.status); + myArenaData = await res.json(); + } catch { + showArenaError("Spielerdaten konnten nicht geladen werden."); + return; + } + } + + // Screen wechseln + document.getElementById("arena-mode-screen").style.display = "none"; + document.getElementById("arena-2v2-screen").style.display = "flex"; + + // Lobbyliste anfordern + socket.emit("get_2v2_lobbies"); + + // ZurΓΌck-Button + document.getElementById("arena-2v2-back").onclick = () => { + leave2v2Team(socket); + document.getElementById("arena-2v2-screen").style.display = "none"; + document.getElementById("arena-mode-screen").style.display = ""; + my2v2TeamId = null; + }; + + // Team erstellen + document.getElementById("arena-create-team-btn").onclick = () => { + socket.emit("create_2v2_team", myArenaData); + }; + + // Socket-Listener registrieren (einmalig) + socket.off("2v2_lobbies"); + socket.off("2v2_team_joined"); + socket.off("2v2_team_update"); + socket.off("2v2_partner_left"); + socket.off("2v2_searching"); + socket.off("match_found_2v2"); + socket.off("2v2_error"); + + socket.on("2v2_lobbies", (list) => render2v2LobbyList(list, socket)); + + socket.on("2v2_team_joined", (data) => { + my2v2TeamId = data.teamId; + document.getElementById("arena-team-panel").style.display = "block"; + document.getElementById("arena-lobby-section").style.display = "none"; + }); + + socket.on("2v2_team_update", (data) => render2v2TeamPanel(data, socket)); + + socket.on("2v2_partner_left", (data) => { + const status = document.getElementById("arena-team-status"); + if (status) status.innerHTML = `⚠️ ${data.name} hat das Team verlassen.`; + // Bereit-Button zurΓΌcksetzen + render2v2TeamPanel({ teamId: my2v2TeamId, players: [{ name: myArenaData.name, level: myArenaData.level, ready: false }], count: 1 }, socket); + }); + + socket.on("2v2_searching", () => { + const status = document.getElementById("arena-team-status"); + if (status) status.innerHTML = `
⏳ Suche nach Gegnerteam…
`; + const actions = document.getElementById("arena-team-actions"); + if (actions) actions.innerHTML = ""; + }); + + socket.on("match_found_2v2", (data) => { + socket.off("2v2_lobbies"); + socket.off("2v2_team_update"); + socket.off("2v2_partner_left"); + socket.off("2v2_searching"); + + showMatchFoundOverlay(myArenaData.name, `Team ${data.myTeam === 1 ? 2 : 1}`, () => { + document.getElementById("arena-2v2-screen").style.display = "none"; + document.getElementById("arena-mode-screen").style.display = ""; + openArenaPopup( + `/arena/2v2?match=${encodeURIComponent(data.matchId)}&slot=${encodeURIComponent(data.mySlot)}`, + data.opponents?.join(" & ") || "Gegner", + data.matchId, + ); + }); + }); + + socket.on("2v2_error", (data) => { + const status = document.getElementById("arena-team-status"); + if (status) { status.innerHTML = `❌ ${data.message}`; } + }); +} + +function render2v2LobbyList(list, socket) { + const el = document.getElementById("arena-lobby-list"); + if (!el) return; + if (!list.length) { + el.innerHTML = `
Keine offenen Teams vorhanden.
`; + return; + } + el.innerHTML = list.map(team => ` +
+
+ βš”οΈ ${team.leader} + Lvl ${team.leaderLevel} + ${team.count}/2 Spieler +
+ +
+ `).join(""); + + el.querySelectorAll(".arena-btn-join").forEach(btn => { + btn.addEventListener("click", () => { + socket.emit("join_2v2_team", { teamId: btn.dataset.teamid, playerData: myArenaData }); + }); + }); +} + +function render2v2TeamPanel(data, socket) { + const playersEl = document.getElementById("arena-team-players"); + const actionsEl = document.getElementById("arena-team-actions"); + const statusEl = document.getElementById("arena-team-status"); + if (!playersEl || !actionsEl) return; + + playersEl.innerHTML = data.players.map(p => ` +
+ ${p.name} + Lvl ${p.level} + ${p.ready ? 'βœ… Bereit' : 'βŒ› Wartet'} +
+ `).join(""); + + if (data.count < 2) { + actionsEl.innerHTML = `
Warte auf Partner…
`; + if (statusEl) statusEl.innerHTML = ""; + } else { + const myEntry = data.players.find(p => p.name === myArenaData?.name); + const iAmReady = myEntry?.ready; + actionsEl.innerHTML = iAmReady + ? `` + : ``; + + if (!iAmReady) { + document.getElementById("arena-ready-btn")?.addEventListener("click", () => { + socket.emit("2v2_player_ready", { teamId: my2v2TeamId }); + }); + } + } +} + +function leave2v2Team(socket) { + if (my2v2TeamId) { + socket.emit("leave_2v2_team"); + my2v2TeamId = null; + } + socket.off("2v2_lobbies"); + socket.off("2v2_team_joined"); + socket.off("2v2_team_update"); + socket.off("2v2_partner_left"); + socket.off("2v2_searching"); + socket.off("match_found_2v2"); + socket.off("2v2_error"); +} + /* ── 1v1: Hauptlogik ───────────────────────────────────────────────────────── */ async function handle1v1Click(card) { const socket = getSocket(); diff --git a/public/js/quickmenu/events.js b/public/js/quickmenu/events.js index 3296827..69239a1 100644 --- a/public/js/quickmenu/events.js +++ b/public/js/quickmenu/events.js @@ -202,16 +202,30 @@ export async function loadEvents() {
- -