P3 alpha: wolf moon every 7th night, the alpha breaks wooden doors, iron-banded door, broken-door repair, alpha pelt and cloak (protocol 7)

This commit is contained in:
Paul Bailey
2026-11-05 01:40:52 +00:00
parent 411bfef34a
commit fc58c8d0e1
18 changed files with 742 additions and 40 deletions

View File

@@ -1,17 +1,28 @@
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.
## 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.
##
## An alpha wolf can break a closed wooden door (bash()): after DOOR_HP worth
## of blows the panel gives way and hangs open, and the door shows as broken
## until you repair it (E, two wood). An iron-banded door (items.json
## place.sturdy) can't be broken. The frame stays either way, so whatever it
## holds up keeps standing.
const OPEN_ANGLE := 1.75 ## radians: swings toward -Z, away from where you stood to place it
const DOOR_HP := 100.0
const REPAIR_COST := {"wood": 2}
var open := false
var broken := false
var door_hp := DOOR_HP
var _hinge: Node3D
var _panel: AnimatableBody3D
var _panel_shape: CollisionShape3D
var _tween: Tween
func _visual_mesh() -> Mesh:
return ItemDB.mesh_for(String(def.get("mesh", item_id)) + "_frame") # (wood_door_frame, stone_door_frame)
return ItemDB.mesh_for(String(def.get("mesh", item_id)) + "_frame") # (wood_door_frame, stone_doorway_frame...)
func _build() -> void:
_hinge = Node3D.new()
@@ -27,23 +38,38 @@ func _build() -> void:
_panel.set_meta("owner_piece", self)
_hinge.add_child(_panel)
var mi := MeshInstance3D.new()
mi.mesh = ItemDB.mesh_for("wood_door_panel")
mi.mesh = ItemDB.mesh_for(String(def.place.get("panel", "wood_door_panel")))
mi.material_override = ItemDB.item_material()
_panel.add_child(mi)
var cs := CollisionShape3D.new()
_panel_shape = 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)
_panel_shape.shape = box
_panel_shape.position = Vector3(0.54, 0.95, 0.0)
_panel.add_child(_panel_shape)
## Iron-banded: nothing breaks it.
func sturdy() -> bool:
return bool(def.place.get("sturdy", false))
## Shut and in one piece (something trying to get in has to get past it).
func blocks() -> bool:
return not open and not broken
func interact_prompt(_player: Node) -> String:
if broken:
return "Broken door [E] Repair (2 wood)"
return "Door [E] %s" % ("Close" if open else "Open")
func interact(player: Node) -> void:
Actions.toggle_door(player, self)
if broken:
Actions.repair_door(player, self)
else:
Actions.toggle_door(player, self)
func set_open(on: bool, animate: bool = true) -> void:
if broken:
on = true # (it hangs open off one hinge)
open = on
var target := OPEN_ANGLE if on else 0.0
if _tween != null:
@@ -54,8 +80,46 @@ func set_open(on: bool, animate: bool = true) -> void:
else:
_hinge.rotation.y = target
## A blow from something trying to get in. Returns "hit", "held" (iron
## bands), "broke" (this blow broke it) or "" (open or already broken).
func bash(damage: float) -> String:
if not blocks():
return ""
if sturdy():
return "held"
door_hp -= damage
if door_hp > 0.0:
return "hit"
set_broken(true)
return "broke"
## Broken: the panel hangs open, askew, and stops anything. Repaired: shut
## and whole again.
func set_broken(on: bool) -> void:
broken = on
if on:
door_hp = 0.0
set_open(true, false)
_hinge.rotation = Vector3(0.0, OPEN_ANGLE + 0.35, 0.18)
_panel_shape.disabled = true
else:
door_hp = DOOR_HP
_hinge.rotation = Vector3.ZERO
_panel_shape.disabled = false
set_open(false, false)
func save_extra() -> Dictionary:
return {"open": open}
return {"open": open, "broken": broken}
func load_extra(d: Dictionary) -> void:
set_open(bool(d.get("open", false)), false)
set_broken(bool(d.get("broken", false)))
if not broken:
set_open(bool(d.get("open", false)), false)
## A server telling us this door's state: swing it if it only opened or
## closed, snap it if it broke or was mended.
func net_state(d: Dictionary) -> void:
if bool(d.get("broken", false)) != broken:
load_extra(d)
elif not broken:
set_open(bool(d.get("open", false)))