Ludo-3D/Assets/Scripts/Gameplay/GameplayManager.cs
Ashby Issac 6b5dd5d0f0 Bug fixes + Refactored/Restructurd changes + Dice roll logical changes.
Remove event deallocation function call in DiceView due to flow breakage because of timer in delay.
Added a debug test bool inside GameplayManager for testing dice logic without dice animation.
Fixed issue with additional steps being kept track for player (PlayerPawn.cs)
Bound restart logic for the Game over popup alone.
Added a maxDiceSixRollCounter for keeping track of how many times 6 can be rolled.
Fixed issue with wrong player being selected while restart is clicked.
Fixed indexing logical errors while finding possible tile data.
Fixed issue with player attacking another player and moving constantly.
Fixed issue with player not switching when there is no option for dice roll.
Handled dice roll logic when pawns are in finishing path.
Fixed indexing issue with availPlayers collection where wrong indexes were being selected for removing from the collection.
Fixed issue with tile data not resetting on restart.
Restructured logic for showing winners inside Game Over popup.
Restructured GameOverPopup and GameOverScreen with respect to showing/hiding screens/popups.
2026-01-31 20:33:50 +05:30

1094 lines
43 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using DG.Tweening;
using TMPro;
using UnityEngine;
public enum BotMove
{
FinishingPathMove = 0,
SafeMove = 1,
AttackMove = 2,
NormalMove = 3,
NoMoves = 4
}
public class GameplayManager : MonoBehaviour, IBase, IBootLoader, IDataLoader
{
[SerializeField] private bool isDebugTest = false;
public bool IsDebugTest => isDebugTest;
[SerializeField] DiceRollHandler diceRollHandler;
[SerializeField] private int diceValue = 0;
[SerializeField] private int maxDiceSixRollCounter = 2;
[SerializeField] private TextMeshProUGUI diceText;
[SerializeField] private Transform pointerDebug;
[SerializeField] private MeshRenderer pointerMeshRend;
[SerializeField] private Material turnMat;
[SerializeField] private Material selectMat;
[SerializeField] private PlayerGameData[] playerGameDatas;
[SerializeField] private PlayerBaseHandler playerBaseHandler;
private PlayerType currentPlayerTypeTurn;
public PlayerType CurrentPlayerTypeTurn => currentPlayerTypeTurn;
private int currentPlayerTurnIndex = 0;
private List<PlayerType> allPlayerTypes = new List<PlayerType>();
private List<PlayerType> botTypesInGame = new List<PlayerType>();
private List<PlayerData> playerDatas = new List<PlayerData>();
private Dictionary<PlayerType, PlayerGameData> playerGameDatasDict = new Dictionary<PlayerType, PlayerGameData>();
private Dictionary<PlayerType, Dictionary<int, BotMove>> botRuntimeMovementData = new Dictionary<PlayerType, Dictionary<int, BotMove>>();
private TilesManager tilesManager;
private UIManager uIManager;
private GameManager gameManager;
private int diceRolledValue;
private bool CanRollDiceAgain = false; // used for when you get a 6 or when you reach the finish point
private int diceSixRollCounter = 0;
private List<PlayerPawn> availPlayers = new List<PlayerPawn>();
private bool canSwitchPlayer = false;
public bool CanRollDiceForUser
{
get; private set;
}
public int TotalPlayersInGame
{
get; private set;
}
public List<PlayerData> PlayerDatas => playerDatas;
public List<PlayerType> PlayerTypesCollection => allPlayerTypes;
public void Initialize()
{
InterfaceManager.Instance?.RegisterInterface<GameplayManager>(this);
DOTween.useSafeMode = false;
}
public void InitializeData()
{
tilesManager = InterfaceManager.Instance.GetInterfaceInstance<TilesManager>();
uIManager = InterfaceManager.Instance.GetInterfaceInstance<UIManager>();
gameManager = InterfaceManager.Instance.GetInterfaceInstance<GameManager>();
}
public void InitPlayerTypesForPVP(List<PlayerType> types, List<string> names)
{
allPlayerTypes = new List<PlayerType>(types);
playerDatas.Clear();
TotalPlayersInGame = types.Count;
for (int i=0; i<types.Count; i++)
{
playerDatas.Add(new PlayerData
{
playerType = types[i],
playerName = names[i],
});
}
tilesManager.InitTilesData();
playerBaseHandler.InitPlayerTypes(allPlayerTypes);
InitCurrentGamePlayerInfo();
SetCanRollDiceForUser(true);
}
public void InitPlayerTypesForBotMatch(PlayerData selectedPlayerData, int botCount)
{
playerDatas = new List<PlayerData>();
botTypesInGame = new List<PlayerType>();
allPlayerTypes = new List<PlayerType>();
TotalPlayersInGame = botCount + 1;
AssignBotTypes(selectedPlayerData.playerType, botCount);
foreach (PlayerType playerType in Enum.GetValues(typeof(PlayerType)))
{
if (botTypesInGame.Contains(playerType))
{
allPlayerTypes.Add(playerType);
playerDatas.Add(new PlayerData { playerType = playerType, playerName = $"{playerType}" });
}
else if (selectedPlayerData.playerType == playerType)
{
allPlayerTypes.Add(selectedPlayerData.playerType);
playerDatas.Add(new PlayerData { playerType = selectedPlayerData.playerType, playerName = $"{selectedPlayerData.playerName}" });
}
}
tilesManager.InitTilesData();
playerBaseHandler.InitPlayerTypes(allPlayerTypes);
InitCurrentGamePlayerInfo();
InitBotRuntimeData();
AssignPlayerAndBotStates(selectedPlayerData.playerType);
SetCanRollDiceForUser(!botTypesInGame.Contains(allPlayerTypes[0]));
if (botTypesInGame.Contains(allPlayerTypes[0]))
Invoke(nameof(HandleDiceRoll), 1f);
}
private void InitBotRuntimeData()
{
botRuntimeMovementData = new Dictionary<PlayerType, Dictionary<int, BotMove>>();
foreach (var botType in botTypesInGame)
{
PlayerGameData playerGameData = playerGameDatasDict[botType];
if (!botRuntimeMovementData.ContainsKey(botType))
{
botRuntimeMovementData.Add(botType, new Dictionary<int, BotMove>());
}
foreach (var pawn in playerGameData.playerPawnsDict)
{
botRuntimeMovementData[botType].Add(pawn.Value.PlayerId, BotMove.NoMoves);
}
}
}
private void AssignPlayerAndBotStates(PlayerType selectedPlayerType)
{
PlayerBase playerBase = playerBaseHandler.GetPlayerBase(selectedPlayerType);
playerBase.AssignBotState(PawnType.User);
foreach (PlayerType playerType in botTypesInGame)
{
playerBase = playerBaseHandler.GetPlayerBase(playerType);
playerBase.AssignBotState(PawnType.Bot);
}
}
private void AssignBotTypes(PlayerType selectedPlayerType, int botCount)
{
int addedBots = 0;
if (botCount == 1)
{
var playerType = (PlayerType)((int)selectedPlayerType + 2 < Enum.GetValues(typeof(PlayerType)).Length ?
(int)selectedPlayerType + 2 : (int)selectedPlayerType - 2);
botTypesInGame.Add(playerType);
}
else if (botCount == 2)
{
foreach (PlayerType enumType in Enum.GetValues(typeof(PlayerType)))
{
if (enumType == selectedPlayerType) continue;
botTypesInGame.Add(enumType);
addedBots++;
if (addedBots == botCount) break;
}
}
else
{
foreach (PlayerType enumType in Enum.GetValues(typeof(PlayerType)))
{
if (enumType == selectedPlayerType) continue;
botTypesInGame.Add(enumType);
}
}
}
// TODO :: Call based on 2P/3P/4P
public void InitCurrentGamePlayerInfo()
{
currentPlayerTypeTurn = allPlayerTypes[currentPlayerTurnIndex];
Debug.Log($"currentPlayerTypeTurn: {currentPlayerTypeTurn}");
SetCurrentSelectedPointer();
// initialize the board based on the player types
playerGameDatasDict = new Dictionary<PlayerType, PlayerGameData>();
foreach (PlayerGameData playerGameData in playerGameDatas)
{
if (!allPlayerTypes.Contains(playerGameData.playerType))
continue;
Debug.Log($"playerGameData.playerType: {playerGameData.playerType}");
playerGameDatasDict.Add(playerGameData.playerType, playerGameData);
playerGameDatasDict[playerGameData.playerType].playerPawnsDict = new Dictionary<int, PlayerPawn>();
foreach (Transform playerPawnChild in playerGameData.playersParent)
{
if (!playerPawnChild.gameObject.activeInHierarchy) continue;
var pawn = playerPawnChild.GetComponent<PlayerPawn>();
playerGameDatasDict[playerGameData.playerType].playerPawnsDict.Add(pawn.PlayerId, pawn);
}
playerGameDatasDict[playerGameData.playerType].totalPawnsInHome = playerGameDatasDict[playerGameData.playerType].playerPawnsDict.Count;
}
}
public void EnablePlayerSelectionStates(bool state)
{
foreach (var playerPawn in playerGameDatasDict[currentPlayerTypeTurn].playerPawnsDict)
{
if (playerPawn.Value.GetPlayerState() == PlayerState.InFinishingPath) continue;
playerPawn.Value.SetPlayerSelectionState(state);
}
}
public void OnDiceInteracted()
{
diceRollHandler.HandleDiceViewForUser();
}
public void RollDiceForPlayer(int rolledVal)
{
OnDiceRolled(rolledVal);
OnNoMovesLeft();
}
// Summary :: Function will be called and effective when a dice is rolled and no selection of pawns is made.
private void OnNoMovesLeft()
{
if (canSwitchPlayer && !CanRollDiceAgain)
{
Debug.Log($"Switching player");
SwitchPlayer();
}
}
private bool CheckForMaxDiceRollAttempt()
{
if (diceSixRollCounter > maxDiceSixRollCounter) // TODO :: Reset after test
{
CanRollDiceAgain = false;
SwitchPlayer();
return true;
}
return false;
}
private void RollDiceForBot(int rolledVal)
{
Debug.Log($"CallTest: RollDiceForBot");
// OnDiceRolled(diceValue == 0 ? UnityEngine.Random.Range(1, Ludo_3D_Constants.Max_Dice_Rolls + 1) : diceValue);
OnDiceRolled(rolledVal);
SelectPawnFromBotBase();
OnNoMovesLeft();
}
// TODO :: Call right after the dice is rolled with the animation
// What happens when you get a 6
private void SelectPawnFromBotBase()
{
if (canSwitchPlayer || availPlayers.Count() < 1 && !CanRollDiceAgain || !botTypesInGame.Contains(currentPlayerTypeTurn))
{
Debug.Log($"returning from SelectPawnFromBotBase");
return; // Have a better check here
}
Debug.Log($"CallTest: SelectPawnFromBotBase: {currentPlayerTypeTurn}");
var botPawnsDictForCurrentPlayer = botRuntimeMovementData[currentPlayerTypeTurn]; // set the data inside this dict
// check the data from the playerGameDataDict
// change playerPawnsDict to list
// only select the pawns that are active
// if no pawns have left the home select the first pawn inside the base should be selected
int savedPlayerId = -1;
PlayerPawn pawn = null;
Debug.Log($"SelectPawnFromBotBase: availPlayers.Count(): {availPlayers.Count()}, CanRollDiceAgain: {CanRollDiceAgain}");
if (playerGameDatasDict[currentPlayerTypeTurn].totalPawnsInHome == 0)
{
InitActivePlayers();
}
if (availPlayers.Count() < 1 && CanRollDiceAgain) // got a 6 roll value
{
pawn = playerGameDatasDict[currentPlayerTypeTurn].playerPawnsDict.Values.FirstOrDefault(pawn => pawn.GetPlayerState() == PlayerState.InHome);
Debug.Log($"SelectedPawn: {pawn.name}");
OnPawnSelected(pawn);
return;
}
// TODO :: Double check
foreach (var key in botPawnsDictForCurrentPlayer.Keys)
{
Debug.Log($"b :: botPawnsDictForCurrentPlayer[key]: {key}, {botPawnsDictForCurrentPlayer[key]}");
// botPawnsDictForCurrentPlayer[key] = BotMove.NoMoves;
}
Debug.Log($"Before Iterating");
foreach (var playerPawn in availPlayers)
{
int possibleSteps = 0;
Tile possibleTileData = null;
if (playerPawn.GetPlayerState() != PlayerState.InFinishingPath)
FindPossibleTileData(playerPawn, out possibleSteps, out possibleTileData);
if (playerPawn.GetPlayerState() == PlayerState.InFinishingPath || possibleSteps > playerGameDatasDict[currentPlayerTypeTurn].endIndex) // TODO :: have a better second check
{
Debug.Log($"AI playerPawn :: {playerPawn.name} :: {playerPawn.PlayerId} :: inFinishingPath :: canSelectPlayer: {playerPawn.CanSelectPlayer}");
if (playerPawn.CanSelectPlayer)
{
botPawnsDictForCurrentPlayer[playerPawn.PlayerId] = BotMove.FinishingPathMove;
savedPlayerId = playerPawn.PlayerId;
break;
}
else
{
botPawnsDictForCurrentPlayer[playerPawn.PlayerId] = BotMove.NoMoves;
}
}
else if (possibleTileData != null && possibleTileData.IsSafeZone)
{
Debug.Log($"AI playerPawn :: {playerPawn.name} :: {playerPawn.PlayerId} :: safeMove");
botPawnsDictForCurrentPlayer[playerPawn.PlayerId] = BotMove.SafeMove;
}
else if (possibleTileData != null && possibleTileData.HasPawnsAvailable && possibleTileData.CurrentHoldingPlayerType != playerPawn.PlayerType)
{
Debug.Log($"AI playerPawn :: {playerPawn.name} :: {playerPawn.PlayerId} :: attackMove");
botPawnsDictForCurrentPlayer[playerPawn.PlayerId] = BotMove.AttackMove;
}
else
{
Debug.Log($"AI playerPawn :: {playerPawn.name} :: {playerPawn.PlayerId} :: normalMove");
botPawnsDictForCurrentPlayer[playerPawn.PlayerId] = BotMove.NormalMove;
}
}
List<int> playerIds = new List<int>();
if (savedPlayerId != -1)
Debug.Log($"SavedPlayerId: {savedPlayerId}, CanSelectPlayer: {playerGameDatasDict[currentPlayerTypeTurn].playerPawnsDict[savedPlayerId].CanSelectPlayer}");
if (savedPlayerId != -1 && playerGameDatasDict[currentPlayerTypeTurn].playerPawnsDict[savedPlayerId].CanSelectPlayer)
{
pawn = playerGameDatasDict[currentPlayerTypeTurn].playerPawnsDict[savedPlayerId]; // chances are when one of the character reaches towards the finishing point
}
else
{
if (botPawnsDictForCurrentPlayer.ContainsValue(BotMove.SafeMove) && botPawnsDictForCurrentPlayer.ContainsValue(BotMove.AttackMove))
{
InitPlayerIdsBasedOnState((val) => val == BotMove.AttackMove || val == BotMove.SafeMove);
savedPlayerId = playerIds[UnityEngine.Random.Range(0, playerIds.Count)];
pawn = playerGameDatasDict[currentPlayerTypeTurn].playerPawnsDict[savedPlayerId];
Debug.Log($"AI playerPawn :: {pawn.name} :: Getting savedplayer id");
}
else if (botPawnsDictForCurrentPlayer.ContainsValue(BotMove.SafeMove))
{
InitPawnBasedOnState(BotMove.SafeMove);
Debug.Log($"AI playerPawn :: {pawn.name} :: Getting savedplayer id");
}
else if (botPawnsDictForCurrentPlayer.ContainsValue(BotMove.AttackMove))
{
InitPawnBasedOnState(BotMove.AttackMove);
Debug.Log($"AI playerPawn :: {pawn.name} :: Getting savedplayer id");
}
else if (botPawnsDictForCurrentPlayer.ContainsValue(BotMove.NormalMove))
{
InitPawnBasedOnState(BotMove.NormalMove);
Debug.Log($"AI playerPawn :: {pawn.name} :: Getting savedplayer id");
}
}
if (pawn != null)
{
Debug.Log($"AI playerPawn :: {pawn.name} :: SelectedPawn: {pawn.name}");
OnPawnSelected(pawn);
}
else
{
if (CheckForMaxDiceRollAttempt())
{
return;
}
if (CanRollDiceAgain)
HandleDiceRoll();
else
SwitchPlayer();
}
void InitPawnBasedOnState(BotMove botMove)
{
InitPlayerIdsBasedOnState((val) => val == botMove);
ReturnPlayerWithMaxSteps(ref savedPlayerId);
pawn = playerGameDatasDict[currentPlayerTypeTurn].playerPawnsDict[savedPlayerId];
}
void InitPlayerIdsBasedOnState(Predicate<BotMove> state)
{
foreach (var botPair in botPawnsDictForCurrentPlayer)
if (state.Invoke(botPair.Value))
playerIds.Add(botPair.Key);
}
void ReturnPlayerWithMaxSteps(ref int savedPlayerId)
{
int maxStepsTaken = -999;
foreach (var id in playerIds)
{
if (playerGameDatasDict[currentPlayerTypeTurn].playerPawnsDict[id].StepsTaken > maxStepsTaken)
{
maxStepsTaken = playerGameDatasDict[currentPlayerTypeTurn].playerPawnsDict[id].StepsTaken;
savedPlayerId = id;
}
}
}
}
private void FindPossibleTileData(PlayerPawn playerPawn, out int possibleSteps, out Tile possibleTileData)
{
possibleSteps = playerGameDatasDict[playerPawn.PlayerType].playerPawnsDict[playerPawn.PlayerId].StepsTaken + diceRolledValue;
int lastStepGenTileIdx = playerGameDatasDict[playerPawn.PlayerType].endIndex;
int possibleTileIndex = playerPawn.CurrentTileIndex + diceRolledValue;
int totalStepsInGeneralPath = tilesManager.GetGeneralTilesLength() - 1; // including the first safe zone
int lastTileIndex = tilesManager.GetGeneralTilesLength() - 1;
int index = possibleSteps > totalStepsInGeneralPath ? possibleTileIndex - lastStepGenTileIdx - 1
: possibleTileIndex > lastTileIndex ? possibleTileIndex - lastTileIndex - 1 : possibleTileIndex;
possibleTileData = possibleSteps > totalStepsInGeneralPath ? tilesManager.RetrieveFinishingTileBasedOnIndex(playerPawn.PlayerType, index) : tilesManager.RetrieveTileBasedOnIndex(index);
}
public void OnDiceRolled(int rolledVal)
{
SetCanRollDiceForUser(false);
// add core dice logic here
Debug.Log($"Tile Index :: LUDO :: rolledVal: {rolledVal} :: {currentPlayerTypeTurn}");
diceRolledValue = rolledVal;
diceText.text = $"{diceRolledValue}";
availPlayers = new List<PlayerPawn>();
if (rolledVal == Ludo_3D_Constants.Max_Dice_Rolls)
{
canSwitchPlayer = false;
// provide option to select a pawn from the list
// also play a simple animation before selecting
CanRollDiceAgain = true;
diceSixRollCounter++;
pointerMeshRend.material = selectMat;
foreach (var playerPawn in playerGameDatasDict[currentPlayerTypeTurn].playerPawnsDict)
if (playerPawn.Value.GetPlayerState() == PlayerState.InFinishingPath)
playerPawn.Value.SetPlayerSelectionState(false);
Debug.Log($"### AreAllPawnsInFinishingPath");
if (AreAllPawnsInFinishingPath())
{
SetCanRollDiceForUser(!botTypesInGame.Contains(currentPlayerTypeTurn));
return;
}
Debug.Log($"### EnablePlayerSelectionStates");
EnablePlayerSelectionStates(true);
// pointerMeshRend.materials[0] = selectMat;
}
else // if there are any other pawns that are in safe or moving state
{
// for player's logic
InitActivePlayers();
int customAvailPlayers = availPlayers.Count();
Debug.Log($"before CustomAvailablePlayers: {customAvailPlayers}");
List<int> indexesToRemove = new List<int>();
for (int i = 0; i < availPlayers.Count; i++)
{
Debug.Log($"## playerPawn.GetPlayerState(): {availPlayers[i].GetPlayerState()}");
if (availPlayers[i].GetPlayerState() == PlayerState.InFinishingPath)
{
Debug.Log($"diceRolledValue: {diceRolledValue}, FinishingDataLen: {tilesManager.GetFinishingTileDataLength(currentPlayerTypeTurn)}, playerPawn.CurrentTileIndex: {availPlayers[i].CurrentTileIndex}");
if (diceRolledValue <= tilesManager.GetFinishingTileDataLength(currentPlayerTypeTurn) - (availPlayers[i].CurrentTileIndex + 1))
{
availPlayers[i].SetPlayerSelectionState(true);
}
else
{
indexesToRemove.Add(i);
availPlayers[i].SetPlayerSelectionState(false);
customAvailPlayers--;
}
continue;
}
availPlayers[i].SetPlayerSelectionState(true);
}
for (int idx = indexesToRemove.Count - 1; idx >= 0; idx--)
availPlayers.RemoveAt(idx);
// if (availPlayers.Count() < 1)
Debug.Log($"CustomAvailablePlayers: {customAvailPlayers}");
canSwitchPlayer = customAvailPlayers < 1;
CanRollDiceAgain = false;
}
Debug.Log($"CanRollDiceAgain: {CanRollDiceAgain}, canSwitchPlayer: {canSwitchPlayer}");
}
private void InitActivePlayers()
{
availPlayers = playerGameDatasDict[currentPlayerTypeTurn].playerPawnsDict.Values.Select(pawn => pawn)
.Where(pawn => pawn.GetPlayerState() == PlayerState.InSafeZone ||
pawn.GetPlayerState() == PlayerState.Moving ||
pawn.GetPlayerState() == PlayerState.InFinishingPath).ToList();
foreach (var player in availPlayers) // TODO :: Move from here
{
DisplayPlayerCountOnTile(player, true);
}
}
private bool AreAllPawnsInFinishingPath()
{
bool areAllPawnsInFinishingPath = false;
foreach (var pawn in playerGameDatasDict[currentPlayerTypeTurn].playerPawnsDict)
{
if (pawn.Value.GetPlayerState() == PlayerState.HasFinished) continue;
if (pawn.Value.GetPlayerState() == PlayerState.InFinishingPath)
{
areAllPawnsInFinishingPath = true;
continue;
}
areAllPawnsInFinishingPath = false;
break;
}
return areAllPawnsInFinishingPath;
}
private void UpdatePlayerState(PlayerPawn playerPawn, PlayerState playerState)
{
Debug.Log($"#### UpdatePlayerState ");
playerGameDatasDict[playerPawn.PlayerType].playerPawnsDict[playerPawn.PlayerId] = playerPawn;
playerGameDatasDict[playerPawn.PlayerType].playerPawnsDict[playerPawn.PlayerId].SetPlayerState(playerState);
playerPawn.SetPlayerState(playerState);
}
private void CheckDiceRollForBot()
{
if (CanRollDiceAgain)
{
HandleDiceRoll();
}
}
private void HandleDiceRoll()
{
if (isDebugTest)
diceRollHandler.HandleDiceViewForBot((rollVal) => RollDiceForBot(rollVal), diceValue == 0 ? UnityEngine.Random.Range(1, Ludo_3D_Constants.Max_Dice_Rolls + 1) : diceValue);
else
diceRollHandler.HandleDiceViewForBot((rollVal) => RollDiceForBot(rollVal));
}
public void OnPawnSelected(PlayerPawn playerPawn)
{
EnablePlayerSelectionStates(false);
PlayerGameData playerGameData = playerGameDatasDict[currentPlayerTypeTurn];
Debug.Log($"playerPawn.GetPlayerState(): {playerPawn.GetPlayerState()}");
if (playerPawn.GetPlayerState() == PlayerState.InHome)
{
Tile targetTile = tilesManager.RetrieveTileBasedOnIndex(playerGameData.startIndex);
DisplayPlayerCountOnTile(playerPawn, false);
playerPawn.MoveToTile(
GetAndInitPositionInsideSafeZone(playerPawn, targetTile),
onComplete: () =>
{
playerGameDatasDict[playerGameData.playerType].totalPawnsInHome--;
UpdatePlayerState(playerPawn, PlayerState.InSafeZone);
DisplayPlayerCountOnTile(playerPawn, true);
if (CheckForMaxDiceRollAttempt())
{
return;
}
if (playerPawn.IsBotPlayer)
CheckDiceRollForBot();
else
SetCanRollDiceForUser(true);
}, playerGameData.startIndex);
return;
}
else if (playerPawn.GetPlayerState() == PlayerState.InFinishingPath)
{
ApplyFinishingPathLogic(playerPawn);
}
else if (playerPawn.CurrentTileIndex == playerGameDatasDict[currentPlayerTypeTurn].endIndex)
{
tilesManager.RetrieveTileBasedOnIndex(playerPawn.CurrentTileIndex).ResetPlayerPawn(playerPawn);
ApplyFinishingPathLogic(playerPawn);
}
else if (playerPawn.GetPlayerState() == PlayerState.InSafeZone || playerPawn.GetPlayerState() == PlayerState.Moving)
{
// move based on the dice value
Debug.Log($"Tile Index :: currentTileIndex: {playerPawn.CurrentTileIndex}");
int nextTileIdx = GetNextGeneralTileIndex(playerPawn);
int targetIdx = playerPawn.CurrentTileIndex + diceRolledValue;
if (nextTileIdx == 0)
targetIdx = (targetIdx - playerPawn.CurrentTileIndex) - 1;
Tile currentSittingTile = tilesManager.RetrieveTileBasedOnIndex(playerPawn.CurrentTileIndex);
if (currentSittingTile.IsSafeZone)
{
SafeTile safeTile = (SafeTile)currentSittingTile;
safeTile.UpdateSafeZonePlayerData(currentPlayerTypeTurn, playerPawn);
// DisplayPlayerCountOnTile(playerPawn, false);
// if (safeTile.PlayerTypesCount > 0)
// {
// var pawns = safeTile.GetPlayerPawns(playerPawn.PlayerType);
// foreach (var pawn in pawns)
// DisplayPlayerCountOnTile(pawn, true);
// }
if (safeTile.PlayerTypesCount == 1)
{
PlayerType playerType = safeTile.GetFirstPlayerType();
var playerPawns = safeTile.GetPlayerPawns(playerType);
foreach (var pawn in playerPawns)
pawn.MoveToCustomTilePosition(safeTile.CenterPlacementPosition);
}
}
else
{
currentSittingTile.ResetPlayerPawn(playerPawn);
}
MoveThroughTiles(playerPawn, nextTileIdx, targetIndex: targetIdx);
}
}
private void ApplyFinishingPathLogic(PlayerPawn playerPawn)
{
int finishingPathIndex = GetNextFinishingTileIndex(playerPawn);
int targetIdx = finishingPathIndex + diceRolledValue > tilesManager.GetFinishingTileDataLength(currentPlayerTypeTurn) - 1 ?
tilesManager.GetFinishingTileDataLength(currentPlayerTypeTurn) - 1 : finishingPathIndex + diceRolledValue;
Debug.Log($"TargetIdx: {targetIdx}, finishingPathIndex: {finishingPathIndex}");
DisplayPlayerCountOnTile(playerPawn, false);
MoveThroughFinishingPath(playerPawn, finishingPathIndex, targetIdx);
}
public int GetNextGeneralTileIndex(PlayerPawn playerPawn)
{
return playerPawn.CurrentTileIndex == tilesManager.GetGeneralTilesLength() - 1 ? 0 : playerPawn.CurrentTileIndex + 1;
}
private int GetNextFinishingTileIndex(PlayerPawn playerPawn)
{
return playerPawn.CurrentTileIndex > tilesManager.GetFinishingTileDataLength(currentPlayerTypeTurn) - 1 ? 0 : playerPawn.CurrentTileIndex + 1;
}
private void SwitchPlayer(PlayerPawn playerPawn = null)
{
Debug.Log($"CallTest: SwitchPlayer");
if (playerPawn)
UpdatePlayerState(playerPawn, tilesManager.RetrieveTileBasedOnIndex(playerPawn.CurrentTileIndex).IsSafeZone ? PlayerState.InSafeZone : PlayerState.Moving);
if (!CanRollDiceAgain)
{
Debug.Log($"currentPlayerTurn: {currentPlayerTypeTurn}");
Debug.Log($"currentPlayerTurnIndex: {currentPlayerTurnIndex}");
Debug.Log($"before SwitchPlayer availPlayers: {availPlayers.Count}, playerPawn: {playerPawn}");
if (availPlayers.Count < 1)
InitActivePlayers();
Debug.Log($"after SwitchPlayer availPlayers: {availPlayers.Count}, playerPawn: {playerPawn}");
SetDisplayCountForAllAvailPlayers(false);
if (allPlayerTypes.Count == 1)
{
Debug.LogError($"GAME IS OVER");
return;
}
if (currentPlayerTypeTurn == allPlayerTypes[allPlayerTypes.Count - 1])
{
currentPlayerTurnIndex = 0;
currentPlayerTypeTurn = allPlayerTypes[currentPlayerTurnIndex];
}
else
{
currentPlayerTurnIndex++;
currentPlayerTypeTurn = allPlayerTypes[currentPlayerTurnIndex];
}
uIManager.UpdatePlayerTurnText(currentPlayerTypeTurn);
diceSixRollCounter = 0;
diceText.text = $"{0}";
InitActivePlayers();
SetDisplayCountForAllAvailPlayers(true);
}
SetCanRollDiceForUser(!botTypesInGame.Contains(currentPlayerTypeTurn));
Debug.Log($"CurrentPlayerTurn: {currentPlayerTypeTurn}");
SetCurrentSelectedPointer();
pointerMeshRend.material = turnMat;
// pointerMeshRend.materials[0] = turnMat;
Debug.Log($"botTypesInGame.Contains(currentPlayerTypeTurn): {botTypesInGame.Contains(currentPlayerTypeTurn)}");
if (botTypesInGame.Contains(currentPlayerTypeTurn)) // TODO :: Double check calling of the function
{
Debug.Log($"Invoking RollDiceForBot");
Invoke(nameof(HandleDiceRoll), 1f);
}
}
private void SetCurrentSelectedPointer()
{
var tempPos = playerBaseHandler.GetPlayerBase(currentPlayerTypeTurn).transform.position;
pointerDebug.position = new Vector3(tempPos.x, 3f, tempPos.z);
}
public void SetDisplayCountForAllAvailPlayers(bool state)
{
foreach (var pawn in availPlayers)
{
DisplayPlayerCountOnTile(pawn, state);
}
}
private void MoveThroughTiles(PlayerPawn playerPawn, int index, int targetIndex)
{
Tile nextTile = tilesManager.RetrieveTileBasedOnIndex(index);
Vector3 targetPosition = nextTile.CenterPlacementPosition;
Debug.Log($"Tile Index :: nextIndex: {index}, targetIndex: {targetIndex}, nextTileName: {nextTile.name}");
if (index == targetIndex) // if the target index is the safe zone only then apply the logic for rearranging pawns
{
Tile targetTile = tilesManager.RetrieveTileBasedOnIndex(targetIndex);
if (targetTile.IsSafeZone)
{
targetPosition = GetAndInitPositionInsideSafeZone(playerPawn, targetTile);
}
}
Debug.Log($"tile targetPosition: {targetPosition}");
DisplayPlayerCountOnTile(playerPawn, false);
playerPawn.MoveToTile(
targetPosition,
onComplete: () =>
{
diceRolledValue--;
Debug.Log($"DiceRolledValue: {diceRolledValue}");
if (diceRolledValue > 0)
{
int nextTileIndex = GetNextGeneralTileIndex(playerPawn);
Debug.Log($"currentTileIndex: {playerPawn.CurrentTileIndex}, nextTileIndex: {nextTileIndex}, targetIndex: {targetIndex}");
if (playerPawn.GetPlayerState() == PlayerState.InFinishingPath || index == playerGameDatasDict[currentPlayerTypeTurn].endIndex)
{
// MoveThroughTiles(playerPawn, index, targetIndex);
Debug.Log($"TargetIdx: {targetIndex - index}");
MoveThroughFinishingPath(playerPawn, 0, targetIndex - index);
}
else if (nextTileIndex <= targetIndex)
{
if (nextTileIndex == 0)
targetIndex = (targetIndex - playerPawn.CurrentTileIndex) - 1;
MoveThroughTiles(playerPawn, nextTileIndex, targetIndex);
}
}
else
{
// TODO :: Improve this logic, use a collection
Debug.Log($"nextTile.IsSafeZone: {nextTile.IsSafeZone}");
if (CanRollDiceAgain)
DisplayPlayerCountOnTile(playerPawn, true);
if (!nextTile.IsSafeZone)
{
Debug.Log($"nextTile.HasPawnsAvailable: {nextTile.HasPawnsAvailable}");
if (nextTile.HasPawnsAvailable && playerPawn.PlayerType != nextTile.CurrentHoldingPlayerType)
{
Debug.Log($"nextTile.PlayerPawn: {nextTile.CurrentHoldingPlayerType}, {nextTile.transform.name}");
Debug.Log($"nextTile.TotalPawnsInTile: {nextTile.TotalPawnsInTile}");
// play animation for moving back to base.
// TODO :: Send existing pawn back to base.
// means there's already a pawn there, move him back to the base.
int counter = nextTile.TotalPawnsInTile;
for (int i = counter; i > 0; i--)
{
var pawn = nextTile.GetPlayerPawn();
Debug.Log($"pawn: {pawn}");
Debug.Log($"playerBase: {playerBaseHandler}");
var playerBasePos = playerBaseHandler.GetPlayerBase(pawn.PlayerType)
.GetBasePlacementDataPosition(pawn.PlayerId - 1);
Debug.Log($"playerBasePos: {playerBasePos}");
playerGameDatasDict[pawn.PlayerType].totalPawnsInHome++;
pawn.MoveBackToHome(playerBasePos);
}
if (CheckForMaxDiceRollAttempt())
{
nextTile.InitPlayerPawn(playerPawn, currentPlayerTypeTurn);
return;
}
CanRollDiceAgain = true;
if (!playerPawn.IsBotPlayer)
SetCanRollDiceForUser(true);
}
nextTile.InitPlayerPawn(playerPawn, currentPlayerTypeTurn);
if (CheckForMaxDiceRollAttempt())
{
return;
}
}
else
{
if (CheckForMaxDiceRollAttempt())
{
return;
}
}
SwitchPlayer(playerPawn);
}
},
index);
}
private Vector3 GetAndInitPositionInsideSafeZone(PlayerPawn playerPawn, Tile targetTile)
{
Vector3 targetPosition;
SafeTile targetSafeTile = (SafeTile)targetTile;
Debug.Log($"targetSafeTile.PlayerTypesCount: {targetSafeTile.PlayerTypesCount}");
if (targetSafeTile.PlayerTypesCount == 1)
{
Debug.Log($"targetSafeTile.ContainsPlayerType(currentPlayerTypeTurn): {targetSafeTile.ContainsPlayerType(currentPlayerTypeTurn)}");
if (!targetSafeTile.ContainsPlayerType(currentPlayerTypeTurn)) // means it is a new player type, the second one
{
PlayerType initialPlayerType = targetSafeTile.GetFirstPlayerType();
// rearrange already existing player from center position to it's saved transform
var playerPawns = targetSafeTile.GetPlayerPawns(initialPlayerType);
foreach (var pawn in playerPawns)
{
var placementPoint = targetSafeTile.GetPlacementPoint(initialPlayerType);
pawn.MoveToCustomTilePosition(placementPoint.position);
}
targetSafeTile.InitPlayerPawn(playerPawn, currentPlayerTypeTurn);
targetPosition = targetSafeTile.GetPlacementPoint(currentPlayerTypeTurn).position;
}
else
{
targetSafeTile.InitPlayerPawn(playerPawn, currentPlayerTypeTurn);
targetPosition = targetTile.CenterPlacementPosition;
}
}
else
{
// TODO :: Check the data if it's consistent
Debug.Log($"targetSafeTile.ContainsPlayerType(currentPlayerTypeTurn): {targetSafeTile.ContainsPlayerType(currentPlayerTypeTurn)}");
if (!targetSafeTile.ContainsPlayerType(currentPlayerTypeTurn))
{
Debug.Log($"targetSafeTile.PlayerTypesCount: {targetSafeTile.PlayerTypesCount}");
if (targetSafeTile.PlayerTypesCount < 1) // he is the only player that is being added to the safe zone
{
targetSafeTile.InitPlayerPawn(playerPawn, currentPlayerTypeTurn);
targetPosition = targetTile.CenterPlacementPosition;
}
else
{
targetSafeTile.InitPlayerPawn(playerPawn, currentPlayerTypeTurn);
targetPosition = targetSafeTile.GetPlacementPoint(currentPlayerTypeTurn).position;
}
}
else
{
targetSafeTile.InitPlayerPawn(playerPawn, currentPlayerTypeTurn);
targetPosition = targetSafeTile.GetPlacementPoint(currentPlayerTypeTurn).position;
}
}
return targetPosition;
}
private void MoveThroughFinishingPath(PlayerPawn playerPawn, int index, int targetIndex)
{
UpdatePlayerState(playerPawn, PlayerState.InFinishingPath);
playerPawn.MoveToTile(
tilesManager.RetrieveFinishingTileBasedOnIndex(currentPlayerTypeTurn, index).transform.position,
onComplete: () =>
{
diceRolledValue--;
Debug.Log($"DiceRolledValue: {diceRolledValue}");
if (diceRolledValue > 0)
{
int tileIndex = GetNextFinishingTileIndex(playerPawn);
Debug.Log($"tileIndex: {tileIndex}, targetIndex: {targetIndex}");
if (tileIndex <= targetIndex)
{
// MoveThroughTiles(playerPawn, index, targetIndex);
MoveThroughFinishingPath(playerPawn, tileIndex, targetIndex);
}
}
else
{
DisplayPlayerCountOnTile(playerPawn, true);
Debug.Log($"CurrentTileIndex: {playerPawn.CurrentTileIndex} == lastIndex: {tilesManager.GetFinishingTileDataLength(currentPlayerTypeTurn) - 1}");
if (playerPawn.CurrentTileIndex == tilesManager.GetFinishingTileDataLength(currentPlayerTypeTurn) - 1)
{
UpdatePlayerState(playerPawn, PlayerState.HasFinished);
playerGameDatasDict[currentPlayerTypeTurn].totalPawnsFinished++;
Debug.Log($"totalPawnsFinished: {playerGameDatasDict[currentPlayerTypeTurn].totalPawnsFinished}, playerPawnsDict.Count: {playerGameDatasDict[currentPlayerTypeTurn].playerPawnsDict.Count}");
if (playerGameDatasDict[currentPlayerTypeTurn].totalPawnsFinished == playerGameDatasDict[currentPlayerTypeTurn].playerPawnsDict.Count)
{
CanRollDiceAgain = false;
if (allPlayerTypes.Contains(currentPlayerTypeTurn))
{
allPlayerTypes.Remove(currentPlayerTypeTurn);
Debug.Log($"currentPlayerTypeTurn: {currentPlayerTypeTurn}");
Debug.Log($"playerDatas.FirstOrDefault(data => data.playerType == currentPlayerTypeTurn): {playerDatas.FirstOrDefault(data => data.playerType == currentPlayerTypeTurn)}");
playerDatas.FirstOrDefault(data => data.playerType == currentPlayerTypeTurn).ranking = TotalPlayersInGame - allPlayerTypes.Count;
}
if (allPlayerTypes.Count == 1)
{
// Game is over
var lastFinishingPlayerType = allPlayerTypes[0];
allPlayerTypes.RemoveAt(0);
playerDatas.FirstOrDefault(data => data.playerType == lastFinishingPlayerType).ranking = TotalPlayersInGame - allPlayerTypes.Count;
// Show Game Over panel
gameManager.OnGameStateChanged(GameState.GameOver);
return;
}
SwitchPlayer();
Debug.Log($"PlayerTypes: {allPlayerTypes.Count}");
}
else
{
CanRollDiceAgain = true;
if (playerPawn.IsBotPlayer)
CheckDiceRollForBot();
else
SetCanRollDiceForUser(true);
}
}
else
{
// activate here
if (CheckForMaxDiceRollAttempt())
{
return;
}
SwitchPlayer();
}
}
},
index);
}
private void SetCanRollDiceForUser(bool state)
{
CanRollDiceForUser = state;
Debug.Log($"CAnRollDiceForUser: {CanRollDiceForUser}");
}
private void DisplayPlayerCountOnTile(PlayerPawn playerPawn, bool show)
{
Tile tile = playerPawn.GetPlayerState() == PlayerState.InFinishingPath ?
tilesManager.RetrieveFinishingTileBasedOnIndex(playerPawn.PlayerType, playerPawn.CurrentTileIndex)
: tilesManager.RetrieveTileBasedOnIndex(playerPawn.CurrentTileIndex);
playerPawn.ShowPlayerCountCanvas(show);
if (!show) return;
int count = 0;
if (tile.IsSafeZone)
{
count = (tile as SafeTile).GetPlayerPawnsCountInTile(playerPawn.PlayerType);
}
else
{
count = tile.TotalPawnsInTile;
}
playerPawn.GetComponentInChildren<PlayerCountCanvas>().SetPlayerCount(count);
}
public void ResetData()
{
ResetGameRestartData();
playerDatas = null;
botTypesInGame = null;
allPlayerTypes = null;
botRuntimeMovementData = null;
playerGameDatasDict = null;
playerDatas = null;
availPlayers = null;
}
public void ResetGameRestartData()
{
currentPlayerTurnIndex = 0;
}
}