|
|
@ -0,0 +1,213 @@ |
|
|
|
using System.Collections; |
|
|
|
using System.Collections.Generic; |
|
|
|
using UnityEngine; |
|
|
|
using Networking.Server; |
|
|
|
using TMPro; |
|
|
|
using UnityEngine.UI; |
|
|
|
|
|
|
|
[CreateAssetMenu(menuName = "Major Project/GameModes/Racetrack", order = 201)] |
|
|
|
public class RacetrackGameMode : GameMode |
|
|
|
{ |
|
|
|
|
|
|
|
public int MaxRound = 5; |
|
|
|
public string nextScene = "ServerTestScene"; |
|
|
|
List<ClientData> ConnectedClients; |
|
|
|
public Material OverlayMaterial; |
|
|
|
public float scrollSpeed = 0.0f; //The rate at which the level will scroll past
|
|
|
|
|
|
|
|
|
|
|
|
public int RoundCount { get; private set; } |
|
|
|
private Dictionary<ClientData, List<Block>> BlocksOwned; |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Called once all players have finished their moves but before the Objective is checked
|
|
|
|
/// </summary>
|
|
|
|
protected override void OnRoundEnd(PlayerData[] allPlayers) |
|
|
|
{ |
|
|
|
//Move the camera forward at a steady rate each round
|
|
|
|
if (scrollSpeed > 0.0f) |
|
|
|
{ |
|
|
|
Camera.main.transform.Translate(scrollSpeed, 0, 0, Space.World); |
|
|
|
Debug.Log("New camera position at x = " + Camera.main.transform.position.x); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
Debug.Log("Not scrolling"); |
|
|
|
} |
|
|
|
|
|
|
|
//At the end of each round, any stuck players are freed to resume moving next round
|
|
|
|
foreach (PlayerData player in allPlayers) |
|
|
|
{ |
|
|
|
player.character.stuck = false; |
|
|
|
|
|
|
|
if (player.character.inPit) |
|
|
|
{ |
|
|
|
player.character.respawnCharacter(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
RoundCount++; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Checks if the Game is finished
|
|
|
|
/// </summary>
|
|
|
|
/// <returns>returns if game is finished</returns>
|
|
|
|
public override bool isGameOver(PlayerData[] allPlayers) |
|
|
|
{ |
|
|
|
return (RoundCount >= MaxRound -1); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Called once per player after they have moved onto a block
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="character">Character which moved</param>
|
|
|
|
/// <param name="client">Client of the character</param>
|
|
|
|
/// <param name="currentBlock">Block moved onto</param>
|
|
|
|
protected override void OnPlayerFinishedMove(Character character, ClientData client, Block currentBlock) |
|
|
|
{ |
|
|
|
handleFalling(character, client, currentBlock, character.justMoved); |
|
|
|
|
|
|
|
/*Debug.Log("Moved to square at " + currentBlock.transform.position.x + ", " |
|
|
|
+ currentBlock.transform.position.y + ", " |
|
|
|
+ currentBlock.transform.position.z); |
|
|
|
|
|
|
|
//If a character has fallen in the water or into a pit, we mark that fact, and they lose the rest of their turn
|
|
|
|
character.inWater = currentBlock.isWater; |
|
|
|
character.inPit = currentBlock.isPit; |
|
|
|
|
|
|
|
if (character.inWater == true || character.inPit == true) |
|
|
|
{ |
|
|
|
character.stuck = true; |
|
|
|
} |
|
|
|
|
|
|
|
Debug.Log("inWater = " + character.inWater + ", inPit = " + character.inPit + ", stuck = " + character.stuck);*/ |
|
|
|
|
|
|
|
//Commented out because we don't do this in the racetrack mode
|
|
|
|
|
|
|
|
/*ClientData OwnedClient; |
|
|
|
Material overlay = null; |
|
|
|
if (isOwned(currentBlock, out OwnedClient)) |
|
|
|
{ |
|
|
|
if (OwnedClient == client) |
|
|
|
return; |
|
|
|
|
|
|
|
BlocksOwned[OwnedClient].Remove(currentBlock); |
|
|
|
|
|
|
|
foreach (Material mat in currentBlock.GetComponent<Renderer>().materials) |
|
|
|
{ |
|
|
|
if (mat.name == OverlayMaterial.name + " (Instance)") |
|
|
|
overlay = mat; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (overlay == null) |
|
|
|
{ |
|
|
|
overlay = new Material(OverlayMaterial); |
|
|
|
List<Material> mats = new List<Material>(currentBlock.GetComponent<Renderer>().materials); |
|
|
|
mats.Add(overlay); |
|
|
|
currentBlock.GetComponent<Renderer>().materials = mats.ToArray(); |
|
|
|
} |
|
|
|
|
|
|
|
overlay.SetColor("_NewColor", client.Color); |
|
|
|
|
|
|
|
if (!BlocksOwned.ContainsKey(client)) |
|
|
|
BlocksOwned.Add(client, new List<Block>()); |
|
|
|
|
|
|
|
BlocksOwned[client].Add(currentBlock); |
|
|
|
|
|
|
|
if (overlay != null) |
|
|
|
currentBlock.StartCoroutine(AnimateBlock(overlay, 0.25f));*/ |
|
|
|
} |
|
|
|
|
|
|
|
protected override void OnRoundStart(PlayerData[] allPlayers) |
|
|
|
{ |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
protected override void OnAllPlayersFinishedMove(PlayerData[] allPlayers) |
|
|
|
{ |
|
|
|
foreach (PlayerData player in allPlayers) |
|
|
|
{ |
|
|
|
/* The justMoved variable is used to determine whether a player taking their turn in the water should become stuck |
|
|
|
* (because they moved into/in the water), or not (because they're turning while remaining in the same square) |
|
|
|
* It's not needed from move to move, so we clear it |
|
|
|
*/ |
|
|
|
player.character.justMoved = false; |
|
|
|
|
|
|
|
if (BlocksOwned.ContainsKey(player.client)) |
|
|
|
player.client.SceneScore = BlocksOwned[player.client].Count; |
|
|
|
else |
|
|
|
player.client.SceneScore = 0; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
protected override void OnGameOver(PlayerData[] allPlayers) |
|
|
|
{ |
|
|
|
throw new System.NotImplementedException(); |
|
|
|
} |
|
|
|
|
|
|
|
private bool isOwned(Block block, out ClientData client) |
|
|
|
{ |
|
|
|
client = null; |
|
|
|
|
|
|
|
foreach (KeyValuePair<ClientData, List<Block>> ownedList in BlocksOwned) |
|
|
|
{ |
|
|
|
if (ownedList.Value.Contains(block)) |
|
|
|
{ |
|
|
|
client = ownedList.Key; |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
private void handleFalling(Character character, ClientData client, Block currentBlock, bool didMove) |
|
|
|
{ |
|
|
|
//If a character has fallen in the water or into a pit, we mark that fact, and they lose the rest of their turn
|
|
|
|
character.inWater = currentBlock.isWater; |
|
|
|
character.inPit = currentBlock.isPit; |
|
|
|
|
|
|
|
if (didMove && (character.inWater || character.inPit)) |
|
|
|
{ |
|
|
|
character.stuck = true; |
|
|
|
} |
|
|
|
|
|
|
|
if (character.inPit) |
|
|
|
{ |
|
|
|
character.lives -= 1; |
|
|
|
} |
|
|
|
|
|
|
|
Debug.Log("inWater = " + character.inWater + ", inPit = " + character.inPit + ", stuck = " + character.stuck); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
private IEnumerator AnimateBlock(Material mat, float time) |
|
|
|
{ |
|
|
|
|
|
|
|
float timeElasped = 0; |
|
|
|
|
|
|
|
while (timeElasped < time) |
|
|
|
{ |
|
|
|
mat.SetFloat("_Multiplier", (timeElasped / time)); |
|
|
|
yield return new WaitForEndOfFrame(); |
|
|
|
|
|
|
|
timeElasped += Time.deltaTime; |
|
|
|
} |
|
|
|
|
|
|
|
mat.SetFloat("_Multiplier", 1); |
|
|
|
} |
|
|
|
|
|
|
|
protected override void OnGameStart(PlayerData[] allPlayers) |
|
|
|
{ |
|
|
|
BlocksOwned = new Dictionary<ClientData, List<Block>>(); |
|
|
|
RoundCount = 0; |
|
|
|
for(int i = 0; i < allPlayers.Length; i++) |
|
|
|
{ |
|
|
|
OnPlayerFinishedMove(allPlayers[i].character, allPlayers[i].client, allPlayers[i].character.CurrentBlock); |
|
|
|
} |
|
|
|
} |
|
|
|
} |