public float StaminaDamage;
/// <summary>
- /// How much stamina damage is required to enter stam crit.
+ /// The base stamina the entity requires to enter stam crit. Should rarely if ever be modified outside of yaml.
/// </summary>
- [ViewVariables(VVAccess.ReadWrite), DataField, AutoNetworkedField]
+ [DataField, AutoNetworkedField]
+ public float BaseCritThreshold = 100f;
+
+ /// <summary>
+ /// Modified crit threshold for when an entity should enter stamcrit.
+ /// </summary>
+ [ViewVariables, AutoNetworkedField]
public float CritThreshold = 100f;
/// <summary>
/// Multiplies the entity's <see cref="StaminaComponent.StaminaDamage"/> by the <see cref="Modifier"/>.
/// </summary>
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState, Access(typeof(SharedStaminaSystem))]
-public sealed partial class StaminaModifierComponent : Component
+public sealed partial class StaminaModifierStatusEffectComponent : Component
{
/// <summary>
/// What to multiply max stamina by.
--- /dev/null
+using Content.Shared.Damage.Components;
+
+namespace Content.Shared.Damage.Events;
+
+/// <summary>
+/// Raised whenever the <see cref="StaminaComponent.CritThreshold"/> needs to be refreshed.
+/// </summary>
+[ByRefEvent]
+public record struct RefreshStaminaCritThresholdEvent
+{
+ public float ThresholdValue = 100f;
+ public float Modifier = 1f;
+
+ public RefreshStaminaCritThresholdEvent(float thresholdValue)
+ {
+ ThresholdValue = thresholdValue;
+ }
+}
using Content.Shared.Damage.Components;
+using Content.Shared.Damage.Events;
+using Content.Shared.StatusEffectNew;
namespace Content.Shared.Damage.Systems;
{
private void InitializeModifier()
{
- SubscribeLocalEvent<StaminaModifierComponent, ComponentStartup>(OnModifierStartup);
- SubscribeLocalEvent<StaminaModifierComponent, ComponentShutdown>(OnModifierShutdown);
+ SubscribeLocalEvent<StaminaModifierStatusEffectComponent, StatusEffectAppliedEvent>(OnEffectApplied);
+ SubscribeLocalEvent<StaminaModifierStatusEffectComponent, StatusEffectRemovedEvent>(OnEffectRemoved);
+ SubscribeLocalEvent<StaminaModifierStatusEffectComponent, StatusEffectRelayedEvent<RefreshStaminaCritThresholdEvent>>(OnRefreshCritThreshold);
}
- private void OnModifierStartup(EntityUid uid, StaminaModifierComponent comp, ComponentStartup args)
+ private void OnEffectApplied(Entity<StaminaModifierStatusEffectComponent> ent, ref StatusEffectAppliedEvent args)
{
- if (!TryComp<StaminaComponent>(uid, out var stamina))
- return;
-
- stamina.CritThreshold *= comp.Modifier;
+ RefreshStaminaCritThreshold(args.Target);
}
- private void OnModifierShutdown(EntityUid uid, StaminaModifierComponent comp, ComponentShutdown args)
+ private void OnEffectRemoved(Entity<StaminaModifierStatusEffectComponent> ent, ref StatusEffectRemovedEvent args)
{
- if (!TryComp<StaminaComponent>(uid, out var stamina))
- return;
-
- stamina.CritThreshold /= comp.Modifier;
+ RefreshStaminaCritThreshold(args.Target);
}
- /// <summary>
- /// Change the stamina modifier for an entity.
- /// If it has <see cref="StaminaComponent"/> it will also be updated.
- /// </summary>
- public void SetModifier(EntityUid uid, float modifier, StaminaComponent? stamina = null, StaminaModifierComponent? comp = null)
+ private void OnRefreshCritThreshold(Entity<StaminaModifierStatusEffectComponent> ent, ref StatusEffectRelayedEvent<RefreshStaminaCritThresholdEvent> args)
{
- if (!Resolve(uid, ref comp))
- return;
-
- var old = comp.Modifier;
+ var evArgs = args.Args;
+ evArgs.Modifier = Math.Max(ent.Comp.Modifier, evArgs.Modifier); // We only pick the highest value, to avoid stacking different status effects.
+ args.Args = evArgs;
+ }
- if (old.Equals(modifier))
+ public void RefreshStaminaCritThreshold(Entity<StaminaComponent?> entity)
+ {
+ if (!Resolve(entity, ref entity.Comp))
return;
- comp.Modifier = modifier;
- Dirty(uid, comp);
+ var ev = new RefreshStaminaCritThresholdEvent(entity.Comp.BaseCritThreshold);
+ RaiseLocalEvent(entity, ref ev);
- if (Resolve(uid, ref stamina, false))
- {
- // scale to the new threshold, act as if it was removed then added
- stamina.CritThreshold *= modifier / old;
- }
+ entity.Comp.CritThreshold = ev.ThresholdValue * ev.Modifier;
}
}
private void OnStartup(Entity<StaminaComponent> entity, ref ComponentStartup args)
{
+ // Set the base threshold here since ModifiedCritThreshold can't be modified via yaml.
+ entity.Comp.CritThreshold = entity.Comp.BaseCritThreshold;
+
UpdateStaminaVisuals(entity);
}
SubscribeLocalEvent<StatusEffectContainerComponent, StandUpAttemptEvent>(RefRelayStatusEffectEvent);
SubscribeLocalEvent<StatusEffectContainerComponent, StunEndAttemptEvent>(RefRelayStatusEffectEvent);
+ SubscribeLocalEvent<StatusEffectContainerComponent, RefreshStaminaCritThresholdEvent>(RefRelayStatusEffectEvent);
SubscribeLocalEvent<StatusEffectContainerComponent, BeforeForceSayEvent>(RelayStatusEffectEvent);
SubscribeLocalEvent<StatusEffectContainerComponent, BeforeAlertSeverityCheckEvent>(RelayStatusEffectEvent);
0: Alive
10: Dead
- type: Stamina
- critThreshold: 10
+ baseCritThreshold: 10
animationThreshold: 1
- type: DamageStateVisuals
states:
types:
Piercing: 0
- type: Bloodstream
- bloodReferenceSolution:
+ bloodReferenceSolution:
reagents:
- ReagentId: Blood
Quantity: 50
baseWalkSpeed: 2.5
baseSprintSpeed: 3.5
- type: Stamina
- critThreshold: 100
+ baseCritThreshold: 100
- type: DamageStateVisuals
states:
Alive:
0: Alive
82: Dead # Might seem random, but this brings up the hits to kill with a crusher mark to 3
- type: Stamina
- critThreshold: 150
+ baseCritThreshold: 150
- type: DamageStateVisuals
states:
Alive:
0: Alive
120: Dead
- type: Stamina
- critThreshold: 120
+ baseCritThreshold: 120
- type: Destructible
thresholds:
- trigger:
0: Alive
75: Dead
- type: Stamina
- critThreshold: 50
+ baseCritThreshold: 50
animationThreshold: 25
- type: Butcherable
spawned:
0: Alive
75: Dead
- type: Stamina
- critThreshold: 50
+ baseCritThreshold: 50
animationThreshold: 25
- type: Butcherable
spawned:
allowed:
- Corporeal
- Electrocution
- - StaminaModifier
- type: Fixtures
fixtures:
fix1:
- !type:GibBehavior
recursive: false
- type: Stamina
- critThreshold: 60
+ baseCritThreshold: 60
- type: MeleeWeapon
soundHit:
path: /Audio/Weapons/bladeslice.ogg
baseWalkSpeed : 3
baseSprintSpeed : 4
- type: Stamina
- critThreshold: 120
+ baseCritThreshold: 120
- type: Destructible
thresholds:
- trigger:
- Electrocution
- TemporaryBlindness
- Pacified
- - StaminaModifier
- Flashed
- RadiationProtection
- Adrenaline
0: Alive
80: Dead
- type: Stamina
- critThreshold: 150
+ baseCritThreshold: 150
- type: MovementAlwaysTouching
- type: Bloodstream
bloodReferenceSolution:
Dead:
Base: kangaroo-space-dead
- type: Stamina
- critThreshold: 180
+ baseCritThreshold: 180
- type: Inventory
speciesId: kangaroo
templateId: spacekangaroo
0: Alive
45: Dead
- type: Stamina
- critThreshold: 150
+ baseCritThreshold: 150
- type: DamageStateVisuals
states:
Alive:
0: Alive
45: Dead
- type: Stamina
- critThreshold: 150
+ baseCritThreshold: 150
- type: DamageStateVisuals
states:
Alive:
- !type:GibBehavior
recursive: false
- type: Stamina
- critThreshold: 15
+ baseCritThreshold: 15
animationThreshold: 5
- type: MovementAlwaysTouching
- type: DamageStateVisuals
speedModifierThresholds:
25: 0.5
- type: Stamina
- critThreshold: 200
+ baseCritThreshold: 200
- type: Bloodstream
bloodReferenceSolution:
reagents:
0: Alive
100: Dead
- type: Stamina
- critThreshold: 300
+ baseCritThreshold: 300
- type: SlowOnDamage
speedModifierThresholds:
50: 0.7
- type: ComplexInteraction
- type: MobState
- type: Stamina
- critThreshold: 200
+ baseCritThreshold: 200
- type: Bloodstream
bloodReferenceSolution:
reagents:
- Muted
- TemporaryBlindness
- Pacified
- - StaminaModifier
- Flashed
- RadiationProtection
- Adrenaline
parent: [ PainNumbnessTraitStatusEffect, MobStatusEffectDebuff ]
id: StatusEffectPainNumbness
name: pain numbness
+
+- type: entity
+ parent: MobStatusEffectBase
+ id: StaminaModifierStatusEffect
+ components:
+ - type: StatusEffect
+ whitelist:
+ components:
+ - Stamina
+ - type: StaminaModifierStatusEffect
+
+- type: entity
+ parent: StaminaModifierStatusEffect
+ name: 2x max stamina
+ id: StatusEffectDesoxyStamina
+
+- type: entity
+ parent: StaminaModifierStatusEffect
+ id: StatusEffectStimulantsStamina
+ name: 1.5x max stamina
+ components:
+ - type: StaminaModifierStatusEffect
+ modifier: 1.5
- !type:MovementSpeedModifier
walkSpeedModifier: 1.20
sprintSpeedModifier: 1.20
- - !type:GenericStatusEffect
- key: StaminaModifier # You are on meth. You keep going.
- component: StaminaModifier
+ - !type:ModifyStatusEffect
+ effectProto: StatusEffectDesoxyStamina # You are on meth. You keep going.
time: 3
- !type:GenericStatusEffect
key: Adrenaline
- !type:MovementSpeedModifier
walkSpeedModifier: 1.25
sprintSpeedModifier: 1.25
+ - !type:ModifyStatusEffect
+ effectProto: StatusEffectStimulantsStamina # You are on meth. You keep going.
+ time: 3
- !type:ModifyStatusEffect
effectProto: StatusEffectStunned
time: 3.5
- type: statusEffect
id: RatvarianLanguage #Praise him
-- type: statusEffect
- id: StaminaModifier
-
- type: statusEffect
id: Flashed