I'm looking for some guidance on how to develop a card combat system similar to Legends of RuneTerra auto combat. I'm a bit lost on how to get the proper card info from each drop zone (5 each player) and how to compare them.
I'm trying to run a combat function when both players have pressed their End Turn button again during the Execute phase. Currently, pressing the button just disconnects a player (there was a Red jester card across from the Blue one).
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Mirror;
public class CombatManager : NetworkBehaviour
{
// Reference to the GameManager
public GameManager gameManager;
// Reference to the PlayerManager
public PlayerManager playerManager;
// Start is called before the first frame update
void Start()
{
// Find references to GameManager and PlayerManager
gameManager = GameObject.Find("GameManager").GetComponent<GameManager>();
playerManager = GameObject.Find("PlayerManager").GetComponent<PlayerManager>();
}
// Method to compare power and health values of cards in the first drop zones of both players
public void CompareCards()
{
// Get the card GameObjects from the first drop zones of both players
GameObject allyCardObject = playerManager.AllyDropZone1?.transform?.GetChild(0)?.gameObject;
GameObject enemyCardObject = playerManager.EnemyDropZone1?.transform?.GetChild(0)?.gameObject;
// Check for null references
if (allyCardObject == null || enemyCardObject == null)
{
Debug.LogError("One or both card GameObjects are null.");
return; // Exit the method to prevent further execution
}
// Get the Card components attached to the card GameObjects
Card allyCard = allyCardObject.GetComponent<Card>();
Card enemyCard = enemyCardObject.GetComponent<Card>();
// Check for null Card components
if (allyCard == null || enemyCard == null)
{
Debug.LogError("One or both Card components are null.");
return; // Exit the method to prevent further execution
}
// Display the initial health values before combat
Debug.Log("Ally Card Initial Health: " + allyCard.health);
Debug.Log("Enemy Card Initial Health: " + enemyCard.health);
// Subtract the power of the enemy card from the health of the ally card
allyCard.health -= enemyCard.power;
// Display the updated health values after combat
Debug.Log("Ally Card Updated Health: " + allyCard.health);
Debug.Log("Enemy Card Health: " + enemyCard.health);
// Check if the ally card's health is less than or equal to 0
if (allyCard.health <= 0)
{
// Destroy the ally card GameObject if its health is <= 0
NetworkServer.Destroy(allyCardObject);
}
// Notify clients to update the displayed cards after combat
RpcUpdateCombatResult(allyCardObject, allyCard.health);
}
// Method to notify clients to update the displayed cards after combat
[ClientRpc]
private void RpcUpdateCombatResult(GameObject cardObject, int newHealth)
{
// Update the health of the card on the client side
Card card = cardObject.GetComponent<Card>();
card.health = newHealth;
// Implement logic to update the UI or perform other actions based on the combat result
}
}
public class PlayerManager : NetworkBehaviour
{
//Start of all network shared objects & variables//
public GameManager GameManager;
public GameObject PlayerCard;
public CombatManager CombatManager;
//All ally objects
public int AllyHealth;
public GameObject AllyDropZone1;
public GameObject AllyDropZone2;
public GameObject AllyDropZone3;
public GameObject AllyDropZone4;
public GameObject AllyDropZone5;
public GameObject AllyHand;
public GameObject AllyDeck;
//All enemy object
public int EnemyHealth;
public GameObject EnemyDropZone1;
public GameObject EnemyDropZone2;
public GameObject EnemyDropZone3;
public GameObject EnemyDropZone4;
public GameObject EnemyDropZone5;
public GameObject EnemyHand;
public GameObject EnemyDeck;
//Lists that will hold ally and enemy drop zones resepctively
public List<GameObject> AllyDropZones = new List<GameObject>();
public List<GameObject> EnemyDropZones = new List<GameObject>();
//Card list we are pulling from
public static List<Card> cardList = new List<Card>();
//Variable tracking current player
public int CardsPlayed = 0;
[SyncVar]
public int TurnsEnded = 0;
public bool IsMyTurn = false;
//Possible alternative Card List; same purpose but better way of getting it
private List<GameObject> cards = new List<GameObject>();
//Runs the code below when Host+Client/Client button is selected
public override void OnStartClient()
{
base.OnStartClient();
//Connect to GameManager
GameManager = GameObject.Find("GameManager").GetComponent<GameManager>();
//Connects hand and deck of both players to a variable by looking for objects with listed name
AllyHand = GameObject.Find("AllyHand");
AllyDeck = GameObject.Find("AllyDeck");
EnemyHand = GameObject.Find("EnemyHand");
EnemyDeck = GameObject.Find("EnemyDeck");
//Connects each ally drop zones to each variable by looking for objects with listed name
AllyDropZone1 = GameObject.Find("AllyDropZone");
AllyDropZone2 = GameObject.Find("AllyDropZone (1)");
AllyDropZone3 = GameObject.Find("AllyDropZone (2)");
AllyDropZone4 = GameObject.Find("AllyDropZone (3)");
AllyDropZone5 = GameObject.Find("AllyDropZone (4)");
//Connects each enemy drop zones to each variable by looking for objects with listed name
EnemyDropZone1 = GameObject.Find("EnemyDropZone");
EnemyDropZone2 = GameObject.Find("EnemyDropZone (1)");
EnemyDropZone3 = GameObject.Find("EnemyDropZone (2)");
EnemyDropZone4 = GameObject.Find("EnemyDropZone (3)");
EnemyDropZone5 = GameObject.Find("EnemyDropZone (4)");
//Fills Ally list with ally drop zones
AllyDropZones.Add(AllyDropZone1);
AllyDropZones.Add(AllyDropZone2);
AllyDropZones.Add(AllyDropZone3);
AllyDropZones.Add(AllyDropZone4);
AllyDropZones.Add(AllyDropZone5);
//Fills Enemy list will enemy drop zones
EnemyDropZones.Add(EnemyDropZone1);
EnemyDropZones.Add(EnemyDropZone2);
EnemyDropZones.Add(EnemyDropZone3);
EnemyDropZones.Add(EnemyDropZone4);
EnemyDropZones.Add(EnemyDropZone5);
//Determines which player goes first; Whoever presses "Client" button goes first
if (isClientOnly)
{
IsMyTurn = true;
}
//Message to show that client is running; appears in console tab
Debug.Log("OnStartClient was activated");
}
//Starts server (Host + Client)
[Server]
public override void OnStartServer()
{
base.OnStartServer();
//Tells us that the server is running
Debug.Log("OnStartServer was activated");
}
//Command that adds cards to players hands and grants authority
[Command]
public void CmdDealCards()
{
//Fills player's hand with a card and repeats 3 times
for (int i = 0; i < 3; i++)
{
GameObject card = Instantiate(PlayerCard, new Vector2(0, 0), Quaternion.identity);
NetworkServer.Spawn(card, connectionToClient);
//Sets current status of the card to "Dealt" which makes it appear in hand for the Server
RpcShowCard(card, "Dealt");
}
//Changes game manager current state
RpcGMChangeState("Compile {}");
}
//Calls upon CmdPlayCard
public void PlayCard(GameObject card)
{
CmdPlayCard(card);
Debug.Log("Cards Played counter: " + CardsPlayed);
}
//Calls upon RocShowCard
[Command]
void CmdPlayCard(GameObject card)
{
RpcShowCard(card, "Played"); //Sets current status of the card to "Played" which makes it appear in a drop zone for the Server
}
//Command to call function that checks if player ends their turn
[Command]
public void CmdEndTurn()
{
Debug.Log("TurnsEnded = " + TurnsEnded);
RpcEndTurn();
if (TurnsEnded == 1)
{
//Changes game manager current state
RpcGMChangeState("Execute {}");
}
Debug.Log("TurnsEnded = " + TurnsEnded);
}
[ClientRpc]
public void RpcEndTurn()
{
PlayerManager pm = NetworkClient.connection.identity.GetComponent<PlayerManager>();
pm.IsMyTurn = !pm.IsMyTurn;
Debug.Log("Ran RpcEndTurn");
}
//Command that initializes combat system
[Command]
public void CmdCombatSystem()
{
CombatManager.CompareCards();
}
//Actual function that moves the recently added card to hand and/or drop zone
[ClientRpc]
void RpcShowCard(GameObject card, string type)
{
if(type == "Dealt") // "Dealt" cards are placed into player's hand and checking ownership allows for it mirror
{
if (isOwned)
{
card.transform.SetParent(AllyHand.transform, false);
}
else
{
card.transform.SetParent(EnemyHand.transform, false);
}
}
else if(type == "Played") // "Played" cards are placed into a player's drop zone and check mirror condition
{
if (CardsPlayed == 5)
{
CardsPlayed = 5;
}
if (isOwned)
{
//card.transform.SetParent(AllyDropZones[CardsPlayed].transform, false);
card.transform.SetParent(AllyDropZones[CardsPlayed].transform, false);
}
else if (!isOwned)
{
card.transform.SetParent(EnemyDropZones[CardsPlayed].transform, false);
}
//Increases card counter
CardsPlayed++;
Debug.Log("Card ID: " + card.name);
}
}
//Changes GameState by passing Game State name and calling function
//Check Gamemanger to see function def. (TLDR: ReadyClicks var +1)
[ClientRpc]
void RpcGMChangeState(string stateRequest)
{
GameManager.ChangeGameState(stateRequest);
if (stateRequest == "Compile {}")
{
GameManager.ChangeReadyClicks();
}
if(stateRequest == "Execute {}")
{
GameManager.ChangeReadyClicks();
}
}
}