Files
Cinderwild/scripts/ui/hut_outline.gd

75 lines
3.1 KiB
GDScript

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