/* ============================================================ public/js/gaststaette/glucksspiel.js Glücksspiel-Tab in der Gaststätte – Karten nach Fraktion anzeigen (wie Kartendeck) – Karten gleicher ID ins Kombinier-Feld legen – "Kombinieren"-Button ============================================================ */ const CARDS_PER_PAGE = 18; const RARITY_CRYSTALS = { 1: "roter-cristal.png", 2: "blauer-cristal.png", 3: "gelber-cristal.png", 4: "gruener-cristal.png", 5: "oranger-cristal.png", 6: "violet-cristal.png", 7: "pinker-cristal.png", }; function rarityImgs(rarity, size = 13) { const file = RARITY_CRYSTALS[String(rarity)]; if (!file) return ""; const count = parseInt(rarity) || 0; const img = `Stufe ${rarity}`; return img.repeat(count); } function gsRangeIcon() { return ``; } function gsRaceIcon() { return ``; } // State let gs_groupId = null; let gs_page = 1; let gs_cards = []; let gs_combineId = null; let gs_combineCards = []; let gs_initialized = false; let gs_tavernLevel = 1; let gs_required = 10; // Karten für 100% function getRequired(tavernLevel) { if (tavernLevel < 5) return 10; if (tavernLevel < 10) return 8; if (tavernLevel < 15) return 6; if (tavernLevel < 20) return 5; return 3; } function getChance(amount, required) { return Math.min(Math.round((amount / required) * 100), 100); } /* ══════════════════════════════════════════════ INIT ══════════════════════════════════════════════ */ export async function loadGlucksspiel() { const container = document.getElementById("gs-tab1"); if (!container) return; // CSS einmalig laden if (!document.querySelector('link[href="/css/glucksspiel.css"]')) { const link = document.createElement("link"); link.rel = "stylesheet"; link.href = "/css/glucksspiel.css"; document.head.appendChild(link); } // Nur beim ersten Aufruf rendern if (gs_initialized) return; gs_initialized = true; container.innerHTML = renderShell(); attachCombineEvents(); try { // Gaststätte-Level und benötigte Karten laden const infoRes = await fetch("/api/cards/combine-info"); if (infoRes.ok) { const info = await infoRes.json(); gs_tavernLevel = info.tavernLevel; gs_required = info.required; } const res = await fetch("/api/card-groups"); if (!res.ok) throw new Error(); const groups = await res.json(); renderTabs(groups); if (groups.length) { gs_groupId = groups[0].id; await loadCards(); } } catch { container.innerHTML = `

Fehler beim Laden.

`; } } /* ══════════════════════════════════════════════ SHELL ══════════════════════════════════════════════ */ function renderShell() { return `
Meine Karten
Lade Karten...
Kombinieren
Klicke auf eine Karte links um sie hier zu platzieren.
Nur Karten gleicher Art können kombiniert werden.
`; } /* ══════════════════════════════════════════════ FRAKTIONS-TABS ══════════════════════════════════════════════ */ function renderTabs(groups) { const container = document.getElementById("gs-faction-tabs"); if (!container) return; container.innerHTML = groups .map((g, i) => { const color = g.color || "#6b4b2a"; return ` `; }) .join(""); container.querySelectorAll(".gs-tab").forEach((btn) => { btn.addEventListener("click", async () => { const color = btn.style.borderColor; container.querySelectorAll(".gs-tab").forEach((b) => { b.classList.remove("gs-tab-active"); b.style.background = ""; }); btn.classList.add("gs-tab-active"); btn.style.background = `${color}33`; gs_groupId = parseInt(btn.dataset.group); gs_page = 1; await loadCards(); }); }); } /* ══════════════════════════════════════════════ KARTEN LADEN ══════════════════════════════════════════════ */ async function loadCards() { const grid = document.getElementById("gs-grid"); const pagination = document.getElementById("gs-pagination"); if (!grid) return; grid.innerHTML = `
Lade Karten...
`; if (pagination) pagination.innerHTML = ""; try { const res = await fetch( `/api/user-cards?group_id=${gs_groupId}&page=${gs_page}&limit=${CARDS_PER_PAGE}` ); if (!res.ok) throw new Error(); const data = await res.json(); gs_cards = data.cards || []; renderGrid(grid, gs_cards); renderPagination(pagination, data.totalPages, data.total); } catch { grid.innerHTML = `
Keine Karten gefunden.
`; } } /* ══════════════════════════════════════════════ KARTEN-GRID RENDERN ══════════════════════════════════════════════ */ function renderGrid(grid, cards) { if (!cards || !cards.length) { grid.innerHTML = `
Keine Karten in dieser Gruppe.
`; return; } grid.innerHTML = cards.map((c) => { // Karte deaktivieren wenn sie nicht zur aktuellen Kombination passt const disabled = gs_combineId !== null && c.card_id !== gs_combineId; // Anzahl bereits im Kombinier-Feld const inField = gs_combineCards.filter(x => x.card_id === c.card_id).length; const available = c.amount - inField; return `
${c.name} ${c.attack != null ? `${c.attack}` : ""} ${c.defends != null ? `${c.defends}` : ""} ${c.cooldown != null ? `${c.cooldown}` : ""} ${c.rarity ? `
${rarityImgs(c.rarity, 12)}
` : ""} ${(c.range != null || c.race != null) ? `
${c.range != null ? `${gsRangeIcon()} ${c.range}` : ""} ${c.race != null ? `${gsRaceIcon()} ${c.race}` : ""}
` : ""}
`; }).join(""); grid.querySelectorAll(".gs-card:not(.gs-card-disabled)").forEach((el) => { el.addEventListener("click", () => { const card = cards.find((c) => c.card_id === parseInt(el.dataset.cardId)); if (!card) return; const inField = gs_combineCards.filter(x => x.card_id === card.card_id).length; if (inField >= card.amount) { showToast("Keine weiteren Exemplare verfügbar."); return; } addToField(card); }); }); } /* ══════════════════════════════════════════════ KARTE ZUM KOMBINIER-FELD HINZUFÜGEN ══════════════════════════════════════════════ */ function addToField(card) { gs_combineId = card.card_id; gs_combineCards.push({ ...card }); renderCombineField(); renderGrid(document.getElementById("gs-grid"), gs_cards); } /* ══════════════════════════════════════════════ KARTE AUS FELD ENTFERNEN ══════════════════════════════════════════════ */ function removeFromField(index) { gs_combineCards.splice(index, 1); if (gs_combineCards.length === 0) gs_combineId = null; renderCombineField(); renderGrid(document.getElementById("gs-grid"), gs_cards); } /* ══════════════════════════════════════════════ KOMBINIER-FELD RENDERN ══════════════════════════════════════════════ */ function renderCombineField() { const grid = document.getElementById("gs-combine-grid"); const hint = document.getElementById("gs-combine-hint"); const count = document.getElementById("gs-combine-count"); const btn = document.getElementById("gs-combine-btn"); if (!grid) return; if (!gs_combineCards.length) { grid.innerHTML = ""; hint.style.display = "block"; count.textContent = ""; btn.disabled = true; return; } hint.style.display = "none"; const chance = getChance(gs_combineCards.length, gs_required); const chanceColor = chance >= 100 ? "#44ff44" : chance >= 60 ? "#f0d060" : "#ff6644"; // Karten als gestapelter Stapel – jede Karte leicht versetzt const offset = Math.min(6, 40 / gs_combineCards.length); // max 6px versatz const stackHeight = offset * (gs_combineCards.length - 1); // extra höhe für stapel const stackCards = gs_combineCards.map((c, i) => `
${c.name} ${c.attack != null ? `${c.attack}` : ""} ${c.defends != null ? `${c.defends}` : ""} ${c.cooldown != null ? `${c.cooldown}` : ""} ${c.rarity ? `
${rarityImgs(c.rarity, 12)}
` : ""} ${(c.range != null || c.race != null) ? `
${c.range != null ? `${gsRangeIcon()} ${c.range}` : ""} ${c.race != null ? `${gsRaceIcon()} ${c.race}` : ""}
` : ""}
`).join(""); grid.innerHTML = `
${stackCards}
`; // Klick auf Stapel → oberste Karte entfernen grid.querySelector(".gs-card-stack").addEventListener("click", () => { removeFromField(gs_combineCards.length - 1); }); count.innerHTML = `
${gs_combineCards.length} Karte${gs_combineCards.length !== 1 ? "n" : ""} im Stapel ${chance}% Erfolgschance
${gs_required} Karten = 100% (Gaststätte Lv.${gs_tavernLevel})
`; btn.disabled = gs_combineCards.length < 2; } /* ══════════════════════════════════════════════ KOMBINIEREN-BUTTON ══════════════════════════════════════════════ */ function attachCombineEvents() { // Wird nach renderShell aufgerufen setTimeout(() => { const btn = document.getElementById("gs-combine-btn"); if (!btn) return; btn.addEventListener("click", async () => { if (gs_combineCards.length < 2) return; btn.disabled = true; btn.textContent = "Kombiniere..."; try { const res = await fetch("/api/cards/combine", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ card_id: gs_combineId, amount: gs_combineCards.length, }), }); const data = await res.json(); if (!res.ok) { showToast(data.error || "Kombinieren fehlgeschlagen."); btn.disabled = false; btn.textContent = "Kombinieren"; return; } if (!data.success) { // Misserfolg – Karten sind weg showToast(`❌ Misserfolg! (${data.chance}% Chance) – Karten verbraucht.`); gs_combineCards = []; gs_combineId = null; renderCombineField(); await loadCards(); } else { // Erfolg – neue Karte zeigen showToast(`✅ Erfolg! Du erhältst: ${data.reward.name} (Rarity ${data.reward.rarity})`); gs_combineCards = []; gs_combineId = null; gs_initialized = false; renderCombineField(); await loadCards(); } } catch { showToast("Verbindungsfehler."); btn.disabled = false; } finally { btn.textContent = "Kombinieren"; } }); }, 50); } /* ══════════════════════════════════════════════ PAGINATION ══════════════════════════════════════════════ */ function renderPagination(pagination, totalPages, total) { if (!pagination || !totalPages || totalPages <= 1) return; pagination.innerHTML = ` ${Array.from({ length: totalPages }, (_, i) => i + 1) .map((p) => ``) .join("")} ${total} Karten`; pagination.querySelector("#gs-prev")?.addEventListener("click", async () => { if (gs_page > 1) { gs_page--; await loadCards(); } }); pagination.querySelector("#gs-next")?.addEventListener("click", async () => { if (gs_page < totalPages) { gs_page++; await loadCards(); } }); pagination.querySelectorAll("[data-page]").forEach((btn) => { btn.addEventListener("click", async () => { gs_page = parseInt(btn.dataset.page); await loadCards(); }); }); } /* ══════════════════════════════════════════════ TOAST ══════════════════════════════════════════════ */ function showToast(msg) { const existing = document.querySelector(".gs-toast"); if (existing) existing.remove(); const t = document.createElement("div"); t.className = "gs-toast"; t.textContent = msg; t.style.cssText = ` position:fixed;bottom:80px;left:50%;transform:translateX(-50%); background:linear-gradient(#4a2808,#2a1004);border:2px solid #8b6a3c; border-radius:8px;color:#f0d9a6;font-family:"Cinzel",serif;font-size:13px; padding:10px 22px;z-index:9999;pointer-events:none;`; document.body.appendChild(t); setTimeout(() => t.remove(), 2800); }