How can I call 'Object's' that have specific Enum value's

Godot Version

4.7

Question

Hello,

I am new to programming, and am learning by making a card game, one goal I have is to have the ability "When specific card is played - draw another card of specific type"

All of my cards are Objects under class names, and their types are from an Enum list.

I have tried several things, such as using a mix of for loops and matches, to several other functions meant for Arrays - I’ll spare the details, but would love if someone can point me in the right direction.

Each ability lives in three functions:

Firstly, one that calls the needed function within the player manager:

func ability_manager(card: Card):
var wildcard_number = int(card.wildcard_number)
var wildcard = card.wildcard
var wildcard_variable

match card.ability_category:
	###CARD ABILITY HANDLED HERE###
	Card.AbilityCategory.DRAW:
		draw_cards(wildcard_number)
	Card.AbilityCategory.DISCARD_REDRAW:
		discard_cards()
		await(3.0)
		draw_cards(wildcard_number)
	Card.AbilityCategory.DRAW_SPECIFIC:
		for i in range(wildcard_number):
			draw_specific_card(wildcard)
	Card.AbilityCategory.HAND_VALUE_MANIPULATION:
		update_value(wildcard_number)

Bolded is the function for this ability.

This calls the actual abilities function, within the player:

func draw_variable_card(card: Card) -> void:
	#THIS IS NOT WORKING AS INTENDED
	if !character.draw_pile.cards.is_empty():
		hand.add_card(character.draw_pile.draw_variable_card(card))
		print("character.draw_pile.draw_variable_card(card_type)")
	#if character.mana == 0:
		#hand.disable_hand()
	#else:
		#pass

This is setting the card needed to draw, and calling the Deck’s draw card function - which is:

func draw_card() -> void:
	var tween = create_tween()
	if !character.draw_pile.cards.is_empty():
		hand.add_card(character.draw_pile.draw_card())
		if character.mana == 0:
			hand.disable_hand()
		if hand.get_child_count() >= 6:
			hand.add_theme_constant_override('separation', 800 / hand.get_child_count())

And here is a version I have been trying to type up - but where I am lost (within the deck)

func draw_variable_card(card: Card) -> Card:
	if cards.has(card):
		cards.erase(card)
		card_pile_size_changed.emit(cards.size())
		return card
	else:
		return null

This is my first time posting on anything like this, so please let me know if you need more info.

Would love help, or just to be pointed to a function that may do exactly what I am looking for.

Thank you again.

It would help to format your code so we can see the indentation etc

I agree with gertkeno, please format your code by typing ``` before any code you paste.

Could you tell us what specifically isn’t working?

Thank you, just fixed the correct format - I think.

Thank you, should be fixed now,

and the issue I am having is essentially that the return is always null:

Here is the most recent iteration I am trying out:

I am not sure how to:

  1. Look through the objects in an array, that contain a specific Export Variable (choses from an Enum list.
  2. Assign that card (with the specific variable) to be the card that gets drawn - or ‘returned’
func draw_variable_card() -> Card:
	var card
	if cards.has(Card.CardType.CRITTER):
		card = cards.find(Card.CardType.CRITTER)
		cards.erase(card)
		card_pile_size_changed.emit(cards.size())
		return card
	else:
		return null

if cards is an Array then .find and .erase is being used improperly here. Otherwise it may help to show us your cards and Card type.

Do you get any errors? Your initial post has a #THIS IS NOT WORKING section commented, but you don’t explain what you expect it to do, nor what it does wrong? Can you explain what you expect vs what really happens?

Yes, of course,

so essentially, I have an export variable “CardType” that pulls from an Enum -

enum CardType {FLORA, DOODAD, GIZMO, CRITTER, SIMPLETON}

this is within the card ('card ’ is a resource) script - and i have ‘tres’ files for each specific card that I use to define what the card type is for each separate Card.

In the actual ‘Level’ scene, I use a ‘Deck’ script that returns the front card in the ‘cards’ array -

func draw_card() -> Card:
	var card = cards.pop_front()
	card_pile_size_changed.emit(cards.size())
	return card

this returns the card to the Player Manager script, function:

func draw_card() -> void:
	var tween = create_tween()
	if !character.draw_pile.cards.is_empty():
		hand.add_card(character.draw_pile.draw_card())
		if character.mana == 0:
			hand.disable_hand()
		if hand.get_child_count() >= 6:
			hand.add_theme_constant_override('separation', 800 / hand.get_child_count())

These two work as expected - telling the deck what card to return, and this is then ‘drawn’ by the player into their ‘hand’


My specific goal, is to find a way to return a card (in the first ‘func draw_card’) ONLY if the Card.CARDTYPE enum matches Card.CARDTYPE.CRITTER (for example)

That way the player will draw a card that fits that criteria, ignoring the front card.

I tried using for loops before this,

but I am just trying to see if there is even a way to look in an array of objects, and check for a specific ‘CardType’ - and then return it.


Currently, what is happening, is it is returning null - even if a card does fit the criteria.

My most recent error was:

Invalid access to property or key 'value' on a base object of type 'Nil'.

I hope this makes sense, and thank you for your help here!

You will have to use loops, finding the first object of a type won’t be too difficult, here’s a function that matches what find does while only comparing the variable my_card_type_variable

func find_of_type(deck: Array[Card], type: CardType) -> int:
    var index: int = 0
    while index < deck.size():
        if deck[index].my_card_type_variable == type:
            return index
        index += 1
    return -1 # couldn't find anything

Still, make sure you are using find and erase correctly. Find returns an index, not the actual object, erase takes in actual objects, not indexes.

func draw_variable_card() -> Card:
	var card_index: int = find_of_type(cards, Card.CardType.CRITTER)
	if card_index == -1:
		return null
	else:
		var card: Card = cards[card_index]
		cards.remote_at(card_index)
		card_pile_size_changed.emit(cards.size())
		return card

I don’t see you using value anywhere in your samples so this error may be irrelevant or the code pasted is.