GameMode/Rules/Koth/KothWinCondition.cs

Win condition component for a King-of-the-Hill style game mode. Tracks per-team scores in a networked dictionary, listens for HillWinEvent, increments the winning team score, and transitions the game state to either a round-win state or a team-game-win state when a target score is reached.

Networking
using Sandbox;
using Sandbox.Events;
using Sandbox.Utility;

namespace KOTH;

public sealed class KothWinCondition : Component,
	IGameEventHandler<HillWinEvent>
{
	[Property, Sync(SyncFlags.FromHost)]
	public int TargetScore { get; set; } = 3;

	[Sync(SyncFlags.FromHost)]
	public NetDictionary<Team, int> Scores { get; private set; } = new();

	[Property]
	public StateComponent RoundWinState { get; set; }

	[Property]
	public StateComponent TGameWinState { get; set; }

	[Property]
	public StateComponent CTGameWinState { get; set; }

	///////////////////////////////////////////////////////////////////////////

	protected override void OnAwake()
	{
		base.OnAwake();

		if (Networking.IsHost)
		{
			//if (Scores != null)
			//{
			Scores = new()
				{
				// TODO : will need to add any extra teams here as well! not pragmatic!
				{ Team.CounterTerrorist, 0 }, { Team.Terrorist, 0 }, { Team.Unassigned, 0 },
				};
			//}
		}

	}

	public void OnGameEvent(HillWinEvent EventArgs)
	{
		Log.Info($"all : scores {Scores[Team.CounterTerrorist]} : {Scores[Team.Terrorist]}");

		if (!Networking.IsHost)
			return;

		var Hill = EventArgs.Hill;
		if (!Hill.IsValid())
		{
			Log.Error("Invalid hill captured!");
			return;
		}

		Team WinningTeam = EventArgs.Team;
		var TeamScore = ++Scores[WinningTeam];

		if (TeamScore >= TargetScore)
		{
			var NextState = WinningTeam == Team.CounterTerrorist ? CTGameWinState : TGameWinState;
			GameMode.Instance.StateMachine.Transition(NextState);
		}
		else
		{
			GameMode.Instance.StateMachine.Transition(RoundWinState);
		}

		Log.Info($"host : scores {Scores[Team.CounterTerrorist]} : {Scores[Team.Terrorist]}");
	}
}