dok/views/launcher.ejs
2026-03-16 13:30:25 +00:00

585 lines
18 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8" />
<title>Dynasty of Knights</title>
<link
rel="icon"
href="/images/favicon/dok_favicon_32px.ico"
type="image/x-icon"
/>
<link rel="stylesheet" href="/css/launcher.css" />
<link rel="stylesheet" href="/css/global.css" />
<link rel="stylesheet" href="/css/building.css" />
<link rel="stylesheet" href="/css/quickmenu.css" />
<link rel="stylesheet" href="/css/mine.css" />
<style>
body {
margin: 0;
height: 100vh;
background: #000;
display: flex;
justify-content: center;
align-items: center;
font-family: sans-serif;
color: white;
}
.panel {
background: rgba(0, 0, 0, 0.6);
padding: 40px;
border-radius: 10px;
text-align: center;
width: 400px;
}
/* ── Music Control ── */
#music-control {
position: fixed;
bottom: 16px;
right: 16px;
z-index: 9999;
display: flex;
align-items: center;
gap: 8px;
background: rgba(10, 5, 0, 0.85);
border: 1px solid #c8960c;
border-radius: 8px;
padding: 6px 10px;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.6);
}
#music-mute-btn {
background: none;
border: none;
cursor: pointer;
font-size: 20px;
line-height: 1;
padding: 0;
color: #f0d080;
transition: transform 0.15s;
}
#music-mute-btn:hover {
transform: scale(1.2);
}
#music-volume {
-webkit-appearance: none;
appearance: none;
width: 80px;
height: 4px;
background: #3a2000;
border-radius: 2px;
outline: none;
cursor: pointer;
}
#music-volume::-webkit-slider-thumb {
-webkit-appearance: none;
width: 12px;
height: 12px;
border-radius: 50%;
background: #c8960c;
cursor: pointer;
}
</style>
</head>
<body>
<div class="worldmap">
<img src="/images/dok_bg.png" class="map-image" />
<svg
viewBox="0 0 2037 1018"
width="2037"
height="1018"
class="map-overlay"
>
<!-- 1 -->
<a href="/building/1" class="building" data-id="1">
<title></title>
<polygon
class="area"
points="276,185 387,192 379,382 287,365 284,364"
/>
</a>
<!-- 2 -->
<a href="/building/2" class="building" data-id="2">
<title></title>
<polygon
class="area"
points="777,365 865,238 969,263 1039,347 1071,419 1095,531 925,479 776,497"
/>
</a>
<!-- 3 -->
<a href="/building/3" class="building" data-id="3">
<title></title>
<polygon
class="area"
points="1239,261 1271,234 1300,262 1301,399 1240,404"
/>
</a>
<!-- 4 -->
<a href="/building/4" class="building" data-id="4">
<title></title>
<polygon
class="area"
points="1679,404 1679,270 1696,258 1728,178 1756,175 1780,211 1803,292 1804,362 1716,417"
/>
</a>
<!-- 5 -->
<a href="/building/5" class="building" data-id="5">
<title></title>
<polygon
class="area"
points="388,597 387,531 445,470 559,453 580,474 609,483 618,510 612,521 607,606"
/>
</a>
<!-- 6 -->
<a href="/building/6" class="building" data-id="6">
<title></title>
<polygon
class="area"
points="350,721 286,719 245,709 242,698 198,687 195,602 246,614 270,548 320,555 367,610"
/>
</a>
<!-- 7 -->
<a href="/building/7" class="building" data-id="7">
<title></title>
<polygon
class="area"
points="450,884 371,915 299,885 294,816 380,812 382,768 410,755 546,740 564,769 557,787 534,874"
/>
</a>
<!-- 8 -->
<a href="/building/8" class="building" data-id="8">
<title></title>
<polygon
class="area"
points="794,853 828,778 1023,752 1094,760 1171,784 1257,826 1272,869 1242,913 1161,943 1075,964 946,948 836,904"
/>
</a>
<!-- 9 -->
<a href="/building/9" class="building" data-id="9">
<title></title>
<polygon
class="area"
points="1201,746 1204,669 1245,564 1326,565 1377,664 1373,752 1297,763"
/>
</a>
<!-- 10 -->
<a href="/building/10" class="building" data-id="10">
<title></title>
<polygon
class="area"
points="1773,599 1775,573 1804,539 1830,508 1862,508 1881,482 1915,481 1933,509 1929,596 1882,612"
/>
</a>
<!-- 11 -->
<a href="/building/11" class="building" data-id="11">
<title></title>
<polygon
class="area"
points="1455,655 1464,442 1481,443 1503,425 1573,416 1614,451 1617,534 1634,541 1637,609 1521,652"
/>
</a>
<!-- 12 -->
<a href="/building/12" class="building" data-id="12">
<title></title>
<polygon
class="area"
points="1455,883 1455,837 1442,835 1460,792 1443,760 1459,743 1574,762 1660,754 1671,731 1729,731 1722,794 1714,906 1687,928 1509,902"
/>
</a>
<!-- 13 -->
<a href="/building/13" class="building" data-id="13">
<title></title>
<polygon
class="area"
points="694,714 695,656 734,605 754,600 767,534 775,600 798,597 829,640 827,726 774,733"
/>
</a>
</svg>
</div>
<div id="building-popup" class="building-popup">
<div class="popup-header">
<span id="popup-title">Gebäude</span>
<span class="popup-close">✕</span>
</div>
<div class="popup-tabs">
<button class="tab active" data-tab="info">Info</button>
<button class="tab" data-tab="actions">Aktionen</button>
<button class="tab" data-tab="upgrade">Upgrade</button>
<button class="tab" data-tab="history">Geschichte</button>
</div>
<div class="popup-content">
<div class="tab-content active" id="tab-info"></div>
<div class="tab-content" id="tab-actions"></div>
<div class="tab-content" id="tab-upgrade"></div>
<div class="tab-content" id="tab-history"></div>
</div>
</div>
<div id="online-users">
<div class="online-header">Spieler Online</div>
<div id="online-list"></div>
</div>
<div id="game-chat">
<div class="chat-header" id="chat-title">Globalchat</div>
<div class="chat-channels">
<button data-channel="global" class="active">Global</button>
<button data-channel="guild">Gilde</button>
<button data-channel="private">Privat</button>
</div>
<textarea id="chat-messages" readonly></textarea>
<div class="chat-input">
<input id="chat-text" placeholder="Nachricht..." />
<button id="chat-send">Senden</button>
</div>
</div>
<div id="map-tooltip"></div>
<!-- ================================
Quick Menu Toggle
================================ -->
<button id="quickmenu-toggle" title="Menü ein/ausblenden">◄</button>
<!-- ================================
Quick Menu Panel
================================ -->
<div id="quickmenu-panel">
<div class="qm-slot" data-popup="qm-popup-glucksbox">
<img
src="/images/quickmenu/glucksbox.png"
alt=""
onerror="this.style.display = 'none'"
/>
<span class="qm-slot-label">Glücksbox</span>
</div>
<div class="qm-slot" data-popup="qm-popup-events">
<img
src="/images/quickmenu/events.png"
alt=""
onerror="this.style.display = 'none'"
/>
<span class="qm-slot-label">Tägliche Events</span>
</div>
<div class="qm-slot" data-popup="qm-popup-heldenbonus">
<img
src="/images/quickmenu/heldenbonus.png"
alt=""
onerror="this.style.display = 'none'"
/>
<span class="qm-slot-label">Helden Bonus</span>
</div>
<div class="qm-slot" data-popup="qm-popup-sealedliga">
<img
src="/images/quickmenu/sealedliga.png"
alt=""
onerror="this.style.display = 'none'"
/>
<span class="qm-slot-label">Sealed Liga</span>
</div>
<div class="qm-slot" data-popup="qm-popup-beschwoerer">
<img
src="/images/quickmenu/beschwoerer.png"
alt=""
onerror="this.style.display = 'none'"
/>
<span class="qm-slot-label">Beschwörer der Seelen</span>
</div>
<div class="qm-slot" data-popup="qm-popup-onlinebonus">
<img
src="/images/quickmenu/onlinebonus.png"
alt=""
onerror="this.style.display = 'none'"
/>
<span class="qm-slot-label">Online Bonus</span>
</div>
<div class="qm-slot" data-popup="qm-popup-aktionen">
<img
src="/images/quickmenu/aktionen.png"
alt=""
onerror="this.style.display = 'none'"
/>
<span class="qm-slot-label">Aktionen</span>
</div>
<div class="qm-slot" data-popup="qm-popup-basar">
<img
src="/images/quickmenu/basar.png"
alt=""
onerror="this.style.display = 'none'"
/>
<span class="qm-slot-label">Basar</span>
</div>
<div class="qm-slot" data-popup="qm-popup-boosteraktion">
<img
src="/images/quickmenu/boosteraktion.png"
alt=""
onerror="this.style.display = 'none'"
/>
<span class="qm-slot-label">10 Booster Aktion</span>
</div>
<div class="qm-slot" data-popup="qm-popup-boosterjagd">
<img
src="/images/quickmenu/boosterjagd.png"
alt=""
onerror="this.style.display = 'none'"
/>
<span class="qm-slot-label">Boosterjagd</span>
</div>
</div>
<!-- ================================
Quick Menu Overlay
================================ -->
<div id="qm-overlay"></div>
<!-- ================================
Quick Menu Popups (je 1800x1000)
================================ -->
<div id="qm-popup-glucksbox" class="qm-popup">
<div class="qm-popup-header">
<span class="qm-popup-title">Glücksbox</span>
<span class="qm-popup-close">✕</span>
</div>
<div class="qm-popup-body" id="qm-body-glucksbox"></div>
</div>
<div id="qm-popup-events" class="qm-popup">
<div class="qm-popup-header">
<span class="qm-popup-title">Tägliche Events</span>
<span class="qm-popup-close">✕</span>
</div>
<div class="qm-popup-body" id="qm-body-events"></div>
</div>
<div id="qm-popup-heldenbonus" class="qm-popup">
<div class="qm-popup-header">
<span class="qm-popup-title">Helden Bonus</span>
<span class="qm-popup-close">✕</span>
</div>
<div class="qm-popup-body" id="qm-body-heldenbonus"></div>
</div>
<div id="qm-popup-sealedliga" class="qm-popup">
<div class="qm-popup-header">
<span class="qm-popup-title">Sealed Liga</span>
<span class="qm-popup-close">✕</span>
</div>
<div class="qm-popup-body" id="qm-body-sealedliga"></div>
</div>
<div id="qm-popup-beschwoerer" class="qm-popup">
<div class="qm-popup-header">
<span class="qm-popup-title">Beschwörer der Seelen</span>
<span class="qm-popup-close">✕</span>
</div>
<div class="qm-popup-body" id="qm-body-beschwoerer"></div>
</div>
<div id="qm-popup-onlinebonus" class="qm-popup">
<div class="qm-popup-header">
<span class="qm-popup-title">Online Bonus</span>
<span class="qm-popup-close">✕</span>
</div>
<div class="qm-popup-body" id="qm-body-onlinebonus"></div>
</div>
<div id="qm-popup-aktionen" class="qm-popup">
<div class="qm-popup-header">
<span class="qm-popup-title">Aktionen</span>
<span class="qm-popup-close">✕</span>
</div>
<div class="qm-popup-body" id="qm-body-aktionen"></div>
</div>
<div id="qm-popup-basar" class="qm-popup">
<div class="qm-popup-header">
<span class="qm-popup-title">Basar</span>
<span class="qm-popup-close">✕</span>
</div>
<div class="qm-popup-body" id="qm-body-basar"></div>
</div>
<div id="qm-popup-boosteraktion" class="qm-popup">
<div class="qm-popup-header">
<span class="qm-popup-title">10 Booster Aktion</span>
<span class="qm-popup-close">✕</span>
</div>
<div class="qm-popup-body" id="qm-body-boosteraktion"></div>
</div>
<div id="qm-popup-boosterjagd" class="qm-popup">
<div class="qm-popup-header">
<span class="qm-popup-title">Boosterjagd</span>
<span class="qm-popup-close">✕</span>
</div>
<div class="qm-popup-body" id="qm-body-boosterjagd"></div>
</div>
<div id="game-notification-overlay"></div>
<div id="game-notification">
<div class="notification-header">
<span id="notification-icon">⚔️</span>
<span id="notification-title">Hinweis</span>
</div>
<div class="notification-body">
<p id="notification-message"></p>
</div>
<div class="notification-footer">
<button class="notification-btn" id="notification-ok">OK</button>
</div>
</div>
<!-- Music -->
<div id="music-control">
<button id="music-mute-btn" title="Musik ein/ausschalten">🔊</button>
<input
type="range"
id="music-volume"
min="0"
max="1"
step="0.01"
value="0.4"
title="Lautstärke"
/>
</div>
<audio id="bg-music" preload="auto"></audio>
<script>
(function () {
const playlist = [
"/music/jean-paul-v-danse-des-princesses-307890.mp3",
"/music/delosound-medieval-background-351307.mp3",
"/music/dueg-oth-musik-adel-142724.mp3",
"/music/jean-paul-v-dancing-in-the-medieval-time-329033.mp3",
"/music/kaazoom-medieval-dance-2-min-edit-medieval-music-404925.mp3",
"/music/emmraan-fantasy-kingdom-261257.mp3",
"/music/dueg-oth-musik-hintergrund-142725.mp3",
];
const audio = document.getElementById("bg-music");
const muteBtn = document.getElementById("music-mute-btn");
const vol = document.getElementById("music-volume");
let muted = localStorage.getItem("dok_muted") === "true";
let started = false; // ← merkt sich, ob Wiedergabe schon lief
if (localStorage.getItem("dok_vol") !== null)
vol.value = localStorage.getItem("dok_vol");
audio.volume = parseFloat(vol.value);
let index = 0;
const shuffled = [...playlist].sort(() => Math.random() - 0.5);
function playTrack(i) {
audio.src = shuffled[i];
audio.muted = muted;
if (!muted) {
audio
.play()
.then(() => {
started = true;
})
.catch(() => {});
}
}
audio.addEventListener("ended", () => {
index = (index + 1) % shuffled.length;
playTrack(index);
});
function applyMute() {
audio.muted = muted;
muteBtn.textContent = muted ? "🔇" : "🔊";
localStorage.setItem("dok_muted", muted);
// Wenn gerade nicht stumm, aber Audio pausiert → starten/fortsetzen
if (!muted) {
if (!audio.src) playTrack(index);
audio
.play()
.then(() => {
started = true;
})
.catch(() => {});
}
}
muteBtn.addEventListener("click", () => {
muted = !muted;
applyMute();
});
vol.addEventListener("input", () => {
audio.volume = parseFloat(vol.value);
localStorage.setItem("dok_vol", vol.value);
if (parseFloat(vol.value) > 0 && muted) {
muted = false;
applyMute();
}
muteBtn.textContent = parseFloat(vol.value) === 0 ? "🔇" : "🔊";
});
// Track laden (noch kein play() Browser erlaubt das vor Interaktion nicht)
playTrack(0);
applyMute();
// Bei JEDER Interaktion prüfen, ob Audio noch nicht läuft → nachholen
// (kein { once: true } mehr, schadet aber kaum da der Check schnell ist)
function tryResume() {
if (!muted && (audio.paused || !started)) {
audio
.play()
.then(() => {
started = true;
})
.catch(() => {});
}
}
document.addEventListener("click", tryResume);
document.addEventListener("keydown", tryResume);
document.addEventListener("pointerdown", tryResume);
})();
</script>
<script type="module" src="/js/map-ui.js"></script>
<script src="/socket.io/socket.io.js"></script>
<script>
window.playerName = "<%= character.name %>";
</script>
<script src="/js/chat.js"></script>
<script type="module" src="/js/quickmenu.js"></script>
</body>
</html>