139 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
		
		
			
		
	
	
			139 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
|  | using Fusion; | ||
|  | using System.Collections.Generic; | ||
|  | using UnityEngine; | ||
|  | 
 | ||
|  | namespace TPSBR | ||
|  | { | ||
|  | 	public class EliminationGameplayMode : GameplayMode | ||
|  | 	{ | ||
|  | 		// PRIVATE MEMBERS | ||
|  | 
 | ||
|  | 		[SerializeField] | ||
|  | 		private int _extraLives = 4; | ||
|  | 
 | ||
|  | 		private EliminationComparer _playerComparer = new EliminationComparer(); | ||
|  | 
 | ||
|  | 		// GameplayMode INTERFACE | ||
|  | 
 | ||
|  | 		protected override void PreparePlayerStatistics(ref PlayerStatistics playerStatistics) | ||
|  | 		{ | ||
|  | 			base.PreparePlayerStatistics(ref playerStatistics); | ||
|  | 
 | ||
|  | 			// Do not add extra lives after reconnect | ||
|  | 			if (playerStatistics.Deaths == 0 && playerStatistics.IsEliminated == false && playerStatistics.ExtraLives == 0) | ||
|  | 			{ | ||
|  | 				playerStatistics.ExtraLives = (short)GetExtraLivesForNewPlayer(); | ||
|  | 			} | ||
|  | 		} | ||
|  | 
 | ||
|  | 		protected override float GetRespawnTime(PlayerStatistics playerStatistics) | ||
|  | 		{ | ||
|  | 			if (playerStatistics.ExtraLives > 0) | ||
|  | 				return base.GetRespawnTime(playerStatistics); | ||
|  | 
 | ||
|  | 			return -1f; | ||
|  | 		} | ||
|  | 
 | ||
|  | 		protected override void AgentDeath(ref PlayerStatistics victimStatistics, ref PlayerStatistics killerStatistics) | ||
|  | 		{ | ||
|  | 			base.AgentDeath(ref victimStatistics, ref killerStatistics); | ||
|  | 
 | ||
|  | 			if (victimStatistics.ExtraLives > 0) | ||
|  | 			{ | ||
|  | 				victimStatistics.ExtraLives -= 1; | ||
|  | 			} | ||
|  | 		} | ||
|  | 
 | ||
|  | 		protected override void SortPlayers(List<PlayerStatistics> allStatistics) | ||
|  | 		{ | ||
|  | 			allStatistics.Sort(_playerComparer); | ||
|  | 		} | ||
|  | 
 | ||
|  | 		protected override void CheckWinCondition() | ||
|  | 		{ | ||
|  | 			var alivePlayers    = 0; | ||
|  | 			var lastAlivePlayer = PlayerRef.None; | ||
|  | 
 | ||
|  | 			foreach (var player in Context.NetworkGame.ActivePlayers) | ||
|  | 			{ | ||
|  | 				if (player == null) | ||
|  | 					continue; | ||
|  | 
 | ||
|  | 				var statistics = player.Statistics; | ||
|  | 				if (statistics.ExtraLives > 0 || statistics.IsAlive == true || statistics.RespawnTimer.IsRunning == true) | ||
|  | 				{ | ||
|  | 					if (alivePlayers > 0) | ||
|  | 						return; | ||
|  | 
 | ||
|  | 					alivePlayers    += 1; | ||
|  | 					lastAlivePlayer  = player.Object.InputAuthority; | ||
|  | 				} | ||
|  | 			} | ||
|  | 
 | ||
|  | 			if (alivePlayers == 1) | ||
|  | 			{ | ||
|  | 				FinishGameplay(); | ||
|  | 				Log.Info($"Player {lastAlivePlayer} won the match!"); | ||
|  | 			} | ||
|  | 			else if (alivePlayers == 0) | ||
|  | 			{ | ||
|  | 				Log.Error("No player alive, this should not happen"); | ||
|  | 				FinishGameplay(); | ||
|  | 			} | ||
|  | 		} | ||
|  | 
 | ||
|  | 		// PRIVATE METHODS | ||
|  | 
 | ||
|  | 		private int GetExtraLivesForNewPlayer() | ||
|  | 		{ | ||
|  | 			int minExtraLives = int.MaxValue; | ||
|  | 			int maxExtraLives = int.MinValue; | ||
|  | 
 | ||
|  | 			foreach (var player in Context.NetworkGame.ActivePlayers) | ||
|  | 			{ | ||
|  | 				if (player == null) | ||
|  | 					continue; | ||
|  | 
 | ||
|  | 				var playerStatistics = player.Statistics; | ||
|  | 
 | ||
|  | 				if (playerStatistics.Deaths == 0 && playerStatistics.ExtraLives == 0 && playerStatistics.IsEliminated == false) | ||
|  | 					continue; // Player not yet initialized properly | ||
|  | 
 | ||
|  | 				minExtraLives = Mathf.Min(minExtraLives, playerStatistics.ExtraLives); | ||
|  | 				maxExtraLives = Mathf.Max(maxExtraLives, playerStatistics.ExtraLives); | ||
|  | 			} | ||
|  | 
 | ||
|  | 			int extraLives = _extraLives; | ||
|  | 
 | ||
|  | 			if (minExtraLives < int.MaxValue && maxExtraLives > int.MinValue) | ||
|  | 			{ | ||
|  | 				extraLives = Mathf.Clamp(Mathf.RoundToInt((minExtraLives + maxExtraLives) * 0.5f), 0, _extraLives); | ||
|  | 			} | ||
|  | 
 | ||
|  | 			return extraLives; | ||
|  | 		} | ||
|  | 
 | ||
|  | 		// HELPERS | ||
|  | 
 | ||
|  | 		private class EliminationComparer : IComparer<PlayerStatistics> | ||
|  | 		{ | ||
|  | 			public int Compare(PlayerStatistics x, PlayerStatistics y) | ||
|  | 			{ | ||
|  | 				var result = x.IsEliminated.CompareTo(y.IsEliminated); | ||
|  | 				if (result != 0) | ||
|  | 					return result; | ||
|  | 
 | ||
|  | 				result = y.ExtraLives.CompareTo(x.ExtraLives); | ||
|  | 				if (result != 0) | ||
|  | 					return result; | ||
|  | 
 | ||
|  | 				result = y.Kills.CompareTo(x.Kills); | ||
|  | 				if (result != 0) | ||
|  | 					return result; | ||
|  | 
 | ||
|  | 				return x.Deaths.CompareTo(y.Deaths); | ||
|  | 			} | ||
|  | 		} | ||
|  | 	} | ||
|  | } |