Update DamageableSystem to modern standards (#39417)

* Update DamageableSystem to modern standards

* DamageContainerId -> DamageContainerID with lint flag

* Replace strings with protoids

* Make CVar subscription declarations all consistently whitespaced

* ChangeDamage -> TryChangeDamage, cope with C# jank

* Revert event signature changes

* Restore a comment

* Re-add two queries

* Init the queries

* Use appearanceQuery in DamageChanged

* Use damageableQuery in TryChangeDamage

* Use damageableQuery in SetDamageModifierSetId

* Final cleanup, fix sandboxing

* Rectify ExplosionSystem:::ProcessEntity's call to TryChangeDamage

* Re-organize DamageableSystem

* first big fuck you breaking change.

* THATS A LOT OF DAMAGE!!!

* Fix test fails

* test fixes 2

* push it

---------

Co-authored-by: Princess Cheeseballs <66055347+Pronana@users.noreply.github.com>
This commit is contained in:
Hannah Giovanna Dawson
2025-10-27 19:53:04 +00:00
committed by GitHub
parent cf66dd7b35
commit cdbe92d37d
157 changed files with 1127 additions and 967 deletions

View File

@@ -1,12 +1,13 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading.Tasks;
using BenchmarkDotNet.Attributes;
using Content.IntegrationTests;
using Content.IntegrationTests.Pair;
using Content.Server.Destructible;
using Content.Shared.Damage;
using Content.Shared.Damage.Components;
using Content.Shared.Damage.Prototypes;
using Content.Shared.Damage.Systems;
using Content.Shared.FixedPoint;
using Content.Shared.Maps;
using Robust.Shared;

View File

@@ -1,5 +1,6 @@
using System.Linq;
using Content.Shared.Damage;
using Content.Shared.Damage.Components;
using Content.Shared.Damage.Prototypes;
using Content.Shared.FixedPoint;
using Robust.Client.GameObjects;

View File

@@ -1,28 +1,22 @@
using System.Linq;
using System.Numerics;
using Content.Client.Message;
using Content.Shared.Atmos;
using Content.Client.UserInterface.Controls;
using Content.Shared.Alert;
using Content.Shared.Damage;
using Content.Shared.Damage.Components;
using Content.Shared.Damage.Prototypes;
using Content.Shared.FixedPoint;
using Content.Shared.Humanoid;
using Content.Shared.Humanoid.Prototypes;
using Content.Shared.IdentityManagement;
using Content.Shared.Inventory;
using Content.Shared.MedicalScanner;
using Content.Shared.Mobs;
using Content.Shared.Mobs.Components;
using Content.Shared.Mobs.Systems;
using Content.Shared.Nutrition.Components;
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface.XAML;
using Robust.Client.GameObjects;
using Robust.Client.Graphics;
using Robust.Client.UserInterface.Controls;
using Robust.Client.ResourceManagement;
using Robust.Client.UserInterface;
using Robust.Shared.Prototypes;
using Robust.Shared.Utility;

View File

@@ -1,7 +1,7 @@
using System.Numerics;
using Content.Client.StatusIcon;
using Content.Client.UserInterface.Systems;
using Content.Shared.Damage;
using Content.Shared.Damage.Components;
using Content.Shared.FixedPoint;
using Content.Shared.Mobs;
using Content.Shared.Mobs.Components;

View File

@@ -1,5 +1,4 @@
using Content.Shared.Atmos.Rotting;
using Content.Shared.Damage;
using Content.Shared.Inventory.Events;
using Content.Shared.Mobs.Components;
using Content.Shared.Overlays;
@@ -7,6 +6,7 @@ using Content.Shared.StatusIcon;
using Content.Shared.StatusIcon.Components;
using Robust.Shared.Prototypes;
using System.Linq;
using Content.Shared.Damage.Components;
namespace Content.Client.Overlays;

View File

@@ -1,4 +1,4 @@
using Content.Shared.Damage;
using Content.Shared.Damage.Components;
using Content.Shared.FixedPoint;
using Content.Shared.Mobs;
using Content.Shared.Mobs.Components;

View File

@@ -1,6 +1,8 @@
using Content.Shared.Administration.Systems;
using Content.Shared.Damage;
using Content.Shared.Damage.Components;
using Content.Shared.Damage.Prototypes;
using Content.Shared.Damage.Systems;
using Content.Shared.FixedPoint;
using Content.Shared.Mobs.Components;
using Content.Shared.Mobs.Systems;

View File

@@ -1,6 +1,8 @@
using System.Linq;
using Content.Shared.Damage;
using Content.Shared.Damage.Components;
using Content.Shared.Damage.Prototypes;
using Content.Shared.Damage.Systems;
using Content.Shared.Execution;
using Content.Shared.FixedPoint;
using Content.Shared.Ghost;
@@ -280,7 +282,7 @@ public sealed class SuicideCommandTests
await server.WaitAssertion(() =>
{
// Heal all damage first (possible low pressure damage taken)
damageableSystem.SetAllDamage(player, damageableComp, 0);
damageableSystem.ClearAllDamage((player, damageableComp));
consoleHost.GetSessionShell(playerMan.Sessions.First()).ExecuteCommand("suicide");
var lethalDamageThreshold = mobThresholdsComp.Thresholds.Keys.Last();
@@ -355,7 +357,7 @@ public sealed class SuicideCommandTests
await server.WaitAssertion(() =>
{
// Heal all damage first (possible low pressure damage taken)
damageableSystem.SetAllDamage(player, damageableComp, 0);
damageableSystem.ClearAllDamage((player, damageableComp));
consoleHost.GetSessionShell(playerMan.Sessions.First()).ExecuteCommand("suicide");
var lethalDamageThreshold = mobThresholdsComp.Thresholds.Keys.Last();

View File

@@ -1,6 +1,8 @@
using Content.IntegrationTests.Tests.Interaction;
using Content.Shared.Damage;
using Content.Shared.Damage.Components;
using Content.Shared.Damage.Prototypes;
using Content.Shared.Damage.Systems;
using Content.Shared.FixedPoint;
using Robust.Shared.Prototypes;
@@ -21,7 +23,7 @@ public sealed class WindowRepair : InteractionTest
var damageType = Server.ProtoMan.Index(BluntDamageType);
var damage = new DamageSpecifier(damageType, FixedPoint2.New(10));
Assert.That(comp.Damage.GetTotal(), Is.EqualTo(FixedPoint2.Zero));
await Server.WaitPost(() => sys.TryChangeDamage(SEntMan.GetEntity(Target), damage, ignoreResistances: true));
await Server.WaitPost(() => sys.TryChangeDamage(SEntMan.GetEntity(Target).Value, damage, ignoreResistances: true));
await RunTicks(5);
Assert.That(comp.Damage.GetTotal(), Is.GreaterThan(FixedPoint2.Zero));

View File

@@ -1,5 +1,7 @@
using Content.Shared.Damage;
using Content.Shared.Damage.Components;
using Content.Shared.Damage.Prototypes;
using Content.Shared.Damage.Systems;
using Content.Shared.FixedPoint;
using Robust.Shared.GameObjects;
using Robust.Shared.Map;
@@ -232,10 +234,14 @@ namespace Content.IntegrationTests.Tests.Damageable
Assert.That(sDamageableComponent.TotalDamage, Is.EqualTo(FixedPoint2.Zero));
});
// Test SetAll function
sDamageableSystem.SetAllDamage(sDamageableEntity, sDamageableComponent, 10);
// Test SetAll and ClearAll function
sDamageableSystem.SetAllDamage((sDamageableEntity, sDamageableComponent), 10);
Assert.That(sDamageableComponent.TotalDamage, Is.EqualTo(FixedPoint2.New(10 * sDamageableComponent.Damage.DamageDict.Count)));
sDamageableSystem.SetAllDamage(sDamageableEntity, sDamageableComponent, 0);
sDamageableSystem.SetAllDamage((sDamageableEntity, sDamageableComponent), 0);
Assert.That(sDamageableComponent.TotalDamage, Is.EqualTo(FixedPoint2.Zero));
sDamageableSystem.SetAllDamage((sDamageableEntity, sDamageableComponent), 10);
Assert.That(sDamageableComponent.TotalDamage, Is.EqualTo(FixedPoint2.New(10 * sDamageableComponent.Damage.DamageDict.Count)));
sDamageableSystem.ClearAllDamage((sDamageableEntity, sDamageableComponent));
Assert.That(sDamageableComponent.TotalDamage, Is.EqualTo(FixedPoint2.Zero));
// Test 'wasted' healing

View File

@@ -1,5 +1,7 @@
using Content.Shared.Damage;
using Content.Shared.Damage.Components;
using Content.Shared.Damage.Prototypes;
using Content.Shared.Damage.Systems;
using Content.Shared.Destructible.Thresholds.Triggers;
using Content.Shared.FixedPoint;
using Robust.Shared.GameObjects;
@@ -130,7 +132,7 @@ namespace Content.IntegrationTests.Tests.Destructible
sTestThresholdListenerSystem.ThresholdsReached.Clear();
// Heal both classes of damage to 0
sDamageableSystem.SetAllDamage(sDestructibleEntity, sDamageableComponent, 0);
sDamageableSystem.ClearAllDamage((sDestructibleEntity, sDamageableComponent));
// No new thresholds reached, healing should not trigger it
Assert.That(sTestThresholdListenerSystem.ThresholdsReached, Is.Empty);
@@ -174,7 +176,7 @@ namespace Content.IntegrationTests.Tests.Destructible
threshold.TriggersOnce = true;
// Heal brute and burn back to 0
sDamageableSystem.SetAllDamage(sDestructibleEntity, sDamageableComponent, 0);
sDamageableSystem.ClearAllDamage((sDestructibleEntity, sDamageableComponent));
// No new thresholds reached from healing
Assert.That(sTestThresholdListenerSystem.ThresholdsReached, Is.Empty);

View File

@@ -1,5 +1,7 @@
using Content.Shared.Damage;
using Content.Shared.Damage.Components;
using Content.Shared.Damage.Prototypes;
using Content.Shared.Damage.Systems;
using Content.Shared.Destructible.Thresholds.Triggers;
using Robust.Shared.GameObjects;
using Robust.Shared.Prototypes;

View File

@@ -2,6 +2,7 @@ using System.Linq;
using Content.Server.Destructible.Thresholds.Behaviors;
using Content.Shared.Damage;
using Content.Shared.Damage.Prototypes;
using Content.Shared.Damage.Systems;
using Content.Shared.Destructible.Thresholds;
using Robust.Shared.GameObjects;
using Robust.Shared.Prototypes;

View File

@@ -3,7 +3,9 @@ using Content.Server.Destructible;
using Content.Server.Destructible.Thresholds;
using Content.Server.Destructible.Thresholds.Behaviors;
using Content.Shared.Damage;
using Content.Shared.Damage.Components;
using Content.Shared.Damage.Prototypes;
using Content.Shared.Damage.Systems;
using Content.Shared.FixedPoint;
using Robust.Shared.Audio.Systems;
using Content.Shared.Destructible;
@@ -124,7 +126,7 @@ namespace Content.IntegrationTests.Tests.Destructible
Assert.That(sTestThresholdListenerSystem.ThresholdsReached, Is.Empty);
// Set damage to 0
sDamageableSystem.SetAllDamage(sDestructibleEntity, sDamageableComponent, 0);
sDamageableSystem.ClearAllDamage((sDestructibleEntity, sDamageableComponent));
// Damage for 100, up to 100
sDamageableSystem.TryChangeDamage(sDestructibleEntity, bluntDamage * 10, true);
@@ -185,7 +187,7 @@ namespace Content.IntegrationTests.Tests.Destructible
sTestThresholdListenerSystem.ThresholdsReached.Clear();
// Heal all damage
sDamageableSystem.SetAllDamage(sDestructibleEntity, sDamageableComponent, 0);
sDamageableSystem.ClearAllDamage((sDestructibleEntity, sDamageableComponent));
// Damage up to 50
sDamageableSystem.TryChangeDamage(sDestructibleEntity, bluntDamage * 5, true);
@@ -247,7 +249,7 @@ namespace Content.IntegrationTests.Tests.Destructible
sTestThresholdListenerSystem.ThresholdsReached.Clear();
// Heal the entity completely
sDamageableSystem.SetAllDamage(sDestructibleEntity, sDamageableComponent, 0);
sDamageableSystem.ClearAllDamage((sDestructibleEntity, sDamageableComponent));
// Check that the entity has 0 damage
Assert.That(sDamageableComponent.TotalDamage, Is.EqualTo(FixedPoint2.Zero));

View File

@@ -10,7 +10,7 @@ using Content.Server.Roles;
using Content.Server.RoundEnd;
using Content.Server.Shuttles.Components;
using Content.Shared.CCVar;
using Content.Shared.Damage;
using Content.Shared.Damage.Components;
using Content.Shared.FixedPoint;
using Content.Shared.GameTicking;
using Content.Shared.Hands.Components;

View File

@@ -4,7 +4,9 @@ using Content.Server.Ghost.Roles;
using Content.Server.Ghost.Roles.Components;
using Content.Server.Mind;
using Content.Shared.Damage;
using Content.Shared.Damage.Components;
using Content.Shared.Damage.Prototypes;
using Content.Shared.Damage.Systems;
using Content.Shared.FixedPoint;
using Content.Shared.Mind;
using Content.Shared.Mind.Components;
@@ -147,7 +149,7 @@ public sealed partial class MindTests
var damageable = entMan.GetComponent<DamageableComponent>(entity);
var prototype = protoMan.Index(BluntDamageType);
damageableSystem.SetDamage(entity, damageable, new DamageSpecifier(prototype, FixedPoint2.New(401)));
damageableSystem.SetDamage((entity, damageable), new DamageSpecifier(prototype, FixedPoint2.New(401)));
Assert.That(mindSystem.GetMind(entity, mindContainerComp), Is.EqualTo(mindId));
});

View File

@@ -1,7 +1,6 @@
using Content.IntegrationTests.Tests.Movement;
using Content.Server.NPC.HTN;
using Content.Shared.Damage;
using Content.Shared.FixedPoint;
using Content.Shared.Damage.Components;
using Content.Shared.Item.ItemToggle;
using Content.Shared.Item.ItemToggle.Components;
using Content.Shared.Mobs;

View File

@@ -1,5 +1,6 @@
using Content.Server.Storage.EntitySystems;
using Content.Shared.Damage;
using Content.Shared.Damage.Systems;
using Robust.Shared.Containers;
using Robust.Shared.GameObjects;

View File

@@ -2,7 +2,9 @@ using System.Linq;
using Content.IntegrationTests.Tests.Interaction;
using Content.Server.VendingMachines;
using Content.Shared.Damage;
using Content.Shared.Damage.Components;
using Content.Shared.Damage.Prototypes;
using Content.Shared.Damage.Systems;
using Content.Shared.FixedPoint;
using Content.Shared.VendingMachines;
using Robust.Shared.Prototypes;
@@ -200,7 +202,7 @@ public sealed class VendingInteractionTest : InteractionTest
// Damage the vending machine to the point that it breaks
var damageType = ProtoMan.Index(TestDamageType);
var damage = new DamageSpecifier(damageType, FixedPoint2.New(100));
await Server.WaitPost(() => damageableSys.TryChangeDamage(SEntMan.GetEntity(Target), damage, ignoreResistances: true));
await Server.WaitPost(() => damageableSys.TryChangeDamage(SEntMan.GetEntity(Target).Value, damage, ignoreResistances: true));
await RunTicks(5);
Assert.That(damageableComp.Damage.GetTotal(), Is.GreaterThan(FixedPoint2.Zero), $"{VendingMachineProtoId} did not take damage.");
}

