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:
parent
d9638a4ea4
commit
2afca16299
9 changed files with 156 additions and 46 deletions
|
|
@ -49,6 +49,10 @@ const _STAGE_H: int = 32
|
|||
var stage: Stage = Stage.SOWN
|
||||
## Progress within the current growth stage; 0..STAGE_TICKS.
|
||||
var stage_progress: int = 0
|
||||
## Float accumulator for sub-tick growth when crop_growth buff is active.
|
||||
## Carries fractional progress between ticks so the buff has the correct
|
||||
## expected-value effect even though stage_progress is stored as int.
|
||||
var _stage_accum: float = 0.0
|
||||
|
||||
# Phase 13 — "no growth indoors" rule. True once we've logged the first
|
||||
# indoor detection for this crop instance so we don't flood the audit log.
|
||||
|
|
@ -106,9 +110,11 @@ func on_harvest_tick() -> void:
|
|||
if not is_harvestable():
|
||||
return
|
||||
var item_type := _harvest_output_for(crop_kind)
|
||||
var base_qty: int = 1
|
||||
var drop_qty: int = Storyteller.multiply_drops(base_qty, Storyteller.get_buff_multiplier(&"harvest_yield"))
|
||||
var it: Item = ITEM_SCENE.instantiate()
|
||||
get_parent().add_child(it)
|
||||
it.setup(item_type, 1, tile)
|
||||
it.setup(item_type, drop_qty, tile)
|
||||
# Carry the crop_kind through as a visual subtype so wheat / corn /
|
||||
# potato / strawberry each render distinctly, while item_type stays
|
||||
# generic (TYPE_GRAIN / TYPE_VEGETABLE) for stockpile filter purposes.
|
||||
|
|
@ -149,7 +155,13 @@ func _on_sim_tick(_n: int) -> void:
|
|||
# Crop has moved outdoors or was never indoors — reset the log flag so a
|
||||
# future re-roofing produces another audit line.
|
||||
_logged_indoor = false
|
||||
stage_progress += 1
|
||||
# Apply crop_growth buff: accumulate fractional progress each tick so the
|
||||
# expected-value growth rate exactly matches the multiplier.
|
||||
var growth_mult: float = Storyteller.get_buff_multiplier(&"crop_growth")
|
||||
_stage_accum += growth_mult
|
||||
var whole: int = int(floor(_stage_accum))
|
||||
_stage_accum -= float(whole)
|
||||
stage_progress += whole
|
||||
if stage_progress >= STAGE_TICKS:
|
||||
stage_progress = 0
|
||||
stage = (int(stage) + 1) as Stage
|
||||
|
|
@ -169,6 +181,7 @@ func to_dict() -> Dictionary:
|
|||
"crop_kind": String(crop_kind),
|
||||
"stage": int(stage),
|
||||
"stage_progress": stage_progress,
|
||||
"stage_accum": _stage_accum,
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -182,6 +195,7 @@ static func from_dict(d: Dictionary) -> Dictionary:
|
|||
"crop_kind": StringName(d.get("crop_kind", "wheat")),
|
||||
"stage": int(d.get("stage", Stage.SOWN)),
|
||||
"stage_progress": int(d.get("stage_progress", 0)),
|
||||
"stage_accum": float(d.get("stage_accum", 0.0)),
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue