- 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
60 lines
1.6 KiB
GDScript
60 lines
1.6 KiB
GDScript
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()
|