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 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 { 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); } } } }