diff --git a/Content.Client/HealthAnalyzer/UI/HealthAnalyzerControl.xaml.cs b/Content.Client/HealthAnalyzer/UI/HealthAnalyzerControl.xaml.cs index 92079542bd..80b3e4b6a7 100644 --- a/Content.Client/HealthAnalyzer/UI/HealthAnalyzerControl.xaml.cs +++ b/Content.Client/HealthAnalyzer/UI/HealthAnalyzerControl.xaml.cs @@ -135,7 +135,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); } @@ -153,7 +153,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 bd5cac05dd..522b53b5a9 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 20b0877548..11e7abd8a9 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 0000000000..b129307e74 --- /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 064d67f606..0336abaa98 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 af1651f8dc..3b907eb494 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 692a8ec4f9..77d14431f5 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 cef27d4d2f..428d2aa9cd 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 6c11f88b1e..4b08476982 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 92f56571a6..0000000000 --- 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 facdcce0e8..c19f14ea19 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 e08e742b41..ff56c1affc 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 32c67fd0c2..78b00f4d56 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 17d14679fb..8743ec3752 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. /// @@ -70,31 +71,6 @@ public sealed partial class DamageableSystem : EntitySystem // byref struct event. 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 diff --git a/Content.Shared/Destructible/Triggers/DamageGroupTrigger.cs b/Content.Shared/Destructible/Triggers/DamageGroupTrigger.cs index c1add2e891..11c78fbd1e 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 3691039189..0cfa4dedca 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 b4fdc5ed3c..56bda116a1 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 78f97cc449..8372e4923d 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 b670c067b9..1d8e946844 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 11f6989a5a..6befa31419 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 47810b6bfa..74663cc814 100644 --- a/Resources/Prototypes/Body/species_base.yml +++ b/Resources/Prototypes/Body/species_base.yml @@ -186,8 +186,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 b57dd64636..00344c9383 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml @@ -2424,8 +2424,8 @@ angle: 0 animation: WeaponArcBite damage: - groups: - Brute: 5 + types: + Piercing: 5 - type: Item size: Normal sprite: Mobs/Animals/grenadepenguin.rsi @@ -2592,9 +2592,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: MobSpiderBase diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/miscellaneous.yml b/Resources/Prototypes/Entities/Mobs/NPCs/miscellaneous.yml index e49e9fe322..45ff0ea755 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 653704cfbb..0a35ebf5e5 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 33653ed207..29793609e1 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/xeno.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/xeno.yml @@ -78,8 +78,8 @@ collection: AlienClaw animation: WeaponArcBite damage: - groups: - Brute: 6 + types: + Piercing: 6 - type: DamageStateVisuals states: Alive: @@ -176,8 +176,8 @@ 40: 0.7 - type: MeleeWeapon damage: - groups: - Brute: 6 + types: + Slash: 6 - type: MovementSpeedModifier baseSprintSpeed: 4 - type: Fixtures @@ -214,8 +214,8 @@ - type: MovementSpeedModifier - type: MeleeWeapon damage: - groups: - Brute: 12 + types: + Slash: 12 - type: Fixtures fixtures: fix1: @@ -251,8 +251,8 @@ baseSprintSpeed: 4 - type: MeleeWeapon damage: - groups: - Brute: 10 + types: + Slash: 10 - type: SlowOnDamage speedModifierThresholds: 50: 0.7 @@ -284,8 +284,8 @@ baseSprintSpeed: 6.0 - type: MeleeWeapon damage: - groups: - Brute: 5 + types: + Slash: 5 - type: Fixtures fixtures: fix1: @@ -506,8 +506,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 2aa28bc089..57b682caea 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/dragon.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/dragon.yml @@ -229,8 +229,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 bae37a421b..c09faf40bd 100644 --- a/Resources/Prototypes/Entities/Mobs/base.yml +++ b/Resources/Prototypes/Entities/Mobs/base.yml @@ -161,8 +161,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 d9475c9ebe..1913f6b4e1 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 be2d04fea1..9436776d0d 100644 --- a/Resources/Prototypes/Entities/Objects/Consumable/Food/Baked/cake.yml +++ b/Resources/Prototypes/Entities/Objects/Consumable/Food/Baked/cake.yml @@ -1121,8 +1121,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 0f8450a5e3..bbcfdbdbe6 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 c82debbfc9..51aca993f7 100644 --- a/Resources/Prototypes/Entities/Objects/Shields/shields.yml +++ b/Resources/Prototypes/Entities/Objects/Shields/shields.yml @@ -71,9 +71,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 1bb9d10307..0fb3f1a04b 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 @@ -66,9 +72,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 7893dfd646..c09bef4a3a 100644 --- a/Resources/Prototypes/Entities/Objects/Specific/Medical/healing.yml +++ b/Resources/Prototypes/Entities/Objects/Specific/Medical/healing.yml @@ -130,8 +130,10 @@ damageContainers: - Biological 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: @@ -176,8 +178,10 @@ damageContainers: - Biological 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" @@ -268,9 +272,8 @@ damageContainers: - Biological 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 @@ -368,10 +371,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 79fb907a7c..fd8e5d6334 100644 --- a/Resources/Prototypes/Entities/Objects/Specific/Medical/surgery.yml +++ b/Resources/Prototypes/Entities/Objects/Specific/Medical/surgery.yml @@ -209,8 +209,8 @@ heldPrefix: improv - type: MeleeWeapon damage: - groups: - Brute: 10 + types: + Slash: 10 soundHit: path: /Audio/Weapons/bladeslice.ogg - type: Tool @@ -228,8 +228,8 @@ heldPrefix: electric - type: MeleeWeapon damage: - groups: - Brute: 15 + types: + Slash: 15 soundHit: path: /Audio/Items/drill_hit.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 30822a024a..29cb56db7d 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Projectiles/magic.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Projectiles/magic.yml @@ -106,8 +106,7 @@ deleteOnCollide: false onlyCollideWhenShot: true damage: - types: - Brute: 0 + types: {} - type: Sprite noRot: true sprite: Structures/Storage/closet.rsi @@ -246,11 +245,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 cc09a5a378..85fb02ce85 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 @@ -62,9 +61,8 @@ path: "/Audio/Items/drill_hit.ogg" attackRate: 4 damage: - groups: - Brute: 3 types: + Piercing: 3 Structural: 15 - type: entity @@ -84,9 +82,8 @@ path: "/Audio/Items/drill_hit.ogg" attackRate: 4 damage: - groups: - Brute: 6 types: + Piercing: 6 Structural: 30 @@ -132,8 +129,10 @@ delay: 0.9 - type: LeechOnMarker leech: - groups: - Brute: -6 + types: + Blunt: -2 + Slash: -2 + Piercing: -2 - type: Gun soundGunshot: /Audio/Weapons/plasma_cutter.ogg fireRate: 1 @@ -238,8 +237,10 @@ count: 1 - type: LeechOnMarker leech: - groups: - Brute: -21 + 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 49b085b29a..bb2bb08cc4 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 538a83e2c2..ad2e95f147 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: @@ -877,13 +876,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 1914262a4e..cb43938adf 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 29d4a18f1c..fcabcadee5 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 7885702a9f..1b1ae04cd5 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 ] @@ -259,11 +259,9 @@ min: 1 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 b575ad47bd..36f7e2073f 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 597b101392..782df52a51 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: 1.5 + Blunt: 1.5 - type: reagent id: Bicaridine @@ -246,8 +245,7 @@ types: Asphyxiation: 1 Cold: 2 - groups: - Brute: 0.5 + Blunt: 0.5 - !type:Jitter conditions: - !type:ReagentCondition @@ -344,9 +342,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 @@ -626,12 +632,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 @@ -812,18 +816,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 @@ -887,8 +887,8 @@ min: 0 max: 20 damage: - groups: - Brute: 1.5 + types: + Blunt: 1.5 - !type:EvenHealthChange conditions: - !type:ReagentCondition @@ -902,8 +902,8 @@ reagent: Ultravasculine min: 20 damage: - groups: - Brute: 6 + types: + Blunt: 6 - !type:AdjustReagent conditions: - !type:ReagentCondition diff --git a/Resources/Prototypes/Reagents/narcotics.yml b/Resources/Prototypes/Reagents/narcotics.yml index 2a57cba68b..396bcacf99 100644 --- a/Resources/Prototypes/Reagents/narcotics.yml +++ b/Resources/Prototypes/Reagents/narcotics.yml @@ -17,7 +17,7 @@ damage: types: Poison: 0.55 - Blunt: 0.5 + Blunt: 1.1 # meant to be slightly more than tricordrazine heals # OD - !type:HealthChange conditions: diff --git a/Resources/Prototypes/Reagents/toxins.yml b/Resources/Prototypes/Reagents/toxins.yml index 103c284a67..670baa829b 100644 --- a/Resources/Prototypes/Reagents/toxins.yml +++ b/Resources/Prototypes/Reagents/toxins.yml @@ -332,8 +332,9 @@ effects: - !type:HealthChange damage: - groups: - Airloss: 10 + types: + Asphyxiation: 5 + Bloodloss: 5 - type: reagent id: MindbreakerToxin @@ -368,8 +369,8 @@ - !type:HealthChange probability: 0.1 damage: - groups: - Brute: 2 + types: + Blunt: 2 # todo: cough, sneeze - !type:HealthChange conditions: @@ -377,10 +378,9 @@ reagent: Histamine min: 45 damage: - groups: - Brute: 2 - Airloss: 2 types: + Blunt: 2 + Asphyxiation: 2 Poison: 2 - !type:PopupMessage type: Local @@ -660,8 +660,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 fb0d845bd8..0ceb48401a 100644 --- a/Resources/Prototypes/XenoArch/effects.yml +++ b/Resources/Prototypes/XenoArch/effects.yml @@ -1256,9 +1256,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