wire buff consumers, sick penalty, multi-count cremation

A: Storyteller.multiply_drops() stochastic-rounding helper drives
crop_growth, harvest_yield, chop, mine consumption sites. sleep_decay
multiplied in Pawn sleep tick.

B: Pawn._sick_speed_penalty() (0% healthy → 75% severity 3, clamped to
25% min speed). JobRunner._work_speed_mult coin-flips per-tick progress
on INTERACT/BUILD/CRAFT toils. Sleep/eat/treat unaffected.

C: CraftingProvider builds N deposit trips for ingredient2_count > 1.
JobRunner._tick_craft validates+consumes the full count from buffer.
Cremation now actually requires and consumes 5 wood.

crop._stage_accum round-trips through save/load to preserve buff-
accumulated fractional growth.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
megaproxy 2026-05-16 18:17:29 +01:00
parent d9638a4ea4
commit 2afca16299
9 changed files with 156 additions and 46 deletions

View file

@ -403,6 +403,18 @@ func _on_sim_tick_buffs(_tick: int) -> void:
_prune_expired_buffs()
## Stochastic rounding for fractional drop counts.
## Converts a float drop amount to an int: floor(amt) drops are guaranteed;
## the fractional remainder is a probability of one extra drop. This way a
## multiplier of 1.25 on a base of 4 yields 5 drops 25% of the time and 4
## drops 75% of the time — expected value exactly matches the multiplier.
static func multiply_drops(base: int, mult: float) -> int:
var raw: float = float(base) * mult
var guaranteed: int = int(floor(raw))
var frac: float = raw - float(guaranteed)
return guaranteed + (1 if randf() < frac else 0)
## Convert a Category enum value to the snake-case StringName used in
## CATEGORY_COOLDOWN_DAYS and _category_last_fired.
func _category_to_str(cat: EventDef.Category) -> StringName: