initial commit
This commit is contained in:
commit
d701598350
67 changed files with 9351 additions and 0 deletions
56
Outnumbered/SnapshotBuilder.cs
Normal file
56
Outnumbered/SnapshotBuilder.cs
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
using System.Collections.Frozen;
|
||||
using CounterStrikeSharp.API;
|
||||
using CounterStrikeSharp.API.Core;
|
||||
using Outnumbered.Config;
|
||||
using Outnumbered.Data;
|
||||
using Outnumbered.Domain;
|
||||
|
||||
namespace Outnumbered;
|
||||
|
||||
// The single engine site that reads a player into an immutable PlayerSnapshot for the pure Domain math, plus the stat
|
||||
// registry (_statDefs) the Domain resolvers consume. Everything pure (handicap / combat / progression / stat resolution)
|
||||
// takes a snapshot + _statDefs and never touches a pawn/controller — so the CS2/CSSharp surface lives only here.
|
||||
public sealed partial class OutnumberedPlugin
|
||||
{
|
||||
private const int BaseMaxHp = 100;
|
||||
private const int BaseMaxArmor = 100;
|
||||
|
||||
// key -> StatDef, rebuilt from Config.Stats on Load + every !og_reload. This is the stat registry the Domain resolvers
|
||||
// index (StatResolver/CombatResolver take it) — the key->def view of the named Config.Stats fields (which stay, for JSON
|
||||
// back-compat). Projected straight from StatRegistry (Stats.cs), so a new stat is one registry row, not a line here.
|
||||
// FrozenDictionary: built once per load/reload, read per-hit (OffenseMultiplier alone does 3+ lookups/hit) — frozen
|
||||
// has faster reads than Dictionary. Ordinal matches Dictionary<string,_>'s default, so lookups are bit-identical.
|
||||
private FrozenDictionary<string, StatDef> _statDefs = FrozenDictionary<string, StatDef>.Empty;
|
||||
|
||||
private void RebuildStatDefs() =>
|
||||
_statDefs = StatRegistry.ToFrozenDictionary(r => r.Key, r => r.Def(Config.Stats), StringComparer.Ordinal);
|
||||
|
||||
// Build the immutable Domain input for one player. `p` is optional: it supplies the live pawn Health (drives the
|
||||
// missing-HP fraction for Berserk) — null is fine for paths that don't read Health (XP rate, where t ignores HP).
|
||||
// Upgrades + Cards are held by reference, so building a snapshot per hit/tick is allocation-free.
|
||||
internal PlayerSnapshot Snapshot(PlayerData pd, CCSPlayerController? p = null)
|
||||
{
|
||||
var pawn = p?.PlayerPawn.Value;
|
||||
double now = Server.CurrentTime; // read once for the 3 ability checks below (can't advance within this build)
|
||||
return new PlayerSnapshot
|
||||
{
|
||||
Level = pd.Level,
|
||||
Prestige = pd.Prestige,
|
||||
Xp = pd.Xp,
|
||||
Kills = pd.Kills,
|
||||
Deaths = pd.Deaths,
|
||||
HeadshotKills = pd.HeadshotKills,
|
||||
Streak = pd.Streak,
|
||||
Health = pawn?.Health ?? 0,
|
||||
HandicapProgress = _driver?.HandicapProgress(pd) ?? 0.0,
|
||||
HandicapFloor = _driver?.HandicapFloor(pd) ?? -1.0,
|
||||
TeamDealMult = _driver?.TeamDealMult() ?? 1.0,
|
||||
TeamTakeMult = _driver?.TeamTakeMult() ?? 1.0,
|
||||
OverchargeActive = AbilityActive(pd, AbOvercharge, now), // CombatResolver gates these on Abilities.Enabled
|
||||
BerserkActive = AbilityActive(pd, AbBerserk, now),
|
||||
AdrenalineActive = AbilityActive(pd, AbAdrenaline, now),
|
||||
Upgrades = pd.Upgrades,
|
||||
Cards = _driver?.CardSource(pd), // survival run (IStatBonusSource); null in TDM/GG
|
||||
};
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue