diff --git a/app.js b/app.js
index 552ed11..7a47c6a 100644
--- a/app.js
+++ b/app.js
@@ -30,6 +30,7 @@ const boosterRoutes = require("./routes/booster.route");
const pointsRoutes = require("./routes/points.route");
const combineRoutes = require("./routes/combine.route");
const bazaarRoutes = require("./routes/bazaar.route");
+const himmelstorRoutes = require("./routes/himmelstor.route");
const compression = require("compression");
@@ -406,6 +407,7 @@ app.use("/api", require("./routes/daily.route"));
app.use("/api/points", pointsRoutes);
app.use("/api", combineRoutes);
app.use("/api", bazaarRoutes);
+app.use("/himmelstor", himmelstorRoutes);
/* ========================
404 Handler
diff --git a/public/css/himmelstor.css b/public/css/himmelstor.css
new file mode 100644
index 0000000..bf4e89a
--- /dev/null
+++ b/public/css/himmelstor.css
@@ -0,0 +1,120 @@
+/* ================================
+ HIMMELSTOR UI
+ public/css/himmelstor.css
+================================ */
+
+#himmelstor-ui {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ padding: 32px 20px;
+ min-height: 100%;
+}
+
+.ht-title {
+ font-size: 28px;
+ font-weight: bold;
+ color: #c8a0ff;
+ text-shadow:
+ 0 0 8px rgba(155, 114, 207, 0.8),
+ 2px 2px 4px rgba(0, 0, 0, 0.9);
+ letter-spacing: 3px;
+ text-transform: uppercase;
+ margin-bottom: 6px;
+ font-family: "Palatino Linotype", "Book Antiqua", Palatino, serif;
+}
+
+.ht-subtitle {
+ color: #7a6090;
+ font-size: 13px;
+ margin: 0 0 36px 0;
+ font-style: italic;
+ letter-spacing: 1px;
+}
+
+/* ================================
+ MODE CARDS
+================================ */
+
+.ht-modes {
+ display: flex;
+ gap: 24px;
+ flex-wrap: wrap;
+ justify-content: center;
+}
+
+.ht-mode-card {
+ width: 160px;
+ background: linear-gradient(
+ 160deg,
+ rgba(25, 15, 40, 0.95) 0%,
+ rgba(10, 8, 20, 0.98) 100%
+ );
+ border: 2px solid #4a3a6b;
+ border-radius: 6px;
+ padding: 28px 16px 22px;
+ text-align: center;
+ cursor: pointer;
+ position: relative;
+ overflow: hidden;
+ box-shadow:
+ inset 0 1px 0 rgba(155, 114, 207, 0.15),
+ 0 4px 16px rgba(0, 0, 0, 0.6);
+ transition:
+ transform 0.15s ease,
+ border-color 0.15s ease,
+ box-shadow 0.15s ease;
+}
+
+/* Ornamental top line */
+.ht-mode-card::before {
+ content: "";
+ position: absolute;
+ top: 0;
+ left: 10%;
+ right: 10%;
+ height: 2px;
+ background: linear-gradient(
+ 90deg,
+ transparent,
+ #9b72cf,
+ transparent
+ );
+}
+
+.ht-mode-card:hover {
+ transform: translateY(-4px);
+ border-color: #9b72cf;
+ box-shadow:
+ inset 0 1px 0 rgba(155, 114, 207, 0.25),
+ 0 8px 24px rgba(0, 0, 0, 0.7),
+ 0 0 12px rgba(155, 114, 207, 0.25);
+}
+
+.ht-mode-card:active {
+ transform: translateY(-1px);
+}
+
+.ht-mode-icon {
+ font-size: 36px;
+ margin-bottom: 12px;
+ line-height: 1;
+ filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.8));
+}
+
+.ht-mode-label {
+ font-size: 22px;
+ font-weight: bold;
+ color: #c8a0ff;
+ text-shadow: 1px 1px 3px rgba(0, 0, 0, 0.9);
+ letter-spacing: 2px;
+ font-family: "Palatino Linotype", "Book Antiqua", Palatino, serif;
+ margin-bottom: 10px;
+}
+
+.ht-mode-desc {
+ font-size: 11px;
+ color: #6a5080;
+ line-height: 1.5;
+ font-style: italic;
+}
diff --git a/public/js/buildings/himmelstor.js b/public/js/buildings/himmelstor.js
new file mode 100644
index 0000000..d40d67e
--- /dev/null
+++ b/public/js/buildings/himmelstor.js
@@ -0,0 +1,382 @@
+/* ============================================================
+ public/js/buildings/himmelstor.js
+ Himmelstor – Tages- und Wochenherausforderung
+ Gleiche Struktur wie arena.js, aber Daily & Weekly
+============================================================ */
+
+export async function loadHimmelstor() {
+ const ui = document.querySelector(".building-ui");
+ if (!ui) return;
+
+ /* ── Decks laden ─────────────────────────────────────────── */
+ let decks = [];
+ try {
+ const res = await fetch("/api/decks");
+ if (res.ok) decks = await res.json();
+ } catch (e) { console.error("[Himmelstor] Decks:", e); }
+
+ const deckOptions = decks.length === 0
+ ? ``
+ : `` +
+ decks.filter(d => d.card_count > 0)
+ .map(d => ``)
+ .join("") +
+ (decks.some(d => d.card_count === 0)
+ ? decks.filter(d => d.card_count === 0)
+ .map(d => ``)
+ .join("")
+ : "");
+
+ ui.innerHTML = `
+
+
+
🌤️ Himmelstor
+
Wähle Deck und Herausforderung
+
+
+
+
+
+
☀️
+
Daily
+
Tagesherausforderung
+
+
+
+
+
+
+
🌙
+
Weekly
+
Wochenherausforderung
+
+
+
+
+
+
+ ${decks.length === 0
+ ? `
⚠️ Kein Deck vorhanden – gehe zur Burg → Kartendeck
`
+ : ""}
+
+
+
+
`;
+
+ injectHimmelstorStyles();
+ initHimmelstorModes();
+}
+
+/* ── Styles ──────────────────────────────────────────────── */
+function injectHimmelstorStyles() {
+ if (document.getElementById("ht-popup-styles")) return;
+ const style = document.createElement("style");
+ style.id = "ht-popup-styles";
+ style.textContent = `
+ @keyframes htFadeIn { from{opacity:0} to{opacity:1} }
+ @keyframes htScaleIn { from{transform:scale(0.94);opacity:0} to{transform:scale(1);opacity:1} }
+ @keyframes htPulse { 0%,100%{opacity:1} 50%{opacity:0.5} }
+
+ #himmelstor-ui { display:flex; flex-direction:column; height:100%; }
+
+ #himmelstor-mode-screen {
+ display:flex; flex-direction:column; align-items:center; padding:16px;
+ }
+
+ .ht-title {
+ font-family:"Cinzel",serif; font-size:18px; color:#f0d060;
+ letter-spacing:3px; text-align:center; margin-bottom:4px;
+ }
+ .ht-subtitle {
+ font-family:"Cinzel",serif; font-size:11px; color:#a08060;
+ margin:0 0 14px;
+ }
+
+ .ht-modes {
+ display:flex; gap:10px; justify-content:center;
+ flex-wrap:wrap; width:100%;
+ }
+
+ .ht-mode-wrap {
+ flex:1; min-width:120px; max-width:195px;
+ display:flex; flex-direction:column; gap:6px;
+ }
+
+ .ht-mode-card {
+ flex:1; min-width:120px; max-width:195px;
+ background:linear-gradient(180deg,#1a1a2e,#0f0f1a);
+ border:2px solid #4a3a6b; border-radius:12px;
+ padding:21px 12px; cursor:pointer; text-align:center;
+ transition:border-color .2s, transform .1s;
+ box-shadow: inset 0 1px 0 rgba(160,120,255,0.1), 0 4px 16px rgba(0,0,0,0.6);
+ }
+ .ht-mode-card:hover { border-color:#9b72cf; transform:translateY(-2px); }
+ .ht-mode-card.searching {
+ opacity:.6; pointer-events:none;
+ border-color:rgba(155,114,207,.5) !important;
+ }
+ .ht-mode-locked {
+ opacity:.45; cursor:not-allowed !important;
+ border-color:#2a1e40 !important;
+ }
+ .ht-mode-locked:hover { transform:none !important; border-color:#2a1e40 !important; }
+
+ .ht-mode-icon { font-size:36px; margin-bottom:9px; }
+ .ht-mode-label {
+ font-family:"Cinzel",serif; font-size:19px;
+ color:#c8a0ff; font-weight:bold;
+ }
+ .ht-mode-desc { font-size:15px; color:#6a5080; margin-top:6px; line-height:1.4; }
+
+ .ht-deck-select {
+ width:100%; background:#0f0f1a; border:1px solid #4a3a6b;
+ border-radius:6px; color:#e0d0ff; font-family:"Cinzel",serif;
+ font-size:15px; padding:8px 9px; cursor:pointer;
+ appearance:none; -webkit-appearance:none;
+ background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23806090'/%3E%3C/svg%3E");
+ background-repeat:no-repeat; background-position:right 6px center;
+ padding-right:28px;
+ }
+ .ht-deck-select:focus { outline:none; border-color:#9b72cf; }
+ .ht-deck-select option { background:#0f0f1a; color:#e0d0ff; }
+
+ .ht-no-deck-hint {
+ margin-top:10px; padding:8px 12px; border-radius:7px;
+ background:rgba(231,76,60,.1); border:1px solid rgba(231,76,60,.3);
+ color:#e07060; font-family:"Cinzel",serif; font-size:11px; text-align:center;
+ }
+ .ht-no-deck-hint strong { color:#c8a0ff; }
+
+ #ht-queue-status {
+ margin-top:12px; padding:10px 18px; border-radius:10px;
+ width:100%; box-sizing:border-box;
+ background:rgba(155,114,207,.08); border:1px solid rgba(155,114,207,.3);
+ color:#c8a0ff; font-family:"Cinzel",serif; font-size:12px;
+ letter-spacing:1px; text-align:center; animation:htPulse 2s ease-in-out infinite;
+ }
+ .ht-cancel {
+ display:inline-block; margin-top:6px; font-size:11px;
+ color:rgba(255,100,100,.8); cursor:pointer; text-decoration:underline;
+ animation:none;
+ }
+ .ht-cancel:hover { color:#e74c3c; }
+
+ /* Match-Found Overlay */
+ #ht-match-found-overlay {
+ position:fixed; inset:0; z-index:10000;
+ background:rgba(0,0,0,.9); display:flex; flex-direction:column;
+ align-items:center; justify-content:center; animation:htFadeIn .3s ease;
+ }
+ .ht-mfo-title {
+ font-family:"Cinzel",serif; font-size:36px; color:#c8a0ff;
+ text-shadow:0 0 30px rgba(155,114,207,.6);
+ letter-spacing:6px; margin-bottom:12px;
+ }
+ .ht-mfo-vs {
+ font-family:"Cinzel",serif; font-size:18px;
+ color:rgba(255,255,255,.75); letter-spacing:3px;
+ }
+ .ht-mfo-bar {
+ width:300px; height:4px; background:rgba(155,114,207,.2);
+ border-radius:2px; margin-top:24px; overflow:hidden;
+ }
+ .ht-mfo-bar-fill {
+ height:100%; background:#9b72cf; width:0%;
+ border-radius:2px; transition:width 1.5s ease;
+ }
+
+ /* Popup iframe */
+ #ht-backdrop {
+ position:fixed; inset:0; background:rgba(0,0,0,.82);
+ backdrop-filter:blur(5px); z-index:9998; animation:htFadeIn .25s ease;
+ }
+ #ht-popup {
+ position:fixed; inset:50px; z-index:9999; display:flex;
+ flex-direction:column; border-radius:14px; overflow:hidden;
+ box-shadow:0 0 0 1px rgba(155,114,207,.35),0 30px 90px rgba(0,0,0,.85);
+ animation:htScaleIn .28s cubic-bezier(.22,1,.36,1);
+ }
+ #ht-popup-titlebar {
+ display:flex; align-items:center; justify-content:space-between;
+ background:rgba(10,8,20,.95); border-bottom:1px solid rgba(155,114,207,.3);
+ padding:0 16px; height:42px; flex-shrink:0;
+ }
+ #ht-popup-titlebar .ht-ap-title {
+ font-family:"Cinzel",serif; font-size:13px; letter-spacing:4px;
+ color:rgba(200,160,255,.85); text-transform:uppercase;
+ }
+ #ht-popup-titlebar .ht-ap-url { font-size:11px; color:rgba(255,255,255,.22); }
+ #ht-popup iframe { flex:1; border:none; width:100%; display:block; }
+ `;
+ document.head.appendChild(style);
+}
+
+/* ── State ───────────────────────────────────────────────── */
+let htSelectedDeckId = null;
+
+/* ── Modus-Initialisierung ───────────────────────────────── */
+function initHimmelstorModes() {
+ /* Deck-Dropdown: Karte freischalten wenn Deck gewählt */
+ document.querySelectorAll(".ht-deck-select").forEach(select => {
+ select.addEventListener("change", () => {
+ const mode = select.dataset.mode;
+ const card = document.querySelector(`.ht-mode-card[data-mode="${mode}"]`);
+ if (!card) return;
+ if (select.value) {
+ card.classList.remove("ht-mode-locked");
+ htSelectedDeckId = Number(select.value);
+ } else {
+ card.classList.add("ht-mode-locked");
+ }
+ });
+ });
+
+ /* Modus-Karte klicken */
+ document.querySelectorAll(".ht-mode-card").forEach(card => {
+ card.addEventListener("click", () => {
+ if (card.classList.contains("ht-mode-locked")) return;
+ const mode = card.dataset.mode;
+ const select = document.querySelector(`.ht-deck-select[data-mode="${mode}"]`);
+ htSelectedDeckId = select ? Number(select.value) : null;
+ if (!htSelectedDeckId) return;
+ sessionStorage.setItem("selectedDeckId", htSelectedDeckId);
+ handleHtModeClick(card, mode);
+ });
+ });
+}
+
+/* ── Modus klicken ───────────────────────────────────────── */
+async function handleHtModeClick(card, mode) {
+ if (card.classList.contains("searching")) return;
+
+ let me;
+ try {
+ const res = await fetch("/arena/me");
+ if (!res.ok) throw new Error("Status " + res.status);
+ me = await res.json();
+ } catch {
+ showHtError("Spielerdaten konnten nicht geladen werden.");
+ return;
+ }
+
+ setHtCardSearching(card, mode, true);
+ showHtQueueStatus(mode);
+
+ const socket = window._socket;
+ if (!socket) { showHtError("Keine Verbindung zum Server."); return; }
+
+ socket.off("ht_match_found");
+ socket.off("ht_queue_status");
+
+ socket.on("ht_queue_status", data => {
+ if (data.status === "waiting") showHtQueueStatus(mode, data.poolSize);
+ else if (data.status === "left") { setHtCardSearching(card, mode, false); hideHtQueueStatus(); }
+ });
+
+ socket.once("ht_match_found", data => {
+ socket.off("ht_queue_status");
+ setHtCardSearching(card, mode, false);
+ hideHtQueueStatus();
+ showHtMatchFoundOverlay(me.name, data.opponent?.name || "Gegner", () => {
+ openHtPopup(
+ `/himmelstor/${mode}?match=${encodeURIComponent(data.matchId)}&slot=${encodeURIComponent(data.mySlot)}&deck=${encodeURIComponent(htSelectedDeckId || '')}&opponent=${encodeURIComponent(data.opponent?.name || '')}`,
+ data.opponent?.name || "Gegner", data.matchId
+ );
+ });
+ });
+
+ socket.emit("ht_join", {
+ id: me.id, name: me.name, level: me.level, mode,
+ });
+}
+
+/* ── UI Hilfsfunktionen ──────────────────────────────────── */
+const HT_LABELS = { daily: "Daily", weekly: "Weekly" };
+const HT_DESCS = { daily: "Tagesherausforderung", weekly: "Wochenherausforderung" };
+
+function setHtCardSearching(card, mode, searching) {
+ const label = card.querySelector(".ht-mode-label");
+ const desc = card.querySelector(".ht-mode-desc");
+ if (searching) {
+ card.classList.add("searching");
+ label.textContent = "⏳ Suche…";
+ desc.textContent = "Warte auf Gegner…";
+ } else {
+ card.classList.remove("searching");
+ label.textContent = HT_LABELS[mode] || mode;
+ desc.textContent = HT_DESCS[mode] || "";
+ }
+}
+
+function showHtQueueStatus(mode, poolSize) {
+ const box = document.getElementById("ht-queue-status");
+ if (!box) return;
+ const pool = poolSize ? ` · ${poolSize} im Pool` : "";
+ const label = mode === "daily" ? "Tagesherausforderung" : "Wochenherausforderung";
+ box.style.display = "block";
+ box.innerHTML = `⏳ Suche ${label}${pool}
+
Suche abbrechen`;
+ document.getElementById("ht-cancel-btn")?.addEventListener("click", () => {
+ cancelHtQueue(document.querySelector(`.ht-mode-card[data-mode="${mode}"]`), mode);
+ });
+}
+
+function hideHtQueueStatus() {
+ const box = document.getElementById("ht-queue-status");
+ if (box) box.style.display = "none";
+}
+
+function showHtError(msg) {
+ const box = document.getElementById("ht-queue-status");
+ if (!box) return;
+ box.style.cssText += ";display:block;animation:none;border-color:rgba(231,76,60,.5);color:#e74c3c;";
+ box.textContent = "❌ " + msg;
+ setTimeout(() => {
+ box.style.display = "none";
+ box.style.animation = "";
+ box.style.borderColor = "";
+ box.style.color = "";
+ }, 3000);
+}
+
+function cancelHtQueue(card, mode) {
+ const socket = window._socket;
+ if (socket) { socket.emit("ht_leave", { mode }); socket.off("ht_match_found"); socket.off("ht_queue_status"); }
+ if (card) setHtCardSearching(card, mode, false);
+ hideHtQueueStatus();
+}
+
+function showHtMatchFoundOverlay(myName, opponentName, onDone) {
+ if (document.getElementById("ht-match-found-overlay")) return;
+ const overlay = document.createElement("div");
+ overlay.id = "ht-match-found-overlay";
+ overlay.innerHTML = `
+ 🌤️ Herausforderung!
+ ${myName} vs ${opponentName}
+ `;
+ document.body.appendChild(overlay);
+ requestAnimationFrame(() => {
+ const b = document.getElementById("htMfBar");
+ if (b) b.style.width = "100%";
+ });
+ setTimeout(() => { overlay.remove(); onDone(); }, 1600);
+}
+
+function openHtPopup(src, opponentName, matchId) {
+ document.getElementById("ht-backdrop")?.remove();
+ document.getElementById("ht-popup")?.remove();
+ const backdrop = document.createElement("div"); backdrop.id = "ht-backdrop";
+ const popup = document.createElement("div"); popup.id = "ht-popup";
+ popup.innerHTML = `
+
+ `;
+ document.body.appendChild(backdrop);
+ document.body.appendChild(popup);
+}
diff --git a/public/js/map-ui.js b/public/js/map-ui.js
index 13cdcae..3fb4833 100644
--- a/public/js/map-ui.js
+++ b/public/js/map-ui.js
@@ -1,4 +1,5 @@
import { loadArena } from "./buildings/arena.js?v=4";
+import { loadHimmelstor } from "./buildings/himmelstor.js";
import { loadCharacterHouse } from "./buildings/character-house.js?v=2";
import { loadBlackmarket } from "./buildings/blackmarket.js?v=2";
import { loadMine } from "./buildings/mine.js?v=2";
@@ -48,7 +49,8 @@ document.getElementById("qm-overlay")?.addEventListener("mouseenter", () => {
});
const buildingModules = {
- 1: loadArena, // Arena – eigenes UI, Tabs ausblenden
+ 1: loadArena, // Arena – eigenes UI, Tabs ausblenden
+ 3: loadHimmelstor, // Himmelstor – eigenes UI, Tabs ausblenden
10: loadMine, // Mine – Tabs bleiben sichtbar
11: loadCharacterHouse, // Charakterhaus – eigenes UI, Tabs ausblenden
12: loadBlackmarket, // Schwarzmarkt – eigenes UI, Tabs ausblenden
diff --git a/routes/himmelstor.route.js b/routes/himmelstor.route.js
new file mode 100644
index 0000000..b58491a
--- /dev/null
+++ b/routes/himmelstor.route.js
@@ -0,0 +1,112 @@
+/* ============================================================
+ routes/himmelstor.route.js
+ GET /himmelstor/daily – Tagesherausforderung Spielfeld
+ GET /himmelstor/weekly – Wochenherausforderung Spielfeld
+============================================================ */
+
+const express = require("express");
+const router = express.Router();
+const db = require("../database/database");
+
+function requireLogin(req, res, next) {
+ if (!req.session?.user) return res.status(401).json({ error: "Nicht eingeloggt" });
+ next();
+}
+
+/* HP-Formel: 20 + (level-1)*2 */
+function calcAvatarHp(level) {
+ return 20 + (Math.max(1, Math.min(50, level || 1)) - 1) * 2;
+}
+
+async function getPlayerHp(userId) {
+ try {
+ const [[acc]] = await db.query("SELECT level FROM accounts WHERE id = ?", [userId]);
+ return calcAvatarHp(acc?.level ?? 1);
+ } catch {
+ return 20;
+ }
+}
+
+/* ── GET /himmelstor/daily ─────────────────────────────── */
+router.get("/daily", requireLogin, async (req, res) => {
+ const userId = req.session.user.id;
+ const { match: matchId, slot } = req.query;
+
+ if (!matchId) {
+ return res.render("1v1-battlefield", {
+ title: "☀️ Daily Herausforderung",
+ matchId: null,
+ mySlot: "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 = await getPlayerHp(userId);
+ const isP1 = slot === "player1";
+
+ res.render("1v1-battlefield", {
+ title: "☀️ Daily Herausforderung",
+ matchId,
+ mySlot: slot || "player1",
+ player1: isP1 ? (me?.ingame_name || "Du") : "Gegner",
+ player2: isP1 ? "Gegner" : (me?.ingame_name || "Du"),
+ player1hp: isP1 ? hp : 20,
+ player1mana: 3,
+ player2hp: isP1 ? 20 : hp,
+ player2mana: 3,
+ });
+ } catch (err) {
+ console.error("[Himmelstor /daily]", err);
+ res.status(500).send("Fehler beim Laden des Spielfelds.");
+ }
+});
+
+/* ── GET /himmelstor/weekly ────────────────────────────── */
+router.get("/weekly", requireLogin, async (req, res) => {
+ const userId = req.session.user.id;
+ const { match: matchId, slot } = req.query;
+
+ if (!matchId) {
+ return res.render("1v1-battlefield", {
+ title: "🌙 Weekly Herausforderung",
+ matchId: null,
+ mySlot: "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 = await getPlayerHp(userId);
+ const isP1 = slot === "player1";
+
+ res.render("1v1-battlefield", {
+ title: "🌙 Weekly Herausforderung",
+ matchId,
+ mySlot: slot || "player1",
+ player1: isP1 ? (me?.ingame_name || "Du") : "Gegner",
+ player2: isP1 ? "Gegner" : (me?.ingame_name || "Du"),
+ player1hp: isP1 ? hp : 20,
+ player1mana: 3,
+ player2hp: isP1 ? 20 : hp,
+ player2mana: 3,
+ });
+ } catch (err) {
+ console.error("[Himmelstor /weekly]", err);
+ res.status(500).send("Fehler beim Laden des Spielfelds.");
+ }
+});
+
+module.exports = router;
diff --git a/views/launcher.ejs b/views/launcher.ejs
index b065a51..b714e5c 100644
--- a/views/launcher.ejs
+++ b/views/launcher.ejs
@@ -93,9 +93,13 @@
+
-
+
@@ -656,12 +660,16 @@
-
+
0
-
+
0
@@ -669,12 +677,16 @@
@@ -796,15 +808,25 @@
-
+
@@ -898,7 +920,9 @@
💠 Gems kaufen
✕
- Unterstütze das Spiel und erhalte wertvolle Gems!
+
+ Unterstütze das Spiel und erhalte wertvolle Gems!
+