I’m not drawing cards from my decklist/JSON

33 Views Asked by At

enter image description hereI’m getting my data for the cards as a JSON, it’s added to my deck list but when I start drawing the card’s ID which dictates the card’s info isn’t the same but random. For example:

{ "cardsWithThisId": [ 0, 0, 0, 0, 0, 0, 0, 0, 40 ] }

is in my JSON this should mean I have 40 cards with the ID of 8 since it’s 0 - 8 currently.

It could be the shuffle that's failed to work but I'm unsure fully

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;
using System.IO;
public class PlayerDeck : MonoBehaviour
{
    public List<Card> deck = new List<Card>();
    public List<Card> container = new List<Card>();
    public static List<Card> staticDeck = new List<Card>();
    private CustomDeckData deckData;
    public int x;
    public static int deckSize;

    public GameObject cardInDeck1;
    public GameObject cardInDeck2;
    public GameObject cardInDeck3;
    public GameObject cardInDeck4;

    public GameObject CardBack;
    public GameObject CardToHand;
    public GameObject Deck;

    public GameObject[] Clones;

    public GameObject Hand;

    // Reference to ThisCard script
    public ThisCard thisCardScript;

    public TextMeshProUGUI LoseText;

    public GameObject LoseTextGameObject;
    // Start is called before the first frame update
    void Start()
    {
        LoadDeckFromJSON(); // Load the deck from JSON

        thisCardScript = GetComponentInChildren<ThisCard>();
        StartCoroutine(StartGame());
    }

    // Update is called once per frame
    void Update()
    {
        if (deckSize <= 0)
        {
            LoseTextGameObject.SetActive(true);
            LoseText.text = "Deck Out, You Lose";

        }


        staticDeck = deck;
        if (deckSize < 30)
        {
            cardInDeck1.SetActive(false);
        }
        if (deckSize < 20)
        {
            cardInDeck2.SetActive(false);
        }
        if (deckSize < 2)
        {
            cardInDeck3.SetActive(false);
        }
        if (deckSize < 1)
        {
            cardInDeck4.SetActive(false);
        }

        if (ThisCard.drawX > 0)
        {
            StartCoroutine(Draw(ThisCard.drawX));
            ThisCard.drawX = 0;
        }

        if (TurnSystem.startTurn == true)
        {
            StartCoroutine(Draw(1));
            TurnSystem.startTurn = false;
        }
    }
    void LoadDeckFromJSON()
    {
        // Load the JSON file into a string
        string jsonString = File.ReadAllText(Application.persistentDataPath + "/deck.json");

        // Parse the JSON string into a CustomDeckData object
        deckData = JsonUtility.FromJson<CustomDeckData>(jsonString);

        if (deckData != null)
        {
            // Clear the existing deck
            deck.Clear();

            // Populate the deck based on the loaded data
            for (int i = 0; i < deckData.cardsWithThisId.Length; i++)
            {
                int cardId = deckData.cardsWithThisId[i];

                // Find the corresponding card in the database and add it to the deck
                for (int j = 0; j < cardId; j++)
                {
                    Card foundCard = CardDataBase.cardList.Find(card => card.id == i);

                    if (foundCard != null)
                    {
                        deck.Add(foundCard);
                    }
                }
            }

            deckSize = deck.Count; // Set the deck size based on the loaded deck
        }
    }
    IEnumerator Example()
    {
        yield return new WaitForSeconds(1);
        Clones = GameObject.FindGameObjectsWithTag("Deck");

        foreach (GameObject Deck in Clones)
        {
            Destroy(Deck);
        }
    }

    IEnumerator StartGame()
    {
        // Draw 4 initial cards
        for (int i = 0; i <= 4; i++)
        {
            DrawCardToHand();
            yield return new WaitForSeconds(1);
        }
    }

