85 lines
3.3 KiB
GDScript
85 lines
3.3 KiB
GDScript
extends SceneTree
|
||
## Identitäts-Probe-Map (Karte t_1da96275): deterministische Testkarte, die
|
||
## BOTH WORLDS — Editor-Playtest UND Quest-Client — mit EXAKT denselben
|
||
## Daten fährt (Identitäts-Vertrag: gleiche Map → gleiche Block/Walk-
|
||
## Entscheidungen).
|
||
##
|
||
## Layout (Höhenfeld res 33 = 2-m-Zellen, 64 × 64 m):
|
||
## x < 0 → Höhe 0.0 (flach)
|
||
## 0 ≤ x < 8 → Höhe 0.3 (Stufe 0.3 m — erklimmbar, Step-Up)
|
||
## x ≥ 8 → Höhe 1.1 (Stufe 0.8 m darüber — blockt)
|
||
## Objekte (alle auf FLACHEM Terrain, damit die Proben sauber sind):
|
||
## building_001 bei (−16, 0, −16) → Tür-Probe (Azimut 202.5°, Befund
|
||
## Karte t_f9adf97c: freie Breite 1.10 m)
|
||
## barracks_001 bei ( 20, 0, 12) → Wand-Probe (Trimesh blockt)
|
||
## box_006 bei (−16, 0, 8) → Kisten-Stufe 0.334 m (Step-Up)
|
||
## Run: godot4 --headless --path . -s res://tests/gen_identitaet_map.gd
|
||
## Schreibt: ${SVR_IDENTITAET_MAP:-/tmp/svr_identitaet_probe.svmap} (JSON).
|
||
|
||
const STEP_KLEIN := 0.3
|
||
const STUFE_GROSS := 1.1
|
||
|
||
|
||
func _initialize() -> void:
|
||
var res := 33
|
||
var size := 64.0
|
||
var heights := PackedFloat32Array()
|
||
heights.resize(res * res)
|
||
for zi in res:
|
||
for xi in res:
|
||
# Platzierungs-Konvention: (0,0) liegt bei (−size/2, −size/2);
|
||
# Höhe hängt nur von x ab (Spalten).
|
||
var x := float(xi) / float(res - 1) * size - size * 0.5
|
||
var h := 0.0
|
||
if x >= 0.0:
|
||
h = STEP_KLEIN
|
||
if x >= 8.0:
|
||
h = STUFE_GROSS
|
||
heights[zi * res + xi] = h
|
||
var raw_b64 := TerrainField.encode(heights, 0.0, STUFE_GROSS)
|
||
var doc: Dictionary = {
|
||
"format_version": 1,
|
||
"info": {"name": "Identitaets-Probe", "author": "Karte t_1da96275", "version": 1},
|
||
"terrain": {
|
||
"type": "heightmap",
|
||
"resolution": res,
|
||
"size_x_m": size,
|
||
"size_z_m": size,
|
||
"min_height_m": 0.0,
|
||
"max_height_m": STUFE_GROSS,
|
||
"heightmap_r16_b64": raw_b64,
|
||
},
|
||
"objects": [
|
||
{"id": "building_001", "pos": [-16.0, 0.0, -16.0], "rot_y_deg": 0.0, "scale": 1.0},
|
||
{"id": "barracks_001", "pos": [20.0, 0.0, 12.0], "rot_y_deg": 0.0, "scale": 1.0},
|
||
{"id": "box_006", "pos": [-16.0, 0.0, 8.0], "rot_y_deg": 0.0, "scale": 1.0},
|
||
# Wand-Ersatz für die „Stufe 0.8 m blockt"-Probe: 0.85 m hoch —
|
||
# über der Step-Up-Grenze (0.45 m) → muss blocken. Steht AUF der
|
||
# 0.3-Ebene (Terrain bei x=2 ist 0.3), Fußpunkt-Konvention.
|
||
{"id": "barrel_001", "pos": [2.0, 0.3, 20.0], "rot_y_deg": 0.0, "scale": 1.0},
|
||
],
|
||
"spawn_zones": {
|
||
"0": {"points": [
|
||
{"id": "A1", "pos": [-30.0, 0.0, -30.0]}, {"id": "A2", "pos": [-28.0, 0.0, -20.0]},
|
||
{"id": "A3", "pos": [-26.0, 0.0, 20.0]}, {"id": "A4", "pos": [-24.0, 0.0, 10.0]},
|
||
]},
|
||
"1": {"points": [
|
||
{"id": "B1", "pos": [30.0, 0.0, -30.0]}, {"id": "B2", "pos": [28.0, 0.0, -20.0]},
|
||
{"id": "B3", "pos": [26.0, 0.0, 20.0]}, {"id": "B4", "pos": [24.0, 0.0, 10.0]},
|
||
]},
|
||
},
|
||
"bounds": {"min": [-32.0, -5.0, -32.0], "max": [32.0, 20.0, 32.0]},
|
||
"weather": "mittag",
|
||
}
|
||
var path := OS.get_environment("SVR_IDENTITAET_MAP")
|
||
if path.is_empty():
|
||
path = "/tmp/svr_identitaet_probe.svmap"
|
||
var fa := FileAccess.open(path, FileAccess.WRITE)
|
||
if fa == null:
|
||
printerr("IDENT_GEN FAIL: kann nicht schreiben: " + path)
|
||
quit(1)
|
||
return
|
||
fa.store_string(JSON.stringify(doc))
|
||
fa.close()
|
||
print("IDENT_MAP=%s" % path)
|
||
quit(0)
|