How to avoid endless if statements?

Godot Version

4.5 stable

Question

hey, im making a strategy game in godot currently my main script looks like this

extends Node2D
## Main game functionality such as attacking and conquering

@export var player_country_id: int = 0
@export var country_id_list: Dictionary = {
	0:"None",
	1:"France",
	2:"Switzerland",
}
@export var unselected_color: Color
@export var selected_color: Color

var country_power: float = 0.0
var mouse_is_in_country: int = 0
var country_lock: bool = false

func _process(_delta: float) -> void:
	$UiLayer/GUI/VBoxContainer/FpsCounter.text = "FPS: " + str(Engine.get_frames_per_second())

func _input(event: InputEvent) -> void: # When any input happens
	
	if event.is_action_pressed("select"): # ACTIONS FOR SELECTING
		
		if not country_lock: # ACTIONS FOR SELECTING A STARTER COUNTRY
			if mouse_is_in_country == 0: # if no country is hovered over
				return # abort
			elif mouse_is_in_country == 1: # If mouse is in france's hitbox
				$France/Shape.color = selected_color
			elif mouse_is_in_country == 2:
				$Switzerland/Shape.color = selected_color
			else:
				return
				
			player_country_id = mouse_is_in_country # Set player ID
			country_lock = true # block selecting a different country
			print("Selected Country: " + str(player_country_id)+ " = " + str(country_id_list[player_country_id])) # debug
			$"UiLayer/GUI/VBoxContainer/Country Selection".text = "Selected  Country: " + str(country_id_list[player_country_id])
		
		if country_lock: # ACTIONS FOR COUNTRIES
			if mouse_is_in_country == 0 or mouse_is_in_country == player_country_id: # if no country is hovered over or not player
				return
			if not country_power >= 10:
				return
			
			if mouse_is_in_country == 1:
				$France/Shape.color = selected_color
			if mouse_is_in_country == 2:
				$Switzerland/Shape.color = selected_color


func _on_france_mouse_entered() -> void:
	mouse_is_in_country = 1


func _on_switzerland_mouse_entered() -> void:
	mouse_is_in_country = 2


func _on_power_increase_cooldown_timeout() -> void:
	if not country_lock:
		return
	country_power += 1
	$UiLayer/GUI/VBoxContainer/PowerCounter.text = "Power: " + str(country_power)

this works for 2 countries but if I add the 181 others this is gonna be a nightmare so how can I replace the if country with a stable system for easy expansion?

Couldnt you use a dictionary where the key is the name of a country and the value is a separate dictionary with all relevant info about the country?

Then have each country set the value of some buffer variable to whatever country it is. E.g. germany. So no need for a separate function for each country. Just name the nodes Germany, Finland etc and set the value based on node name.

You should implement some basic country class for that i think. Make sure to force an error if no such country exists in the dictionary. Its easy to get silent errors if you e.g write “denmark” instead of “Denmark”. So whenever you set the value of the current country, check if that key exists in the dictionary.

Then, when you need to check something you could highlight borders based on the key or play a fail sound based on if country[power] is higher than your own etc etc.

2 Likes

You can use arrays or dictionaries to associate a number to a value, You already have a country_id_list why not use it?

func _input(event: InputEvent) -> void: # When any input happens
	if event.is_action_pressed("select"): # ACTIONS FOR SELECTING
		if not country_lock: # ACTIONS FOR SELECTING A STARTER COUNTRY
			if country_id_list.has(mouse_is_in_country):
				var country_node: Node = get_node(country_id_list[mouse_is_in_country])
				var country_shape: Polygon2D = country_node.get_node("Shape")
				country_shape = selected_color

Though @baba is right, it’s likely you could delegate more of your code per-object, or per-country in this case.

2 Likes

When you’re hooking up the mouse_entered signal, you can bind an extra argument, like (say) the country ID or name. Personally, I’d advise binding a StringName, since those are basically atoms (that is, internally it’s represented by a unique number), so you can do something like:

func _mouse_entered_country(country: StringName) -> void:
    mouse_is_in_country = country

    match country:
        &"France":
            # Do France Things
        &"Switzerland":
            # Do Switzerland Things
        _:
            # Anything else...

@gertkeno I will try this thanks!