feat: let the player live as a citizen with needs and carried inventory

This commit is contained in:
Rijad Zuzo
2026-08-11 00:18:39 +02:00
parent f72aa659d2
commit 37f262fb84
20 changed files with 746 additions and 90 deletions
+1
View File
@@ -4,6 +4,7 @@ extends RefCounted
const KIND_ANIMAL := &"animal"
const KIND_RESOURCE := &"resource"
const KIND_PANTRY := &"pantry"
const KIND_STORAGE_DEPOSIT := &"storage_deposit"
const KIND_GUARD := &"guard"
const KIND_STUDY := &"study"
+90 -10
View File
@@ -11,6 +11,7 @@ signal interaction_feedback(heading: String, message: String, succeeded: bool)
@export var world_view_manager: Node
@export var pantry_storage: StorageNode
@export var woodpile_storage: StorageNode
@export var guard_site: ActivitySite
@export var study_site: ActivitySite
@@ -81,6 +82,8 @@ func try_interact() -> void:
)
PlayerInteractionResult.KIND_PANTRY:
_execute_pantry_interaction(context)
PlayerInteractionResult.KIND_STORAGE_DEPOSIT:
_execute_deposit_interaction(context)
func get_interaction_context() -> PlayerInteractionResult:
@@ -113,7 +116,12 @@ func get_interaction_context() -> PlayerInteractionResult:
study_site
)
if is_near_storage(pantry_storage):
if _get_carried_food() > 0.0:
return _build_deposit_context(SimulationIds.RESOURCE_FOOD, pantry_storage)
return _build_pantry_context()
if woodpile_storage != null and is_near_storage(woodpile_storage):
if _get_carried_wood() > 0.0:
return _build_deposit_context(SimulationIds.RESOURCE_WOOD, woodpile_storage)
return null
@@ -346,10 +354,15 @@ func _build_resource_context(node: ResourceNode) -> PlayerInteractionResult:
func _build_pantry_context() -> PlayerInteractionResult:
var pantry_food := _get_pantry_food()
var blocked_reason := "" if pantry_food > 0.0 else "The village pantry is empty."
var carried_food := _get_carried_food()
var blocked_reason := ""
var detail := "%.0f food available" % pantry_food
if not blocked_reason.is_empty():
detail = "Pantry empty"
if pantry_food <= 0.0 and carried_food < 1.0:
blocked_reason = "The village pantry is empty and you carry no food."
detail = "Pantry empty · carry nothing"
elif pantry_food <= 0.0:
blocked_reason = "The village pantry is empty."
detail = "Pantry empty · carry %.0f food" % carried_food
return PlayerInteractionResult.new(
PlayerInteractionResult.KIND_PANTRY,
SimulationIds.ACTION_EAT,
@@ -362,6 +375,29 @@ func _build_pantry_context() -> PlayerInteractionResult:
)
func _build_deposit_context(
resource_id: StringName, storage_node: StorageNode
) -> PlayerInteractionResult:
var resource_name := String(resource_id).capitalize()
var carried := (
_get_carried_food() if resource_id == SimulationIds.RESOURCE_FOOD else _get_carried_wood()
)
var action_id := (
SimulationIds.ACTION_DEPOSIT_FOOD
if resource_id == SimulationIds.RESOURCE_FOOD
else SimulationIds.ACTION_DEPOSIT_WOOD
)
return PlayerInteractionResult.new(
PlayerInteractionResult.KIND_STORAGE_DEPOSIT,
action_id,
storage_node.storage_id,
storage_node.display_name,
"Deposit %s" % resource_name.to_lower(),
"%s · carrying %.0f" % [storage_node.display_name, carried],
storage_node
)
func _execute_animal_interaction(context: PlayerInteractionResult) -> void:
var node := context.target_node as AnimalNode
if node == null or not context.is_available():
@@ -401,10 +437,12 @@ func _execute_resource_interaction(context: PlayerInteractionResult) -> void:
"%s is unavailable" % context.display_name, "Nothing could be gathered.", false
)
return
var destination := "pantry" if node.resource_id == SimulationIds.RESOURCE_FOOD else "woodpile"
interaction_feedback.emit(
"%s gathered" % String(node.resource_id).capitalize(),
"%.1f moved to the village %s." % [extracted, destination],
(
"%.1f added to your pack — deposit it at the %s."
% [extracted, _storage_name_for(node.resource_id)]
),
true
)
@@ -413,12 +451,42 @@ func _execute_pantry_interaction(context: PlayerInteractionResult) -> void:
if not context.is_available():
interaction_feedback.emit("The pantry is empty", context.blocked_reason, false)
return
var food_before := _get_pantry_food()
simulation_manager.eat_food(stomach_capacity_for_food)
var consumed := food_before - _get_pantry_food()
interaction_feedback.emit(
"Ate from the pantry", "%.0f village food consumed." % consumed, consumed > 0.0
if not simulation_manager.has_method("eat_player_food"):
push_error("Player: SimulationManager cannot consume player food")
return
if simulation_manager.eat_player_food():
interaction_feedback.emit("Ate", "Hunger eased from carried or pantry food.", true)
return
interaction_feedback.emit("Nothing to eat", "The village pantry is empty.", false)
func _execute_deposit_interaction(context: PlayerInteractionResult) -> void:
if not simulation_manager.has_method("deposit_player_inventory"):
push_error("Player: SimulationManager cannot deposit player inventory")
return
var resource_id := (
SimulationIds.RESOURCE_FOOD
if context.action_id == SimulationIds.ACTION_DEPOSIT_FOOD
else SimulationIds.RESOURCE_WOOD
)
var deposited: float = simulation_manager.deposit_player_inventory(resource_id)
var resource_name := String(resource_id).capitalize()
if deposited <= 0.0:
interaction_feedback.emit(
"%s not stored" % resource_name,
"The %s is full." % context.display_name.to_lower(),
false
)
return
interaction_feedback.emit(
"%s stored" % resource_name,
"%.0f moved to the %s." % [deposited, context.display_name.to_lower()],
true
)
func _storage_name_for(resource_id: StringName) -> String:
return "village pantry" if resource_id == SimulationIds.RESOURCE_FOOD else "village woodpile"
func _get_animal_feed_cost() -> float:
@@ -433,6 +501,18 @@ func _get_pantry_food() -> float:
return pantry.get_amount(SimulationIds.RESOURCE_FOOD) if pantry != null else 0.0
func _get_carried_food() -> float:
if not simulation_manager.has_method("get_player_state"):
return 0.0
return simulation_manager.get_player_state().get_inventory_amount(SimulationIds.RESOURCE_FOOD)
func _get_carried_wood() -> float:
if not simulation_manager.has_method("get_player_state"):
return 0.0
return simulation_manager.get_player_state().get_inventory_amount(SimulationIds.RESOURCE_WOOD)
func is_near_storage(storage_node: StorageNode) -> bool:
if storage_node == null:
return false