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) <noreply@anthropic.com>
This commit is contained in:
@@ -1,7 +1,16 @@
|
|||||||
-- ============================================================
|
-- ============================================================
|
||||||
-- class_modules.audio_info: Lehrer-Schalter für den Vorlese-Modus
|
-- class_modules.audio_info: Lehrer-Schalter für den Vorlese-Modus
|
||||||
-- (Audio-Info-Modus in Sims, derzeit Tourismustal). Default AN.
|
-- (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
|
SET @exists := (SELECT COUNT(*) FROM information_schema.COLUMNS
|
||||||
ADD COLUMN IF NOT EXISTS audio_info TINYINT(1) NOT NULL DEFAULT 1;
|
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;
|
||||||
|
|||||||
@@ -35,17 +35,20 @@ const SPRITE_DEFS = {
|
|||||||
access: { w: 52, bottom: 8 },
|
access: { w: 52, bottom: 8 },
|
||||||
rescue: { w: 60, bottom: 9 },
|
rescue: { w: 60, bottom: 9 },
|
||||||
snow: { w: 44, bottom: 7 },
|
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)
|
// Megabauwerke: eigene Motive (mehr Elemente statt vergrößerter Fenster)
|
||||||
mega_restaurant: { w: 104, bottom: 12 },
|
mega_restaurant: { w: 116, bottom: 24 },
|
||||||
mega_hotel: { w: 106, bottom: 12 },
|
mega_hotel: { w: 118, bottom: 24 },
|
||||||
mega_staffhouse: { w: 102, bottom: 12 },
|
mega_staffhouse: { w: 114, bottom: 24 },
|
||||||
mega_snow: { w: 96, bottom: 11 },
|
mega_snow: { w: 108, bottom: 24 },
|
||||||
mega_badesee: { w: 110, bottom: 14 },
|
mega_badesee: { w: 122, bottom: 26 },
|
||||||
mega_ropes: { w: 106, bottom: 11 },
|
mega_ropes: { w: 116, bottom: 22 },
|
||||||
mega_playground: { w: 104, bottom: 12 },
|
mega_playground: { w: 116, bottom: 24 },
|
||||||
mega_bikerental: { w: 98, bottom: 12 },
|
mega_bikerental: { w: 110, bottom: 24 },
|
||||||
mega_trail: { w: 100, bottom: 11 },
|
mega_trail: { w: 112, bottom: 22 },
|
||||||
ropes: { w: 58, bottom: 8 },
|
ropes: { w: 58, bottom: 8 },
|
||||||
bikerental: { w: 50, bottom: 8 },
|
bikerental: { w: 50, bottom: 8 },
|
||||||
platform: { w: 62, bottom: 9 },
|
platform: { w: 62, bottom: 9 },
|
||||||
@@ -1088,8 +1091,9 @@ export class IsoRenderer {
|
|||||||
ctx.strokeStyle = 'rgba(47,62,70,0.06)';
|
ctx.strokeStyle = 'rgba(47,62,70,0.06)';
|
||||||
ctx.stroke();
|
ctx.stroke();
|
||||||
|
|
||||||
// kleine Details je Untergrund
|
// kleine Details je Untergrund (nicht auf bebauten Kacheln – sonst
|
||||||
if (!snowy && !tile.road) this._tileDetail(tile, x, y);
|
// 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);
|
if (tile.terrain === 'water' && !tile.bridge) this._waterStreak(tile, x, y);
|
||||||
|
|
||||||
// Talstraße (bzw. Brücke über den Fluss)
|
// Talstraße (bzw. Brücke über den Fluss)
|
||||||
@@ -1130,8 +1134,19 @@ export class IsoRenderer {
|
|||||||
this._drawTree(x, y, snowy, tile.tint);
|
this._drawTree(x, y, snowy, tile.tint);
|
||||||
}
|
}
|
||||||
if (tile.deco) this._drawDeco(tile.deco, x, y);
|
if (tile.deco) this._drawDeco(tile.deco, x, y);
|
||||||
// Große Gebäude (2×2) zeichnet nur die Anker-Kachel – zentriert übers Areal
|
// Gebäude: 1×1 zeichnet seine Kachel. Große (2×2) zeichnet die VORDERSTE
|
||||||
if (tile.building && !tile.buildingRef) this._drawBuilding(tile.building, x, y, tile);
|
// 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
|
// Noch nicht erschlossene Hochlagen liegen unter Nebel
|
||||||
if (tile.r < this.state.stageRow) {
|
if (tile.r < this.state.stageRow) {
|
||||||
|
|||||||
Reference in New Issue
Block a user