M1c: weather, snap building, shelter, beds and regrowth
- 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
This commit is contained in:
@@ -11,6 +11,7 @@ extends Node3D
|
||||
signal prompt_changed(text: String)
|
||||
|
||||
const Campfire = preload("res://scripts/building/campfire.gd")
|
||||
const BuildPiece = preload("res://scripts/building/build_piece.gd")
|
||||
const REACH := 3.2
|
||||
const PLACE_REACH := 6.0
|
||||
const SWING_TIME := 0.5
|
||||
@@ -26,6 +27,7 @@ var _ghost_bad_mat: StandardMaterial3D
|
||||
var _ghost_yaw := 0.0
|
||||
var _place_xf := Transform3D()
|
||||
var _place_ok := false
|
||||
var _place_reason := ""
|
||||
var _prompt := ""
|
||||
var _held_shown := "~"
|
||||
var _torch_light: OmniLight3D
|
||||
@@ -123,6 +125,8 @@ func _target() -> Object:
|
||||
if not _ray.is_colliding():
|
||||
return null
|
||||
var c := _ray.get_collider()
|
||||
if c != null and c.has_meta("owner_piece"):
|
||||
c = c.get_meta("owner_piece") # a door's moving panel
|
||||
if c == null or not c.has_method("interact_prompt"):
|
||||
return null
|
||||
if c.get("depleted") == true:
|
||||
@@ -138,7 +142,8 @@ func _physics_process(delta: float) -> void:
|
||||
var def := _held_def()
|
||||
if def.has("place"):
|
||||
_update_ghost(def)
|
||||
_set_prompt("[LMB] Place %s [R] Rotate" % def.name)
|
||||
var why := "" if _place_ok or _place_reason.is_empty() else " (%s)" % _place_reason
|
||||
_set_prompt("[LMB] Place %s [R] Rotate%s" % [def.name, why])
|
||||
return
|
||||
_ghost.visible = false
|
||||
if _torch_light.visible:
|
||||
@@ -146,7 +151,10 @@ func _physics_process(delta: float) -> void:
|
||||
_torch_light.light_energy = float(def.get("light", {}).get("energy", 1.5)) * (0.85 + 0.15 * sin(_t * 17.0) * sin(_t * 5.3))
|
||||
var t := _target()
|
||||
if t != null:
|
||||
_set_prompt(t.interact_prompt(player))
|
||||
var p: String = t.interact_prompt(player)
|
||||
if t.is_in_group("piece") and t.item_id != "grave":
|
||||
p += " [X] Dismantle"
|
||||
_set_prompt(p)
|
||||
elif def.has("food"):
|
||||
_set_prompt("[RMB] Eat %s" % def.name)
|
||||
else:
|
||||
@@ -163,8 +171,16 @@ func _update_ghost(def: Dictionary) -> void:
|
||||
_place_ok = false
|
||||
return
|
||||
var yaw := player.rotation.y + _ghost_yaw # piece's front (+Z) faces the player
|
||||
_place_xf = Transform3D(Basis(Vector3.UP, yaw), hit.position)
|
||||
_place_ok = player.get_parent().placement_valid(def, _place_xf)
|
||||
if BuildPiece.is_build(def):
|
||||
# Building pieces snap to what's already built (build_system.gd).
|
||||
var res: Dictionary = player.get_parent().build.placement(def, hit, yaw)
|
||||
_place_xf = res.xf
|
||||
_place_ok = res.ok
|
||||
_place_reason = res.reason
|
||||
else:
|
||||
_place_xf = Transform3D(Basis(Vector3.UP, yaw), hit.position)
|
||||
_place_ok = player.get_parent().placement_valid(def, _place_xf)
|
||||
_place_reason = "" if _place_ok else "blocked or too steep"
|
||||
_ghost.global_transform = _place_xf
|
||||
_ghost.material_override = _ghost_ok_mat if _place_ok else _ghost_bad_mat
|
||||
_ghost.visible = true
|
||||
@@ -185,7 +201,12 @@ func _unhandled_input(event: InputEvent) -> void:
|
||||
if _held_def().has("food"):
|
||||
Actions.eat(player, player.selected)
|
||||
elif event.is_action_pressed("rotate_piece"):
|
||||
_ghost_yaw += deg_to_rad(22.5)
|
||||
# Building pieces turn in quarter turns (they snap to a grid).
|
||||
_ghost_yaw += deg_to_rad(90.0 if BuildPiece.is_build(_held_def()) else 22.5)
|
||||
elif event.is_action_pressed("dismantle"):
|
||||
var t := _target()
|
||||
if t != null and t.is_in_group("piece"):
|
||||
Actions.dismantle(player, t)
|
||||
elif event.is_action_pressed("interact"):
|
||||
var t := _target()
|
||||
if t != null and t.has_method("interact"):
|
||||
|
||||
Reference in New Issue
Block a user