I have a Resource for Stats, with variables for health, speed, etcetera:
extends Resource
class_name Stats
signal stats_changed(property, original_value, new_value)
@export var health : int = 100: set = set_health
@export var max_health : int = 100: set = set_max_health
@export var defense : int = 10: set = set_defense
@export var stealth : int = 0: set = set_stealth
@export var weight : int = 10: set = set_weight
@export var speed : int = 100: set = set_speed
@export var dodge_speed : int = 180
@export var money: int = 0: set = set_money
@export var max_money: int = 999999
enum Properties {
HEALTH,
MAX_HEALTH,
DEFENSE,
STEALTH,
WEIGHT,
SPEED,
DODGE_SPEED,
MONEY,
MAX_MONEY
}
func set_money(value):
emit_signal("stats_changed", Properties.MONEY, money, value)
money = clamp(value, 0, max_money)
func set_max_health(value):
emit_signal("stats_changed", Properties.MAX_HEALTH, max_health, value)
health = clamp(value, 0, max_health)
max_health = value
func set_health(value):
emit_signal("stats_changed", Properties.HEALTH, health, value)
health = clamp(value, 0, max_health)
func set_defense(value):
emit_signal("stats_changed", Properties.DEFENSE, defense, value)
defense = value
func set_speed(value):
emit_signal("stats_changed", Properties.SPEED, speed, value)
speed = value
func set_stealth(value):
emit_signal("stats_changed", Properties.STEALTH, money, value)
stealth = value
func set_weight(value):
emit_signal("stats_changed", Properties.WEIGHT, weight, value)
weight = value
func get_current_speed():
return speed - weight
func get_current_dodge_speed():
return dodge_speed - weight
func get_stat_color(property : int):
match property:
Properties.HEALTH:
return Color.DEEP_PINK
Properties.MONEY:
return Color.YELLOW
Properties.WEIGHT:
return Color.YELLOW_GREEN
Properties.DEFENSE:
return Color.DEEP_SKY_BLUE
Properties.STEALTH:
return Color.WEB_PURPLE
As you can notice, the code gets very repetitive. So, I thought of a dictionary of arrays/dictionaries/objects. The key would be an enum item (int), or string. And the value could be an array or dictionary. This way, I could link one property with others directly related, like the max value, current_max_health or the color, to not have to use a huge if statement for that. I have two max variables because in the game, your max health can be limited temporarily with certain effects.
When setting a new property with a custom method, the stats_changed signal would be called:
var stats := {
Properties.HEALTH: [100, 100],
Properties.DEFENSE: [10, 10],
Properties.STEALTH: [0, 100],
Properties.WEIGHT: [10, 100],
Properties.SPEED: [100, 200],
Properties.DODGE_SPEED: [180, 200],
Properties.MONEY: [0, 999999],
}
signal stats_changed(property: int, old_value, new_value)
func set_stat(property: int, value):
var old_value = stats[property][0]
var max_value = stats[property][1]
stats[property][0] = clamp(value, 0, max_value)
emit_signal("stats_changed", property, old_value, stats[property][0])
func get_stat(property: int):
return stats[property][0]
func get_max_stat(property: int):
return stats[property][1]
I don't know if using a dictionary of objects is better instead, as not all properties have the same variables (Some don't have max value, some have two...).
It's one of those times I don't know if it's a great or awful idea. What do you think?