Erster Commit

This commit is contained in:
2026-08-22 08:40:29 +02:00
commit 875477d425
1961 changed files with 930336 additions and 0 deletions
+318
View File
@@ -0,0 +1,318 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<title>Map Editor</title>
<style>
* { box-sizing: border-box; }
html, body { margin: 0; height: 100%; background: #0a0a0a; color: #eee; font-family: Arial, sans-serif; overflow: hidden; }
#appLayout { display: flex; height: 100vh; width: 100vw; }
/* ---------- Linke Seite: Kopfzeile + Karte ---------- */
#mainArea { flex: 1; display: flex; flex-direction: column; min-width: 0; }
#topBar {
display: flex;
flex-wrap: wrap;
gap: 8px;
align-items: center;
padding: 8px 12px;
background: #1a1a1a;
border-bottom: 1px solid #333;
}
a.back { color: #6fbf73; text-decoration: none; font-size: 14px; margin-right: 6px; }
a.back:hover { text-decoration: underline; }
#topBar input, #topBar select, #topBar button {
background: #222; border: 1px solid #444; color: #eee;
padding: 6px 8px; border-radius: 4px; font-size: 13px;
}
#topBar button { background: #2c7a3d; cursor: pointer; border-color: #2c7a3d; }
#topBar button:hover { opacity: 0.85; }
#camLabel { color: #888; font-size: 12px; margin-left: auto; white-space: nowrap; }
#canvasWrap { flex: 1; position: relative; background: #000; min-height: 0; }
#canvas { display: block; position: absolute; top: 0; left: 0; }
#hintBar {
padding: 4px 12px;
background: #161616;
color: #777;
font-size: 11px;
border-top: 1px solid #2a2a2a;
}
/* ---------- Rechte Seite: Sidebar mit Tabs ---------- */
#sidebar {
width: 360px;
flex-shrink: 0;
background: #161616;
border-left: 1px solid #333;
display: flex;
flex-direction: column;
}
#sidebarTabs {
display: flex;
border-bottom: 1px solid #333;
}
.sidebar-tab-btn {
flex: 1;
background: #1a1a1a;
border: none;
border-right: 1px solid #333;
color: #999;
padding: 10px 4px;
font-size: 12px;
cursor: pointer;
}
.sidebar-tab-btn:last-child { border-right: none; }
.sidebar-tab-btn:hover { background: #222; }
.sidebar-tab-btn.active { background: #222; color: #f5d90a; border-bottom: 2px solid #f5d90a; }
#sidebarBody { flex: 1; overflow-y: auto; padding: 12px; }
.sidebar-panel { display: none; }
.sidebar-panel.active { display: block; }
.toolbar-group { margin-bottom: 14px; }
.toolbar-group-label {
font-size: 10px; color: #777; text-transform: uppercase;
letter-spacing: 0.5px; display: block; margin-bottom: 6px;
}
.toolbar-group-buttons { display: flex; flex-wrap: wrap; gap: 6px; }
.mode-btn {
width: 42px; height: 42px; font-size: 19px;
background: #2a2a2a; border: 2px solid #444; border-radius: 6px;
cursor: pointer; display: flex; align-items: center; justify-content: center;
}
.mode-btn:hover { border-color: #666; }
.mode-btn.active { border-color: #f5d90a; background: #3a3520; box-shadow: 0 0 6px rgba(245,217,10,0.5); }
#layerToggles { display: flex; flex-direction: column; gap: 8px; font-size: 13px; color: #ccc; }
#layerToggles label { display: flex; align-items: center; gap: 8px; cursor: pointer; }
#tilePalette, #objectPalette { display: flex; flex-wrap: wrap; gap: 6px; }
.tile-swatch {
width: 56px; border: 2px solid #000; border-radius: 4px; cursor: pointer;
display: flex; flex-direction: column; align-items: center; overflow: hidden;
background: #1a1a1a; font-family: Arial, sans-serif;
}
.tile-swatch .color-box { width: 100%; height: 32px; position: relative; }
.tile-swatch .collision-icon { position: absolute; top: 1px; right: 1px; font-size: 9px; text-shadow: 0 0 2px black; }
.tile-swatch .tile-label {
font-size: 9px; color: #ccc; padding: 2px; text-align: center;
white-space: nowrap; overflow: hidden; text-overflow: ellipsis; width: 100%;
}
.tile-swatch.selected { border-color: #f5d90a; box-shadow: 0 0 6px #f5d90a; }
.sidebar-section-title { color: #f5d90a; font-size: 13px; margin: 0 0 8px 0; }
.sidebar-hint { color: #777; font-size: 11px; margin-bottom: 10px; }
#shopEditor {
position: absolute; right: 10px; top: 60px; width: 200px;
background: rgba(20,20,20,0.9); color: white; padding: 10px;
border: 2px solid #444; border-radius: 6px;
}
</style>
</head>
<body>
<div id="appLayout">
<div id="mainArea">
<div id="topBar">
<a class="back" href="/index.html">&larr; Startseite</a>
<input type="text" id="mapName" placeholder="Map-Name (z.B. stadt)">
<select id="mapSelect"><option value="">Map laden...</option></select>
<button id="newMapBtn">Neue Map</button>
<button id="saveMapBtn">Speichern</button>
<input type="text" id="doorTargetMap" placeholder="Ziel-Map" style="width:110px;">
<input type="number" id="doorTargetX" placeholder="Ziel X" style="width:70px;">
<input type="number" id="doorTargetY" placeholder="Ziel Y" style="width:70px;">
<input type="number" id="mapWidth" placeholder="Breite" style="width:70px;">
<input type="number" id="mapHeight" placeholder="Höhe" style="width:70px;">
<button id="resizeMapBtn">Größe ändern</button>
<span id="camLabel"></span>
</div>
<div id="canvasWrap">
<canvas id="canvas" width="1500" height="800"></canvas>
</div>
<div id="hintBar">
Pfeiltasten oder mittlere Maustaste (gedrückt halten + ziehen) zum Scrollen. Linksklick = setzen, Rechtsklick = löschen (außer Tile-Modus: da malt Rechtsklick "leer"). Werkzeuge und Paletten jetzt rechts →
</div>
</div>
<div id="sidebar">
<div id="sidebarTabs">
<button class="sidebar-tab-btn active" data-sidebar-tab="modes">🛠️ Werkzeuge</button>
<button class="sidebar-tab-btn" data-sidebar-tab="layers">👁️ Ebenen</button>
<button class="sidebar-tab-btn" data-sidebar-tab="palette">🧱📦 Tiles &amp; Objekte</button>
</div>
<div id="sidebarBody">
<!-- WERKZEUGE -->
<div class="sidebar-panel active" id="panel-modes">
<select id="modeSelect" style="display:none;">
<option value="tile">Tiles setzen</option>
<option value="rotate">Tile drehen</option>
<option value="spawn">Spawn-Punkt setzen</option>
<option value="door">Tür/Portal setzen</option>
<option value="object">Objekte setzen</option>
<option value="shop">Shop setzen</option>
<option value="atm">ATM setzen</option>
<option value="garage">Garage setzen</option>
<option value="jobcenter">Jobcenter setzen</option>
<option value="clothingshop">Kleidungsladen setzen</option>
<option value="insuranceoffice">Versicherungsbüro setzen</option>
<option value="plateoffice">Kfz-Zulassungsstelle setzen</option>
<option value="trailershop">Anhänger-Shop setzen</option>
<option value="gasstation">Tankstelle setzen</option>
<option value="repairshop">Werkstatt setzen</option>
<option value="house">Haus setzen</option>
<option value="jobpoint">Job-Punkt setzen</option>
<option value="taxistand">Taxi-Stand setzen</option>
<option value="hospital">Krankenhaus setzen</option>
<option value="prison">Gefängnis setzen</option>
<option value="zone">Territoriums-Zone setzen</option>
<option value="impound">Abschlepphof setzen</option>
<option value="firestation">Feuerwache setzen</option>
<option value="drug_harvest">Anbaustelle setzen</option>
<option value="drug_process">Labor setzen</option>
<option value="drug_dealer">Verkaufsort (Pool) setzen</option>
</select>
<div class="toolbar-group">
<span class="toolbar-group-label">Terrain</span>
<div class="toolbar-group-buttons">
<button class="mode-btn" data-mode="tile" title="Tiles setzen">🧱</button>
<button class="mode-btn" data-mode="rotate" title="Tile drehen (Linksklick=+90°, Rechtsklick=-90°)">🔄</button>
<button class="mode-btn" data-mode="object" title="Objekte setzen">📦</button>
<button class="mode-btn" data-mode="spawn" title="Spawn-Punkt setzen">🚩</button>
<button class="mode-btn" data-mode="door" title="Tür/Portal setzen">🚪</button>
</div>
</div>
<div class="toolbar-group">
<span class="toolbar-group-label">Shops &amp; Gebäude</span>
<div class="toolbar-group-buttons">
<button class="mode-btn" data-mode="shop" title="Shop setzen">🛒</button>
<button class="mode-btn" data-mode="atm" title="ATM setzen">🏧</button>
<button class="mode-btn" data-mode="garage" title="Garage setzen">🚗</button>
<button class="mode-btn" data-mode="gasstation" title="Tankstelle setzen"></button>
<button class="mode-btn" data-mode="repairshop" title="Werkstatt setzen">🔧</button>
<button class="mode-btn" data-mode="house" title="Haus setzen">🏠</button>
<button class="mode-btn" data-mode="jobcenter" title="Jobcenter setzen">💼</button>
<button class="mode-btn" data-mode="clothingshop" title="Kleidungsladen setzen">👕</button>
<button class="mode-btn" data-mode="insuranceoffice" title="Versicherungsbüro setzen">🛡️</button>
<button class="mode-btn" data-mode="plateoffice" title="Kfz-Zulassungsstelle setzen">🔖</button>
<button class="mode-btn" data-mode="trailershop" title="Anhänger-Shop setzen">🚛</button>
</div>
</div>
<div class="toolbar-group">
<span class="toolbar-group-label">Verkehr</span>
<div class="toolbar-group-buttons">
<button class="mode-btn" data-mode="taxistand" title="Taxi-Stand setzen">🚕</button>
<button class="mode-btn" data-mode="jobpoint" title="Job-Punkt setzen">📍</button>
<button class="mode-btn" data-mode="impound" title="Abschlepphof setzen">🚛</button>
<button class="mode-btn" data-mode="firestation" title="Feuerwache setzen">🚒</button>
</div>
</div>
<div class="toolbar-group">
<span class="toolbar-group-label">Sicherheit</span>
<div class="toolbar-group-buttons">
<button class="mode-btn" data-mode="hospital" title="Krankenhaus setzen">🏥</button>
<button class="mode-btn" data-mode="prison" title="Gefängnis setzen">🔒</button>
<button class="mode-btn" data-mode="zone" title="Territoriums-Zone setzen">🚩</button>
</div>
</div>
<div class="toolbar-group">
<span class="toolbar-group-label">Drogen</span>
<div class="toolbar-group-buttons">
<button class="mode-btn" data-mode="drug_harvest" title="Anbaustelle setzen">🌿</button>
<button class="mode-btn" data-mode="drug_process" title="Labor setzen">⚗️</button>
<button class="mode-btn" data-mode="drug_dealer" title="Verkaufsort (Pool) setzen">💰</button>
</div>
</div>
</div>
<!-- EBENEN -->
<div class="sidebar-panel" id="panel-layers">
<h3 class="sidebar-section-title">Sichtbarkeit</h3>
<div id="layerToggles">
<label><input type="checkbox" class="layer-toggle" data-layer="object" checked> 📦 Objekte</label>
<label><input type="checkbox" class="layer-toggle" data-layer="shop" checked> 🛒 Shops</label>
<label><input type="checkbox" class="layer-toggle" data-layer="atm" checked> 🏧 ATMs</label>
<label><input type="checkbox" class="layer-toggle" data-layer="garage" checked> 🚗 Garagen</label>
<label><input type="checkbox" class="layer-toggle" data-layer="jobcenter" checked> 💼 Jobcenter</label>
<label><input type="checkbox" class="layer-toggle" data-layer="clothingshop" checked> 👕 Kleidungsläden</label>
<label><input type="checkbox" class="layer-toggle" data-layer="insuranceoffice" checked> 🛡️ Versicherungsbüros</label>
<label><input type="checkbox" class="layer-toggle" data-layer="plateoffice" checked> 🔖 Zulassungsstellen</label>
<label><input type="checkbox" class="layer-toggle" data-layer="trailershop" checked> 🚛 Anhänger-Shops</label>
<label><input type="checkbox" class="layer-toggle" data-layer="gasstation" checked> ⛽ Tankstellen</label>
<label><input type="checkbox" class="layer-toggle" data-layer="repairshop" checked> 🔧 Werkstätten</label>
<label><input type="checkbox" class="layer-toggle" data-layer="house" checked> 🏠 Häuser</label>
<label><input type="checkbox" class="layer-toggle" data-layer="jobpoint" checked> 📍 Job-Punkte</label>
<label><input type="checkbox" class="layer-toggle" data-layer="taxistand" checked> 🚕 Taxi-Stände</label>
<label><input type="checkbox" class="layer-toggle" data-layer="hospital" checked> 🏥 Krankenhäuser</label>
<label><input type="checkbox" class="layer-toggle" data-layer="prison" checked> 🔒 Gefängnisse</label>
<label><input type="checkbox" class="layer-toggle" data-layer="zone" checked> 🚩 Zonen</label>
<label><input type="checkbox" class="layer-toggle" data-layer="impound" checked> 🚛 Abschlepphöfe</label>
<label><input type="checkbox" class="layer-toggle" data-layer="firestation" checked> 🚒 Feuerwachen</label>
<label><input type="checkbox" class="layer-toggle" data-layer="drug_harvest" checked> 🌿 Anbaustellen</label>
<label><input type="checkbox" class="layer-toggle" data-layer="drug_process" checked> ⚗️ Labore</label>
<label><input type="checkbox" class="layer-toggle" data-layer="drug_dealer" checked> 💰 Verkaufsorte</label>
</div>
</div>
<!-- TILES & OBJEKTE -->
<div class="sidebar-panel" id="panel-palette">
<h3 class="sidebar-section-title">🧱 Tile-Palette</h3>
<div style="margin-bottom:12px;">
<label for="brushSize" style="color:#ccc; font-size:13px; display:block; margin-bottom:4px;">Pinselgröße:</label>
<select id="brushSize">
<option value="1">1×1</option>
<option value="2">2×2</option>
<option value="4">4×4</option>
<option value="6">6×6</option>
<option value="8">8×8</option>
</select>
<div class="sidebar-hint">Klicken und ziehen malt durchgehend. Drehen-Werkzeug (🔄) dreht Tile ODER Objekt an der angeklickten Stelle.</div>
</div>
<div id="tilePalette"></div>
<h3 class="sidebar-section-title" style="margin-top:20px;">📦 Objekt-Palette</h3>
<div id="objectPalette"></div>
</div>
</div>
</div>
</div>
<script src="map_editor.js?v=26"></script>
<script>
// Sidebar-Tabs umschalten
document.querySelectorAll(".sidebar-tab-btn").forEach(btn => {
btn.addEventListener("click", () => {
document.querySelectorAll(".sidebar-tab-btn").forEach(b => b.classList.remove("active"));
document.querySelectorAll(".sidebar-panel").forEach(p => p.classList.remove("active"));
btn.classList.add("active");
document.getElementById("panel-" + btn.dataset.sidebarTab).classList.add("active");
});
});
// Canvas füllt den verfügbaren Platz aus, statt fest 1500x800 zu sein
function resizeEditorCanvas() {
const wrap = document.getElementById("canvasWrap");
const canvas = document.getElementById("canvas");
canvas.width = wrap.clientWidth;
canvas.height = wrap.clientHeight;
if (typeof render === "function") render();
}
window.addEventListener("resize", resizeEditorCanvas);
window.addEventListener("load", resizeEditorCanvas);
// Direkt beim Einbinden schon einmal versuchen (falls load-Event schon vorbei ist)
setTimeout(resizeEditorCanvas, 50);
</script>
</body>
</html>