View File

@@ -5,6 +5,7 @@ using Content.Server.Wires;
using Content.Shared.Cargo.Prototypes;
using Content.Shared.Damage;
using Content.Shared.Damage.Prototypes;
using Content.Shared.Damage.Systems;
using Content.Shared.Prototypes;
using Content.Shared.Storage.Components;
using Content.Shared.VendingMachines;
@@ -296,14 +297,12 @@ namespace Content.IntegrationTests.Tests
restock = entityManager.SpawnEntity("TestRestockExplode", coordinates);
var damageSpec = new DamageSpecifier(prototypeManager.Index(TestDamageType), 100);
var damageResult = damageableSystem.TryChangeDamage(restock, damageSpec);
var damageResult = damageableSystem.ChangeDamage(restock, damageSpec);
#pragma warning disable NUnit2045
Assert.That(damageResult, Is.Not.Null,
"Received null damageResult when attempting to damage restock box.");
Assert.That(!damageResult.Empty, "Received empty damageResult when attempting to damage restock box.");
Assert.That((int) damageResult!.GetTotal(), Is.GreaterThan(0),
"Box damage result was not greater than 0.");
Assert.That((int) damageResult.GetTotal(), Is.GreaterThan(0), "Box damage result was not greater than 0.");
#pragma warning restore NUnit2045
});
await server.WaitRunTicks(15);

View File

@@ -1,5 +1,5 @@
using Content.IntegrationTests.Tests.Interaction;
using Content.Shared.Damage;
using Content.Shared.Damage.Components;
using Content.Shared.Weapons.Ranged.Components;
using Content.Shared.Weapons.Ranged.Systems;
using Content.Shared.Wieldable.Components;

View File

@@ -12,6 +12,7 @@ using Content.Shared.Chat;
using Content.Shared.Construction;
using Content.Shared.Containers.ItemSlots;
using Content.Shared.Damage;
using Content.Shared.Damage.Systems;
using Content.Shared.Database;
using Content.Shared.Roles;
using Content.Shared.StationRecords;

View File

@@ -1,6 +1,5 @@
using Content.Server.Administration.Components;
using Content.Server.Atmos.EntitySystems;
using Content.Server.Body.Components;
using Content.Server.Body.Systems;
using Content.Server.Electrocution;
using Content.Server.Explosion.EntitySystems;
@@ -24,7 +23,6 @@ using Content.Shared.Body.Part;
using Content.Shared.Clothing.Components;
using Content.Shared.Clumsy;
using Content.Shared.Cluwne;
using Content.Shared.Damage;
using Content.Shared.Damage.Systems;
using Content.Shared.Database;
using Content.Shared.Electrocution;
@@ -58,6 +56,7 @@ using Robust.Shared.Spawners;
using Robust.Shared.Utility;
using System.Numerics;
using System.Threading;
using Content.Shared.Damage.Components;
using Timer = Robust.Shared.Timing.Timer;
namespace Content.Server.Administration.Systems;

View File

@@ -251,7 +251,7 @@ public sealed partial class AtmosphereSystem
var maxPressureCapped = Math.Min(maxPressure, ent.Comp.MaxEffectivePressure);
var appliedDamage = ScaleDamage(ent, ent.Comp.BaseDamage, maxPressureCapped);
_damage.TryChangeDamage(ent, appliedDamage, ignoreResistances: true, interruptsDoAfters: false);
_damage.ChangeDamage(ent.Owner, appliedDamage, ignoreResistances: true, interruptsDoAfters: false);
SetIsTakingDamageState(ent, true);
}

View File

@@ -14,7 +14,7 @@ using Robust.Shared.Map;
using Robust.Shared.Physics.Systems;
using Robust.Shared.Prototypes;
using System.Linq;
using Content.Shared.Damage;
using Content.Shared.Damage.Systems;
using Robust.Shared.Threading;
namespace Content.Server.Atmos.EntitySystems;

View File

@@ -3,7 +3,8 @@ using Content.Server.Administration.Logs;
using Content.Server.Atmos.Components;
using Content.Shared.Alert;
using Content.Shared.Atmos;
using Content.Shared.Damage;
using Content.Shared.Damage.Components;
using Content.Shared.Damage.Systems;
using Content.Shared.Database;
using Content.Shared.FixedPoint;
using Content.Shared.Inventory;

View File

@@ -7,7 +7,7 @@ using Content.Shared.ActionBlocker;
using Content.Shared.Alert;
using Content.Shared.Atmos;
using Content.Shared.Atmos.Components;
using Content.Shared.Damage;
using Content.Shared.Damage.Systems;
using Content.Shared.Database;
using Content.Shared.IgnitionSource;
using Content.Shared.Interaction;

View File

@@ -2,7 +2,7 @@ using Content.Server.Atmos.EntitySystems;
using Content.Shared.Atmos;
using Content.Shared.Atmos.Rotting;
using Content.Shared.Body.Events;
using Content.Shared.Damage;
using Content.Shared.Damage.Systems;
using Content.Shared.Temperature.Components;
using Robust.Server.Containers;
using Robust.Shared.Physics.Components;

