From 6dfba1b5b96da36917b0fa8d183e8963a3f19590 Mon Sep 17 00:00:00 2001 From: Dustin Date: Thu, 10 Apr 2025 22:39:48 -0700 Subject: [PATCH] Stamina callback to player to decide transition. --- lib/components/Stamina_Component.gd | 13 +++++ .../playerE/PlayerE-Movement_StateReceiver.gd | 28 ++++++--- src/actors/players/playerE/PlayerE.gd | 57 ++++++++++++++----- src/actors/players/playerE/PlayerE.tscn | 1 + 4 files changed, 76 insertions(+), 23 deletions(-) diff --git a/lib/components/Stamina_Component.gd b/lib/components/Stamina_Component.gd index b4db627..dc182ed 100644 --- a/lib/components/Stamina_Component.gd +++ b/lib/components/Stamina_Component.gd @@ -2,11 +2,24 @@ class_name StaminaComponent extends Node export var max_stamina: int = 0 +## Recovery Rate in units per second +export var recovery_rate: int = 0 onready var stamina :int = max_stamina signal stamina_depleted() +var recovery_counter: float = 0 + + +func _process(delta): + recovery_counter += delta + if recovery_rate != 0: + var _rate :float = 1.0/float(recovery_rate) + if recovery_counter > _rate: ## Divide by zero warning + recover(1) + recovery_counter = 0 + func reduce_stamina(_amount :int): if _amount < 0: push_error("ERROR: Only positive numbers in stamina component functions.") diff --git a/src/actors/players/playerE/PlayerE-Movement_StateReceiver.gd b/src/actors/players/playerE/PlayerE-Movement_StateReceiver.gd index 23c47ce..529c619 100644 --- a/src/actors/players/playerE/PlayerE-Movement_StateReceiver.gd +++ b/src/actors/players/playerE/PlayerE-Movement_StateReceiver.gd @@ -1,6 +1,7 @@ extends Movement_StateReceiver var parent_request_state_change :FuncRef +var parent_use_primary_item :FuncRef var player_number: int = 1 @@ -17,6 +18,10 @@ func _ready(): #TODO Should probably assert here or something. state_ref.connect("state_entered", self, "_on_state_entered_" + state_name) parent_request_state_change = funcref(get_node(callable_state_machine), 'check_parent_before_state_change') + + if parent.has_method("use_primary_item"): + parent_use_primary_item = funcref(parent, "use_primary_item") + # Lets see if this nutty thing works # var state_ref :State = get_node(callable_state_machine).get_state_reference('idle') # state_ref.connect("state_entered", self, "_on_state_entered_idle") @@ -80,11 +85,11 @@ func wants_dash() -> bool: var _wants_roll :bool func wants_roll() -> bool: if Input.is_action_just_pressed("dash_" + str(player_number)) and Input.is_action_pressed("move_up_" + str(player_number)): - _wants_roll = true - return true - else: - _wants_roll = false - return false + if parent.enough_stamina_for("roll"): + _wants_roll = true + return true + _wants_roll = false + return false var _wants_climb :bool func wants_climb() -> bool: @@ -154,15 +159,20 @@ func _state_process_physics_idle(): func attack_primary(): ##Another thing I wish I could avoid the funcref or string call - if get_parent().has_method("primary_item"): - var _item_state_name :String = get_parent().primary_item() +# if get_parent().has_method("use_primary_item"): +# var _item_state_name :String = get_parent().use_primary_item() +# if _item_state_name != '': +# request_state_change.call_func(_item_state_name) + if parent_use_primary_item.is_valid(): + var _item_state_name :String = parent_use_primary_item.call_func() if _item_state_name != '': request_state_change.call_func(_item_state_name) + func attack_secondary(): - if get_parent().has_method("secondary_item"): - var _item_state_name :String = get_parent().secondary_item() + if get_parent().has_method("use_secondary_item"): + var _item_state_name :String = get_parent().use_secondary_item() if _item_state_name != '': request_state_change.call_func(_item_state_name) diff --git a/src/actors/players/playerE/PlayerE.gd b/src/actors/players/playerE/PlayerE.gd index 6557ddc..245cb30 100644 --- a/src/actors/players/playerE/PlayerE.gd +++ b/src/actors/players/playerE/PlayerE.gd @@ -14,7 +14,10 @@ var punch_item :Item = preload("res://assets/items/punch.tres") const state_stamina_cost :Dictionary = { "jump": 10, - "attack_sword":20 + "attack_sword":20, + "attack_punch":10, + "roll":40, + "ledge_climb":10 } # Called when the node enters the scene tree for the first time. @@ -31,16 +34,16 @@ func _ready(): movement_component.state_stamina_cost = state_stamina_cost -var stamina_recovery :float = 0.0 +#var stamina_recovery :float = 0.0 # Called every frame. 'delta' is the elapsed time since the previous frame. func _process(delta): PlayerInfo.player_position = global_position.round() - stamina_recovery += delta - if stamina_recovery > 1.0: - stamina_component.recover(1) - stamina_recovery = 0.0 - #print("recover ", stamina_component.stamina) +# stamina_recovery += delta +# if stamina_recovery > 1.0: +# stamina_component.recover(1) +# stamina_recovery = 0.0 +# #print("recover ", stamina_component.stamina) PlayerInfo.player_stamina = stamina_component.stamina @@ -89,6 +92,15 @@ func touch_the_thing(the_thing: Interactable) -> bool: the_thing.trigger_interaction() return true +func enough_stamina_for(_state_name :String) -> bool: + if state_stamina_cost.has(_state_name): + if stamina_component.stamina >= state_stamina_cost[_state_name]: + return true + else: + return false + ## Return true by default because we don't have a cost for this move + return true + var state_to_item_map :Dictionary = { "sword": "attack_sword" , "gun": "attack_shoot", @@ -97,7 +109,7 @@ var state_to_item_map :Dictionary = { } ##TODO: We need to find a way to 'use' the item. -func primary_item() -> String: +func use_primary_item() -> String: # if player_inventory.primary_selection.consumable == false: # if state_to_item_map.has(player_inventory.primary_selection.name): # player_inventory.remove_from_inventory(player_inventory.primary_selection) @@ -106,18 +118,33 @@ func primary_item() -> String: if player_inventory.primary_selection != null: # Have to make sure we even have a second var _item_name :String = player_inventory.primary_selection.name if state_to_item_map.has(_item_name): + var state_name = state_to_item_map[_item_name] + ## This item state has a cost associated with it. + if state_stamina_cost.has(state_name): + if state_stamina_cost[state_name] <= stamina_component.stamina: + #print("Yup: ", state_stamina_cost[state_name], "<=", stamina_component.stamina) + player_inventory.remove_from_inventory(player_inventory.primary_selection) + return state_to_item_map[_item_name] + else: + ## TODO: maybe some sort of 'fail' animation state + print("Nope: ", state_stamina_cost[state_name], "<=", stamina_component.stamina) + return '' ## you can't use this player_inventory.remove_from_inventory(player_inventory.primary_selection) return state_to_item_map[_item_name] return '' -func secondary_item() -> String: +func use_secondary_item() -> String: if player_inventory.secondary_selection != null: # Have to make sure we even have a second var _item_name :String = player_inventory.secondary_selection.name if state_to_item_map.has(_item_name): - player_inventory.remove_from_inventory(player_inventory.secondary_selection) - return state_to_item_map[_item_name] - + var state_name = state_to_item_map[_item_name] + if enough_stamina_for(state_name): + player_inventory.remove_from_inventory(player_inventory.secondary_selection) + return state_to_item_map[_item_name] + else: + ## TODO: maybe some sort of 'fail' animation state + return '' return '' #func check_state_change(_new_state_name: String) -> bool: @@ -133,5 +160,7 @@ func secondary_item() -> String: func _on_Movement_StateMachine_state_changed(old_state_name, new_state): - if new_state.name == "jump": - stamina_component.reduce_stamina(state_stamina_cost["jump"]) +# if new_state.name == "jump": +# stamina_component.reduce_stamina(state_stamina_cost["jump"]) + if state_stamina_cost.has(new_state.name): + stamina_component.reduce_stamina(state_stamina_cost[new_state.name]) diff --git a/src/actors/players/playerE/PlayerE.tscn b/src/actors/players/playerE/PlayerE.tscn index 871db73..5a75540 100644 --- a/src/actors/players/playerE/PlayerE.tscn +++ b/src/actors/players/playerE/PlayerE.tscn @@ -138,6 +138,7 @@ max_health = 100 [node name="Stamina_Component" parent="." index="9" instance=ExtResource( 29 )] unique_name_in_owner = true max_stamina = 50 +recovery_rate = 5 [node name="Hurtbox_Component" parent="." index="10" instance=ExtResource( 16 )] collision_layer = 16