diff --git a/public/images/items/1v1.png b/public/images/items/1v1.png new file mode 100644 index 0000000..aca446f Binary files /dev/null and b/public/images/items/1v1.png differ diff --git a/public/images/items/2v2.png b/public/images/items/2v2.png new file mode 100644 index 0000000..69c39c3 Binary files /dev/null and b/public/images/items/2v2.png differ diff --git a/public/js/quickmenu/events.js b/public/js/quickmenu/events.js index 551d8a2..d727be1 100644 --- a/public/js/quickmenu/events.js +++ b/public/js/quickmenu/events.js @@ -20,19 +20,22 @@ function rarityImgs(rarity, size = 13) { } function cardHTML(card, isFront = true) { - if (!isFront) return `?`; + if (!isFront) + return `?`; // image zuerst, dann icon als Fallback const imgFile = card?.image || card?.icon || null; - const img = imgFile ? `/images/cards/${imgFile}` : "/images/items/rueckseite.png"; + const img = imgFile + ? `/images/cards/${imgFile}` + : "/images/items/rueckseite.png"; return ` - ${card?.name || ''} - ${card?.attack != null ? `${card.attack}` : ""} - ${card?.defends != null ? `${card.defends}` : ""} - ${card?.cooldown!= null ? `${card.cooldown}` : ""} - ${card?.rarity ? `
${rarityImgs(card.rarity, 11)}
` : ""} -
${card?.name || ''}
+ ${card?.attack != null ? `${card.attack}` : ""} + ${card?.defends != null ? `${card.defends}` : ""} + ${card?.cooldown != null ? `${card.cooldown}` : ""} + ${card?.rarity ? `
${rarityImgs(card.rarity, 11)}
` : ""} +
${card?.name || ""}
`; } @@ -45,15 +48,20 @@ export async function loadEvents() { if (!document.querySelector('link[href="/css/events.css"]')) { const link = document.createElement("link"); - link.rel = "stylesheet"; + link.rel = "stylesheet"; link.href = "/css/events.css"; document.head.appendChild(link); } const events = [ - { id: 1, img: "/images/items/runenhaufen.png", label: "Booster Öffnen", type: "booster" }, - { id: 2, img: "/images/items/runenhaufen.png", label: "Textzeile 2" }, - { id: 3, img: "/images/items/runenhaufen.png", label: "Textzeile 3" }, + { + id: 1, + img: "/images/items/runenhaufen.png", + label: "Booster Öffnen", + type: "booster", + }, + { id: 2, img: "/images/items/1v1.png", label: "Textzeile 2" }, + { id: 3, img: "/images/items/2v2.png", label: "Textzeile 3" }, { id: 4, img: "/images/items/runenhaufen.png", label: "Textzeile 4" }, { id: 5, img: "/images/items/runenhaufen.png", label: "Textzeile 5" }, ]; @@ -72,18 +80,20 @@ export async function loadEvents() { body.innerHTML = `
- ${events.map(ev => { - const done = completedToday.includes(ev.id); - return ` -
+ ${events + .map((ev) => { + const done = completedToday.includes(ev.id); + return ` +
${ev.label} - ${done ? `
` : ''} + ${done ? `
` : ""}
${ev.label} - ${done ? `Bereits erledigt` : ''} + ${done ? `Bereits erledigt` : ""}
`; - }).join("")} + }) + .join("")}
@@ -95,12 +105,15 @@ export async function loadEvents() { Klicken zum Öffnen
- ${Array.from({length: 5}, (_, i) => ` + ${Array.from( + { length: 5 }, + (_, i) => `
?
-
`).join("")} +
`, + ).join("")} @@ -116,32 +129,32 @@ export async function loadEvents() { `; - const overlay = body.querySelector("#event-detail-overlay"); - const edpImg = body.querySelector("#edp-img"); - const edpTitle = body.querySelector("#edp-title"); - const edpBody = body.querySelector("#edp-body"); - const boosterUi = body.querySelector("#booster-ui"); + const overlay = body.querySelector("#event-detail-overlay"); + const edpImg = body.querySelector("#edp-img"); + const edpTitle = body.querySelector("#edp-title"); + const edpBody = body.querySelector("#edp-body"); + const boosterUi = body.querySelector("#booster-ui"); const eventsGrid = body.querySelector("#events-grid"); /* ── Event-Karten ── */ - body.querySelectorAll(".event-card").forEach(card => { + body.querySelectorAll(".event-card").forEach((card) => { card.addEventListener("click", () => { // Bereits erledigt → nicht anklickbar if (card.dataset.done === "true") return; if (card.dataset.type === "booster") { eventsGrid.style.display = "none"; - boosterUi.style.display = "flex"; + boosterUi.style.display = "flex"; resetBooster(); return; } const id = Number(card.dataset.eventId); - const ev = events.find(e => e.id === id); + const ev = events.find((e) => e.id === id); if (!ev) return; - edpImg.src = ev.img; - edpImg.alt = ev.label; + edpImg.src = ev.img; + edpImg.alt = ev.label; edpTitle.textContent = ev.label; - edpBody.textContent = "Inhalt folgt..."; + edpBody.textContent = "Inhalt folgt..."; overlay.classList.add("active"); }); }); @@ -155,16 +168,24 @@ export async function loadEvents() { body: JSON.stringify({ eventId }), }); // Karte visuell als erledigt markieren - const card = body.querySelector(`.event-card[data-event-id="${eventId}"]`); + const card = body.querySelector( + `.event-card[data-event-id="${eventId}"]`, + ); if (card) { card.dataset.done = "true"; card.classList.add("event-done"); const wrap = card.querySelector(".event-card-img-wrap"); if (wrap && !wrap.querySelector(".event-done-overlay")) { - wrap.insertAdjacentHTML("beforeend", `
`); + wrap.insertAdjacentHTML( + "beforeend", + `
`, + ); } if (!card.querySelector(".event-done-label")) { - card.insertAdjacentHTML("beforeend", `Bereits erledigt`); + card.insertAdjacentHTML( + "beforeend", + `Bereits erledigt`, + ); } } } catch (e) { @@ -172,8 +193,12 @@ export async function loadEvents() { } } - body.querySelector("#edp-close-btn").addEventListener("click", () => overlay.classList.remove("active")); - overlay.addEventListener("click", e => { if (e.target === overlay) overlay.classList.remove("active"); }); + body + .querySelector("#edp-close-btn") + .addEventListener("click", () => overlay.classList.remove("active")); + overlay.addEventListener("click", (e) => { + if (e.target === overlay) overlay.classList.remove("active"); + }); body.querySelector("#booster-back-btn").addEventListener("click", () => { // Gesperrt nur wenn Slot gerade läuft @@ -183,7 +208,7 @@ export async function loadEvents() { const boosterDone = boosterCard?.dataset.done === "true"; if (!allRevealed && !boosterDone) return; eventsGrid.style.display = ""; - boosterUi.style.display = "none"; + boosterUi.style.display = "none"; clearAllIntervals(); isSpinning = false; }); @@ -192,16 +217,16 @@ export async function loadEvents() { // ESC wird zentral in quickmenu.js behandelt (verhindert Listener-Stapelung) /* ── Booster Zustand ── */ - let allCards = []; - let isSpinning = false; - let allRevealed = false; // true sobald alle 5 Karten aufgedeckt + gespeichert - let spinIntervals = {}; // { index: intervalId } - let slotLocked = {}; // { index: true } → verhindert Überschreiben nach reveal + let allCards = []; + let isSpinning = false; + let allRevealed = false; // true sobald alle 5 Karten aufgedeckt + gespeichert + let spinIntervals = {}; // { index: intervalId } + let slotLocked = {}; // { index: true } → verhindert Überschreiben nach reveal function clearAllIntervals() { - Object.values(spinIntervals).forEach(id => clearInterval(id)); + Object.values(spinIntervals).forEach((id) => clearInterval(id)); spinIntervals = {}; - slotLocked = {}; + slotLocked = {}; } async function preloadCards() { @@ -217,19 +242,23 @@ export async function loadEvents() { function resetBooster() { clearAllIntervals(); - isSpinning = false; + isSpinning = false; allRevealed = false; for (let i = 0; i < 5; i++) { - const inner = body.querySelector(`#booster-slot-${i} .booster-slot-inner`); + const inner = body.querySelector( + `#booster-slot-${i} .booster-slot-inner`, + ); inner.innerHTML = `?`; - body.querySelector(`#booster-slot-${i}`).classList.remove("revealed", "spinning"); + body + .querySelector(`#booster-slot-${i}`) + .classList.remove("revealed", "spinning"); } const stapel = body.querySelector("#booster-stapel"); stapel.classList.remove("used"); stapel.style.opacity = "1"; - stapel.style.cursor = "pointer"; + stapel.style.cursor = "pointer"; body.querySelector("#booster-hint").textContent = "Klicken zum Öffnen"; preloadCards(); } @@ -237,7 +266,7 @@ export async function loadEvents() { /* ── Slot drehen – 350ms, damit man die Karten erkennt ── */ function startSpinSlot(index) { slotLocked[index] = false; - const slot = body.querySelector(`#booster-slot-${index}`); + const slot = body.querySelector(`#booster-slot-${index}`); const inner = slot.querySelector(".booster-slot-inner"); slot.classList.add("spinning"); @@ -252,13 +281,13 @@ export async function loadEvents() { /* ── Slot enthüllen – Sperre setzen BEVOR clearInterval ── */ function revealSlot(index, card) { - slotLocked[index] = true; // zuerst sperren + slotLocked[index] = true; // zuerst sperren clearInterval(spinIntervals[index]); // dann stoppen delete spinIntervals[index]; console.log(`[Booster] Slot ${index} enthüllt:`, card); - const slot = body.querySelector(`#booster-slot-${index}`); + const slot = body.querySelector(`#booster-slot-${index}`); const inner = slot.querySelector(".booster-slot-inner"); slot.classList.remove("spinning"); slot.classList.add("revealed"); @@ -283,17 +312,17 @@ export async function loadEvents() { const stapel = body.querySelector("#booster-stapel"); stapel.classList.add("used"); stapel.style.opacity = "0.35"; - stapel.style.cursor = "default"; + stapel.style.cursor = "default"; body.querySelector("#booster-hint").textContent = "Wird gezogen..."; // Zurück-Button während der Animation sperren const backBtn = body.querySelector("#booster-back-btn"); backBtn.style.opacity = "0.35"; - backBtn.style.cursor = "not-allowed"; + backBtn.style.cursor = "not-allowed"; let drawnCards = []; try { - const res = await fetch("/api/booster/open", { method: "POST" }); + const res = await fetch("/api/booster/open", { method: "POST" }); const text = await res.text(); console.log("[Booster] API Antwort raw:", text); const data = JSON.parse(text); @@ -312,32 +341,37 @@ export async function loadEvents() { setTimeout(() => revealSlot(i, drawnCards[i]), (i + 1) * 5000); } - setTimeout(async () => { - body.querySelector("#booster-hint").textContent = "Karten werden gespeichert..."; - isSpinning = false; + setTimeout( + async () => { + body.querySelector("#booster-hint").textContent = + "Karten werden gespeichert..."; + isSpinning = false; - // Karten in user_cards speichern - try { - const cardIds = drawnCards.map(c => c.id); - const saveRes = await fetch("/api/booster/save", { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ cardIds }), - }); - if (!saveRes.ok) throw new Error(saveRes.status); - } catch (e) { - console.error("Karten speichern fehlgeschlagen", e); - } + // Karten in user_cards speichern + try { + const cardIds = drawnCards.map((c) => c.id); + const saveRes = await fetch("/api/booster/save", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ cardIds }), + }); + if (!saveRes.ok) throw new Error(saveRes.status); + } catch (e) { + console.error("Karten speichern fehlgeschlagen", e); + } - // Booster-Daily als erledigt markieren (event_id = 1) - await markDailyComplete(1); + // Booster-Daily als erledigt markieren (event_id = 1) + await markDailyComplete(1); - allRevealed = true; - body.querySelector("#booster-hint").textContent = "Alle Karten erhalten! ✓"; - const backBtn = body.querySelector("#booster-back-btn"); - backBtn.style.opacity = "1"; - backBtn.style.cursor = "pointer"; - }, 5 * 5000 + 500); + allRevealed = true; + body.querySelector("#booster-hint").textContent = + "Alle Karten erhalten! ✓"; + const backBtn = body.querySelector("#booster-back-btn"); + backBtn.style.opacity = "1"; + backBtn.style.cursor = "pointer"; + }, + 5 * 5000 + 500, + ); }); preloadCards();