diff --git a/public/js/quickmenu.js b/public/js/quickmenu.js
index 2cd21af..f0a9972 100644
--- a/public/js/quickmenu.js
+++ b/public/js/quickmenu.js
@@ -127,6 +127,12 @@ function isBoosterSpinning() {
if (card) return true;
}
+ const arena2Ui = document.getElementById("arena2-ui");
+ if (arena2Ui && arena2Ui.style.display !== "none") {
+ const card = arena2Ui.querySelector(".arena-mode-card-daily.searching");
+ if (card) return true;
+ }
+
return false;
}
diff --git a/public/js/quickmenu/events.js b/public/js/quickmenu/events.js
index a21dda4..711b14b 100644
--- a/public/js/quickmenu/events.js
+++ b/public/js/quickmenu/events.js
@@ -61,7 +61,7 @@ export async function loadEvents() {
type: "booster",
},
{ id: 2, img: "/images/items/1v1.png", label: "1 v 1", type: "arena" },
- { id: 3, img: "/images/items/2v2.png", label: "2 v 2" },
+ { id: 3, img: "/images/items/2v2.png", label: "2 v 2", type: "arena2" },
{
id: 4,
img: "/images/items/holz.png",
@@ -202,6 +202,19 @@ export async function loadEvents() {
+
+
`;
document.body.appendChild(overlay);
- requestAnimationFrame(() => {
- const b = document.getElementById("mfBar");
- if (b) b.style.width = "100%";
- });
- setTimeout(() => {
- overlay.remove();
- onDone();
- }, 1600);
+ requestAnimationFrame(() => { const b = document.getElementById("mfBar"); if (b) b.style.width = "100%"; });
+ setTimeout(() => { overlay.remove(); onDone(); }, 1600);
}
- function openArenaMatchPopup(src, opponentName, matchId) {
+ function openArenaMatchPopup(src, opponentName, matchId, mode = "1v1") {
document.getElementById("arena-backdrop")?.remove();
document.getElementById("arena-popup")?.remove();
const backdrop = document.createElement("div");
backdrop.id = "arena-backdrop";
- backdrop.style.cssText =
- "position:fixed;inset:0;background:rgba(0,0,0,0.82);backdrop-filter:blur(5px);z-index:9998;";
+ backdrop.style.cssText = "position:fixed;inset:0;background:rgba(0,0,0,0.82);backdrop-filter:blur(5px);z-index:9998;";
const popup = document.createElement("div");
popup.id = "arena-popup";
- popup.style.cssText =
- "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);";
+ popup.style.cssText = "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);";
popup.innerHTML = `
- ⚔️ 1v1 · vs ${opponentName}
+ ⚔️ ${mode} · vs ${opponentName}
${matchId}
`;
@@ -509,6 +508,111 @@ export async function loadEvents() {
document.body.appendChild(popup);
}
+ body.querySelector("#arena2-back-btn").addEventListener("click", () => {
+ if (isArena2Searching) return;
+ eventsGrid.style.display = "";
+ arena2Ui.style.display = "none";
+ cancelArena2Search();
+ });
+
+ /* ── Arena2 Daily Zustand (2v2) ── */
+ let isArena2Searching = false;
+
+ function resetArena2Daily() {
+ isArena2Searching = false;
+ const card = body.querySelector("#arena-2v2-card");
+ const status = body.querySelector("#arena2-daily-status");
+ if (card) {
+ card.classList.remove("searching");
+ card.querySelector(".arena-mode-label-daily").textContent = "2v2";
+ card.querySelector(".arena-mode-desc-daily").textContent = "Verbünde dich mit einem Kameraden im Kampf";
+ }
+ if (status) status.style.display = "none";
+ const backBtn = body.querySelector("#arena2-back-btn");
+ if (backBtn) { backBtn.style.opacity = "1"; backBtn.style.cursor = "pointer"; }
+ }
+
+ function cancelArena2Search() {
+ const socket = window._socket;
+ if (socket) {
+ socket.emit("leave_2v2");
+ socket.off("match_found_2v2");
+ socket.off("queue_status_2v2");
+ }
+ resetArena2Daily();
+ }
+
+ body.querySelector("#arena-2v2-card").addEventListener("click", async () => {
+ if (isArena2Searching) return;
+
+ const socket = window._socket;
+ if (!socket) {
+ showArena2Status("❌ Keine Verbindung zum Server.", true);
+ return;
+ }
+
+ let me;
+ try {
+ const res = await fetch("/arena/me");
+ if (!res.ok) throw new Error(res.status);
+ me = await res.json();
+ } catch {
+ showArena2Status("❌ Spielerdaten konnten nicht geladen werden.", true);
+ return;
+ }
+
+ isArena2Searching = true;
+ const card2v2 = body.querySelector("#arena-2v2-card");
+ card2v2.classList.add("searching");
+ card2v2.querySelector(".arena-mode-label-daily").textContent = "⏳ Suche…";
+ card2v2.querySelector(".arena-mode-desc-daily").textContent = "Warte auf Mitspieler & Gegner…";
+
+ const backBtn = body.querySelector("#arena2-back-btn");
+ backBtn.style.opacity = "0.35";
+ backBtn.style.cursor = "not-allowed";
+
+ showArena2Status(`⏳ Suche Gegner (Level ${Math.max(1, me.level - 5)}–${me.level + 5})…`);
+
+ socket.off("match_found_2v2");
+ socket.off("queue_status_2v2");
+
+ socket.on("queue_status_2v2", (data) => {
+ if (data.status === "waiting") {
+ const pool = data.poolSize ? ` · ${data.poolSize} im Pool` : "";
+ showArena2Status(`⏳ Suche Gegner (Level ${Math.max(1, me.level - 5)}–${me.level + 5})${pool}
+
Suche abbrechen`);
+ body.querySelector("#arena2-cancel-link")?.addEventListener("click", () => cancelArena2Search());
+ }
+ });
+
+ socket.once("match_found_2v2", (data) => {
+ socket.off("queue_status_2v2");
+ isArena2Searching = false;
+ markDailyComplete(3);
+ showArenaMatchFound(me.name, data.opponent.name, () => {
+ eventsGrid.style.display = "";
+ arena2Ui.style.display = "none";
+ openArenaMatchPopup(
+ `/arena/2v2?match=${encodeURIComponent(data.matchId)}&slot=${encodeURIComponent(data.mySlot)}`,
+ data.opponent.name,
+ data.matchId,
+ "2v2",
+ );
+ });
+ });
+
+ socket.emit("join_2v2", { id: me.id, name: me.name, level: me.level });
+ });
+
+ function showArena2Status(html, isError = false) {
+ const box = body.querySelector("#arena2-daily-status");
+ if (!box) return;
+ box.style.display = "block";
+ box.style.color = isError ? "#e74c3c" : "#dceb15";
+ box.innerHTML = html;
+ if (isError) setTimeout(() => { box.style.display = "none"; }, 3000);
+ }
+
/* ── Booster Zustand ── */
let allCards = [];
let isSpinning = false;