- Seeded weather (clear/cloudy/rain/storm, snow and blizzards on cold days and above the snowline), lightning, synthesised rain/wind/thunder sound - Rain/snow particles stopped by roofs; wet ground, settled snow and wind via global shader uniforms - Snap-together wood floor, wall, door, roof and gable with structural support, collapse and X to dismantle - Shelter detection: dry under a roof, warmer and Rested inside with a fire; rain burns an uncovered campfire faster - Bed sets the spawn point and lets you sleep through the night - Trees, boulders and ground pickups regrow; timers saved - Grass cleared under floors; shorter HUD hint - New test_weather_building suite (62 checks) and tests/run_all.sh, which also fails on script errors
62 lines
1.9 KiB
GDScript
62 lines
1.9 KiB
GDScript
extends "res://scripts/building/build_piece.gd"
|
|
## Wooden door: a wall-sized frame (snaps like a wall) with a hinged panel.
|
|
## E opens or closes it. The panel is an AnimatableBody3D so it pushes the
|
|
## player out of the way rather than trapping them.
|
|
|
|
const OPEN_ANGLE := 1.75 ## radians: swings toward -Z, away from where you stood to place it
|
|
|
|
var open := false
|
|
var _hinge: Node3D
|
|
var _panel: AnimatableBody3D
|
|
var _tween: Tween
|
|
|
|
func _visual_mesh() -> Mesh:
|
|
return ItemDB.mesh_for("wood_door_frame")
|
|
|
|
func _build() -> void:
|
|
_hinge = Node3D.new()
|
|
_hinge.name = "Hinge"
|
|
_hinge.position = Vector3(-0.54, 0.0, 0.0)
|
|
add_child(_hinge)
|
|
_panel = AnimatableBody3D.new()
|
|
_panel.name = "Panel"
|
|
# Follow the hinge directly (sync_to_physics would only track the body's
|
|
# own motion, not its parent rotating).
|
|
_panel.sync_to_physics = false
|
|
_panel.collision_layer = 1 | BUILD_LAYER
|
|
_panel.set_meta("owner_piece", self)
|
|
_hinge.add_child(_panel)
|
|
var mi := MeshInstance3D.new()
|
|
mi.mesh = ItemDB.mesh_for("wood_door_panel")
|
|
mi.material_override = ItemDB.item_material()
|
|
_panel.add_child(mi)
|
|
var cs := CollisionShape3D.new()
|
|
var box := BoxShape3D.new()
|
|
box.size = Vector3(1.06, 1.86, 0.08)
|
|
cs.shape = box
|
|
cs.position = Vector3(0.54, 0.95, 0.0)
|
|
_panel.add_child(cs)
|
|
|
|
func interact_prompt(_player: Node) -> String:
|
|
return "Door [E] %s" % ("Close" if open else "Open")
|
|
|
|
func interact(player: Node) -> void:
|
|
Actions.toggle_door(player, self)
|
|
|
|
func set_open(on: bool, animate: bool = true) -> void:
|
|
open = on
|
|
var target := OPEN_ANGLE if on else 0.0
|
|
if _tween != null:
|
|
_tween.kill()
|
|
if animate and is_inside_tree():
|
|
_tween = create_tween()
|
|
_tween.tween_property(_hinge, "rotation:y", target, 0.45).set_trans(Tween.TRANS_SINE)
|
|
else:
|
|
_hinge.rotation.y = target
|
|
|
|
func save_extra() -> Dictionary:
|
|
return {"open": open}
|
|
|
|
func load_extra(d: Dictionary) -> void:
|
|
set_open(bool(d.get("open", false)), false)
|