mirror of
https://github.com/space-wizards/space-station-14.git
synced 2026-02-15 03:31:30 +01:00
1v1 me first to 31 no powerups [Deathmatch Gamemode] (#19467)
Co-authored-by: Kara <lunarautomaton6@gmail.com>
This commit is contained in:
129
Content.Server/KillTracking/KillTrackingSystem.cs
Normal file
129
Content.Server/KillTracking/KillTrackingSystem.cs
Normal file
@@ -0,0 +1,129 @@
|
||||
using Content.Server.NPC.HTN;
|
||||
using Content.Shared.Damage;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Content.Shared.Mobs;
|
||||
using Robust.Server.GameObjects;
|
||||
|
||||
namespace Content.Server.KillTracking;
|
||||
|
||||
/// <summary>
|
||||
/// This handles <see cref="KillTrackerComponent"/> and recording who is damaging and killing entities.
|
||||
/// </summary>
|
||||
public sealed class KillTrackingSystem : EntitySystem
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public override void Initialize()
|
||||
{
|
||||
SubscribeLocalEvent<KillTrackerComponent, DamageChangedEvent>(OnDamageChanged);
|
||||
SubscribeLocalEvent<KillTrackerComponent, MobStateChangedEvent>(OnMobStateChanged);
|
||||
}
|
||||
|
||||
private void OnDamageChanged(EntityUid uid, KillTrackerComponent component, DamageChangedEvent args)
|
||||
{
|
||||
if (args.DamageDelta == null)
|
||||
return;
|
||||
|
||||
if (!args.DamageIncreased)
|
||||
{
|
||||
foreach (var key in component.LifetimeDamage.Keys)
|
||||
{
|
||||
component.LifetimeDamage[key] -= args.DamageDelta.Total;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
var source = GetKillSource(args.Origin);
|
||||
var damage = component.LifetimeDamage.GetValueOrDefault(source);
|
||||
component.LifetimeDamage[source] = damage + args.DamageDelta.Total;
|
||||
}
|
||||
|
||||
private void OnMobStateChanged(EntityUid uid, KillTrackerComponent component, MobStateChangedEvent args)
|
||||
{
|
||||
if (args.NewMobState != component.KillState || args.OldMobState >= args.NewMobState)
|
||||
return;
|
||||
|
||||
// impulse is the entity that did the finishing blow.
|
||||
var killImpulse = GetKillSource(args.Origin);
|
||||
|
||||
// source is the kill tracker source with the most damage dealt.
|
||||
var largestSource = GetLargestSource(component.LifetimeDamage);
|
||||
largestSource ??= killImpulse;
|
||||
|
||||
KillSource? killSource;
|
||||
KillSource? assistSource = null;
|
||||
|
||||
if (killImpulse is KillEnvironmentSource)
|
||||
{
|
||||
// if the kill was environmental, whatever did the most damage gets the kill.
|
||||
killSource = largestSource;
|
||||
}
|
||||
else if (killImpulse == largestSource)
|
||||
{
|
||||
// if the impulse and the source are the same, there's no assist
|
||||
killSource = killImpulse;
|
||||
}
|
||||
else
|
||||
{
|
||||
// the impulse gets the kill and the most damage gets the assist
|
||||
killSource = killImpulse;
|
||||
|
||||
// no assist is given to environmental kills
|
||||
if (largestSource is not KillEnvironmentSource)
|
||||
{
|
||||
// you have to do at least 50% of largest source's damage to get the assist.
|
||||
if (component.LifetimeDamage[largestSource] >= component.LifetimeDamage[killSource] / 2)
|
||||
{
|
||||
assistSource = largestSource;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// it's a suicide if:
|
||||
// - you caused your own death
|
||||
// - the kill source was the entity that died
|
||||
// - the entity that died had an assist on themselves
|
||||
var suicide = args.Origin == uid ||
|
||||
killSource is KillNpcSource npc && npc.NpcEnt == uid ||
|
||||
killSource is KillPlayerSource player && player.PlayerId == CompOrNull<ActorComponent>(uid)?.PlayerSession.UserId ||
|
||||
assistSource is KillNpcSource assistNpc && assistNpc.NpcEnt == uid ||
|
||||
assistSource is KillPlayerSource assistPlayer && assistPlayer.PlayerId == CompOrNull<ActorComponent>(uid)?.PlayerSession.UserId;
|
||||
|
||||
var ev = new KillReportedEvent(uid, killSource, assistSource, suicide);
|
||||
RaiseLocalEvent(uid, ref ev, true);
|
||||
}
|
||||
|
||||
private KillSource GetKillSource(EntityUid? sourceEntity)
|
||||
{
|
||||
if (TryComp<ActorComponent>(sourceEntity, out var actor))
|
||||
return new KillPlayerSource(actor.PlayerSession.UserId);
|
||||
if (HasComp<HTNComponent>(sourceEntity))
|
||||
return new KillNpcSource(sourceEntity.Value);
|
||||
return new KillEnvironmentSource();
|
||||
}
|
||||
|
||||
private KillSource? GetLargestSource(Dictionary<KillSource, FixedPoint2> lifetimeDamages)
|
||||
{
|
||||
KillSource? maxSource = null;
|
||||
var maxDamage = FixedPoint2.Zero;
|
||||
foreach (var (source, damage) in lifetimeDamages)
|
||||
{
|
||||
if (damage < maxDamage)
|
||||
continue;
|
||||
maxSource = source;
|
||||
maxDamage = damage;
|
||||
}
|
||||
|
||||
return maxSource;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event broadcasted and raised by-ref on an entity with <see cref="KillTrackerComponent"/> when they are killed.
|
||||
/// </summary>
|
||||
/// <param name="Entity">The entity that was killed</param>
|
||||
/// <param name="Primary">The primary source of the kill</param>
|
||||
/// <param name="Assist">A secondary source of the kill. Can be null.</param>
|
||||
/// <param name="Suicide">True if the entity that was killed caused their own death.</param>
|
||||
[ByRefEvent]
|
||||
public readonly record struct KillReportedEvent(EntityUid Entity, KillSource Primary, KillSource? Assist, bool Suicide);
|
||||
Reference in New Issue
Block a user