Creating a "weapon wheel" using an array

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

Hello, and thanks for clicking on my question.

Long story short, im trying to implement a “weapon selection” at the start of the levels in my game.

I could make this work with a number var to which i add or remove 1, and then go “If var = [number]…” and correspond each number to each weapon, but i’d like to make it more polished and learn more about arrays in the process.

Here’s what im trying to implement:

  1. On a singleton, there’s an array called “unlockedweapons”, and also a boolean var for each weapon (For example “shotgununlocked = false”)

  2. When a weapon is unlocked (“shotgununlocked = true”), it will be added to that “unlockedweapons” array, on a fixed position on the index (for example, the shotgun will be added in position #2) this happens once when the level starts, in a function called “checkguns” which basically checks if vars are true and inserts them into the array.

  3. When the level starts, the player character can interact with the trunk of a car, which pops up the “weapon selection”, you can go up or down the selector to choose your weapon.

My issues are:

  • First of all, how can i script for “Next in array”? Because it doesnt work if, for example, i have the pistol (#0) and the shotgun (#2) unlocked, and the position inbetween is “null”

  • If only the pistol (#0) and the shotgun (#2) are unlocked, how can i make the weapon selector show them next to each other? And then when the SMG (#1) is unlocked, make it so the SMG appears between them? Another solution to this problem could be just making them all appear and the locked ones are darkened and unselectable

Thanks in advance!

:bust_in_silhouette: Reply From: estebanmolca

For the first problem, you can skip the loop step that reads the array using the continue keyword. In this case I verify that the name of the weapon is not null but it can be any condition, then I could save the results in the other array.

var guns= ['ak','','pistol']
func _ready():
	for g in guns:
		if g == "":
			continue
		print(g)

For the second question, the array class has an insert method, which given an index and the data, inserts the data in that index updating the indexes of the following elements. The idea that they appear darkened and unselectable is fine, like the csgo menu. Another idea is to use a dictionary instead of an array, since you could group several data related to each weapon: name, defaul slot, unblocked, price, etc.

    #[name, defaul slot, unblocked, price] 
    var guns= {
       	    weapon_ak47 = ['AK_47', 1, true, 2900] ,
        	weapon_awp = ['AWP' , 3 , false, 4900]
   }
        
        func _ready():
        	#for g in guns.values():
        		#print(g)
        		
        	#guns.weapon_ak47[2] = false	
        	
        	#for g in guns.values():
        		#print(g)
        		
        	for g in guns.values():
        		if g[2] == false:
        			continue
        		print(g)		

There are several ways, if you work with dictionaries, read the documentation carefully since in certain cases it can generate confusion, especially if you nest a lot of data or other dictionaries.

Hey, thanks a lot for the reply!

I could start writing my code and i got some of it working so far, even if i still struggle to understand some things about arrays and their functions.

So… so far i have an array that can correctly display the unlocked guns, with "null"s on the spaces of guns that are not unlocked yet.

Now, you may have answered this next question and i couldnt understand it, but:

(For example) I want the array to start on “Pistol” when the player opens the trunk (Pressing “E”), and then when the player presses up/down, the array moves to the next slot, if that slot is “null” it’s skipped.

Then, when the player presses “E” again, that weapon’s node is added to the player node and the trunk closes.

I have all the code for opening, prompting the “weapon select” wheel, and closing the trunk, but im missing this key part.

Thanks in advance!

Tato64 | 2021-03-09 23:26

Ok, I don’t know how you get if a weapon is locked, so I’m going to assume that you have an array with the weapons and you have another array of the same size that says if it’s locked or not. Then I go through the array of weapons through a for and save in an empty array only the indices that are valid. For example if the array would be [false, true, false, true] you would have to put in the empty array: [1,3].
Then I create an integer variable and increase or decrease it one by one as I press up or down. I use this variable to go through the array with the valid indexes and the value I get from that array I use to select the weapon in the array of weapons. I know it is a bit confusing and maybe there is another shorter way, but it is the idea that I came up with and I share it with you. I leave you an example in pseudocode of how the idea would be, I hope you can adapt it to the project. Any questions here I am listening …

var weapons=  [pistol,smg,shotgun,sniper,machinegun,granade,knife,rpg]
var available=[true,false,false,true,true,true,false,true] #is blocked or unblocked	
var current_slot = 0
var valid_slots = []

func get_unlocked():
	var valid_index = [] #empty nunmbers array to save valid indexes
		for i in range(available.size()): #size is 8 in this case, range for 0 to 7
			if available[i] == false #if gun is locked -->
				continue # --> skip the actual index, jump to next iteration 
			valid_index.append(i) #if gun is unlocked, save te index in the array
		return valid_index #return array and end function 
#according to availables, this function would return [0,3,4,5,7]	

func _process(delta):
	if Input.is_action_just_pressed("e") and others_conditions:
		inventory = true
		valid_slots = get_unlocked() #we obtain the valid indices
	
	if inventory:
		if press up: 
			current_slot += 1
		if press down: 
			current_slot -= 1
		if current_slot > valid_slots.size() - 1:  
			current slot = 0 #back to first
		if current_slot < 0: 
			current slot = valid_slots.size() -1:  #back to end
		var slot_select = valid_slots[current_slot]		
		
		var selected_weapon = weapons[slot_select] 

estebanmolca | 2021-03-10 01:45

Sorry for the late reply, life gets in the way.

But i could understand this perfectly and it works exactly as intended, time for me to polish the final details now.

Thank you so much!

Tato64 | 2021-03-20 05:27