Status effects fix. Refresh the status effect cooldown. (#5708)

This commit is contained in:
pointer-to-null
2021-12-07 09:18:07 +03:00
committed by GitHub
parent 4688c74d43
commit 090e74792c
26 changed files with 111 additions and 62 deletions

View File

@@ -73,7 +73,7 @@ namespace Content.IntegrationTests.Tests
Assert.That(inventory.TryGetSlotItem(Slots.INNERCLOTHING, out ItemComponent uniform)); Assert.That(inventory.TryGetSlotItem(Slots.INNERCLOTHING, out ItemComponent uniform));
Assert.That(uniform.Owner.Prototype != null && uniform.Owner.Prototype.ID == "InventoryJumpsuitJanitorDummy"); Assert.That(uniform.Owner.Prototype != null && uniform.Owner.Prototype.ID == "InventoryJumpsuitJanitorDummy");
EntitySystem.Get<StunSystem>().TryStun(human.Uid, TimeSpan.FromSeconds(1f)); EntitySystem.Get<StunSystem>().TryStun(human.Uid, TimeSpan.FromSeconds(1f), true);
// Since the mob is stunned, they can't equip this. // Since the mob is stunned, they can't equip this.
Assert.That(inventory.SpawnItemInSlot(Slots.IDCARD, "InventoryIDCardDummy", true), Is.False); Assert.That(inventory.SpawnItemInSlot(Slots.IDCARD, "InventoryIDCardDummy", true), Is.False);

View File

@@ -180,7 +180,7 @@ namespace Content.Server.Atmos.EntitySystems
flammable.Resisting = true; flammable.Resisting = true;
flammable.Owner.PopupMessage(Loc.GetString("flammable-component-resist-message")); flammable.Owner.PopupMessage(Loc.GetString("flammable-component-resist-message"));
_stunSystem.TryParalyze(uid, TimeSpan.FromSeconds(2f), alerts: alerts); _stunSystem.TryParalyze(uid, TimeSpan.FromSeconds(2f), true, alerts: alerts);
// TODO FLAMMABLE: Make this not use TimerComponent... // TODO FLAMMABLE: Make this not use TimerComponent...
flammable.Owner.SpawnTimer(2000, () => flammable.Owner.SpawnTimer(2000, () =>

View File

@@ -15,12 +15,17 @@ public class Electrocute : ReagentEffect
[DataField("electrocuteDamageScale")] public int ElectrocuteDamageScale = 5; [DataField("electrocuteDamageScale")] public int ElectrocuteDamageScale = 5;
/// <remarks>
/// true - refresh electrocute time, false - accumulate electrocute time
/// </remarks>
[DataField("refresh")] public bool Refresh = true;
public override bool ShouldLog => true; public override bool ShouldLog => true;
public override void Effect(ReagentEffectArgs args) public override void Effect(ReagentEffectArgs args)
{ {
EntitySystem.Get<ElectrocutionSystem>().TryDoElectrocution(args.SolutionEntity, null, EntitySystem.Get<ElectrocutionSystem>().TryDoElectrocution(args.SolutionEntity, null,
Math.Max((args.Quantity * ElectrocuteDamageScale).Int(), 1), TimeSpan.FromSeconds(ElectrocuteTime)); Math.Max((args.Quantity * ElectrocuteDamageScale).Int(), 1), TimeSpan.FromSeconds(ElectrocuteTime), Refresh);
args.Source?.RemoveReagent(args.Reagent.ID, args.Quantity); args.Source?.RemoveReagent(args.Reagent.ID, args.Quantity);
} }

View File

@@ -30,6 +30,12 @@ namespace Content.Server.Chemistry.ReagentEffects.StatusEffects
[DataField("time")] [DataField("time")]
public float Time = 2.0f; public float Time = 2.0f;
/// <remarks>
/// true - refresh status effect time, false - accumulate status effect time
/// </remarks>
[DataField("refresh")]
public bool Refresh = true;
/// <summary> /// <summary>
/// Should this effect add the status effect, remove time from it, or set its cooldown? /// Should this effect add the status effect, remove time from it, or set its cooldown?
/// </summary> /// </summary>
@@ -41,7 +47,7 @@ namespace Content.Server.Chemistry.ReagentEffects.StatusEffects
var statusSys = args.EntityManager.EntitySysManager.GetEntitySystem<StatusEffectsSystem>(); var statusSys = args.EntityManager.EntitySysManager.GetEntitySystem<StatusEffectsSystem>();
if (Type == StatusEffectMetabolismType.Add && Component != String.Empty) if (Type == StatusEffectMetabolismType.Add && Component != String.Empty)
{ {
statusSys.TryAddStatusEffect(args.SolutionEntity, Key, TimeSpan.FromSeconds(Time), Component); statusSys.TryAddStatusEffect(args.SolutionEntity, Key, TimeSpan.FromSeconds(Time), Refresh, Component);
} }
else if (Type == StatusEffectMetabolismType.Remove) else if (Type == StatusEffectMetabolismType.Remove)
{ {

View File

@@ -23,10 +23,16 @@ namespace Content.Server.Chemistry.ReagentEffects.StatusEffects
[DataField("time")] [DataField("time")]
public float Time = 2.0f; public float Time = 2.0f;
/// <remarks>
/// true - refresh jitter time, false - accumulate jitter time
/// </remarks>
[DataField("refresh")]
public bool Refresh = true;
public override void Effect(ReagentEffectArgs args) public override void Effect(ReagentEffectArgs args)
{ {
args.EntityManager.EntitySysManager.GetEntitySystem<SharedJitteringSystem>() args.EntityManager.EntitySysManager.GetEntitySystem<SharedJitteringSystem>()
.DoJitter(args.SolutionEntity, TimeSpan.FromSeconds(Time), Amplitude, Frequency); .DoJitter(args.SolutionEntity, TimeSpan.FromSeconds(Time), Refresh, Amplitude, Frequency);
} }
} }
} }

View File

@@ -61,7 +61,7 @@ namespace Content.Server.Conveyor
signal != TwoWayLeverSignal.Middle) signal != TwoWayLeverSignal.Middle)
{ {
args.Cancel(); args.Cancel();
_stunSystem.TryParalyze(uid, TimeSpan.FromSeconds(2f)); _stunSystem.TryParalyze(uid, TimeSpan.FromSeconds(2f), true);
component.Owner.PopupMessage(args.Attemptee, Loc.GetString("conveyor-component-failed-link")); component.Owner.PopupMessage(args.Attemptee, Loc.GetString("conveyor-component-failed-link"));
} }
} }

View File

@@ -51,7 +51,7 @@ namespace Content.Server.Damage.Systems
component.LastHit = _gameTiming.CurTime; component.LastHit = _gameTiming.CurTime;
if (_robustRandom.Prob(component.StunChance)) if (_robustRandom.Prob(component.StunChance))
_stunSystem.TryStun(uid, TimeSpan.FromSeconds(component.StunSeconds)); _stunSystem.TryStun(uid, TimeSpan.FromSeconds(component.StunSeconds), true);
var damageScale = (speed / component.MinimumSpeed) * component.Factor; var damageScale = (speed / component.MinimumSpeed) * component.Factor;

View File

@@ -585,7 +585,7 @@ namespace Content.Server.Doors.Components
if (e.Owner.HasComponent<DamageableComponent>()) if (e.Owner.HasComponent<DamageableComponent>())
EntitySystem.Get<DamageableSystem>().TryChangeDamage(e.Owner.Uid, CrushDamage); EntitySystem.Get<DamageableSystem>().TryChangeDamage(e.Owner.Uid, CrushDamage);
EntitySystem.Get<StunSystem>().TryParalyze(e.Owner.Uid, TimeSpan.FromSeconds(DoorStunTime)); EntitySystem.Get<StunSystem>().TryParalyze(e.Owner.Uid, TimeSpan.FromSeconds(DoorStunTime), true);
} }
// If we hit someone, open up after stun (opens right when stun ends) // If we hit someone, open up after stun (opens right when stun ends)

View File

@@ -52,7 +52,7 @@ namespace Content.Server.Electrocution
} }
entityManager.EntitySysManager.GetEntitySystem<ElectrocutionSystem>() entityManager.EntitySysManager.GetEntitySystem<ElectrocutionSystem>()
.TryDoElectrocution(uid, null, damage, TimeSpan.FromSeconds(seconds)); .TryDoElectrocution(uid, null, damage, TimeSpan.FromSeconds(seconds), true);
} }
} }
} }

View File

