Adding scenes to an array before runtime

Godot Version

4.2.1

Question

So, I am making an ability system and I currently have two different abilities aswell as an object that is used to add a specfic ability to the player script. But moving forward i would like for the object to not have a specific ability attached but instead it should pick a random ability from an array of available abilities. The idea I have is that it should look something like this:

class_name ability_pick_up
extends Node2D

var next_ability = abilities_array.pick_random()
#where the array contains a series of prepackaged ability scenes
#currently the variable above looks is defined as such:
#var next_ability = preload("res://Abilities/explosion.tscn")


func _on_area_2d_body_entered(body):
	if body.is_in_group("Player_body"):
		body.current_ability1 = next_ability
		self.queue_free()

The issue I’m facing is that I have minimal experience with arrays and I’m unsure as to how i would approach this issue

Any and all help is appreciated :slight_smile:

I would suggest that you do not have an array of preloaded scenes but have just their references. I would do it something like this (untested):

var ability_path: String = "...res://Abilities/%s.tscn"
var all_abilities: Array = [
   "explosion",
   "invisibility",
   "bombs",
]

# Then later when you need it
var next_ability: PackedScene = load(ability_path % all_abilities.pick_random())

Otherwise you may be loading, say, twenty ability scenes, and using hardly any of them.

You may also not want the abilities repeated until they are all exhausted, in which case you would not pick from all_abilities but from a duplicate like this:

# additional var
var available_abilities: Array = []

# First check it is not empty
if available_abilities.is_empty():
   available_abilities = all_abilities.duplicate()

# Then after selecting one just delete it from the available list
var selected_ability: String = available_abilities.pick_random()
var next_ability: PackedScene = load(ability_path % selected_ability)
all_abilities.erase(selected_ability)



PS I don’t think your filenames should be capitalised btw. So your Abilities folder should be called ā€˜abilities’.

2 Likes

aah so whenever i make an ability i should make a line of code that adds the name of the ability to the ā€œall abilities arrayā€ as a string so that the string name can replace %s in the next_ability line?

And when the player picks up the ā€œability_pick_upā€ a random string name is selected (and then also a random ability)?

I’m relatively new to godot I just want to make sure I understand it right

1 Like

Nevermind the string just needs to be added in the ability pick up script (I think)

That’s about right. The only reason for a root_path variable is not to store the same info again and again in your array.

There are actually quite a few ways to go about this, for instance I would usually have a ā€œlevel_builderā€ run before the main scene is run. The level builder does all the work writing to a singleton called something like level_data. In that level builder you would have all your ability scenes as children of an abilities container, and then making the array would be just a case of doing get_children().

This is something you could do in your main game loop, just have all your ability scenes as children of an ā€˜abilities’ node. Then rather than maintaining your array you could just get_children to create your available_abilities list. If you are not going to have too many, and they are relatively small scenes, this will have little impact on your game. Perhaps better than loading them when needed if you are going to be re-using all of them again and again.

Hope that helps in some way.

Edit: Without seeing more of your code structure and implementation plans it is hard to be exact, but yes, I think your pick_ability script would be attached to a node and that node could have all your abilities as children right from the start.

1 Like

It does!
But currently I plan on having making a roguelite so having a lot of abilities that can mix and match to make different combinations. I thought that having them as individual scenes would be best.

Btw when i ran the code i got the error

"E 0:00:01:0428 ability_pick_up.gd:11 @ @implicit_new(): Cannot open file ā€˜ā€¦res:/Abilities/explosion.tscn’.
"

As well as a similar error for the other ability I have

Definitely have your abilities as separate scenes. You can then just add those scenes to your pick_ability folder (or load them when needed is fine of course).

Is that the location and correct name of your scene?
res:/Abilities/explosion.tscn

1 Like

Is that the location and correct name of your scene?
res:/Abilities/explosion.tscn

As far as I can see yes

Nevermind lol

I forgot to remove the 3 dots at the start

"...res://Abilities/%s.tscn"

It works great! Thank you so much!

1 Like

From the file system, your abilities folder looks empty?

It should look something more like this example:

Your explosion.tscn scene should be in your Abilities folder (if that is the structure you are creating).

1 Like

Thats just the way i have it set up
The reason it looks empty is because there are no other folders but if you look at the bottom half (belov the bar with ā€œFilter Filesā€) my ability scenes and scripts are there :slight_smile:

Sorry, my bad. I was expecting sub folders. Give me a mo to take another look.

You are missing a /
res://Abilities/explosion.tscn

PS I did say this was untested example code, sorry if my example was bad.

It works amazing after i removed the three dots! This has been a huge help :))

2 Likes