diff --git a/Content.Client/Entry/IgnoredComponents.cs b/Content.Client/Entry/IgnoredComponents.cs index 38d417121a..a50348367b 100644 --- a/Content.Client/Entry/IgnoredComponents.cs +++ b/Content.Client/Entry/IgnoredComponents.cs @@ -288,6 +288,7 @@ namespace Content.Client.Entry "HandLabeler", "Label", "GhostRadio", + "Armor" }; } } diff --git a/Content.Server/Armor/ArmorComponent.cs b/Content.Server/Armor/ArmorComponent.cs new file mode 100644 index 0000000000..b0d932572f --- /dev/null +++ b/Content.Server/Armor/ArmorComponent.cs @@ -0,0 +1,15 @@ +using Content.Shared.Damage; +using Robust.Shared.GameObjects; +using Robust.Shared.Serialization.Manager.Attributes; + +namespace Content.Server.Armor +{ + [RegisterComponent] + public class ArmorComponent : Component + { + public override string Name => "Armor"; + + [DataField("modifiers", required: true)] + public DamageModifierSet Modifiers = default!; + } +} diff --git a/Content.Server/Armor/ArmorSystem.cs b/Content.Server/Armor/ArmorSystem.cs new file mode 100644 index 0000000000..cb57a99d51 --- /dev/null +++ b/Content.Server/Armor/ArmorSystem.cs @@ -0,0 +1,20 @@ +using Content.Shared.Damage; +using Robust.Shared.GameObjects; + +namespace Content.Server.Armor +{ + public class ArmorSystem : EntitySystem + { + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnDamageModify); + } + + private void OnDamageModify(EntityUid uid, ArmorComponent component, DamageModifyEvent args) + { + args.Damage = DamageSpecifier.ApplyModifierSet(args.Damage, component.Modifiers); + } + } +} diff --git a/Content.Server/Body/Respiratory/RespiratorComponent.cs b/Content.Server/Body/Respiratory/RespiratorComponent.cs index 979110d8e9..af62035418 100644 --- a/Content.Server/Body/Respiratory/RespiratorComponent.cs +++ b/Content.Server/Body/Respiratory/RespiratorComponent.cs @@ -347,7 +347,7 @@ namespace Content.Server.Body.Respiratory alertsComponent.ShowAlert(AlertType.LowOxygen); } - EntitySystem.Get().TryChangeDamage(Owner.Uid, Damage); + EntitySystem.Get().TryChangeDamage(Owner.Uid, Damage, true); } private void StopSuffocation() @@ -359,7 +359,7 @@ namespace Content.Server.Body.Respiratory alertsComponent.ClearAlert(AlertType.LowOxygen); } - EntitySystem.Get().TryChangeDamage(Owner.Uid, DamageRecovery); + EntitySystem.Get().TryChangeDamage(Owner.Uid, DamageRecovery, true); } public GasMixture Clean(BloodstreamComponent bloodstream) diff --git a/Content.Server/Inventory/InventorySystem.cs b/Content.Server/Inventory/InventorySystem.cs index a9210797df..7cbc3ad769 100644 --- a/Content.Server/Inventory/InventorySystem.cs +++ b/Content.Server/Inventory/InventorySystem.cs @@ -1,5 +1,6 @@ using Content.Server.Atmos; using Content.Server.Inventory.Components; +using Content.Shared.Damage; using Robust.Shared.Containers; using Robust.Shared.GameObjects; @@ -15,6 +16,7 @@ namespace Content.Server.Inventory SubscribeLocalEvent(HandleInvRemovedFromContainer); SubscribeLocalEvent(OnHighPressureEvent); SubscribeLocalEvent(OnLowPressureEvent); + SubscribeLocalEvent(OnDamageModify); } private static void HandleInvRemovedFromContainer(EntityUid uid, InventoryComponent component, EntRemovedFromContainerMessage args) @@ -37,6 +39,14 @@ namespace Content.Server.Inventory RelayPressureEvent(component, args); } + private void OnDamageModify(EntityUid uid, InventoryComponent component, DamageModifyEvent args) + { + foreach (var equipped in component.GetAllHeldItems()) + { + RaiseLocalEvent(equipped.Uid, args, false); + } + } + private void RelayPressureEvent(InventoryComponent component, T args) where T : PressureEvent { foreach (var equipped in component.GetAllHeldItems()) diff --git a/Content.Shared/Damage/DamageableSystem.cs b/Content.Shared/Damage/DamageableSystem.cs index 117dfebba9..797173879b 100644 --- a/Content.Shared/Damage/DamageableSystem.cs +++ b/Content.Shared/Damage/DamageableSystem.cs @@ -118,13 +118,18 @@ namespace Content.Shared.Damage } // Apply resistances - if (!ignoreResistances && damageable.DamageModifierSetId != null) + if (!ignoreResistances) { - if (_prototypeManager.TryIndex(damageable.DamageModifierSetId, out var modifierSet)) + if (damageable.DamageModifierSetId != null && + _prototypeManager.TryIndex(damageable.DamageModifierSetId, out var modifierSet)) { damage = DamageSpecifier.ApplyModifierSet(damage, modifierSet); } + var ev = new DamageModifyEvent(damage); + RaiseLocalEvent(uid, ev, false); + damage = ev.Damage; + if (damage.Empty) { return damage; @@ -199,6 +204,23 @@ namespace Content.Shared.Damage } } + /// + /// Raised on an entity when damage is about to be dealt, + /// in case anything else needs to modify it other than the base + /// damageable component. + /// + /// For example, armor. + /// + public class DamageModifyEvent : EntityEventArgs + { + public DamageSpecifier Damage; + + public DamageModifyEvent(DamageSpecifier damage) + { + Damage = damage; + } + } + public class DamageChangedEvent : EntityEventArgs { /// diff --git a/Resources/Prototypes/Entities/Clothing/Eyes/glasses.yml b/Resources/Prototypes/Entities/Clothing/Eyes/glasses.yml index 7572f232ab..a6eaa6ede3 100644 --- a/Resources/Prototypes/Entities/Clothing/Eyes/glasses.yml +++ b/Resources/Prototypes/Entities/Clothing/Eyes/glasses.yml @@ -69,6 +69,10 @@ sprite: Clothing/Eyes/Glasses/meson.rsi - type: Clothing sprite: Clothing/Eyes/Glasses/meson.rsi + - type: Armor + modifiers: + coefficients: + Radiation: 0.5 - type: entity parent: ClothingEyesBase diff --git a/Resources/Prototypes/Entities/Clothing/Head/base.yml b/Resources/Prototypes/Entities/Clothing/Head/base.yml index ea2aa62164..9944903a2d 100644 --- a/Resources/Prototypes/Entities/Clothing/Head/base.yml +++ b/Resources/Prototypes/Entities/Clothing/Head/base.yml @@ -29,6 +29,14 @@ - type: PressureProtection highPressureMultiplier: 0.5 lowPressureMultiplier: 100 + - type: Armor + modifiers: + coefficients: + Blunt: 0.90 + Slash: 0.90 + Piercing: 0.95 + Heat: 0.90 + Radiation: 0.25 - type: entity abstract: true diff --git a/Resources/Prototypes/Entities/Clothing/Head/helmets.yml b/Resources/Prototypes/Entities/Clothing/Head/helmets.yml index ecef0b5fbc..138853fa3c 100644 --- a/Resources/Prototypes/Entities/Clothing/Head/helmets.yml +++ b/Resources/Prototypes/Entities/Clothing/Head/helmets.yml @@ -41,6 +41,13 @@ sprite: Clothing/Head/Helmets/security.rsi - type: Clothing sprite: Clothing/Head/Helmets/security.rsi + - type: Armor + modifiers: + coefficients: + Blunt: 0.8 + Slash: 0.8 + Piercing: 0.9 + Heat: 0.8 - type: entity parent: ClothingHeadBase diff --git a/Resources/Prototypes/Entities/Clothing/OuterClothing/armor.yml b/Resources/Prototypes/Entities/Clothing/OuterClothing/armor.yml index da84209ac2..6cd0dda45a 100644 --- a/Resources/Prototypes/Entities/Clothing/OuterClothing/armor.yml +++ b/Resources/Prototypes/Entities/Clothing/OuterClothing/armor.yml @@ -1,3 +1,5 @@ +# Numbers for armor here largely taken from /tg/. + - type: entity parent: ClothingOuterBase id: ClothingOuterArmorReflective @@ -8,6 +10,13 @@ sprite: Clothing/OuterClothing/Armor/armor_reflec.rsi - type: Clothing sprite: Clothing/OuterClothing/Armor/armor_reflec.rsi + - type: Armor + modifiers: + coefficients: + Blunt: 0.9 + Slash: 0.9 + Piercing: 0.9 + Heat: 0.4 # this technically means it protects against fires pretty well? - type: entity parent: ClothingOuterBase @@ -19,6 +28,13 @@ sprite: Clothing/OuterClothing/Armor/bulletproof.rsi - type: Clothing sprite: Clothing/OuterClothing/Armor/bulletproof.rsi + - type: Armor + modifiers: + coefficients: + Blunt: 0.9 + Slash: 0.9 + Piercing: 0.4 + Heat: 0.9 - type: entity parent: ClothingOuterBase @@ -30,6 +46,13 @@ sprite: Clothing/OuterClothing/Armor/cult_armour.rsi - type: Clothing sprite: Clothing/OuterClothing/Armor/cult_armour.rsi + - type: Armor + modifiers: + coefficients: + Blunt: 0.5 + Slash: 0.5 + Piercing: 0.6 + Heat: 0.5 - type: entity parent: ClothingOuterBase @@ -41,9 +64,17 @@ sprite: Clothing/OuterClothing/Armor/heavy.rsi - type: Clothing sprite: Clothing/OuterClothing/Armor/heavy.rsi + - type: Armor + modifiers: + coefficients: + Blunt: 0.2 + Slash: 0.2 + Piercing: 0.2 + Heat: 0.5 + Radiation: 0 - type: entity - parent: ClothingOuterBase + parent: ClothingOuterArmorHeavy id: ClothingOuterArmorHeavyGreen name: green heavy armor suit description: A heavily armored suit with green accents that protects against excessive damage. @@ -54,7 +85,7 @@ sprite: Clothing/OuterClothing/Armor/heavygreen.rsi - type: entity - parent: ClothingOuterBase + parent: ClothingOuterArmorHeavy id: ClothingOuterArmorHeavyRed name: red heavy armor suit description: A heavily armored suit with red accents that protects against excessive damage. @@ -65,7 +96,7 @@ sprite: Clothing/OuterClothing/Armor/heavyred.rsi - type: entity - parent: ClothingOuterBase + parent: ClothingOuterArmorHeavy id: ClothingOuterArmorMagusblue name: magus blue description: An blue armored suit that provides good protection. @@ -76,7 +107,7 @@ sprite: Clothing/OuterClothing/Armor/magusblue.rsi - type: entity - parent: ClothingOuterBase + parent: ClothingOuterArmorHeavy id: ClothingOuterArmorMagusred name: magus red description: A red armored suit that provides good protection. diff --git a/Resources/Prototypes/Entities/Clothing/OuterClothing/base.yml b/Resources/Prototypes/Entities/Clothing/OuterClothing/base.yml index b848142286..a75ebf5845 100644 --- a/Resources/Prototypes/Entities/Clothing/OuterClothing/base.yml +++ b/Resources/Prototypes/Entities/Clothing/OuterClothing/base.yml @@ -18,3 +18,11 @@ - type: PressureProtection highPressureMultiplier: 0.75 lowPressureMultiplier: 100 + - type: Armor + modifiers: + coefficients: + Blunt: 0.90 + Slash: 0.90 + Piercing: 0.95 + Heat: 0.90 + Radiation: 0.25 diff --git a/Resources/Prototypes/Entities/Clothing/OuterClothing/coats.yml b/Resources/Prototypes/Entities/Clothing/OuterClothing/coats.yml index e8662570c4..3a249fd9c8 100644 --- a/Resources/Prototypes/Entities/Clothing/OuterClothing/coats.yml +++ b/Resources/Prototypes/Entities/Clothing/OuterClothing/coats.yml @@ -49,6 +49,13 @@ sprite: Clothing/OuterClothing/Coats/hos_trenchcoat.rsi - type: Storage capacity: 10 + - type: Armor + modifiers: + coefficients: + Blunt: 0.7 + Slash: 0.7 + Piercing: 0.7 + Heat: 0.7 - type: entity parent: ClothingOuterBase diff --git a/Resources/Prototypes/Entities/Clothing/OuterClothing/vests.yml b/Resources/Prototypes/Entities/Clothing/OuterClothing/vests.yml index d67a6ce0c6..04af80ea0f 100644 --- a/Resources/Prototypes/Entities/Clothing/OuterClothing/vests.yml +++ b/Resources/Prototypes/Entities/Clothing/OuterClothing/vests.yml @@ -30,6 +30,13 @@ sprite: Clothing/OuterClothing/Vests/kevlar.rsi - type: Clothing sprite: Clothing/OuterClothing/Vests/kevlar.rsi + - type: Armor + modifiers: + coefficients: + Blunt: 0.9 + Slash: 0.9 + Piercing: 0.4 + Heat: 0.9 - type: entity parent: ClothingOuterBase