@@ -188,7 +188,7 @@ namespace Content.Server.Electrocution
entity, entity,
uid, uid,
(int) (electrified.ShockDamage * MathF.Pow(RecursiveDamageMultiplier, depth)), (int) (electrified.ShockDamage * MathF.Pow(RecursiveDamageMultiplier, depth)),
TimeSpan.FromSeconds(electrified.ShockTime * MathF.Pow(RecursiveTimeMultiplier, depth)), TimeSpan.FromSeconds(electrified.ShockTime * MathF.Pow(RecursiveTimeMultiplier, depth)), true,
electrified.SiemensCoefficient); electrified.SiemensCoefficient);
} }
@@ -224,7 +224,7 @@ namespace Content.Server.Electrocution
node, node,
(int) (electrified.ShockDamage * MathF.Pow(RecursiveDamageMultiplier, depth) * damageMult), (int) (electrified.ShockDamage * MathF.Pow(RecursiveDamageMultiplier, depth) * damageMult),
TimeSpan.FromSeconds(electrified.ShockTime * MathF.Pow(RecursiveTimeMultiplier, depth) * TimeSpan.FromSeconds(electrified.ShockTime * MathF.Pow(RecursiveTimeMultiplier, depth) *
timeMult), timeMult), true,
electrified.SiemensCoefficient); electrified.SiemensCoefficient);
} }
@@ -246,12 +246,12 @@ namespace Content.Server.Electrocution
/// <returns>Whether the entity <see cref="uid"/> was stunned by the shock.</returns> /// <returns>Whether the entity <see cref="uid"/> was stunned by the shock.</returns>
public bool TryDoElectrocution( public bool TryDoElectrocution(
EntityUid uid, EntityUid? sourceUid, int shockDamage, TimeSpan time, float siemensCoefficient = 1f, EntityUid uid, EntityUid? sourceUid, int shockDamage, TimeSpan time, bool refresh, float siemensCoefficient = 1f,
StatusEffectsComponent? statusEffects = null, StatusEffectsComponent? statusEffects = null,
SharedAlertsComponent? alerts = null) SharedAlertsComponent? alerts = null)
{ {
if (!DoCommonElectrocutionAttempt(uid, sourceUid, ref siemensCoefficient) if (!DoCommonElectrocutionAttempt(uid, sourceUid, ref siemensCoefficient)
|| !DoCommonElectrocution(uid, sourceUid, shockDamage, time, siemensCoefficient, statusEffects, alerts)) || !DoCommonElectrocution(uid, sourceUid, shockDamage, time, refresh, siemensCoefficient, statusEffects, alerts))
return false; return false;
RaiseLocalEvent(uid, new ElectrocutedEvent(uid, sourceUid, siemensCoefficient)); RaiseLocalEvent(uid, new ElectrocutedEvent(uid, sourceUid, siemensCoefficient));
@@ -265,6 +265,7 @@ namespace Content.Server.Electrocution
Node node, Node node,
int shockDamage, int shockDamage,
TimeSpan time, TimeSpan time,
bool refresh,
float siemensCoefficient = 1f, float siemensCoefficient = 1f,
StatusEffectsComponent? statusEffects = null, StatusEffectsComponent? statusEffects = null,
SharedAlertsComponent? alerts = null, SharedAlertsComponent? alerts = null,
@@ -275,9 +276,9 @@ namespace Content.Server.Electrocution
// Coefficient needs to be higher than this to do a powered electrocution! // Coefficient needs to be higher than this to do a powered electrocution!
if(siemensCoefficient <= 0.5f) if(siemensCoefficient <= 0.5f)
return DoCommonElectrocution(uid, sourceUid, shockDamage, time, siemensCoefficient, statusEffects, alerts); return DoCommonElectrocution(uid, sourceUid, shockDamage, time, refresh, siemensCoefficient, statusEffects, alerts);
if (!DoCommonElectrocution(uid, sourceUid, null, time, siemensCoefficient, statusEffects, alerts)) if (!DoCommonElectrocution(uid, sourceUid, null, time, refresh, siemensCoefficient, statusEffects, alerts))
return false; return false;
if (!Resolve(sourceUid, ref sourceTransform)) // This shouldn't really happen, but just in case... if (!Resolve(sourceUid, ref sourceTransform)) // This shouldn't really happen, but just in case...
@@ -319,7 +320,7 @@ namespace Content.Server.Electrocution
} }
private bool DoCommonElectrocution(EntityUid uid, EntityUid? sourceUid, private bool DoCommonElectrocution(EntityUid uid, EntityUid? sourceUid,
int? shockDamage, TimeSpan time, float siemensCoefficient = 1f, int? shockDamage, TimeSpan time, bool refresh, float siemensCoefficient = 1f,
StatusEffectsComponent? statusEffects = null, StatusEffectsComponent? statusEffects = null,
SharedAlertsComponent? alerts = null) SharedAlertsComponent? alerts = null)
{ {
@@ -341,14 +342,14 @@ namespace Content.Server.Electrocution
!_statusEffectsSystem.CanApplyEffect(uid, StatusEffectKey, statusEffects)) !_statusEffectsSystem.CanApplyEffect(uid, StatusEffectKey, statusEffects))
return false; return false;
if (!_statusEffectsSystem.TryAddStatusEffect<ElectrocutedComponent>(uid, StatusEffectKey, time, if (!_statusEffectsSystem.TryAddStatusEffect<ElectrocutedComponent>(uid, StatusEffectKey, time, refresh,
statusEffects, alerts)) statusEffects, alerts))
return false; return false;
var shouldStun = siemensCoefficient > 0.5f; var shouldStun = siemensCoefficient > 0.5f;
if (shouldStun) if (shouldStun)
_stunSystem.TryParalyze(uid, time * ParalyzeTimeMultiplier, statusEffects, alerts); _stunSystem.TryParalyze(uid, time * ParalyzeTimeMultiplier, refresh, statusEffects, alerts);
// TODO: Sparks here. // TODO: Sparks here.
@@ -362,8 +363,8 @@ namespace Content.Server.Electrocution
$"{statusEffects.Owner} took {actual.Total} powered electrocution damage"); $"{statusEffects.Owner} took {actual.Total} powered electrocution damage");
} }
_stutteringSystem.DoStutter(uid, time * StutteringTimeMultiplier, statusEffects, alerts); _stutteringSystem.DoStutter(uid, time * StutteringTimeMultiplier, refresh, statusEffects, alerts);
_jitteringSystem.DoJitter(uid, time * JitterTimeMultiplier, JitterAmplitude, JitterFrequency, true, _jitteringSystem.DoJitter(uid, time * JitterTimeMultiplier, refresh, JitterAmplitude, JitterFrequency, true,
statusEffects, alerts); statusEffects, alerts);
_popupSystem.PopupEntity(Loc.GetString("electrocuted-component-mob-shocked-popup-player"), uid, _popupSystem.PopupEntity(Loc.GetString("electrocuted-component-mob-shocked-popup-player"), uid,

View File

@@ -131,7 +131,7 @@ namespace Content.Server.Flash
flashable.Dirty(); flashable.Dirty();
} }
_stunSystem.TrySlowdown(target, TimeSpan.FromSeconds(flashDuration/1000f), _stunSystem.TrySlowdown(target, TimeSpan.FromSeconds(flashDuration/1000f), true,
slowTo, slowTo); slowTo, slowTo);
if (displayPopup && user != null && target != user) if (displayPopup && user != null && target != user)

