Tutorial: Old Tam's hut outline beside the fire, pieces snap into it

This commit is contained in:
Paul Bailey
2026-11-05 15:01:59 +00:00
parent f93ebe1bea
commit dbcc6f6e59
6 changed files with 157 additions and 8 deletions

View File

@@ -36,6 +36,7 @@ var pieces_root: Node3D
var _hash: Dictionary = {} ## Vector3i -> Array of [piece, point]
var last_blocker: Object ## what the last failed overlap check hit (debugging)
var outline: Node3D = null ## the tutorial's hut outline, while it's up (placement snaps to it)
var _dirty := true
func setup(w: Node3D) -> void:
@@ -206,6 +207,15 @@ func placement(def: Dictionary, hit: Dictionary, yaw: float) -> Dictionary:
var info: Dictionary = BuildPiece.kinds()[kind]
var hp: Vector3 = hit.position
var cands := []
# The tutorial's hut outline (ui/hut_outline.gd): a piece aimed near an
# empty slot of its own kind goes there, like building to a plan.
if outline != null and is_instance_valid(outline):
for s in outline.slots:
if s[0] == String(def.id) and (s[2] as Node3D).visible:
var sxf: Transform3D = s[1]
var d := sxf.origin.distance_to(hp)
if d < 2.0:
cands.append([d * 0.3, sxf])
for piece in build_pieces():
if piece.global_position.distance_to(hp) > 4.5:
continue
@@ -394,16 +404,19 @@ func _hut_place(out: Dictionary, center: Vector3, yaw: float, id: String, local:
## A spot near `near` with a clear, fairly flat `half`-metre square: nothing
## solid in the way and the ground within 0.6 m across it. Searches outward
## in rings. Returns `near` itself if nothing is found.
func debug_find_site(near: Vector3, half: float) -> Vector3:
func debug_find_site(near: Vector3, half: float, step: float = 4.0, min_dist: float = 0.0) -> Vector3:
var space := world.get_world_3d().direct_space_state
var box := BoxShape3D.new()
box.size = Vector3(half * 2.0 + 2.0, 6.0, half * 2.0 + 2.0)
var ex: Array[RID] = [terrain.get_node("TerrainBody").get_rid(), world.player.get_rid()]
for ring in range(0, 12):
var rings := int(ceil(48.0 / step))
for ring in range(0, rings):
if ring * step < min_dist:
continue
var n := maxi(1, ring * 6)
for i in range(n):
var a := TAU * i / n
var c := near + Vector3(cos(a), 0, sin(a)) * ring * 4.0
var c := near + Vector3(cos(a), 0, sin(a)) * ring * step
if not terrain.inside_boundary(c.x, c.z, half + 4.0):
continue
var hs: Array[float] = []