View File

@@ -2,7 +2,7 @@ using Content.Shared.Bed;
using Content.Shared.Bed.Components;
using Content.Shared.Bed.Sleep;
using Content.Shared.Buckle.Components;
using Content.Shared.Damage;
using Content.Shared.Damage.Systems;
using Content.Shared.Mobs.Systems;
namespace Content.Server.Bed

View File

@@ -4,7 +4,7 @@ using Content.Server.Popups;
using Content.Shared.ActionBlocker;
using Content.Shared.Actions;
using Content.Shared.Bible;
using Content.Shared.Damage;
using Content.Shared.Damage.Systems;
using Content.Shared.Ghost.Roles.Components;
using Content.Shared.IdentityManagement;
using Content.Shared.Interaction;
@@ -14,7 +14,6 @@ using Content.Shared.Mobs.Systems;
using Content.Shared.Popups;
using Content.Shared.Timing;
using Content.Shared.Verbs;
using Robust.Shared.Audio;
using Robust.Shared.Audio.Systems;
using Robust.Shared.Player;
using Robust.Shared.Random;
@@ -133,9 +132,7 @@ namespace Content.Server.Bible
}
}
var damage = _damageableSystem.TryChangeDamage(args.Target.Value, component.Damage, true, origin: uid);
if (damage == null || damage.Empty)
if (_damageableSystem.TryChangeDamage(args.Target.Value, component.Damage, true, origin: uid))
{
var othersMessage = Loc.GetString(component.LocPrefix + "-heal-success-none-others", ("user", Identity.Entity(args.User, EntityManager)), ("target", Identity.Entity(args.Target.Value, EntityManager)), ("bible", uid));
_popupSystem.PopupEntity(othersMessage, args.User, Filter.PvsExcept(args.User), true, PopupType.Medium);

View File

@@ -12,7 +12,7 @@ using Content.Shared.Chat;
using Content.Shared.Chemistry.Components;
using Content.Shared.Chemistry.EntitySystems;
using Content.Shared.Chemistry.Reagent;
using Content.Shared.Damage;
using Content.Shared.Damage.Systems;
using Content.Shared.Database;
using Content.Shared.EntityConditions;
using Content.Shared.EntityConditions.Conditions.Body;
@@ -367,7 +367,7 @@ public sealed class RespiratorSystem : EntitySystem
if (ent.Comp.SuffocationCycles == 2)
_adminLogger.Add(LogType.Asphyxiation, $"{ToPrettyString(ent):entity} started suffocating");
_damageableSys.TryChangeDamage(ent, ent.Comp.Damage, interruptsDoAfters: false);
_damageableSys.ChangeDamage(ent.Owner, ent.Comp.Damage, interruptsDoAfters: false);
if (ent.Comp.SuffocationCycles < ent.Comp.SuffocationCycleThreshold)
return;
@@ -381,7 +381,7 @@ public sealed class RespiratorSystem : EntitySystem
if (ent.Comp.SuffocationCycles >= 2)
_adminLogger.Add(LogType.Asphyxiation, $"{ToPrettyString(ent):entity} stopped suffocating");
_damageableSys.TryChangeDamage(ent, ent.Comp.DamageRecovery);
_damageableSys.ChangeDamage(ent.Owner, ent.Comp.DamageRecovery);
var ev = new StopSuffocatingEvent();
RaiseLocalEvent(ent, ref ev);

View File

@@ -1,20 +1,16 @@
using Content.Server.Storage.Components;
using Content.Server.Storage.EntitySystems;
using Content.Shared.Access.Components;
using Content.Shared.CardboardBox;
using Content.Shared.CardboardBox.Components;
using Content.Shared.Damage;
using Content.Shared.Damage.Systems;
using Content.Shared.Interaction;
using Content.Shared.Movement.Components;
using Content.Shared.Movement.Systems;
using Content.Shared.Stealth;
using Content.Shared.Stealth.Components;
using Content.Shared.Storage.Components;
using Robust.Server.GameObjects;
using Robust.Shared.Audio;
using Robust.Shared.Audio.Systems;
using Robust.Shared.Containers;
using Robust.Shared.Player;
using Robust.Shared.Timing;
namespace Content.Server.CardboardBox;
@@ -109,10 +105,10 @@ public sealed class CardboardBoxSystem : SharedCardboardBoxSystem
//Relay damage to the mover
private void OnDamage(EntityUid uid, CardboardBoxComponent component, DamageChangedEvent args)
{
if (args.DamageDelta != null && args.DamageIncreased)
{
_damageable.TryChangeDamage(component.Mover, args.DamageDelta, origin: args.Origin);
}
if (args.DamageDelta == null || !args.DamageIncreased || component.Mover is not { } mover)
return;
_damageable.ChangeDamage(mover, args.DamageDelta, origin: args.Origin);
}
private void OnEntInserted(EntityUid uid, CardboardBoxComponent component, EntInsertedIntoContainerMessage args)

View File

@@ -2,7 +2,7 @@ using Content.Server.Ghost;
using Content.Server.Hands.Systems;
using Content.Shared.Administration.Logs;
using Content.Shared.Chat;
using Content.Shared.Damage;
using Content.Shared.Damage.Components;
using Content.Shared.Database;
using Content.Shared.IdentityManagement;
using Content.Shared.Interaction.Events;

View File

@@ -1,3 +1,5 @@
using Content.Shared.Damage.Systems;
namespace Content.Server.Chat.Systems;
using Content.Shared.Chat;

View File

@@ -12,7 +12,7 @@ using Content.Shared.CCVar;
using Content.Shared.Chemistry.Components;
using Content.Shared.Cloning;
using Content.Shared.Chat;
using Content.Shared.Damage;
using Content.Shared.Damage.Components;
using Content.Shared.DeviceLinking.Events;
using Content.Shared.Emag.Components;
using Content.Shared.Emag.Systems;

View File

@@ -8,7 +8,7 @@ using Content.Shared.Chat;
using Content.Shared.Chat.Prototypes;
using Content.Shared.Clumsy;
using Content.Shared.Cluwne;
using Content.Shared.Damage;
using Content.Shared.Damage.Systems;
using Content.Shared.Mobs;
using Content.Shared.NameModifier.EntitySystems;
using Content.Shared.Popups;

View File

@@ -1,13 +1,8 @@
using Content.Server.Destructible;
using Content.Shared.Construction;
using Content.Shared.Damage;
using Content.Shared.Damage.Components;
using Content.Shared.Examine;
using Content.Shared.FixedPoint;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Content.Server.Construction.Conditions;

View File

@@ -4,7 +4,7 @@ using Content.Server.Administration;
using Content.Shared.Administration;
using Content.Shared.Damage;
using Content.Shared.Damage.Prototypes;
using Content.Shared.FixedPoint;
using Content.Shared.Damage.Systems;
using Robust.Shared.Console;
using Robust.Shared.Prototypes;

View File

@@ -2,6 +2,7 @@ using Content.Shared.Bed.Sleep;
using Content.Shared.Damage;
using Content.Shared.Damage.Events;
using Content.Shared.Damage.ForceSay;
using Content.Shared.Damage.Systems;
using Content.Shared.FixedPoint;
using Content.Shared.Mobs;
using Content.Shared.Mobs.Systems;

View File

@@ -1,8 +1,7 @@
using Content.Server.Damage.Components;
using Content.Shared.Damage;
using Robust.Shared.Player;
using Content.Shared.Weapons.Melee.Events;
using System.Linq;
using Content.Shared.Damage.Systems;
namespace Content.Server.Damage.Systems;

View File

@@ -9,7 +9,7 @@ namespace Content.Server.Damage.Systems
/// </summary>
public sealed class DamageOnLandSystem : EntitySystem
{
[Dependency] private readonly DamageableSystem _damageableSystem = default!;
[Dependency] private readonly Shared.Damage.Systems.DamageableSystem _damageableSystem = default!;
public override void Initialize()
{

View File

@@ -11,7 +11,7 @@ namespace Content.Server.Damage.Systems
{
public sealed class DamageOnToolInteractSystem : EntitySystem
{
[Dependency] private readonly DamageableSystem _damageableSystem = default!;
[Dependency] private readonly Shared.Damage.Systems.DamageableSystem _damageableSystem = default!;
[Dependency] private readonly IAdminLogManager _adminLogger = default!;
[Dependency] private readonly SharedToolSystem _toolSystem = default!;
@@ -35,22 +35,22 @@ namespace Content.Server.Damage.Systems
&& itemToggle.Activated
&& !welder.TankSafe)
{
var dmg = _damageableSystem.TryChangeDamage(args.Target, weldingDamage, origin: args.User);
if (dmg != null)
if (_damageableSystem.TryChangeDamage(args.Target, weldingDamage, out var dmg, origin: args.User))
{
_adminLogger.Add(LogType.Damaged,
$"{ToPrettyString(args.User):user} used {ToPrettyString(args.Used):used} as a welder to deal {dmg.GetTotal():damage} damage to {ToPrettyString(args.Target):target}");
}
args.Handled = true;
}
else if (component.DefaultDamage is {} damage
&& _toolSystem.HasQuality(args.Used, component.Tools))
{
var dmg = _damageableSystem.TryChangeDamage(args.Target, damage, origin: args.User);
if (dmg != null)
if (_damageableSystem.TryChangeDamage(args.Target, damage, out var dmg, origin: args.User))
{
_adminLogger.Add(LogType.Damaged,
$"{ToPrettyString(args.User):user} used {ToPrettyString(args.Used):used} as a tool to deal {dmg.GetTotal():damage} damage to {ToPrettyString(args.Target):target}");
}
args.Handled = true;
}

View File

@@ -17,7 +17,7 @@ public sealed class DamageOtherOnHitSystem : SharedDamageOtherOnHitSystem
{
[Dependency] private readonly IAdminLogManager _adminLogger = default!;
[Dependency] private readonly GunSystem _guns = default!;
[Dependency] private readonly DamageableSystem _damageable = default!;
[Dependency] private readonly Shared.Damage.Systems.DamageableSystem _damageable = default!;
[Dependency] private readonly SharedCameraRecoilSystem _sharedCameraRecoil = default!;
[Dependency] private readonly SharedColorFlashEffectSystem _color = default!;
@@ -33,13 +33,13 @@ public sealed class DamageOtherOnHitSystem : SharedDamageOtherOnHitSystem
if (TerminatingOrDeleted(args.Target))
return;
var dmg = _damageable.TryChangeDamage(args.Target, component.Damage * _damageable.UniversalThrownDamageModifier, component.IgnoreResistances, origin: args.Component.Thrower);
var dmg = _damageable.ChangeDamage(args.Target, component.Damage * _damageable.UniversalThrownDamageModifier, component.IgnoreResistances, origin: args.Component.Thrower);
// Log damage only for mobs. Useful for when people throw spears at each other, but also avoids log-spam when explosions send glass shards flying.
if (dmg != null && HasComp<MobStateComponent>(args.Target))
if (HasComp<MobStateComponent>(args.Target))
_adminLogger.Add(LogType.ThrowHit, $"{ToPrettyString(args.Target):target} received {dmg.GetTotal():damage} damage from collision");
if (dmg is { Empty: false })
if (!dmg.Empty)
{
_color.RaiseEffect(Color.Red, [args.Target], Filter.Pvs(args.Target, entityManager: EntityManager));
}

View File

@@ -1,6 +1,7 @@
using Content.Server.Damage.Components;
using Content.Server.Popups;
using Content.Shared.Damage;
using Content.Shared.Damage.Systems;
using Robust.Shared.Player;
using Robust.Shared.Random;

View File

@@ -1,6 +1,6 @@
using Content.Server.Damage.Components;
using Content.Server.Destructible;
using Content.Shared.Damage;
using Content.Shared.Damage.Components;
using Content.Shared.Examine;
using Content.Shared.Rounding;
using Robust.Shared.Prototypes;

View File

@@ -7,7 +7,7 @@ public sealed partial class DestructibleSystem
/// <summary>
/// Tests all triggers in a DestructibleComponent to see how expensive it is to query them.
/// </summary>
public void TestAllTriggers(List<Entity<DamageableComponent, DestructibleComponent>> destructibles)
public void TestAllTriggers(List<Entity<Shared.Damage.Components.DamageableComponent, DestructibleComponent>> destructibles)
{
foreach (var (uid, damageable, destructible) in destructibles)
{
@@ -22,7 +22,7 @@ public sealed partial class DestructibleSystem
/// <summary>
/// Tests all behaviours in a DestructibleComponent to see how expensive it is to query them.
/// </summary>
public void TestAllBehaviors(List<Entity<DamageableComponent, DestructibleComponent>> destructibles)
public void TestAllBehaviors(List<Entity<Shared.Damage.Components.DamageableComponent, DestructibleComponent>> destructibles)
{
foreach (var (uid, damageable, destructible) in destructibles)
{

View File

@@ -11,6 +11,7 @@ using Content.Server.Fluids.EntitySystems;
using Content.Server.Stack;
using Content.Shared.Chemistry.EntitySystems;
using Content.Shared.Damage;
using Content.Shared.Damage.Systems;
using Content.Shared.Database;
using Content.Shared.Destructible;
using Content.Shared.Destructible.Thresholds.Triggers;
@@ -111,7 +112,7 @@ namespace Content.Server.Destructible
/// <summary>
/// Check if the given threshold should trigger.
/// </summary>
public bool Triggered(DamageThreshold threshold, Entity<DamageableComponent> owner)
public bool Triggered(DamageThreshold threshold, Entity<Shared.Damage.Components.DamageableComponent> owner)
{
if (threshold.Trigger == null)
return false;
@@ -135,7 +136,7 @@ namespace Content.Server.Destructible
/// <summary>
/// Check if the conditions for the given threshold are currently true.
/// </summary>
public bool Reached(DamageThreshold threshold, Entity<DamageableComponent> owner)
public bool Reached(DamageThreshold threshold, Entity<Shared.Damage.Components.DamageableComponent> owner)
{
if (threshold.Trigger == null)
return false;

View File

@@ -1,7 +1,7 @@
using Content.Server.Atmos.EntitySystems;
using Content.Server.Disposal.Tube;
using Content.Shared.Body.Components;
using Content.Shared.Damage;
using Content.Shared.Damage.Systems;
using Content.Shared.Disposal.Components;
using Content.Shared.Item;
using Content.Shared.Throwing;

View File

@@ -2,16 +2,14 @@ using Content.Server.Chat.Systems;
using Content.Server.NPC;
using Content.Server.NPC.Systems;
using Content.Server.Pinpointer;
using Content.Shared.Damage;
using Content.Shared.Dragon;
using Content.Shared.Examine;
using Content.Shared.Sprite;
using Robust.Shared.GameObjects;
using Robust.Shared.Map;
using Robust.Shared.Player;
using Robust.Shared.Serialization.Manager;
using System.Numerics;
using Robust.Shared.Audio;
using Content.Shared.Damage.Components;
using Robust.Shared.Audio.Systems;
using Robust.Shared.GameStates;
using Robust.Shared.Utility;

View File

@@ -1,14 +1,12 @@
using Content.Server.Administration.Logs;
using Content.Server.NodeContainer;
using Content.Server.NodeContainer.EntitySystems;
using Content.Server.NodeContainer.NodeGroups;
using Content.Server.NodeContainer.Nodes;
using Content.Server.Power.Components;
using Content.Server.Power.EntitySystems;
using Content.Server.Power.NodeGroups;
using Content.Server.Weapons.Melee;
using Content.Shared.Damage;
using Content.Shared.Damage.Prototypes;
using Content.Shared.Damage.Systems;
using Content.Shared.Database;
using Content.Shared.Electrocution;
using Content.Shared.IdentityManagement;
@@ -27,7 +25,6 @@ using Content.Shared.Tag;
using Content.Shared.Weapons.Melee.Events;
using Robust.Shared.Audio;
using Robust.Shared.Audio.Systems;
using Robust.Shared.Map;
using Robust.Shared.Physics.Events;
using Robust.Shared.Player;
using Robust.Shared.Prototypes;
@@ -402,19 +399,16 @@ public sealed class ElectrocutionSystem : SharedElectrocutionSystem
? _stun.TryUpdateParalyzeDuration(uid, time * ParalyzeTimeMultiplier)
: _stun.TryAddParalyzeDuration(uid, time * ParalyzeTimeMultiplier);
}
// TODO: Sparks here.
if (shockDamage is { } dmg)
{
var actual = _damageable.TryChangeDamage(uid,
new DamageSpecifier(_prototypeManager.Index(DamageType), dmg), origin: sourceUid);
if (actual != null)
if (_damageable.TryChangeDamage(uid, new DamageSpecifier(_prototypeManager.Index(DamageType), dmg), out var damage, origin: sourceUid))
{
_adminLogger.Add(LogType.Electrocution,
$"{ToPrettyString(uid):entity} received {actual.GetTotal():damage} powered electrocution damage{(sourceUid != null ? " from " + ToPrettyString(sourceUid.Value) : ""):source}");
$"{ToPrettyString(uid):entity} received {damage:damage} powered electrocution damage{(sourceUid != null ? " from " + ToPrettyString(sourceUid.Value) : ""):source}");
}
}

View File

@@ -1,9 +1,7 @@
using Content.Server.Atmos.Components;
using Content.Server.Destructible;
using Content.Shared.Atmos;
using Content.Shared.Damage;
using Content.Shared.Damage.Systems;
using Content.Shared.Explosion;
using Content.Shared.Explosion.EntitySystems;
using Content.Shared.FixedPoint;
using Robust.Shared.Map.Components;

View File

@@ -1,13 +1,10 @@
using System.Linq;
using System.Numerics;
using Content.Server.Atmos.EntitySystems;
using Content.Server.Explosion.Components;
using Content.Shared.CCVar;
using Content.Shared.Damage;
using Content.Shared.Damage.Components;
using Content.Shared.Database;
using Content.Shared.Explosion;
using Content.Shared.Explosion.Components;
using Content.Shared.Explosion.EntitySystems;
using Content.Shared.Maps;
using Content.Shared.Physics;
using Content.Shared.Projectiles;
@@ -17,7 +14,6 @@ using Robust.Shared.Map.Components;
using Robust.Shared.Physics;
using Robust.Shared.Physics.Components;
using Robust.Shared.Physics.Dynamics;
using Robust.Shared.Player;
using Robust.Shared.Random;
using Robust.Shared.Timing;
using Robust.Shared.Utility;
@@ -439,28 +435,25 @@ public sealed partial class ExplosionSystem
float? fireStacksOnIgnite,
EntityUid? cause)
{
if (originalDamage != null)
if (originalDamage is not null)
{
GetEntitiesToDamage(uid, originalDamage, id);
foreach (var (entity, damage) in _toDamage)
{
if (_actorQuery.HasComp(entity))
{
// Log damage to player entities only, cause this will create a massive amount of log spam otherwise.
if (cause != null)
{
_adminLogger.Add(LogType.ExplosionHit, LogImpact.Medium, $"Explosion of {ToPrettyString(cause):actor} dealt {damage.GetTotal()} damage to {ToPrettyString(entity):subject}");
}
else
{
_adminLogger.Add(LogType.ExplosionHit, LogImpact.Medium, $"Explosion at {epicenter:epicenter} dealt {damage.GetTotal()} damage to {ToPrettyString(entity):subject}");
}
}
if (!_damageableQuery.TryComp(entity, out var damageable))
continue;
// TODO EXPLOSIONS turn explosions into entities, and pass the the entity in as the damage origin.
_damageableSystem.TryChangeDamage(entity, damage, ignoreResistances: true, ignoreGlobalModifiers: true);
_damageableSystem.TryChangeDamage((entity, damageable), damage, ignoreResistances: true, ignoreGlobalModifiers: true);
if (_actorQuery.HasComp(entity))
{
// Log damage to player entities only; this will create a massive amount of log spam otherwise.
if (cause is not null)
_adminLogger.Add(LogType.ExplosionHit, LogImpact.Medium, $"Explosion of {ToPrettyString(cause):actor} dealt {damage.GetTotal()} damage to {ToPrettyString(entity):subject}");
else
_adminLogger.Add(LogType.ExplosionHit, LogImpact.Medium, $"Explosion at {epicenter:epicenter} dealt {damage.GetTotal()} damage to {ToPrettyString(entity):subject}");
}
}
}
@@ -666,7 +659,7 @@ sealed class Explosion
private readonly IEntityManager _entMan;
private readonly ExplosionSystem _system;
private readonly SharedMapSystem _mapSystem;
private readonly DamageableSystem _damageable;
private readonly Shared.Damage.Systems.DamageableSystem _damageable;
public readonly EntityUid VisualEnt;
@@ -690,7 +683,7 @@ sealed class Explosion
EntityUid visualEnt,
EntityUid? cause,
SharedMapSystem mapSystem,
DamageableSystem damageable)
Shared.Damage.Systems.DamageableSystem damageable)
{
VisualEnt = visualEnt;
Cause = cause;

View File

@@ -9,7 +9,8 @@ using Content.Server.NPC.Pathfinding;
using Content.Shared.Atmos.Components;
using Content.Shared.Camera;
using Content.Shared.CCVar;
using Content.Shared.Damage;
using Content.Shared.Damage.Components;
using Content.Shared.Damage.Systems;
using Content.Shared.Database;
using Content.Shared.Explosion;
using Content.Shared.Explosion.Components;

View File

@@ -3,13 +3,14 @@ using System.Numerics;
using Content.Server.Administration.Logs;
using Content.Server.Chat.Managers;
using Content.Server.GameTicking;
using Content.Server.Ghost.Components;
using Content.Server.Mind;
using Content.Server.Roles.Jobs;
using Content.Shared.Actions;
using Content.Shared.CCVar;
using Content.Shared.Damage;
using Content.Shared.Damage.Components;
using Content.Shared.Damage.Prototypes;
using Content.Shared.Damage.Systems;
using Content.Shared.Database;
using Content.Shared.Examine;
using Content.Shared.Eye;
@@ -586,7 +587,7 @@ namespace Content.Server.Ghost
DamageSpecifier damage = new(_prototypeManager.Index(AsphyxiationDamageType), dealtDamage);
_damageable.TryChangeDamage(playerEntity, damage, true);
_damageable.ChangeDamage(playerEntity.Value, damage, true);
}
}

View File

@@ -1,7 +1,7 @@
using Content.Server.Body.Systems;
using Content.Server.Popups;
using Content.Shared.Actions;
using Content.Shared.Damage;
using Content.Shared.Damage.Systems;
using Content.Shared.DoAfter;
using Content.Shared.Examine;
using Content.Shared.Guardian;
@@ -285,8 +285,8 @@ namespace Content.Server.Guardian
if (args.DamageDelta == null || component.Host == null || component.DamageShare == 0)
return;
_damageSystem.TryChangeDamage(
component.Host,
_damageSystem.ChangeDamage(
component.Host.Value,
args.DamageDelta * component.DamageShare,
origin: args.Origin,
ignoreResistances: true,

View File

@@ -1,10 +1,9 @@
using Content.Server.Body.Systems;
using Content.Server.Destructible;
using Content.Server.Examine;
using Content.Server.Polymorph.Components;
using Content.Server.Popups;
using Content.Shared.Body.Components;
using Content.Shared.Damage;
using Content.Shared.Damage.Systems;
using Content.Shared.Examine;
using Content.Shared.Popups;
using Robust.Shared.Audio.Systems;

View File

@@ -1,5 +1,6 @@
using Content.Server.NPC.HTN;
using Content.Shared.Damage;
using Content.Shared.Damage.Systems;
using Content.Shared.FixedPoint;
using Content.Shared.Mobs;
using Content.Shared.Mobs.Systems;

View File

@@ -7,7 +7,6 @@ using Content.Server.Hands.Systems;
using Content.Server.Kitchen.Components;
using Content.Server.Power.Components;
using Content.Server.Power.EntitySystems;
using Content.Server.Temperature.Components;
using Content.Server.Temperature.Systems;
using Content.Shared.Body.Components;
using Content.Shared.Body.Part;
@@ -40,9 +39,8 @@ using Robust.Shared.Timing;
using Content.Shared.Stacks;
using Content.Server.Construction.Components;
using Content.Shared.Chat;
using Content.Shared.Damage;
using Content.Shared.Damage.Components;
using Content.Shared.Temperature.Components;
using Robust.Shared.Utility;
namespace Content.Server.Kitchen.EntitySystems
{

View File

@@ -2,6 +2,7 @@ using Content.Server.Explosion.EntitySystems;
using Content.Server.Lightning;
using Content.Server.Lightning.Components;
using Content.Shared.Damage;
using Content.Shared.Damage.Systems;
using Robust.Server.GameObjects;
namespace Content.Server.Tesla.EntitySystems;
@@ -26,7 +27,7 @@ public sealed class LightningTargetSystem : EntitySystem
{
DamageSpecifier damage = new();
damage.DamageDict.Add("Structural", uid.Comp.DamageFromLightning);
_damageable.TryChangeDamage(uid, damage, true);
_damageable.ChangeDamage(uid.Owner, damage, true);
if (uid.Comp.LightningExplode)
{

View File

@@ -4,7 +4,7 @@ using Content.Server.Body.Systems;
using Content.Server.Mech.Components;
using Content.Server.Power.EntitySystems;
using Content.Shared.ActionBlocker;
using Content.Shared.Damage;
using Content.Shared.Damage.Systems;
using Content.Shared.DoAfter;
using Content.Shared.FixedPoint;
using Content.Shared.Interaction;
@@ -265,7 +265,7 @@ public sealed partial class MechSystem : SharedMechSystem
component.PilotSlot.ContainedEntity != null)
{
var damage = args.DamageDelta * component.MechToPilotDamageMultiplier;
_damageable.TryChangeDamage(component.PilotSlot.ContainedEntity, damage);
_damageable.ChangeDamage(component.PilotSlot.ContainedEntity.Value, damage);
}
}

View File

@@ -8,7 +8,8 @@ using Content.Server.Popups;
using Content.Server.PowerCell;
using Content.Shared.Traits.Assorted;
using Content.Shared.Chat;
using Content.Shared.Damage;
using Content.Shared.Damage.Components;
using Content.Shared.Damage.Systems;
using Content.Shared.DoAfter;
using Content.Shared.Interaction;
using Content.Shared.Item.ItemToggle;

View File

@@ -2,7 +2,7 @@ using Content.Server.Medical.Components;
using Content.Server.PowerCell;
using Content.Shared.Body.Components;
using Content.Shared.Chemistry.EntitySystems;
using Content.Shared.Damage;
using Content.Shared.Damage.Components;
using Content.Shared.DoAfter;
using Content.Shared.IdentityManagement;
using Content.Shared.Interaction;

View File

@@ -1,6 +1,7 @@
using Content.Server.Administration.Logs;
using Content.Server.Destructible;
using Content.Shared.Damage;
using Content.Shared.Damage.Components;
using Content.Shared.Damage.Systems;
using Content.Shared.Database;
using Content.Shared.FixedPoint;
using Content.Shared.Mobs.Systems;

View File

@@ -3,7 +3,7 @@ using System.Threading.Tasks;
using Content.Shared.NPC.Components;
using Content.Server.NPC.Pathfinding;
using Content.Shared.Chemistry.Components.SolutionManager;
using Content.Shared.Damage;
using Content.Shared.Damage.Components;
using Content.Shared.Interaction;
using Content.Shared.Mobs.Components;
using Content.Shared.Silicons.Bots;

View File

@@ -1,6 +1,7 @@
using Content.Server.NPC.Components;
using Content.Shared.CombatMode;
using Content.Shared.Damage;
using Content.Shared.Damage.Systems;
using Content.Shared.Mobs.Components;
using Content.Shared.NPC.Components;
using Content.Shared.NPC.Systems;

View File

@@ -6,7 +6,6 @@ using Content.Server.NPC.Queries.Curves;
using Content.Server.NPC.Queries.Queries;
using Content.Server.Nutrition.Components;
using Content.Shared.Chemistry.EntitySystems;
using Content.Shared.Damage;
using Content.Shared.Examine;
using Content.Shared.Fluids.Components;
using Content.Shared.Inventory;
@@ -29,6 +28,7 @@ using Robust.Shared.Prototypes;
using Robust.Shared.Utility;
using Content.Shared.Atmos.Components;
using System.Linq;
using Content.Shared.Damage.Components;
using Content.Shared.Temperature.Components;
namespace Content.Server.NPC.Systems;

View File

@@ -1,6 +1,6 @@
using Content.Server.Ninja.Events;
using Content.Server.Power.EntitySystems;
using Content.Shared.Damage;
using Content.Shared.Damage.Systems;
using Content.Shared.Interaction;
using Content.Shared.Ninja.Components;
using Content.Shared.Ninja.Systems;
@@ -9,8 +9,6 @@ using Content.Shared.Stunnable;
using Content.Shared.Timing;
using Content.Shared.Whitelist;
using Robust.Shared.Audio.Systems;
using Robust.Shared.Timing;
using Robust.Shared.Prototypes;
namespace Content.Server.Ninja.Systems;
@@ -62,7 +60,7 @@ public sealed class StunProviderSystem : SharedStunProviderSystem
_audio.PlayPvs(comp.Sound, target);
_damageable.TryChangeDamage(target, comp.StunDamage, false, true, null, origin: uid);
_damageable.ChangeDamage(target, comp.StunDamage, origin: uid);
_stun.TryAddParalyzeDuration(target, comp.StunTime);
// short cooldown to prevent instant stunlocking

View File

@@ -4,7 +4,7 @@ using Content.Server.Nutrition.Components;
using Content.Server.Popups;
using Content.Shared.Body.Components;
using Content.Shared.Atmos;
using Content.Shared.Damage;
using Content.Shared.Damage.Systems;
using Content.Shared.DoAfter;
using Content.Shared.Emag.Systems;
using Content.Shared.IdentityManagement;

View File

@@ -4,7 +4,8 @@ using Content.Server.Inventory;
using Content.Server.Polymorph.Components;
using Content.Shared.Buckle;
using Content.Shared.Coordinates;
using Content.Shared.Damage;
using Content.Shared.Damage.Components;
using Content.Shared.Damage.Systems;
using Content.Shared.Destructible;
using Content.Shared.Hands.EntitySystems;
using Content.Shared.IdentityManagement;
@@ -228,7 +229,7 @@ public sealed partial class PolymorphSystem : EntitySystem
_mobThreshold.GetScaledDamage(uid, child, out var damage) &&
damage != null)
{
_damageable.SetDamage(child, damageParent, damage);
_damageable.SetDamage((child, damageParent), damage);
}
if (configuration.Inventory == PolymorphInventoryChange.Transfer)
@@ -323,7 +324,7 @@ public sealed partial class PolymorphSystem : EntitySystem
_mobThreshold.GetScaledDamage(uid, parent, out var damage) &&
damage != null)
{
_damageable.SetDamage(parent, damageParent, damage);
_damageable.SetDamage((parent, damageParent), damage);
}
if (component.Configuration.Inventory == PolymorphInventoryChange.Transfer)

View File

@@ -3,7 +3,8 @@ using Content.Server.Destructible;
using Content.Server.Effects;
using Content.Server.Weapons.Ranged.Systems;
using Content.Shared.Camera;
using Content.Shared.Damage;
using Content.Shared.Damage.Components;
using Content.Shared.Damage.Systems;
using Content.Shared.Database;
using Content.Shared.FixedPoint;
using Content.Shared.Projectiles;
@@ -54,64 +55,63 @@ public sealed class ProjectileSystem : SharedProjectileSystem
damageRequired -= damageableComponent.TotalDamage;
damageRequired = FixedPoint2.Max(damageRequired, FixedPoint2.Zero);
}
var modifiedDamage = _damageableSystem.TryChangeDamage(target, ev.Damage, component.IgnoreResistances, damageable: damageableComponent, origin: component.Shooter);
var deleted = Deleted(target);
if (modifiedDamage is not null && Exists(component.Shooter))
if (_damageableSystem.TryChangeDamage((target, damageableComponent), ev.Damage, out var damage, component.IgnoreResistances, origin: component.Shooter) && Exists(component.Shooter))
{
if (modifiedDamage.AnyPositive() && !deleted)
if (!deleted)
{
_color.RaiseEffect(Color.Red, new List<EntityUid> { target }, Filter.Pvs(target, entityManager: EntityManager));
}
_adminLogger.Add(LogType.BulletHit,
LogImpact.Medium,
$"Projectile {ToPrettyString(uid):projectile} shot by {ToPrettyString(component.Shooter!.Value):user} hit {otherName:target} and dealt {modifiedDamage.GetTotal():damage} damage");
}
$"Projectile {ToPrettyString(uid):projectile} shot by {ToPrettyString(component.Shooter!.Value):user} hit {otherName:target} and dealt {damage:damage} damage");
// If penetration is to be considered, we need to do some checks to see if the projectile should stop.
if (modifiedDamage is not null && component.PenetrationThreshold != 0)
{
// If a damage type is required, stop the bullet if the hit entity doesn't have that type.
if (component.PenetrationDamageTypeRequirement != null)
// If penetration is to be considered, we need to do some checks to see if the projectile should stop.
if (component.PenetrationThreshold != 0)
{
var stopPenetration = false;
foreach (var requiredDamageType in component.PenetrationDamageTypeRequirement)
// If a damage type is required, stop the bullet if the hit entity doesn't have that type.
if (component.PenetrationDamageTypeRequirement != null)
{
if (!modifiedDamage.DamageDict.Keys.Contains(requiredDamageType))
var stopPenetration = false;
foreach (var requiredDamageType in component.PenetrationDamageTypeRequirement)
{
stopPenetration = true;
break;
if (!damage.DamageDict.Keys.Contains(requiredDamageType))
{
stopPenetration = true;
break;
}
}
if (stopPenetration)
component.ProjectileSpent = true;
}
// If the object won't be destroyed, it "tanks" the penetration hit.
if (damage.GetTotal() < damageRequired)
{
component.ProjectileSpent = true;
}
if (!component.ProjectileSpent)
{
component.PenetrationAmount += damageRequired;
// The projectile has dealt enough damage to be spent.
if (component.PenetrationAmount >= component.PenetrationThreshold)
{
component.ProjectileSpent = true;
}
}
if (stopPenetration)
component.ProjectileSpent = true;
}
// If the object won't be destroyed, it "tanks" the penetration hit.
if (modifiedDamage.GetTotal() < damageRequired)
else
{
component.ProjectileSpent = true;
}
if (!component.ProjectileSpent)
{
component.PenetrationAmount += damageRequired;
// The projectile has dealt enough damage to be spent.
if (component.PenetrationAmount >= component.PenetrationThreshold)
{
component.ProjectileSpent = true;
}
}
}
else
{
component.ProjectileSpent = true;
}
if (!deleted)
{
_guns.PlayImpactSound(target, modifiedDamage, component.SoundHit, component.ForceSound);
_guns.PlayImpactSound(target, damage, component.SoundHit, component.ForceSound);
if (!args.OurBody.LinearVelocity.IsLengthZero())
_sharedCameraRecoil.KickCamera(target, args.OurBody.LinearVelocity.Normalized());

View File

@@ -213,7 +213,7 @@ public sealed partial class RevenantSystem
return;
DamageSpecifier dspec = new();
dspec.DamageDict.Add("Cold", damage.Value);
_damage.TryChangeDamage(args.Args.Target, dspec, true, origin: uid);
_damage.ChangeDamage(args.Args.Target.Value, dspec, true, origin: uid);
args.Handled = true;
}

View File

@@ -3,7 +3,7 @@ using Content.Server.Actions;
using Content.Server.GameTicking;
using Content.Server.Store.Systems;
using Content.Shared.Alert;
using Content.Shared.Damage;
using Content.Shared.Damage.Systems;
using Content.Shared.DoAfter;
using Content.Shared.Examine;
using Content.Shared.Eye;

View File

@@ -20,6 +20,7 @@ using Robust.Shared.Physics.Events;
using Robust.Shared.Prototypes;
using Robust.Shared.Random;
using System.Numerics;
using Content.Shared.Damage.Components;
namespace Content.Server.Shuttles.Systems;
@@ -372,7 +373,7 @@ public sealed partial class ShuttleSystem
damageSpec.DamageDict["Blunt"] = scaledDamage;
damageSpec.DamageDict["Structural"] = scaledDamage * _structuralDamage;
_damageSys.TryChangeDamage(localEnt, damageSpec, damageable: damageable);
_damageSys.ChangeDamage((localEnt, damageable), damageSpec);
}
// might've been destroyed
if (TerminatingOrDeleted(localEnt) || EntityManager.IsQueuedForDeletion(localEnt))

View File

@@ -8,7 +8,7 @@ using Content.Server.Shuttles.Events;
using Content.Server.Station.Systems;
using Content.Server.Stunnable;
using Content.Shared.Buckle.Components;
using Content.Shared.Damage;
using Content.Shared.Damage.Systems;
using Content.Shared.Light.Components;
using Content.Shared.Movement.Events;
using Content.Shared.Salvage;

View File

@@ -1,16 +1,14 @@
using System.Numerics;
using Content.Server.Audio;
using Content.Server.Power.Components;
using Content.Server.Power.EntitySystems;
using Content.Server.Shuttles.Components;
using Content.Shared.Damage;
using Content.Shared.Damage.Systems;
using Content.Shared.Examine;
using Content.Shared.Interaction;
using Content.Shared.Maps;
using Content.Shared.Physics;
using Content.Shared.Shuttles.Components;
using Content.Shared.Temperature;
using Robust.Shared.Map;
using Robust.Shared.Map.Components;
using Robust.Shared.Physics.Collision.Shapes;
using Robust.Shared.Physics.Components;

View File

@@ -1,6 +1,6 @@
using Content.Shared.Containers.ItemSlots;
using Content.Shared.DeviceNetwork;
using Content.Shared.Damage;
using Content.Shared.Damage.Components;
using Content.Shared.FixedPoint;
using Content.Shared.Mobs;
using Content.Shared.Mobs.Systems;

View File

@@ -12,7 +12,8 @@ using Content.Server.Station.Systems;
using Content.Shared.Alert;
using Content.Shared.Chat.Prototypes;
using Content.Shared.Containers.ItemSlots;
using Content.Shared.Damage;
using Content.Shared.Damage.Components;
using Content.Shared.Damage.Systems;
using Content.Shared.Destructible;
using Content.Shared.DeviceNetwork.Components;
using Content.Shared.DoAfter;
@@ -127,10 +128,7 @@ public sealed class StationAiSystem : SharedStationAiSystem
_battery.SetCharge(ent, battery.MaxCharge);
}
if (TryComp<DamageableComponent>(ent, out var damageable))
{
_damageable.SetAllDamage(ent, damageable, 0);
}
_damageable.ClearAllDamage(ent.Owner);
}
protected override void OnAiInsert(Entity<StationAiCoreComponent> ent, ref EntInsertedIntoContainerMessage args)

View File

@@ -2,7 +2,7 @@
using Content.Server.Destructible;
using Content.Server.PowerCell;
using Content.Shared.Speech.Components;
using Content.Shared.Damage;
using Content.Shared.Damage.Components;
using Content.Shared.FixedPoint;
using Content.Shared.Speech;
using Robust.Shared.Random;

View File

@@ -1,4 +1,5 @@
using Content.Shared.Damage;
using Content.Shared.Damage.Components;
using Content.Shared.Damage.Systems;
using Content.Shared.Spreader;
using Robust.Shared.Prototypes;
using Robust.Shared.Random;

View File

@@ -5,7 +5,8 @@ using Content.Server.Body.Components;
using Content.Server.Temperature.Components;
using Content.Shared.Alert;
using Content.Shared.Atmos;
using Content.Shared.Damage;
using Content.Shared.Damage.Components;
using Content.Shared.Damage.Systems;
using Content.Shared.Database;
using Content.Shared.Inventory;
using Content.Shared.Rejuvenate;

View File

@@ -5,6 +5,7 @@ using Content.Server.Power.Components;
using Content.Server.Vocalization.Systems;
using Content.Shared.Cargo;
using Content.Shared.Damage;
using Content.Shared.Damage.Systems;
using Content.Shared.Destructible;
using Content.Shared.Emp;
using Content.Shared.Power;

View File

@@ -1,4 +1,4 @@
using Content.Shared.Damage;
using Content.Shared.Damage.Components;
using Content.Shared.Weapons.Ranged.Components;
using Robust.Shared.Map;

View File

@@ -14,10 +14,9 @@ using Content.Server.NPC.Systems;
using Content.Server.StationEvents.Components;
using Content.Server.Speech.Components;
using Content.Shared.Body.Components;
using Content.Shared.Chat;
using Content.Shared.CombatMode;
using Content.Shared.CombatMode.Pacification;
using Content.Shared.Damage;
using Content.Shared.Damage.Components;
using Content.Shared.Hands.Components;
using Content.Shared.Hands.EntitySystems;
using Content.Shared.Humanoid;
@@ -248,8 +247,7 @@ public sealed partial class ZombieSystem
tempComp.ColdDamage.ClampMax(0);
//Heals the zombie from all the damage it took while human
if (TryComp<DamageableComponent>(target, out var damageablecomp))
_damageable.SetAllDamage(target, damageablecomp, 0);
_damageable.ClearAllDamage(target);
_mobState.ChangeMobState(target, MobState.Alive);
_faction.ClearFactions(target, dirty: false);

View File

@@ -1,4 +1,3 @@
using System.Linq;
using Content.Shared.NPC.Prototypes;
using Content.Server.Actions;
using Content.Server.Body.Systems;
@@ -11,7 +10,7 @@ using Content.Shared.Armor;
using Content.Shared.Bed.Sleep;
using Content.Shared.Cloning.Events;
using Content.Shared.Chat;
using Content.Shared.Damage;
using Content.Shared.Damage.Systems;
using Content.Shared.Humanoid;
using Content.Shared.Inventory;
using Content.Shared.Mind;
@@ -118,7 +117,7 @@ namespace Content.Server.Zombies
var curTime = _timing.CurTime;
// Hurt the living infected
var query = EntityQueryEnumerator<PendingZombieComponent, DamageableComponent, MobStateComponent>();
var query = EntityQueryEnumerator<PendingZombieComponent, Shared.Damage.Components.DamageableComponent, MobStateComponent>();
while (query.MoveNext(out var uid, out var comp, out var damage, out var mobState))
{
// Process only once per second
@@ -138,11 +137,11 @@ namespace Content.Server.Zombies
? comp.CritDamageMultiplier
: 1f;
_damageable.TryChangeDamage(uid, comp.Damage * multiplier, true, false, damage);
_damageable.ChangeDamage((uid, damage), comp.Damage * multiplier, true, false);
}
// Heal the zombified
var zombQuery = EntityQueryEnumerator<ZombieComponent, DamageableComponent, MobStateComponent>();
var zombQuery = EntityQueryEnumerator<ZombieComponent, Shared.Damage.Components.DamageableComponent, MobStateComponent>();
while (zombQuery.MoveNext(out var uid, out var comp, out var damage, out var mobState))
{
// Process only once per second
@@ -159,7 +158,7 @@ namespace Content.Server.Zombies
: 1f;
// Gradual healing for living zombies.
_damageable.TryChangeDamage(uid, comp.PassiveHealing * multiplier, true, false, damage);
_damageable.ChangeDamage((uid, damage), comp.PassiveHealing * multiplier, true, false);
}
}

View File

@@ -1,5 +1,6 @@
using Content.Shared.Clothing.Components;
using Content.Shared.Damage;
using Content.Shared.Damage.Systems;
using Content.Shared.Examine;
using Content.Shared.Inventory;
using Content.Shared.Silicons.Borgs;

View File

@@ -4,6 +4,7 @@ using Content.Shared.Buckle.Components;
using Content.Shared.Damage;
using Content.Shared.Damage.Events;
using Content.Shared.Damage.ForceSay;
using Content.Shared.Damage.Systems;
using Content.Shared.Emoting;
using Content.Shared.Examine;
using Content.Shared.Eye.Blinding.Systems;

View File

@@ -1,6 +1,6 @@
using Content.Shared.Damage;
using Content.Shared.Damage.Prototypes;
using Robust.Shared.Audio;
using Content.Shared.Damage.Components;
using Content.Shared.Damage.Systems;
using Robust.Shared.Audio.Systems;
using Robust.Shared.Containers;
@@ -42,31 +42,31 @@ public sealed partial class BlockingSystem
private void OnUserDamageModified(EntityUid uid, BlockingUserComponent component, DamageModifyEvent args)
{
if (TryComp<BlockingComponent>(component.BlockingItem, out var blocking))
if (component.BlockingItem is not { } item || !TryComp<BlockingComponent>(item, out var blocking))
return;
if (args.Damage.GetTotal() <= 0)
return;
// A shield should only block damage it can itself absorb. To determine that we need the Damageable component on it.
if (!TryComp<DamageableComponent>(item, out var dmgComp))
return;
var blockFraction = blocking.IsBlocking ? blocking.ActiveBlockFraction : blocking.PassiveBlockFraction;
blockFraction = Math.Clamp(blockFraction, 0, 1);
_damageable.TryChangeDamage((item, dmgComp), blockFraction * args.OriginalDamage);
var modify = new DamageModifierSet();
foreach (var key in dmgComp.Damage.DamageDict.Keys)
{
if (args.Damage.GetTotal() <= 0)
return;
modify.Coefficients.TryAdd(key, 1 - blockFraction);
}
// A shield should only block damage it can itself absorb. To determine that we need the Damageable component on it.
if (!TryComp<DamageableComponent>(component.BlockingItem, out var dmgComp))
return;
args.Damage = DamageSpecifier.ApplyModifierSet(args.Damage, modify);
var blockFraction = blocking.IsBlocking ? blocking.ActiveBlockFraction : blocking.PassiveBlockFraction;
blockFraction = Math.Clamp(blockFraction, 0, 1);
_damageable.TryChangeDamage(component.BlockingItem, blockFraction * args.OriginalDamage);
var modify = new DamageModifierSet();
foreach (var key in dmgComp.Damage.DamageDict.Keys)
{
modify.Coefficients.TryAdd(key, 1 - blockFraction);
}
args.Damage = DamageSpecifier.ApplyModifierSet(args.Damage, modify);
if (blocking.IsBlocking && !args.Damage.Equals(args.OriginalDamage))
{
_audio.PlayPvs(blocking.BlockSound, uid);
}
if (blocking.IsBlocking && !args.Damage.Equals(args.OriginalDamage))
{
_audio.PlayPvs(blocking.BlockSound, uid);
}
}

View File

@@ -6,8 +6,8 @@ using Content.Shared.Chemistry.EntitySystems;
using Content.Shared.Chemistry.Reaction;
using Content.Shared.Chemistry.Reagent;
using Content.Shared.Damage;
using Content.Shared.Damage.Systems;
using Content.Shared.EntityEffects.Effects.Solution;
using Content.Shared.EntityEffects.Effects.Transform;
using Content.Shared.FixedPoint;
using Content.Shared.Fluids;
using Content.Shared.Forensics.Components;
@@ -99,8 +99,7 @@ public abstract class SharedBloodstreamSystem : EntitySystem
// bloodloss damage is based on the base value, and modified by how low your blood level is.
var amt = bloodstream.BloodlossDamage / (0.1f + bloodPercentage);
_damageableSystem.TryChangeDamage(uid, amt,
ignoreResistances: false, interruptsDoAfters: false);
_damageableSystem.TryChangeDamage(uid, amt, ignoreResistances: false, interruptsDoAfters: false);
// Apply dizziness as a symptom of bloodloss.
// The effect is applied in a way that it will never be cleared without being healthy.

View File

@@ -181,7 +181,7 @@ public partial class SharedBodySystem
{
// TODO BODY SYSTEM KILL : remove this when wounding and required parts are implemented properly
var damage = new DamageSpecifier(Prototypes.Index(BloodlossDamageType), 300);
Damageable.TryChangeDamage(bodyEnt, damage);
Damageable.ChangeDamage(bodyEnt.Owner, damage);
}
}

View File

@@ -1,4 +1,4 @@
using Content.Shared.Damage;
using Content.Shared.Damage.Systems;
using Content.Shared.Movement.Systems;
using Content.Shared.Standing;
using Robust.Shared.Containers;

View File

@@ -4,7 +4,8 @@ using Content.Shared.Armor;
using Content.Shared.Atmos.Rotting;
using Content.Shared.Body.Components;
using Content.Shared.Changeling.Components;
using Content.Shared.Damage;
using Content.Shared.Damage.Components;
using Content.Shared.Damage.Systems;
using Content.Shared.Database;
using Content.Shared.DoAfter;
using Content.Shared.Humanoid;
@@ -92,7 +93,7 @@ public sealed class ChangelingDevourSystem : EntitySystem
if (damage.Damage.DamageDict.TryGetValue(damagePoints.Key, out var val) && val > comp.DevourConsumeDamageCap)
return;
}
_damageable.TryChangeDamage(target, comp.DamagePerTick, true, true, damage, user);
_damageable.ChangeDamage((target.Value, damage), comp.DamagePerTick, true, true, user);
}
/// <summary>

View File

@@ -1,8 +1,10 @@
using System.Linq;
using Content.Shared.Damage;
using Content.Shared.Damage.Components;
using Content.Shared.Damage.Prototypes;
using Content.Shared.Damage.Systems;
using Content.Shared.Mobs.Components;
using Robust.Shared.Prototypes;
using System.Linq;
namespace Content.Shared.Chat;
@@ -40,7 +42,7 @@ public sealed class SharedSuicideSystem : EntitySystem
appliedDamageSpecifier.DamageDict[key] = Math.Ceiling((double) (value * lethalAmountOfDamage / totalDamage));
}
_damageableSystem.TryChangeDamage(target, appliedDamageSpecifier, true, origin: target);
_damageableSystem.ChangeDamage(target.AsNullable(), appliedDamageSpecifier, true, origin: target);
}
/// <summary>
@@ -64,6 +66,6 @@ public sealed class SharedSuicideSystem : EntitySystem
}
var damage = new DamageSpecifier(damagePrototype, lethalAmountOfDamage);
_damageableSystem.TryChangeDamage(target, damage, true, origin: target);
_damageableSystem.ChangeDamage(target.AsNullable(), damage, true, origin: target);
}
}

