798 lines
30 KiB
C#
798 lines
30 KiB
C#
using System.Linq;
|
|
using Content.Server.Cargo.Components;
|
|
using Content.Server.GameTicking;
|
|
using Content.Server.Mind;
|
|
using Content.Server.Station.Systems;
|
|
using Content.Server.Store.Systems;
|
|
using Content.Shared._Sunrise.StatsBoard;
|
|
using Content.Shared.Bed.Sleep;
|
|
using Content.Shared.Cargo.Components;
|
|
using Content.Shared.Clumsy;
|
|
using Content.Shared.Construction;
|
|
using Content.Shared.Cuffs.Components;
|
|
using Content.Shared.Damage;
|
|
using Content.Shared.Doors.Systems;
|
|
using Content.Shared.Electrocution;
|
|
using Content.Shared.Fluids;
|
|
using Content.Shared.Ghost;
|
|
using Content.Shared.Humanoid;
|
|
using Content.Shared.Humanoid.Prototypes;
|
|
using Content.Shared.Interaction.Components;
|
|
using Content.Shared.Interaction.Events;
|
|
using Content.Shared.Item;
|
|
using Content.Shared.Mind.Components;
|
|
using Content.Shared.Mobs;
|
|
using Content.Shared.Slippery;
|
|
using Content.Shared.Tag;
|
|
using Robust.Shared.Network;
|
|
using Robust.Shared.Player;
|
|
using Robust.Shared.Prototypes;
|
|
using Robust.Shared.Timing;
|
|
using Robust.Shared.Localization;
|
|
using Content.Shared.Damage.Systems;
|
|
|
|
namespace Content.Server.StatsBoard;
|
|
|
|
public sealed class StatsBoardSystem : EntitySystem
|
|
{
|
|
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
|
[Dependency] private readonly TagSystem _tagSystem = default!;
|
|
[Dependency] private readonly StationSystem _station = default!;
|
|
[Dependency] private readonly MindSystem _mindSystem = default!;
|
|
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
|
[Dependency] private readonly GameTicker _gameTicker = default!;
|
|
[Dependency] private readonly ISharedPlayerManager _player = default!;
|
|
|
|
private (EntityUid? killer, EntityUid? victim, TimeSpan time) _firstMurder = (null, null, TimeSpan.Zero);
|
|
private EntityUid? _hamsterKiller;
|
|
private int _jointCreated;
|
|
private (EntityUid? clown, TimeSpan? time) _clownCuffed = (null, null);
|
|
private readonly Dictionary<EntityUid, StatisticEntry> _statisticEntries = new();
|
|
|
|
public override void Initialize()
|
|
{
|
|
base.Initialize();
|
|
|
|
SubscribeLocalEvent<ActorComponent, DamageChangedEvent>(OnDamageModify);
|
|
SubscribeLocalEvent<ActorComponent, SlippedEvent>(OnSlippedEvent);
|
|
SubscribeLocalEvent<ActorComponent, CreamedEvent>(OnCreamedEvent);
|
|
SubscribeLocalEvent<ActorComponent, InteractionAttemptEvent>(OnInteractionAttempt);
|
|
SubscribeLocalEvent<ActorComponent, MobStateChangedEvent>(OnMobStateChanged);
|
|
SubscribeLocalEvent<ActorComponent, DoorEmaggedEvent>(OnDoorEmagged);
|
|
SubscribeLocalEvent<ActorComponent, ElectrocutedEvent>(OnElectrocuted);
|
|
SubscribeLocalEvent<ActorComponent, SubtractCashEvent>(OnItemPurchasedEvent);
|
|
SubscribeLocalEvent<ActorComponent, CuffedEvent>(OnCuffedEvent);
|
|
SubscribeLocalEvent<ActorComponent, ItemConstructionCreated>(OnCraftedEvent);
|
|
SubscribeLocalEvent<ActorComponent, AbsorberPudleEvent>(OnAbsorbedPuddleEvent);
|
|
SubscribeLocalEvent<ActorComponent, MindAddedMessage>(OnMindAdded);
|
|
}
|
|
|
|
private void OnMindAdded(EntityUid uid, ActorComponent comp, MindAddedMessage ev)
|
|
{
|
|
if (_statisticEntries.ContainsKey(uid) || ev.Mind.Comp.UserId == null || HasComp<GhostComponent>(uid))
|
|
return;
|
|
|
|
var value = new StatisticEntry(MetaData(uid).EntityName, ev.Mind.Comp.UserId.Value);
|
|
_statisticEntries.Add(uid, value);
|
|
}
|
|
|
|
public void CleanEntries()
|
|
{
|
|
_firstMurder = (null, null, TimeSpan.Zero);
|
|
_hamsterKiller = null;
|
|
_jointCreated = 0;
|
|
_clownCuffed = (null, TimeSpan.Zero);
|
|
_statisticEntries.Clear();
|
|
}
|
|
|
|
private void OnAbsorbedPuddleEvent(EntityUid uid, ActorComponent comp, ref AbsorberPudleEvent ev)
|
|
{
|
|
if (!_mindSystem.TryGetMind(comp.PlayerSession, out var mindId, out var mind))
|
|
return;
|
|
|
|
if (_statisticEntries.TryGetValue(uid, out var value))
|
|
{
|
|
value.AbsorbedPuddleCount += 1;
|
|
}
|
|
}
|
|
|
|
private void OnCraftedEvent(EntityUid uid, ActorComponent comp, ref ItemConstructionCreated ev)
|
|
{
|
|
if (!_mindSystem.TryGetMind(comp.PlayerSession, out var mindId, out var mind))
|
|
return;
|
|
|
|
if (!_statisticEntries.TryGetValue(uid, out var value))
|
|
return;
|
|
|
|
if (!TryComp<MetaDataComponent>(ev.Item, out var metaDataComponent))
|
|
return;
|
|
|
|
if (metaDataComponent.EntityPrototype == null)
|
|
return;
|
|
switch (metaDataComponent.EntityPrototype.ID)
|
|
{
|
|
case "Blunt":
|
|
case "Joint":
|
|
_jointCreated += 1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
private void OnCuffedEvent(EntityUid uid, ActorComponent comp, ref CuffedEvent ev)
|
|
{
|
|
if (!_statisticEntries.TryGetValue(uid, out var value))
|
|
return;
|
|
|
|
value.CuffedCount += 1;
|
|
if (_clownCuffed.clown != null)
|
|
return;
|
|
if (!HasComp<ClumsyComponent>(uid))
|
|
return;
|
|
_clownCuffed.clown = uid;
|
|
_clownCuffed.time = _gameTiming.CurTime.Subtract(_gameTicker.RoundStartTimeSpan);
|
|
}
|
|
|
|
private void OnItemPurchasedEvent(EntityUid uid, ActorComponent comp, ref SubtractCashEvent ev)
|
|
{
|
|
if (!_statisticEntries.TryGetValue(uid, out var value))
|
|
return;
|
|
|
|
if (ev.Currency != "Telecrystal")
|
|
return;
|
|
if (value.SpentTk == null)
|
|
{
|
|
value.SpentTk = ev.Cost.Int();
|
|
}
|
|
else
|
|
{
|
|
value.SpentTk += ev.Cost.Int();
|
|
}
|
|
}
|
|
|
|
private void OnElectrocuted(EntityUid uid, ActorComponent comp, ElectrocutedEvent ev)
|
|
{
|
|
if (!_statisticEntries.TryGetValue(uid, out var value))
|
|
return;
|
|
|
|
value.ElectrocutedCount += 1;
|
|
}
|
|
|
|
private void OnDoorEmagged(EntityUid uid, ActorComponent comp, ref DoorEmaggedEvent ev)
|
|
{
|
|
if (!_statisticEntries.TryGetValue(uid, out var value))
|
|
return;
|
|
|
|
value.DoorEmagedCount += 1;
|
|
}
|
|
|
|
private void OnInteractionAttempt(EntityUid uid, ActorComponent comp, InteractionAttemptEvent args)
|
|
{
|
|
if (!_statisticEntries.TryGetValue(uid, out var value))
|
|
return;
|
|
|
|
if (!HasComp<ItemComponent>(args.Target))
|
|
return;
|
|
if (MetaData(args.Target.Value).EntityPrototype == null)
|
|
return;
|
|
var entityPrototype = MetaData(args.Target.Value).EntityPrototype;
|
|
if (entityPrototype is not { ID: "CaptainIDCard" })
|
|
return;
|
|
if (value.IsInteractedCaptainCard)
|
|
return;
|
|
value.IsInteractedCaptainCard = true;
|
|
}
|
|
|
|
private void OnCreamedEvent(EntityUid uid, ActorComponent comp, ref CreamedEvent ev)
|
|
{
|
|
if (!_statisticEntries.TryGetValue(uid, out var value))
|
|
return;
|
|
|
|
value.CreamedCount += 1;
|
|
}
|
|
|
|
private void OnMobStateChanged(EntityUid uid, ActorComponent comp, MobStateChangedEvent args)
|
|
{
|
|
if (!_statisticEntries.TryGetValue(uid, out var value))
|
|
return;
|
|
|
|
switch (args.NewMobState)
|
|
{
|
|
case MobState.Dead:
|
|
{
|
|
value.DeadCount += 1;
|
|
|
|
EntityUid? origin = null;
|
|
if (args.Origin != null)
|
|
{
|
|
origin = args.Origin.Value;
|
|
}
|
|
|
|
if (_firstMurder.victim == null && HasComp<HumanoidAppearanceComponent>(uid))
|
|
{
|
|
_firstMurder.victim = uid;
|
|
_firstMurder.killer = origin;
|
|
_firstMurder.time = _gameTiming.CurTime.Subtract(_gameTicker.RoundStartTimeSpan);
|
|
Logger.Info($"First Murder. CurTime: {_gameTiming.CurTime}, RoundStartTimeSpan: {_gameTicker.RoundStartTimeSpan}, Substract: {_gameTiming.CurTime.Subtract(_gameTicker.RoundStartTimeSpan)}");
|
|
}
|
|
|
|
if (origin != null)
|
|
{
|
|
if (_hamsterKiller == null && _tagSystem.HasTag(uid, "Hamster"))
|
|
{
|
|
_hamsterKiller = origin.Value;
|
|
}
|
|
|
|
if (!_statisticEntries.TryGetValue(origin.Value, out var originEntry))
|
|
return;
|
|
|
|
if (_tagSystem.HasTag(uid, "Mouse"))
|
|
{
|
|
originEntry.KilledMouseCount += 1;
|
|
}
|
|
|
|
if (HasComp<HumanoidAppearanceComponent>(uid))
|
|
originEntry.HumanoidKillCount += 1;
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
private void OnDamageModify(EntityUid uid, ActorComponent comp, DamageChangedEvent ev)
|
|
{
|
|
DamageGetModify(uid, ev);
|
|
|
|
if (ev.Origin != null)
|
|
DamageTakeModify(ev.Origin.Value, ev);
|
|
}
|
|
|
|
private void DamageTakeModify(EntityUid uid, DamageChangedEvent ev)
|
|
{
|
|
if (!_statisticEntries.TryGetValue(uid, out var value))
|
|
return;
|
|
|
|
if (ev.DamageDelta == null)
|
|
return;
|
|
|
|
if (ev.DamageIncreased)
|
|
{
|
|
value.TotalInflictedDamage += ev.DamageDelta.GetTotal().Int();
|
|
}
|
|
else
|
|
{
|
|
value.TotalInflictedHeal += Math.Abs(ev.DamageDelta.GetTotal().Int());
|
|
}
|
|
}
|
|
|
|
private void DamageGetModify(EntityUid uid, DamageChangedEvent ev)
|
|
{
|
|
if (!_statisticEntries.TryGetValue(uid, out var value))
|
|
return;
|
|
|
|
if (ev.DamageDelta == null)
|
|
return;
|
|
|
|
if (ev.DamageIncreased)
|
|
{
|
|
value.TotalTakeDamage += ev.DamageDelta.GetTotal().Int();
|
|
}
|
|
else
|
|
{
|
|
value.TotalTakeHeal += Math.Abs(ev.DamageDelta.GetTotal().Int());
|
|
}
|
|
}
|
|
|
|
private void OnSlippedEvent(EntityUid uid, ActorComponent comp, ref SlippedEvent ev)
|
|
{
|
|
if (!_statisticEntries.TryGetValue(uid, out var value))
|
|
return;
|
|
|
|
if (HasComp<HumanoidAppearanceComponent>(uid))
|
|
value.SlippedCount += 1;
|
|
}
|
|
|
|
private StationBankAccountComponent? GetBankAccount(EntityUid? uid)
|
|
{
|
|
if (uid != null && TryComp<StationBankAccountComponent>(uid, out var bankAccount))
|
|
{
|
|
return bankAccount;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public override void Update(float frameTime)
|
|
{
|
|
base.Update(frameTime);
|
|
|
|
var statsQuery = EntityQueryEnumerator<ActorComponent>();
|
|
while (statsQuery.MoveNext(out var ent, out var comp))
|
|
{
|
|
if (!_statisticEntries.TryGetValue(ent, out var value))
|
|
return;
|
|
|
|
if (TryComp<TransformComponent>(ent, out var transformComponent) &&
|
|
transformComponent.GridUid == null && HasComp<HumanoidAppearanceComponent>(ent))
|
|
value.SpaceTime += TimeSpan.FromSeconds(frameTime);
|
|
|
|
if (TryComp<CuffableComponent>(ent, out var cuffableComponent) &&
|
|
!cuffableComponent.CanStillInteract)
|
|
value.CuffedTime += TimeSpan.FromSeconds(frameTime);
|
|
|
|
if (HasComp<SleepingComponent>(ent))
|
|
value.SleepTime += TimeSpan.FromSeconds(frameTime);
|
|
}
|
|
}
|
|
|
|
public StatisticEntry[] GetStatisticEntries()
|
|
{
|
|
return _statisticEntries.Values.ToArray();
|
|
}
|
|
|
|
public SharedStatisticEntry ConvertToSharedStatisticEntry(StatisticEntry entry)
|
|
{
|
|
return new SharedStatisticEntry(entry.Name, entry.FirstActor)
|
|
{
|
|
TotalTakeDamage = entry.TotalTakeDamage,
|
|
TotalTakeHeal = entry.TotalTakeHeal,
|
|
TotalInflictedDamage = entry.TotalInflictedDamage,
|
|
TotalInflictedHeal = entry.TotalInflictedHeal,
|
|
SlippedCount = entry.SlippedCount,
|
|
CreamedCount = entry.CreamedCount,
|
|
DoorEmagedCount = entry.DoorEmagedCount,
|
|
ElectrocutedCount = entry.ElectrocutedCount,
|
|
CuffedCount = entry.CuffedCount,
|
|
AbsorbedPuddleCount = entry.AbsorbedPuddleCount,
|
|
SpentTk = entry.SpentTk,
|
|
DeadCount = entry.DeadCount,
|
|
HumanoidKillCount = entry.HumanoidKillCount,
|
|
KilledMouseCount = entry.KilledMouseCount,
|
|
CuffedTime = entry.CuffedTime,
|
|
SpaceTime = entry.SpaceTime,
|
|
SleepTime = entry.SleepTime,
|
|
IsInteractedCaptainCard = entry.IsInteractedCaptainCard,
|
|
};
|
|
}
|
|
|
|
public string GetRoundStats()
|
|
{
|
|
var result = "";
|
|
var totalSlipped = 0;
|
|
var totalCreampied = 0;
|
|
var totalDamage = 0;
|
|
var totalHeal = 0;
|
|
var totalDoorEmaged = 0;
|
|
var maxSlippedCount = 0;
|
|
var maxDeadCount = 0;
|
|
var maxSpeciesCount = 0;
|
|
var maxDoorEmagedCount = 0;
|
|
var totalKilledMice = 0;
|
|
var totalAbsorbedPuddle = 0;
|
|
var maxKillsMice = 0;
|
|
var totalCaptainCardInteracted = 0;
|
|
var totalElectrocutedCount = 0;
|
|
var totalSleepTime = TimeSpan.Zero;
|
|
var minSpentTk = int.MaxValue;
|
|
var maxHumKillCount = 0;
|
|
var totalCuffedCount = 0;
|
|
var maxTakeDamage = 0;
|
|
var maxInflictedHeal = 0;
|
|
var maxInflictedDamage = 0;
|
|
var maxPuddleAbsorb = 0;
|
|
var maxCuffedTime = TimeSpan.Zero;
|
|
var maxSpaceTime = TimeSpan.Zero;
|
|
var maxSleepTime = TimeSpan.Zero;
|
|
string? mostPopularSpecies = null;
|
|
Dictionary<string, int> roundSpecies = new();
|
|
EntityUid? mostSlippedCharacter = null;
|
|
EntityUid? mostDeadCharacter = null;
|
|
EntityUid? mostDoorEmagedCharacter = null;
|
|
EntityUid? mostKillsMiceCharacter = null;
|
|
EntityUid? playerWithMinSpentTk = null;
|
|
EntityUid? playerWithMaxHumKills = null;
|
|
EntityUid? playerWithMaxDamage = null;
|
|
EntityUid? playerWithLongestCuffedTime = null;
|
|
EntityUid? playerWithLongestSpaceTime = null;
|
|
EntityUid? playerWithLongestSleepTime = null;
|
|
EntityUid? playerWithMostInflictedHeal = null;
|
|
EntityUid? playerWithMostInflictedDamage = null;
|
|
EntityUid? playerWithMostPuddleAbsorb = null;
|
|
|
|
foreach (var (uid, data) in _statisticEntries)
|
|
{
|
|
if (TryComp<HumanoidAppearanceComponent>(uid, out var humanoidAppearanceComponent))
|
|
{
|
|
var speciesProto = _prototypeManager.Index<SpeciesPrototype>(humanoidAppearanceComponent.Species);
|
|
|
|
if (roundSpecies.TryGetValue(speciesProto.Name, out var count))
|
|
{
|
|
roundSpecies[speciesProto.Name] = count + 1;
|
|
}
|
|
else
|
|
{
|
|
roundSpecies.Add(speciesProto.Name, 1);
|
|
}
|
|
}
|
|
|
|
totalDoorEmaged += data.DoorEmagedCount;
|
|
totalSlipped += data.SlippedCount;
|
|
totalCreampied += data.CreamedCount;
|
|
totalDamage += data.TotalTakeDamage;
|
|
totalHeal += data.TotalTakeHeal;
|
|
totalCuffedCount += data.CuffedCount;
|
|
totalKilledMice += data.KilledMouseCount;
|
|
totalSleepTime += data.SleepTime;
|
|
totalAbsorbedPuddle += data.AbsorbedPuddleCount;
|
|
totalElectrocutedCount += data.ElectrocutedCount;
|
|
|
|
if (data.SlippedCount > maxSlippedCount)
|
|
{
|
|
maxSlippedCount = data.SlippedCount;
|
|
mostSlippedCharacter = uid;
|
|
}
|
|
|
|
if (data.DoorEmagedCount > maxDoorEmagedCount)
|
|
{
|
|
maxDoorEmagedCount = data.DoorEmagedCount;
|
|
mostDoorEmagedCharacter = uid;
|
|
}
|
|
|
|
if (data.DeadCount > maxDeadCount)
|
|
{
|
|
maxDeadCount = data.DeadCount;
|
|
mostDeadCharacter = uid;
|
|
}
|
|
|
|
if (data.KilledMouseCount > maxKillsMice)
|
|
{
|
|
maxKillsMice = data.KilledMouseCount;
|
|
mostKillsMiceCharacter = uid;
|
|
}
|
|
|
|
if (data.IsInteractedCaptainCard)
|
|
{
|
|
totalCaptainCardInteracted += 1;
|
|
}
|
|
|
|
if (data.SpentTk != null && data.SpentTk < minSpentTk)
|
|
{
|
|
minSpentTk = data.SpentTk.Value;
|
|
playerWithMinSpentTk = uid;
|
|
}
|
|
|
|
if (data.HumanoidKillCount > maxHumKillCount)
|
|
{
|
|
maxHumKillCount = data.HumanoidKillCount;
|
|
playerWithMaxHumKills = uid;
|
|
}
|
|
|
|
if (data.TotalTakeDamage > maxTakeDamage)
|
|
{
|
|
maxTakeDamage = data.TotalTakeDamage;
|
|
playerWithMaxDamage = uid;
|
|
}
|
|
|
|
if (data.CuffedTime > maxCuffedTime)
|
|
{
|
|
maxCuffedTime = data.CuffedTime;
|
|
playerWithLongestCuffedTime = uid;
|
|
}
|
|
|
|
if (data.SleepTime > maxSleepTime)
|
|
{
|
|
maxSleepTime = data.SleepTime;
|
|
playerWithLongestSleepTime = uid;
|
|
}
|
|
|
|
if (data.SpaceTime > maxSpaceTime)
|
|
{
|
|
maxSpaceTime = data.SpaceTime;
|
|
playerWithLongestSpaceTime = uid;
|
|
}
|
|
|
|
if (data.TotalInflictedHeal > maxInflictedHeal)
|
|
{
|
|
maxInflictedHeal = data.TotalInflictedHeal;
|
|
playerWithMostInflictedHeal = uid;
|
|
}
|
|
|
|
if (data.TotalInflictedDamage > maxInflictedDamage)
|
|
{
|
|
maxInflictedDamage = data.TotalInflictedDamage;
|
|
playerWithMostInflictedDamage = uid;
|
|
}
|
|
|
|
if (data.AbsorbedPuddleCount > maxPuddleAbsorb)
|
|
{
|
|
maxPuddleAbsorb = data.AbsorbedPuddleCount;
|
|
playerWithMostPuddleAbsorb = uid;
|
|
}
|
|
}
|
|
|
|
result += Loc.GetString("statsentry-species-entry-name") + "\n";
|
|
foreach (var speciesEntry in roundSpecies)
|
|
{
|
|
var species = speciesEntry.Key;
|
|
var count = speciesEntry.Value;
|
|
|
|
if (count > maxSpeciesCount)
|
|
{
|
|
maxSpeciesCount = count;
|
|
mostPopularSpecies = species;
|
|
}
|
|
|
|
result += Loc.GetString("statsentry-species-entry", ("name", Loc.GetString(species)), ("count", count)) + "\n";
|
|
}
|
|
|
|
if (mostPopularSpecies != null)
|
|
{
|
|
result += Loc.GetString("statsentry-mst-pop-species", ("name", Loc.GetString(mostPopularSpecies))) + "\n";
|
|
}
|
|
|
|
var station = _station.GetStations().FirstOrDefault();
|
|
var bank = GetBankAccount(station);
|
|
|
|
if (bank != null)
|
|
{
|
|
result += Loc.GetString("statsentry-bank-balance-total", ("balance", bank.Accounts.Values.Sum())) + "\n";
|
|
foreach (var (account, balance) in bank.Accounts)
|
|
{
|
|
result += Loc.GetString("statsentry-bank-balance-account", ("account", Loc.GetString(account)), ("balance", balance)) + "\n";
|
|
}
|
|
}
|
|
|
|
if (_firstMurder.victim != null)
|
|
{
|
|
var victimUsername = TryGetUsername(_firstMurder.victim.Value);
|
|
var victimName = TryGetName(_firstMurder.victim.Value);
|
|
var victimUsernameColor = victimUsername != null ? $" ([color=gray]{victimUsername}[/color])" : "";
|
|
result += Loc.GetString("statsentry-firth-murder", ("name", victimName), ("username", victimUsernameColor)) + "\n";
|
|
result += Loc.GetString("statsentry-firth-murder-time", ("time", _firstMurder.time.ToString("hh\\:mm\\:ss"))) + "\n";
|
|
if (_firstMurder.killer != null)
|
|
{
|
|
var killerUsername = TryGetUsername(_firstMurder.killer.Value);
|
|
var killerName = TryGetName(_firstMurder.killer.Value);
|
|
var killerUsernameColor = killerUsername != null ? $" ([color=gray]{killerUsername}[/color])" : "";
|
|
result += Loc.GetString("statsentry-firth-murder-killer", ("name", killerName), ("username", killerUsernameColor)) + "\n";
|
|
}
|
|
else
|
|
{
|
|
result += Loc.GetString("statsentry-firth-murder-killer-none") + "\n";
|
|
}
|
|
}
|
|
|
|
if (totalSlipped >= 1)
|
|
{
|
|
result += Loc.GetString("statsentry-total-slipped", ("count", totalSlipped)) + "\n";
|
|
}
|
|
|
|
if (mostSlippedCharacter != null && maxSlippedCount > 1)
|
|
{
|
|
var username = TryGetUsername(mostSlippedCharacter.Value);
|
|
var name = TryGetName(mostSlippedCharacter.Value);
|
|
var usernameColor = username != null ? $" ([color=gray]{username}[/color])" : "";
|
|
result += Loc.GetString("statsentry-most-slipped", ("name", name), ("username", usernameColor), ("count", maxSlippedCount)) + "\n";
|
|
}
|
|
|
|
if (totalCreampied >= 1)
|
|
{
|
|
result += Loc.GetString("statsentry-total-creampied", ("total", totalCreampied)) + "\n";
|
|
}
|
|
|
|
if (mostDeadCharacter != null && maxDeadCount > 1)
|
|
{
|
|
var username = TryGetUsername(mostDeadCharacter.Value);
|
|
var name = TryGetName(mostDeadCharacter.Value);
|
|
var usernameColor = username != null ? $" ([color=gray]{username}[/color])" : "";
|
|
result += Loc.GetString("statsentry-most-dead", ("name", name), ("username", usernameColor), ("count", maxDeadCount)) + "\n";
|
|
}
|
|
|
|
if (totalDoorEmaged >= 1)
|
|
{
|
|
result += Loc.GetString("statsentry-total-door-emaged", ("count", totalDoorEmaged)) + "\n";
|
|
}
|
|
|
|
if (mostDoorEmagedCharacter != null)
|
|
{
|
|
var username = TryGetUsername(mostDoorEmagedCharacter.Value);
|
|
var name = TryGetName(mostDoorEmagedCharacter.Value);
|
|
var usernameColor = username != null ? $" ([color=gray]{username}[/color])" : "";
|
|
result += Loc.GetString("statsentry-most-door-emaged-character", ("name", name), ("username", usernameColor), ("count", maxDoorEmagedCount)) + "\n";
|
|
}
|
|
|
|
if (_jointCreated >= 1)
|
|
{
|
|
result += Loc.GetString("statsentry-joint-created", ("count", _jointCreated)) + "\n";
|
|
}
|
|
|
|
if (totalKilledMice >= 1)
|
|
{
|
|
result += Loc.GetString("statsentry-total-killed-mice", ("count", totalKilledMice)) + "\n";
|
|
}
|
|
|
|
if (mostKillsMiceCharacter != null && maxKillsMice > 1)
|
|
{
|
|
var username = TryGetUsername(mostKillsMiceCharacter.Value);
|
|
var name = TryGetName(mostKillsMiceCharacter.Value);
|
|
var usernameColor = username != null ? $" ([color=gray]{username}[/color])" : "";
|
|
result += Loc.GetString("statsentry-most-kills-mice-character", ("name", name), ("username", usernameColor), ("count", maxKillsMice)) + "\n";
|
|
}
|
|
|
|
if (_hamsterKiller != null)
|
|
{
|
|
var username = TryGetUsername(_hamsterKiller.Value);
|
|
var name = TryGetName(_hamsterKiller.Value);
|
|
var usernameColor = username != null ? $" ([color=gray]{username}[/color])" : "";
|
|
result += Loc.GetString("statsentry-hamster-killer", ("name", name), ("username", usernameColor)) + "\n";
|
|
}
|
|
|
|
if (totalCuffedCount >= 1)
|
|
{
|
|
result += Loc.GetString("statsentry-total-cuffed-count", ("count", totalCuffedCount)) + "\n";
|
|
}
|
|
|
|
if (playerWithLongestCuffedTime != null)
|
|
{
|
|
var username = TryGetUsername(playerWithLongestCuffedTime.Value);
|
|
var name = TryGetName(playerWithLongestCuffedTime.Value);
|
|
var usernameColor = username != null ? $" ([color=gray]{username}[/color])" : "";
|
|
result += Loc.GetString("statsentry-player-with-longest-cuffed-time", ("name", name), ("username", usernameColor), ("time", maxCuffedTime.ToString("hh\\:mm\\:ss"))) + "\n";
|
|
}
|
|
|
|
if (totalSleepTime > TimeSpan.Zero)
|
|
{
|
|
result += Loc.GetString("statsentry-total-sleep-time", ("time", totalSleepTime.ToString("hh\\:mm\\:ss"))) + "\n";
|
|
}
|
|
|
|
if (playerWithLongestSleepTime != null)
|
|
{
|
|
var username = TryGetUsername(playerWithLongestSleepTime.Value);
|
|
var name = TryGetName(playerWithLongestSleepTime.Value);
|
|
var usernameColor = username != null ? $" ([color=gray]{username}[/color])" : "";
|
|
result += Loc.GetString("statsentry-player-with-longest-sleep-time", ("name", name), ("username", usernameColor)) + "\n";
|
|
result += Loc.GetString("statsentry-player-with-longest-sleep-time-time", ("time", maxSleepTime.ToString("hh\\:mm\\:ss"))) + "\n";
|
|
}
|
|
|
|
if (playerWithLongestSpaceTime != null)
|
|
{
|
|
var username = TryGetUsername(playerWithLongestSpaceTime.Value);
|
|
var name = TryGetName(playerWithLongestSpaceTime.Value);
|
|
var usernameColor = username != null ? $" ([color=gray]{username}[/color])" : "";
|
|
result += Loc.GetString("statsentry-player-with-longest-space-time", ("name", name), ("username", usernameColor), ("time", maxSpaceTime.ToString("hh\\:mm\\:ss"))) + "\n";
|
|
}
|
|
|
|
if (_clownCuffed.clown != null && _clownCuffed.time != null)
|
|
{
|
|
var username = TryGetUsername(_clownCuffed.clown.Value);
|
|
var name = TryGetName(_clownCuffed.clown.Value);
|
|
var usernameColor = username != null ? $" ([color=gray]{username}[/color])" : "";
|
|
result += Loc.GetString("statsentry-clown-cuffed", ("name", name), ("username", usernameColor), ("time", _clownCuffed.time.Value.ToString("hh\\:mm\\:ss"))) + "\n";
|
|
}
|
|
|
|
if (totalHeal >= 1)
|
|
{
|
|
result += Loc.GetString("statsentry-total-heal", ("count", totalHeal)) + "\n";
|
|
}
|
|
|
|
if (playerWithMostInflictedHeal != null)
|
|
{
|
|
var username = TryGetUsername(playerWithMostInflictedHeal.Value);
|
|
var name = TryGetName(playerWithMostInflictedHeal.Value);
|
|
var usernameColor = username != null ? $" ([color=gray]{username}[/color])" : "";
|
|
result += Loc.GetString("statsentry-player-with-most-infected-heal", ("name", name), ("username", usernameColor), ("count", maxInflictedHeal)) + "\n";
|
|
}
|
|
|
|
if (totalDamage >= 1)
|
|
{
|
|
result += Loc.GetString("statsentry-total-damage", ("count", totalDamage)) + "\n";
|
|
}
|
|
|
|
if (playerWithMostInflictedDamage != null)
|
|
{
|
|
var username = TryGetUsername(playerWithMostInflictedDamage.Value);
|
|
var name = TryGetName(playerWithMostInflictedDamage.Value);
|
|
var usernameColor = username != null ? $" ([color=gray]{username}[/color])" : "";
|
|
result += Loc.GetString("statsentry-player-with-most-infected-damage", ("name", name), ("username", usernameColor), ("count", maxInflictedDamage)) + "\n";
|
|
}
|
|
|
|
if (playerWithMinSpentTk != null)
|
|
{
|
|
var username = TryGetUsername(playerWithMinSpentTk.Value);
|
|
var name = TryGetName(playerWithMinSpentTk.Value);
|
|
var usernameColor = username != null ? $" ([color=gray]{username}[/color])" : "";
|
|
result += Loc.GetString("statsentry-player-with-min-spent-tk", ("name", name), ("username", usernameColor), ("count", minSpentTk)) + "\n";
|
|
}
|
|
|
|
if (playerWithMaxHumKills != null && maxHumKillCount > 1)
|
|
{
|
|
var username = TryGetUsername(playerWithMaxHumKills.Value);
|
|
var name = TryGetName(playerWithMaxHumKills.Value);
|
|
var usernameColor = username != null ? $" ([color=gray]{username}[/color])" : "";
|
|
result += Loc.GetString("statsentry-player-with-max-hum-kills", ("name", name), ("username", usernameColor)) + "\n";
|
|
result += Loc.GetString("statsentry-player-with-max-hum-kills-count", ("count", maxHumKillCount)) + "\n";
|
|
}
|
|
|
|
if (playerWithMaxDamage != null)
|
|
{
|
|
var username = TryGetUsername(playerWithMaxDamage.Value);
|
|
var name = TryGetName(playerWithMaxDamage.Value);
|
|
var usernameColor = username != null ? $" ([color=gray]{username}[/color])" : "";
|
|
result += Loc.GetString("statsentry-player-with-max-damage", ("name", name), ("username", usernameColor), ("count", maxTakeDamage)) + "\n";
|
|
}
|
|
|
|
if (totalAbsorbedPuddle >= 1)
|
|
{
|
|
result += Loc.GetString("statsentry-total-absorbed-puddle", ("count", totalAbsorbedPuddle)) + "\n";
|
|
}
|
|
|
|
if (playerWithMostPuddleAbsorb != null && maxPuddleAbsorb > 1)
|
|
{
|
|
var username = TryGetUsername(playerWithMostPuddleAbsorb.Value);
|
|
var name = TryGetName(playerWithMostPuddleAbsorb.Value);
|
|
var usernameColor = username != null ? $" ([color=gray]{username}[/color])" : "";
|
|
result += Loc.GetString("statsentry-player-with-most-puddle-absorb", ("name", name), ("username", usernameColor), ("count", maxPuddleAbsorb)) + "\n";
|
|
}
|
|
|
|
if (totalCaptainCardInteracted >= 1)
|
|
{
|
|
result += Loc.GetString("statsentry-total-captain-card-interacted", ("count", totalCaptainCardInteracted)) + "\n";
|
|
}
|
|
|
|
if (totalElectrocutedCount >= 1)
|
|
{
|
|
result += Loc.GetString("statsentry-total-electrocuted-count", ("count", totalElectrocutedCount)) + "\n";
|
|
}
|
|
|
|
//убрал пробельчик, так как всё равно он есть при добавлении ласт строчки
|
|
|
|
return result;
|
|
}
|
|
|
|
private string? TryGetUsername(EntityUid uid)
|
|
{
|
|
string? username = null;
|
|
|
|
if (_mindSystem.TryGetMind(uid, out var mindId, out var mind) && _player.TryGetSessionById(mind.UserId, out var session))
|
|
{
|
|
username = session.Name;
|
|
}
|
|
|
|
return username;
|
|
}
|
|
|
|
private string TryGetName(EntityUid uid)
|
|
{
|
|
if (_statisticEntries.TryGetValue(uid, out var value))
|
|
return value.Name;
|
|
|
|
if (TryComp<MetaDataComponent>(uid, out var metaDataComponent))
|
|
return metaDataComponent.EntityName;
|
|
|
|
return "Кто это блядь?";
|
|
}
|
|
}
|
|
|
|
[Serializable]
|
|
public sealed partial class StatisticEntry(string name, NetUserId userId)
|
|
{
|
|
public string Name { get; set; } = name;
|
|
public NetUserId FirstActor { get; set; } = userId;
|
|
public int TotalTakeDamage { get; set; } = 0;
|
|
public int TotalTakeHeal { get; set; } = 0;
|
|
public int TotalInflictedDamage { get; set; } = 0;
|
|
public int TotalInflictedHeal { get; set; } = 0;
|
|
public int SlippedCount { get; set; } = 0;
|
|
public int CreamedCount { get; set; } = 0;
|
|
public int DoorEmagedCount { get; set; } = 0;
|
|
public int ElectrocutedCount { get; set; } = 0;
|
|
public int CuffedCount { get; set; } = 0;
|
|
public int AbsorbedPuddleCount { get; set; } = 0;
|
|
public int? SpentTk { get; set; } = null;
|
|
public int DeadCount { get; set; } = 0;
|
|
public int HumanoidKillCount { get; set; } = 0;
|
|
public int KilledMouseCount { get; set; } = 0;
|
|
public TimeSpan CuffedTime { get; set; } = TimeSpan.Zero;
|
|
public TimeSpan SpaceTime { get; set; } = TimeSpan.Zero;
|
|
public TimeSpan SleepTime { get; set; } = TimeSpan.Zero;
|
|
public bool IsInteractedCaptainCard { get; set; } = false;
|
|
}
|