This commit is contained in:
cay 2026-04-14 06:53:49 +01:00
parent ba987e5564
commit e8145a6b58
3 changed files with 15 additions and 104 deletions

View File

@ -51,17 +51,6 @@ export async function loadArena() {
</select> </select>
</div> </div>
<div class="arena-mode-wrap">
<div class="arena-mode-card arena-mode-locked" data-mode="4v4">
<div class="arena-mode-icon">🛡</div>
<div class="arena-mode-label">4v4</div>
<div class="arena-mode-desc">Schlachtruf</div>
</div>
<select class="arena-deck-select" data-mode="4v4">
${deckOptions}
</select>
</div>
</div> </div>
<!-- Level-Range Auswahl (nur 1v1) --> <!-- Level-Range Auswahl (nur 1v1) -->
@ -105,29 +94,6 @@ export async function loadArena() {
</div> </div>
</div> </div>
<!-- 4v4 Lobby -->
<div id="arena-4v4-screen" style="display:none;">
<div class="arena-lobby-header">
<button class="arena-back-btn" data-back="4v4"> Zurück</button>
<div class="arena-title" style="margin:0;">🛡 4v4 Team-Lobby</div>
</div>
<div id="arena-4v4-error" style="display:none;"></div>
<div id="arena-4v4-team-panel" style="display:none;">
<div class="arena-team-box">
<div class="arena-team-title">Dein Team (4v4)</div>
<div id="arena-4v4-team-players"></div>
<div id="arena-4v4-team-actions"></div>
</div>
<div id="arena-4v4-team-status"></div>
</div>
<div id="arena-4v4-lobby-section">
<div class="arena-lobby-actions">
<button class="arena-btn-create" data-create="4v4"> Eigenes Team erstellen</button>
</div>
<div class="arena-lobby-title">Offene Teams</div>
<div id="arena-4v4-lobby-list"><div class="arena-lobby-empty">Keine offenen Teams vorhanden.</div></div>
</div>
</div>
</div>`; </div>`;
injectArenaStyles(); injectArenaStyles();
@ -221,13 +187,13 @@ function injectArenaStyles() {
.qs-cancel { display:inline-block; margin-top:6px; font-size:11px; color:rgba(255,100,100,.8); cursor:pointer; text-decoration:underline; animation:none; } .qs-cancel { display:inline-block; margin-top:6px; font-size:11px; color:rgba(255,100,100,.8); cursor:pointer; text-decoration:underline; animation:none; }
.qs-cancel:hover { color:#e74c3c; } .qs-cancel:hover { color:#e74c3c; }
#arena-2v2-error,#arena-4v4-error { #arena-2v2-error {
padding:8px 12px; border-radius:7px; margin-bottom:8px; padding:8px 12px; border-radius:7px; margin-bottom:8px;
background:rgba(231,76,60,.12); border:1px solid rgba(231,76,60,.4); background:rgba(231,76,60,.12); border:1px solid rgba(231,76,60,.4);
color:#e74c3c; font-family:"Cinzel",serif; font-size:11px; text-align:center; color:#e74c3c; font-family:"Cinzel",serif; font-size:11px; text-align:center;
} }
#arena-2v2-screen,#arena-4v4-screen { flex-direction:column; gap:12px; padding:14px; height:100%; overflow-y:auto; } #arena-2v2-screen { flex-direction:column; gap:12px; padding:14px; height:100%; overflow-y:auto; }
.arena-lobby-header { display:flex; align-items:center; gap:14px; } .arena-lobby-header { display:flex; align-items:center; gap:14px; }
.arena-back-btn { background:none; border:1px solid rgba(255,200,80,.3); color:#c8960c; font-family:"Cinzel",serif; font-size:11px; padding:4px 10px; border-radius:4px; cursor:pointer; } .arena-back-btn { background:none; border:1px solid rgba(255,200,80,.3); color:#c8960c; font-family:"Cinzel",serif; font-size:11px; padding:4px 10px; border-radius:4px; cursor:pointer; }
.arena-back-btn:hover { background:rgba(200,150,12,.15); } .arena-back-btn:hover { background:rgba(200,150,12,.15); }
@ -362,7 +328,6 @@ function getSocket() { return window._socket || null; }
/* ── State ─────────────────────────────────────────────────*/ /* ── State ─────────────────────────────────────────────────*/
let myArenaData = null; let myArenaData = null;
let my2v2TeamId = null; let my2v2TeamId = null;
let my4v4TeamId = null;
let selectedDeckId = null; // Gewähltes Deck für das nächste Match let selectedDeckId = null; // Gewähltes Deck für das nächste Match
/* ── Modus-Initialisierung ─────────────────────────────────*/ /* ── Modus-Initialisierung ─────────────────────────────────*/
@ -394,7 +359,6 @@ function initArenaModes() {
sessionStorage.setItem("selectedDeckId", selectedDeckId); sessionStorage.setItem("selectedDeckId", selectedDeckId);
if (mode === "1v1") handle1v1Click(card); if (mode === "1v1") handle1v1Click(card);
else if (mode === "2v2") openTeamLobby("2v2"); else if (mode === "2v2") openTeamLobby("2v2");
else if (mode === "4v4") openTeamLobby("4v4");
}); });
}); });
@ -407,7 +371,6 @@ function initArenaModes() {
document.getElementById(`arena-${mode}-screen`).style.display = "none"; document.getElementById(`arena-${mode}-screen`).style.display = "none";
document.getElementById("arena-mode-screen").style.display = ""; document.getElementById("arena-mode-screen").style.display = "";
if (mode === "2v2") my2v2TeamId = null; if (mode === "2v2") my2v2TeamId = null;
if (mode === "4v4") my4v4TeamId = null;
return; return;
} }
@ -475,7 +438,7 @@ function cancelQueue(card) {
hideQueueStatus(); hideQueueStatus();
} }
/* ── Team-Lobby (2v2 / 4v4) ────────────────────────────────*/ /* ── Team-Lobby (2v2) ─────────────────────────────────────*/
async function openTeamLobby(mode) { async function openTeamLobby(mode) {
const socket = getSocket(); const socket = getSocket();
@ -510,7 +473,6 @@ async function openTeamLobby(mode) {
socket.on(`${mode}_team_joined`, data => { socket.on(`${mode}_team_joined`, data => {
if (mode === "2v2") my2v2TeamId = data.teamId; if (mode === "2v2") my2v2TeamId = data.teamId;
if (mode === "4v4") my4v4TeamId = data.teamId;
document.getElementById(`arena-${mode}-team-panel`).style.display = "block"; document.getElementById(`arena-${mode}-team-panel`).style.display = "block";
document.getElementById(`arena-${mode}-lobby-section`).style.display = "none"; document.getElementById(`arena-${mode}-lobby-section`).style.display = "none";
hideModeError(mode); hideModeError(mode);
@ -521,11 +483,11 @@ async function openTeamLobby(mode) {
socket.on(`${mode}_partner_left`, data => { socket.on(`${mode}_partner_left`, data => {
const statusEl = document.getElementById(`arena-${mode}-team-status`); const statusEl = document.getElementById(`arena-${mode}-team-status`);
if (statusEl) statusEl.innerHTML = `<span style="color:#e74c3c;">⚠️ ${data.name} hat das Team verlassen.</span>`; if (statusEl) statusEl.innerHTML = `<span style="color:#e74c3c;">⚠️ ${data.name} hat das Team verlassen.</span>`;
const teamId = mode === "2v2" ? my2v2TeamId : my4v4TeamId; const teamId = my2v2TeamId;
renderTeamPanel({ renderTeamPanel({
teamId, leaderId: null, teamId, leaderId: null,
players: [{ socketId: socket.id, name: myArenaData.name, level: myArenaData.level, ready: false }], players: [{ socketId: socket.id, name: myArenaData.name, level: myArenaData.level, ready: false }],
count: 1, max: mode === "4v4" ? 4 : 2 count: 1, max: 2
}, socket, mode); }, socket, mode);
}); });
@ -553,7 +515,6 @@ async function openTeamLobby(mode) {
socket.on(`${mode}_kicked`, data => { socket.on(`${mode}_kicked`, data => {
if (mode === "2v2") my2v2TeamId = null; if (mode === "2v2") my2v2TeamId = null;
if (mode === "4v4") my4v4TeamId = null;
document.getElementById(`arena-${mode}-team-panel`).style.display = "none"; document.getElementById(`arena-${mode}-team-panel`).style.display = "none";
document.getElementById(`arena-${mode}-lobby-section`).style.display = "block"; document.getElementById(`arena-${mode}-lobby-section`).style.display = "block";
socket.emit(`get_${mode}_lobbies`); socket.emit(`get_${mode}_lobbies`);
@ -564,7 +525,7 @@ async function openTeamLobby(mode) {
/* ── Lobby-Liste rendern ───────────────────────────────────*/ /* ── Lobby-Liste rendern ───────────────────────────────────*/
function renderLobbyList(list, socket, mode) { function renderLobbyList(list, socket, mode) {
const el = document.getElementById(`arena-${mode}-lobby-list`); const el = document.getElementById(`arena-${mode}-lobby-list`);
const max = mode === "4v4" ? 4 : 2; const max = 2;
if (!el) return; if (!el) return;
if (!list.length) { if (!list.length) {
el.innerHTML = `<div class="arena-lobby-empty">Keine offenen Teams vorhanden.</div>`; el.innerHTML = `<div class="arena-lobby-empty">Keine offenen Teams vorhanden.</div>`;
@ -593,8 +554,8 @@ function renderTeamPanel(data, socket, mode) {
const actionsEl = document.getElementById(`arena-${mode}-team-actions`); const actionsEl = document.getElementById(`arena-${mode}-team-actions`);
if (!playersEl || !actionsEl) return; if (!playersEl || !actionsEl) return;
const max = data.max || (mode === "4v4" ? 4 : 2); const max = data.max || 2;
const teamId = mode === "2v2" ? my2v2TeamId : my4v4TeamId; const teamId = my2v2TeamId;
const mySocketId = getSocket()?.id; const mySocketId = getSocket()?.id;
const iAmLeader = data.leaderId === mySocketId; const iAmLeader = data.leaderId === mySocketId;

View File

@ -160,48 +160,4 @@ router.get("/2v2", requireLogin, async (req, res) => {
} }
}); });
/* ================================
4v4 Spielfeld
GET /arena/4v4
================================ */
router.get("/4v4", requireLogin, async (req, res) => {
const userId = req.session.user.id;
const { match: matchId, slot } = req.query;
if (!matchId) {
return res.render("1v1-battlefield", {
title: "4v4 Kampf",
matchId: null,
mySlot: "team1_player1",
player1: req.session?.user?.ingame_name || "Spieler 1",
player2: "Gegner",
player1hp: 20,
player1mana: 3,
player2hp: 20,
player2mana: 3,
});
}
try {
const [[me]] = await db.query("SELECT ingame_name FROM accounts WHERE id = ?", [userId]);
const { hp, mana } = await getPlayerStats(userId);
res.render("1v1-battlefield", {
title: "⚔️ 4v4 Kampf",
matchId,
mySlot: slot || "team1_player1",
player1: me?.ingame_name || "Du",
player2: "Gegner",
player1hp: hp,
player1mana: mana,
player2hp: 20,
player2mana: 3,
});
} catch (err) {
console.error("[Arena /4v4]", err);
res.status(500).send("Fehler beim Laden des Spielfelds.");
}
});
module.exports = router; module.exports = router;

View File

@ -1,6 +1,6 @@
/* ============================================================ /* ============================================================
sockets/arena.socket.js sockets/arena.socket.js
1v1 Matchmaking + 2v2 Team-Lobby + 4v4 Team-Lobby 1v1 Matchmaking + 2v2 Team-Lobby
inkl. Kampfphase nach end_turn inkl. Kampfphase nach end_turn
============================================================ */ ============================================================ */
@ -21,25 +21,21 @@ const READY_TIMEOUT = 30;
const teams2v2 = new Map(); const teams2v2 = new Map();
const readyTeams2v2 = new Map(); const readyTeams2v2 = new Map();
/* ── 4v4 State ── */
const teams4v4 = new Map();
const readyTeams4v4 = new Map();
function generateId() { function generateId() {
return `${Date.now()}_${Math.random().toString(36).slice(2, 7)}`; return `${Date.now()}_${Math.random().toString(36).slice(2, 7)}`;
} }
/* /*
HELPER: Generisch für 2v2 UND 4v4 HELPER: Generisch für 2v2
*/ */
function getTeamMap(mode) { function getTeamMap(mode) {
return mode === "4v4" ? teams4v4 : teams2v2; return teams2v2;
} }
function getReadyMap(mode) { function getReadyMap(mode) {
return mode === "4v4" ? readyTeams4v4 : readyTeams2v2; return readyTeams2v2;
} }
function getMaxPlayers(mode) { function getMaxPlayers(mode) {
return mode === "4v4" ? 4 : 2; return 2;
} }
function broadcastLobbies(io, mode) { function broadcastLobbies(io, mode) {
@ -259,7 +255,7 @@ function boardStateToCards(boardState) {
} }
/* /*
Handler-Generator für 2v2 und 4v4 Handler-Generator für 2v2
*/ */
function registerTeamModeHandlers(io, socket, mode) { function registerTeamModeHandlers(io, socket, mode) {
const max = getMaxPlayers(mode); const max = getMaxPlayers(mode);
@ -787,9 +783,8 @@ function registerArenaHandlers(io, socket) {
}, animDuration); }, animDuration);
}); });
/* ── 2v2 & 4v4 ── */ /* ── 2v2 ── */
registerTeamModeHandlers(io, socket, "2v2"); registerTeamModeHandlers(io, socket, "2v2");
registerTeamModeHandlers(io, socket, "4v4");
/* ── Disconnect ── */ /* ── Disconnect ── */
socket.on("disconnect", () => { socket.on("disconnect", () => {
@ -797,7 +792,6 @@ function registerArenaHandlers(io, socket) {
console.log(`[1v1] ${socket.id} disconnected aus Pool entfernt.`); console.log(`[1v1] ${socket.id} disconnected aus Pool entfernt.`);
} }
leaveAllTeams_nvn(socket.id, io, "2v2"); leaveAllTeams_nvn(socket.id, io, "2v2");
leaveAllTeams_nvn(socket.id, io, "4v4");
}); });
} }