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)