Best data structure for hierarchical, global data?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By bloqm

I want to implement tags, that are descriptors that will allow me to do boolean logic.

Ideally, they would look like this (pseudocode):

Tags
    CharacterType
            Warrior
            Wizard
    Buffs
            SpeedBuff
            DamageBuff

And, ideally, this data structure should be available globally, so you could type something like this with autocompletion or at least some type checking:

if player_type == Tags.CharacterType.Wizard:
    remove_all_tags_children_of( Tags.Buffs ) 

I’ve tried two approaches so far.

  • One was to use strings to define the tags, but this was a lot of work, and error prone while typing.
  • The other was to use custom, empty classes and subclasses, and this would be perfect… if it was implemented in Godot 3.x. At the moment class_name and other custom classes simply aren’t recognized as such, and you can’t modify ClassDB to include them.

Any ideas on this? Perhaps there’s a simpler way that I’m missing? TY!

:bust_in_silhouette: Reply From: Inces

class_name can be checked for using iskeyword

if player is Wizard :
       for child in player.get_node("buffs").get_children():
              if child is SpeedBuff or child is DamageBuff:
                  child.queue_free()

Thank you! Already tried that, but it won’t work as of version 3.5.
Godot doesn’t treat custom ‘classes’ as real classes and even if you override is_class and get_class for every single class, it fails to recognize inheritance and the like.

bloqm | 2022-05-30 15:48

You probably use class_name, but in case you don’t…

CharlesMerriam | 2022-05-30 17:57

:bust_in_silhouette: Reply From: CharlesMerriam

This may be a bit of a hack, but how I would do it. There are a lot of possible integers and I want to spend as little time as possible maintaining the tags:

enum Tags {
     CLASS = 100, WIZARD, FIGHTER, CLERIC,
     BUFFS=200, SPEED, DAMAGE, FIRE,
     CONTAINERS=300, CHEST, BAG,PILE,BOX,FOOTLOCKER
}

func is_a(group, thing):
     return thing > group and thing < group + 100

if is_a(Tags.CLASS, Tags.WIZARD):....

You mileage may vary.

wow man, this is awesome, I need to try it too :slight_smile:

Inces | 2022-05-31 17:30

You’re welcome!

CharlesMerriam | 2022-06-01 05:59

SOLVED.

I ended up using similar to this. Nested const enums. Behold:

const Class = {
	Warrior = {},
	Wizard = {
		RedMage = {}
	}
}

With some helper functions I have total control over the tags. I keep the tree hierarchy and the code completion, and can write stuff like remove_all(Tags.States.Defuffs).
The downside: It’s hard to debug. I had to write a function to translate a tag-path into a string.

bloqm | 2022-06-19 20:14