I have a “battler” that has a readiness value and it ticks up every physics process. Once it hits 100 the game pauses and waits for an action to be chosen and then resumes.
This works for the player when they pick an action through the menu. But for the AI (or if I try to not use the menu for the player) they don’t reset like they should. Even though I use the exact same signal that gets emitted when an action button is pressed.
Things I’ve Done:
I first thought that the readiness variable wasn’t getting reset, but it was.
Then I thought maybe it wasn’t unpausing correctly but it is.
The opponent is selecting a move and it is firing the signal and using the move
If I take away the menu from the player and try to have it pick randomly it also just sits there without resetting
If I add the menu to the opponent it works as it should
There is no code in the menu that touches anything outside of itself other than when it sends the signal from the BattleManager autoload script
I do have my code on GitHub I’m not sure I’m explaining it well enough… I’ve been stuck on this single problem for three days now. My rubber duck is tired of listening to me repeat myself.
This is the code of the action button
extends TextureButton
@onready var icon: TextureRect = $HBoxContainer/Icon
@onready var label: Label = $HBoxContainer/Label
var action_resource : Action
func _ready() -> void:
icon.texture = action_resource.action_icon #Set icon based on resource
label.text = action_resource.action_name #Set name based on resource
func _on_pressed() -> void:
#action_resource._on_press()
BattleManager.action_chosen.emit(action_resource)
This is the code of the turn manager system where the difference between a player and the AI is:
func _play_turn(battler: Battler):
#TODO: Add fatigue system
_pause(true) #Pause all of the battlers
if battler.battler_resource.is_player: #If battler is player
is_player_turn = true
ui_menu.setup(battler.battler_resource) #Setup menu for the player
ui_menu.show()#Show the player's menu
else: #Opponent AI Turn
is_player_turn = false
#Just pick action randomly
var random_move = battler.battler_resource.action_list.pick_random()
BattleManager.action_chosen.emit(random_move)
Can you post the code for the signal’s receiver? (I know you have the github link but this way I don’t have to find it).
Have you tried putting breakpoints into the _play_turn method and signal receivers and stepping through with F11? You can see the scoped variables and their values while doing this, it might help you find the problem.
Here is the function that gets called by the signal…
func _action_chosen(action):
var formulas = Formulas.new() #Create instance of the formulas for use
var dmg = 0 #Create variable to hold damage amount
if is_player_turn:
ui_menu.hide() #Hide the menu
dmg = formulas.calculate_base_damage(battle.player_chaomon, battle.opponent_chaomon, action)
battle.opponent_chaomon._take_damage(dmg)
_reset(_player) #Reset readiness for player
else:
dmg = formulas.calculate_base_damage(battle.opponent_chaomon, battle.player_chaomon, action)
battle.player_chaomon._take_damage(dmg)
_reset(_opponent) #Reset readiness for opponent
_pause(false) #Unpause all of the battlers
This is the reset function… Even with the enemy when it does its actions it does reset the readiness. So I know its going through the functions.
func _reset(battler):
battler._readiness = 0.0 #Set readiness back to 0.0
print(battler.battler_resource.chaomon_name)
print(battler._readiness)
battler.pause(false) #Make sure they aren't paused
Just so it is here, this is the battler code where the _readiness runs
func _physics_process(delta: float) -> void:
if battler_resource and !_paused: #If the resource is correct and not paused
_set_readiness(_readiness + battler_resource.base_speed * delta * _timescale) #Set the readiness
#Sets the readiness of the Chaomon
func _set_readiness(value: float) -> void: #Set the readiness of the Battler
_readiness = value #Set readiness
readiness_changed.emit(_readiness) #Emit the new readiness
if !battler_resource.is_player:
print(battler_resource.chaomon_name)
print(_readiness)
if _readiness >= 100.0: #If battler is ready to act
ready_to_act.emit() #Signal that battler is ready to act
pause(true)
else:
pause(false)
Have you tried putting breakpoints into the _play_turn method and signal receivers and stepping through with F11? You can see the scoped variables and their values while doing this, it might help you find the problem.
I haven’t done breakpoints, I didn’t know you could do them, but I’ve put print statements and looked at the tree to see what the variables are doing and they were fine but I’ll try doing it step by step to see if there is something else going on.
Breakpoints helped… It was a problem with where I had a pause function. I don’t know why when using a button it somehow skipped over that pause function call but it works now.
Thank you so much! The breakpoints is a Godsend. I should have remembered from my old C++ days.
Glad I could (sort of) help. Given how quickly you can iterate in Godot, breakpoints have very quickly become my first step in a lot of debugging situations. There are actually two ways to use them in GDScript as well - you can click the margin (or hit F9) in the Script editor as you would in any other IDE or you can use the breakpoint keyword in your script. I’ve not found much use for the second option yet but it’s good to know about.