View File

@@ -158,7 +158,7 @@ public sealed partial class InstrumentSystem : SharedInstrumentSystem
if (mob != null) if (mob != null)
{ {
_stunSystem.TryParalyze(mob.Uid, TimeSpan.FromSeconds(1)); _stunSystem.TryParalyze(mob.Uid, TimeSpan.FromSeconds(1), true);
instrument.Owner.PopupMessage(mob, "instrument-component-finger-cramps-max-message"); instrument.Owner.PopupMessage(mob, "instrument-component-finger-cramps-max-message");
} }

View File

@@ -247,7 +247,7 @@ namespace Content.Server.PneumaticCannon
if(data.User.TryGetComponent<StatusEffectsComponent>(out var status) if(data.User.TryGetComponent<StatusEffectsComponent>(out var status)
&& comp.Power == PneumaticCannonPower.High) && comp.Power == PneumaticCannonPower.High)
{ {
_stun.TryParalyze(data.User.Uid, TimeSpan.FromSeconds(comp.HighPowerStunTime), status); _stun.TryParalyze(data.User.Uid, TimeSpan.FromSeconds(comp.HighPowerStunTime), true, status);
data.User.PopupMessage(Loc.GetString("pneumatic-cannon-component-power-stun", data.User.PopupMessage(Loc.GetString("pneumatic-cannon-component-power-stun",
("cannon", comp.Owner))); ("cannon", comp.Owner)));
} }

View File

@@ -28,13 +28,13 @@ namespace Content.Server.Speech.EntitySystems
SubscribeLocalEvent<StutteringAccentComponent, AccentGetEvent>(OnAccent); SubscribeLocalEvent<StutteringAccentComponent, AccentGetEvent>(OnAccent);
} }
public override void DoStutter(EntityUid uid, TimeSpan time, StatusEffectsComponent? status = null, SharedAlertsComponent? alerts = null) public override void DoStutter(EntityUid uid, TimeSpan time, bool refresh, StatusEffectsComponent? status = null, SharedAlertsComponent? alerts = null)
{ {
if (!Resolve(uid, ref status, false)) if (!Resolve(uid, ref status, false))
return; return;
if (!_statusEffectsSystem.HasStatusEffect(uid, StutterKey, status)) if (!_statusEffectsSystem.HasStatusEffect(uid, StutterKey, status))
_statusEffectsSystem.TryAddStatusEffect<StutteringAccentComponent>(uid, StutterKey, time, status, alerts); _statusEffectsSystem.TryAddStatusEffect<StutteringAccentComponent>(uid, StutterKey, time, refresh, status, alerts);
else else
_statusEffectsSystem.TryAddTime(uid, StutterKey, time, status); _statusEffectsSystem.TryAddTime(uid, StutterKey, time, status);
} }

View File

@@ -37,12 +37,12 @@ namespace Content.Server.Stunnable
// Let the actual methods log errors for these. // Let the actual methods log errors for these.
Resolve(otherUid, ref alerts, ref standingState, ref appearance, false); Resolve(otherUid, ref alerts, ref standingState, ref appearance, false);
_stunSystem.TryStun(otherUid, TimeSpan.FromSeconds(component.StunAmount), status, alerts); _stunSystem.TryStun(otherUid, TimeSpan.FromSeconds(component.StunAmount), true, status, alerts);
_stunSystem.TryKnockdown(otherUid, TimeSpan.FromSeconds(component.KnockdownAmount), _stunSystem.TryKnockdown(otherUid, TimeSpan.FromSeconds(component.KnockdownAmount), true,
status, alerts); status, alerts);
_stunSystem.TrySlowdown(otherUid, TimeSpan.FromSeconds(component.SlowdownAmount), _stunSystem.TrySlowdown(otherUid, TimeSpan.FromSeconds(component.SlowdownAmount), true,
component.WalkSpeedMultiplier, component.RunSpeedMultiplier, status, alerts); component.WalkSpeedMultiplier, component.RunSpeedMultiplier, status, alerts);
} }
} }

View File

@@ -34,7 +34,7 @@ namespace Content.Server.Stunnable
if (args.Handled || !_random.Prob(args.PushProbability)) if (args.Handled || !_random.Prob(args.PushProbability))
return; return;
if (!TryParalyze(uid, TimeSpan.FromSeconds(4f), status)) if (!TryParalyze(uid, TimeSpan.FromSeconds(4f), true, status))
return; return;
var source = args.Source; var source = args.Source;

View File

