Godot Version
4.4.1
Question
I’m making an RPG similar to Final Fantasy, and I need the ATB bar to reset, but every time I click on an enemy, I get “Invalid call. Nonexistent function ‘highlight’ in base ‘Nil’.” and i did some debugging and figured out that the function _on_player_atb_read is only activating once when it should activate every time a ATB bar gets filled up. I think the reason why is that the code only connects one of the player bars’ signals instead of all 4
Here is all the code
ATB bar code
class_name ATBBar
extends ProgressBar
@onready var _anim: AnimationPlayer = $AnimationPlayer
const SPEED_BASE: float = 0.25
signal filled()
func _ready() -> void:
#choses a random value to se the ATB bar
_anim.play("RESET")
value = randf_range(min_value, max_value * 0.75)
func reset() -> void:
_anim.play("RESET")
value = min_value
set_process(true)
func _process(_delta: float) -> void:
#this increases the value every frame
value += SPEED_BASE
#this checks for when the value has reaced the max value
if is_equal_approx(value, max_value):
_anim.play("Highlight")
set_process(false)
#emits the signal
filled.emit()
Battle Code
extends Control
enum States {
OPTIONS,
TARGET
}
@onready var _options: = $Options
@onready var _optionsMenu: Menu = $Options/Options
@onready var _enemies: Menu = $Enemies
@onready var _players_info: Array = $GuiMargin/Windows/Players/MarginContainer/VBoxContainer.get_children()
var state: States = States.OPTIONS
var atbQueue: Array = []
var eventQueue: Array = []
func _ready() -> void:
_options.hide()
for player in _players_info:
player.atb_ready.connect(_on_player_atb_read.bind(player))
func _on_options_button_focused(_button: BaseButton) -> void:
pass
func _unhandled_input(event: InputEvent) -> void:
#activates when the esc is pressed
if event.is_action_pressed("ui_cancel"):
match state:
#it will do nothing if you are in options
States.OPTIONS:
pass
States.TARGET:
#will set the state back to options and but the focus back on fight
state = States.OPTIONS
_optionsMenu.button_focus()
func _on_options_button_pressed(button: BaseButton) -> void:
#this checks if the button is pressed by it's name going to be real might change it later
match button.text:
"Fight":
state = States.TARGET
_enemies.button_focus()
func _on_player_atb_read(player: BattlePlayerBar) -> void:
if atbQueue.is_empty():
player.highlight()
_options.show()
_optionsMenu.button_focus(0)
atbQueue.append(player)
print("happen")
print(player.name)
func advance_atb_queue() -> void:
var currentSelected: BattlePlayerBar = atbQueue.pop_front()
currentSelected.reset()
atbQueue.front().highlight()
func _on_players_button_pressed(_button: BaseButton) -> void:
state = States.OPTIONS
advance_atb_queue()
func _on_enemies_button_pressed(_button: BaseButton) -> void:
advance_atb_queue()
Battle Player Bar code
class_name BattlePlayerBar
extends HBoxContainer
@onready var _anim: AnimationPlayer = $AnimationPlayer
@onready var _atb: ATBBar = $ATBBar
signal atb_ready()
func _ready() -> void:
_anim.play("RESET")
func highlight(on: bool = true) -> void:
var anim: String = "Highlight" if on else "RESET"
_anim.play(anim)
func reset() -> void:
highlight()
_atb.reset()
func _on_atb_bar_filled() -> void:
atb_ready.emit()