    public void DrawCardToHand()
    {
        if (deckData != null && deckData.cardsWithThisId.Length > 0)
        {
            // Iterate through the loaded deck IDs
            foreach (int cardId in deckData.cardsWithThisId)
            {
                // Find the corresponding card in the database
                Card drawnCard = CardDataBase.cardList.Find(card => card.id == cardId);

                // If the card is found, draw it and remove from the deck
                if (drawnCard != null)
                {
                    // Set the ID on the ThisCard script before instantiating
                    if (thisCardScript != null)
                    {
                        thisCardScript.thisID = drawnCard.id;
                    }
                    else
                    {
                        Debug.LogError("thisCardScript is null");
                    }

                    // Instantiate the CardToHand object
                    Instantiate(CardToHand, transform.position, transform.rotation);
                    deckSize--;
                    return; // Exit the method after drawing one card
                }
            }

            Debug.LogWarning("No more cards to draw from the loaded deck.");
        }
        else
        {
            Debug.LogWarning("Deck data is missing or empty, cannot draw more cards.");
        }
    }
    public void Shuffle()
    {
        for (int i = 0; i < deckSize; i++)
        {
            container[0] = deck[i];
            int randomIndex = Random.Range(i, deckSize);
            deck[i] = deck[randomIndex];
            deck[randomIndex] = container[0];
        }

        Instantiate(CardBack, transform.position, transform.rotation);

        StartCoroutine(Example());
    }

    IEnumerator Draw(int x)
    {
        for (int i = 0; i < x; i++)
        {
            yield return new WaitForSeconds(1);

            DrawCardToHand();
        }
    }
}
[System.Serializable]
public class CustomDeckData
{
    public int[] cardsWithThisId;
}

This is the card code if you want to check it out though I wish to focus on the playerdeck code.

using System.Collections.Generic;
using UnityEngine;
using TMPro;
using UnityEngine.UI;

public class ThisCard : MonoBehaviour
{
    private List<Card> thisCardList = new List<Card>();
    public int thisID;

    public int id;
    public string cardName;
    public int cost;
    public int power;
    public string cardDescription;

    public TextMeshProUGUI nameText;
    public TextMeshProUGUI costText;
    public TextMeshProUGUI powerText;
    public TextMeshProUGUI descriptionText;

    public Sprite thisSprite;
    public Image thatImage;

    public Image frame;

    public bool cardBack;
    CardBack CardBackScript;

    public GameObject Hand;

    public int numberOfCardsInDeck;

    public bool canBeSummon;
    public bool summoned;
    public GameObject battleZone;


    public static int drawX;
    public int drawXcards;
    public int addXmaxGil;

    public GameObject attackBorder;
    public GameObject Target;
    public GameObject Enemy;
    public bool summoningSickness;
    public bool cantAttack;
    public bool canAttack;
    public static bool staticTargeting;
    public static bool staticTargetingEnemy;

    public bool targeting;
    public bool targetingEnemy;

    public bool onlyThisCardAttack;

    public GameObject summonBorder;

    public bool canBeDestroyed;
    public GameObject Graveyard;
    public bool beInGraveyard;
    public int hurted;
    public int actualpower;
    public int returnXcards;
    public bool useReturn;
    public int resurrectXcards;
    public static bool UcanReturn;
    public int healXpower;
    public bool canHeal;
    public static bool useRevive;
    public int boostXpower;
    public bool canBoost;

    public GameObject EnemyZone;
    public AICardToHand aiCardToHand;
    public bool spell;
    public int damageDealtBySpell;
    public bool dealDamage;
    public bool stopDealDamage;
    public bool ward;
    public bool directattack;
    public GameObject wardguard;
    // Start is called before the first frame update
    void Start()
    {
        CardBackScript = GetComponent<CardBack>();
        thisCardList.Add(CardDataBase.cardList[Random.Range(1, CardDataBase.cardList.Count)]);
        thatImage.sprite = thisCardList[0].thisImage;

        //UpdateUI();
        canBeSummon = false;
        summoned = false;

        drawX = 0;

        canAttack = false;
        summoningSickness = true;
        Enemy = GameObject.Find("Enemy HP");
        targeting = false;
        targetingEnemy = false;
        beInGraveyard = false;
        canHeal = true;
        canBoost = true;
        directattack = true;
        EnemyZone = GameObject.Find("EnemyZone");
        Graveyard = GameObject.Find("MyGraveyard");


    }

