using System.Collections.Generic; using System.Linq; using UnityEngine; public enum PlayerTypes { Player1 = 0, Player2 = 1, Player3 = 2, Player4 = 3 } [System.Serializable] public class PlayerGameData { public PlayerTypes playerType; public GameObject playerCornerEntity; public int startIndex; public int endIndex; public Transform playersParent; public List playerPawns; } public class GameplayManager : MonoBehaviour, IBase, IBootLoader, IDataLoader { [SerializeField] private Transform pointerDebug; [SerializeField] private MeshRenderer pointerMeshRend; [SerializeField] private Material turnMat; [SerializeField] private Material selectMat; [SerializeField] private PlayerGameData[] playerGameDatas; private PlayerTypes currentPlayerTurn; private int currentPlayerTurnIndex = 0; private List playerTypes = new List(); public List PlayerTypesCollection => playerTypes; // private Dictionary playerPawnsDict = new Dictionary>(); private Dictionary playerGameDatasDict = new Dictionary(); private TilesManager tilesManager; private int diceRolledValue; public bool CanRollDice { get; private set; } private bool HasRolledSix = false; public void Initialize() { InterfaceManager.Instance?.RegisterInterface(this); } public void InitializeData() { tilesManager = InterfaceManager.Instance.GetInterfaceInstance(); CanRollDice = true; InitCurrentGamePlayerInfo( new List { PlayerTypes.Player1, PlayerTypes.Player2, PlayerTypes.Player3, PlayerTypes.Player4 }); } // TODO :: Call based on 2P/3P/4P public void InitCurrentGamePlayerInfo(List playerTypes) { this.playerTypes = playerTypes; currentPlayerTurn = playerTypes[currentPlayerTurnIndex]; // initialize the board based on the player types foreach (PlayerGameData playerGameData in playerGameDatas) { if (!playerTypes.Contains(playerGameData.playerType)) { playerGameData.playerCornerEntity.SetActive(false); } else { playerGameDatasDict.Add(playerGameData.playerType, playerGameData); playerGameDatasDict[playerGameData.playerType].playerPawns = new List(); foreach (Transform playerPawnChild in playerGameData.playersParent) { playerGameDatasDict[playerGameData.playerType].playerPawns.Add(playerPawnChild.GetComponent()); } } } } public void EnablePlayerSelectionStates(bool state) { foreach (PlayerPawn playerPawn in playerGameDatasDict[currentPlayerTurn].playerPawns) { if (playerPawn.GetPlayerState() == PlayerState.InFinishingPath) continue; playerPawn.SetPlayerSelectionState(state); } } public void OnDiceRolled(int rolledVal) { CanRollDice = false; // add core dice logic here Debug.Log($"LUDO :: rolledVal: {rolledVal}"); diceRolledValue = rolledVal; if (rolledVal == Ludo_3D_Constants.Max_Dice_Rolls) { // provide option to select a pawn from the list // also play a simple animation before selecting EnablePlayerSelectionStates(true); HasRolledSix = true; pointerMeshRend.material = selectMat; // pointerMeshRend.materials[0] = selectMat; } else // if there are any other pawns that are in safe or moving state { // for player's logic IEnumerable availPlayers = playerGameDatasDict[currentPlayerTurn].playerPawns.Select(pawn => pawn) .Where(pawn => pawn.GetPlayerState() == PlayerState.InSafeZone || pawn.GetPlayerState() == PlayerState.Moving || pawn.GetPlayerState() == PlayerState.InFinishingPath); foreach (PlayerPawn playerPawn in availPlayers) { Debug.Log($"## playerPawn.GetPlayerState(): {playerPawn.GetPlayerState()}"); if (playerPawn.GetPlayerState() == PlayerState.InFinishingPath) { // TODO :: if rolled dice value <= rem tiles to complete in finishing path // TODO :: playerPawn.SetPlayerSelectionState(true); // if (diceRolledValue < 6 - playerPawn.CurrentTileIndex) // TODO :: Change hardcoded value } else { playerPawn.SetPlayerSelectionState(true); } } if (availPlayers.Count() < 1) { SwitchPlayer(); CanRollDice = true; } HasRolledSix = false; } } public void OnPawnSelected(PlayerPawn playerPawn) { EnablePlayerSelectionStates(false); PlayerGameData playerGameData = playerGameDatasDict[currentPlayerTurn]; if (playerPawn.GetPlayerState() == PlayerState.InHome) { playerPawn.MoveToTile( tilesManager.RetrieveTileBasedOnIndex(playerGameData.startIndex).transform.position, onComplete: () => { CanRollDice = true; playerPawn.SetPlayerState(PlayerState.InSafeZone); }, playerGameData.startIndex); return; } else if (playerPawn.GetPlayerState() == PlayerState.InSafeZone || playerPawn.GetPlayerState() == PlayerState.Moving || playerPawn.GetPlayerState() == PlayerState.InFinishingPath) { // move based on the dice value MoveThroughTiles(playerPawn, playerPawn.CurrentTileIndex + 1, targetIndex: playerPawn.CurrentTileIndex + diceRolledValue); } } private void SwitchPlayer() { if (!HasRolledSix) { if (currentPlayerTurn == playerTypes[playerTypes.Count - 1]) { currentPlayerTurnIndex = 0; currentPlayerTurn = playerTypes[currentPlayerTurnIndex]; } else { currentPlayerTurnIndex++; currentPlayerTurn = playerTypes[currentPlayerTurnIndex]; Debug.Log($"currentPlayerTurn: {currentPlayerTurn}"); Debug.Log($"currentPlayerTurnIndex: {currentPlayerTurnIndex}"); } } var tempPos = playerGameDatasDict[currentPlayerTurn].playerCornerEntity.transform.position; pointerDebug.position = new Vector3(tempPos.x, 3f, tempPos.z); pointerMeshRend.material = turnMat; // pointerMeshRend.materials[0] = turnMat; } private void MoveThroughTiles(PlayerPawn playerPawn, int index, int targetIndex) { Tile tile = tilesManager.RetrieveTileBasedOnIndex(index); playerPawn.MoveToTile( tilesManager.RetrieveTileBasedOnIndex(index).transform.position, onComplete: () => { if (playerPawn.GetPlayerState() == PlayerState.InFinishingPath || index == playerGameDatasDict[currentPlayerTurn].endIndex) { // MoveThroughTiles(playerPawn, index, targetIndex); Debug.Log($"IsMovingThroughFinishingPath({currentPlayerTurn}): {index + 1} :: {playerGameDatasDict[currentPlayerTurn].endIndex}"); MoveThroughFinishingPath(playerPawn, 0, targetIndex - index); } else if (index + 1 <= targetIndex) { MoveThroughTiles(playerPawn, index + 1, targetIndex); } else { if (tile.PlayerPawn != null) { // send this pawn back to base } tile.InitPlayerPawn(playerPawn); SwitchPlayer(); } }, index); CanRollDice = true; playerPawn.SetPlayerState(tilesManager.RetrieveTileBasedOnIndex(playerPawn.CurrentTileIndex).IsSafeZone ? PlayerState.InSafeZone : PlayerState.Moving); } private void MoveThroughFinishingPath(PlayerPawn playerPawn, int index, int targetIndex) { playerPawn.SetPlayerState(PlayerState.InFinishingPath); playerPawn.MoveToTile( tilesManager.RetrievePositionForFinishingTile(currentPlayerTurn, index).position, onComplete: () => { Debug.Log($"index: {index}, targetIndex: {targetIndex}"); if (index + 1 < targetIndex) { // MoveThroughTiles(playerPawn, index, targetIndex); MoveThroughFinishingPath(playerPawn, index + 1, targetIndex); } else { SwitchPlayer(); } }, index); } }