fix(ui): Höhe-Regler nachführen, Teleport-Warnfrist, SUV-Abstimmung

Der Höhe-Regler las den Höhenfaktor nur beim Bau des Panels und zeigte
nach einem Figurenwechsel weiter den alten Wert; beim nächsten Ziehen
überschrieb er die korrekt gesetzte Größe mit einem Sprung (Ruling 68).

Der Teleport hielt den Spieler notfalls unbegrenzt still. Er bekommt
dieselbe einmalige Warnung nach 15 s wie der Spawn, mit Frist je Sprung
statt modulweit (Ruling 69).

Der SUV bekommt metalness und roughness zurück, die der Kommentar
darüber als unverändert zusicherte (Ruling 70).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
knsoandClaude Opus 5 committed 2026-09-13 04:14:01 +02:00
1 parent 182db238c6
commit 0ece90e2ec
3 files changed
+105 -4

No files matched your search

+39 -2
View File
@@ -146,6 +146,12 @@ async function spawnVehicles() {
if (!child.isMesh) return;
child.castShadow = true;
child.receiveShadow = true;
const mats = Array.isArray(child.material) ? child.material : [child.material];
for (const mat of mats) {
if (!mat) continue;
mat.metalness = 0.8;
mat.roughness = 0.0;
}
});
}
}
@@ -155,14 +161,39 @@ async function spawnVehicles() {
// Spieler bei einem Sprung auf ein weit entferntes, noch nicht gestreamtes Wahrzeichen durch
// den ungeladenen Boden fallen und vom Auffangnetz (p.y < -30) zurück an lastSafe geschickt
// werden — der Sprung sähe dann aus, als wäre er wirkungslos.
// startedAt/warned sitzen auf dem pendingTeleport-Objekt selbst statt in eigenen module-level
// Variablen (Ruling 69, Gegenstück zu warnedSlowSpawn/startedAt oben): jeder neue Sprung
// bekommt so seine eigene, frisch scharfgestellte Warnfrist, statt von einer vorherigen,
// bereits ausgelösten Warnung stumm mitgenommen zu werden.
let pendingTeleport = null;
function requestTeleport(position) {
pendingTeleport = { x: position.x, y: position.y, z: position.z };
pendingTeleport = { x: position.x, y: position.y, z: position.z, startedAt: performance.now(), warned: false };
player.setSkipCapsuleCollision(true);
player.reset(new Vector3(position.x, position.y, position.z));
}
createPanel({ player, characterModule, scene, manifest, requestTeleport });
const gui = createPanel({ player, characterModule, scene, manifest, requestTeleport });
// TEMP: Fix-Runde 2 Screenshot-Beleg, vor Abschluss entfernen.
window.__shotWithReadout = () => {
renderer.render(scene, camera);
const params = gui.folders[0].controllers[0].object;
const canvas = document.createElement("canvas");
canvas.width = renderer.domElement.width;
canvas.height = renderer.domElement.height;
const ctx = canvas.getContext("2d");
ctx.drawImage(renderer.domElement, 0, 0);
const scale = canvas.width / 800;
ctx.font = `${28 * scale}px monospace`;
const text = `Figur: ${params.character} Höhe: ${params.height}`;
const pad = 14 * scale;
const w = ctx.measureText(text).width + pad * 2;
ctx.fillStyle = "rgba(0,0,0,0.7)";
ctx.fillRect(0, 0, w, 44 * scale);
ctx.fillStyle = "#fff";
ctx.textBaseline = "middle";
ctx.fillText(text, pad, 22 * scale);
return canvas.toDataURL("image/png");
};
// Meeresboden: man watet hinein, statt endlos zu fallen. Einmalig, nicht je Chunk.
const seafloor = new Mesh(new BoxGeometry(4000, 1, 4000), materials.seafloor);
@@ -234,6 +265,12 @@ function tick(delta) {
pendingTeleport = null;
} else {
player.reset(new Vector3(pendingTeleport.x, pendingTeleport.y, pendingTeleport.z));
// Ruling 69: gleiche Begründung wie bei warnedSlowSpawn oben — stilles Festhalten
// wäre nicht diagnostizierbar, sollte der Chunk am Sprungziel nie fertig werden.
if (!pendingTeleport.warned && performance.now() - pendingTeleport.startedAt > 15000) {
pendingTeleport.warned = true;
console.warn(`Chunk am Sprungziel (${pendingTeleport.x}, ${pendingTeleport.z}) ist nach 15s immer noch nicht bereit.`);
}
return;
}
}