    // Update is called once per frame
    void Update()
    {
        Hand = GameObject.Find("Hand");
        if (this.transform.parent == Hand.transform)
        {
            cardBack = false;
        }

        id = thisCardList[0].id;
        cardName = thisCardList[0].cardName;
        cost = thisCardList[0].cost;
        power = thisCardList[0].power;
        actualpower = power - hurted;
        cardDescription = thisCardList[0].cardDescription;
        thisSprite = thisCardList[0].thisImage;

        drawXcards = thisCardList[0].drawXcards;
        addXmaxGil = thisCardList[0].addXmaxGil;
        returnXcards = thisCardList[0].returnXcards;
        healXpower = thisCardList[0].healXpower;
        boostXpower = thisCardList[0].boostXpower;
        spell = thisCardList[0].spell;
        damageDealtBySpell = thisCardList[0].damageDealtBySpell;
        ward = thisCardList[0].ward;
        resurrectXcards = thisCardList[0].resurrectXcards;
        // Check for color condition using the color property of the Card class
        if (thisCardList[0].color == "White")
        {
            frame.color = new Color32(255, 255, 255, 255);  // Set the color to white
        }
        else if (thisCardList[0].color == "Blue")
        {
            frame.color = new Color32(26, 109, 236, 255);  // Set the color to white
        }
        else if (thisCardList[0].color == "Green")
        {
            frame.color = new Color32(122, 236, 26, 255);  // Set the color to white
        }
        else if (thisCardList[0].color == "Black")
        {
            frame.color = new Color32(51, 32, 32, 255);  // Set the color to white
        }
        CardBackScript.UpdateCard(cardBack);
        UpdateUI();

        if (this.tag == "Clone")
        {
          
            thisCardList[0] = PlayerDeck.staticDeck[PlayerDeck.deckSize - 1];

            PlayerDeck.deckSize--;
            cardBack = false;
            this.tag = "Untagged";
        }
        if (this.tag != "Clone")
        {
            if (TurnSystem.currentGil >= cost && summoned == false && beInGraveyard == false && TurnSystem.isYourTurn ==true)
            {
                canBeSummon = true;
            }
            else
            {
                canBeSummon = false;
            }

            if (canBeSummon == true)
            {
                gameObject.GetComponent<Draggable>().enabled = true;
            }
            else
            {
                gameObject.GetComponent<Draggable>().enabled = false;
            }

            battleZone = GameObject.Find("Zone");

            if (!summoned && this.transform.parent == battleZone.transform)
            {
                Summon();
            }
            if(ward == true && summoned == true)
            {
                wardguard.SetActive(true);
            }
            else
            {
                wardguard.SetActive(false);
            }
        }

        if(canAttack == true && beInGraveyard == false )
        {
            Debug.Log("Can attack1.");
            attackBorder.SetActive(true);
        }
        else
        {
            Debug.Log("Can't attack1.");
            attackBorder.SetActive(false);
        }

        if(TurnSystem.isYourTurn == false && summoned == true)
        {
            summoningSickness = false;
            cantAttack = false;
        }

        if(TurnSystem.isYourTurn == true && summoningSickness == false && cantAttack == false)
        {
            canAttack = true;
        }
        else
        {
            canAttack = false;
        }
        targeting = staticTargeting;
        targetingEnemy = staticTargetingEnemy;

        if(targetingEnemy == true)
        {
            Target = Enemy;
        }
        else
        {
            Target = null;
        }

        if(targeting == true && onlyThisCardAttack == true)
        {
            Attack();
        }

        if(canBeSummon == true || UcanReturn == true && beInGraveyard == true || useRevive == true && beInGraveyard == true) 
        { 
            summonBorder.SetActive(true);
        
        
        }
        else
        { 
            summonBorder.SetActive(false);
        }
       /* if (canBeSummon == true || useRevive == true && beInGraveyard == true)
        {
            summonBorder.SetActive(true);
            Debug.Log("revive border test.");


        }
        else
        {
            summonBorder.SetActive(false);
        }*/

        if (actualpower <= 0 && spell == false)
        {
            Destroy();
            canBeDestroyed = true;
        }
        if(returnXcards > 0 && summoned == true && useReturn == false && TurnSystem.isYourTurn == true)
        {
            Return(returnXcards);
            useReturn = true;
        }

        if (resurrectXcards > 0 && summoned == true && useRevive == false && TurnSystem.isYourTurn == true)
        {
            Revive(resurrectXcards);
            useRevive = true;
        }
        if (TurnSystem.isYourTurn == false)
        {
            useRevive = false;
            useReturn = false;
        }
        
        if(canHeal == true && summoned == true)
        {
            Heal();
            canHeal = false;
        }

        if(canBoost == true && summoned == true)
        {
           // AttackBoost();
           // canBoost = false;
        }
        if(damageDealtBySpell >0)
        {
            dealDamage = true;
        }
        if(dealDamage == true && this.transform.parent == battleZone.transform && spell ==true)
        {
            Debug.Log("spell test1.");
            attackBorder.SetActive(true);
        }
        else if(dealDamage == false && this.transform.parent == battleZone.transform && spell == true)
        {
            Debug.Log("spell test2.");  
            attackBorder.SetActive(false);
        }
        if(dealDamage == true && this.transform.parent == battleZone.transform)
        {
            Debug.Log("Attempting to speelll test.");
            dealxDamage(damageDealtBySpell);
        }
        if(stopDealDamage == true)
        {
            Debug.Log("Stop deal damage test.");
            attackBorder.SetActive(false);
            dealDamage = false;
        }
        if(this.transform.parent == battleZone.transform && spell == true && dealDamage == false)
        {
            Debug.Log("Spell gone");
            canBeDestroyed = true;
            Destroy();
        }
        foreach (Transform child in EnemyZone.transform)
        {
            AICardToHand childAICard = child.GetComponent<AICardToHand>();
            if (childAICard.ward == true)
            {
                directattack = false;
            }
            else
            {
                directattack = true;
            }
        }

    }
    public void Summon()
    {
        TurnSystem.currentGil -= cost;
        summoned = true;
        MaxGil(addXmaxGil);
        drawX = drawXcards;
    }

