Enum based variable accepts ints that are higher than enum size

Godot Version

4.3

Question

I’m just learning programming and GDScript and i love strong typing and all forms of securing that the code works as intended with so little space for error.

Problem:
Right now when I make a variable that takes values from an enum I didn’t find a simple way to make sure it doesn’t just take an integer that is higher than the highest value in the enum. My workaround is a setter that checks if the set value is smaller than the length of the enum.

enum Potion {ICEPOT, HEALINGPOT, EXPLODINGPOT, SHOCKPOT, TOXICPOT}

var SelectedPotion := Potion.ICEPOT:
	get:
		return SelectedPotion
	set(value):
		if value < Potion.size():
			SelectedPotion = value
		else:
			push_error("Not in Potion Enum")

Without the above setter you are able to set any int value you want to the variable, for example:

Selected Potion = 12

Which would result in issues later on.

Question:
Is there any simpler/in-built way that I’m missing?

You should get warnings about using and int when enum is expected, and also a separate warning when the int is out of range of the enum.
You should be able to set that you want to get an error instead of a warning in these cases in the project settings.

edit: with the Advanced settings enabled, under Debug/GDScript

1 Like

No there isn’t an inbuilt way to protect a variable set on an enum like that. The way I would do it is like this:

enum Potions {ICEPOT, HEALINGPOT, EXPLODINGPOT, SHOCKPOT, TOXICPOT}

const DEFAULT_POTION: int = Potions.ICEPOT

var selected_potion: int = DEFAULT_POTION: 
	get = get_selected_potion, 
	set = set_selected_potion


func get_selected_potion() -> int:
	if not is_potion_index_valid(selected_potion):
		push_warning("Currently selected potion (%d) was not found in Potions enum. Setting to default." % selected_potion)
		selected_potion = DEFAULT_POTION
	return selected_potion


func get_potion_name(potion_index: int) -> String:
	return Potions.keys()[potion_index] if is_potion_index_valid(potion_index) else "INVALID POTION"


func set_selected_potion(requested_potion: int) -> void:
	if is_potion_index_valid(requested_potion):
		selected_potion = requested_potion
		return
	push_warning("Requested potion (%d) was not found in Potions enum. Setting to default." % requested_potion)
	selected_potion = DEFAULT_POTION


func is_potion_index_valid(potion_index: int) -> bool:
	return potion_index in Potions.values()

And you can test it with something like this:


func _ready():
	testing_potion_selection()


func testing_potion_selection() -> void:
	print("Testing potion selection:")
	selected_potion = 15  # Invalid
	selected_potion = -1  # Invalid
	selected_potion = 2   # Valid
	print("Final selected potion: %s" % get_potion_name(selected_potion))


I am a beginner with GDScript too so there may be better ways. But here, if you request an invalid potion a default potion will be set instead and a warning sent to output. I would add a null version for your enum and set the default to that as well.


enum Potions {NONE, ICEPOT, HEALINGPOT, EXPLODINGPOT, SHOCKPOT, TOXICPOT}

const DEFAULT_POTION: int = Potions.NONE

Best wishes,

Paul

PS I would also probably keep all that stuff in a seperate class or potion_manager that dealt exclusively with your potions too. If that helps at all?

PPS I have no idea why that strange formatting appears on the pasted code. I am sure I used the right “Paste your code here” function. Sorry about that if it looks weird, I tested it and it all works fine.

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.