Manager component for game modes, handles King of the Hill scoring and a Sudden Death state. It awards periodic points to the player standing in the zone, detects trigger enter/exit to track the zone owner, checks arena shrinker to enable sudden death, and exposes a force multiplier while sudden death is active.
using Sandbox;
using System;
using System.Linq;
public sealed class GameModeManager : Component, Component.ITriggerListener
{
public static GameModeManager Instance { get; private set; }
[Property] public bool EnableKingOfTheHill { get; set; } = true;
[Property] public int PointsPerSecond { get; set; } = 2;
[Property] public float ZoneCheckInterval { get; set; } = 1.0f;
[Property] public bool EnableSuddenDeath { get; set; } = true;
[Property] public float SuddenDeathThresholdTime { get; set; } = 20f;
[Property] public float SuddenDeathForceMultiplier { get; set; } = 2.5f;
public bool IsSuddenDeathActive { get; private set; } = false;
private TimeSince _timeSinceZoneTick;
private GameObject _currentZoneOwner;
protected override void OnStart()
{
Instance = this;
}
protected override void OnUpdate()
{
if ( EnableSuddenDeath && !IsSuddenDeathActive )
{
CheckSuddenDeathCondition();
}
if ( EnableKingOfTheHill && _timeSinceZoneTick >= ZoneCheckInterval )
{
_timeSinceZoneTick = 0;
AwardHillPoints();
}
}
private void CheckSuddenDeathCondition()
{
var shrinker = Scene.GetAllComponents<ArenaShrinker>().FirstOrDefault();
if ( shrinker.IsValid() && shrinker.TimeRemaining <= SuddenDeathThresholdTime && shrinker.TimeRemaining > 0f )
{
TriggerSuddenDeath();
}
}
public void TriggerSuddenDeath()
{
IsSuddenDeathActive = true;
CameraJuice.Instance?.Shake( 25f );
if ( Killfeed.Instance != null )
{
Killfeed.Instance.AddEntry( "СИСТЕМА", "ВСЕ ИГРОКИ", "ВНЕЗАПНАЯ СМЕРТЬ!" );
}
Log.Info( "[GameModeManager] Активирован режим SUDDEN DEATH!" );
}
public void OnTriggerEnter( Collider other )
{
var root = other.GameObject.Root;
if ( root.Components.Get<PlayerHealth>().IsValid() )
{
_currentZoneOwner = root;
}
}
public void OnTriggerExit( Collider other )
{
var root = other.GameObject.Root;
if ( _currentZoneOwner == root )
{
_currentZoneOwner = null;
}
}
private void AwardHillPoints()
{
if ( _currentZoneOwner.IsValid() )
{
var health = _currentZoneOwner.Components.Get<PlayerHealth>();
if ( health.IsValid() && !health.IsDead )
{
if ( !_currentZoneOwner.IsProxy && ScoreManager.Instance != null )
{
ScoreManager.Instance.AddScore( PointsPerSecond );
}
}
}
}
public float GetForceMultiplier()
{
return IsSuddenDeathActive ? SuddenDeathForceMultiplier : 1.0f;
}
}