fix six critical bugs from audit sprint
save/load round-trip: workbench bills, crop static-method, bed owner, wolf target now all survive reload via Bill.from_dict reconstruction, _spawn_crop using setup(), and a new _post_load_resolve_references pass. PlantProvider: sow path added; consumes 1 grain on a TILLED crop tile. CraftingProvider: ingredient2 supported via new KIND_DEPOSIT_AT_WB toil and Workbench.deposited_inputs buffer. Cremation pyre now actually consumes wood. HaulingProvider: per-item haul_retry_count + haul_rejected after 3 orphan passes; new EventBus.stockpile_layout_changed resets rejects on any player stockpile edit. Storyteller: 14 stubbed event effects implemented. New buff registry (add_buff/get_buff_multiplier/has_buff, day-prune, save/load) drives seasonal/resource events. New request_pawn_spawn signal + WANDERER table for arrivals. New SICK status + 3 mood thoughts. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
00cf8f445d
commit
d9638a4ea4
19 changed files with 711 additions and 101 deletions
|
|
@ -115,6 +115,8 @@ func tick() -> void:
|
|||
_tick_pickup_corpse(t)
|
||||
Toil.KIND_DEPOSIT_CORPSE:
|
||||
_tick_deposit_corpse(t)
|
||||
Toil.KIND_DEPOSIT_AT_WB:
|
||||
_tick_deposit_at_wb(t)
|
||||
|
||||
if t.done:
|
||||
job.advance()
|
||||
|
|
@ -365,13 +367,46 @@ func _tick_deposit(t) -> void:
|
|||
t.done = true
|
||||
|
||||
|
||||
## Execute one tick of a DEPOSIT_AT_WB toil.
|
||||
##
|
||||
## Single-tick: transfers pawn.carried_item into the workbench's deposited_inputs
|
||||
## buffer (wb.add_deposited_input) without spawning the item on the floor.
|
||||
## This is leg-1 of a two-ingredient craft; leg-2 fetches ingredient2, then
|
||||
## _tick_craft validates the buffer before beginning the work countdown.
|
||||
##
|
||||
## Fails silently (t.done = true) if workbench is gone or pawn has nothing.
|
||||
func _tick_deposit_at_wb(t) -> void:
|
||||
var wb_path := NodePath(t.data.get("workbench", ""))
|
||||
var wb = get_tree().get_root().get_node_or_null(wb_path)
|
||||
if wb == null or not is_instance_valid(wb):
|
||||
Audit.log("job_runner", "%s deposit_at_wb: workbench gone — skipping" % pawn.pawn_name)
|
||||
t.done = true
|
||||
return
|
||||
if pawn.carried_item == null:
|
||||
Audit.log("job_runner", "%s deposit_at_wb: nothing to deposit" % pawn.pawn_name)
|
||||
t.done = true
|
||||
return
|
||||
var item = pawn.carried_item
|
||||
wb.add_deposited_input(item.item_type, item.stack_size)
|
||||
Audit.log(
|
||||
"job_runner",
|
||||
"%s deposit_at_wb: %s ×%d → workbench buffer" % [pawn.pawn_name, item.item_type, item.stack_size]
|
||||
)
|
||||
item.queue_free()
|
||||
pawn.carried_item = null
|
||||
t.done = true
|
||||
|
||||
|
||||
## Execute one tick of a CRAFT toil.
|
||||
##
|
||||
## First tick (started=false):
|
||||
## - Resolves the Workbench node from the stored NodePath. Missing → skip.
|
||||
## - Looks up the Bill at data["bill_index"]. Out-of-range → skip.
|
||||
## - Validates pawn position matches workbench.tile. Mismatch → skip.
|
||||
## - Validates pawn is carrying the correct ingredient type. Missing → skip.
|
||||
## - For recipes with ingredient_type: validates pawn is carrying it OR (for
|
||||
## two-ingredient recipes) validates wb.deposited_inputs has ingredient1
|
||||
## and pawn is carrying ingredient2.
|
||||
## - For no-ingredient recipes (ingredient_type == &""): no carry check.
|
||||
## - Calls wb.begin_craft(bill) to register the active bill + reset progress.
|
||||
## - Marks started=true and logs the craft start.
|
||||
##
|
||||
|
|
@ -379,7 +414,8 @@ func _tick_deposit(t) -> void:
|
|||
## - Calls wb.tick_craft() which increments current_work_progress and returns
|
||||
## true when bill.recipe.work_ticks is reached.
|
||||
## - On completion:
|
||||
## * Consumes the carried ingredient (queue_free + clear pawn slot).
|
||||
## * Consumes pawn.carried_item (ingredient or ingredient2); queue_free + clear.
|
||||
## * For two-ingredient recipes, also calls wb.consume_deposited_input for ing1.
|
||||
## * Rolls quality via QualityCalc.roll() using the pawn's skill level.
|
||||
## * Spawns an Item scene child of wb.get_parent() at wb.tile.
|
||||
## * Calls wb.on_craft_complete() (records bill completion + resets state).
|
||||
|
|
@ -414,13 +450,39 @@ func _tick_craft(t) -> void:
|
|||
t.done = true
|
||||
return
|
||||
|
||||
if pawn.carried_item == null or pawn.carried_item.item_type != bill.recipe.ingredient_type:
|
||||
Audit.log(
|
||||
"job_runner",
|
||||
"%s craft: wrong or missing ingredient — skipping" % pawn.pawn_name
|
||||
)
|
||||
t.done = true
|
||||
return
|
||||
# Ingredient validation — three cases:
|
||||
# (a) No primary ingredient (ingredient_type == &""): skip carry checks.
|
||||
# (b) Single ingredient: pawn must be carrying ingredient_type.
|
||||
# (c) Two ingredients: wb.deposited_inputs must hold ingredient1,
|
||||
# pawn must be carrying ingredient2.
|
||||
var has_primary: bool = bill.recipe.ingredient_type != &""
|
||||
var has_secondary: bool = bill.recipe.ingredient2_type != &""
|
||||
if has_primary:
|
||||
if has_secondary:
|
||||
# Two-ingredient path: check buffer (ing1) + carry (ing2).
|
||||
if not wb.has_deposited_input(bill.recipe.ingredient_type, 1):
|
||||
Audit.log(
|
||||
"job_runner",
|
||||
"%s craft: ingredient1 not in workbench buffer — skipping" % pawn.pawn_name
|
||||
)
|
||||
t.done = true
|
||||
return
|
||||
if pawn.carried_item == null or pawn.carried_item.item_type != bill.recipe.ingredient2_type:
|
||||
Audit.log(
|
||||
"job_runner",
|
||||
"%s craft: wrong or missing ingredient2 — skipping" % pawn.pawn_name
|
||||
)
|
||||
t.done = true
|
||||
return
|
||||
else:
|
||||
# Single-ingredient path: pawn carries ingredient1.
|
||||
if pawn.carried_item == null or pawn.carried_item.item_type != bill.recipe.ingredient_type:
|
||||
Audit.log(
|
||||
"job_runner",
|
||||
"%s craft: wrong or missing ingredient — skipping" % pawn.pawn_name
|
||||
)
|
||||
t.done = true
|
||||
return
|
||||
|
||||
# Register the bill with the workbench and reset its progress counter.
|
||||
wb.begin_craft(bill)
|
||||
|
|
@ -450,11 +512,18 @@ func _tick_craft(t) -> void:
|
|||
return
|
||||
var bill = wb.bills[bill_index]
|
||||
|
||||
# Consume ingredient.
|
||||
# Consume ingredients.
|
||||
# Single-ingredient: pawn.carried_item holds the only input — free it.
|
||||
# Two-ingredient: pawn.carried_item is ingredient2; ingredient1 was buffered
|
||||
# in wb.deposited_inputs by _tick_deposit_at_wb — remove it from the buffer.
|
||||
# No-ingredient: carried_item is null; nothing to consume.
|
||||
var ingredient = pawn.carried_item
|
||||
pawn.carried_item = null
|
||||
if ingredient != null and is_instance_valid(ingredient):
|
||||
ingredient.queue_free()
|
||||
if bill.recipe.ingredient2_type != &"":
|
||||
# ingredient2 was the carried item (consumed above); ingredient1 is in the buffer.
|
||||
wb.consume_deposited_input(bill.recipe.ingredient_type, 1)
|
||||
|
||||
# Roll quality based on pawn skill for this recipe.
|
||||
var skill_level: int = pawn.get_skill(bill.recipe.required_skill)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue