M1b: survival stats, day/night, fire fuel, cooking, foraging, torches, death + grave
- Health, stamina, hunger, warmth and wet with HUD bars, status tags and clock - 20-minute day/night cycle with moon, stars and lit clouds - Campfire fuel (2 min start, 15 min max), heat radius, cooking needs a lit fire - Berry bushes (regrow 10 min), mushrooms, roasted mushroom, torch - Stamina costs for sprint, jump and harvest hits - Death respawns at island start and leaves a grave bag - Saves include stats, time of day, fire fuel, regrowth timers and graves - New test_survival_stats suite; tests fail if a script error aborts them
This commit is contained in:
59
scripts/world/forage.gd
Normal file
59
scripts/world/forage.gd
Normal file
@@ -0,0 +1,59 @@
|
||||
extends Area3D
|
||||
## A berry bush you can forage with E: berries plus some fiber. It's then bare
|
||||
## until it regrows (`regrow_seconds` of play time). Walk-through, on
|
||||
## collision layer 2 like pickups. Regrow timers are saved (props.forage).
|
||||
|
||||
const ItemMeshes = preload("res://scripts/items/item_meshes.gd")
|
||||
|
||||
var uid := ""
|
||||
var regrow_seconds := 600.0
|
||||
var regrow_left := 0.0 ## 0 = ripe
|
||||
var rng := RandomNumberGenerator.new()
|
||||
var _mesh: MeshInstance3D
|
||||
|
||||
func setup(material: Material) -> void:
|
||||
collision_layer = 2
|
||||
collision_mask = 0
|
||||
monitoring = false
|
||||
_mesh = MeshInstance3D.new()
|
||||
_mesh.material_override = material
|
||||
add_child(_mesh)
|
||||
var cs := CollisionShape3D.new()
|
||||
var sph := SphereShape3D.new()
|
||||
sph.radius = 0.7
|
||||
cs.shape = sph
|
||||
cs.position = Vector3(0, 0.5, 0)
|
||||
add_child(cs)
|
||||
_refresh()
|
||||
|
||||
func ripe() -> bool:
|
||||
return regrow_left <= 0.0
|
||||
|
||||
func _refresh() -> void:
|
||||
_mesh.mesh = ItemMeshes.build("berry_bush" if ripe() else "berry_bush_bare")
|
||||
|
||||
func _process(delta: float) -> void:
|
||||
if regrow_left > 0.0:
|
||||
regrow_left = maxf(regrow_left - delta, 0.0)
|
||||
if regrow_left <= 0.0:
|
||||
_refresh()
|
||||
|
||||
func interact_prompt(_player: Node) -> String:
|
||||
if ripe():
|
||||
return "Berry bush [E] Pick berries"
|
||||
return "Berry bush (regrowing, %d min)" % ceili(regrow_left / 60.0)
|
||||
|
||||
func interact(player: Node) -> void:
|
||||
Actions.forage(player, self)
|
||||
|
||||
## Called by Actions.forage. Returns what was picked.
|
||||
func harvest() -> Dictionary:
|
||||
if not ripe():
|
||||
return {}
|
||||
regrow_left = regrow_seconds
|
||||
_refresh()
|
||||
return {"berries": rng.randi_range(2, 4), "fiber": rng.randi_range(1, 2)}
|
||||
|
||||
func restore(left: float) -> void:
|
||||
regrow_left = left
|
||||
_refresh()
|
||||
Reference in New Issue
Block a user