16 Commits

Author SHA1 Message Date
67862a46f3 Add boot flow, save-system skeleton, and Equipment skeleton
boot/: opening_screen (attribution -> title/flavor text placeholder,
explicitly marked TODO for a later real cinematic, skippable by
keypress/click) -> main_menu (Neues Spiel/Fortsetzen/Optionen/Credits/
Beenden, ConfirmationDialog for overwrite-existing-save) -> options_menu
(TabContainer with 4 empty placeholder categories: Grafik/Sound/
Steuerung/Spieloptionen) and credits_screen, both just navigable stubs.
project.godot's run/main_scene now points at boot/opening_screen.tscn
instead of directly at the gameplay scene.

autoload/save_manager.gd: new SaveManager singleton. Deliberately
minimal — persists only a timestamp to user://savegame.json — but a
real, working has_save()/save_game()/load_game()/start_new_game()
round trip, enough to back the menu's Start/Continue/overwrite-confirm
logic without inventing game state that doesn't exist yet.

player/equipment/: Equipment (Node) + EquipmentItem (Resource) stub
classes per the user's explicit ask for a "class diagram skeleton" to
build on later — exported fields and empty TODO methods, no logic.
Wired as a child of world/island.tscn's real Player (not player.tscn,
which is only a debug prototype scene, not the actual game's player).
player.gd's new `equipment` onready var uses get_node_or_null() since
that child only exists on the real player, not every scene reusing
this script.

Verified headless: all new boot scenes load cleanly, a full boot smoke
test via run/main_scene succeeds, and — since button-click navigation
can't be simulated headlessly — SaveManager's actual save/load/
overwrite/cleanup cycle was exercised directly and behaves correctly
(has_save flips true/false correctly, loaded data matches what was
saved). Manual in-editor check of the menu navigation itself is still
needed and not yet done.
2026-08-27 09:21:15 +02:00
c6d7e6c84e Restructure project into boot/autoload/world/player folders
Flat root layout replaced with a domain-based structure:
- autoload/    the two existing singleton scripts (InteractionManager,
               InteractionUI) — grouped by role, matching project.godot's
               [autoload] section
- world/       the flying island: terrain.gd, and world/poi/ for the POI
               marker + gate scripts/scenes
- player/      everything about the player as a character: player.gd/.tscn,
               camera_rig.gd (it only exists to follow the player)
- boot/        created empty for now, will hold the opening/menu screens

main.tscn renamed to world/island.tscn — "main" stops making sense once
the actual run/main_scene becomes a boot screen (next commit). Verified
via grep that main.tscn was referenced nowhere else by path (only by UID
elsewhere, which self-heals).

Every .gd got its .uid sidecar moved alongside it. Two ext_resource
entries had no UID (poi_gate.tscn's own script ref, and island.tscn's
ref to poi_gate.tscn) and needed their path= fixed by hand; everything
else is UID-based and resolved itself after a project reimport.

Also removed two untracked-looking but actually committed editor temp
files (preview_scene.tscn*.tmp, leftovers from the unused hterrain
addon, referenced nowhere).

Verified headless: all 8 affected scenes (island, poi, poi_gate,
player, interaction_ui, and the three debug prototypes that reference
moved files) load with exit code 0. No behavior change, pure move.
2026-08-27 09:18:17 +02:00
865b91cdef Move gate out of the mountain hitboxes blocking it
Placing the gate right at the table-edge chord meant it landed inside
the overlapping border-prop hitboxes there (measured: they reach out
to radius ~14.9 at that angle, the gate was at 13.2 — actually
overlapping by ~0.45 units). Moved it out to radius 16 along the same
30° bisector, just past where the border wall's hitboxes end.

Verified headless by measuring actual distances: closest border-prop
hitbox edge is now 1.9 units clear of the gate's own trigger radius.
2026-08-26 21:42:37 +02:00
b430d929c5 Rework the gate: smaller, right at the border, locked until ready, Yes/No prompt
- Moved GateToCenter to sit right on the region-1/center table-edge
  border (angle 30° bisector, radius ~13.2, where that edge's chord
  actually sits) instead of a few units inside the region, and scaled
  the instance down to 0.5x.
- target_position now lands just past the border on the table side
  (radius ~11.5 at the same angle) instead of teleporting to the
  absolute island center — "you walked through the gate," not "you
  warped across the map."
- Gate is now genuinely non-interactive while locked: no prompt shown,
  _input() doesn't even check for the key press, and the marker shows
  "Verschlossen" instead of its real name (mirrors poi.gd's existing
  "???" pattern for undiscovered POIs).
- Once unlocked, interacting opens a "Durchgehen?" Ja/Nein menu
  instead of teleporting immediately. Added
  InteractionManager.handle_interaction_action() delegation so POIs
  can own custom menu actions without hardcoding them into the shared
  manager.

Verified headless: locked state hides the prompt and shows
"Verschlossen"; unlocking (all 6 region1_pois visited) restores the
real name and prompt; "Nein" leaves the player position untouched;
"Ja" moves the player to exactly target_position.
2026-08-26 21:38:27 +02:00
c20d71f043 Billboard POI sprites so they face the camera on rotation
poi.tscn/poi_gate.tscn's AnimatedSprite3D had no billboard mode set
(default: disabled, fixed orientation in world space), so POI markers
would appear to rotate/distort as the step-rotating camera moved
around them. Set billboard = 2 (Y-locked), matching the convention
already used for the player's own AnimatedSprite3D.

Verified headless: POI, Ort1, and GateToCenter instances all report
billboard mode 2 at runtime.
2026-08-26 21:32:08 +02:00
72bc3a6553 Add invisible edge barrier and fix an out-of-bounds POI
We only ever built the inner region-to-region borders, never a wall
at the island's own outer rim (girdle) — nothing stopped the player
walking off into the (collision-less) pavilion below. Added
_build_edge_barrier(): 6 invisible BoxShape3D walls along the girdle
chords.

Also found the actual bug behind "one POI is outside": a facet's true
outer boundary is a straight hexagon chord, not an arc, so its usable
radius varies with angle — girdle_radius only at the two corners,
dropping to girdle_radius*cos(30°) (~87%) at the facet's own bisector.
Ort6 was placed at exactly the bisector angle with radius 44, just
past the true edge (~43.3 there) despite being "inside" the naive
[table_radius, girdle_radius] range. Moved it to angle 38°/radius 36,
comfortable inside the true boundary at that angle.

Verified headless: pushing the player outward with constant velocity
for 3 simulated seconds pins it at radius 42.64 (never crosses the
~43.3 true edge), settled and on_floor=true throughout. Re-verified
the POI/gate group logic still passes after moving Ort6.
2026-08-26 21:17:13 +02:00
92f220e208 Populate the first region: 6 placeholder POIs + gated center portal
poi.tscn now uses the checkerboard debug texture instead of the ruins
sprite, and poi.gd gained a marker_color export (multiplied into the
existing visited/undiscovered dimming) so each POI marker can be
tinted a distinct color. Six instances placed inside region k=0's
wedge (angle ~12-48°, radius ~18-38, clear of the border walls),
tagged with the "region1_pois" group, in red/orange/yellow/green/
blue/purple.

Simplified InteractionManager's "Erkunden" content to a plain
placeholder ("Das wurde besucht.") instead of the old random
animal-track flavor text, and removed the now-dead handle_explore()
submenu it drove. Added InteractionManager.open_message() for POIs
that need an info popup without the explore/rest/close menu.

New poi_gate.gd/.tscn: a portal placed near region k=0's table-edge
border. Checks whether every POI in "region1_pois" has been visited;
if not, shows a "not yet" message, otherwise teleports the player to
target_position (the center) — a one-way shortcut past the border
wall rather than an opening in it, matching the "explore everything,
then unlock the way onward" progression the user described (this
pattern will repeat per outer region later).

Verified headless: all 6 POIs register in the group with correct
names/colors, gate refuses the transition at 0/6 and 5/6 visited and
allows it at 6/6, and the teleport lands the player exactly on
target_position.
2026-08-26 21:05:38 +02:00
37e0151988 Wall off the table's own 6 edges too, not just the outer ridges
_build_region_borders() previously only bordered the 6 seams between
adjacent outer regions (table corner -> girdle corner). Generalized
_build_ridge() into _build_border_segment(p0, p1), which chains
overlap-guaranteed props along any straight 3D segment, and reused it
for the 6 table edges (table corner -> next table corner) as well —
these separate the center region from each outer region.

Verified headless the same way as the ridges: 43/43 pairs on one
table edge genuinely overlap (worst case -0.13 units). 744 border
props total across all 12 edges now.
2026-08-26 20:46:52 +02:00
eac8fdf042 Replace guesswork border spacing with a real overlap check
_build_ridge() now picks each prop's real-world collision radius
(shape radius * scale, same values as elsewhere in main.tscn) and
places it so its hitbox is guaranteed to overlap the previous one's
(border_overlap=0.8 of the combined radii), correcting the step
iteratively since the facet is sloped so distance isn't purely
radial. Lateral jitter shrunk to 0.05 so it can't itself exceed the
smallest possible combined radius (two forest props) and break the
guarantee.

Verified headless by measuring actual 3D distance between every
consecutive pair of props on one ridge against their combined radii:
83/83 pairs genuinely overlap, worst case still -0.13 units of
overlap (no gap anywhere). 504 border props total across all 6
ridges (was 142 with the old fixed-spacing approach).
2026-08-26 20:40:03 +02:00
2ab62278c6 Fix border prop spacing (was leaving massive gaps)
The random step jitter in _build_region_borders() was still ±4.0, a
constant left over from before the island rescale — at the new
border_spacing of 3.5 that could produce near-zero or even negative
steps as often as it produced 7.5-unit gaps, independent of position
along the ridge (hence gaps showing up near the center too, just by
bad luck). Jitter is now proportional to border_spacing (±25%), and
spacing itself tightened to 1.5 for a denser wall.

Verified headless: 142 border props total, max gap along one ridge
now ~1.9 units (was up to 7.5), consistent from table edge to girdle.
2026-08-26 20:11:22 +02:00
e547fbe199 Rescale island to match player/prop scale, spawn in an outer region
Island geometry (table/girdle/crown/pavilion radii, border spacing)
scaled down ~5x. The player capsule, camera distance and mountain/
forest scale factors were already correctly tuned to the small world
scale established elsewhere in main.tscn; the island itself was the
outlier (girdle radius 260 vs. a ~0.5-tall player), making border
props and the player look like specks. Shrinking the island was the
smaller change versus rescaling every already-tuned system.

Player now spawns partway out on one outer facet (region) instead of
on the center table, so a walk toward the middle is an actual journey
around/through the outer regions rather than starting there.

Verified headless with a physics simulation on the new sloped spawn
point: player settles and stays on_floor=true, no fall-through.
2026-08-26 20:06:47 +02:00
4b21780f6d Fix player falling through terrain
Player gets its own CapsuleShape3D (was a small CylinderShape3D, never
actually shared with anything — the shared oversized capsule flagged
earlier only affects the 4 mountain props, unrelated to the player).

Real cause of the fall-through: the crown collision is a zero-thickness
trimesh and the player spawned with exactly zero clearance sitting
right on the surface, a classic tunneling setup. Fixed by giving the
trimesh backface_collision (collide from both sides) and spawning the
player with a bit of headroom so it settles onto the floor instead of
starting embedded in it. Verified headless: player now falls from
spawn height to rest exactly on the surface and stays on_floor=true
over a 3s simulated run.
2026-08-26 19:58:28 +02:00
817c701bd1 Bring the diamond island into main.tscn with region-border props
Promote debug/HexDiamondIsland.gd to terrain.gd at project root now
that main.tscn depends on it, and swap it in for the old flat
checkerboard Ground (Player/Camera/POI untouched, table sits at the
same y=0 the old ground surface used).

Add _build_region_borders(): places mountain.glb/mountain2v5.glb/
forest.glb (same models, scale factors and hitbox sizes already used
elsewhere in main.tscn) continuously along the 6 ridges between table
corners and girdle corners, i.e. the shared edges between adjacent
outer regions.
2026-08-26 19:53:08 +02:00
fb14fe868d Ignore unused zylann.hterrain addon
Not referenced by any scene and too large to push (native binaries +
doc images, ~19MB). Kept on disk locally; re-fetch it if HTerrain is
ever actually adopted.
2026-08-26 19:36:54 +02:00
7a24584c7d Add hex-diamond island terrain prototype
New standalone debug prototype exploring the "gem-cut" flying island
shape: a flat hexagonal table (center region) surrounded by 6 sloped
trapezoidal facets down to the girdle (6 outer regions), with a
non-walkable 6-sided pavilion pyramid below for the underside. Crown
gets trimesh collision for later player testing; all 6 outer facets
stay visually neutral (alternating flat color only) since theming
comes later. Doesn't touch main.tscn or the old cross-layout prototype.
2026-08-26 19:26:07 +02:00
fa38e603a1 Initial commit: WayfarersWanderer project state
Godot 4.6 exploration game with player movement, step-rotation camera
rig, and POI interaction system (explore/rest/close menu). main.tscn
is a test scene with placeholder props; debug/ holds unwired terrain
prototypes (voxel river, procedural island mesh, cross-shaped hub
2026-08-26 19:05:30 +02:00