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:
@@ -29,6 +29,11 @@ var rng := RandomNumberGenerator.new()
|
||||
|
||||
var _shake := 0.0
|
||||
var _shake_axis := Vector3.RIGHT
|
||||
var _stump: MeshInstance3D
|
||||
var _orig_shapes: Array = [] ## [CollisionShape3D, shape, position] before the stump
|
||||
|
||||
## Emitted when a player fells or mines this (not when a save restores it).
|
||||
signal depleted_now(node: Node)
|
||||
|
||||
func display_name() -> String:
|
||||
return "Tree" if kind == "tree" else "Boulder"
|
||||
@@ -107,7 +112,36 @@ func _deplete(from: Vector3, animate: bool = true) -> void:
|
||||
else:
|
||||
if animate:
|
||||
_burst(global_position + Vector3(0, 0.8, 0), chip_color, 40)
|
||||
queue_free()
|
||||
# Kept (hidden, no collision) so it can regrow later.
|
||||
set_process(false)
|
||||
remove_from_group("harvestable")
|
||||
if animate:
|
||||
depleted_now.emit(self)
|
||||
|
||||
## Brings a felled tree or mined boulder back, growing in over a few seconds.
|
||||
func regrow() -> void:
|
||||
if not depleted:
|
||||
return
|
||||
depleted = false
|
||||
hp = max_hp
|
||||
if _stump != null:
|
||||
_stump.queue_free()
|
||||
_stump = null
|
||||
for e in _orig_shapes:
|
||||
e[0].shape = e[1]
|
||||
e[0].position = e[2]
|
||||
_orig_shapes.clear()
|
||||
if has_meta("is_stump"):
|
||||
remove_meta("is_stump")
|
||||
collision_layer = 1
|
||||
add_to_group("harvestable")
|
||||
set_process(true)
|
||||
if is_inside_tree() and DisplayServer.get_name() != "headless":
|
||||
var tw := create_tween()
|
||||
tw.tween_method(func(k: float): _set_instance(Transform3D(base_xf.basis.scaled_local(Vector3.ONE * k), base_xf.origin)),
|
||||
0.15, 1.0, 4.0).set_trans(Tween.TRANS_SINE)
|
||||
else:
|
||||
_set_instance(base_xf)
|
||||
|
||||
func _fell(from: Vector3, animate: bool) -> void:
|
||||
var world := get_parent()
|
||||
@@ -139,9 +173,11 @@ func _make_stump(world: Node) -> void:
|
||||
stump.material_override = stump_material
|
||||
world.add_child(stump)
|
||||
stump.global_position = base_xf.origin
|
||||
_stump = stump
|
||||
# Keep collision as a short stump.
|
||||
for c in get_children():
|
||||
if c is CollisionShape3D and c.shape is CapsuleShape3D:
|
||||
_orig_shapes.append([c, c.shape, c.position])
|
||||
var cyl := CylinderShape3D.new()
|
||||
cyl.radius = (c.shape as CapsuleShape3D).radius
|
||||
cyl.height = 0.6
|
||||
|
||||
Reference in New Issue
Block a user