    public void MaxGil(int x) 
    {
        TurnSystem.maxGil += x;
    }
    void UpdateUI()
    {

        nameText.text = cardName;
        costText.text = cost.ToString();
        powerText.text = actualpower.ToString();
        descriptionText.text = cardDescription;
        thatImage.sprite = thisSprite;
    }
    public void Attack()
    {
        if (canAttack && summoned && Target != null)
        {
            Debug.Log("Attempting to attack.");

            if (Target == Enemy && directattack == true)
            {
                Debug.Log("Attacking Enemy");
                EnemyHp.staticHp -= power;
                targeting = false;
                cantAttack = true;
            }
        }
        else
        {
            // Debug.Log("Attempting to attack AI.");

            foreach (Transform child in EnemyZone.transform)
            {
                AICardToHand childAICard = child.GetComponent<AICardToHand>();

                if ( childAICard.isTarget == true && cantAttack == false)
                {
                    Debug.Log("Target found in EnemyZone.");
                    childAICard.hurted += actualpower;  // Adjusting hurted value by the power of the attacking card
                    hurted = childAICard.actualpower;
                    cantAttack = true;
                }
               /* else
                {
                    Debug.LogError("AICardToHand component not found or conditions not met on the target AI card.");
                }*/
            }
        }
    }



    public void UntargetEnemy()
    {
        staticTargetingEnemy = false;
    }
    public void TargetEnemy()
    {
        staticTargetingEnemy = true;
    }

    public void StartAttack()
    {
        staticTargeting = true;
    }

    public void StopAttack()
    {
        staticTargeting = false;

    }
    public void OneCardAttack()
    {
        onlyThisCardAttack = true;
    }
    public void OneCardAttackStop()
    {
        onlyThisCardAttack = false;

    }

    public void Destroy()
    {
        Graveyard = GameObject.Find("MyGraveyard");

        if(canBeDestroyed == true)
        {
            this.transform.SetParent(Graveyard.transform);
            canBeDestroyed = false;
            summoned = false;
            beInGraveyard = true;

            hurted = 0;
        }
    }

    public void Revive(int x)
    {
        for (int i = 0; i <= x; i++)
        {
            ReviveCard();
        }
    }

    public void ReviveCard()
    {
        Debug.Log("Revive card test.");
        useRevive = true;
        actualpower += power;

    }
    public void Return(int x)
    {
        for(int i = 0; i <= x; i++)
        {
            ReturnCard();
        }
    }
    
    public void ReturnCard()
    {
        UcanReturn = true;
    }