@@ -129,21 +129,21 @@ namespace Content.Server.Stunnable
if (!EntityManager.HasComponent<SlowedDownComponent>(entity.Uid)) if (!EntityManager.HasComponent<SlowedDownComponent>(entity.Uid))
{ {
if (_robustRandom.Prob(comp.ParalyzeChanceNoSlowdown)) if (_robustRandom.Prob(comp.ParalyzeChanceNoSlowdown))
_stunSystem.TryParalyze(entity.Uid, TimeSpan.FromSeconds(comp.ParalyzeTime), status); _stunSystem.TryParalyze(entity.Uid, TimeSpan.FromSeconds(comp.ParalyzeTime), true, status);
else else
_stunSystem.TrySlowdown(entity.Uid, TimeSpan.FromSeconds(comp.SlowdownTime), 0.5f, 0.5f, status); _stunSystem.TrySlowdown(entity.Uid, TimeSpan.FromSeconds(comp.SlowdownTime), true, 0.5f, 0.5f, status);
} }
else else
{ {
if (_robustRandom.Prob(comp.ParalyzeChanceWithSlowdown)) if (_robustRandom.Prob(comp.ParalyzeChanceWithSlowdown))
_stunSystem.TryParalyze(entity.Uid, TimeSpan.FromSeconds(comp.ParalyzeTime), status); _stunSystem.TryParalyze(entity.Uid, TimeSpan.FromSeconds(comp.ParalyzeTime), true, status);
else else
_stunSystem.TrySlowdown(entity.Uid, TimeSpan.FromSeconds(comp.SlowdownTime), 0.5f, 0.5f, status); _stunSystem.TrySlowdown(entity.Uid, TimeSpan.FromSeconds(comp.SlowdownTime), true, 0.5f, 0.5f, status);
} }
var slowdownTime = TimeSpan.FromSeconds(comp.SlowdownTime); var slowdownTime = TimeSpan.FromSeconds(comp.SlowdownTime);
_jitterSystem.DoJitter(entity.Uid, slowdownTime, status:status); _jitterSystem.DoJitter(entity.Uid, slowdownTime, true, status:status);
_stutteringSystem.DoStutter(entity.Uid, slowdownTime, status); _stutteringSystem.DoStutter(entity.Uid, slowdownTime, true, status);
if (!comp.Owner.TryGetComponent<PowerCellSlotComponent>(out var slot) || slot.Cell == null || !(slot.Cell.CurrentCharge < comp.EnergyPerUse)) if (!comp.Owner.TryGetComponent<PowerCellSlotComponent>(out var slot) || slot.Cell == null || !(slot.Cell.CurrentCharge < comp.EnergyPerUse))
return; return;

View File

