diff --git a/Content.Server/Clothing/Components/GloveHeatResistanceComponent.cs b/Content.Server/Clothing/Components/GloveHeatResistanceComponent.cs
deleted file mode 100644
index 29a3b901a786..000000000000
--- a/Content.Server/Clothing/Components/GloveHeatResistanceComponent.cs
+++ /dev/null
@@ -1,12 +0,0 @@
-namespace Content.Server.Clothing.Components;
-
-///
-/// TODO this needs removed somehow.
-/// Handles 'heat resistance' for gloves touching bulbs and that's it, ick.
-///
-[RegisterComponent]
-public sealed partial class GloveHeatResistanceComponent : Component
-{
- [DataField("heatResistance")]
- public int HeatResistance = 323;
-}
diff --git a/Content.Server/Light/Components/PoweredLightComponent.cs b/Content.Server/Light/Components/PoweredLightComponent.cs
index 489a49eec220..1a6f610516e8 100644
--- a/Content.Server/Light/Components/PoweredLightComponent.cs
+++ b/Content.Server/Light/Components/PoweredLightComponent.cs
@@ -30,10 +30,6 @@ public sealed partial class PoweredLightComponent : Component
[DataField("on")]
public bool On = true;
- [DataField("damage", required: true)]
- [ViewVariables(VVAccess.ReadWrite)]
- public DamageSpecifier Damage = default!;
-
[DataField("ignoreGhostsBoo")]
public bool IgnoreGhostsBoo;
diff --git a/Content.Server/Light/EntitySystems/PoweredLightSystem.cs b/Content.Server/Light/EntitySystems/PoweredLightSystem.cs
index 8aa432c21ea2..33b7ce0782f4 100644
--- a/Content.Server/Light/EntitySystems/PoweredLightSystem.cs
+++ b/Content.Server/Light/EntitySystems/PoweredLightSystem.cs
@@ -1,5 +1,4 @@
using Content.Server.Administration.Logs;
-using Content.Server.Clothing.Components;
using Content.Server.DeviceLinking.Events;
using Content.Server.DeviceLinking.Systems;
using Content.Server.DeviceNetwork;
@@ -24,6 +23,8 @@
using Robust.Shared.Player;
using Robust.Shared.Timing;
using Robust.Shared.Audio.Systems;
+using Content.Shared.Damage.Systems;
+using Content.Shared.Damage.Components;
namespace Content.Server.Light.EntitySystems
{
@@ -33,11 +34,8 @@ namespace Content.Server.Light.EntitySystems
public sealed class PoweredLightSystem : EntitySystem
{
[Dependency] private readonly IGameTiming _gameTiming = default!;
- [Dependency] private readonly DamageableSystem _damageableSystem = default!;
[Dependency] private readonly SharedAmbientSoundSystem _ambientSystem = default!;
[Dependency] private readonly LightBulbSystem _bulbSystem = default!;
- [Dependency] private readonly SharedPopupSystem _popupSystem = default!;
- [Dependency] private readonly IAdminLogManager _adminLogger= default!;
[Dependency] private readonly SharedHandsSystem _handsSystem = default!;
[Dependency] private readonly DeviceLinkSystem _signalSystem = default!;
[Dependency] private readonly SharedContainerSystem _containerSystem = default!;
@@ -45,7 +43,7 @@ public sealed class PoweredLightSystem : EntitySystem
[Dependency] private readonly SharedAudioSystem _audio = default!;
[Dependency] private readonly PointLightSystem _pointLight = default!;
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
- [Dependency] private readonly InventorySystem _inventory = default!;
+ [Dependency] private readonly DamageOnInteractSystem _damageOnInteractSystem = default!;
private static readonly TimeSpan ThunkDelay = TimeSpan.FromSeconds(2);
public const string LightBulbContainer = "light_bulb";
@@ -106,40 +104,7 @@ private void OnInteractHand(EntityUid uid, PoweredLightComponent light, Interact
if (bulbUid == null)
return;
- // check if it's possible to apply burn damage to user
var userUid = args.User;
- if (EntityManager.TryGetComponent(bulbUid.Value, out LightBulbComponent? lightBulb))
- {
- // get users heat resistance
- var res = int.MinValue;
- if (_inventory.TryGetSlotEntity(userUid, "gloves", out var slotEntity) &&
- TryComp(slotEntity, out var gloves))
- {
- res = gloves.HeatResistance;
- }
-
- // check heat resistance against user
- var burnedHand = light.CurrentLit && res < lightBulb.BurningTemperature;
- if (burnedHand)
- {
- var damage = _damageableSystem.TryChangeDamage(userUid, light.Damage, origin: userUid);
-
- // If damage is null then the entity could not take heat damage so they did not get burned.
- if (damage != null)
- {
-
- var burnMsg = Loc.GetString("powered-light-component-burn-hand");
- _popupSystem.PopupEntity(burnMsg, uid, userUid);
- _adminLogger.Add(LogType.Damaged, $"{ToPrettyString(args.User):user} burned their hand on {ToPrettyString(args.Target):target} and received {damage.GetTotal():damage} damage");
- _audio.PlayEntity(light.BurnHandSound, Filter.Pvs(uid), uid, true);
-
- args.Handled = true;
- return;
- }
- }
- }
-
-
//removing a broken/burned bulb, so allow instant removal
if(TryComp(bulbUid.Value, out var bulb) && bulb.State != LightBulbState.Normal)
{
@@ -435,6 +400,10 @@ private void SetLight(EntityUid uid, bool value, Color? color = null, PoweredLig
if (softness != null)
_pointLight.SetSoftness(uid, (float) softness, pointLight);
}
+
+ // light bulbs burn your hands!
+ if (TryComp(uid, out var damageOnInteractComp))
+ _damageOnInteractSystem.SetIsDamageActiveTo((uid, damageOnInteractComp), value);
}
public void ToggleLight(EntityUid uid, PoweredLightComponent? light = null)
diff --git a/Content.Shared/Anomaly/Components/AnomalyComponent.cs b/Content.Shared/Anomaly/Components/AnomalyComponent.cs
index 88e942ec5079..724dfd38d2f6 100644
--- a/Content.Shared/Anomaly/Components/AnomalyComponent.cs
+++ b/Content.Shared/Anomaly/Components/AnomalyComponent.cs
@@ -202,20 +202,6 @@ public sealed partial class AnomalyComponent : Component
public float GrowingPointMultiplier = 1.5f;
#endregion
- ///
- /// The amount of damage dealt when either a player touches the anomaly
- /// directly or by hitting the anomaly.
- ///
- [DataField(required: true)]
- public DamageSpecifier AnomalyContactDamage = default!;
-
- ///
- /// The sound effect played when a player
- /// burns themselves on an anomaly via contact.
- ///
- [DataField]
- public SoundSpecifier AnomalyContactDamageSound = new SoundPathSpecifier("/Audio/Effects/lightburn.ogg");
-
///
/// A prototype entity that appears when an anomaly supercrit collapse.
///
diff --git a/Content.Shared/Anomaly/SharedAnomalySystem.cs b/Content.Shared/Anomaly/SharedAnomalySystem.cs
index da1d31c6ff65..c3d6591b7252 100644
--- a/Content.Shared/Anomaly/SharedAnomalySystem.cs
+++ b/Content.Shared/Anomaly/SharedAnomalySystem.cs
@@ -30,7 +30,6 @@ public abstract class SharedAnomalySystem : EntitySystem
[Dependency] private readonly INetManager _net = default!;
[Dependency] protected readonly IRobustRandom Random = default!;
[Dependency] protected readonly ISharedAdminLogManager AdminLog = default!;
- [Dependency] private readonly DamageableSystem _damageable = default!;
[Dependency] protected readonly SharedAudioSystem Audio = default!;
[Dependency] protected readonly SharedAppearanceSystem Appearance = default!;
[Dependency] private readonly SharedPhysicsSystem _physics = default!;
@@ -42,26 +41,10 @@ public override void Initialize()
{
base.Initialize();
- SubscribeLocalEvent(OnInteractHand);
- SubscribeLocalEvent(OnAttacked);
SubscribeLocalEvent(OnAnomalyThrowStart);
SubscribeLocalEvent(OnAnomalyThrowEnd);
}
- private void OnInteractHand(EntityUid uid, AnomalyComponent component, InteractHandEvent args)
- {
- DoAnomalyBurnDamage(uid, args.User, component);
- args.Handled = true;
- }
-
- private void OnAttacked(EntityUid uid, AnomalyComponent component, AttackedEvent args)
- {
- if (HasComp(args.Used))
- return;
-
- DoAnomalyBurnDamage(uid, args.User, component);
- }
-
private void OnAnomalyThrowStart(Entity ent, ref MeleeThrowOnHitStartEvent args)
{
if (!TryComp(args.Used, out var corePowered) || !TryComp(ent, out var body))
@@ -75,15 +58,6 @@ private void OnAnomalyThrowEnd(Entity ent, ref MeleeThrowOnHit
_physics.SetBodyType(ent, BodyType.Static);
}
- public void DoAnomalyBurnDamage(EntityUid source, EntityUid target, AnomalyComponent component)
- {
- _damageable.TryChangeDamage(target, component.AnomalyContactDamage, true);
- if (!Timing.IsFirstTimePredicted || _net.IsServer)
- return;
- Audio.PlayPvs(component.AnomalyContactDamageSound, source);
- Popup.PopupEntity(Loc.GetString("anomaly-component-contact-damage"), target, target);
- }
-
public void DoAnomalyPulse(EntityUid uid, AnomalyComponent? component = null)
{
if (!Resolve(uid, ref component))
diff --git a/Content.Shared/Damage/Components/DamageOnAttackedComponent.cs b/Content.Shared/Damage/Components/DamageOnAttackedComponent.cs
new file mode 100644
index 000000000000..5f6bd7d99720
--- /dev/null
+++ b/Content.Shared/Damage/Components/DamageOnAttackedComponent.cs
@@ -0,0 +1,47 @@
+using Robust.Shared.Audio;
+using Robust.Shared.GameStates;
+
+namespace Content.Shared.Damage.Components;
+
+
+///
+/// This component is added to entities that you want to damage the player
+/// if the player interacts with it. For example, if a player tries touching
+/// a hot light bulb or an anomaly. This damage can be cancelled if the user
+/// has a component that protects them from this.
+///
+[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
+public sealed partial class DamageOnAttackedComponent : Component
+{
+ ///
+ /// How much damage to apply to the person making contact
+ ///
+ [DataField(required: true), AutoNetworkedField]
+ public DamageSpecifier Damage = default!;
+
+ ///
+ /// Whether the damage should be resisted by a person's armor values
+ /// and the
+ ///
+ [DataField]
+ public bool IgnoreResistances = false;
+
+ ///
+ /// What kind of localized text should pop up when they interact with the entity
+ ///
+ [DataField]
+ public LocId? PopupText;
+
+ ///
+ /// The sound that should be made when interacting with the entity
+ ///
+ [DataField]
+ public SoundSpecifier InteractSound = new SoundPathSpecifier("/Audio/Effects/lightburn.ogg");
+
+ ///
+ /// Generic boolean to toggle the damage application on and off
+ /// This is useful for things that can be toggled on or off, like a stovetop
+ ///
+ [DataField, AutoNetworkedField]
+ public bool IsDamageActive = true;
+}
diff --git a/Content.Shared/Damage/Components/DamageOnAttackedProtectionComponent.cs b/Content.Shared/Damage/Components/DamageOnAttackedProtectionComponent.cs
new file mode 100644
index 000000000000..9581d2049664
--- /dev/null
+++ b/Content.Shared/Damage/Components/DamageOnAttackedProtectionComponent.cs
@@ -0,0 +1,29 @@
+using Content.Shared.Inventory;
+using Robust.Shared.GameStates;
+
+namespace Content.Shared.Damage.Components;
+
+
+///
+/// This component is added to entities to protect them from being damaged
+/// when attacking objects with the
+/// If the entity has sufficient protection, the entity will take no damage.
+///
+[RegisterComponent, NetworkedComponent]
+public sealed partial class DamageOnAttackedProtectionComponent : Component, IClothingSlots
+{
+ ///
+ /// How much and what kind of damage to protect the user from
+ /// when interacting with something with
+ ///
+ [DataField(required: true)]
+ public DamageModifierSet DamageProtection = default!;
+
+ ///
+ /// Only protects if the item is in the correct slot
+ /// i.e. having gloves in your pocket doesn't protect you, it has to be on your hands
+ /// Set slots to NONE if it works while you hold the item in your main hand
+ ///
+ [DataField]
+ public SlotFlags Slots { get; set; } = SlotFlags.WITHOUT_POCKET;
+}
diff --git a/Content.Shared/Damage/Components/DamageOnInteractComponent.cs b/Content.Shared/Damage/Components/DamageOnInteractComponent.cs
new file mode 100644
index 000000000000..9487dec8ef96
--- /dev/null
+++ b/Content.Shared/Damage/Components/DamageOnInteractComponent.cs
@@ -0,0 +1,47 @@
+using Robust.Shared.Audio;
+using Robust.Shared.GameStates;
+
+namespace Content.Shared.Damage.Components;
+
+
+///
+/// This component is added to entities that you want to damage the player
+/// if the player interacts with it. For example, if a player tries touching
+/// a hot light bulb or an anomaly. This damage can be cancelled if the user
+/// has a component that protects them from this.
+///
+[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
+public sealed partial class DamageOnInteractComponent : Component
+{
+ ///
+ /// How much damage to apply to the person making contact
+ ///
+ [DataField(required: true), AutoNetworkedField]
+ public DamageSpecifier Damage = default!;
+
+ ///
+ /// Whether the damage should be resisted by a person's armor values
+ /// and the
+ ///
+ [DataField]
+ public bool IgnoreResistances;
+
+ ///
+ /// What kind of localized text should pop up when they interact with the entity
+ ///
+ [DataField]
+ public LocId? PopupText;
+
+ ///
+ /// The sound that should be made when interacting with the entity
+ ///
+ [DataField]
+ public SoundSpecifier InteractSound = new SoundPathSpecifier("/Audio/Effects/lightburn.ogg");
+
+ ///
+ /// Generic boolean to toggle the damage application on and off
+ /// This is useful for things that can be toggled on or off, like a stovetop
+ ///
+ [DataField, AutoNetworkedField]
+ public bool IsDamageActive = true;
+}
diff --git a/Content.Shared/Damage/Components/DamageOnInteractProtectionComponent.cs b/Content.Shared/Damage/Components/DamageOnInteractProtectionComponent.cs
new file mode 100644
index 000000000000..f57c3d22c17c
--- /dev/null
+++ b/Content.Shared/Damage/Components/DamageOnInteractProtectionComponent.cs
@@ -0,0 +1,29 @@
+using Content.Shared.Inventory;
+using Robust.Shared.GameStates;
+
+namespace Content.Shared.Damage.Components;
+
+
+///
+/// This component is added to entities to protect them from being damaged
+/// when interacting with objects with the
+/// If the entity has sufficient protection, interaction with the object is not cancelled.
+/// This allows the user to do things like remove a lightbulb.
+///
+[RegisterComponent, NetworkedComponent]
+public sealed partial class DamageOnInteractProtectionComponent : Component, IClothingSlots
+{
+ ///
+ /// How much and what kind of damage to protect the user from
+ /// when interacting with something with
+ ///
+ [DataField(required: true)]
+ public DamageModifierSet DamageProtection = default!;
+
+ ///
+ /// Only protects if the item is in the correct slot
+ /// i.e. having gloves in your pocket doesn't protect you, it has to be on your hands
+ ///
+ [DataField]
+ public SlotFlags Slots { get; set; } = SlotFlags.GLOVES;
+}
diff --git a/Content.Shared/Damage/Systems/DamageOnAttackedSystem.cs b/Content.Shared/Damage/Systems/DamageOnAttackedSystem.cs
new file mode 100644
index 000000000000..ab5866c5aa57
--- /dev/null
+++ b/Content.Shared/Damage/Systems/DamageOnAttackedSystem.cs
@@ -0,0 +1,99 @@
+using Content.Shared.Administration.Logs;
+using Content.Shared.Damage.Components;
+using Content.Shared.Database;
+using Content.Shared.Hands.Components;
+using Content.Shared.Hands.EntitySystems;
+using Content.Shared.Inventory;
+using Content.Shared.Popups;
+using Content.Shared.Weapons.Melee.Events;
+using Robust.Shared.Audio.Systems;
+using Robust.Shared.Network;
+using Robust.Shared.Timing;
+
+namespace Content.Shared.Damage.Systems;
+
+public sealed class DamageOnAttackedSystem : EntitySystem
+{
+ [Dependency] private readonly ISharedAdminLogManager _adminLogger = default!;
+ [Dependency] private readonly IGameTiming _gameTiming = default!;
+ [Dependency] private readonly INetManager _net = default!;
+ [Dependency] private readonly DamageableSystem _damageableSystem = default!;
+ [Dependency] private readonly SharedAudioSystem _audioSystem = default!;
+ [Dependency] private readonly SharedPopupSystem _popupSystem = default!;
+ [Dependency] private readonly InventorySystem _inventorySystem = default!;
+ [Dependency] private readonly SharedHandsSystem _handsSystem = default!;
+
+ public override void Initialize()
+ {
+ base.Initialize();
+
+ SubscribeLocalEvent(OnAttacked);
+ }
+
+ ///
+ /// Damages the user that attacks the entity and potentially
+ /// plays a sound or pops up text in response
+ ///
+ /// The entity being hit
+ /// Contains the user that hit the entity
+ private void OnAttacked(Entity entity, ref AttackedEvent args)
+ {
+ if (!entity.Comp.IsDamageActive)
+ return;
+
+ var totalDamage = entity.Comp.Damage;
+
+ if (!entity.Comp.IgnoreResistances)
+ {
+ // try to get the damage on attacked protection component from something the entity has in their inventory
+ _inventorySystem.TryGetInventoryEntity(args.User, out var protectiveEntity);
+
+ // if comp is null that means the user didn't have anything equipped that protected them
+ // let's check their hands to see if the thing they attacked with gives them protection, like the GORILLA gauntlet
+ if (protectiveEntity.Comp == null && TryComp(args.User, out var handsComp))
+ {
+ if (_handsSystem.TryGetActiveItem((args.User, handsComp), out var itemInHand) &&
+ TryComp(itemInHand, out var itemProtectComp)
+ && itemProtectComp.Slots == SlotFlags.NONE)
+ {
+ protectiveEntity = (itemInHand.Value, itemProtectComp);
+ }
+ }
+
+ // if comp is null, that means both the inventory and hands had nothing to protect them
+ // let's check if the entity itself has the protective comp, like with borgs
+ if (protectiveEntity.Comp == null &&
+ TryComp(args.User, out var protectiveComp))
+ {
+ protectiveEntity = (args.User, protectiveComp);
+ }
+
+ // if comp is NOT NULL that means they have damage protection!
+ if (protectiveEntity.Comp != null)
+ {
+ totalDamage = DamageSpecifier.ApplyModifierSet(totalDamage, protectiveEntity.Comp.DamageProtection);
+ }
+ }
+
+ totalDamage = _damageableSystem.TryChangeDamage(args.User, totalDamage, entity.Comp.IgnoreResistances, origin: entity);
+
+ if (totalDamage != null && totalDamage.AnyPositive())
+ {
+ _adminLogger.Add(LogType.Damaged, $"{ToPrettyString(args.User):user} injured themselves by attacking {ToPrettyString(entity):target} and received {totalDamage.GetTotal():damage} damage");
+ _audioSystem.PlayPredicted(entity.Comp.InteractSound, entity, args.User);
+
+ if (entity.Comp.PopupText != null)
+ _popupSystem.PopupClient(Loc.GetString(entity.Comp.PopupText), args.User, args.User);
+
+ }
+ }
+
+ public void SetIsDamageActiveTo(Entity entity, bool mode)
+ {
+ if (entity.Comp.IsDamageActive == mode)
+ return;
+
+ entity.Comp.IsDamageActive = mode;
+ Dirty(entity);
+ }
+}
diff --git a/Content.Shared/Damage/Systems/DamageOnInteractSystem.cs b/Content.Shared/Damage/Systems/DamageOnInteractSystem.cs
new file mode 100644
index 000000000000..4b50a1fd0e07
--- /dev/null
+++ b/Content.Shared/Damage/Systems/DamageOnInteractSystem.cs
@@ -0,0 +1,85 @@
+using Content.Shared.Administration.Logs;
+using Content.Shared.Damage.Components;
+using Content.Shared.Database;
+using Content.Shared.Interaction;
+using Content.Shared.Inventory;
+using Content.Shared.Popups;
+using Robust.Shared.Audio.Systems;
+using Robust.Shared.Network;
+using Robust.Shared.Timing;
+
+namespace Content.Shared.Damage.Systems;
+
+public sealed class DamageOnInteractSystem : EntitySystem
+{
+ [Dependency] private readonly ISharedAdminLogManager _adminLogger = default!;
+ [Dependency] private readonly IGameTiming _gameTiming = default!;
+ [Dependency] private readonly INetManager _net = default!;
+ [Dependency] private readonly DamageableSystem _damageableSystem = default!;
+ [Dependency] private readonly SharedAudioSystem _audioSystem = default!;
+ [Dependency] private readonly SharedPopupSystem _popupSystem = default!;
+ [Dependency] private readonly InventorySystem _inventorySystem = default!;
+
+ public override void Initialize()
+ {
+ base.Initialize();
+
+ SubscribeLocalEvent(OnHandInteract);
+ }
+
+ ///
+ /// Damages the user that interacts with the entity with an empty hand and
+ /// plays a sound or pops up text in response. If the user does not have
+ /// proper protection, the user will only be damaged and other interactions
+ /// will be cancelled.
+ ///
+ /// The entity being interacted with
+ /// Contains the user that interacted with the entity
+ private void OnHandInteract(Entity entity, ref InteractHandEvent args)
+ {
+ if (!entity.Comp.IsDamageActive)
+ return;
+
+ var totalDamage = entity.Comp.Damage;
+
+ if (!entity.Comp.IgnoreResistances)
+ {
+ // try to get damage on interact protection from either the inventory slots of the entity
+ _inventorySystem.TryGetInventoryEntity(args.User, out var protectiveEntity);
+
+ // or checking the entity for the comp itself if the inventory didn't work
+ if (protectiveEntity.Comp == null && TryComp(args.User, out var protectiveComp))
+ {
+ protectiveEntity = (args.User, protectiveComp);
+ }
+
+ // if protectiveComp isn't null after all that, it means the user has protection,
+ // so let's calculate how much they resist
+ if (protectiveEntity.Comp != null)
+ {
+ totalDamage = DamageSpecifier.ApplyModifierSet(totalDamage, protectiveEntity.Comp.DamageProtection);
+ }
+ }
+
+ totalDamage = _damageableSystem.TryChangeDamage(args.User, totalDamage, origin: args.Target);
+
+ if (totalDamage != null && totalDamage.AnyPositive())
+ {
+ args.Handled = true;
+ _adminLogger.Add(LogType.Damaged, $"{ToPrettyString(args.User):user} injured their hand by interacting with {ToPrettyString(args.Target):target} and received {totalDamage.GetTotal():damage} damage");
+ _audioSystem.PlayPredicted(entity.Comp.InteractSound, args.Target, args.User);
+
+ if (entity.Comp.PopupText != null)
+ _popupSystem.PopupClient(Loc.GetString(entity.Comp.PopupText), args.User, args.User);
+ }
+ }
+
+ public void SetIsDamageActiveTo(Entity entity, bool mode)
+ {
+ if (entity.Comp.IsDamageActive == mode)
+ return;
+
+ entity.Comp.IsDamageActive = mode;
+ Dirty(entity);
+ }
+}
diff --git a/Content.Shared/Inventory/InventorySystem.Slots.cs b/Content.Shared/Inventory/InventorySystem.Slots.cs
index 228b788722ec..2522dd5d0a33 100644
--- a/Content.Shared/Inventory/InventorySystem.Slots.cs
+++ b/Content.Shared/Inventory/InventorySystem.Slots.cs
@@ -30,7 +30,7 @@ private void ShutdownSlots()
///
/// Tries to find an entity in the specified slot with the specified component.
///
- public bool TryGetInventoryEntity(Entity entity, out EntityUid targetUid)
+ public bool TryGetInventoryEntity(Entity entity, out Entity target)
where T : IComponent, IClothingSlots
{
if (TryGetContainerSlotEnumerator(entity.Owner, out var containerSlotEnumerator))
@@ -43,12 +43,12 @@ public bool TryGetInventoryEntity(Entity entity, out Ent
if ((((IClothingSlots) required).Slots & slot.SlotFlags) == 0x0)
continue;
- targetUid = item;
+ target = (item, required);
return true;
}
}
- targetUid = EntityUid.Invalid;
+ target = EntityUid.Invalid;
return false;
}
diff --git a/Resources/Prototypes/Entities/Clothing/Hands/base_clothinghands.yml b/Resources/Prototypes/Entities/Clothing/Hands/base_clothinghands.yml
index 02cf0ab6f67d..c1a53ccf6e5f 100644
--- a/Resources/Prototypes/Entities/Clothing/Hands/base_clothinghands.yml
+++ b/Resources/Prototypes/Entities/Clothing/Hands/base_clothinghands.yml
@@ -23,6 +23,10 @@
tags:
- ClothMade
- WhitelistChameleon
+ - type: DamageOnInteractProtection
+ damageProtection:
+ flatReductions:
+ Heat: 5 # the average lightbulb only does around four damage!
- type: entity
abstract: true
diff --git a/Resources/Prototypes/Entities/Clothing/Hands/colored.yml b/Resources/Prototypes/Entities/Clothing/Hands/colored.yml
index 0fa298b648bd..556442cee118 100644
--- a/Resources/Prototypes/Entities/Clothing/Hands/colored.yml
+++ b/Resources/Prototypes/Entities/Clothing/Hands/colored.yml
@@ -283,8 +283,6 @@
color: "#535353"
- type: Clothing
sprite: Clothing/Hands/Gloves/Color/black.rsi
- - type: GloveHeatResistance
- heatResistance: 1400
- type: Butcherable
butcheringType: Knife
spawned:
@@ -305,8 +303,6 @@
sprite: Clothing/Hands/Gloves/Color/yellow.rsi
- type: Clothing
sprite: Clothing/Hands/Gloves/Color/yellow.rsi
- - type: GloveHeatResistance
- heatResistance: 1400
- type: Butcherable
butcheringType: Knife
spawned:
@@ -323,9 +319,6 @@
name: budget insulated gloves
description: These gloves are cheap knockoffs of the coveted ones - no way this can end badly.
components:
- - type: GloveHeatResistance
- # can't take out lights using budgets
- heatResistance: 0
- type: RandomInsulation
# Why repeated numbers? So some numbers are more common, of course!
list:
diff --git a/Resources/Prototypes/Entities/Clothing/Hands/gloves.yml b/Resources/Prototypes/Entities/Clothing/Hands/gloves.yml
index f1d99884658a..53a165cd5716 100644
--- a/Resources/Prototypes/Entities/Clothing/Hands/gloves.yml
+++ b/Resources/Prototypes/Entities/Clothing/Hands/gloves.yml
@@ -103,8 +103,6 @@
sprite: Clothing/Hands/Gloves/captain.rsi
- type: Clothing
sprite: Clothing/Hands/Gloves/captain.rsi
- - type: GloveHeatResistance
- heatResistance: 1400
- type: Insulated
- type: Fiber
fiberMaterial: fibers-durathread
@@ -169,8 +167,6 @@
sprite: Clothing/Hands/Gloves/leather.rsi
- type: Clothing
sprite: Clothing/Hands/Gloves/leather.rsi
- - type: GloveHeatResistance
- heatResistance: 1400
- type: Fiber
fiberMaterial: fibers-leather
fiberColor: fibers-brown
@@ -225,8 +221,6 @@
enum.ToggleVisuals.Layer:
True: {state: icon-green}
False: {state: icon}
- - type: GloveHeatResistance
- heatResistance: 1400
- type: Insulated
- type: Fiber
fiberMaterial: fibers-nanomachines
@@ -270,8 +264,6 @@
sprite: Clothing/Hands/Gloves/combat.rsi
- type: Clothing
sprite: Clothing/Hands/Gloves/combat.rsi
- - type: GloveHeatResistance
- heatResistance: 1400
- type: Insulated
- type: Fiber
fiberMaterial: fibers-insulative
@@ -287,8 +279,6 @@
sprite: Clothing/Hands/Gloves/tacticalmaidgloves.rsi
- type: Clothing
sprite: Clothing/Hands/Gloves/tacticalmaidgloves.rsi
- - type: GloveHeatResistance
- heatResistance: 1400
- type: Insulated
- type: Fiber
fiberColor: fibers-black
@@ -324,6 +314,10 @@
- type: Fiber
fiberMaterial: fibers-synthetic
fiberColor: fibers-black
+ - type: DamageOnInteractProtection
+ damageProtection:
+ flatReductions:
+ Heat: 0 # no protection
- type: entity
parent: ClothingHandsBase
@@ -338,6 +332,10 @@
- type: Fiber
fiberMaterial: fibers-insulative
fiberColor: fibers-yellow
+ - type: DamageOnInteractProtection
+ damageProtection:
+ flatReductions:
+ Heat: 0 # no protection
- type: entity
parent: ClothingHandsButcherable
@@ -352,6 +350,10 @@
- type: Fiber
fiberMaterial: fibers-insulative
fiberColor: fibers-olive
+ - type: DamageOnInteractProtection
+ damageProtection:
+ flatReductions:
+ Heat: 0 # no protection
- type: entity
# Intentionally named after regular gloves, they're meant to be sneaky.
diff --git a/Resources/Prototypes/Entities/Clothing/OuterClothing/base_clothingouter.yml b/Resources/Prototypes/Entities/Clothing/OuterClothing/base_clothingouter.yml
index 7c264a596a0c..5df6adffec96 100644
--- a/Resources/Prototypes/Entities/Clothing/OuterClothing/base_clothingouter.yml
+++ b/Resources/Prototypes/Entities/Clothing/OuterClothing/base_clothingouter.yml
@@ -136,6 +136,11 @@
- WhitelistChameleon
- type: ClothingRequiredStepTriggerImmune
slots: WITHOUT_POCKET
+ - type: DamageOnInteractProtection
+ damageProtection:
+ flatReductions:
+ Heat: 10 # the average lightbulb only does around four damage!
+ slots: OUTERCLOTHING
- type: entity
abstract: true
@@ -156,6 +161,11 @@
size: Huge
- type: ClothingRequiredStepTriggerImmune
slots: WITHOUT_POCKET
+ - type: DamageOnInteractProtection
+ damageProtection:
+ flatReductions:
+ Heat: 10 # the average lightbulb only does around four damage!
+ slots: OUTERCLOTHING
- type: entity
parent: ClothingOuterBase
diff --git a/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml b/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml
index 2618207b7a90..6c73fd8f1167 100644
--- a/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml
+++ b/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml
@@ -222,6 +222,10 @@
guides:
- Cyborgs
- type: StepTriggerImmune
+ - type: DamageOnInteractProtection
+ damageProtection:
+ flatReductions:
+ Heat: 10 # capable of touching light bulbs and stoves without feeling pain!
- type: entity
abstract: true
diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/behonker.yml b/Resources/Prototypes/Entities/Mobs/NPCs/behonker.yml
index 6f9935d351d3..1db787a66d84 100644
--- a/Resources/Prototypes/Entities/Mobs/NPCs/behonker.yml
+++ b/Resources/Prototypes/Entities/Mobs/NPCs/behonker.yml
@@ -110,9 +110,6 @@
collection: BananiumHorn
params:
volume: 5
- anomalyContactDamage:
- types:
- Radiation: 10
- type: Input
context: "human"
- type: Bloodstream
@@ -158,9 +155,6 @@
suffix: "Ice"
components:
- type: Anomaly
- anomalyContactDamage:
- types:
- Cold: 10
- type: ExplosionAnomaly
supercriticalExplosion: Cryo
explosionTotalIntensity: 1000
diff --git a/Resources/Prototypes/Entities/Objects/Specific/Research/anomaly.yml b/Resources/Prototypes/Entities/Objects/Specific/Research/anomaly.yml
index 99f874406b42..929f509710ec 100644
--- a/Resources/Prototypes/Entities/Objects/Specific/Research/anomaly.yml
+++ b/Resources/Prototypes/Entities/Objects/Specific/Research/anomaly.yml
@@ -147,3 +147,10 @@
- type: ContainerContainer
containers:
core_slot: !type:ContainerSlot
+ - type: DamageOnAttackedProtection
+ damageProtection:
+ flatReductions:
+ Heat: 100
+ Cold: 100
+ Radiation: 100
+ slots: NONE
diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Melee/sword.yml b/Resources/Prototypes/Entities/Objects/Weapons/Melee/sword.yml
index 0bab2c828dec..838cde619faf 100644
--- a/Resources/Prototypes/Entities/Objects/Weapons/Melee/sword.yml
+++ b/Resources/Prototypes/Entities/Objects/Weapons/Melee/sword.yml
@@ -154,7 +154,7 @@
- type: DisarmMalus
- type: entity
- name: The Throngler
+ name: Throngler
parent: BaseSword
id: Throngler
description: Why would you make this?
@@ -180,3 +180,6 @@
size: Ginormous
sprite: Objects/Weapons/Melee/Throngler-in-hand.rsi
- type: DisarmMalus
+ - type: Grammar
+ attributes:
+ proper: true
diff --git a/Resources/Prototypes/Entities/Structures/Lighting/base_lighting.yml b/Resources/Prototypes/Entities/Structures/Lighting/base_lighting.yml
index 436eaa2697f0..f684ca3425a3 100644
--- a/Resources/Prototypes/Entities/Structures/Lighting/base_lighting.yml
+++ b/Resources/Prototypes/Entities/Structures/Lighting/base_lighting.yml
@@ -89,9 +89,6 @@
enabled: false
- type: PoweredLight
bulb: Tube
- damage:
- types:
- Heat: 2
- type: ContainerContainer
containers:
light_bulb: !type:ContainerSlot
@@ -117,6 +114,11 @@
on: base
broken: broken
burned: burned
+ - type: DamageOnInteract
+ damage:
+ types:
+ Heat: 2
+ popupText: powered-light-component-burn-hand
- type: entity
id: Poweredlight
@@ -130,15 +132,17 @@
enabled: true
- type: PoweredLight
hasLampOnSpawn: LightTube
- damage:
- types:
- Heat: 2
- type: AmbientOnPowered
- type: AmbientSound
volume: -15
range: 2
sound:
path: /Audio/Ambience/Objects/light_hum.ogg
+ - type: DamageOnInteract
+ damage:
+ types:
+ Heat: 2
+ popupText: powered-light-component-burn-hand
#LED lights
- type: entity
@@ -149,14 +153,16 @@
components:
- type: PoweredLight
hasLampOnSpawn: LedLightTube
- damage:
- types:
- Heat: 1 #LEDs don't get as hot
- type: PointLight
radius: 15
energy: 1
softness: 0.9
color: "#EEEEFF"
+ - type: DamageOnInteract
+ damage:
+ types:
+ Heat: 1 # LEDs don't get as hot
+ popupText: powered-light-component-burn-hand
- type: entity
parent: AlwaysPoweredWallLight
@@ -178,9 +184,11 @@
components:
- type: PoweredLight
hasLampOnSpawn: ExteriorLightTube
+ - type: DamageOnInteract
damage:
types:
- Heat: 4 #brighter light gets hotter
+ Heat: 4 # brighter light gets hotter
+ popupText: powered-light-component-burn-hand
- type: entity
parent: AlwaysPoweredWallLight
@@ -202,14 +210,16 @@
components:
- type: PoweredLight
hasLampOnSpawn: SodiumLightTube
- damage:
- types:
- Heat: 2
- type: PointLight
radius: 10
energy: 2.5
softness: 0.9
color: "#FFAF38"
+ - type: DamageOnInteract
+ damage:
+ types:
+ Heat: 2
+ popupText: powered-light-component-burn-hand
- type: entity
parent: AlwaysPoweredWallLight
@@ -289,9 +299,6 @@
light_bulb: !type:ContainerSlot
- type: PoweredLight
bulb: Bulb
- damage:
- types:
- Heat: 2
- type: ApcPowerReceiver
- type: ExtensionCableReceiver
- type: DeviceNetwork
@@ -312,6 +319,11 @@
- On
- Off
- Toggle
+ - type: DamageOnInteract
+ damage:
+ types:
+ Heat: 2
+ popupText: powered-light-component-burn-hand
- type: entity
id: PoweredLEDSmallLight
@@ -328,9 +340,11 @@
color: "#EEEEFF"
- type: PoweredLight
hasLampOnSpawn: LedLightBulb
+ - type: DamageOnInteract
damage:
types:
Heat: 1
+ popupText: powered-light-component-burn-hand
- type: entity
id: PoweredSmallLight
@@ -343,9 +357,11 @@
enabled: true
- type: PoweredLight
hasLampOnSpawn: LightBulb
+ - type: DamageOnInteract
damage:
types:
Heat: 2
+ popupText: powered-light-component-burn-hand
#Emergency Lights
- type: entity
@@ -398,14 +414,16 @@
components:
- type: PoweredLight
hasLampOnSpawn: LightTubeCrystalCyan
- damage:
- types:
- Heat: 2
- type: PointLight
radius: 8
energy: 3
softness: 0.5
color: "#47f8ff"
+ - type: DamageOnInteract
+ damage:
+ types:
+ Heat: 2
+ popupText: powered-light-component-burn-hand
- type: entity
id: AlwaysPoweredlightCyan
@@ -425,14 +443,16 @@
components:
- type: PoweredLight
hasLampOnSpawn: LightTubeCrystalBlue
- damage:
- types:
- Heat: 2
- type: PointLight
radius: 8
energy: 3
softness: 0.5
color: "#39a1ff"
+ - type: DamageOnInteract
+ damage:
+ types:
+ Heat: 2
+ popupText: powered-light-component-burn-hand
- type: entity
id: AlwaysPoweredlightBlue
@@ -452,14 +472,16 @@
components:
- type: PoweredLight
hasLampOnSpawn: LightTubeCrystalPink
- damage:
- types:
- Heat: 2
- type: PointLight
radius: 8
energy: 3
softness: 0.5
color: "#ff66cc"
+ - type: DamageOnInteract
+ damage:
+ types:
+ Heat: 2
+ popupText: powered-light-component-burn-hand
- type: entity
id: AlwaysPoweredlightPink
@@ -479,14 +501,16 @@
components:
- type: PoweredLight
hasLampOnSpawn: LightTubeCrystalOrange
- damage:
- types:
- Heat: 2
- type: PointLight
radius: 8
energy: 3
softness: 0.5
color: "#ff8227"
+ - type: DamageOnInteract
+ damage:
+ types:
+ Heat: 2
+ popupText: powered-light-component-burn-hand
- type: entity
id: AlwaysPoweredlightOrange
@@ -506,14 +530,16 @@
components:
- type: PoweredLight
hasLampOnSpawn: LightTubeCrystalRed
- damage:
- types:
- Heat: 2
- type: PointLight
radius: 8
energy: 3
softness: 0.5
color: "#fb4747"
+ - type: DamageOnInteract
+ damage:
+ types:
+ Heat: 2
+ popupText: powered-light-component-burn-hand
- type: entity
id: AlwaysPoweredlightRed
@@ -533,14 +559,16 @@
components:
- type: PoweredLight
hasLampOnSpawn: LightTubeCrystalGreen
- damage:
- types:
- Heat: 2
- type: PointLight
radius: 8
energy: 3
softness: 0.5
color: "#52ff39"
+ - type: DamageOnInteract
+ damage:
+ types:
+ Heat: 2
+ popupText: powered-light-component-burn-hand
- type: entity
id: AlwaysPoweredlightGreen
diff --git a/Resources/Prototypes/Entities/Structures/Lighting/ground_lighting.yml b/Resources/Prototypes/Entities/Structures/Lighting/ground_lighting.yml
index 2afde4ef3fce..0771cb71bc06 100644
--- a/Resources/Prototypes/Entities/Structures/Lighting/ground_lighting.yml
+++ b/Resources/Prototypes/Entities/Structures/Lighting/ground_lighting.yml
@@ -77,9 +77,6 @@
enabled: false
- type: PoweredLight
bulb: Tube
- damage:
- types:
- Heat: 2
- type: ContainerContainer
containers:
light_bulb: !type:ContainerSlot
@@ -108,6 +105,11 @@
on: base
broken: broken
burned: burned
+ - type: DamageOnInteract
+ damage:
+ types:
+ Heat: 2
+ popupText: powered-light-component-burn-hand
- type: entity
id: PoweredLightPostSmall
@@ -122,9 +124,6 @@
enabled: true
- type: PoweredLight
hasLampOnSpawn: LightTube
- damage:
- types:
- Heat: 2
- type: StaticPrice
price: 25
- type: AmbientOnPowered
@@ -133,6 +132,11 @@
range: 3
sound:
path: /Audio/Ambience/Objects/light_hum.ogg
+ - type: DamageOnInteract
+ damage:
+ types:
+ Heat: 2
+ popupText: powered-light-component-burn-hand
- type: entity
id: PoweredLEDLightPostSmall
@@ -151,9 +155,6 @@
color: "#EEEEFF"
- type: PoweredLight
hasLampOnSpawn: LedLightTube
- damage:
- types:
- Heat: 1
- type: StaticPrice
price: 25
- type: AmbientOnPowered
@@ -162,3 +163,8 @@
range: 3
sound:
path: /Audio/Ambience/Objects/light_hum.ogg
+ - type: DamageOnInteract
+ damage:
+ types:
+ Heat: 1
+ popupText: powered-light-component-burn-hand
diff --git a/Resources/Prototypes/Entities/Structures/Lighting/strobe_lighting.yml b/Resources/Prototypes/Entities/Structures/Lighting/strobe_lighting.yml
index 72f543964699..50e24eab73d2 100644
--- a/Resources/Prototypes/Entities/Structures/Lighting/strobe_lighting.yml
+++ b/Resources/Prototypes/Entities/Structures/Lighting/strobe_lighting.yml
@@ -87,9 +87,6 @@
- type: PoweredLight
bulb: Bulb
on: false
- damage:
- types:
- Heat: 2
- type: ApcPowerReceiver
- type: ExtensionCableReceiver
- type: DeviceNetwork
@@ -113,6 +110,11 @@
- type: Construction
graph: LightFixture
node: strobeLight
+ - type: DamageOnInteract
+ damage:
+ types:
+ Heat: 2
+ popupText: powered-light-component-burn-hand
- type: entity
id: PoweredStrobeLightPolice
diff --git a/Resources/Prototypes/Entities/Structures/Specific/Anomaly/anomalies.yml b/Resources/Prototypes/Entities/Structures/Specific/Anomaly/anomalies.yml
index 8bca49c4e5fe..a16aaaabbbe3 100644
--- a/Resources/Prototypes/Entities/Structures/Specific/Anomaly/anomalies.yml
+++ b/Resources/Prototypes/Entities/Structures/Specific/Anomaly/anomalies.yml
@@ -9,9 +9,6 @@
collection: RadiationPulse
params:
volume: 5
- anomalyContactDamage:
- types:
- Radiation: 10
- type: AmbientSound
range: 5
volume: -5
@@ -51,6 +48,15 @@
- type: SecretDataAnomaly
randomStartSecretMin: 0
randomStartSecretMax: 2
+ - type: DamageOnInteract
+ damage:
+ types:
+ Radiation: 10
+ popupText: anomaly-component-contact-damage
+ - type: DamageOnAttacked
+ damage:
+ types:
+ Radiation: 10
- type: entity
id: AnomalyPyroclastic
@@ -99,6 +105,15 @@
- type: IgniteOnCollide
fixtureId: fix1
fireStacks: 1
+ - type: DamageOnInteract
+ damage:
+ types:
+ Heat: 10
+ popupText: anomaly-component-contact-damage
+ - type: DamageOnAttacked
+ damage:
+ types:
+ Heat: 10
- type: entity
id: AnomalyGravity
@@ -294,9 +309,6 @@
collection: RadiationPulse
params:
volume: 5
- anomalyContactDamage:
- types:
- Radiation: 10
- type: entity
id: AnomalyIce
@@ -319,9 +331,6 @@
- type: Anomaly
corePrototype: AnomalyCoreIce
coreInertPrototype: AnomalyCoreIceInert
- anomalyContactDamage:
- types:
- Cold: 10
- type: ExplosionAnomaly
supercriticalExplosion: Cryo
explosionTotalIntensity: 300
@@ -345,6 +354,15 @@
releasedGas: 8 # Frezon. Please replace if there is a better way to specify this
releaseOnMaxSeverity: true
spawnRadius: 0
+ - type: DamageOnInteract
+ damage:
+ types:
+ Cold: 10
+ popupText: anomaly-component-contact-damage
+ - type: DamageOnAttacked
+ damage:
+ types:
+ Cold: 10
- type: entity
id: AnomalyRockBase
@@ -609,9 +627,6 @@
coreInertPrototype: AnomalyCoreFloraInert
minPulseLength: 60
maxPulseLength: 120
- anomalyContactDamage:
- types:
- Slash: 0
- type: TileSpawnAnomaly
entries:
- settings:
@@ -715,9 +730,6 @@
coreInertPrototype: AnomalyCoreLiquidInert
minPulseLength: 60
maxPulseLength: 120
- anomalyContactDamage:
- types:
- Slash: 1
- type: EntitySpawnAnomaly
entries:
- settings:
@@ -829,9 +841,6 @@
coreInertPrototype: AnomalyCoreShadowInert
minPulseLength: 60
maxPulseLength: 120
- anomalyContactDamage:
- types:
- Cold: 10
animationTime: 4
offset: "-0.1,0.1"
- type: EntitySpawnAnomaly
@@ -857,3 +866,12 @@
- type: Tag
tags:
- SpookyFog
+ - type: DamageOnInteract
+ damage:
+ types:
+ Cold: 10
+ popupText: anomaly-component-contact-damage
+ - type: DamageOnAttacked
+ damage:
+ types:
+ Cold: 10
diff --git a/Resources/Prototypes/Entities/Structures/Wallmounts/service_light.yml b/Resources/Prototypes/Entities/Structures/Wallmounts/service_light.yml
index b8aaa60c3723..baadcb67dbf8 100644
--- a/Resources/Prototypes/Entities/Structures/Wallmounts/service_light.yml
+++ b/Resources/Prototypes/Entities/Structures/Wallmounts/service_light.yml
@@ -24,6 +24,8 @@
bulb: Bulb
on: false
hasLampOnSpawn: ServiceLightBulb
+ - type: DamageOnInteract
damage:
types:
Heat: 5
+ popupText: powered-light-component-burn-hand