Adding hunger mechanic
This commit is contained in:
@@ -15,6 +15,10 @@ class_name GridCharacterController
|
|||||||
@export_range(0.0, 200.0, 0.5) var movement_water_usage_ml_per_meter: float = 2.0
|
@export_range(0.0, 200.0, 0.5) var movement_water_usage_ml_per_meter: float = 2.0
|
||||||
@export_range(50.0, 2000.0, 50.0) var low_water_threshold_ml: float = 400.0
|
@export_range(50.0, 2000.0, 50.0) var low_water_threshold_ml: float = 400.0
|
||||||
@export_range(100.0, 2000.0, 25.0) var bladder_capacity_ml: float = 750.0
|
@export_range(100.0, 2000.0, 25.0) var bladder_capacity_ml: float = 750.0
|
||||||
|
@export_range(200.0, 6000.0, 50.0) var max_food_kcal: float = 2000.0
|
||||||
|
@export_range(0.0, 5.0, 0.1) var passive_food_usage_kcal_per_minute: float = 1.5
|
||||||
|
@export_range(0.0, 200.0, 0.5) var movement_food_usage_kcal_per_meter: float = 1.0
|
||||||
|
@export_range(50.0, 1000.0, 25.0) var low_food_threshold_kcal: float = 300.0
|
||||||
@export var vitals_display_path: NodePath
|
@export var vitals_display_path: NodePath
|
||||||
|
|
||||||
var _grid_manager: GridPlaneManager = null
|
var _grid_manager: GridPlaneManager = null
|
||||||
@@ -35,8 +39,10 @@ var _bladder_level_ml: float = 0.0
|
|||||||
var _needs_water: bool = false
|
var _needs_water: bool = false
|
||||||
var _needs_bathroom: bool = false
|
var _needs_bathroom: bool = false
|
||||||
var _returning_home_for_needs: bool = false
|
var _returning_home_for_needs: bool = false
|
||||||
|
var _food_level_kcal: float = 0.0
|
||||||
|
var _needs_food: bool = false
|
||||||
|
|
||||||
signal vitals_changed(water_level: float, bladder_level: float, needs_water: bool, needs_bathroom: bool)
|
signal vitals_changed(water_level: float, bladder_level: float, needs_water: bool, needs_bathroom: bool, food_level: float, needs_food: bool)
|
||||||
|
|
||||||
func get_water_level() -> float:
|
func get_water_level() -> float:
|
||||||
return _water_level_ml
|
return _water_level_ml
|
||||||
@@ -50,6 +56,12 @@ func is_water_low() -> bool:
|
|||||||
func is_bladder_full() -> bool:
|
func is_bladder_full() -> bool:
|
||||||
return _needs_bathroom
|
return _needs_bathroom
|
||||||
|
|
||||||
|
func get_food_level() -> float:
|
||||||
|
return _food_level_kcal
|
||||||
|
|
||||||
|
func is_food_low() -> bool:
|
||||||
|
return _needs_food
|
||||||
|
|
||||||
func _ready() -> void:
|
func _ready() -> void:
|
||||||
set_physics_process(true)
|
set_physics_process(true)
|
||||||
set_process_unhandled_input(true)
|
set_process_unhandled_input(true)
|
||||||
@@ -60,6 +72,7 @@ func _ready() -> void:
|
|||||||
_spawn_home()
|
_spawn_home()
|
||||||
_water_level_ml = max_water_ml
|
_water_level_ml = max_water_ml
|
||||||
_bladder_level_ml = 0.0
|
_bladder_level_ml = 0.0
|
||||||
|
_food_level_kcal = max_food_kcal
|
||||||
_update_awake_duration()
|
_update_awake_duration()
|
||||||
if _day_night_controller:
|
if _day_night_controller:
|
||||||
_last_time_hours = _day_night_controller.get_time_of_day_hours()
|
_last_time_hours = _day_night_controller.get_time_of_day_hours()
|
||||||
@@ -67,7 +80,7 @@ func _ready() -> void:
|
|||||||
_last_time_hours = 0.0
|
_last_time_hours = 0.0
|
||||||
_is_sleeping = false
|
_is_sleeping = false
|
||||||
_sleep_pending_return = false
|
_sleep_pending_return = false
|
||||||
emit_signal("vitals_changed", _water_level_ml, _bladder_level_ml, _needs_water, _needs_bathroom)
|
emit_signal("vitals_changed", _water_level_ml, _bladder_level_ml, _needs_water, _needs_bathroom, _food_level_kcal, _needs_food)
|
||||||
|
|
||||||
func _physics_process(delta: float) -> void:
|
func _physics_process(delta: float) -> void:
|
||||||
if not _is_moving:
|
if not _is_moving:
|
||||||
@@ -82,7 +95,7 @@ func _physics_process(delta: float) -> void:
|
|||||||
var step: float = move_speed * delta
|
var step: float = move_speed * delta
|
||||||
var move_vector: Vector3 = direction.normalized() * min(step, distance)
|
var move_vector: Vector3 = direction.normalized() * min(step, distance)
|
||||||
global_position += move_vector
|
global_position += move_vector
|
||||||
emit_signal("vitals_changed", _water_level_ml, _bladder_level_ml, _needs_water, _needs_bathroom)
|
emit_signal("vitals_changed", _water_level_ml, _bladder_level_ml, _needs_water, _needs_bathroom, _food_level_kcal, _needs_food)
|
||||||
|
|
||||||
func _unhandled_input(event: InputEvent) -> void:
|
func _unhandled_input(event: InputEvent) -> void:
|
||||||
if Engine.is_editor_hint():
|
if Engine.is_editor_hint():
|
||||||
@@ -197,7 +210,7 @@ func _update_home_position() -> void:
|
|||||||
_home_instance.global_position = world_center + Vector3.UP * 0.01
|
_home_instance.global_position = world_center + Vector3.UP * 0.01
|
||||||
|
|
||||||
func _should_ignore_player_input() -> bool:
|
func _should_ignore_player_input() -> bool:
|
||||||
return _is_sleeping or _sleep_pending_return or _needs_water or _needs_bathroom
|
return _is_sleeping or _sleep_pending_return or _needs_water or _needs_bathroom or _needs_food
|
||||||
|
|
||||||
func _handle_arrival_at_current_cell() -> void:
|
func _handle_arrival_at_current_cell() -> void:
|
||||||
if _current_cell == start_cell:
|
if _current_cell == start_cell:
|
||||||
@@ -211,6 +224,8 @@ func _on_arrived_home() -> void:
|
|||||||
if _needs_water:
|
if _needs_water:
|
||||||
_fill_water()
|
_fill_water()
|
||||||
_needs_water = false
|
_needs_water = false
|
||||||
|
if _needs_food:
|
||||||
|
_eat_food()
|
||||||
_returning_home_for_needs = false
|
_returning_home_for_needs = false
|
||||||
if _sleep_pending_return:
|
if _sleep_pending_return:
|
||||||
_enter_sleep_state()
|
_enter_sleep_state()
|
||||||
@@ -283,14 +298,14 @@ func _apply_passive_water_usage(delta_hours: float) -> void:
|
|||||||
if delta_hours <= 0.0:
|
if delta_hours <= 0.0:
|
||||||
return
|
return
|
||||||
var minutes := delta_hours * 60.0
|
var minutes := delta_hours * 60.0
|
||||||
var amount := minutes * passive_water_usage_ml_per_minute
|
_consume_water(minutes * passive_water_usage_ml_per_minute)
|
||||||
_consume_water(amount)
|
_consume_food(minutes * passive_food_usage_kcal_per_minute)
|
||||||
|
|
||||||
func _apply_movement_water_usage(distance: float) -> void:
|
func _apply_movement_water_usage(distance: float) -> void:
|
||||||
if distance <= 0.0:
|
if distance <= 0.0:
|
||||||
return
|
return
|
||||||
var usage := movement_water_usage_ml_per_meter * distance
|
_consume_water(movement_water_usage_ml_per_meter * distance)
|
||||||
_consume_water(usage)
|
_consume_food(movement_food_usage_kcal_per_meter * distance)
|
||||||
|
|
||||||
func _consume_water(amount: float) -> void:
|
func _consume_water(amount: float) -> void:
|
||||||
if amount <= 0.0:
|
if amount <= 0.0:
|
||||||
@@ -307,16 +322,32 @@ func _consume_water(amount: float) -> void:
|
|||||||
if not _returning_home_for_needs and not _sleep_pending_return:
|
if not _returning_home_for_needs and not _sleep_pending_return:
|
||||||
_returning_home_for_needs = true
|
_returning_home_for_needs = true
|
||||||
_request_home_return()
|
_request_home_return()
|
||||||
emit_signal("vitals_changed", _water_level_ml, _bladder_level_ml, _needs_water, _needs_bathroom)
|
emit_signal("vitals_changed", _water_level_ml, _bladder_level_ml, _needs_water, _needs_bathroom, _food_level_kcal, _needs_food)
|
||||||
|
|
||||||
|
func _consume_food(amount: float) -> void:
|
||||||
|
if amount <= 0.0:
|
||||||
|
return
|
||||||
|
_food_level_kcal = max(_food_level_kcal - amount, 0.0)
|
||||||
|
if _food_level_kcal <= low_food_threshold_kcal:
|
||||||
|
_needs_food = true
|
||||||
|
if not _returning_home_for_needs and not _sleep_pending_return:
|
||||||
|
_returning_home_for_needs = true
|
||||||
|
_request_home_return()
|
||||||
|
emit_signal("vitals_changed", _water_level_ml, _bladder_level_ml, _needs_water, _needs_bathroom, _food_level_kcal, _needs_food)
|
||||||
|
|
||||||
func _fill_water() -> void:
|
func _fill_water() -> void:
|
||||||
_water_level_ml = max_water_ml
|
_water_level_ml = max_water_ml
|
||||||
emit_signal("vitals_changed", _water_level_ml, _bladder_level_ml, _needs_water, _needs_bathroom)
|
emit_signal("vitals_changed", _water_level_ml, _bladder_level_ml, _needs_water, _needs_bathroom, _food_level_kcal, _needs_food)
|
||||||
|
|
||||||
func _empty_bladder() -> void:
|
func _empty_bladder() -> void:
|
||||||
_bladder_level_ml = 0.0
|
_bladder_level_ml = 0.0
|
||||||
_needs_bathroom = false
|
_needs_bathroom = false
|
||||||
emit_signal("vitals_changed", _water_level_ml, _bladder_level_ml, _needs_water, _needs_bathroom)
|
emit_signal("vitals_changed", _water_level_ml, _bladder_level_ml, _needs_water, _needs_bathroom, _food_level_kcal, _needs_food)
|
||||||
|
|
||||||
|
func _eat_food() -> void:
|
||||||
|
_food_level_kcal = max_food_kcal
|
||||||
|
_needs_food = false
|
||||||
|
emit_signal("vitals_changed", _water_level_ml, _bladder_level_ml, _needs_water, _needs_bathroom, _food_level_kcal, _needs_food)
|
||||||
|
|
||||||
func _request_home_return() -> void:
|
func _request_home_return() -> void:
|
||||||
if _is_sleeping:
|
if _is_sleeping:
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ class_name WaterDisplay
|
|||||||
|
|
||||||
@export var character_path: NodePath
|
@export var character_path: NodePath
|
||||||
@export var show_bladder: bool = true
|
@export var show_bladder: bool = true
|
||||||
|
@export var show_food: bool = true
|
||||||
@export var show_water: bool = true
|
@export var show_water: bool = true
|
||||||
|
|
||||||
var _character: GridCharacterController = null
|
var _character: GridCharacterController = null
|
||||||
@@ -13,11 +14,11 @@ func _ready() -> void:
|
|||||||
_resolve_character()
|
_resolve_character()
|
||||||
if _character:
|
if _character:
|
||||||
_character.vitals_changed.connect(_on_vitals_changed)
|
_character.vitals_changed.connect(_on_vitals_changed)
|
||||||
_on_vitals_changed(_character.get_water_level(), _character.get_bladder_level(), _character.is_water_low(), _character.is_bladder_full())
|
_on_vitals_changed(_character.get_water_level(), _character.get_bladder_level(), _character.is_water_low(), _character.is_bladder_full(), _character.get_food_level(), _character.is_food_low())
|
||||||
|
|
||||||
func _process(_delta: float) -> void:
|
func _process(_delta: float) -> void:
|
||||||
if Engine.is_editor_hint():
|
if Engine.is_editor_hint():
|
||||||
_update_text(0.0, 0.0, false, false)
|
_update_text(0.0, 0.0, false, false, 0.0, false)
|
||||||
|
|
||||||
func _resolve_character() -> void:
|
func _resolve_character() -> void:
|
||||||
if character_path != NodePath():
|
if character_path != NodePath():
|
||||||
@@ -25,13 +26,20 @@ func _resolve_character() -> void:
|
|||||||
else:
|
else:
|
||||||
_character = get_parent() as GridCharacterController
|
_character = get_parent() as GridCharacterController
|
||||||
|
|
||||||
func _on_vitals_changed(water_level: float, bladder_level: float, needs_water: bool, needs_bathroom: bool) -> void:
|
func _on_vitals_changed(water_level: float, bladder_level: float, needs_water: bool, needs_bathroom: bool, food_level: float, needs_food: bool) -> void:
|
||||||
_update_text(water_level, bladder_level, needs_water, needs_bathroom)
|
_update_text(water_level, bladder_level, needs_water, needs_bathroom, food_level, needs_food)
|
||||||
|
|
||||||
func _update_text(water_level: float, bladder_level: float, needs_water: bool, needs_bathroom: bool) -> void:
|
func _update_text(water_level: float, bladder_level: float, needs_water: bool, needs_bathroom: bool, food_level: float, needs_food: bool) -> void:
|
||||||
var parts: Array[String] = []
|
var parts: Array[String] = []
|
||||||
if show_water:
|
if show_water:
|
||||||
parts.append("Water: %4d ml%s" % [int(water_level), " !" if needs_water else ""])
|
parts.append("Water: %4d ml%s" % [int(water_level), " !" if needs_water else ""])
|
||||||
if show_bladder:
|
if show_bladder:
|
||||||
parts.append("Bladder: %4d ml%s" % [int(bladder_level), " !" if needs_bathroom else ""])
|
parts.append("Bladder: %4d ml%s" % [int(bladder_level), " !" if needs_bathroom else ""])
|
||||||
|
if show_food:
|
||||||
|
parts.append("Food: %4d kcal%s" % [int(food_level), " !" if needs_food else ""])
|
||||||
|
if show_food and parts.size() >= 3:
|
||||||
|
var first_line := " | ".join(parts.slice(0, 2))
|
||||||
|
var second_line := " | ".join(parts.slice(2, parts.size()))
|
||||||
|
text = first_line + "\n" + second_line
|
||||||
|
else:
|
||||||
text = " | ".join(parts)
|
text = " | ".join(parts)
|
||||||
|
|||||||
Reference in New Issue
Block a user