From 328d542fdc0aae03f08e91b4c5d0aee62c216b41 Mon Sep 17 00:00:00 2001 From: Thomas Date: Sat, 11 Jul 2026 18:10:46 +0200 Subject: [PATCH] Tourismustal: 2x2-Gebaeude korrekt im Painter (vorderste Kachel zeichnet) Grosse Gebaeude wurden von davorliegenden Kacheln uebermalt (Grasbueschel ueber dem Hotelfuss). Jetzt zeichnet die VORDERSTE Footprint-Kachel das Sprite, Terrain-Details entfallen auf bebauten Kacheln, Sprite-Mitte = Mitte der 4 Kacheln, w/bottom so dass der Fuss die vordere Spitze deckt. SQL-Migration audio_info MySQL-kompatibel (information_schema-Guard statt MariaDB IF NOT EXISTS - Prod ist echtes MySQL). Co-Authored-By: Claude Opus 4.8 (1M context) --- .../2026-07-11-class-modules-audio-info.sql | 15 +++++-- App/sims/tourismustal/js/iso.js | 43 +++++++++++++------ 2 files changed, 41 insertions(+), 17 deletions(-) diff --git a/App/Don_t_Deploy/2026-07-11-class-modules-audio-info.sql b/App/Don_t_Deploy/2026-07-11-class-modules-audio-info.sql index f28b0d8..0f819ff 100644 --- a/App/Don_t_Deploy/2026-07-11-class-modules-audio-info.sql +++ b/App/Don_t_Deploy/2026-07-11-class-modules-audio-info.sql @@ -1,7 +1,16 @@ -- ============================================================ -- class_modules.audio_info: Lehrer-Schalter für den Vorlese-Modus -- (Audio-Info-Modus in Sims, derzeit Tourismustal). Default AN. --- Stand: 2026-07-11 · Atlas · idempotent (MariaDB IF NOT EXISTS) +-- Stand: 2026-07-11 · Atlas +-- ACHTUNG: Prod ist echtes MySQL (kein MariaDB) → kein "IF NOT EXISTS" +-- bei ADD COLUMN. Guard über information_schema, damit idempotent. -- ============================================================ -ALTER TABLE class_modules - ADD COLUMN IF NOT EXISTS audio_info TINYINT(1) NOT NULL DEFAULT 1; +SET @exists := (SELECT COUNT(*) FROM information_schema.COLUMNS + WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'class_modules' + AND COLUMN_NAME = 'audio_info'); +SET @ddl := IF(@exists = 0, + 'ALTER TABLE class_modules ADD COLUMN audio_info TINYINT(1) NOT NULL DEFAULT 1', + 'SELECT 1'); +PREPARE stmt FROM @ddl; +EXECUTE stmt; +DEALLOCATE PREPARE stmt; diff --git a/App/sims/tourismustal/js/iso.js b/App/sims/tourismustal/js/iso.js index 5e366d9..1e70244 100644 --- a/App/sims/tourismustal/js/iso.js +++ b/App/sims/tourismustal/js/iso.js @@ -35,17 +35,20 @@ const SPRITE_DEFS = { access: { w: 52, bottom: 8 }, rescue: { w: 60, bottom: 9 }, snow: { w: 44, bottom: 7 }, - bikepark: { w: 108, bottom: 14 }, // 2×2-Areal, zentriert gezeichnet + // 2×2-Areale: Mitte des Sprites = Mitte der 4 Kacheln; w/bottom so + // gewählt, dass der Fuß bis zur vorderen Kachel-Spitze reicht (~40 px + // unter dem Zentrum: bottom + 0.12·w ≈ 38). + bikepark: { w: 116, bottom: 24 }, // Megabauwerke: eigene Motive (mehr Elemente statt vergrößerter Fenster) - mega_restaurant: { w: 104, bottom: 12 }, - mega_hotel: { w: 106, bottom: 12 }, - mega_staffhouse: { w: 102, bottom: 12 }, - mega_snow: { w: 96, bottom: 11 }, - mega_badesee: { w: 110, bottom: 14 }, - mega_ropes: { w: 106, bottom: 11 }, - mega_playground: { w: 104, bottom: 12 }, - mega_bikerental: { w: 98, bottom: 12 }, - mega_trail: { w: 100, bottom: 11 }, + mega_restaurant: { w: 116, bottom: 24 }, + mega_hotel: { w: 118, bottom: 24 }, + mega_staffhouse: { w: 114, bottom: 24 }, + mega_snow: { w: 108, bottom: 24 }, + mega_badesee: { w: 122, bottom: 26 }, + mega_ropes: { w: 116, bottom: 22 }, + mega_playground: { w: 116, bottom: 24 }, + mega_bikerental: { w: 110, bottom: 24 }, + mega_trail: { w: 112, bottom: 22 }, ropes: { w: 58, bottom: 8 }, bikerental: { w: 50, bottom: 8 }, platform: { w: 62, bottom: 9 }, @@ -1088,8 +1091,9 @@ export class IsoRenderer { ctx.strokeStyle = 'rgba(47,62,70,0.06)'; ctx.stroke(); - // kleine Details je Untergrund - if (!snowy && !tile.road) this._tileDetail(tile, x, y); + // kleine Details je Untergrund (nicht auf bebauten Kacheln – sonst + // liegen Grasbüschel ÜBER dem Fuß großer 2×2-Gebäude) + if (!snowy && !tile.road && !tile.building) this._tileDetail(tile, x, y); if (tile.terrain === 'water' && !tile.bridge) this._waterStreak(tile, x, y); // Talstraße (bzw. Brücke über den Fluss) @@ -1130,8 +1134,19 @@ export class IsoRenderer { this._drawTree(x, y, snowy, tile.tint); } if (tile.deco) this._drawDeco(tile.deco, x, y); - // Große Gebäude (2×2) zeichnet nur die Anker-Kachel – zentriert übers Areal - if (tile.building && !tile.buildingRef) this._drawBuilding(tile.building, x, y, tile); + // Gebäude: 1×1 zeichnet seine Kachel. Große (2×2) zeichnet die VORDERSTE + // Teil-Kachel (Painter-Reihenfolge!) – sonst übermalen die davorliegenden + // Kacheln den Gebäudefuß. Gezeichnet wird zentriert über dem Areal. + if (tile.building) { + const a = tile.buildingRef || { c: tile.c, r: tile.r }; + const at = this.state.map[a.r]?.[a.c]; + const big = at && ((BUILDINGS[at.building]?.size || 1) > 1 || at.mega); + if (!big) { + if (!tile.buildingRef) this._drawBuilding(tile.building, x, y, tile); + } else if (tile.c === a.c + 1 && tile.r === a.r + 1) { + this._drawBuilding(at.building, x, y, at); + } + } // Noch nicht erschlossene Hochlagen liegen unter Nebel if (tile.r < this.state.stageRow) {