Targeting system in a turn-based rpg

Hi! I’m working on a turn based game and I’m struggling a bit with how to code the targets for each action. I suspect the solution is easy, but to explain it I’ll require to sample a bit of the code.

First, I have my “selecting enemies” system as such (I’m omitting the unecessary parts):

var index: int = 0
func _input(_event):
	if Input.is_action_just_pressed("ui_left") and actionsPanel.selectingEnemies == true:
		if index > 0:
			index -= 1
			switch_select(index, index+1)
			show_stats(index, index+1)
	if Input.is_action_just_pressed("ui_right") and actionsPanel.selectingEnemies == true:
		print(enemies[index])
		if index < enemies.size() -1:
			index += 1
			switch_select(index, index - 1)
			show_stats(index, index - 1)
	if Input.is_action_just_pressed("ui_accept") and actionsPanel.selectingEnemies == true:
		actionQueue.push_back(deal_damage)

func switch_select(x,y):
        #the "show_stats" function is the same thing. Omitted for brevity
	enemies[x].select()
	enemies[y].unselect()

This lets me select which enemy from my “enemyPod” instanced scene I’m targeting by moving left to right like DragonQuest
Then, the “deal_damage” function is

func deal_damage():
	data.take_phys_damage(enemies[index], party_spawning.active_character.job.strength)

#"data" is a global script with all the actions in one place. It's referenced from this:
func take_phys_damage(target, value: int):
	enemy.current_health = health
	target.health -= value

It may be a cumbersome way to do it, but I’ll refactor it as necessary.
I then solve the actions as such:

func solve_actions():
	for action in actionQueue:
		action.call()

Now my problem is: Whenever I call the solve_actions() function, it deals damage for each party member only to the last selected enemy, because that’s where the index stopped at the last selection, I assume.
How do I make it so it stores the selected enemy index each time I press “enter” and push bach the “deal_damage()” function to the array?

You could make deal_damage() take the index as an argument. Then when you queue the action you can bind the current index to the callable like this:
actionQueue.push_back(deal_damage.bind(index))
So when you do action.call() it’ll pass the value that was the index at the time of queuing the action.

If that doesn’t work for some reason you can make an action an array (or sub-class) instead of just a callable, and the first element of the array would be the callable, the second is the arguments (index), and store the current index that way.

1 Like

Holy shit, it worked. Thanks a ton.
I was having a similar problem to actually store which character was the “active” character and I applied the same solution and that seemed to fix it as well.
I’ll leave the code here so whoever finds this page in the future may take some hints.
Excuse the spaghetti code, hope it helps someone though, you never know

extends Node
class_name enemyDriver
var actionQueue = []
var enemies: Array = []
var index: int = 0
@onready var battle_controler = $".."
@onready var actionsPanel = $"../ActionsPanel"
@onready var party_spawning = $"../PartySpawning"
signal action_selected
func initialize():
       ##This instances a pod for random encounters. Currently it's hardcoded for testing purposes.
	var enemyPod = preload("res://Mechanics/EnemyResources/enemy_pod.tscn").instantiate()
	add_child(enemyPod)
	enemies = enemyPod.get_children()
	
func _input(_event):
	if Input.is_action_just_pressed("ui_left") and actionsPanel.selectingEnemies == true:
		if index > 0:
			index -= 1
			switch_select(index, index+1)
			show_stats(index, index+1)
	if Input.is_action_just_pressed("ui_right") and actionsPanel.selectingEnemies == true:
		if index < enemies.size() -1:
			index += 1
			switch_select(index, index - 1)
			show_stats(index, index - 1)
	if Input.is_action_just_pressed("ui_accept") and actionsPanel.selectingEnemies == true:
		actionQueue.push_back(deal_damage.bind(enemies[index], party_spawning.active_character.job.strength))
		unselecting_enemies()
		action_selected.emit()
	if Input.is_action_just_pressed("ui_down") and actionsPanel.selectingEnemies == true:
		actionsPanel.selectingEnemies = false
		actionsPanel.show_actions()		

func deal_damage(current_index, current_player):
	enemies[index] = current_index
	party_spawning.active_character.job.strength = current_player
	data.take_phys_damage(enemies[index], party_spawning.active_character.job.strength)
	enemies[index].enemy_hurt.play("hurt")
	battle_controler.display_text_tooltip("You dealt %d damage to %s!" % [party_spawning.active_character.job.strength, enemies[index].enemy.name])
func solve_actions():
	for action in actionQueue:
		action.call()
		await get_tree().create_timer(1).timeout
	actionQueue.clear()
		
func unselecting_enemies():
	actionsPanel.selectingEnemies = false
	enemies[index].unselect()
	enemies[index].hide_info()	
	
	
func selecting_enemies():
	battle_controler.hide_text_tooltip()
	await actionsPanel.hide_actions()
	actionsPanel.selectingEnemies = true
	enemies[index].select()
	enemies[index].show_info()			
		
func switch_select(x,y):
	enemies[x].select()
	enemies[y].unselect()
	
func show_stats(x,y):
	enemies[x].show_info()
	enemies[y].hide_info()	
1 Like