GameLoop/PlayerTracker.cs
public class KillTracker : GameObjectSystem<KillTracker>
{
private record KillRecord( float Time, string Weapon );
private float KillWindow = 5f;
private readonly Dictionary<Guid, List<KillRecord>> KillLog = new();
public KillTracker( Scene scene ) : base( scene )
{
}
public void OnPlayerKilled( PlayerData attacker, PlayerData victim, DamageInfo dmg )
{
if ( !attacker.IsValid() ) return;
// Don't count suicide kills
if ( attacker == victim ) return;
var time = RealTime.Now;
var id = attacker.PlayerId;
var weaponName = dmg.Weapon.IsValid() ? dmg.Weapon.Name : "unknown";
if ( !KillLog.ContainsKey( id ) )
{
KillLog[id] = new();
}
if ( KillLog[id].Any( kill => time - kill.Time > KillWindow ) )
{
Log.Trace( "Kill window is too high, clearing" );
KillLog[id].Clear();
}
KillLog[id].Add( new KillRecord( time, weaponName ) );
CheckForMultiKill( attacker, victim, weaponName );
}
void CheckForMultiKill( PlayerData attacker, PlayerData victim, string weapon )
{
var playerKills = KillLog[attacker.PlayerId];
var totalKillCount = playerKills.Count;
var weaponKillCount = playerKills.Count( kill => kill.Weapon == weapon );
if ( totalKillCount >= 2 )
{
Log.Info( $"Multi Kill {attacker.DisplayName}! - {totalKillCount} kills" );
attacker.AddStat( $"multikill.{totalKillCount}" );
}
Scene.RunEvent<Feed>( x => x.NotifyKill( attacker, totalKillCount ) );
if ( weaponKillCount >= 2 )
{
attacker.AddStat( $"multikill.{weapon}.{weaponKillCount}" );
}
}
}