P4 hazards: food spoilage with rot speed setting, smoking rack and salt, food poisoning, harsher blizzards, hard winters with lake ice, lightning on trees, snow on roofs (protocol 11)

This commit is contained in:
Paul Bailey
2026-11-05 11:49:13 +00:00
parent 657c3140fe
commit 3389ec9a21
27 changed files with 1541 additions and 56 deletions

View File

@@ -82,9 +82,27 @@ func set_stack(stack) -> void:
_wear_fill.anchor_right = k
_wear_fill.color = Color(0.85, 0.25, 0.2) if k < 0.2 else (Color(0.9, 0.75, 0.25) if k < 0.5 else Color(0.45, 0.8, 0.35))
tooltip_text += "\n%d of %d uses left" % [left, full]
elif stack.has("rot") and Inventory.keeps_for(String(stack.id)) > 0.0:
# Food: a bar that runs down green to brown as it goes off.
var k := Inventory.freshness(stack)
_wear.visible = true
_wear_fill.anchor_right = maxf(k, 0.04)
_wear_fill.color = Color(0.45, 0.8, 0.35).lerp(Color(0.5, 0.33, 0.15), 1.0 - k)
tooltip_text += "\n" + freshness_text(stack)
else:
_wear.visible = false
## "Fresh", "Going off (about 9 hours left)", "Nearly rotten (2 hours left)".
static func freshness_text(stack) -> String:
var k := Inventory.freshness(stack)
var h := Inventory.hours_left(stack)
var left := ("%d hours left" % roundi(h)) if h < 48.0 else ("%d days left" % roundi(h / 24.0))
if k > 0.6:
return "Fresh (%s)" % left
if k > 0.2:
return "Going off (%s)" % left
return "Nearly rotten (%s)" % left
func set_selected(on: bool) -> void:
add_theme_stylebox_override("panel", _selected_style if on else _style)

View File

@@ -8,6 +8,9 @@ const WORLD_SCENE := "res://scenes/world.tscn"
var _pages: Dictionary = {} ## name -> Control
var _name_edit: LineEdit
var _seed_edit: LineEdit
var _rot_pick: OptionButton
## [setting, what the New World page calls it]
const ROT_CHOICES := [["normal", "Normally (raw meat lasts 2 days)"], ["slow", "Slowly (twice as long)"], ["off", "Never"]]
var _list: VBoxContainer
var _armed_delete := ""
@@ -181,6 +184,7 @@ func _show(page: String) -> void:
elif page == "new":
_name_edit.text = _unique_name()
_seed_edit.text = ""
_rot_pick.select(0)
_name_edit.grab_focus()
_name_edit.select_all()
@@ -571,6 +575,12 @@ func _new_page() -> Control:
_seed_edit.custom_minimum_size = Vector2(360, 40)
_seed_edit.text_submitted.connect(func(_t): _create())
v.add_child(_seed_edit)
v.add_child(UITheme.label("Food spoils", 15, UITheme.TEXT_DIM))
_rot_pick = OptionButton.new()
for t in ROT_CHOICES:
_rot_pick.add_item(t[1])
_rot_pick.custom_minimum_size = Vector2(360, 36)
v.add_child(_rot_pick)
var h := HBoxContainer.new()
h.add_theme_constant_override("separation", 10)
h.add_child(_button("Create & Play", _create, 170))
@@ -660,7 +670,8 @@ func _create() -> void:
world_name = _unique_name()
var seed_text := _seed_edit.text.strip_edges()
var seed := int(seed_text) if seed_text.is_valid_int() else (seed_text.hash() if not seed_text.is_empty() else randi())
_play(Saves.create_world(world_name, seed))
var rot: String = ROT_CHOICES[maxi(_rot_pick.selected, 0)][0]
_play(Saves.create_world(world_name, seed, {"rot": rot}))
func _play(id: String) -> void:
Saves.current_id = id