| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667 |
- using Content.Shared.Damage;
- using Content.Shared.Damage.Prototypes;
- using Content.Shared.Mobs.Components;
- using Robust.Shared.Prototypes;
- using System.Linq;
- namespace Content.Shared.Chat;
- public sealed class SharedSuicideSystem : EntitySystem
- {
- [Dependency] private readonly DamageableSystem _damageableSystem = default!;
- [Dependency] private readonly IPrototypeManager _prototypeManager = default!;
- /// <summary>
- /// Applies lethal damage spread out across the damage types given.
- /// </summary>
- public void ApplyLethalDamage(Entity<DamageableComponent> target, DamageSpecifier damageSpecifier)
- {
- // Create a new damageSpecifier so that we don't make alterations to the original DamageSpecifier
- // Failing to do this will permanently change a weapon's damage making it insta-kill people
- var appliedDamageSpecifier = new DamageSpecifier(damageSpecifier);
- if (!TryComp<MobThresholdsComponent>(target, out var mobThresholds))
- return;
- // Mob thresholds are sorted from alive -> crit -> dead,
- // grabbing the last key will give us how much damage is needed to kill a target from zero
- // The exact lethal damage amount is adjusted based on their current damage taken
- var lethalAmountOfDamage = mobThresholds.Thresholds.Keys.Last() - target.Comp.TotalDamage;
- var totalDamage = appliedDamageSpecifier.GetTotal();
- // Removing structural because it causes issues against entities that cannot take structural damage,
- // then getting the total to use in calculations for spreading out damage.
- appliedDamageSpecifier.DamageDict.Remove("Structural");
- // Split the total amount of damage needed to kill the target by every damage type in the DamageSpecifier
- foreach (var (key, value) in appliedDamageSpecifier.DamageDict)
- {
- appliedDamageSpecifier.DamageDict[key] = Math.Ceiling((double) (value * lethalAmountOfDamage / totalDamage));
- }
- _damageableSystem.TryChangeDamage(target, appliedDamageSpecifier, true, origin: target);
- }
- /// <summary>
- /// Applies lethal damage in a single type, specified by a single damage type.
- /// </summary>
- public void ApplyLethalDamage(Entity<DamageableComponent> target, ProtoId<DamageTypePrototype>? damageType)
- {
- if (!TryComp<MobThresholdsComponent>(target, out var mobThresholds))
- return;
- // Mob thresholds are sorted from alive -> crit -> dead,
- // grabbing the last key will give us how much damage is needed to kill a target from zero
- // The exact lethal damage amount is adjusted based on their current damage taken
- var lethalAmountOfDamage = mobThresholds.Thresholds.Keys.Last() - target.Comp.TotalDamage;
- // We don't want structural damage for the same reasons listed above
- if (!_prototypeManager.TryIndex(damageType, out var damagePrototype) || damagePrototype.ID == "Structural")
- {
- Log.Error($"{nameof(SharedSuicideSystem)} could not find the damage type prototype associated with {damageType}. Falling back to Blunt");
- damagePrototype = _prototypeManager.Index<DamageTypePrototype>("Blunt");
- }
- var damage = new DamageSpecifier(damagePrototype, lethalAmountOfDamage);
- _damageableSystem.TryChangeDamage(target, damage, true, origin: target);
- }
- }
|