# In a function how do I return more then one value

Attention Topic was automatically imported from the old Question2Answer platform.

for an example this is what I have

``````func take_damage(move,attacker):
randomize()
critical = 1
var critical_chance = randi() % 100 + 1
#var critical_chance = 5
if critical_chance <= 6.25:
critical = 2

var type : float = Get_effectiveness(move.type,type_1) * Get_effectiveness(move.type,type_2)
var modifier : float = rand_range(0.85,1.0) * type * critical
var a : float = (2.0 * attacker.level / 5.0 + 2.0)
var b : float = (a * attacker.attack * move.power / defence) / 50.0
var c : float = (b + 2.0) * modifier
var damage = int(c)
current_health -= damage
print(str(attacker.name) + " = " + str(damage))
return critical > 1
``````

This function currently returns if a critical hit happens but I would also like to turn other variables like if current_health is <= 0 and other stats, I saw in unity something about returning a function or was it a class, cant remember anyways whats the preferred way for godot/gdscript

Just return multiple values as `Array` or `Dictionary`. Something like this:

``````return [critical, current_health]
``````

Then you can get `critical` and `current_health` as

``````var result = take_damage(move, attacker)
var critical = result[0]
var current_health = result[1]
``````

If you want to return multiple values you can either create an `Object` to handle those multiple values (not preferred), return an `Array` (less preferred) or return a `Dictionary`. (`Vectors` work as well if you’re dealing with numbers.)

I would suggest that you let the attacker handle the logic of determining the damage and at the end emitting a signal with the amount of damage and the unit that is supposed to be damaged.
Then you could print something like “Attacker uses Move, it was a critical strike!” in the attacker’s logic and “Target takes x damage” when the target takes the damage. I think separating the logic in this manner will allow you to avoid the need to return multiple variables in the first place.

As it stands your `take_damage()` function is quite overloaded: it determines if it was a critical, uses the attacker’s stats to determine the amount of damage in conjunction with the target’s defense (very brittle), prints the amount of damage done, and finally applies the damage to the target. If I was reading code and came across a function called `take_damage()` I would expect it to have 1-2 inputs (amount and maybe damage class/type) and I would apply my defense to that amount then reduce my health (which would probably be the responsibility of a separate function so it can handle UI stuff).

So your suggesting I should try to think outside the box and not make it like this, this function is in a resource script where I can make multiple enemys but I could do it that way but I would still be adding a function that adds the stats and defence stats together, a object sounds good though I don’t really know how an object is presented in code.
Thanks for the tip to make it better but for now I just want things to work my way and then I will improve it with people’s comments of course, thanks though I appreciate it!

Dragon20C | 2021-05-06 18:08

Absolutely man! Don’t get me wrong what you’re doing works and it’s a prototype. It’s good to delegate tasks to different objects from the get go though. I’m spitballing but I would do something like this:

``````signal damage_target(amount, target)
# how you handle this part is really up to how your game is structured
func start_battle(enemies):
for enemy in enemies:
enemy.connect("damage_target", self, "determine_damage")

func use_move_on_target(move, target):
var critical_multiplier = determine_critical()
var damage = determine_move_damage(move)
damage = int(damage * critical multiplier)
print_move(move, critical > 1)
emit_signal("damage_target", damage, target)

func determine_critical()
randomize()
critical = 1
var critical_chance = randi() % 100 + 1
#var critical_chance = 5
if critical_chance <= 6.25:
critical = 2
return critical

func determine_move_damage(move)
var type : float = Get_effectiveness(move.type,type_1) * Get_effectiveness(move.type,type_2)
var modifier : float = rand_range(0.85,1.0) * type
var a : float = (2.0 * self.level / 5.0 + 2.0)
var b : float = (a * self.attack * move.power) / 50.0
var c : float = (b + 2.0) * modifier
var damage = c
return damage

func print_move(move, is_critical):
var to_print = self.name + " uses " + move.name
if is_critical:
to_print += ", it was a critical hit!"
else:
to_print += "."
print(to_print)

# called when the damage_target signal is emitted
func determine_damage(amount, target):
if target == self:
apply_damage(amount)

func apply_damage(amount)
var reduced_by_defence = int(amount / self.defence)
self.current_health -= reduced_by_defence
var damage_message = str(self.name) + " took " + str(reduced_by_defence) + " damage."
if self.current_health <= 0:
print(damage_message + " " + str(self.name), " has died.")
else:
print(damage_message)
``````

timothybrentwood | 2021-05-06 18:47

I see, I don’t usually use signals or I mainly use them for simple tasks but I can try this, thanks!

Dragon20C | 2021-05-06 18:51