270 lines
8.5 KiB
JavaScript
270 lines
8.5 KiB
JavaScript
import { loadCharacterHouse } from "./buildings/character-house.js";
|
||
import { loadBlackmarket } from "./buildings/blackmarket.js";
|
||
import { loadMine } from "./buildings/mine.js";
|
||
const popup = document.getElementById("building-popup");
|
||
const title = document.getElementById("popup-title");
|
||
const tooltip = document.getElementById("map-tooltip");
|
||
|
||
const tooltipCache = {};
|
||
|
||
const buildingModules = {
|
||
11: loadCharacterHouse, // Tabs ausblenden, eigenes UI
|
||
12: loadBlackmarket, // Tabs ausblenden, eigenes UI
|
||
10: loadMine, // Tabs bleiben sichtbar, nur Aktionen-Tab befüllen
|
||
};
|
||
|
||
// Gebäude die ihre eigenen Tabs behalten sollen
|
||
const keepTabsVisible = new Set([10]);
|
||
|
||
/* ================================
|
||
Tabs zurücksetzen
|
||
================================ */
|
||
|
||
function resetTabs() {
|
||
document
|
||
.querySelectorAll(".tab")
|
||
.forEach((t) => t.classList.remove("active"));
|
||
document
|
||
.querySelectorAll(".tab-content")
|
||
.forEach((c) => c.classList.remove("active"));
|
||
|
||
const firstTab = document.querySelector(".tab");
|
||
const firstContent = document.querySelector(".tab-content");
|
||
|
||
if (firstTab) firstTab.classList.add("active");
|
||
if (firstContent) firstContent.classList.add("active");
|
||
}
|
||
|
||
/* ================================
|
||
Gebäude Popup öffnen (Funktion)
|
||
================================ */
|
||
|
||
async function openBuildingPopup(url) {
|
||
title.innerText = "Lädt...";
|
||
popup.style.left = "50%";
|
||
popup.style.top = "50%";
|
||
popup.classList.add("active");
|
||
resetTabs();
|
||
|
||
try {
|
||
const res = await fetch("/api" + url);
|
||
if (!res.ok) throw new Error("API Fehler");
|
||
const data = await res.json();
|
||
|
||
title.innerText = data.name;
|
||
|
||
const infoTab = document.getElementById("tab-info");
|
||
const tabs = document.querySelector(".popup-tabs");
|
||
|
||
infoTab.innerHTML = `
|
||
<div class="popup-info-title">${data.name}</div>
|
||
<div class="popup-stat-row"><span class="popup-stat-key">Level</span><span class="popup-stat-val">${data.level}</span></div>
|
||
<div class="popup-stat-row"><span class="popup-stat-key">Punkte</span><span class="popup-stat-val">${data.points} / ${data.nextLevelPoints}</span></div>
|
||
<p class="popup-desc" style="color:#cccccc !important;font-size:16px;line-height:1.8;">${data.description}</p>
|
||
<div class="popup-xp-wrap">
|
||
</div>
|
||
<div class="popup-divider">✦ · ✦ · ✦</div>
|
||
`;
|
||
|
||
tabs.style.display = "flex";
|
||
|
||
const buildingType = Number(data.type);
|
||
if (buildingModules[buildingType]) {
|
||
if (keepTabsVisible.has(buildingType)) {
|
||
tabs.style.display = "flex";
|
||
} else {
|
||
tabs.style.display = "none";
|
||
infoTab.innerHTML = `<div class="building-ui"></div>`;
|
||
}
|
||
buildingModules[buildingType](url.split("/").pop());
|
||
}
|
||
|
||
// Punkte-Check: Upgrade nur möglich wenn genug Punkte vorhanden
|
||
const hasEnoughPoints =
|
||
data.upgradeRequiredPoints === null ||
|
||
data.points >= data.upgradeRequiredPoints;
|
||
|
||
const canUpgrade = data.upgradeWood !== null && hasEnoughPoints;
|
||
|
||
const pointsPct = data.upgradeRequiredPoints
|
||
? Math.min((data.points / data.upgradeRequiredPoints) * 100, 100)
|
||
: 100;
|
||
|
||
const barColor = hasEnoughPoints ? "#88ff88" : "#e8a020";
|
||
|
||
document.getElementById("tab-upgrade").innerHTML = `
|
||
<div class="popup-info-title">Upgrade</div>
|
||
<div class="popup-stat-row"><span class="popup-stat-key">Holz</span><span class="popup-stat-val">${data.upgradeWood ?? "–"}</span></div>
|
||
<div class="popup-stat-row"><span class="popup-stat-key">Stein</span><span class="popup-stat-val">${data.upgradeStone ?? "–"}</span></div>
|
||
<div class="popup-stat-row"><span class="popup-stat-key">Gold</span><span class="popup-stat-val">${data.upgradeGold ?? "–"}</span></div>
|
||
|
||
<div class="popup-xp-wrap" style="margin-top:14px;">
|
||
<div class="popup-xp-label" style="display:flex;justify-content:space-between;">
|
||
<span>Punkte für Upgrade</span>
|
||
<span style="color:${barColor}">${data.points} / ${data.upgradeRequiredPoints ?? "–"}</span>
|
||
</div>
|
||
<div class="popup-xp-track">
|
||
<div class="popup-xp-fill" style="width:${pointsPct}%;background:${barColor};">
|
||
<div class="popup-xp-shimmer"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<button class="popup-upgrade-btn" id="upgrade-btn" data-building="${url.split("/").pop()}"
|
||
${!canUpgrade ? 'disabled style="opacity:0.4;cursor:not-allowed;"' : ""}>
|
||
⚒ UPGRADE STARTEN ⚒
|
||
</button>
|
||
${!hasEnoughPoints ? `<p style="color:#ff6666;font-size:12px;margin-top:8px;text-align:center;">Noch ${data.upgradeRequiredPoints - data.points} Punkte bis zum Upgrade.</p>` : ""}
|
||
`;
|
||
} catch (error) {
|
||
console.error("Gebäude konnte nicht geladen werden:", error);
|
||
}
|
||
}
|
||
|
||
/* ================================
|
||
Gebäude Popup per Klick öffnen
|
||
================================ */
|
||
|
||
document.querySelectorAll(".building").forEach((building) => {
|
||
building.addEventListener("click", async (e) => {
|
||
e.preventDefault();
|
||
const url = building.getAttribute("href");
|
||
await openBuildingPopup(url);
|
||
});
|
||
});
|
||
|
||
/* ================================
|
||
Upgrade Button
|
||
================================ */
|
||
|
||
document.addEventListener("click", async (e) => {
|
||
const btn = e.target.closest("#upgrade-btn");
|
||
if (!btn || btn.disabled) return;
|
||
|
||
const buildingId = btn.dataset.building;
|
||
btn.disabled = true;
|
||
btn.textContent = "Wird durchgeführt...";
|
||
|
||
try {
|
||
const res = await fetch("/api/building/" + buildingId + "/upgrade", {
|
||
method: "POST",
|
||
});
|
||
const data = await res.json();
|
||
|
||
if (!res.ok || data.error) {
|
||
window.showNotification(
|
||
data.error || "Upgrade fehlgeschlagen.",
|
||
"Upgrade",
|
||
"⚒️",
|
||
);
|
||
btn.disabled = false;
|
||
btn.textContent = "⚒ UPGRADE STARTEN ⚒";
|
||
return;
|
||
}
|
||
|
||
window.showNotification(
|
||
`Upgrade erfolgreich!\nNeues Level: ${data.newLevel}\n\nKosten: ${data.cost.wood} Holz, ${data.cost.stone} Stein, ${data.cost.gold} Gold`,
|
||
"Upgrade",
|
||
"⚒️",
|
||
);
|
||
|
||
// Popup mit frischen Daten neu laden
|
||
await openBuildingPopup("/building/" + buildingId);
|
||
|
||
// HUD aktualisieren
|
||
import("/js/hud.js").then(({ loadHud }) => loadHud());
|
||
} catch (err) {
|
||
console.error("Upgrade Fehler:", err);
|
||
window.showNotification(
|
||
"Fehler beim Upgrade. Bitte erneut versuchen.",
|
||
"Fehler",
|
||
"⚠️",
|
||
);
|
||
btn.disabled = false;
|
||
btn.textContent = "⚒ UPGRADE STARTEN ⚒";
|
||
}
|
||
});
|
||
|
||
/* ================================
|
||
Tabs wechseln
|
||
================================ */
|
||
|
||
document.querySelectorAll(".tab").forEach((tab) => {
|
||
tab.addEventListener("click", () => {
|
||
document
|
||
.querySelectorAll(".tab")
|
||
.forEach((t) => t.classList.remove("active"));
|
||
tab.classList.add("active");
|
||
|
||
document
|
||
.querySelectorAll(".tab-content")
|
||
.forEach((c) => c.classList.remove("active"));
|
||
|
||
document.getElementById("tab-" + tab.dataset.tab).classList.add("active");
|
||
});
|
||
});
|
||
|
||
/* ================================
|
||
Popup schließen
|
||
================================ */
|
||
|
||
document.querySelector(".popup-close").onclick = () => {
|
||
popup.classList.remove("active");
|
||
};
|
||
|
||
/* ================================
|
||
Tooltip
|
||
================================ */
|
||
|
||
document.querySelectorAll(".building").forEach((building) => {
|
||
building.addEventListener("mouseenter", async (e) => {
|
||
try {
|
||
const id = building.dataset.id;
|
||
|
||
if (!tooltipCache[id]) {
|
||
const res = await fetch("/api/building/" + id);
|
||
|
||
if (!res.ok) throw new Error("API Fehler");
|
||
|
||
tooltipCache[id] = await res.json();
|
||
}
|
||
|
||
const data = tooltipCache[id];
|
||
|
||
tooltip.innerHTML = `
|
||
<strong>${data.name}</strong><br>
|
||
Level ${data.level}<br>
|
||
Punkte ${data.points}/${data.nextLevelPoints}<br>
|
||
<hr>
|
||
Upgrade Kosten:<br>
|
||
${data.upgradeCost}
|
||
`;
|
||
|
||
tooltip.style.display = "block";
|
||
} catch (err) {
|
||
console.error("Tooltip Fehler:", err);
|
||
}
|
||
});
|
||
|
||
building.addEventListener("mousemove", (e) => {
|
||
// Tooltip erst rendern lassen damit offsetWidth korrekt ist
|
||
const tw = tooltip.offsetWidth;
|
||
const th = tooltip.offsetHeight;
|
||
|
||
let x = e.clientX + 15;
|
||
let y = e.clientY + 15;
|
||
|
||
// Rechter Rand – Tooltip links vom Cursor anzeigen
|
||
if (x + tw > window.innerWidth - 10) x = e.clientX - tw - 10;
|
||
// Unterer Rand – Tooltip über dem Cursor anzeigen
|
||
if (y + th > window.innerHeight - 10) y = e.clientY - th - 10;
|
||
|
||
tooltip.style.left = x + "px";
|
||
tooltip.style.top = y + "px";
|
||
});
|
||
|
||
building.addEventListener("mouseleave", () => {
|
||
tooltip.style.display = "none";
|
||
});
|
||
});
|