0.1.3: keep match stats per session as it goes, so map changes record them
This commit is contained in:
parent
d06e240417
commit
ddf152c19f
1 changed files with 43 additions and 17 deletions
|
|
@ -21,7 +21,7 @@ namespace PlaytimeHistory;
|
|||
public class PlaytimeHistory : BasePlugin, IPluginConfig<PlaytimeHistoryConfig>
|
||||
{
|
||||
public override string ModuleName => "PlaytimeHistory";
|
||||
public override string ModuleVersion => "0.1.2";
|
||||
public override string ModuleVersion => "0.1.3";
|
||||
public override string ModuleAuthor => "astra";
|
||||
public override string ModuleDescription => "Records playtime per session, team and alive/dead state";
|
||||
|
||||
|
|
@ -50,7 +50,10 @@ public class PlaytimeHistory : BasePlugin, IPluginConfig<PlaytimeHistoryConfig>
|
|||
{
|
||||
public required ulong SteamId;
|
||||
public required string SessionKey;
|
||||
public required MatchStats? Baseline;
|
||||
// The map's running stats as last read, and this session's total so far (null until they've
|
||||
// been read once). Read every second, so a close that can't read them still has them.
|
||||
public MatchStats? LastStats;
|
||||
public MatchStats? Stats;
|
||||
public string? SegmentKey;
|
||||
public DateTime SegmentStart;
|
||||
public int Team;
|
||||
|
|
@ -220,7 +223,10 @@ public class PlaytimeHistory : BasePlugin, IPluginConfig<PlaytimeHistoryConfig>
|
|||
if (tracked == null)
|
||||
OpenSession(slot, player!, now);
|
||||
else
|
||||
{
|
||||
UpdateState(tracked, player!, now);
|
||||
SampleStats(tracked, player!);
|
||||
}
|
||||
}
|
||||
foreach (var slot in _tracked.Keys.Where(s => !seen.Contains(s)).ToList())
|
||||
CloseSession(slot, _tracked[slot], EndKind.Disconnect, now, null, null);
|
||||
|
|
@ -247,7 +253,8 @@ public class PlaytimeHistory : BasePlugin, IPluginConfig<PlaytimeHistoryConfig>
|
|||
private void OpenSession(int slot, CCSPlayerController player, DateTime now)
|
||||
{
|
||||
var location = LookupLocation(player.IpAddress);
|
||||
var tracked = new Tracked { SteamId = player.SteamID, SessionKey = NewKey(), Baseline = ReadStats(player) };
|
||||
var tracked = new Tracked { SteamId = player.SteamID, SessionKey = NewKey() };
|
||||
SampleStats(tracked, player);
|
||||
_tracked[slot] = tracked;
|
||||
_writer!.Enqueue(new SessionOpen(tracked.SessionKey, tracked.SteamId, Config.ServerId, player.PlayerName, now, _map,
|
||||
_tracked.Count, Server.MaxPlayers, location?.CountryIso, location?.CountryName, location?.City, ModuleVersion));
|
||||
|
|
@ -284,7 +291,9 @@ public class PlaytimeHistory : BasePlugin, IPluginConfig<PlaytimeHistoryConfig>
|
|||
if (tracked.SegmentKey != null)
|
||||
_writer!.Enqueue(new SegmentClose(tracked.SegmentKey, now, Config.CountSpectatorTime));
|
||||
|
||||
var stats = player != null ? Delta(ReadStats(player), tracked.Baseline) : null;
|
||||
if (player != null)
|
||||
SampleStats(tracked, player);
|
||||
var stats = tracked.Stats;
|
||||
var ping = tracked.PingSamples > 0
|
||||
? new PingStats((int)(tracked.PingSum / tracked.PingSamples), tracked.PingMin, tracked.PingMax, tracked.PingSamples)
|
||||
: null;
|
||||
|
|
@ -310,24 +319,41 @@ public class PlaytimeHistory : BasePlugin, IPluginConfig<PlaytimeHistoryConfig>
|
|||
|
||||
private static MatchStats? ReadStats(CCSPlayerController player)
|
||||
{
|
||||
var stats = player.ActionTrackingServices?.MatchStats;
|
||||
if (stats == null)
|
||||
try
|
||||
{
|
||||
var stats = player.ActionTrackingServices?.MatchStats;
|
||||
if (stats == null)
|
||||
return null;
|
||||
return new MatchStats(stats.Kills, stats.Deaths, stats.Assists, stats.HeadShotKills, stats.Damage, player.MVPs, player.Score);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return null;
|
||||
return new MatchStats(stats.Kills, stats.Deaths, stats.Assists, stats.HeadShotKills, stats.Damage, player.MVPs, player.Score);
|
||||
}
|
||||
}
|
||||
|
||||
// This session's share of the map's running totals. Totals that went down were reset, so they
|
||||
// count from zero.
|
||||
private static MatchStats? Delta(MatchStats? now, MatchStats? baseline)
|
||||
// Adds what the map's running stats gained since the last read to the session's total. The first
|
||||
// read is only the starting point: what's there already happened before this session. Kills and
|
||||
// score can go down (a teamkill), but deaths and damage only go down when the game resets the
|
||||
// stats (the match starting after warmup, say); then all of the new values count.
|
||||
private static void SampleStats(Tracked tracked, CCSPlayerController player)
|
||||
{
|
||||
var now = ReadStats(player);
|
||||
if (now == null)
|
||||
return null;
|
||||
if (baseline == null)
|
||||
return now;
|
||||
static int D(int n, int b) => n >= b ? n - b : n;
|
||||
return new MatchStats(D(now.Kills, baseline.Kills), D(now.Deaths, baseline.Deaths), D(now.Assists, baseline.Assists),
|
||||
D(now.Headshots, baseline.Headshots), D(now.Damage, baseline.Damage), D(now.Mvp, baseline.Mvp),
|
||||
D(now.Score, baseline.Score));
|
||||
return;
|
||||
var last = tracked.LastStats;
|
||||
tracked.LastStats = now;
|
||||
if (last == null)
|
||||
{
|
||||
tracked.Stats ??= new MatchStats(0, 0, 0, 0, 0, 0, 0);
|
||||
return;
|
||||
}
|
||||
if (now.Deaths < last.Deaths || now.Damage < last.Damage)
|
||||
last = new MatchStats(0, 0, 0, 0, 0, 0, 0);
|
||||
var s = tracked.Stats!;
|
||||
tracked.Stats = new MatchStats(s.Kills + now.Kills - last.Kills, s.Deaths + now.Deaths - last.Deaths,
|
||||
s.Assists + now.Assists - last.Assists, s.Headshots + now.Headshots - last.Headshots,
|
||||
s.Damage + now.Damage - last.Damage, s.Mvp + now.Mvp - last.Mvp, s.Score + now.Score - last.Score);
|
||||
}
|
||||
|
||||
private Geo.Location? LookupLocation(string? address)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue