Exported Enum inside Resource always returns zero

Godot Version

v4.2.2.stable.official [15073afe3]

Question

I have a resource class that is meant to hold all the stat information for an actor in my rpg game. I define a local enum to use in 12 export vars that are meant to define the tier of the base value of the stat, and then how much the stat changes on a level up. (So I can define each character class)

class_name Stats
extends Resource

enum StatTiers {CRAWL, SLOW, NORMAL, FAST, EXTREME}
@export var hp_base: StatTiers
@export var hp_progression: StatTiers
@export var mp_base: StatTiers
@export var mp_progresion: StatTiers
...

The editor all configured:
stats_editor

But every variable is always returning zero. I can see that with this _init script.

func _init():
	print("Init Stat " + self.resource_name)
	print("Base HP " + str(hp_base))
	print("Base MP " + str(mp_base))
	print("Base Strength " + str(strength_base))
	print("Base Agility " + str(agility_base))
	print("Base Resiliance " + str(resiliance_base))
	print("Base Magic " + str(magic_base))

What I need to do with this input is then hand it to the var that will hold the final stat (which takes the tier value and sends it to a randi generator)

# Assign base stats based on stat tier, and rand ranges.
var strength:int = get_base_stat(strength_base):
	set(new_str):
		strength = new_str
		update_strength()

But it is also always a zero at this point, so all of the stats end up getting processed as a “CRAWL” tier.

Any help in understanding why I am not getting the values being set in the editor for all the instances of this resource would be appreciated.

Possibly checking the values too early. Init could be printing the values before theyve been set with the editor values

My next question would be then, how do I know when to access it once its loaded? The object that is holding this resource is returning zero’s as well. Which makes me wonder if I am not letting it get loaded?

Sounds like it is loading if you are getting 0s instead of null references. Sadly im at work for the next 6 hours so i cant do much coding to figure this out atm

I don’t quite understand how you get the resource in the script and where init() is located.

What I realized:

1. You created a resource script - OK.

2. You created a resource based on the script and it was saved in your file system - I’m not sure, so it’s 50/50.

3. Next you have to go to the player script and write something like:

var resource: Stats = preload("path_to_resource").

After that you will be able to use all the variables you have set in the resource

@te1ny thanks for some explainer, let me answer your questions, as it may help get a better answer.

  1. Yes this is a resource script. And the _init() is for that script.

  2. Yes I then made 4 instances of this resource in the file structure.

  3. This is were things get complicated, so this Stats resource is then an attribute of another resource “PlayerCharacter” which is the base resource.
    I have tried doing what you suggested in the PlayerCharacter script but, i get the same results.
    That script:

class_name PlayerCharacter
extends Actor

@export var stats:Stats
@export var equipment:HumanoidEquipment = HumanoidEquipment.new()

func _init():
	print("Init PlayerCharacter " + self.resource_name)

and its a sub class of Actor: which is this script:

class_name Actor
extends Resource

@export var name:String
@export var actor_class:String
@export var type:String

func _init():
	print("Init Actor")

I can define the 3 strings for actor in the editor and get them just fine, but the Stats resource as a export while still returning a stats resource, ends up having that enum value of zero, no matter what I set.

I have tried setting the stats resource dynamically through the inspector on a PlayerCharacter instance, as well as defining a stat instance and then assigning that instance to the PlayerCharacter instance, both with no luck.

init() works correctly and displays 0 everywhere. The point is that the resource script and the resource are two different things. init() that you describe in the resource script does not apply to the resource itself, because the resource is a data store and cannot perform any actions other than storage. For the sake of interest, you can look at the .tres file that is created on the basis of the resource script, there you will see your data in TOML markup.

I have clarified this point for you, the next thing I want to say is that @export may not always store the correct values. Here’s an example I had (C#), I set the @export variable to a speed value of 200, but on startup it was 0. I couldn’t figure out what this was about, but what I can tell you is that you need to “update” the query to the variable. I don’t remember how I did it, so I can’t help you here.

Conclusion: Remove _init() from the Resource script. Try to get the resource file not via @export, but via var resource = preload(…).

If you have more questions or data, please write me.

@te1ny After digging through the documentation some more, I found why print statements in the _init() would not return what is in the exports. The load priority is var Initialization, then anything set in _init(), and then exports.

This doesn’t explain why the parent resource is not getting it though.

I’m also not sure what you mean by the resource not being able to perform any actions. Are you implying that functions internal to the resource script don’t work? Because I do have them working.

Not to be rude or anything, but nothing has been clarified. I would be curious about what you mean by "“update"ing the query”.

Update:
So if I instead don’t use the enum @exports and instead turn my var assignments into exports that take an int… I can have it do work via the setter, and it all works fine.

# Assign base stats based on stat tier, and rand ranges.
@export var strength:int = 1: #get_base_stat(strength_base):
	set(new_str):
		strength = get_base_stat(new_str)
		update_strength()
@export var agility:int = 1: #get_base_stat(agility_base):
	set(new_agi):
		agility = get_base_stat(new_agi)
		update_agility()
@export var resilience:int = 1: #get_base_stat(resilience_base):
	set(new_resil):
		resilience = get_base_stat(new_resil)
		update_resilience()

get_base_stat() is just the function that took in the enum value and churned out the right random in, and update_strength() will then calculate secondary stats based on the new stat.

So I guess really it comes down to why is the Enum not working?

Hey, I was asleep :slight_smile:

See, _init() in a resource will work, but not the way you want it to.

_init() is a class constructor and will be executed whenever you create an object of the class.

For example, when you create Vector2, you write this, Vector2(10, 15), that is, these parameters are passed to the class constructor. In the constructor, it would look something like this:

func _init(x, y):
    self.x = x
    self.y = y

About the resource script and its _init(). You specify empty variables for export and when you create resources, they all get empty (equal to 0). And through the constructor you see 0 everywhere.

You should realize that the resource script is only what describes the resource itself and how it looks like. A resource is a data store and is an alternative to using JSON files to store information.

P.S About the query update, forget it, it was a crutch that worked for me

Example of resource use:

1. Creating the main scene and creating a script for it:

Node.tscn

Node.gd

2. Creating a resource script:

ScriptResource.gd

изображение

3. Creating a resource object (data file)

ObjectResource.tres

изображение

4. Write code to use the data from the resource:

Node.gd

5. Output result

@te1ny Thanks for the explainers!

The reason that the enums where always returning 0 to its parents, was the same reason that the print statements in the _init() function showed them.

The @exported enum variables were being used as the variable initialization for the stat variables (granted as arguments for a randomization function).

Because the order of value assignment is as fallows: Initialization → constructor assignment (in this case _init() since its not a node and doesn’t have _ready() ) → exported values, when the enum value was used as the initialization for another variable it had yet to be defined by the export value.

In my case, how I could have fixed it while still using the enum, and not the int’s that I posted yesterday, would have been to have the parent resource assign the enum value to the other variable. (Since my Stats recource is a subresource of another resource).

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