View File

@@ -2,7 +2,7 @@ using Content.Shared.ActionBlocker;
using Content.Shared.Buckle.Components;
using Content.Shared.Climbing.Components;
using Content.Shared.Climbing.Events;
using Content.Shared.Damage;
using Content.Shared.Damage.Systems;
using Content.Shared.DoAfter;
using Content.Shared.DragDrop;
using Content.Shared.Hands.Components;

View File

@@ -1,5 +1,6 @@
using Content.Shared.Clothing.Components;
using Content.Shared.Damage;
using Content.Shared.Damage.Systems;
using Content.Shared.Examine;
using Content.Shared.Inventory;
using Content.Shared.Movement.Systems;

View File

@@ -2,7 +2,7 @@ using Content.Shared.CCVar;
using Content.Shared.Chemistry.Hypospray.Events;
using Content.Shared.Climbing.Components;
using Content.Shared.Climbing.Events;
using Content.Shared.Damage;
using Content.Shared.Damage.Systems;
using Content.Shared.IdentityManagement;
using Content.Shared.Medical;
using Content.Shared.Popups;
@@ -95,7 +95,7 @@ public sealed class ClumsySystem : EntitySystem
args.Cancelled = true; // fail to catch
if (ent.Comp.CatchingFailDamage != null)
_damageable.TryChangeDamage(ent, ent.Comp.CatchingFailDamage, origin: args.Item);
_damageable.ChangeDamage(ent.Owner, ent.Comp.CatchingFailDamage, origin: args.Item);
// Collisions don't work properly with PopupPredicted or PlayPredicted.
// So we make this server only.
@@ -127,7 +127,7 @@ public sealed class ClumsySystem : EntitySystem
return;
if (ent.Comp.GunShootFailDamage != null)
_damageable.TryChangeDamage(ent, ent.Comp.GunShootFailDamage, origin: ent);
_damageable.ChangeDamage(ent.Owner, ent.Comp.GunShootFailDamage, origin: ent);
_stun.TryUpdateParalyzeDuration(ent, ent.Comp.GunShootFailStunTime);
@@ -199,7 +199,7 @@ public sealed class ClumsySystem : EntitySystem
{
stunTime = bonkComp.BonkTime;
if (bonkComp.BonkDamage != null)
_damageable.TryChangeDamage(target, bonkComp.BonkDamage, true);
_damageable.ChangeDamage(target.Owner, bonkComp.BonkDamage, true);
}
_stun.TryUpdateParalyzeDuration(target, stunTime);

