using Content.Server.Atmos.Components;
+using Content.Server.Damage.Components;
using Content.Shared.Damage;
-using Content.Shared.GameTicking;
+using Content.Shared.Damage.Systems;
+using Content.Shared.FixedPoint;
+using Content.Shared.Rejuvenate;
+using Content.Shared.StatusEffect;
using JetBrains.Annotations;
namespace Content.Server.Damage.Systems
[UsedImplicitly]
public sealed class GodmodeSystem : EntitySystem
{
- private readonly Dictionary<EntityUid, OldEntityInformation> _entities = new();
- [Dependency] private readonly DamageableSystem _damageableSystem = default!;
+ [Dependency] private readonly DamageableSystem _damageable = default!;
public override void Initialize()
{
base.Initialize();
- SubscribeLocalEvent<RoundRestartCleanupEvent>(Reset);
+ SubscribeLocalEvent<GodmodeComponent, BeforeDamageChangedEvent>(OnBeforeDamageChanged);
+ SubscribeLocalEvent<GodmodeComponent, BeforeStatusEffectAddedEvent>(OnBeforeStatusEffect);
+ SubscribeLocalEvent<GodmodeComponent, BeforeStaminaDamageEvent>(OnBeforeStaminaDamage);
}
- public void Reset(RoundRestartCleanupEvent ev)
+ private void OnBeforeDamageChanged(EntityUid uid, GodmodeComponent component, ref BeforeDamageChangedEvent args)
{
- _entities.Clear();
+ args.Cancelled = true;
}
- public bool EnableGodmode(EntityUid entity)
+ private void OnBeforeStatusEffect(EntityUid uid, GodmodeComponent component, ref BeforeStatusEffectAddedEvent args)
{
- if (_entities.ContainsKey(entity))
- {
- return false;
- }
+ args.Cancelled = true;
+ }
+
+ private void OnBeforeStaminaDamage(EntityUid uid, GodmodeComponent component, ref BeforeStaminaDamageEvent args)
+ {
+ args.Cancelled = true;
+ }
- _entities[entity] = new OldEntityInformation(entity, EntityManager);
+ public void EnableGodmode(EntityUid uid)
+ {
+ var godmode = EnsureComp<GodmodeComponent>(uid);
- if (EntityManager.TryGetComponent(entity, out MovedByPressureComponent? moved))
+ if (TryComp<MovedByPressureComponent>(uid, out var moved))
{
+ godmode.WasMovedByPressure = moved.Enabled;
moved.Enabled = false;
}
- if (EntityManager.TryGetComponent(entity, out DamageableComponent? damageable))
+ if (TryComp<DamageableComponent>(uid, out var damageable))
{
- _damageableSystem.SetDamage(entity, damageable, new DamageSpecifier());
+ godmode.OldDamage = new(damageable.Damage);
}
- return true;
+ // Rejuv to cover other stuff
+ RaiseLocalEvent(uid, new RejuvenateEvent());
}
- public bool HasGodmode(EntityUid entity)
+ public void DisableGodmode(EntityUid uid)
{
- return _entities.ContainsKey(entity);
- }
+ if (!TryComp<GodmodeComponent>(uid, out var godmode))
+ return;
- public bool DisableGodmode(EntityUid entity)
- {
- if (!_entities.Remove(entity, out var old))
+ if (TryComp<MovedByPressureComponent>(uid, out var moved))
{
- return false;
+ moved.Enabled = godmode.WasMovedByPressure;
}
- if (EntityManager.TryGetComponent(entity, out MovedByPressureComponent? moved))
- {
- moved.Enabled = old.MovedByPressure;
- }
+ if (!TryComp<DamageableComponent>(uid, out var damageable))
+ return;
- if (EntityManager.TryGetComponent(entity, out DamageableComponent? damageable))
+ if (godmode.OldDamage != null)
{
- if (old.Damage != null)
- {
- _damageableSystem.SetDamage(entity, damageable, old.Damage);
- }
+ _damageable.SetDamage(uid, damageable, godmode.OldDamage);
}
-
- return true;
}
/// <summary>
/// Toggles godmode for a given entity.
/// </summary>
- /// <param name="entity">The entity to toggle godmode for.</param>
+ /// <param name="uid">The entity to toggle godmode for.</param>
/// <returns>true if enabled, false if disabled.</returns>
- public bool ToggleGodmode(EntityUid entity)
+ public bool ToggleGodmode(EntityUid uid)
{
- if (HasGodmode(entity))
+ if (HasComp<GodmodeComponent>(uid))
{
- DisableGodmode(entity);
+ DisableGodmode(uid);
return false;
}
- else
- {
- EnableGodmode(entity);
- return true;
- }
- }
- public sealed class OldEntityInformation
- {
- public OldEntityInformation(EntityUid entity, IEntityManager entityManager)
- {
- Entity = entity;
- MovedByPressure = entityManager.HasComponent<MovedByPressureComponent>(entity);
-
- if (entityManager.TryGetComponent(entity, out DamageableComponent? damageable))
- {
- Damage = damageable.Damage;
- }
- }
-
- public EntityUid Entity { get; }
-
- public bool MovedByPressure { get; }
-
- public DamageSpecifier? Damage { get; }
+ EnableGodmode(uid);
+ return true;
}
}
}
using Content.Shared.Database;
using Content.Shared.IdentityManagement;
using Content.Shared.Popups;
+using Content.Shared.Rejuvenate;
using Content.Shared.Rounding;
using Content.Shared.Stunnable;
using Content.Shared.Weapons.Melee.Events;
SubscribeLocalEvent<StaminaComponent, ComponentGetState>(OnStamGetState);
SubscribeLocalEvent<StaminaComponent, ComponentHandleState>(OnStamHandleState);
SubscribeLocalEvent<StaminaComponent, DisarmedEvent>(OnDisarmed);
+ SubscribeLocalEvent<StaminaComponent, RejuvenateEvent>(OnRejuvenate);
SubscribeLocalEvent<StaminaDamageOnCollideComponent, StartCollideEvent>(OnCollide);
SubscribeLocalEvent<StaminaDamageOnHitComponent, MeleeHitEvent>(OnHit);
}
return MathF.Max(0f, component.StaminaDamage - MathF.Max(0f, (float) (curTime - (component.NextUpdate + pauseTime)).TotalSeconds * component.Decay));
}
+ private void OnRejuvenate(EntityUid uid, StaminaComponent component, RejuvenateEvent args)
+ {
+ if (component.StaminaDamage >= component.CritThreshold)
+ {
+ ExitStamCrit(uid, component);
+ }
+
+ component.StaminaDamage = 0;
+ RemComp<ActiveStaminaComponent>(uid);
+ Dirty(component);
+ }
+
private void OnDisarmed(EntityUid uid, StaminaComponent component, DisarmedEvent args)
{
if (args.Handled || !_random.Prob(args.PushProbability))
public void TakeStaminaDamage(EntityUid uid, float value, StaminaComponent? component = null, EntityUid? source = null, EntityUid? with = null)
{
- if (!Resolve(uid, ref component, false) || component.Critical)
+ if (!Resolve(uid, ref component, false))
+ return;
+
+ var ev = new BeforeStaminaDamageEvent(value);
+ RaiseLocalEvent(uid, ref ev);
+ if (ev.Cancelled)
+ return;
+
+ // Have we already reached the point of max stamina damage?
+ if (component.Critical)
return;
var oldDamage = component.StaminaDamage;
public float CritThreshold;
public TimeSpan LastUpdate;
}
+
}
+
+/// <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);