    public void ReturnThis()
    {
        if (beInGraveyard == true && UcanReturn == true && Graveyard.transform.childCount > 0)
        {
            this.transform.SetParent(Hand.transform);
            UcanReturn = false;
            beInGraveyard = false;
            summoningSickness = true;
        }
        else if (beInGraveyard == true && useRevive == true && Graveyard.transform.childCount > 0 && spell == false)
        {

            this.transform.SetParent(battleZone.transform);
            useRevive = false;
            beInGraveyard = false;
            summoningSickness = true;

        }
        /* else if (beInGraveyard == true && useRevive == true && Graveyard.transform.childCount == 0)
         {
             this.transform.SetParent(Hand.transform);
             UcanReturn = false;
             beInGraveyard = false;
             summoningSickness = true;
         }*/

    }

   /* public void ReviveThis()
    {
        if (beInGraveyard == true && useRevive == true && Graveyard.transform.childCount > 0)
        {
            Debug.Log("Reviving card");
            this.transform.SetParent(Hand.transform);
            useRevive = false;
            beInGraveyard = false;
            summoningSickness = true;
        }
        else
        {
            Debug.Log("Revive conditions not met");
            Debug.Log("beInGraveyard: " + beInGraveyard);
            Debug.Log("useRevive: " + useRevive);
            Debug.Log("Graveyard child count: " + Graveyard.transform.childCount);
        }
    }*/
    public void Heal()
    {
        PlayerHp.staticHp += healXpower;
    }

    /*public void AttackBoost()
    {
        power += boostXpower; // Update power first
        actualpower = power - hurted; // Update actualpower after modifying power
        UpdateUI();
    }*/
    public void dealxDamage(int x)
    {
        if (Target != null)
        {
            if (staticTargetingEnemy = true && stopDealDamage == false && Input.GetMouseButton(0))
            {
                EnemyHp.staticHp -= damageDealtBySpell;
                stopDealDamage = true;

            }

        }

        else
        {
            foreach (Transform child in EnemyZone.transform)
            {
               Debug.Log("Attempting to deal damage to AI.");
                AICardToHand childAICard = child.GetComponent<AICardToHand>();

                if (childAICard.isTarget == true && stopDealDamage == false)
                {
                    
                    childAICard.hurted += damageDealtBySpell;  // Adjusting hurted value by the power of the attacking card
                    stopDealDamage = true;
                   Debug.Log("Test)");
                }
            }
        }
        }
    
}
1

There are 1 best solutions below

1
derHugo On

In DrawCardToHand you iterate on the original deckData.cardsWithThisId.

Instead you should probably rather use the deck!

Further the additional fields like deckSize etc are not really necessary and more work to keep them in sync.

You should probably rather do something like

// use correct prefab type - see further below
// ThisCard is btw a very misleading class name
public ThisCard CardToHand;

public void DrawCardToHand()
{
    // do not hide essential issues like deckData being null
    // You would WANT an exception in that case because it means 
    // that something is essentially wrong in your app

    if (deck.Count > 0)
    {
        // there is no real need to shuffle your deck
        // simply access a random index
        var randomIndex = Random.Range(0, deck.Count);

        var drawnCard = deck[randomIndex];
        deck.RemoveAt(randomIndex);

       
        // // Set the ID on the ThisCard script before instantiating
        // No! Instead rather use correct prefab type and set it on the newly spawned instance!
        var cardInstance = Instantiate(CardToHand, transform.position, transform.rotation);
        cardInstance.thisID = drawnCard.id;
    }
    else
    }
        Debug.LogWarning("No more cards to draw from the loaded deck.");
    }
}

Then further in ThisCard

  • what is the difference between id and thisID
  • why does it have a List<Card> thisCardList itself?
  • and why does it hard overrule whatever you might be setting from the outside with hard coded values from thisCardList[0] every frame in Update?

After spawning the cardInstance I would rather expect you fill it now with the according drawnCard data and do something like e.g.

public class ThisCard : MonoBehaviour
{
    // use a property to make it read-only to the public
    public Card AssociatedCard { get; private set; }
    // plus, there is no need to store all these individually (single source of truth principle)
    //public int id;
    //public string cardName;
    //public int cost;
    //public int power;
    //public string cardDescription;

    public void Initialize(Card card)
    {
        AssociatedCard = card;

        // TODO initialize displayed visuals accordingly
    }

    ...
}

and then in the above do

var cardInstance = Instantiate(CardToHand, transform.position, transform.rotation);
cardInstance.Initialize(drawnCard);