Using anonymous enum's as variables

I’m trying to use an anonymous enum:

class_name Stat

enum { MAX_HP, HP_REGEN, MOVE_SPEED, ... }

So I can do: var stat = Stat.MAX_HP

However, this cannot be used as a variable, e.g. in a function. Calling func do_something(stat: Stat) like do_something(Stat.MAX_HP) results in `Parser Error: Invalid argument for “do_something()” function: argument 1 should be “Stat” but is “Stat.anonymous enum”.

I can avoid this by naming my enum:

class_name Stat

enum Stat { MAX_HP, HP_REGEN, MOVE_SPEED, ... }

but then any time I use this enum I would need to have Stat.Stat.MAX_HP, which is a bit clunky.

Is there any way to resolve this error without naming the enum?

You cannot use an unnamed enum as a type; if you want a quick solution, you can set the type to int in the function.

But let’s examine it better, You have a class for Stat, does this class do anything other than hold states? If not, then you don’t need it at all, simply define an enum named Stat where you use these values and everything will be great.

Note: If your script does something else as well or you insist on holding values in a class, you should convert it to a Resource.

In addition to these aspects, when defining an enum for a class that is intended to be used externally, it is better to choose your class names more carefully, for example:

class_name StateManager

enum States {
    MAX_HP,
    HP_REGEN,
    MOVE_SPEED,
    ...
 }

# And more codes

Just to follow up on why was said, it would make sense why you can’t pass Stat.MAX_HP into a function expecting an object of type Stat. It’s confusing one type with another, as the error implies. Data inside a class is not the same thing as the class itself.

I think the point that you want the enum and the class to have the same name is a sign that you can probably be designing the code differently. An enum like that probably belongs somewhere as Mahan noted. If not, then I might consider using an autoload to hold these, and just have the function take an int parameter. I don’t recall if you’d have to case the enum to an int, but I’d just do that.

When it makes sense to have an enum in a class, I always name it for clarity and do just what you said, like Item.Aspect.TYPE. Usually I’m not using it so often that it’s unwieldy, and it keeps everything very clear.

Thanks for the thoughtful input! I’m actually trying to move the enum out of another class, since multiple classes outside of the old ‘owner’ class started using the Stat list, it just felt like it should be it’s own thing.

I’m not super comfortable with using int, as it would break static typing, potentially leading to errors down the road (e.g. when using multiple enum’s like this, the function wouldn’t be able to know the difference between them).

Well, therefore it would probably make sense to create a resource for this; for example, you can look at the Percent class in Elementum. (link to GitHub)
Of course, you will need less work, as it will only keep one enum.

Note: I do not recommend using autoload; autoloads are used for cases where one thing needs to access everything, not when everyone needs to access one thing. This will prevent problems that are somewhat outside the scope of our discussion.

1 Like