diff --git a/public/js/buildings/arena.js b/public/js/buildings/arena.js index 20f65e3..b3dcb46 100644 --- a/public/js/buildings/arena.js +++ b/public/js/buildings/arena.js @@ -89,8 +89,8 @@ function injectArenaStyles() { const style = document.createElement("style"); style.id = "arena-popup-styles"; style.textContent = ` - @keyframes arenaFadeIn { from { opacity:0; } to { opacity:1; } } - @keyframes arenaScaleIn { from { transform:scale(0.94); opacity:0; } to { transform:scale(1); opacity:1; } } + @keyframes arenaFadeIn { from{opacity:0;} to{opacity:1;} } + @keyframes arenaScaleIn { from{transform:scale(0.94);opacity:0;} to{transform:scale(1);opacity:1;} } @keyframes pulse { 0%,100%{opacity:1;} 50%{opacity:0.5;} } #arena-queue-status { @@ -115,7 +115,7 @@ function injectArenaStyles() { #arena-popup { position:fixed; inset:50px; z-index:9999; display:flex; flex-direction:column; border-radius:14px; overflow:hidden; - box-shadow: 0 0 0 1px rgba(255,215,80,0.35), 0 30px 90px rgba(0,0,0,0.85); + box-shadow:0 0 0 1px rgba(255,215,80,0.35),0 30px 90px rgba(0,0,0,0.85); animation:arenaScaleIn 0.28s cubic-bezier(0.22,1,0.36,1); } #arena-popup-titlebar { @@ -139,64 +139,59 @@ function injectArenaStyles() { .arena-mode-card.searching { opacity:0.6; pointer-events:none; border-color:rgba(255,215,80,0.5)!important; } - #arena-2v2-screen, #arena-4v4-screen { - flex-direction:column; gap:14px; padding:16px; height:100%; overflow-y:auto; - } + #arena-2v2-screen, #arena-4v4-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 { 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 { 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 { 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 { 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; } .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-slots { font-family:"Cinzel",serif; font-size:11px; color:#a08060; text-align:center; padding:4px 0 8px; } + + /* ββ Spieler-Zeile im Team ββ */ .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); + 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-team-player.ready { border-color:#4a8a3c; background:rgba(74,138,60,0.1); } + .arena-team-player.is-leader::before { content:"π "; font-size:11px; } + .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; } + + /* ββ Kick-Button ββ */ + .arena-btn-kick { + background: linear-gradient(#4a1010, #2a0808); + border: 1px solid #8a3030; + border-radius: 5px; + color: #e07070; + font-size: 11px; + font-family: "Cinzel", serif; + padding: 3px 8px; + cursor: pointer; + transition: 0.2s; + flex-shrink: 0; } + .arena-btn-kick:hover { border-color:#e05050; color:#ff9090; background:linear-gradient(#6a1818,#3a1010); } + + .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; - } - .arena-team-slots { - font-family:"Cinzel",serif; font-size:11px; color:#a08060; - text-align:center; padding:4px 0 8px; - } + .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); } @@ -205,16 +200,16 @@ function injectArenaStyles() { function getSocket() { return window._socket || null; } /* ββ State ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ */ -let myArenaData = null; -let my2v2TeamId = null; -let my4v4TeamId = null; +let myArenaData = null; +let my2v2TeamId = null; +let my4v4TeamId = null; /* ββ Modus-Klicks βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ */ function initArenaModes() { document.querySelectorAll(".arena-mode-card").forEach(card => { card.addEventListener("click", () => { const mode = card.dataset.mode; - if (mode === "1v1") handle1v1Click(card); + if (mode === "1v1") handle1v1Click(card); else if (mode === "2v2") openTeamLobby("2v2"); else if (mode === "4v4") openTeamLobby("4v4"); }); @@ -233,24 +228,22 @@ function initArenaModes() { if (mode === "4v4") my4v4TeamId = null; }); - /* Team erstellen Buttons */ + /* Team erstellen */ document.addEventListener("click", e => { const btn = e.target.closest(".arena-btn-create"); if (!btn) return; - const mode = btn.dataset.create; - if (!mode) return; + const mode = btn.dataset.create; const socket = getSocket(); if (!socket) return showModeError(mode, "Keine Verbindung zum Server."); - console.log(`[${mode}] Team erstellen β sende create_${mode}_team mit:`, myArenaData); + console.log(`[${mode}] create_${mode}_team:`, myArenaData); socket.emit(`create_${mode}_team`, myArenaData); }); } -/* ββ Team-Lobby ΓΆffnen (2v2 oder 4v4) ββββββββββββββββββββββββββββββββββββββββ */ +/* ββ Team-Lobby ΓΆffnen ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ */ async function openTeamLobby(mode) { const socket = getSocket(); - /* Screen sofort wechseln */ document.getElementById("arena-mode-screen").style.display = "none"; document.getElementById(`arena-${mode}-screen`).style.display = "flex"; @@ -259,7 +252,6 @@ async function openTeamLobby(mode) { return; } - /* Spielerdaten laden */ if (!myArenaData) { try { const res = await fetch("/arena/me"); @@ -268,15 +260,13 @@ async function openTeamLobby(mode) { console.log(`[${mode}] Spielerdaten:`, myArenaData); } catch (err) { console.error(`[${mode}] Spielerdaten Fehler:`, err); - showModeError(mode, "Spielerdaten konnten nicht geladen werden. (Eingeloggt?)"); + showModeError(mode, "Spielerdaten konnten nicht geladen werden."); return; } } - /* Lobbyliste anfordern */ socket.emit(`get_${mode}_lobbies`); - /* Alte Listener entfernen */ socket.off(`${mode}_lobbies`); socket.off(`${mode}_team_joined`); socket.off(`${mode}_team_update`); @@ -284,9 +274,9 @@ async function openTeamLobby(mode) { socket.off(`${mode}_searching`); socket.off(`match_found_${mode}`); socket.off(`${mode}_error`); + socket.off(`${mode}_kicked`); - /* Listener registrieren */ - socket.on(`${mode}_lobbies`, list => renderLobbyList(list, socket, mode)); + socket.on(`${mode}_lobbies`, list => renderLobbyList(list, socket, mode)); socket.on(`${mode}_team_joined`, data => { if (mode === "2v2") my2v2TeamId = data.teamId; @@ -302,7 +292,7 @@ async function openTeamLobby(mode) { const status = document.getElementById(`arena-${mode}-team-status`); if (status) status.innerHTML = `β οΈ ${data.name} hat das Team verlassen.`; const teamId = mode === "2v2" ? my2v2TeamId : my4v4TeamId; - renderTeamPanel({ teamId, players: [{ name: myArenaData.name, level: myArenaData.level, ready: false }], count: 1, max: mode === "4v4" ? 4 : 2 }, socket, mode); + renderTeamPanel({ teamId, leaderId: null, players: [{ socketId: socket.id, name: myArenaData.name, level: myArenaData.level, ready: false }], count: 1, max: mode === "4v4" ? 4 : 2 }, socket, mode); }); socket.on(`${mode}_searching`, () => { @@ -333,13 +323,28 @@ async function openTeamLobby(mode) { console.warn(`[${mode}] Fehler:`, data.message); showModeError(mode, data.message); }); + + /* ββ Gekickt worden ββ */ + socket.on(`${mode}_kicked`, data => { + if (mode === "2v2") my2v2TeamId = null; + if (mode === "4v4") my4v4TeamId = null; + + // Team-Panel verstecken, Lobby-Liste wieder zeigen + document.getElementById(`arena-${mode}-team-panel`).style.display = "none"; + document.getElementById(`arena-${mode}-lobby-section`).style.display = "block"; + + // Lobby-Liste neu laden + socket.emit(`get_${mode}_lobbies`); + + showModeError(mode, data.message || "Du wurdest aus dem Team entfernt."); + }); } /* ββ Lobby-Liste rendern ββββββββββββββββββββββββββββββββββββββββββββββββββββββ */ function renderLobbyList(list, socket, mode) { - const el = document.getElementById(`arena-${mode}-lobby-list`); - if (!el) return; + const el = document.getElementById(`arena-${mode}-lobby-list`); const max = mode === "4v4" ? 4 : 2; + if (!el) return; if (!list.length) { el.innerHTML = `