2025-09-24 11:24:38 +05:00

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