--- /dev/null
+using Content.Shared.Damage.Systems;
+using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Dictionary;
+using Robust.Shared.GameStates;
+
+namespace Content.Shared.Damage.Components;
+
+/// <summary>
+/// Component that provides entities with stamina resistance.
+/// By default this is applied when worn, but to solely protect the entity itself and
+/// not the wearer use <c>worn: false</c>.
+/// </summary>
+/// <remarks>
+/// This is desirable over just using damage modifier sets, given that equipment like bomb-suits need to
+/// significantly reduce the damage, but shouldn't be silly overpowered in regular combat.
+/// </remarks>
+[NetworkedComponent, RegisterComponent, AutoGenerateComponentState]
+public sealed partial class StaminaResistanceComponent : Component
+{
+ /// <summary>
+ /// The stamina resistance coefficient, This fraction is multiplied into the total resistance.
+ /// </summary>
+ [DataField, AutoNetworkedField]
+ public float DamageCoefficient = 1;
+
+ /// <summary>
+ /// When true, resistances will be applied to the entity wearing this item.
+ /// When false, only this entity will get the resistance.
+ /// </summary>
+ [DataField]
+ public bool Worn = true;
+
+ /// <summary>
+ /// Examine string for stamina resistance.
+ /// Passed <c>value</c> from 0 to 100.
+ /// </summary>
+ [DataField]
+ public LocId Examine = "stamina-resistance-coefficient-value";
+}
--- /dev/null
+using Content.Shared.Inventory;
+
+namespace Content.Shared.Damage.Events;
+
+/// <summary>
+/// Raised before stamina damage is dealt to allow other systems to cancel or modify it.
+/// </summary>
+[ByRefEvent]
+public record struct BeforeStaminaDamageEvent(float Value, bool Cancelled = false) : IInventoryRelayEvent
+{
+ SlotFlags IInventoryRelayEvent.TargetSlots => ~SlotFlags.POCKET;
+}
using Content.Shared.Damage.Components;
+using Content.Shared.Damage.Events;
using Content.Shared.Rejuvenate;
using Content.Shared.Slippery;
using Content.Shared.StatusEffect;
--- /dev/null
+using Content.Shared.Armor;
+using Content.Shared.Damage.Components;
+using Content.Shared.Damage.Events;
+using Content.Shared.Inventory;
+
+namespace Content.Shared.Damage.Systems;
+
+public sealed partial class StaminaSystem
+{
+ private void InitializeResistance()
+ {
+ SubscribeLocalEvent<StaminaResistanceComponent, BeforeStaminaDamageEvent>(OnGetResistance);
+ SubscribeLocalEvent<StaminaResistanceComponent, InventoryRelayedEvent<BeforeStaminaDamageEvent>>(RelayedResistance);
+ SubscribeLocalEvent<StaminaResistanceComponent, ArmorExamineEvent>(OnArmorExamine);
+ }
+
+ private void OnGetResistance(Entity<StaminaResistanceComponent> ent, ref BeforeStaminaDamageEvent args)
+ {
+ args.Value *= ent.Comp.DamageCoefficient;
+ }
+
+ private void RelayedResistance(Entity<StaminaResistanceComponent> ent, ref InventoryRelayedEvent<BeforeStaminaDamageEvent> args)
+ {
+ if (ent.Comp.Worn)
+ OnGetResistance(ent, ref args.Args);
+ }
+
+ private void OnArmorExamine(Entity<StaminaResistanceComponent> ent, ref ArmorExamineEvent args)
+ {
+ var value = MathF.Round((1f - ent.Comp.DamageCoefficient) * 100, 1);
+
+ if (value == 0)
+ return;
+
+ args.Msg.PushNewline();
+ args.Msg.AddMarkupOrThrow(Loc.GetString(ent.Comp.Examine, ("value", value)));
+ }
+}
base.Initialize();
InitializeModifier();
+ InitializeResistance();
SubscribeLocalEvent<StaminaComponent, ComponentStartup>(OnStartup);
SubscribeLocalEvent<StaminaComponent, ComponentShutdown>(OnShutdown);
}
public void TakeStaminaDamage(EntityUid uid, float value, StaminaComponent? component = null,
- EntityUid? source = null, EntityUid? with = null, bool visual = true, SoundSpecifier? sound = null)
+ EntityUid? source = null, EntityUid? with = null, bool visual = true, SoundSpecifier? sound = null, bool ignoreResist = false)
{
if (!Resolve(uid, ref component, false))
return;
if (ev.Cancelled)
return;
+ // Allow stamina resistance to be applied.
+ if (!ignoreResist)
+ {
+ value = ev.Value;
+ }
+
value = UniversalStaminaDamageModifier * value;
// Have we already reached the point of max stamina damage?
_adminLogger.Add(LogType.Stamina, LogImpact.Low, $"{ToPrettyString(uid):user} recovered from stamina crit");
}
}
-
-/// <summary>
-/// Raised before stamina damage is dealt to allow other systems to cancel it.
-/// </summary>
-[ByRefEvent]
-public record struct BeforeStaminaDamageEvent(float Value, bool Cancelled = false);
using Content.Shared.Chemistry.Hypospray.Events;
using Content.Shared.Climbing.Events;
using Content.Shared.Damage;
+using Content.Shared.Damage.Events;
using Content.Shared.Electrocution;
using Content.Shared.Explosion;
using Content.Shared.Eye.Blinding.Systems;
SubscribeLocalEvent<InventoryComponent, CoefficientQueryEvent>(RelayInventoryEvent);
// by-ref events
+ SubscribeLocalEvent<InventoryComponent, BeforeStaminaDamageEvent>(RefRelayInventoryEvent);
SubscribeLocalEvent<InventoryComponent, GetExplosionResistanceEvent>(RefRelayInventoryEvent);
SubscribeLocalEvent<InventoryComponent, IsWeightlessEvent>(RefRelayInventoryEvent);
SubscribeLocalEvent<InventoryComponent, GetSpeedModifierContactCapEvent>(RefRelayInventoryEvent);
melee-stamina = Not enough stamina
slow-on-damage-modifier-examine = Slowness from injuries is reduced by [color=yellow]{$mod}%[/color]
+stamina-resistance-coefficient-value = - [color=lightyellow]Stamina[/color] damage reduced by [color=lightblue]{$value}%[/color].
Caustic: 0.5
- type: ExplosionResistance
damageCoefficient: 0.35
+ #- type: StaminaResistance
+ # damageCoefficient: 0.45
- type: ClothingSpeedModifier
walkModifier: 0.9
sprintModifier: 0.9
lowPressureMultiplier: 1000
- type: ExplosionResistance
damageCoefficient: 0.5
+ #- type: StaminaResistance
+ # damageCoefficient: 0.75
- type: Armor
modifiers:
coefficients:
damageCoefficient: 0.2
- type: FireProtection
reduction: 0.8
+ #- type: StaminaResistance
+ # damageCoefficient: 0.6
- type: Armor
modifiers:
coefficients:
lowPressureMultiplier: 1000
- type: ExplosionResistance
damageCoefficient: 0.5
+ #- type: StaminaResistance
+ # damageCoefficient: 0.6
- type: Armor
modifiers:
coefficients:
lowPressureMultiplier: 1000
- type: ExplosionResistance
damageCoefficient: 0.3
+ #- type: StaminaResistance # Should not have stamina resistance, this is purely so people know it was not forgotten.
+ # damageCoefficient: 0.99
- type: Armor
modifiers:
coefficients:
damageCoefficient: 0.2
- type: FireProtection
reduction: 0.8
+ - type: StaminaResistance
+ damageCoefficient: 0.15 # Needs 21 hits with a disabler to stun :godo:
- type: Armor
modifiers:
coefficients: