extends Node3D ## The tutorial's hut outline (docs/TUTORIAL_DESIGN.md ยง2, step 17): a pale, ## see-through 4 x 4 m hut on a good spot near your fire, the same 20 pieces ## the game's own snapping makes (floors, walls and a door, roofs, gables). ## Each piece of the outline fades out once a real piece of that kind stands ## in its place. It's a suggestion: you can build anywhere. ## [item, offset from the first floor, yaw] (from build_system.gd ## debug_build_hut at yaw 0: the pieces snap to a fixed grid). const LAYOUT := [ ["wood_floor", Vector3(0, 0, 0), 0.0], ["wood_floor", Vector3(2, 0, 0), 0.0], ["wood_floor", Vector3(0, 0, 2), 0.0], ["wood_floor", Vector3(2, 0, 2), 0.0], ["wood_wall", Vector3(0, 0, -1), 0.0], ["wood_wall", Vector3(0, 0, 3), 0.0], ["wood_wall", Vector3(2, 0, -1), 0.0], ["wood_door", Vector3(2, 0, 3), 0.0], ["wood_wall", Vector3(3, 0, 0), PI * 0.5], ["wood_wall", Vector3(-1, 0, 0), PI * 0.5], ["wood_wall", Vector3(3, 0, 2), PI * 0.5], ["wood_wall", Vector3(-1, 0, 2), PI * 0.5], ["wood_roof", Vector3(0, 2, 3), 0.0], ["wood_roof", Vector3(0, 2, -1), PI], ["wood_roof", Vector3(2, 2, 3), 0.0], ["wood_roof", Vector3(2, 2, -1), PI], ["wood_gable", Vector3(-1, 2, 2), PI * 0.5], ["wood_gable", Vector3(-1, 2, 0), -PI * 0.5], ["wood_gable", Vector3(3, 2, 2), PI * 0.5], ["wood_gable", Vector3(3, 2, 0), -PI * 0.5], ] const MATCH := 0.35 ## a real piece this close to a slot fills it var world: Node3D var origin := Transform3D() ## the first floor's place var slots: Array = [] ## [item, Transform3D, MeshInstance3D] var _check := 0.0 ## Lays the outline out with its first floor at `xf` (from build_system's ## free placement, so it sits level on the ground). func setup(w: Node3D, xf: Transform3D) -> void: world = w origin = xf var m := StandardMaterial3D.new() m.shading_mode = BaseMaterial3D.SHADING_MODE_UNSHADED m.transparency = BaseMaterial3D.TRANSPARENCY_ALPHA m.albedo_color = Color(0.6, 0.88, 1.0, 0.22) m.cull_mode = BaseMaterial3D.CULL_DISABLED m.no_depth_test = false for e in LAYOUT: var t := Transform3D(xf.basis * Basis(Vector3.UP, float(e[2])), xf * (e[1] as Vector3)) var mi := MeshInstance3D.new() mi.mesh = ItemDB.mesh_for(String(e[0])) mi.material_override = m mi.cast_shadow = GeometryInstance3D.SHADOW_CASTING_SETTING_OFF add_child(mi) mi.global_transform = t slots.append([String(e[0]), t, mi]) ## The middle of the hut (the guide's marker points here). func center() -> Vector3: return origin * Vector3(1, 0, 1) func _process(delta: float) -> void: _check -= delta if _check <= 0.0: _check = 0.5 refresh() ## Hides each slot a real piece of its kind now fills. Returns how many are ## left to build. func refresh() -> int: var left := 0 var built: Array = world.build.build_pieces() if world != null else [] for s in slots: var filled := false for p in built: if p.item_id == s[0] and (p as Node3D).global_position.distance_to((s[1] as Transform3D).origin) < MATCH: filled = true break (s[2] as MeshInstance3D).visible = not filled if not filled: left += 1 return left