@@ -174,7 +174,7 @@ namespace Content.Server.Weapon.Ranged
{ {
//Wound them //Wound them
EntitySystem.Get<DamageableSystem>().TryChangeDamage(user.Uid, ClumsyDamage); EntitySystem.Get<DamageableSystem>().TryChangeDamage(user.Uid, ClumsyDamage);
EntitySystem.Get<StunSystem>().TryParalyze(user.Uid, TimeSpan.FromSeconds(3f)); EntitySystem.Get<StunSystem>().TryParalyze(user.Uid, TimeSpan.FromSeconds(3f), true);
// Apply salt to the wound ("Honk!") // Apply salt to the wound ("Honk!")
SoundSystem.Play( SoundSystem.Play(

View File

@@ -53,12 +53,13 @@ namespace Content.Shared.Jittering
/// </remarks> /// </remarks>
/// <param name="uid">Entity in question.</param> /// <param name="uid">Entity in question.</param>
/// <param name="time">For how much time to apply the effect.</param> /// <param name="time">For how much time to apply the effect.</param>
/// <param name="refresh">The status effect cooldown should be refreshed (true) or accumulated (false).</param>
/// <param name="amplitude">Jitteriness of the animation. See <see cref="MaxAmplitude"/> and <see cref="MinAmplitude"/>.</param> /// <param name="amplitude">Jitteriness of the animation. See <see cref="MaxAmplitude"/> and <see cref="MinAmplitude"/>.</param>
/// <param name="frequency">Frequency for jittering. See <see cref="MaxFrequency"/> and <see cref="MinFrequency"/>.</param> /// <param name="frequency">Frequency for jittering. See <see cref="MaxFrequency"/> and <see cref="MinFrequency"/>.</param>
/// <param name="forceValueChange">Whether to change any existing jitter value even if they're greater than the ones we're setting.</param> /// <param name="forceValueChange">Whether to change any existing jitter value even if they're greater than the ones we're setting.</param>
/// <param name="status">The status effects component to modify.</param> /// <param name="status">The status effects component to modify.</param>
/// <param name="alerts">The alerts component.</param> /// <param name="alerts">The alerts component.</param>
public void DoJitter(EntityUid uid, TimeSpan time, float amplitude = 10f, float frequency = 4f, bool forceValueChange = false, public void DoJitter(EntityUid uid, TimeSpan time, bool refresh, float amplitude = 10f, float frequency = 4f, bool forceValueChange = false,
StatusEffectsComponent? status = null, StatusEffectsComponent? status = null,
SharedAlertsComponent? alerts = null) SharedAlertsComponent? alerts = null)
{ {
@@ -68,7 +69,7 @@ namespace Content.Shared.Jittering
amplitude = Math.Clamp(amplitude, MinAmplitude, MaxAmplitude); amplitude = Math.Clamp(amplitude, MinAmplitude, MaxAmplitude);
frequency = Math.Clamp(frequency, MinFrequency, MaxFrequency); frequency = Math.Clamp(frequency, MinFrequency, MaxFrequency);
if (StatusEffects.TryAddStatusEffect<JitteringComponent>(uid, "Jitter", time, status, alerts)) if (StatusEffects.TryAddStatusEffect<JitteringComponent>(uid, "Jitter", time, refresh, status, alerts))
{ {
var jittering = EntityManager.GetComponent<JitteringComponent>(uid); var jittering = EntityManager.GetComponent<JitteringComponent>(uid);

View File

@@ -68,7 +68,7 @@ namespace Content.Shared.Nutrition.EntitySystems
CreamedEntity(uid, creamPied, args); CreamedEntity(uid, creamPied, args);
_stunSystem.TryParalyze(uid, TimeSpan.FromSeconds(creamPie.ParalyzeTime)); _stunSystem.TryParalyze(uid, TimeSpan.FromSeconds(creamPie.ParalyzeTime), true);
} }
protected virtual void CreamedEntity(EntityUid uid, CreamPiedComponent creamPied, ThrowHitByEvent args) {} protected virtual void CreamedEntity(EntityUid uid, CreamPiedComponent creamPied, ThrowHitByEvent args) {}

View File

@@ -64,7 +64,7 @@ namespace Content.Shared.Slippery
if (!component.Slippery if (!component.Slippery
|| component.Owner.IsInContainer() || component.Owner.IsInContainer()
|| component.Slipped.Contains(uid) || component.Slipped.Contains(uid)
|| !_statusEffectsSystem.CanApplyEffect(uid, "Stun")) || !_statusEffectsSystem.CanApplyEffect(uid, "Stun")) //Should be KnockedDown instead?
{ {
return false; return false;
} }
@@ -95,11 +95,17 @@ namespace Content.Shared.Slippery
otherBody.LinearVelocity *= component.LaunchForwardsMultiplier; otherBody.LinearVelocity *= component.LaunchForwardsMultiplier;
_stunSystem.TryParalyze(otherBody.OwnerUid, TimeSpan.FromSeconds(5)); bool playSound = !_statusEffectsSystem.HasStatusEffect(otherBody.OwnerUid, "KnockedDown");
_stunSystem.TryParalyze(otherBody.OwnerUid, TimeSpan.FromSeconds(component.ParalyzeTime), true);
component.Slipped.Add(otherBody.OwnerUid); component.Slipped.Add(otherBody.OwnerUid);
component.Dirty(); component.Dirty();
PlaySound(component); //Preventing from playing the slip sound when you are already knocked down.
if(playSound)
{
PlaySound(component);
}
_adminLog.Add(LogType.Slip, LogImpact.Low, $"{component.Owner} slipped on collision with {otherBody.Owner}"); _adminLog.Add(LogType.Slip, LogImpact.Low, $"{component.Owner} slipped on collision with {otherBody.Owner}");

View File

@@ -18,7 +18,7 @@ namespace Content.Shared.Slippery
{ {
public override string Name => "Slippery"; public override string Name => "Slippery";
private float _paralyzeTime = 3f; private float _paralyzeTime = 5f;
private float _intersectPercentage = 0.3f; private float _intersectPercentage = 0.3f;
private float _requiredSlipSpeed = 5f; private float _requiredSlipSpeed = 5f;
private float _launchForwardsMultiplier = 1f; private float _launchForwardsMultiplier = 1f;

View File

@@ -8,7 +8,7 @@ namespace Content.Shared.Speech.EntitySystems
public abstract class SharedStutteringSystem : EntitySystem public abstract class SharedStutteringSystem : EntitySystem
{ {
// For code in shared... I imagine we ain't getting accent prediction anytime soon so let's not bother. // For code in shared... I imagine we ain't getting accent prediction anytime soon so let's not bother.
public virtual void DoStutter(EntityUid uid, TimeSpan time, StatusEffectsComponent? status = null, SharedAlertsComponent? alerts = null) public virtual void DoStutter(EntityUid uid, TimeSpan time, bool refresh, StatusEffectsComponent? status = null, SharedAlertsComponent? alerts = null)
{ {
} }
} }

View File

@@ -38,6 +38,13 @@ namespace Content.Shared.StatusEffect
[ViewVariables] [ViewVariables]
public (TimeSpan, TimeSpan) Cooldown; public (TimeSpan, TimeSpan) Cooldown;
/// <summary>
/// Specifies whether to refresh or accumulate the cooldown of the status effect.
/// true - refresh time, false - accumulate time.
/// </summary>
[ViewVariables]
public bool CooldownRefresh = true;
/// <summary> /// <summary>
/// The name of the relevant component that /// The name of the relevant component that
/// was added alongside the effect, if any. /// was added alongside the effect, if any.
@@ -45,9 +52,10 @@ namespace Content.Shared.StatusEffect
[ViewVariables] [ViewVariables]
public string? RelevantComponent; public string? RelevantComponent;
public StatusEffectState((TimeSpan, TimeSpan) cooldown, string? relevantComponent=null) public StatusEffectState((TimeSpan, TimeSpan) cooldown, bool refresh, string? relevantComponent=null)
{ {
Cooldown = cooldown; Cooldown = cooldown;
CooldownRefresh = refresh;
RelevantComponent = relevantComponent; RelevantComponent = relevantComponent;
} }
} }

View File

@@ -64,7 +64,8 @@ namespace Content.Shared.StatusEffect
} }
var time = effect.Value.Cooldown.Item2 - effect.Value.Cooldown.Item1; var time = effect.Value.Cooldown.Item2 - effect.Value.Cooldown.Item1;
TryAddStatusEffect(uid, effect.Key, time); //TODO: Not sure how to handle refresh here.
TryAddStatusEffect(uid, effect.Key, time, true);
} }
} }
} }
@@ -75,11 +76,12 @@ namespace Content.Shared.StatusEffect
/// <param name="uid">The entity to add the effect to.</param> /// <param name="uid">The entity to add the effect to.</param>
/// <param name="key">The status effect ID to add.</param> /// <param name="key">The status effect ID to add.</param>
/// <param name="time">How long the effect should last for.</param> /// <param name="time">How long the effect should last for.</param>
/// <param name="refresh">The status effect cooldown should be refreshed (true) or accumulated (false).</param>
/// <param name="status">The status effects component to change, if you already have it.</param> /// <param name="status">The status effects component to change, if you already have it.</param>
/// <param name="alerts">The alerts component to modify, if the status effect has an alert.</param> /// <param name="alerts">The alerts component to modify, if the status effect has an alert.</param>
/// <returns>False if the effect could not be added or the component already exists, true otherwise.</returns> /// <returns>False if the effect could not be added or the component already exists, true otherwise.</returns>
/// <typeparam name="T">The component type to add and remove from the entity.</typeparam> /// <typeparam name="T">The component type to add and remove from the entity.</typeparam>
public bool TryAddStatusEffect<T>(EntityUid uid, string key, TimeSpan time, public bool TryAddStatusEffect<T>(EntityUid uid, string key, TimeSpan time, bool refresh,
StatusEffectsComponent? status=null, StatusEffectsComponent? status=null,
SharedAlertsComponent? alerts=null) SharedAlertsComponent? alerts=null)
where T: Component, new() where T: Component, new()
@@ -89,7 +91,7 @@ namespace Content.Shared.StatusEffect
Resolve(uid, ref alerts, false); Resolve(uid, ref alerts, false);
if (TryAddStatusEffect(uid, key, time, status, alerts)) if (TryAddStatusEffect(uid, key, time, refresh, status, alerts))
{ {
// If they already have the comp, we just won't bother updating anything. // If they already have the comp, we just won't bother updating anything.
if (!EntityManager.HasComponent<T>(uid)) if (!EntityManager.HasComponent<T>(uid))
@@ -103,7 +105,7 @@ namespace Content.Shared.StatusEffect
return false; return false;
} }
public bool TryAddStatusEffect(EntityUid uid, string key, TimeSpan time, string component, public bool TryAddStatusEffect(EntityUid uid, string key, TimeSpan time, bool refresh, string component,
StatusEffectsComponent? status = null, StatusEffectsComponent? status = null,
SharedAlertsComponent? alerts = null) SharedAlertsComponent? alerts = null)
{ {
@@ -112,7 +114,7 @@ namespace Content.Shared.StatusEffect
Resolve(uid, ref alerts, false); Resolve(uid, ref alerts, false);
if (TryAddStatusEffect(uid, key, time, status, alerts)) if (TryAddStatusEffect(uid, key, time, refresh, status, alerts))
{ {
// If they already have the comp, we just won't bother updating anything. // If they already have the comp, we just won't bother updating anything.
if (!EntityManager.HasComponent(uid, _componentFactory.GetRegistration(component).Type)) if (!EntityManager.HasComponent(uid, _componentFactory.GetRegistration(component).Type))
@@ -136,6 +138,7 @@ namespace Content.Shared.StatusEffect
/// <param name="uid">The entity to add the effect to.</param> /// <param name="uid">The entity to add the effect to.</param>
/// <param name="key">The status effect ID to add.</param> /// <param name="key">The status effect ID to add.</param>
/// <param name="time">How long the effect should last for.</param> /// <param name="time">How long the effect should last for.</param>
/// <param name="refresh">The status effect cooldown should be refreshed (true) or accumulated (false).</param>
/// <param name="status">The status effects component to change, if you already have it.</param> /// <param name="status">The status effects component to change, if you already have it.</param>
/// <param name="alerts">The alerts component to modify, if the status effect has an alert.</param> /// <param name="alerts">The alerts component to modify, if the status effect has an alert.</param>
/// <returns>False if the effect could not be added, or if the effect already existed.</returns> /// <returns>False if the effect could not be added, or if the effect already existed.</returns>
@@ -146,7 +149,7 @@ namespace Content.Shared.StatusEffect
/// If the effect already exists, it will simply replace the cooldown with the new one given. /// If the effect already exists, it will simply replace the cooldown with the new one given.
/// If you want special 'effect merging' behavior, do it your own damn self! /// If you want special 'effect merging' behavior, do it your own damn self!
/// </remarks> /// </remarks>
public bool TryAddStatusEffect(EntityUid uid, string key, TimeSpan time, public bool TryAddStatusEffect(EntityUid uid, string key, TimeSpan time, bool refresh,
StatusEffectsComponent? status=null, StatusEffectsComponent? status=null,
SharedAlertsComponent? alerts=null) SharedAlertsComponent? alerts=null)
{ {
@@ -163,14 +166,27 @@ namespace Content.Shared.StatusEffect
(TimeSpan, TimeSpan) cooldown = (_gameTiming.CurTime, _gameTiming.CurTime + time); (TimeSpan, TimeSpan) cooldown = (_gameTiming.CurTime, _gameTiming.CurTime + time);
// If they already have this status effect, add the time onto it's cooldown rather than anything else.
if (HasStatusEffect(uid, key, status)) if (HasStatusEffect(uid, key, status))
{ {
status.ActiveEffects[key].Cooldown.Item2 += time; status.ActiveEffects[key].CooldownRefresh = refresh;
if(refresh)
{
//Making sure we don't reset a longer cooldown by applying a shorter one.
if((status.ActiveEffects[key].Cooldown.Item2 - _gameTiming.CurTime) < time)
{
//Refresh cooldown time.
status.ActiveEffects[key].Cooldown = cooldown;
}
}
else
{
//Accumulate cooldown time.
status.ActiveEffects[key].Cooldown.Item2 += time;
}
} }
else else
{ {
status.ActiveEffects.Add(key, new StatusEffectState(cooldown, null)); status.ActiveEffects.Add(key, new StatusEffectState(cooldown, refresh, null));
} }
if (proto.Alert != null && alerts != null) if (proto.Alert != null && alerts != null)

View File

@@ -118,7 +118,7 @@ namespace Content.Shared.Stunnable
/// <summary> /// <summary>
/// Stuns the entity, disallowing it from doing many interactions temporarily. /// Stuns the entity, disallowing it from doing many interactions temporarily.
/// </summary> /// </summary>
public bool TryStun(EntityUid uid, TimeSpan time, public bool TryStun(EntityUid uid, TimeSpan time, bool refresh,
StatusEffectsComponent? status = null, StatusEffectsComponent? status = null,
SharedAlertsComponent? alerts = null) SharedAlertsComponent? alerts = null)
{ {
@@ -130,13 +130,13 @@ namespace Content.Shared.Stunnable
Resolve(uid, ref alerts, false); Resolve(uid, ref alerts, false);
return _statusEffectSystem.TryAddStatusEffect<StunnedComponent>(uid, "Stun", time, alerts: alerts); return _statusEffectSystem.TryAddStatusEffect<StunnedComponent>(uid, "Stun", time, refresh, alerts: alerts);
} }
/// <summary> /// <summary>
/// Knocks down the entity, making it fall to the ground. /// Knocks down the entity, making it fall to the ground.
/// </summary> /// </summary>
public bool TryKnockdown(EntityUid uid, TimeSpan time, public bool TryKnockdown(EntityUid uid, TimeSpan time, bool refresh,
StatusEffectsComponent? status = null, StatusEffectsComponent? status = null,
SharedAlertsComponent? alerts = null) SharedAlertsComponent? alerts = null)
{ {
@@ -148,13 +148,13 @@ namespace Content.Shared.Stunnable
Resolve(uid, ref alerts, false); Resolve(uid, ref alerts, false);
return _statusEffectSystem.TryAddStatusEffect<KnockedDownComponent>(uid, "KnockedDown", time, alerts: alerts); return _statusEffectSystem.TryAddStatusEffect<KnockedDownComponent>(uid, "KnockedDown", time, refresh, alerts: alerts);
} }
/// <summary> /// <summary>
/// Applies knockdown and stun to the entity temporarily. /// Applies knockdown and stun to the entity temporarily.
/// </summary> /// </summary>
public bool TryParalyze(EntityUid uid, TimeSpan time, public bool TryParalyze(EntityUid uid, TimeSpan time, bool refresh,
StatusEffectsComponent? status = null, StatusEffectsComponent? status = null,
SharedAlertsComponent? alerts = null) SharedAlertsComponent? alerts = null)
{ {
@@ -164,13 +164,13 @@ namespace Content.Shared.Stunnable
// Optional component. // Optional component.
Resolve(uid, ref alerts, false); Resolve(uid, ref alerts, false);
return TryKnockdown(uid, time, status, alerts) && TryStun(uid, time, status, alerts); return TryKnockdown(uid, time, refresh, status, alerts) && TryStun(uid, time, refresh, status, alerts);
} }
/// <summary> /// <summary>
/// Slows down the mob's walking/running speed temporarily /// Slows down the mob's walking/running speed temporarily
/// </summary> /// </summary>
public bool TrySlowdown(EntityUid uid, TimeSpan time, public bool TrySlowdown(EntityUid uid, TimeSpan time, bool refresh,
float walkSpeedMultiplier = 1f, float runSpeedMultiplier = 1f, float walkSpeedMultiplier = 1f, float runSpeedMultiplier = 1f,
StatusEffectsComponent? status = null, StatusEffectsComponent? status = null,
SharedAlertsComponent? alerts = null) SharedAlertsComponent? alerts = null)
@@ -184,7 +184,7 @@ namespace Content.Shared.Stunnable
if (time <= TimeSpan.Zero) if (time <= TimeSpan.Zero)
return false; return false;
if (_statusEffectSystem.TryAddStatusEffect<SlowedDownComponent>(uid, "SlowedDown", time, status, alerts)) if (_statusEffectSystem.TryAddStatusEffect<SlowedDownComponent>(uid, "SlowedDown", time, refresh, status, alerts))
{ {
var slowed = EntityManager.GetComponent<SlowedDownComponent>(uid); var slowed = EntityManager.GetComponent<SlowedDownComponent>(uid);
// Doesn't make much sense to have the "TrySlowdown" method speed up entities now does it? // Doesn't make much sense to have the "TrySlowdown" method speed up entities now does it?