View File

@@ -1,3 +1,4 @@
using Content.Shared.Damage.Systems;
using Robust.Shared.GameStates;
namespace Content.Shared.Damage.Components;

View File

@@ -1,4 +1,5 @@
using Content.Shared.Damage.Prototypes;
using Content.Shared.Damage.Systems;
using Content.Shared.FixedPoint;
using Content.Shared.Mobs;
using Content.Shared.StatusIcon;
@@ -6,105 +7,100 @@ using Robust.Shared.GameStates;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;
namespace Content.Shared.Damage
namespace Content.Shared.Damage.Components;
/// <summary>
/// Component that allows entities to take damage.
/// </summary>
/// <remarks>
/// The supported damage types are specified using a <see cref="DamageContainerPrototype"/>s. DamageContainers
/// may also have resistances to certain damage types, defined via a <see cref="DamageModifierSetPrototype"/>.
/// </remarks>
[RegisterComponent]
[NetworkedComponent]
[Access(typeof(DamageableSystem), Other = AccessPermissions.ReadExecute)]
public sealed partial class DamageableComponent : Component
{
/// <summary>
/// Component that allows entities to take damage.
/// This <see cref="DamageContainerPrototype"/> specifies what damage types are supported by this component.
/// If null, all damage types will be supported.
/// </summary>
[DataField("damageContainer")]
// ReSharper disable once InconsistentNaming - This is wrong but fixing it is potentially annoying for downstreams.
public ProtoId<DamageContainerPrototype>? DamageContainerID;
/// <summary>
/// This <see cref="DamageModifierSetPrototype"/> will be applied to any damage that is dealt to this container,
/// unless the damage explicitly ignores resistances.
/// </summary>
/// <remarks>
/// The supported damage types are specified using a <see cref="DamageContainerPrototype"/>s. DamageContainers
/// may also have resistances to certain damage types, defined via a <see cref="DamageModifierSetPrototype"/>.
/// Though DamageModifierSets can be deserialized directly, we only want to use the prototype version here
/// to reduce duplication.
/// </remarks>
[RegisterComponent]
[NetworkedComponent]
[Access(typeof(DamageableSystem), Other = AccessPermissions.ReadExecute)]
public sealed partial class DamageableComponent : Component
[DataField("damageModifierSet")]
public ProtoId<DamageModifierSetPrototype>? DamageModifierSetId;
/// <summary>
/// All the damage information is stored in this <see cref="DamageSpecifier"/>.
/// </summary>
/// <remarks>
/// If this data-field is specified, this allows damageable components to be initialized with non-zero damage.
/// </remarks>
[DataField(readOnly: true)] //TODO FULL GAME SAVE
public DamageSpecifier Damage = new();
/// <summary>
/// Damage, indexed by <see cref="DamageGroupPrototype"/> ID keys.
/// </summary>
/// <remarks>
/// Groups which have no members that are supported by this component will not be present in this
/// dictionary.
/// </remarks>
[ViewVariables] public Dictionary<string, FixedPoint2> DamagePerGroup = new();
/// <summary>
/// The sum of all damages in the DamageableComponent.
/// </summary>
[ViewVariables]
public FixedPoint2 TotalDamage;
[DataField("radiationDamageTypes")]
// ReSharper disable once UseCollectionExpression - Cannot refactor this as it's a potential sandbox violation.
public List<ProtoId<DamageTypePrototype>> RadiationDamageTypeIDs = new() { "Radiation" };
/// <summary>
/// Group types that affect the pain overlay.
/// </summary>
/// TODO: Add support for adding damage types specifically rather than whole damage groups
[DataField]
// ReSharper disable once UseCollectionExpression - Cannot refactor this as it's a potential sandbox volation.
public List<ProtoId<DamageGroupPrototype>> PainDamageGroups = new() { "Brute", "Burn" };
[DataField]
public Dictionary<MobState, ProtoId<HealthIconPrototype>> HealthIcons = new()
{
/// <summary>
/// This <see cref="DamageContainerPrototype"/> specifies what damage types are supported by this component.
/// If null, all damage types will be supported.
/// </summary>
[DataField("damageContainer")]
public ProtoId<DamageContainerPrototype>? DamageContainerID;
{ MobState.Alive, "HealthIconFine" },
{ MobState.Critical, "HealthIconCritical" },
{ MobState.Dead, "HealthIconDead" },
};
/// <summary>
/// This <see cref="DamageModifierSetPrototype"/> will be applied to any damage that is dealt to this container,
/// unless the damage explicitly ignores resistances.
/// </summary>
/// <remarks>
/// Though DamageModifierSets can be deserialized directly, we only want to use the prototype version here
/// to reduce duplication.
/// </remarks>
[DataField("damageModifierSet")]
public ProtoId<DamageModifierSetPrototype>? DamageModifierSetId;
[DataField]
public ProtoId<HealthIconPrototype> RottingIcon = "HealthIconRotting";
/// <summary>
/// All the damage information is stored in this <see cref="DamageSpecifier"/>.
/// </summary>
/// <remarks>
/// If this data-field is specified, this allows damageable components to be initialized with non-zero damage.
/// </remarks>
[DataField(readOnly: true)] // TODO FULL GAME SAVE
public DamageSpecifier Damage = new();
/// <summary>
/// Damage, indexed by <see cref="DamageGroupPrototype"/> ID keys.
/// </summary>
/// <remarks>
/// Groups which have no members that are supported by this component will not be present in this
/// dictionary.
/// </remarks>
[ViewVariables] public Dictionary<string, FixedPoint2> DamagePerGroup = new();
/// <summary>
/// The sum of all damages in the DamageableComponent.
/// </summary>
[ViewVariables]
public FixedPoint2 TotalDamage;
[DataField("radiationDamageTypes")]
public List<ProtoId<DamageTypePrototype>> RadiationDamageTypeIDs = new() { "Radiation" };
/// <summary>
/// Group types that affect the pain overlay.
/// </summary>
/// TODO: Add support for adding damage types specifically rather than whole damage groups
[DataField]
public List<ProtoId<DamageGroupPrototype>> PainDamageGroups = new() { "Brute", "Burn" };
[DataField]
public Dictionary<MobState, ProtoId<HealthIconPrototype>> HealthIcons = new()
{
{ MobState.Alive, "HealthIconFine" },
{ MobState.Critical, "HealthIconCritical" },
{ MobState.Dead, "HealthIconDead" },
};
[DataField]
public ProtoId<HealthIconPrototype> RottingIcon = "HealthIconRotting";
[DataField]
public FixedPoint2? HealthBarThreshold;
}
[Serializable, NetSerializable]
public sealed class DamageableComponentState : ComponentState
{
public readonly Dictionary<string, FixedPoint2> DamageDict;
public readonly string? DamageContainerId;
public readonly string? ModifierSetId;
public readonly FixedPoint2? HealthBarThreshold;
public DamageableComponentState(
Dictionary<string, FixedPoint2> damageDict,
string? damageContainerId,
string? modifierSetId,
FixedPoint2? healthBarThreshold)
{
DamageDict = damageDict;
DamageContainerId = damageContainerId;
ModifierSetId = modifierSetId;
HealthBarThreshold = healthBarThreshold;
}
}
[DataField]
public FixedPoint2? HealthBarThreshold;
}
[Serializable, NetSerializable]
public sealed class DamageableComponentState(
Dictionary<string, FixedPoint2> damageDict,
ProtoId<DamageContainerPrototype>? damageContainerId,
ProtoId<DamageModifierSetPrototype>? modifierSetId,
FixedPoint2? healthBarThreshold)
: ComponentState
{
public readonly Dictionary<string, FixedPoint2> DamageDict = damageDict;
public readonly ProtoId<DamageContainerPrototype>? DamageContainerId = damageContainerId;
public readonly ProtoId<DamageModifierSetPrototype>? ModifierSetId = modifierSetId;
public readonly FixedPoint2? HealthBarThreshold = healthBarThreshold;
}

View File

@@ -1,3 +1,4 @@
using Content.Shared.Damage.Systems;
using Robust.Shared.GameStates;
namespace Content.Shared.Damage.Components;

View File

@@ -1,3 +1,4 @@
using Content.Shared.Damage.Systems;
using Robust.Shared.GameStates;
namespace Content.Shared.Damage.Components;

View File

@@ -1,3 +1,4 @@
using Content.Shared.Damage.Components;
using Content.Shared.Damage.Prototypes;
using Robust.Shared.Serialization;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Dictionary;

Some files were not shown because too many files have changed in this diff Show More