diff --git a/public/css/events.css b/public/css/events.css index b7684f8..02c2972 100644 --- a/public/css/events.css +++ b/public/css/events.css @@ -31,7 +31,7 @@ justify-content: center; padding: 6px; box-sizing: border-box; - position: relative; /* ← fix: damit event-done-overlay korrekt positioniert wird */ + position: relative; /* ← fix: damit event-done-overlay korrekt positioniert wird */ } .event-card-img-wrap img { @@ -406,7 +406,73 @@ white-space: nowrap; } -/* ── Holz-Spenden Stempel ── */ +/* ── Arena Daily UI ── */ +.arena-daily-wrap { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + gap: 16px; + flex: 1; + padding: 20px; +} + +.arena-mode-card-daily { + display: flex; + flex-direction: column; + align-items: center; + gap: 8px; + padding: 20px 40px; + background: linear-gradient(135deg, #2a1a08, #1a0f04); + border: 2px solid #6b4b2a; + border-radius: 12px; + cursor: pointer; + transition: all 0.2s; +} +.arena-mode-card-daily:hover { + border-color: #f0d060; + box-shadow: 0 0 20px rgba(200,160,60,0.3); + transform: scale(1.04); +} +.arena-mode-card-daily.searching { + opacity: 0.6; + pointer-events: none; + border-color: rgba(255,215,80,0.5); +} +.arena-mode-icon { font-size: 2rem; } +.arena-mode-label-daily { + font-family: "Cinzel", serif; + font-size: 18px; + font-weight: bold; + color: #f0d9a6; +} +.arena-mode-desc-daily { + font-family: "Cinzel", serif; + font-size: 11px; + color: #a08060; + text-align: center; +} + +#arena-daily-status { + padding: 10px 18px; + border-radius: 8px; + background: rgba(255,215,80,0.08); + border: 1px solid rgba(255,215,80,0.3); + color: #dceb15; + font-family: "Cinzel", serif; + font-size: 12px; + text-align: center; + letter-spacing: 1px; + animation: pulse 2s ease-in-out infinite; +} +.arena-cancel-link { + display: inline-block; + margin-top: 6px; + font-size: 10px; + color: rgba(255,100,100,0.8); + cursor: pointer; + text-decoration: underline; +} .wood-btn-wrap { position: relative; width: 100%; @@ -440,7 +506,7 @@ color: #e85010; background: rgba(0, 0, 0, 0.5); font-family: "Cinzel", serif; - font-size: 14px; + font-size: 8px; font-weight: bold; letter-spacing: 1px; white-space: nowrap; @@ -451,7 +517,7 @@ .gold-stamp { border-color: #b8960a; - color: #000000; + color: #f0c020; box-shadow: 0 0 6px rgba(200, 160, 10, 0.5); text-shadow: 0 0 6px rgba(200, 160, 10, 0.6); } diff --git a/public/js/quickmenu.js b/public/js/quickmenu.js index 9ce799d..2cd21af 100644 --- a/public/js/quickmenu.js +++ b/public/js/quickmenu.js @@ -120,6 +120,13 @@ function isBoosterSpinning() { const goldUi = document.getElementById("gold-ui"); if (goldUi && goldUi.style.display !== "none" && goldUi.querySelector(".booster-slot.spinning")) return true; + // Arena Daily: sperren während Gegnersuche läuft + const arenaUi = document.getElementById("arena-ui"); + if (arenaUi && arenaUi.style.display !== "none") { + const card = arenaUi.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 aa72776..54fe9f6 100644 --- a/public/js/quickmenu/events.js +++ b/public/js/quickmenu/events.js @@ -60,7 +60,7 @@ export async function loadEvents() { label: "Booster Öffnen", type: "booster", }, - { id: 2, img: "/images/items/1v1.png", label: "1 v 1" }, + { 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: 4, @@ -189,6 +189,19 @@ export async function loadEvents() { + + +
@@ -207,6 +220,7 @@ export async function loadEvents() { const boosterUi = body.querySelector("#booster-ui"); const woodUi = body.querySelector("#wood-ui"); const goldUi = body.querySelector("#gold-ui"); + const arenaUi = body.querySelector("#arena-ui"); const eventsGrid = body.querySelector("#events-grid"); /* ── Event-Karten ── */ @@ -221,6 +235,12 @@ export async function loadEvents() { resetBooster(); return; } + if (card.dataset.type === "arena") { + eventsGrid.style.display = "none"; + arenaUi.style.display = "flex"; + resetArenaDaily(); + return; + } if (card.dataset.type === "gold") { eventsGrid.style.display = "none"; goldUi.style.display = "flex"; @@ -318,8 +338,156 @@ export async function loadEvents() { isGoldSpinning = false; }); + body.querySelector("#arena-back-btn").addEventListener("click", () => { + if (isArenaSearching) return; // Während Suche gesperrt + eventsGrid.style.display = ""; + arenaUi.style.display = "none"; + cancelArenaSearch(); + }); + // ESC wird zentral in quickmenu.js behandelt (verhindert Listener-Stapelung) + /* ── Arena Daily Zustand ── */ + let isArenaSearching = false; + + function resetArenaDaily() { + isArenaSearching = false; + const card = body.querySelector("#arena-1v1-card"); + const status = body.querySelector("#arena-daily-status"); + if (card) { + card.classList.remove("searching"); + card.querySelector(".arena-mode-label-daily").textContent = "1v1"; + card.querySelector(".arena-mode-desc-daily").textContent = "Einzelkampf – Beweis deine Stärke im Duell"; + } + if (status) status.style.display = "none"; + + const backBtn = body.querySelector("#arena-back-btn"); + if (backBtn) { backBtn.style.opacity = "1"; backBtn.style.cursor = "pointer"; } + } + + function cancelArenaSearch() { + const socket = window._socket; + if (socket) { + socket.emit("leave_1v1"); + socket.off("match_found"); + socket.off("queue_status"); + } + resetArenaDaily(); + } + + body.querySelector("#arena-1v1-card").addEventListener("click", async () => { + if (isArenaSearching) return; + + const socket = window._socket; + if (!socket) { + showArenaStatus("❌ Keine Verbindung zum Server.", true); + return; + } + + // Spielerdaten laden + let me; + try { + const res = await fetch("/arena/me"); + if (!res.ok) throw new Error(res.status); + me = await res.json(); + } catch { + showArenaStatus("❌ Spielerdaten konnten nicht geladen werden.", true); + return; + } + + isArenaSearching = true; + const card1v1 = body.querySelector("#arena-1v1-card"); + card1v1.classList.add("searching"); + card1v1.querySelector(".arena-mode-label-daily").textContent = "⏳ Suche…"; + card1v1.querySelector(".arena-mode-desc-daily").textContent = "Warte auf passenden Gegner…"; + + // Zurück-Button sperren während Suche + const backBtn = body.querySelector("#arena-back-btn"); + backBtn.style.opacity = "0.35"; + backBtn.style.cursor = "not-allowed"; + + showArenaStatus(`⏳ Suche Gegner (Level ${Math.max(1, me.level - 5)}–${me.level + 5})…`); + + socket.off("match_found"); + socket.off("queue_status"); + + socket.on("queue_status", (data) => { + if (data.status === "waiting") { + const pool = data.poolSize ? ` · ${data.poolSize} im Pool` : ""; + showArenaStatus(`⏳ Suche Gegner (Level ${Math.max(1, me.level - 5)}–${me.level + 5})${pool} +
Suche abbrechen`); + body.querySelector("#arena-cancel-link")?.addEventListener("click", () => { + cancelArenaSearch(); + }); + } + }); + + socket.once("match_found", (data) => { + socket.off("queue_status"); + isArenaSearching = false; + + // Daily markieren + markDailyComplete(2); + + // Match-Overlay + Popup öffnen (aus arena.js Logik) + showArenaMatchFound(me.name, data.opponent.name, () => { + eventsGrid.style.display = ""; + arenaUi.style.display = "none"; + openArenaMatchPopup( + `/arena/1v1?match=${encodeURIComponent(data.matchId)}&slot=${encodeURIComponent(data.mySlot)}`, + data.opponent.name, + data.matchId, + ); + }); + }); + + socket.emit("join_1v1", { id: me.id, name: me.name, level: me.level }); + }); + + function showArenaStatus(html, isError = false) { + const box = body.querySelector("#arena-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); + } + + function showArenaMatchFound(myName, opponentName, onDone) { + if (document.getElementById("match-found-overlay")) return; + const overlay = document.createElement("div"); + overlay.id = "match-found-overlay"; + overlay.style.cssText = "position:fixed;inset:0;z-index:10000;background:rgba(0,0,0,0.9);display:flex;flex-direction:column;align-items:center;justify-content:center;"; + overlay.innerHTML = ` +
⚔️ Match gefunden!
+
${myName}  vs  ${opponentName}
+
+
+
`; + document.body.appendChild(overlay); + requestAnimationFrame(() => { const b = document.getElementById("mfBar"); if (b) b.style.width = "100%"; }); + setTimeout(() => { overlay.remove(); onDone(); }, 1600); + } + + function openArenaMatchPopup(src, opponentName, matchId) { + 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;"; + 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.innerHTML = ` +
+ ⚔️ 1v1 · vs ${opponentName} + ${matchId} +
+ `; + document.body.appendChild(backdrop); + document.body.appendChild(popup); + } + /* ── Booster Zustand ── */ let allCards = []; let isSpinning = false;