Tourismustal: iPad-Feedback Runde 2 (5 Punkte)

- Bau-Ablehnung erklaert jetzt immer auch die Bauregeln des Gebaeudes
  (Toast: Grund + Beschreibung, 7 s).
- Lehrer-Schalter fuer den Vorlese-Modus: class_modules.audio_info
  (Migration, Default AN) + modules-API set_audio_info + Toggle auf der
  Modul-Karte im Cockpit (Vorlesen an/aus) + Wrapper injiziert
  TT_FEATURES.audioInfo + Sim blendet den Umschalter aus und erzwingt
  Lese-Modus, wenn gesperrt.
- Bus zeigt bei Rueckfahrt sein Heck: Heckscheibe + rote Ruecklichter,
  Tuer/Spiegel richtungsabhaengig.
- Bikepark-Flowtrails: 3 Stufen hangAUFwaerts (gleiche Richtung wie
  Lift-Pisten).
- Info-Button an jedem Bauwerk im Baumenue: erklaert Wirkung, Kosten,
  Lage-Regeln und Lehrplan-Wissen VOR dem Bau.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-11 18:07:03 +02:00
parent cb60a8c16d
commit 55a83d5daf
10 changed files with 131 additions and 35 deletions
+34 -3
View File
@@ -2,7 +2,7 @@
// Auto-Pause), Meldungs-Log, Graphen, Skipass-Regler, Ziele, Toasts,
// Onboarding, Szenenwahl und Topbar-Buttons.
import { BUILDINGS } from './data.js';
import { BUILDINGS, BUILD_INFO, KNOWLEDGE } from './data.js';
import { seasonOfDay, DAYS_PER_YEAR } from './model.js';
import { telemetry } from './telemetry.js';
import { audio } from './audio.js';
@@ -18,7 +18,11 @@ export class UI {
this.cardOpen = false;
this.speedBeforeCard = 1;
this.collectedCards = [];
this.infoMode = localStorage.getItem('tt_infomode') || 'read';
// Vorlese-Modus: kann von der Lehrperson pro Klasse gesperrt werden
this.audioAllowed = window.TT_FEATURES?.audioInfo !== false;
this.infoMode = this.audioAllowed
? (localStorage.getItem('tt_infomode') || 'read')
: 'read';
this.activeBuild = null;
this.toastTimer = null;
@@ -77,11 +81,37 @@ export class UI {
el.innerHTML = `
<span class="emoji">${emoji}</span>
<span class="info"><b>${name}</b><small>${desc}</small></span>
<span class="cost">${cost}</span>`;
<span class="cost">${cost}</span>
<button class="bi-menu-info" title="Alles über: ${name}">️</button>`;
el.addEventListener('click', () => this._toggleBuild(type, el));
el.querySelector('.bi-menu-info').addEventListener('click', e => {
e.stopPropagation(); // nicht in den Baumodus wechseln
audio.click();
this.showBuildInfo(type);
});
return el;
}
// im Baumenü: erklärt ein Bauwerk VOR dem Bau Wirkung, Kosten,
// Lage-Regeln und das Lehrplan-Wissen dazu.
showBuildInfo(type) {
const def = BUILDINGS[type];
const info = BUILD_INFO[type];
const know = (KNOWLEDGE[type] || [])
.map(k => `📚 ${k.term}: ${k.text}`).join('\n\n');
const staffLine = def.staff ? ` + ${def.staff} Angestellte` : '';
this.showCard({
id: `menuinfo-${type}`, transient: true, forceModal: true,
icon: def.emoji, sound: 'none',
title: def.name,
text: `${def.desc}\n\nBaukosten: ${def.cost.toLocaleString('de-AT')} € · `
+ `laufend: ${def.upkeep} €/Tag${staffLine}.`
+ (info ? `\n\n${info.text}` : '')
+ (know ? `\n\n${know}` : ''),
});
telemetry.log('menu_info', { type });
}
_toggleBuild(type, el) {
audio.click();
document.querySelectorAll('.build-item').forEach(i => i.classList.remove('active'));
@@ -141,6 +171,7 @@ export class UI {
$('playerPanel').classList.toggle('hidden');
telemetry.log('player_panel', { open: !$('playerPanel').classList.contains('hidden') });
});
if (!this.audioAllowed) $('btnInfoMode').classList.add('hidden');
$('btnInfoMode').addEventListener('click', e => {
audio.click();
this.infoMode = this.infoMode === 'audio' ? 'read' : 'audio';