diff --git a/Content.Client/HealthAnalyzer/UI/HealthAnalyzerControl.xaml.cs b/Content.Client/HealthAnalyzer/UI/HealthAnalyzerControl.xaml.cs index d8ef38db9f1..6d264c2ed61 100644 --- a/Content.Client/HealthAnalyzer/UI/HealthAnalyzerControl.xaml.cs +++ b/Content.Client/HealthAnalyzer/UI/HealthAnalyzerControl.xaml.cs @@ -201,7 +201,7 @@ public sealed partial class HealthAnalyzerControl : BoxContainer damageable.DamagePerGroup.OrderByDescending(damage => damage.Value) .ToDictionary(x => x.Key, x => x.Value); - IReadOnlyDictionary damagePerType = damageable.Damage.DamageDict; + var damagePerType = damageable.Damage.DamageDict; DrawDiagnosticGroups(damageSortedGroups, damagePerType); @@ -240,7 +240,7 @@ public sealed partial class HealthAnalyzerControl : BoxContainer private void DrawDiagnosticGroups( Dictionary groups, - IReadOnlyDictionary damageDict) + IReadOnlyDictionary, FixedPoint2> damageDict) { GroupsContainer.RemoveAllChildren(); diff --git a/Content.IntegrationTests/Tests/Damageable/DamageSpecifierTest.cs b/Content.IntegrationTests/Tests/Damageable/DamageSpecifierTest.cs index bd5cac05dd1..522b53b5a9c 100644 --- a/Content.IntegrationTests/Tests/Damageable/DamageSpecifierTest.cs +++ b/Content.IntegrationTests/Tests/Damageable/DamageSpecifierTest.cs @@ -1,6 +1,8 @@ using System.Collections.Generic; using Content.Shared.Damage; +using Content.Shared.Damage.Prototypes; using Content.Shared.FixedPoint; +using Robust.Shared.Prototypes; namespace Content.IntegrationTests.Tests.Damageable; @@ -39,14 +41,14 @@ public sealed class DamageSpecifierTest Assert.That(difference, Is.EqualTo(output5)); } - private static readonly Dictionary Input1 = new() + private static readonly Dictionary, FixedPoint2> Input1 = new() { { "A", 1.5f }, { "B", 2 }, { "C", 3 } }; - private static readonly Dictionary Input2 = new() + private static readonly Dictionary, FixedPoint2> Input2 = new() { { "A", 1 }, { "B", 2 }, @@ -54,28 +56,28 @@ public sealed class DamageSpecifierTest { "D", 0.05f } }; - private static readonly Dictionary Output1 = new() + private static readonly Dictionary, FixedPoint2> Output1 = new() { { "A", -1.5f }, { "B", -2 }, { "C", -3 } }; - private static readonly Dictionary Output2 = new() + private static readonly Dictionary, FixedPoint2> Output2 = new() { { "A", 0.75f }, { "B", 1 }, { "C", 1.5 } }; - private static readonly Dictionary Output3 = new() + private static readonly Dictionary, FixedPoint2> Output3 = new() { { "A", 3f }, { "B", 4 }, { "C", 6 } }; - private static readonly Dictionary Output4 = new() + private static readonly Dictionary, FixedPoint2> Output4 = new() { { "A", 0.5f }, { "B", 0 }, @@ -83,7 +85,7 @@ public sealed class DamageSpecifierTest { "D", -0.05f } }; - private static readonly Dictionary Output5 = new() + private static readonly Dictionary, FixedPoint2> Output5 = new() { { "A", 0.25f }, { "B", 0 }, diff --git a/Content.IntegrationTests/Tests/Damageable/DamageableTest.cs b/Content.IntegrationTests/Tests/Damageable/DamageableTest.cs index 20b0877548d..11e7abd8a9c 100644 --- a/Content.IntegrationTests/Tests/Damageable/DamageableTest.cs +++ b/Content.IntegrationTests/Tests/Damageable/DamageableTest.cs @@ -148,17 +148,6 @@ namespace Content.IntegrationTests.Tests.Damageable { var uid = sDamageableEntity; - // Check that the correct types are supported. - Assert.Multiple(() => - { - Assert.That(sDamageableComponent.Damage.DamageDict.ContainsKey(type1.ID), Is.False); - Assert.That(sDamageableComponent.Damage.DamageDict.ContainsKey(type2a.ID), Is.True); - Assert.That(sDamageableComponent.Damage.DamageDict.ContainsKey(type2b.ID), Is.False); - Assert.That(sDamageableComponent.Damage.DamageDict.ContainsKey(type3a.ID), Is.True); - Assert.That(sDamageableComponent.Damage.DamageDict.ContainsKey(type3b.ID), Is.True); - Assert.That(sDamageableComponent.Damage.DamageDict.ContainsKey(type3c.ID), Is.True); - }); - // Check that damage is evenly distributed over a group if its a nice multiple var types = group3.DamageTypes; var damageToDeal = FixedPoint2.New(types.Count * 5); diff --git a/Content.Server/Administration/Logs/Converters/DamageSpecifierConverter.cs b/Content.Server/Administration/Logs/Converters/DamageSpecifierConverter.cs new file mode 100644 index 00000000000..b129307e748 --- /dev/null +++ b/Content.Server/Administration/Logs/Converters/DamageSpecifierConverter.cs @@ -0,0 +1,20 @@ +using System.Text.Json; +using Content.Shared.Damage; +using Robust.Shared.Map; +using Robust.Shared.Map.Components; + +namespace Content.Server.Administration.Logs.Converters; + +[AdminLogConverter] +public sealed class DamageSpecifierConverter : AdminLogConverter +{ + public override void Write(Utf8JsonWriter writer, DamageSpecifier value, JsonSerializerOptions options) + { + writer.WriteStartObject(); + foreach (var (damage, amount) in value.DamageDict) + { + writer.WriteNumber(damage.Id, amount.Double()); + } + writer.WriteEndObject(); + } +} diff --git a/Content.Shared/Atmos/Components/DeltaPressureComponent.cs b/Content.Shared/Atmos/Components/DeltaPressureComponent.cs index 064d67f606b..0336abaa987 100644 --- a/Content.Shared/Atmos/Components/DeltaPressureComponent.cs +++ b/Content.Shared/Atmos/Components/DeltaPressureComponent.cs @@ -67,7 +67,7 @@ public sealed partial class DeltaPressureComponent : Component [DataField] public DamageSpecifier BaseDamage = new() { - DamageDict = new Dictionary + DamageDict = new () { { "Structural", 10 }, }, diff --git a/Content.Shared/Changeling/Components/ChangelingDevourComponent.cs b/Content.Shared/Changeling/Components/ChangelingDevourComponent.cs index af1651f8dc2..3b907eb494e 100644 --- a/Content.Shared/Changeling/Components/ChangelingDevourComponent.cs +++ b/Content.Shared/Changeling/Components/ChangelingDevourComponent.cs @@ -99,7 +99,7 @@ public sealed partial class ChangelingDevourComponent : Component [DataField, AutoNetworkedField] public DamageSpecifier DamagePerTick = new() { - DamageDict = new Dictionary + DamageDict = new () { { "Slash", 10}, { "Piercing", 10 }, diff --git a/Content.Shared/Cluwne/CluwneComponent.cs b/Content.Shared/Cluwne/CluwneComponent.cs index 692a8ec4f93..77d14431f53 100644 --- a/Content.Shared/Cluwne/CluwneComponent.cs +++ b/Content.Shared/Cluwne/CluwneComponent.cs @@ -26,7 +26,7 @@ public sealed partial class CluwneComponent : Component { DamageDict = new() { - { "Genetic", 300.0 }, + { "Cellular", 300.0 }, }, }; diff --git a/Content.Shared/Damage/Components/DamageableComponent.cs b/Content.Shared/Damage/Components/DamageableComponent.cs index d65900e165c..b6c5ea18f51 100644 --- a/Content.Shared/Damage/Components/DamageableComponent.cs +++ b/Content.Shared/Damage/Components/DamageableComponent.cs @@ -17,7 +17,7 @@ namespace Content.Shared.Damage.Components; /// may also have resistances to certain damage types, defined via a . /// [RegisterComponent] -[NetworkedComponent] +[NetworkedComponent, AutoGenerateComponentState(true)] [Access(typeof(DamageableSystem), Other = AccessPermissions.ReadExecute)] public sealed partial class DamageableComponent : Component { @@ -25,7 +25,7 @@ public sealed partial class DamageableComponent : Component /// This specifies what damage types are supported by this component. /// If null, all damage types will be supported. /// - [DataField("damageContainer")] + [DataField("damageContainer"), AutoNetworkedField] // ReSharper disable once InconsistentNaming - This is wrong but fixing it is potentially annoying for downstreams. public ProtoId? DamageContainerID; @@ -37,7 +37,7 @@ public sealed partial class DamageableComponent : Component /// Though DamageModifierSets can be deserialized directly, we only want to use the prototype version here /// to reduce duplication. /// - [DataField("damageModifierSet")] + [DataField("damageModifierSet"), AutoNetworkedField] public ProtoId? DamageModifierSetId; /// @@ -46,7 +46,7 @@ public sealed partial class DamageableComponent : Component /// /// If this data-field is specified, this allows damageable components to be initialized with non-zero damage. /// - [DataField(readOnly: true)] //TODO FULL GAME SAVE + [DataField, AutoNetworkedField] public DamageSpecifier Damage = new(); /// @@ -87,20 +87,6 @@ public sealed partial class DamageableComponent : Component [DataField] public ProtoId RottingIcon = "HealthIconRotting"; - [DataField] + [DataField, AutoNetworkedField] public FixedPoint2? HealthBarThreshold; } - -[Serializable, NetSerializable] -public sealed class DamageableComponentState( - Dictionary damageDict, - ProtoId? damageContainerId, - ProtoId? modifierSetId, - FixedPoint2? healthBarThreshold) - : ComponentState -{ - public readonly Dictionary DamageDict = damageDict; - public readonly ProtoId? DamageContainerId = damageContainerId; - public readonly ProtoId? ModifierSetId = modifierSetId; - public readonly FixedPoint2? HealthBarThreshold = healthBarThreshold; -} diff --git a/Content.Shared/Damage/DamageSpecifier.cs b/Content.Shared/Damage/DamageSpecifier.cs index 6c11f88b1e8..4b084769829 100644 --- a/Content.Shared/Damage/DamageSpecifier.cs +++ b/Content.Shared/Damage/DamageSpecifier.cs @@ -3,11 +3,10 @@ using System.Text.Json.Serialization; using Content.Shared.Damage.Components; using Content.Shared.Damage.Prototypes; using Content.Shared.FixedPoint; -using JetBrains.Annotations; using Robust.Shared.Prototypes; -using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Dictionary; using Robust.Shared.Utility; using Robust.Shared.Serialization; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Generic; namespace Content.Shared.Damage { @@ -19,31 +18,13 @@ namespace Content.Shared.Damage /// functions to apply resistance sets and supports basic math operations to modify this dictionary. /// [DataDefinition, Serializable, NetSerializable] - public sealed partial class DamageSpecifier : IEquatable + public sealed partial class DamageSpecifier : IEquatable, IRobustCloneable { - // For the record I regret so many of the decisions i made when rewriting damageable - // Why is it just shitting out dictionaries left and right - // One day Arrays, stackalloc spans, and SIMD will save the day. - // TODO DAMAGEABLE REFACTOR - - // These exist solely so the wiki works. Please do not touch them or use them. - [JsonPropertyName("types")] - [DataField("types", customTypeSerializer: typeof(PrototypeIdDictionarySerializer))] - [UsedImplicitly] - private Dictionary? _damageTypeDictionary; - - [JsonPropertyName("groups")] - [DataField("groups", customTypeSerializer: typeof(PrototypeIdDictionarySerializer))] - [UsedImplicitly] - private Dictionary? _damageGroupDictionary; - /// /// Main DamageSpecifier dictionary. Most DamageSpecifier functions exist to somehow modifying this. /// - [JsonIgnore] - [ViewVariables(VVAccess.ReadWrite)] - [IncludeDataField(customTypeSerializer: typeof(DamageSpecifierDictionarySerializer), readOnly: true)] - public Dictionary DamageDict { get; set; } = new(); + [DataField("types")] + public Dictionary, FixedPoint2> DamageDict { get; set; } = new(); /// /// Returns a sum of the damage values. @@ -84,6 +65,11 @@ namespace Content.Shared.Damage [JsonIgnore] public bool Empty => DamageDict.Count == 0; + public DamageSpecifier Clone() + { + return new DamageSpecifier(this); + } + public override string ToString() { return "DamageSpecifier(" + string.Join("; ", DamageDict.Select(x => x.Key + ":" + x.Value)) + ")"; diff --git a/Content.Shared/Damage/DamageSpecifierDictionarySerializer.cs b/Content.Shared/Damage/DamageSpecifierDictionarySerializer.cs deleted file mode 100644 index 92f56571a62..00000000000 --- a/Content.Shared/Damage/DamageSpecifierDictionarySerializer.cs +++ /dev/null @@ -1,81 +0,0 @@ -using Content.Shared.Damage.Prototypes; -using Content.Shared.FixedPoint; -using Robust.Shared.Prototypes; -using Robust.Shared.Serialization; -using Robust.Shared.Serialization.Manager; -using Robust.Shared.Serialization.Markdown.Mapping; -using Robust.Shared.Serialization.Markdown.Validation; -using Robust.Shared.Serialization.Markdown.Value; -using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Dictionary; -using Robust.Shared.Serialization.TypeSerializers.Interfaces; - -namespace Content.Shared.Damage; - -//todo writing -public sealed class DamageSpecifierDictionarySerializer : ITypeReader, MappingDataNode> -{ - private ITypeValidator, MappingDataNode> _damageTypeSerializer = new PrototypeIdDictionarySerializer(); - private ITypeValidator, MappingDataNode> _damageGroupSerializer = new PrototypeIdDictionarySerializer(); - - public ValidationNode Validate(ISerializationManager serializationManager, MappingDataNode node, - IDependencyCollection dependencies, ISerializationContext? context = null) - { - var vals = new Dictionary(); - if (node.TryGet("types", out var typesNode)) - { - vals.Add(new ValidatedValueNode(new ValueDataNode("types")), _damageTypeSerializer.Validate(serializationManager, typesNode, dependencies, context)); - } - - if (node.TryGet("groups", out var groupsNode)) - { - vals.Add(new ValidatedValueNode(new ValueDataNode("groups")), _damageGroupSerializer.Validate(serializationManager, groupsNode, dependencies, context)); - } - - return new ValidatedMappingNode(vals); - } - - public Dictionary Read(ISerializationManager serializationManager, MappingDataNode node, IDependencyCollection dependencies, - SerializationHookContext hookCtx, ISerializationContext? context = null, ISerializationManager.InstantiationDelegate>? instanceProvider = null) - { - var dict = instanceProvider != null ? instanceProvider() : new(); - // Add all the damage types by just copying the type dictionary (if it is not null). - if (node.TryGet("types", out var typesNode)) - { - serializationManager.Read(typesNode, instanceProvider: () => dict, notNullableOverride: true); - } - - if (!node.TryGet("groups", out var groupsNode)) - return dict; - - // Then resolve damage groups and add them - var prototypeManager = dependencies.Resolve(); - foreach (var entry in serializationManager.Read>(groupsNode, notNullableOverride: true)) - { - if (!prototypeManager.TryIndex(entry.Key, out var group)) - { - // This can happen if deserialized before prototypes are loaded. - // i made this a warning bc it was failing tests -paul - dependencies.Resolve().RootSawmill.Error($"Unknown damage group given to DamageSpecifier: {entry.Key}"); - continue; - } - - // Simply distribute evenly (except for rounding). - // We do this by reducing remaining the # of types and damage every loop. - var remainingTypes = group.DamageTypes.Count; - var remainingDamage = entry.Value; - foreach (var damageType in group.DamageTypes) - { - var damage = remainingDamage / FixedPoint2.New(remainingTypes); - if (!dict.TryAdd(damageType, damage)) - { - // Key already exists, add values - dict[damageType] += damage; - } - remainingDamage -= damage; - remainingTypes -= 1; - } - } - - return dict; - } -} diff --git a/Content.Shared/Damage/Prototypes/DamageGroupPrototype.cs b/Content.Shared/Damage/Prototypes/DamageGroupPrototype.cs index facdcce0e87..c19f14ea19a 100644 --- a/Content.Shared/Damage/Prototypes/DamageGroupPrototype.cs +++ b/Content.Shared/Damage/Prototypes/DamageGroupPrototype.cs @@ -11,6 +11,7 @@ namespace Content.Shared.Damage.Prototypes /// to change/get/set damage in a . /// [Prototype(2)] + [Obsolete("Do not rely on DamageGroupPrototype for anything besides grouping logically similar damage in UIs")] public sealed partial class DamageGroupPrototype : IPrototype { [IdDataField] public string ID { get; private set; } = default!; diff --git a/Content.Shared/Damage/Systems/DamageableSystem.API.cs b/Content.Shared/Damage/Systems/DamageableSystem.API.cs index e08e742b411..ff56c1affcb 100644 --- a/Content.Shared/Damage/Systems/DamageableSystem.API.cs +++ b/Content.Shared/Damage/Systems/DamageableSystem.API.cs @@ -8,6 +8,15 @@ namespace Content.Shared.Damage.Systems; public sealed partial class DamageableSystem { + /// If the damage container can take the given damage type + private bool SupportsType(ProtoId? container, ProtoId type) + { + if (container is null) + return true; + + return _supportedTypesByContainer[container.Value].Contains(type); + } + /// /// Directly sets the damage in a damageable component. /// This method keeps the damage types supported by the DamageContainerPrototype in the component. @@ -25,30 +34,15 @@ public sealed partial class DamageableSystem foreach (var type in ent.Comp.Damage.DamageDict.Keys) { - if (damage.DamageDict.TryGetValue(type, out var value)) - ent.Comp.Damage.DamageDict[type] = value; - else - ent.Comp.Damage.DamageDict[type] = 0; + if (!damage.DamageDict.ContainsKey(type)) + ent.Comp.Damage.DamageDict.Remove(type); } - OnEntityDamageChanged((ent, ent.Comp)); - } - - /// - /// Directly sets the damage specifier of a damageable component. - /// This will overwrite the complete damage dict, meaning it will bulldoze the supported damage types. - /// - /// - /// This may break persistance as the supported types are reset in case the component is initialized again. - /// So this only makes sense if you also change the DamageContainerPrototype in the component at the same time. - /// Only use this method if you know what you are doing. - /// - public void SetDamageSpecifier(Entity ent, DamageSpecifier damage) - { - if (!_damageableQuery.Resolve(ent, ref ent.Comp, false)) - return; - - ent.Comp.Damage = damage; + foreach (var (type, amount) in damage.DamageDict) + { + if (SupportsType(ent.Comp.DamageContainerID, type)) + ent.Comp.Damage.DamageDict[type] = amount; + } OnEntityDamageChanged((ent, ent.Comp)); } @@ -167,10 +161,10 @@ public sealed partial class DamageableSystem var dict = ent.Comp.Damage.DamageDict; foreach (var (type, value) in damage.DamageDict) { - // CollectionsMarshal my beloved. - if (!dict.TryGetValue(type, out var oldValue)) + if (!SupportsType(ent.Comp.DamageContainerID, type)) continue; + var oldValue = dict.GetValueOrDefault(type); var newValue = FixedPoint2.Max(FixedPoint2.Zero, oldValue + value); if (newValue == oldValue) continue; diff --git a/Content.Shared/Damage/Systems/DamageableSystem.Events.cs b/Content.Shared/Damage/Systems/DamageableSystem.Events.cs index 32c67fd0c2c..78b00f4d56d 100644 --- a/Content.Shared/Damage/Systems/DamageableSystem.Events.cs +++ b/Content.Shared/Damage/Systems/DamageableSystem.Events.cs @@ -6,6 +6,7 @@ using Content.Shared.Inventory; using Content.Shared.Radiation.Events; using Content.Shared.Rejuvenate; using Robust.Shared.GameStates; +using Robust.Shared.Prototypes; namespace Content.Shared.Damage.Systems; @@ -13,11 +14,13 @@ public sealed partial class DamageableSystem { public override void Initialize() { + RebuildContainerCache(); + + SubscribeLocalEvent(OnPrototypesReloaded); SubscribeLocalEvent(DamageableInit); - SubscribeLocalEvent(DamageableHandleState); - SubscribeLocalEvent(DamageableGetState); SubscribeLocalEvent(OnIrradiated); SubscribeLocalEvent(OnRejuvenate); + SubscribeLocalEvent(OnAfterAutoHandleState); _appearanceQuery = GetEntityQuery(); _damageableQuery = GetEntityQuery(); @@ -119,41 +122,49 @@ public sealed partial class DamageableSystem ); } + private void OnPrototypesReloaded(PrototypesReloadedEventArgs ev) + { + if (!ev.WasModified() && !ev.WasModified()) + return; + + RebuildContainerCache(); + } + + private void RebuildContainerCache() + { + _supportedTypesByContainer.Clear(); + + foreach (var proto in _prototypeManager.EnumeratePrototypes()) + { + var set = new HashSet>(); + _supportedTypesByContainer[proto.ID] = set; + + foreach (var type in proto.SupportedTypes) + { + set.Add(type); + } + + foreach (var groupId in proto.SupportedGroups) + { + var group = _prototypeManager.Index(groupId); + foreach (var type in group.DamageTypes) + { + set.Add(type); + } + } + } + } + + private void OnAfterAutoHandleState(Entity ent, ref AfterAutoHandleStateEvent args) + { + OnEntityDamageChanged(ent); + } + /// /// Initialize a damageable component /// private void DamageableInit(Entity ent, ref ComponentInit _) { - if ( - ent.Comp.DamageContainerID is null || - !_prototypeManager.Resolve(ent.Comp.DamageContainerID, out var damageContainerPrototype) - ) - { - // No DamageContainerPrototype was given. So we will allow the container to support all damage types - foreach (var type in _prototypeManager.EnumeratePrototypes()) - { - ent.Comp.Damage.DamageDict.TryAdd(type.ID, FixedPoint2.Zero); - } - } - else - { - // Initialize damage dictionary, using the types and groups from the damage - // container prototype - foreach (var type in damageContainerPrototype.SupportedTypes) - { - ent.Comp.Damage.DamageDict.TryAdd(type, FixedPoint2.Zero); - } - - foreach (var groupId in damageContainerPrototype.SupportedGroups) - { - var group = _prototypeManager.Index(groupId); - foreach (var type in group.DamageTypes) - { - ent.Comp.Damage.DamageDict.TryAdd(type, FixedPoint2.Zero); - } - } - } - ent.Comp.Damage.GetDamagePerGroup(_prototypeManager, ent.Comp.DamagePerGroup); ent.Comp.TotalDamage = ent.Comp.Damage.GetTotal(); } @@ -179,28 +190,6 @@ public sealed partial class DamageableSystem ClearAllDamage(ent.AsNullable()); _mobThreshold.SetAllowRevives(ent, false); } - - private void DamageableHandleState(Entity ent, ref ComponentHandleState args) - { - if (args.Current is not DamageableComponentState state) - return; - - ent.Comp.DamageContainerID = state.DamageContainerId; - ent.Comp.DamageModifierSetId = state.ModifierSetId; - ent.Comp.HealthBarThreshold = state.HealthBarThreshold; - - // Has the damage actually changed? - DamageSpecifier newDamage = new() { DamageDict = new Dictionary(state.DamageDict) }; - var delta = newDamage - ent.Comp.Damage; - delta.TrimZeros(); - - if (delta.Empty) - return; - - ent.Comp.Damage = newDamage; - - OnEntityDamageChanged(ent, delta); - } } /// diff --git a/Content.Shared/Damage/Systems/DamageableSystem.cs b/Content.Shared/Damage/Systems/DamageableSystem.cs index bbb6a0266d4..8743ec37520 100644 --- a/Content.Shared/Damage/Systems/DamageableSystem.cs +++ b/Content.Shared/Damage/Systems/DamageableSystem.cs @@ -17,7 +17,6 @@ public sealed partial class DamageableSystem : EntitySystem { [Dependency] private readonly IPrototypeManager _prototypeManager = default!; [Dependency] private readonly SharedAppearanceSystem _appearance = default!; - [Dependency] private readonly INetManager _netMan = default!; [Dependency] private readonly MobThresholdSystem _mobThreshold = default!; [Dependency] private readonly IConfigurationManager _config = default!; [Dependency] private readonly SharedChemistryGuideDataSystem _chemistryGuideData = default!; @@ -38,6 +37,8 @@ public sealed partial class DamageableSystem : EntitySystem public float UniversalTopicalsHealModifier { get; private set; } = 1f; public float UniversalMobDamageModifier { get; private set; } = 1f; + private Dictionary, HashSet>> _supportedTypesByContainer = new(); + /// /// If the damage in a DamageableComponent was changed this function should be called. /// @@ -71,32 +72,6 @@ public sealed partial class DamageableSystem : EntitySystem RaiseLocalEvent(ent, new DamageChangedEvent(ent.Comp, damageDelta, interruptsDoAfters, origin)); } - private void DamageableGetState(Entity ent, ref ComponentGetState args) - { - if (_netMan.IsServer) - { - args.State = new DamageableComponentState( - ent.Comp.Damage.DamageDict, - ent.Comp.DamageContainerID, - ent.Comp.DamageModifierSetId, - ent.Comp.HealthBarThreshold - ); - // TODO BODY SYSTEM pass damage onto body system - // BOBBY WHEN? 😭 - // BOBBY SOON 🫡 - - return; - } - - // avoid mispredicting damage on newly spawned entities. - args.State = new DamageableComponentState( - ent.Comp.Damage.DamageDict.ShallowClone(), - ent.Comp.DamageContainerID, - ent.Comp.DamageModifierSetId, - ent.Comp.HealthBarThreshold - ); - } - /// /// Goes through an entity damage's and saves them inside a dictionary if the value is higher than 0 /// The dictionary is structured with a string for the name of the damage type, and a FixedPoint2 for the numeric damage value diff --git a/Content.Shared/Destructible/Triggers/DamageGroupTrigger.cs b/Content.Shared/Destructible/Triggers/DamageGroupTrigger.cs index c1add2e891f..11c78fbd1ee 100644 --- a/Content.Shared/Destructible/Triggers/DamageGroupTrigger.cs +++ b/Content.Shared/Destructible/Triggers/DamageGroupTrigger.cs @@ -28,6 +28,6 @@ public sealed partial class DamageGroupTrigger : IThresholdTrigger public bool Reached(Entity damageable, SharedDestructibleSystem system) { - return damageable.Comp.DamagePerGroup[DamageGroup] >= Damage; + return damageable.Comp.DamagePerGroup.GetValueOrDefault(DamageGroup) >= Damage; } } diff --git a/Content.Shared/EntityConditions/Conditions/DamageGroupEntityConditionSystem.cs b/Content.Shared/EntityConditions/Conditions/DamageGroupEntityConditionSystem.cs index 3691039189e..0cfa4dedca3 100644 --- a/Content.Shared/EntityConditions/Conditions/DamageGroupEntityConditionSystem.cs +++ b/Content.Shared/EntityConditions/Conditions/DamageGroupEntityConditionSystem.cs @@ -13,7 +13,7 @@ public sealed partial class DamageGroupEntityConditionSystem : EntityConditionSy { protected override void Condition(Entity entity, ref EntityConditionEvent args) { - var value = entity.Comp.DamagePerGroup[args.Condition.DamageGroup]; + var value = entity.Comp.DamagePerGroup.GetValueOrDefault(args.Condition.DamageGroup); args.Result = value >= args.Condition.Min && value <= args.Condition.Max; } } diff --git a/Content.Shared/Kitchen/Components/KitchenSpikeComponent.cs b/Content.Shared/Kitchen/Components/KitchenSpikeComponent.cs index b4fdc5ed3cc..56bda116a11 100644 --- a/Content.Shared/Kitchen/Components/KitchenSpikeComponent.cs +++ b/Content.Shared/Kitchen/Components/KitchenSpikeComponent.cs @@ -58,7 +58,7 @@ public sealed partial class KitchenSpikeComponent : Component [DataField, AutoNetworkedField] public DamageSpecifier SpikeDamage = new() { - DamageDict = new Dictionary + DamageDict = new() { { "Piercing", 10 }, }, @@ -70,7 +70,7 @@ public sealed partial class KitchenSpikeComponent : Component [DataField, AutoNetworkedField] public DamageSpecifier ButcherDamage = new() { - DamageDict = new Dictionary + DamageDict = new() { { "Slash", 20 }, }, @@ -82,7 +82,7 @@ public sealed partial class KitchenSpikeComponent : Component [DataField, AutoNetworkedField] public DamageSpecifier TimeDamage = new() { - DamageDict = new Dictionary + DamageDict = new() { { "Blunt", 1 }, // Mobs are only gibbed from blunt (at least for now). }, diff --git a/Resources/Prototypes/Body/Species/skeleton.yml b/Resources/Prototypes/Body/Species/skeleton.yml index ba96a047199..f5b21745a24 100644 --- a/Resources/Prototypes/Body/Species/skeleton.yml +++ b/Resources/Prototypes/Body/Species/skeleton.yml @@ -136,12 +136,11 @@ # even if it's a meme - I did research methods: [ Touch ] effects: # TODO: when magic is around - make a milk transformation to a skeleton monster - - !type:HealthChange - damage: - groups: # these groups are the only 3 possible ways to damage a skeleton. numerical values obviously up to discussion - Burn: -1 - Brute: -0.75 - Metaphysical: -2 # Gameplay: skeletons need some way to heal holy damage. Lore: milk is an unholy liquid that shuns the light of god. (/j) + - !type:EvenHealthChange + damage: # these groups are the only 3 possible ways to damage a skeleton. numerical values obviously up to discussion + Burn: -1 + Brute: -0.75 + Metaphysical: -2 # Gameplay: skeletons need some way to heal holy damage. Lore: milk is an unholy liquid that shuns the light of god. (/j) - !type:PopupMessage type: Local visualType: Large diff --git a/Resources/Prototypes/Body/Species/slime.yml b/Resources/Prototypes/Body/Species/slime.yml index b670c067b92..1d8e946844e 100644 --- a/Resources/Prototypes/Body/Species/slime.yml +++ b/Resources/Prototypes/Body/Species/slime.yml @@ -120,8 +120,9 @@ damage: types: Heat: -0.14 - groups: - Brute: -0.14 + Blunt: -0.05 + Piercing: -0.05 + Slash: -0.05 - type: DamageVisuals damageOverlayGroups: Brute: diff --git a/Resources/Prototypes/Body/Species/vox.yml b/Resources/Prototypes/Body/Species/vox.yml index a7d6b6ab872..d0f98bbaa6a 100644 --- a/Resources/Prototypes/Body/Species/vox.yml +++ b/Resources/Prototypes/Body/Species/vox.yml @@ -229,8 +229,9 @@ types: Heat: -0.07 Poison: -0.2 # needs to be less than the PendingZombieComponent does or they never become zombies by the disease. - groups: - Brute: -0.07 + Blunt: -0.02 + Piercing: -0.02 + Slash: -0.02 - type: DamageVisuals damageOverlayGroups: Brute: diff --git a/Resources/Prototypes/Body/species_base.yml b/Resources/Prototypes/Body/species_base.yml index a0943958495..cc51ffcc2b9 100644 --- a/Resources/Prototypes/Body/species_base.yml +++ b/Resources/Prototypes/Body/species_base.yml @@ -204,8 +204,9 @@ damage: types: Heat: -0.07 - groups: - Brute: -0.07 + Blunt: -0.05 + Piercing: -0.05 + Slash: -0.05 - type: Fingerprint - type: Blindable - type: Temperature diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml b/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml index b330bd6740b..3fc6d82b291 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml @@ -2552,8 +2552,8 @@ angle: 0 animation: WeaponArcBite damage: - groups: - Brute: 5 + types: + Piercing: 5 - type: Item size: Normal sprite: Mobs/Animals/grenadepenguin.rsi @@ -2724,9 +2724,12 @@ damage: types: Poison: -0.07 - groups: - Brute: -0.07 - Burn: -0.07 + Blunt: -0.03 + Slash: -0.03 + Piercing: -0.03 + Heat: -0.03 + Cold: -0.03 + Shock: -0.03 - type: entity parent: diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/miscellaneous.yml b/Resources/Prototypes/Entities/Mobs/NPCs/miscellaneous.yml index e49e9fe3220..45ff0ea7553 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/miscellaneous.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/miscellaneous.yml @@ -102,26 +102,23 @@ - reagents: [ Water ] methods: [ Touch ] effects: - - !type:HealthChange + - !type:EvenHealthChange damage: - groups: - Brute: -0.15 + Brute: -0.15 - reagents: [ Blood ] methods: [ Touch ] effects: - - !type:HealthChange + - !type:EvenHealthChange damage: - groups: - Brute: -0.25 - Burn: -0.25 + Brute: -0.25 + Burn: -0.25 - reagents: [ RobustHarvest ] methods: [ Touch ] effects: - - !type:HealthChange + - !type:EvenHealthChange damage: - groups: - Brute: -1 - Burn: -1 + Brute: -1 + Burn: -1 - reagents: [ WeedKiller, PlantBGone ] methods: [ Touch ] effects: @@ -202,8 +199,10 @@ - type: MeleeWeapon hidden: true damage: - groups: - Brute: 9 + types: + Blunt: 3 + Piercing: 3 + Slash: 3 animation: WeaponArcBite - type: Climbing - type: NameIdentifier diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/spacetick.yml b/Resources/Prototypes/Entities/Mobs/NPCs/spacetick.yml index 0529f57875f..ce2f234b874 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/spacetick.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/spacetick.yml @@ -77,8 +77,8 @@ angle: 0 animation: WeaponArcBite damage: - groups: - Brute: 2 + types: + Piercing: 2 - type: SolutionContainerManager solutions: melee: diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/xeno.yml b/Resources/Prototypes/Entities/Mobs/NPCs/xeno.yml index c09660fda26..ddfb4628a79 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/xeno.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/xeno.yml @@ -542,8 +542,8 @@ collection: AlienClaw animation: WeaponArcBite damage: - groups: - Brute: 5 + types: + Slash: 5 - type: DamageStateVisuals states: Alive: diff --git a/Resources/Prototypes/Entities/Mobs/Player/dragon.yml b/Resources/Prototypes/Entities/Mobs/Player/dragon.yml index ffa4ae28de3..729e6f24d78 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/dragon.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/dragon.yml @@ -234,8 +234,8 @@ amount: 1 - type: MeleeWeapon damage: - groups: - Brute: 12 + types: + Piercing: 12 - type: entity parent: BaseAction diff --git a/Resources/Prototypes/Entities/Mobs/base.yml b/Resources/Prototypes/Entities/Mobs/base.yml index b9cae7ec381..0c97c5d1b13 100644 --- a/Resources/Prototypes/Entities/Mobs/base.yml +++ b/Resources/Prototypes/Entities/Mobs/base.yml @@ -162,8 +162,8 @@ soundHit: collection: MetalThud damage: - groups: - Brute: 5 + types: + Blunt: 5 # Used for mobs that are affected by atmospherics, pressure, and heat - type: entity diff --git a/Resources/Prototypes/Entities/Objects/Consumable/Food/Baked/bread.yml b/Resources/Prototypes/Entities/Objects/Consumable/Food/Baked/bread.yml index f5ba8c0d344..b7a2c3988ef 100644 --- a/Resources/Prototypes/Entities/Objects/Consumable/Food/Baked/bread.yml +++ b/Resources/Prototypes/Entities/Objects/Consumable/Food/Baked/bread.yml @@ -999,8 +999,8 @@ path: /Audio/Animals/dog_bark1.ogg hidden: true damage: - groups: - Brute: 1 + types: + Blunt: 1 - type: entity parent: FoodBreadBase diff --git a/Resources/Prototypes/Entities/Objects/Consumable/Food/Baked/cake.yml b/Resources/Prototypes/Entities/Objects/Consumable/Food/Baked/cake.yml index d8819d7a922..2a53c206d75 100644 --- a/Resources/Prototypes/Entities/Objects/Consumable/Food/Baked/cake.yml +++ b/Resources/Prototypes/Entities/Objects/Consumable/Food/Baked/cake.yml @@ -1129,8 +1129,8 @@ path: /Audio/Animals/cat_hiss.ogg hidden: true damage: - groups: - Brute: 1 + types: + Blunt: 1 # Suppermatter # I can't figure out where to put this. It kind of acts like a cake I guess? diff --git a/Resources/Prototypes/Entities/Objects/Misc/books.yml b/Resources/Prototypes/Entities/Objects/Misc/books.yml index 4d51fc3ed12..12e7ee30c45 100644 --- a/Resources/Prototypes/Entities/Objects/Misc/books.yml +++ b/Resources/Prototypes/Entities/Objects/Misc/books.yml @@ -68,7 +68,7 @@ Blunt: 1 - type: DamageOtherOnHit damage: - types: + types: {} - type: entity id: BookSpaceEncyclopedia diff --git a/Resources/Prototypes/Entities/Objects/Shields/shields.yml b/Resources/Prototypes/Entities/Objects/Shields/shields.yml index 16607922dd8..4e7698ecca8 100644 --- a/Resources/Prototypes/Entities/Objects/Shields/shields.yml +++ b/Resources/Prototypes/Entities/Objects/Shields/shields.yml @@ -81,9 +81,10 @@ components: - type: Repairable # Negative values represent healing damage: - groups: - Brute: -60 # 20 of each Brute Type - 20% of a basic shield HP types: + Blunt: -20 + Slash: -20 + Piercing: -20 Heat: -20 fuelCost: 10 # 1/2 of a Welder for a full repair doAfterDelay: 5 diff --git a/Resources/Prototypes/Entities/Objects/Specific/Chapel/bibles.yml b/Resources/Prototypes/Entities/Objects/Specific/Chapel/bibles.yml index 47086dea3a0..a06730d89e3 100644 --- a/Resources/Prototypes/Entities/Objects/Specific/Chapel/bibles.yml +++ b/Resources/Prototypes/Entities/Objects/Specific/Chapel/bibles.yml @@ -8,13 +8,19 @@ delay: 10.0 - type: Bible damage: - groups: - Brute: -15 - Burn: -15 + types: + Blunt: -5 + Piercing: -5 + Slash: -5 + Heat: -5 + Cold: -5 + Shock: -5 damageOnFail: - groups: - Brute: 15 - Airloss: 15 + types: + Blunt: 5 + Piercing: 5 + Slash: 5 + Asphyxiation: 15 damageOnUntrainedUse: ## What a non-chaplain takes when attempting to heal someone types: Heat: 10 @@ -86,9 +92,11 @@ types: Caustic: 20 ## ~15 dps damageOnFail: - groups: - Brute: 15 - Airloss: 25 + types: + Blunt: 5 + Piercing: 5 + Slash: 5 + Asphyxiation: 25 damageOnUntrainedUse: types: Caustic: 50 diff --git a/Resources/Prototypes/Entities/Objects/Specific/Medical/healing.yml b/Resources/Prototypes/Entities/Objects/Specific/Medical/healing.yml index 1b6dd3c1750..7e59ca02757 100644 --- a/Resources/Prototypes/Entities/Objects/Specific/Medical/healing.yml +++ b/Resources/Prototypes/Entities/Objects/Specific/Medical/healing.yml @@ -133,8 +133,10 @@ - Biological - BiologicalMetaphysical # DeltaV damage: - groups: - Brute: -15 # 5 for each type in the group + types: + Blunt: -5 + Piercing: -5 + Slash: -5 healingBeginSound: path: "/Audio/Items/Medical/brutepack_begin.ogg" params: @@ -180,8 +182,10 @@ - Biological - BiologicalMetaphysical # DeltaV damage: - groups: - Brute: -30 # 10 for each type in the group + types: + Blunt: -10 + Piercing: -10 + Slash: -10 bloodlossModifier: -10 # a suture should stop ongoing bleeding healingBeginSound: path: "/Audio/Items/Medical/brutepack_begin.ogg" @@ -274,9 +278,8 @@ - Biological - BiologicalMetaphysical # DeltaV damage: - groups: - Brute: 5 # Tourniquets HURT! types: + Blunt: 5 # Tourniquets HURT Asphyxiation: 5 # Essentially Stopping all blood reaching a part of your body bloodlossModifier: -10 # Tourniquets stop bleeding delay: 0.5 @@ -375,10 +378,14 @@ damageContainers: - Biological damage: - groups: # these are all split across multiple types - Brute: -150 - Burn: -150 - Toxin: -150 + types: # these are all split across multiple types + Blunt: -50 + Piercing: -50 + Slash: -50 + Heat: -50 + Cold: -50 + Shock: -50 + Poison: -150 bloodlossModifier: -20 delay: 1 selfHealPenaltyMultiplier: 0 diff --git a/Resources/Prototypes/Entities/Objects/Specific/Medical/surgery.yml b/Resources/Prototypes/Entities/Objects/Specific/Medical/surgery.yml index 65a0e427c31..9762d858efc 100644 --- a/Resources/Prototypes/Entities/Objects/Specific/Medical/surgery.yml +++ b/Resources/Prototypes/Entities/Objects/Specific/Medical/surgery.yml @@ -241,8 +241,8 @@ - type: MeleeWeapon wideAnimationRotation: 90 # DeltaV: Added wideAnimationRotation damage: - groups: - Brute: 10 + types: + Slash: 10 soundHit: path: /Audio/Weapons/bladeslice.ogg - type: Tool diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Projectiles/magic.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Projectiles/magic.yml index d6fd7d829a5..65b024129b8 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Projectiles/magic.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Projectiles/magic.yml @@ -107,8 +107,7 @@ deleteOnCollide: false onlyCollideWhenShot: true damage: - types: - Brute: 0 + types: {} - type: Sprite noRot: true sprite: Structures/Storage/closet.rsi @@ -247,11 +246,18 @@ color: white - type: Projectile damage: - groups: # good enough. Maybe make it call the rejuvenate command later. - Brute: -900 - Burn: -900 - Airloss: -600 - Toxin: -600 + types: # good enough. Maybe make it call the rejuvenate command later. + Asphyxiation: -200 + Bloodloss: -200 + Blunt: -200 + Caustic: -200 + Cold: -200 + Heat: -200 + Piercing: -200 + Poison: -200 + Radiation: -200 + Shock: -200 + Slash: -200 ignoreResistances: true - type: entity diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Melee/mining.yml b/Resources/Prototypes/Entities/Objects/Weapons/Melee/mining.yml index cdff86910c1..b9f31a73ef2 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Melee/mining.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Melee/mining.yml @@ -18,14 +18,13 @@ params: volume: -3 damage: - groups: - Brute: 5 + types: + Piercing: 5 - type: Wieldable - type: IncreaseDamageOnWield damage: - groups: - Brute: 10 types: + Piercing: 10 Structural: 30 - type: Item size: Normal @@ -89,8 +88,6 @@ attackRate: 4 damage: types: - Piercing: 3 # DeltaV: 6 brute changed to 3 piercing - Slash: 3 # DeltaV: 6 brute changed to 3 slash Structural: 30 - type: entity @@ -137,8 +134,10 @@ delay: 0.9 - type: LeechOnMarker leech: - groups: - Brute: -10 + types: + Blunt: -2 + Slash: -2 + Piercing: -2 - type: Gun soundGunshot: /Audio/Weapons/plasma_cutter.ogg fireRate: 1 @@ -242,9 +241,10 @@ delay: 0.9 # DeltaV - Didn't match the firerate. This is just visuals. - type: LeechOnMarker leech: - groups: - Brute: -21 - - type: MeleeWeapon + types: + Blunt: -5 + Piercing: -5 + Slash: -5 - type: Tag tags: - Pickaxe diff --git a/Resources/Prototypes/NPCs/utility_queries.yml b/Resources/Prototypes/NPCs/utility_queries.yml index 49b085b29ab..bb2bb08cc42 100644 --- a/Resources/Prototypes/NPCs/utility_queries.yml +++ b/Resources/Prototypes/NPCs/utility_queries.yml @@ -174,7 +174,7 @@ # why does Flammable even have a required damage damage: types: - burn: 0 + Heat: 0 considerations: - !type:TargetDistanceCon curve: !type:PresetCurve diff --git a/Resources/Prototypes/Reagents/Consumable/Drink/alcohol.yml b/Resources/Prototypes/Reagents/Consumable/Drink/alcohol.yml index 0af139a01e6..c3232ea3026 100644 --- a/Resources/Prototypes/Reagents/Consumable/Drink/alcohol.yml +++ b/Resources/Prototypes/Reagents/Consumable/Drink/alcohol.yml @@ -167,7 +167,7 @@ damage: types: Poison: 0.02 - - !type:HealthChange + - !type:EvenHealthChange conditions: - !type:ReagentCondition reagent: Ethanol @@ -175,8 +175,7 @@ - !type:MetabolizerTypeCondition type: [ Dwarf ] damage: - groups: - Brute: -0.1 + Brute: -0.1 - !type:Vomit probability: 0.04 conditions: @@ -879,13 +878,12 @@ factor: 2 - !type:SatiateHunger factor: -2 - - !type:HealthChange + - !type:EvenHealthChange damage: - groups: - Burn: -1 - Brute: -1 - Airloss: -1 - Toxin: -1 + Burn: -1 + Brute: -1 + Airloss: -1 + Toxin: -1 - type: reagent id: DriestMartini diff --git a/Resources/Prototypes/Reagents/Consumable/Food/food.yml b/Resources/Prototypes/Reagents/Consumable/Food/food.yml index 642116e08d0..4bd3f6db732 100644 --- a/Resources/Prototypes/Reagents/Consumable/Food/food.yml +++ b/Resources/Prototypes/Reagents/Consumable/Food/food.yml @@ -29,12 +29,11 @@ metabolisms: Metabolites: #This makes it not compete with medicines, a large bonus for something that can heal effects: - - !type:HealthChange + - !type:EvenHealthChange probability: 0.5 damage: - groups: - Brute: -0.5 - Burn: -0.5 + Brute: -0.5 + Burn: -0.5 # Helps you stop bleeding to an extent. - !type:ModifyBleed amount: -0.25 @@ -58,11 +57,10 @@ metabolisms: Metabolites: effects: - - !type:HealthChange + - !type:EvenHealthChange probability: 0.5 damage: - groups: - Brute: -0.4 + Brute: -0.4 - !type:ModifyBloodLevel amount: 1 # weaker than iron but pretty good all things considered - !type:SatiateHunger diff --git a/Resources/Prototypes/Reagents/biological.yml b/Resources/Prototypes/Reagents/biological.yml index 53a48b665db..ebcb2181bec 100644 --- a/Resources/Prototypes/Reagents/biological.yml +++ b/Resources/Prototypes/Reagents/biological.yml @@ -25,14 +25,13 @@ - !type:MetabolizerTypeCondition type: [ Human ] inverted: true - - !type:HealthChange + - !type:EvenHealthChange conditions: - !type:MetabolizerTypeCondition type: [ Bloodsucker ] damage: - groups: - Brute: -3 - Burn: -1.25 + Brute: -3 + Burn: -1.25 Bloodstream: # Don't inject someone else's blood into yourself! Your own blood won't actually metabolise. effects: - !type:HealthChange diff --git a/Resources/Prototypes/Reagents/botany.yml b/Resources/Prototypes/Reagents/botany.yml index d31e9a1a993..5330dfa528b 100644 --- a/Resources/Prototypes/Reagents/botany.yml +++ b/Resources/Prototypes/Reagents/botany.yml @@ -250,7 +250,7 @@ - !type:ReagentCondition reagent: Ammonia min: 0.25 - - !type:HealthChange + - !type:EvenHealthChange conditions: - !type:MetabolizerTypeCondition type: [ Rat ] @@ -260,11 +260,9 @@ scaling: true ignoreResistances: true damage: - groups: - Brute: -2.5 - Burn: -2.5 - types: - Bloodloss: -5 + Brute: -2.5 + Burn: -2.5 + Airloss: -5 - !type:ModifyBloodLevel amount: 1 conditions: diff --git a/Resources/Prototypes/Reagents/chemicals.yml b/Resources/Prototypes/Reagents/chemicals.yml index 25024692989..d4178e9aead 100644 --- a/Resources/Prototypes/Reagents/chemicals.yml +++ b/Resources/Prototypes/Reagents/chemicals.yml @@ -209,10 +209,9 @@ metabolisms: Bloodstream: effects: - - !type:HealthChange + - !type:EvenHealthChange damage: - groups: - Brute: -4 + Brute: -4 - !type:GenericStatusEffect key: Adrenaline component: IgnoreSlowOnDamage diff --git a/Resources/Prototypes/Reagents/medicine.yml b/Resources/Prototypes/Reagents/medicine.yml index 1a5ea70deff..c20485b86ce 100644 --- a/Resources/Prototypes/Reagents/medicine.yml +++ b/Resources/Prototypes/Reagents/medicine.yml @@ -39,8 +39,8 @@ reagent: Dylovene min: 20 damage: - groups: - Brute: 2 + types: + Blunt: 2 - !type:Jitter conditions: - !type:ReagentCondition @@ -133,8 +133,7 @@ damage: types: Radiation: -3 - groups: - Brute: 0.5 # DeltaV - was 1.5, implant removal damage is disabled which is why upstream bumped it + Blunt: 0.5 - type: reagent id: Bicaridine @@ -247,8 +246,7 @@ types: Asphyxiation: 1 Cold: 2 - groups: - Brute: 0.5 + Blunt: 0.5 - !type:Jitter conditions: - !type:ReagentCondition @@ -346,9 +344,17 @@ types: Asphyxiation: -3 Poison: -0.5 - groups: - Brute: -0.5 - Burn: -0.5 + - !type:EvenHealthChange + conditions: + # they gotta be in crit first + - !type:MobStateCondition + mobstate: Critical + - !type:ReagentCondition + reagent: Epinephrine + max: 20 + damage: + Brute: -0.5 + Burn: -0.5 - !type:HealthChange conditions: - !type:ReagentCondition @@ -628,12 +634,10 @@ metabolisms: Bloodstream: effects: - - !type:HealthChange + - !type:EvenHealthChange damage: - groups: - Brute: -3.5 - types: - Asphyxiation: -2.5 + Brute: -1.75 + Airloss: -1 - !type:HealthChange conditions: - !type:ReagentCondition @@ -823,18 +827,14 @@ metabolisms: Bloodstream: effects: - - !type:HealthChange + - !type:EvenHealthChange conditions: - !type:TotalDamageCondition max: 50 damage: - groups: - Brute: -1 - types: - Poison: -0.5 ##Should be about what it was when it healed the toxin group - Heat: -0.33 - Shock: -0.33 - Cold: -0.33 + Brute: -1 + Burn: -1 + Toxin: -0.5 - type: reagent id: Lipozine @@ -911,8 +911,8 @@ min: 0 max: 20 damage: - groups: - Brute: 1.5 + types: + Blunt: 1.5 - !type:EvenHealthChange conditions: - !type:ReagentCondition @@ -926,8 +926,8 @@ reagent: Ultravasculine min: 20 damage: - groups: - Brute: 6 + types: + Blunt: 6 - !type:AdjustReagent conditions: - !type:ReagentCondition diff --git a/Resources/Prototypes/Reagents/toxins.yml b/Resources/Prototypes/Reagents/toxins.yml index ec9234fd27b..7564895f962 100644 --- a/Resources/Prototypes/Reagents/toxins.yml +++ b/Resources/Prototypes/Reagents/toxins.yml @@ -345,8 +345,9 @@ effects: - !type:HealthChange damage: - groups: - Airloss: 10 + types: + Asphyxiation: 5 + Bloodloss: 5 - type: reagent id: MindbreakerToxin @@ -392,8 +393,8 @@ - !type:HealthChange probability: 0.1 damage: - groups: - Brute: 2 + types: + Blunt: 2 # todo: cough, sneeze - !type:HealthChange conditions: @@ -401,10 +402,9 @@ reagent: Histamine min: 45 damage: - groups: - Brute: 2 - Airloss: 2 types: + Blunt: 2 + Asphyxiation: 2 Poison: 2 - !type:PopupMessage type: Local @@ -689,8 +689,9 @@ sprintSpeedModifier: 0.8 - !type:HealthChange damage: - groups: - Airloss: 2 + types: + Asphyxiation: 1 + Bloodloss: 1 - type: reagent id: Tazinide diff --git a/Resources/Prototypes/XenoArch/effects.yml b/Resources/Prototypes/XenoArch/effects.yml index e7254f0841c..d9d54f4562e 100644 --- a/Resources/Prototypes/XenoArch/effects.yml +++ b/Resources/Prototypes/XenoArch/effects.yml @@ -1436,9 +1436,13 @@ components: - MobState damage: - groups: - Brute: -300 - Burn: -300 + types: + Blunt: -100 + Piercing: -100 + Slash: -100 + Heat: -100 + Cold: -100 + Shock: -100 - type: entity id: XenoArtifactTesla