+1 vote

This is the first time working with a class I am having issues understanding on how to use them correctly I have a class that is storing an array, and I want my other scripts to look up values from them but when I try to access a value from it, it says invalid get index "chart" base on gdscript,

here is the code:

extends Node
class_name TypeChart


var chart = [#   Nor   Fir   Wat   Ele   Gra   Ice   Fig   Poi   Gro   Fly   Psy   Bug   Roc   Gho   Dra   Dar  Ste    Fai
    #Normal
    [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.5, 0, 1, 1, 0.5],
    #Fire
    [1, 0.5, 0.5, 1, 2, 2, 1, 1, 1, 1, 1, 2, 0.5, 1, 0.5, 1,2, 1],
    #Water
    [1, 2, 0.5, 2, 0.5, 1, 1, 1, 2, 1, 1, 1, 2, 1, 0.5, 1, 1],
    #Electric
    [1, 1, 2, 0.5,0.5, 2, 1, 1, 0, 2, 1, 1, 1, 1, 0.5, 1, 1],
    #Grass
    [1, 0.5, 2, 1,  0.5, 1, 1, 0.5, 2, 0.5, 1, 0.5, 2, 1, 0.5, 1, 0.5, 1],
    #Ice
    [1, 0.5, 0.5, 1, 2, 0.5, 1, 1, 2, 2, 1, 1, 1, 1, 2, 1, 0.5, 1],
    #Fighting
    [2, 1, 1, 1, 1, 2, 1, 0.5, 1, 0.5, 0.5, 0.5, 2, 0, 1, 2, 2, 0.5],
    #Poison
    [1, 1, 1, 1, 2, 1, 1, 0.5, 0.5, 1, 1, 1, 0.5, 0.5, 1, 1, 0, 2],
    #Ground
    [1, 2, 1, 2, 0.5, 1, 1, 2, 1, 0, 1, 0.5, 2, 1, 1, 1, 2, 1],
    #Flying
    [1, 1, 1, 0.5, 2, 1, 2, 1, 1, 1, 1, 2, 0.5, 1, 1, 1, 0.5, 1],
    #Psychic
    [1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 0.5, 1, 1, 1, 1, 0, 0.5, 1],
    #Bug
    [1, 0.5, 1, 1, 2, 1, 0.5, 0.5, 1, 0.5, 2, 1, 1, 0.5, 1, 2, 0.5, 0.5],
    #Rock
    [1, 2, 1, 1, 1, 2, 0.5, 1, 0.5, 2, 1, 2, 1, 1, 1, 1, 0.5, 1],
    #Ghost
    [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.5, 1, 1, 2, 1, 0.5, 1, 1],
    #Dragon
    [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 0.5, 0],
    #Dark
    [1, 1, 1, 1, 1, 1, 0.5, 1, 1, 1, 2, 1, 1, 2, 1, 0.5, 1, 0.5],
    #Steel
    [1, 0.5, 0.5, 0.5, 1, 2, 1, 1, 1, 1, 1, 2, 0.5, 1, 1, 1, 0.5, 2],
    #Fairy
    [1, 0.5, 1, 1, 1, 1, 2, 0.5, 1, 1,  1, 1, 1, 1, 2, 2, 0.5, 1]
    ]

A simple separate script
and this is where I use the class name to try to access the array

func Get_effectiveness(attack_type,defence_type):
    if attack_type == Types.monster_type.none or defence_type == Types.monster_type.none:
        return 1
    var row : int = attack_type
    var col : int = defence_type
    print("row : " + str(row))
    print("col : " + str(col))
    return TypeChart.chart[row][col]
Godot version 3.3
in Engine by (152 points)

1 Answer

0 votes
Best answer

Either create a Singleton out of it (recommended ONLY FOR STATIC VALUES if you are just starting to program): https://docs.godotengine.org/en/stable/getting_started/step_by_step/singletons_autoload.html

Then you can access it from anywhere in your script using TypeChart.chart. Otherwise you'll need to instance(? generally what it's called in other programming languages, but Godot makes a distiction) it in order to access it:

const LTypeChart = load("res://TypeChart.gd") # your path may differ
var type_chart_instance
func _ready():
    type_chart_instance = LTypeChart.new() # i think _ready() will not run but _init() will

func cool_function():
    do_cool_stuff()
    move.type_array = type_chart_instance.chart[3]

But regardless of which way you do it, please use a Dictionary with constants for keys over an array. XD

extends Node
class_name TypeChart

const TYPE_KEY_FIRE = "fire"
const TYPE_KEY_NORMAL = "nor"
const TYPE_KEY_WATER = "wat"

var CHART: Dictionary = {
    TYPE_KEY_FIRE : { TYPE_KEY_FIRE : 1, TYPE_KEY_NORMAL : 1, TYPE_KEY_WATER: 0.25},
    TYPE_KEY_NORMAL : { TYPE_KEY_FIRE : 1, TYPE_KEY_NORMAL : 1, TYPE_KEY_WATER: 1},
    TYPE_KEY_WATER: { TYPE_KEY_FIRE : 2, TYPE_KEY_NORMAL : 1, TYPE_KEY_WATER: 1},
}
# example usage getting fire's effectiveness vs water:
TypeChart.CHART.get(TypeChart.TYPE_KEY_FIRE).get(TypeChart.TYPE_KEY_WATER)

I know it seems like a lot of work for not much gain, but it's wayyyyyy worth it not to have to memorize which type is at which index for 18 different types. IMO your get_effectiveness() function should live in your TypeChart class - it's a perfect candidate. And if you go the Singleton route consider naming your TypeChart class something more generic like DataBase, or Globals, or CONSTANTS and using it for more things.

by (2,832 points)
selected by

Honestly I have it as a singalton it was the only way I could think of access this array and you mention changing it to a dictionary, I find dicts hard to use , plus I have it like this simply because effectiveness compares two values and finds the corresponding value to both

Dictionaries are very much your friend when creating maps between things. (Type -> Type -> Effectiveness)

I'm thinking about when you create moves: move.type = 5 is WAY less readable and more prone to typing (as in keyboard) errors than move.type = TypeChart.TYPE_KEY_FIRE. Godot will also give you the auto-completion for TYPE_KEY_FIRE when you start typing it making it super convenient to use.

5 would be what's referred to has a magical number - they are evil and should be avoided at all costs. Any number that exists in code besides 0 (or in some cases -1) should be accessed via a variable. Trivial example, but what's more readable at a glance?

if index == -1:
   do_something()

or

const NOT_FOUND = -1
if index == NOT_FOUND:
    do_something()

At the very least consider using an enum to access your array:

class_name TypeChart
enum TYPE { NORMAL = 0,
FIRE, WATER, ELETRIC, GRASS,...., FAIRY}
chart[TYPE.NORMAL][TYPE.WATER] # same thing as chart[0][2]

or from outside of the class:

move.type = TypeChart.TYPE.ELECTRIC # move.type set to 3
Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to webmaster@godotengine.org with your username.