Issue with My Turn Based FF Inspired Combat System

Goodnight, it seems like I am having issues with an aspect of my game. I created a turn-based combat system similar to that of old FF titles. Sadly, when I click attack, only the top enemy gets damaged and updates while the other 2 don’t. Additionally, my player character keeps on healing after every turn even though I did not select healing. Worst of all, defend and heal doesn’t do what it is supposed to do…I have attached images of the code for your better viewing:

These are my scripts (I am new so I sadly cant send screenshots)
Player Script:

extends Node2D

var players: Array =
var index : int = 0

@onready var _focus = $“Saylor (Player)/Focus”
@onready var progress_bar = $“Saylor (Player)/ProgressBar”
@onready var animation_player = $“Saylor (Player)/AnimationPlayer”

var MAX_HEALTH: float = 10
var health: float = MAX_HEALTH
var is_defending: bool = false

func _ready():
players = get_children()
players[0].focus()

func _on_enemy_group_next_player():
if index < players.size() - 1:
index += 1
switch_focus(index, index - 1)
else:
index = 0
switch_focus( index, players.size() - 1 )

func heal(amount: float):
health = clamp(health + amount,0,MAX_HEALTH)
_update_progress_bar()

func take_damage(value: float):
if is_defending:
value /= 2
health = max(health - value, 0)
_update_progress_bar()
_play_animation()
func _update_progress_bar():
progress_bar.value = (health / MAX_HEALTH) * 100

func _play_animation():
pass

func unfocus():
_focus.hide()

func focus():
_focus.show()

func switch_focus(x,y):
players.focus()
players[y].unfocus()

Single Enemy Script:
extends CharacterBody2D

var enemies : Array =
@onready var _focus = $Focus
@onready var progress_bar = $ProgressBar
@onready var animation_player = $AnimationPlayer
@onready var saylor_battle_sprite = $Saylor_battle_sprite

@export var MAX_HEALTH: float = 7

var health: float = 7:
set(value):
health = value
_update_progress_bar()
_play_animation()

func _update_progress_bar():
print(“updated”)
progress_bar.value = (health/MAX_HEALTH) * 100

func _play_animation():
animation_player.play(“Hurt”)

func focus():
_focus.show()

func unfocus():
_focus.hide()

func take_damage(value):
health -= value
_update_progress_bar()
_play_animation()
if health <= 0:
is_dead = true
var is_dead:bool = false

@export var attack_power: int = 2

Multiple Enemy Script (Attached to a 2D Scene that contains 3 instances of the single enemy scene)
extends Node2D

@onready var saylor_battle_sprite = $“…/Saylor_battle_sprite”

var enemies : Array =
var index: int = 0
var action_queue : Array =
var is_battle: bool = false

@onready var choice = $“…/CanvasLayer/Choice”

signal next_player

func _ready():
enemies = get_children()
for i in enemies.size():
enemies[i].position = Vector2(0, i*90)
show_choice()

func _process(_delta):
if not choice.visible:
if Input.is_action_just_pressed(“ui_up”):
if index > 0:
index -= 1
switch_focus(index, index+1)

	if Input.is_action_just_pressed("ui_down"):
		if index < enemies.size() - 1:
			index += 1
			switch_focus(index, index - 1)
	
	if Input.is_action_just_pressed("ui_accept"):
		action_queue.push_back(index)
		emit_signal("next_player")

if action_queue.size() == enemies.size() and not is_battle:
	is_battle = true
	_action(action_queue)

func _action(stack):
var player_node = get_parent().get_node(“Saylor_battle_sprite”)
var num_attacks = 0
for i in stack:
var action = choice.get_node(“Actions”).get_child(i).text
if action == “Attack”:
num_attacks += 1
if num_attacks <= 3:
_reset_focus()
enemies[i].focus()
await get_tree().create_timer(1).timeout
enemies[i].take_damage(1)
else:
break
elif action == “Heal”:
_reset_focus()
player_node.focus()
await get_tree().create_timer(1).timeout
player_node.heal(3)
elif action == “Defend”:
_reset_focus()
player_node.focus()
await get_tree().create_timer(1).timeout
player_node.is_defending = true

player_node.is_defending = false
enemy_attack(player_node)	
action_queue.clear()
is_battle = false
show_choice()

func switch_focus(x,y):
enemies.focus()
enemies[y].unfocus()

func show_choice():
choice.show()
var actions = choice.get_node(“Actions”)
for action in actions.get_children():
action.grab_focus()

func _reset_focus():
index = 0
for enemy in enemies:
enemy.unfocus()

func _start_choosing():
_reset_focus()
enemies[0].focus()

func enemy_attack(player_node):
for enemy in enemies:
if not enemy.is_dead:
player_node.take_damage(enemy.attack_power)
await get_tree().create_timer(0.5).timeout

func _on_attack_pressed():
choice.hide()
_start_choosing()

func _on_defend_pressed():
choice.hide()
_start_choosing()

func _on_heal_pressed():
choice.hide()
_start_choosing()

You can however format your code properly (by clicking on the “</>” symbol in the editor when writing your post) – which is more useful than a screenshot anyway, because it can be easily copied!

Your functions _on_attack_pressed, _on_defend_pressed and _on_heal_pressed all do the same and do not save the choice the player made anywhere. In _action you then look up the name of the action using the i-th item from the stack, which seems to be the index of the selected enemy, however!

3 Likes

Thanks so much! I kinda feel dumb now haha, it works now ^^ I stored the player choice under the functions and modified the _action() function accordingly :slight_smile:

1 Like