Stunnable New Status and Cleanup (#38618)
Co-authored-by: Princess Cheeseballs <66055347+Pronana@users.noreply.github.com> Co-authored-by: pa.pecherskij <pa.pecherskij@interfax.ru>
This commit is contained in:
committed by
GitHub
parent
2b2b9b11b8
commit
e85bc1bb8c
@@ -1,4 +1,4 @@
|
|||||||
using Content.Server.Stunnable;
|
using Content.Server.Stunnable;
|
||||||
using Content.Shared.Inventory;
|
using Content.Shared.Inventory;
|
||||||
using Robust.Shared.GameObjects;
|
using Robust.Shared.GameObjects;
|
||||||
using Robust.Shared.IoC;
|
using Robust.Shared.IoC;
|
||||||
@@ -17,9 +17,7 @@ namespace Content.IntegrationTests.Tests
|
|||||||
components:
|
components:
|
||||||
- type: Inventory
|
- type: Inventory
|
||||||
- type: ContainerContainer
|
- type: ContainerContainer
|
||||||
- type: StatusEffects
|
- type: MobState
|
||||||
allowed:
|
|
||||||
- Stun
|
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
name: InventoryJumpsuitJanitorDummy
|
name: InventoryJumpsuitJanitorDummy
|
||||||
@@ -70,7 +68,7 @@ namespace Content.IntegrationTests.Tests
|
|||||||
});
|
});
|
||||||
#pragma warning restore NUnit2045
|
#pragma warning restore NUnit2045
|
||||||
|
|
||||||
systemMan.GetEntitySystem<StunSystem>().TryStun(human, TimeSpan.FromSeconds(1f), true);
|
systemMan.GetEntitySystem<StunSystem>().TryUpdateStunDuration(human, TimeSpan.FromSeconds(1f));
|
||||||
|
|
||||||
#pragma warning disable NUnit2045
|
#pragma warning disable NUnit2045
|
||||||
// Since the mob is stunned, they can't equip this.
|
// Since the mob is stunned, they can't equip this.
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ public sealed class InnerBodyAnomalySystem : SharedInnerBodyAnomalySystem
|
|||||||
|
|
||||||
EntityManager.AddComponents(ent, injectedAnom.Components);
|
EntityManager.AddComponents(ent, injectedAnom.Components);
|
||||||
|
|
||||||
_stun.TryParalyze(ent, TimeSpan.FromSeconds(ent.Comp.StunDuration), true);
|
_stun.TryUpdateParalyzeDuration(ent, TimeSpan.FromSeconds(ent.Comp.StunDuration));
|
||||||
_jitter.DoJitter(ent, TimeSpan.FromSeconds(ent.Comp.StunDuration), true);
|
_jitter.DoJitter(ent, TimeSpan.FromSeconds(ent.Comp.StunDuration), true);
|
||||||
|
|
||||||
if (ent.Comp.StartSound is not null)
|
if (ent.Comp.StartSound is not null)
|
||||||
@@ -125,7 +125,7 @@ public sealed class InnerBodyAnomalySystem : SharedInnerBodyAnomalySystem
|
|||||||
|
|
||||||
private void OnAnomalyPulse(Entity<InnerBodyAnomalyComponent> ent, ref AnomalyPulseEvent args)
|
private void OnAnomalyPulse(Entity<InnerBodyAnomalyComponent> ent, ref AnomalyPulseEvent args)
|
||||||
{
|
{
|
||||||
_stun.TryParalyze(ent, TimeSpan.FromSeconds(ent.Comp.StunDuration / 2 * args.Severity), true);
|
_stun.TryUpdateParalyzeDuration(ent, TimeSpan.FromSeconds(ent.Comp.StunDuration / 2 * args.Severity));
|
||||||
_jitter.DoJitter(ent, TimeSpan.FromSeconds(ent.Comp.StunDuration / 2 * args.Severity), true);
|
_jitter.DoJitter(ent, TimeSpan.FromSeconds(ent.Comp.StunDuration / 2 * args.Severity), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -213,7 +213,7 @@ public sealed class InnerBodyAnomalySystem : SharedInnerBodyAnomalySystem
|
|||||||
if (_proto.TryIndex(ent.Comp.InjectionProto, out var injectedAnom))
|
if (_proto.TryIndex(ent.Comp.InjectionProto, out var injectedAnom))
|
||||||
EntityManager.RemoveComponents(ent, injectedAnom.Components);
|
EntityManager.RemoveComponents(ent, injectedAnom.Components);
|
||||||
|
|
||||||
_stun.TryParalyze(ent, TimeSpan.FromSeconds(ent.Comp.StunDuration), true);
|
_stun.TryUpdateParalyzeDuration(ent, TimeSpan.FromSeconds(ent.Comp.StunDuration));
|
||||||
|
|
||||||
if (ent.Comp.EndMessage is not null &&
|
if (ent.Comp.EndMessage is not null &&
|
||||||
_mind.TryGetMind(ent, out _, out var mindComponent) &&
|
_mind.TryGetMind(ent, out _, out var mindComponent) &&
|
||||||
|
|||||||
@@ -394,7 +394,7 @@ namespace Content.Server.Atmos.EntitySystems
|
|||||||
flammable.Resisting = true;
|
flammable.Resisting = true;
|
||||||
|
|
||||||
_popup.PopupEntity(Loc.GetString("flammable-component-resist-message"), uid, uid);
|
_popup.PopupEntity(Loc.GetString("flammable-component-resist-message"), uid, uid);
|
||||||
_stunSystem.TryParalyze(uid, TimeSpan.FromSeconds(2f), true);
|
_stunSystem.TryUpdateParalyzeDuration(uid, TimeSpan.FromSeconds(2f));
|
||||||
|
|
||||||
// TODO FLAMMABLE: Make this not use TimerComponent...
|
// TODO FLAMMABLE: Make this not use TimerComponent...
|
||||||
uid.SpawnTimer(2000, () =>
|
uid.SpawnTimer(2000, () =>
|
||||||
|
|||||||
@@ -101,7 +101,7 @@ public sealed class CluwneSystem : EntitySystem
|
|||||||
else if (_robustRandom.Prob(component.KnockChance))
|
else if (_robustRandom.Prob(component.KnockChance))
|
||||||
{
|
{
|
||||||
_audio.PlayPvs(component.KnockSound, uid);
|
_audio.PlayPvs(component.KnockSound, uid);
|
||||||
_stunSystem.TryParalyze(uid, TimeSpan.FromSeconds(component.ParalyzeTime), true);
|
_stunSystem.TryUpdateParalyzeDuration(uid, TimeSpan.FromSeconds(component.ParalyzeTime));
|
||||||
_chat.TrySendInGameICMessage(uid, "spasms", InGameICChatType.Emote, ChatTransmitRange.Normal);
|
_chat.TrySendInGameICMessage(uid, "spasms", InGameICChatType.Emote, ChatTransmitRange.Normal);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using Content.Shared.Bed.Sleep;
|
using Content.Shared.Bed.Sleep;
|
||||||
using Content.Shared.Drowsiness;
|
using Content.Shared.Drowsiness;
|
||||||
using Content.Shared.StatusEffectNew;
|
using Content.Shared.StatusEffectNew;
|
||||||
using Content.Shared.StatusEffectNew.Components;
|
using Content.Shared.StatusEffectNew.Components;
|
||||||
|
|||||||
@@ -397,7 +397,12 @@ public sealed class ElectrocutionSystem : SharedElectrocutionSystem
|
|||||||
var shouldStun = siemensCoefficient > 0.5f;
|
var shouldStun = siemensCoefficient > 0.5f;
|
||||||
|
|
||||||
if (shouldStun)
|
if (shouldStun)
|
||||||
_stun.TryParalyze(uid, time * ParalyzeTimeMultiplier, refresh, statusEffects);
|
{
|
||||||
|
_ = refresh
|
||||||
|
? _stun.TryUpdateParalyzeDuration(uid, time * ParalyzeTimeMultiplier)
|
||||||
|
: _stun.TryAddParalyzeDuration(uid, time * ParalyzeTimeMultiplier);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// TODO: Sparks here.
|
// TODO: Sparks here.
|
||||||
|
|
||||||
|
|||||||
@@ -228,7 +228,7 @@ public sealed class RevolutionaryRuleSystem : GameRuleSystem<RevolutionaryRuleCo
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
_npcFaction.RemoveFaction(uid, RevolutionaryNpcFaction);
|
_npcFaction.RemoveFaction(uid, RevolutionaryNpcFaction);
|
||||||
_stun.TryParalyze(uid, stunTime, true);
|
_stun.TryUpdateParalyzeDuration(uid, stunTime);
|
||||||
RemCompDeferred<RevolutionaryComponent>(uid);
|
RemCompDeferred<RevolutionaryComponent>(uid);
|
||||||
_popup.PopupEntity(Loc.GetString("rev-break-control", ("name", Identity.Entity(uid, EntityManager))), uid);
|
_popup.PopupEntity(Loc.GetString("rev-break-control", ("name", Identity.Entity(uid, EntityManager))), uid);
|
||||||
_adminLogManager.Add(LogType.Mind, LogImpact.Medium, $"{ToPrettyString(uid)} was deconverted due to all Head Revolutionaries dying.");
|
_adminLogManager.Add(LogType.Mind, LogImpact.Medium, $"{ToPrettyString(uid)} was deconverted due to all Head Revolutionaries dying.");
|
||||||
|
|||||||
@@ -461,7 +461,7 @@ public sealed partial class InstrumentSystem : SharedInstrumentSystem
|
|||||||
{
|
{
|
||||||
if (instrument.InstrumentPlayer is {Valid: true} mob)
|
if (instrument.InstrumentPlayer is {Valid: true} mob)
|
||||||
{
|
{
|
||||||
_stuns.TryParalyze(mob, TimeSpan.FromSeconds(1), true);
|
_stuns.TryUpdateParalyzeDuration(mob, TimeSpan.FromSeconds(1));
|
||||||
|
|
||||||
_popup.PopupEntity(Loc.GetString("instrument-component-finger-cramps-max-message"),
|
_popup.PopupEntity(Loc.GetString("instrument-component-finger-cramps-max-message"),
|
||||||
uid, mob, PopupType.LargeCaution);
|
uid, mob, PopupType.LargeCaution);
|
||||||
|
|||||||
@@ -2,16 +2,15 @@ using Content.Server.Body.Systems;
|
|||||||
using Content.Server.Fluids.EntitySystems;
|
using Content.Server.Fluids.EntitySystems;
|
||||||
using Content.Server.Forensics;
|
using Content.Server.Forensics;
|
||||||
using Content.Server.Popups;
|
using Content.Server.Popups;
|
||||||
using Content.Server.Stunnable;
|
|
||||||
using Content.Shared.Body.Components;
|
using Content.Shared.Body.Components;
|
||||||
using Content.Shared.Body.Systems;
|
using Content.Shared.Body.Systems;
|
||||||
using Content.Shared.Chemistry.Components;
|
using Content.Shared.Chemistry.Components;
|
||||||
using Content.Shared.Chemistry.EntitySystems;
|
using Content.Shared.Chemistry.EntitySystems;
|
||||||
using Content.Shared.Chemistry.Reagent;
|
using Content.Shared.Chemistry.Reagent;
|
||||||
using Content.Shared.IdentityManagement;
|
using Content.Shared.IdentityManagement;
|
||||||
|
using Content.Shared.Movement.Systems;
|
||||||
using Content.Shared.Nutrition.Components;
|
using Content.Shared.Nutrition.Components;
|
||||||
using Content.Shared.Nutrition.EntitySystems;
|
using Content.Shared.Nutrition.EntitySystems;
|
||||||
using Content.Shared.StatusEffect;
|
|
||||||
using Robust.Server.Audio;
|
using Robust.Server.Audio;
|
||||||
using Robust.Shared.Audio;
|
using Robust.Shared.Audio;
|
||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
@@ -27,7 +26,7 @@ namespace Content.Server.Medical
|
|||||||
[Dependency] private readonly PopupSystem _popup = default!;
|
[Dependency] private readonly PopupSystem _popup = default!;
|
||||||
[Dependency] private readonly PuddleSystem _puddle = default!;
|
[Dependency] private readonly PuddleSystem _puddle = default!;
|
||||||
[Dependency] private readonly SharedSolutionContainerSystem _solutionContainer = default!;
|
[Dependency] private readonly SharedSolutionContainerSystem _solutionContainer = default!;
|
||||||
[Dependency] private readonly StunSystem _stun = default!;
|
[Dependency] private readonly MovementModStatusSystem _movementMod = default!;
|
||||||
[Dependency] private readonly ThirstSystem _thirst = default!;
|
[Dependency] private readonly ThirstSystem _thirst = default!;
|
||||||
[Dependency] private readonly ForensicsSystem _forensics = default!;
|
[Dependency] private readonly ForensicsSystem _forensics = default!;
|
||||||
[Dependency] private readonly BloodstreamSystem _bloodstream = default!;
|
[Dependency] private readonly BloodstreamSystem _bloodstream = default!;
|
||||||
@@ -57,8 +56,7 @@ namespace Content.Server.Medical
|
|||||||
// It fully empties the stomach, this amount from the chem stream is relatively small
|
// It fully empties the stomach, this amount from the chem stream is relatively small
|
||||||
var solutionSize = (MathF.Abs(thirstAdded) + MathF.Abs(hungerAdded)) / 6;
|
var solutionSize = (MathF.Abs(thirstAdded) + MathF.Abs(hungerAdded)) / 6;
|
||||||
// Apply a bit of slowdown
|
// Apply a bit of slowdown
|
||||||
if (TryComp<StatusEffectsComponent>(uid, out var status))
|
_movementMod.TryUpdateMovementSpeedModDuration(uid, MovementModStatusSystem.VomitingSlowdown, TimeSpan.FromSeconds(solutionSize), 0.5f);
|
||||||
_stun.TrySlowdown(uid, TimeSpan.FromSeconds(solutionSize), true, 0.5f, 0.5f, status);
|
|
||||||
|
|
||||||
// TODO: Need decals
|
// TODO: Need decals
|
||||||
var solution = new Solution();
|
var solution = new Solution();
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ public sealed class StunProviderSystem : SharedStunProviderSystem
|
|||||||
_audio.PlayPvs(comp.Sound, target);
|
_audio.PlayPvs(comp.Sound, target);
|
||||||
|
|
||||||
_damageable.TryChangeDamage(target, comp.StunDamage, false, true, null, origin: uid);
|
_damageable.TryChangeDamage(target, comp.StunDamage, false, true, null, origin: uid);
|
||||||
_stun.TryParalyze(target, comp.StunTime, refresh: false);
|
_stun.TryAddParalyzeDuration(target, comp.StunTime);
|
||||||
|
|
||||||
// short cooldown to prevent instant stunlocking
|
// short cooldown to prevent instant stunlocking
|
||||||
_useDelay.SetLength((uid, useDelay), comp.Cooldown, id: comp.DelayId);
|
_useDelay.SetLength((uid, useDelay), comp.Cooldown, id: comp.DelayId);
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
using Content.Server.Atmos.Components;
|
|
||||||
using Content.Server.Atmos.EntitySystems;
|
using Content.Server.Atmos.EntitySystems;
|
||||||
using Content.Server.Storage.EntitySystems;
|
using Content.Server.Storage.EntitySystems;
|
||||||
using Content.Server.Stunnable;
|
using Content.Server.Stunnable;
|
||||||
@@ -7,7 +6,6 @@ using Content.Shared.Atmos.Components;
|
|||||||
using Content.Shared.Containers.ItemSlots;
|
using Content.Shared.Containers.ItemSlots;
|
||||||
using Content.Shared.Interaction;
|
using Content.Shared.Interaction;
|
||||||
using Content.Shared.PneumaticCannon;
|
using Content.Shared.PneumaticCannon;
|
||||||
using Content.Shared.StatusEffect;
|
|
||||||
using Content.Shared.Tools.Systems;
|
using Content.Shared.Tools.Systems;
|
||||||
using Content.Shared.Weapons.Ranged.Components;
|
using Content.Shared.Weapons.Ranged.Components;
|
||||||
using Content.Shared.Weapons.Ranged.Events;
|
using Content.Shared.Weapons.Ranged.Events;
|
||||||
@@ -80,10 +78,9 @@ public sealed class PneumaticCannonSystem : SharedPneumaticCannonSystem
|
|||||||
if (gas == null && component.GasUsage > 0f)
|
if (gas == null && component.GasUsage > 0f)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (TryComp<StatusEffectsComponent>(args.User, out var status)
|
if (component.Power == PneumaticCannonPower.High
|
||||||
&& component.Power == PneumaticCannonPower.High)
|
&& _stun.TryUpdateParalyzeDuration(args.User, TimeSpan.FromSeconds(component.HighPowerStunTime)))
|
||||||
{
|
{
|
||||||
_stun.TryParalyze(args.User, TimeSpan.FromSeconds(component.HighPowerStunTime), true, status);
|
|
||||||
Popup.PopupEntity(Loc.GetString("pneumatic-cannon-component-power-stun",
|
Popup.PopupEntity(Loc.GetString("pneumatic-cannon-component-power-stun",
|
||||||
("cannon", uid)), cannon, args.User);
|
("cannon", uid)), cannon, args.User);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -177,7 +177,7 @@ public sealed partial class RevenantSystem : EntitySystem
|
|||||||
ChangeEssenceAmount(uid, -abilityCost, component, false);
|
ChangeEssenceAmount(uid, -abilityCost, component, false);
|
||||||
|
|
||||||
_statusEffects.TryAddStatusEffect<CorporealComponent>(uid, "Corporeal", TimeSpan.FromSeconds(debuffs.Y), false);
|
_statusEffects.TryAddStatusEffect<CorporealComponent>(uid, "Corporeal", TimeSpan.FromSeconds(debuffs.Y), false);
|
||||||
_stun.TryStun(uid, TimeSpan.FromSeconds(debuffs.X), false);
|
_stun.TryAddStunDuration(uid, TimeSpan.FromSeconds(debuffs.X));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -616,10 +616,7 @@ public sealed partial class ShuttleSystem
|
|||||||
{
|
{
|
||||||
foreach (var child in toKnock)
|
foreach (var child in toKnock)
|
||||||
{
|
{
|
||||||
if (!_statusQuery.TryGetComponent(child, out var status))
|
_stuns.TryUpdateParalyzeDuration(child, _hyperspaceKnockdownTime);
|
||||||
continue;
|
|
||||||
|
|
||||||
_stuns.TryParalyze(child, _hyperspaceKnockdownTime, true, status);
|
|
||||||
|
|
||||||
// If the guy we knocked down is on a spaced tile, throw them too
|
// If the guy we knocked down is on a spaced tile, throw them too
|
||||||
if (grid != null)
|
if (grid != null)
|
||||||
|
|||||||
@@ -249,7 +249,7 @@ public sealed partial class ShuttleSystem
|
|||||||
|
|
||||||
if (direction.LengthSquared() > minsq)
|
if (direction.LengthSquared() > minsq)
|
||||||
{
|
{
|
||||||
_stuns.TryKnockdown(uid, knockdownTime, true);
|
_stuns.TryUpdateKnockdownDuration(uid, knockdownTime);
|
||||||
_throwing.TryThrow(uid, direction, physics, Transform(uid), _projQuery, direction.Length(), playSound: false);
|
_throwing.TryThrow(uid, direction, physics, Transform(uid), _projQuery, direction.Length(), playSound: false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
using Content.Server.Stunnable.Components;
|
using Content.Server.Stunnable.Components;
|
||||||
using Content.Shared.Standing;
|
using Content.Shared.Movement.Systems;
|
||||||
using Content.Shared.StatusEffect;
|
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using Robust.Shared.Physics.Dynamics;
|
|
||||||
using Content.Shared.Throwing;
|
using Content.Shared.Throwing;
|
||||||
using Robust.Shared.Physics.Events;
|
using Robust.Shared.Physics.Events;
|
||||||
|
|
||||||
@@ -12,6 +10,7 @@ namespace Content.Server.Stunnable
|
|||||||
internal sealed class StunOnCollideSystem : EntitySystem
|
internal sealed class StunOnCollideSystem : EntitySystem
|
||||||
{
|
{
|
||||||
[Dependency] private readonly StunSystem _stunSystem = default!;
|
[Dependency] private readonly StunSystem _stunSystem = default!;
|
||||||
|
[Dependency] private readonly MovementModStatusSystem _movementMod = default!;
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
@@ -22,15 +21,19 @@ namespace Content.Server.Stunnable
|
|||||||
|
|
||||||
private void TryDoCollideStun(EntityUid uid, StunOnCollideComponent component, EntityUid target)
|
private void TryDoCollideStun(EntityUid uid, StunOnCollideComponent component, EntityUid target)
|
||||||
{
|
{
|
||||||
if (!TryComp<StatusEffectsComponent>(target, out var status))
|
_stunSystem.TryUpdateStunDuration(target, component.StunAmount);
|
||||||
return;
|
|
||||||
|
|
||||||
_stunSystem.TryStun(target, component.StunAmount, component.Refresh, status);
|
_stunSystem.TryKnockdown(target, component.KnockdownAmount, component.Refresh, component.AutoStand, force: true);
|
||||||
|
|
||||||
_stunSystem.TryKnockdown(target, component.KnockdownAmount, component.Refresh, component.AutoStand);
|
_movementMod.TryUpdateMovementSpeedModDuration(
|
||||||
|
target,
|
||||||
_stunSystem.TrySlowdown(target, component.SlowdownAmount, component.Refresh, component.WalkSpeedModifier, component.SprintSpeedModifier, status);
|
MovementModStatusSystem.TaserSlowdown,
|
||||||
|
component.SlowdownAmount,
|
||||||
|
component.WalkSpeedModifier,
|
||||||
|
component.SprintSpeedModifier
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void HandleCollide(EntityUid uid, StunOnCollideComponent component, ref StartCollideEvent args)
|
private void HandleCollide(EntityUid uid, StunOnCollideComponent component, ref StartCollideEvent args)
|
||||||
{
|
{
|
||||||
if (args.OurFixtureId != component.FixtureID)
|
if (args.OurFixtureId != component.FixtureID)
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ public sealed class GoliathTentacleSystem : EntitySystem
|
|||||||
// TODO: animation
|
// TODO: animation
|
||||||
|
|
||||||
_popup.PopupPredicted(Loc.GetString("tentacle-ability-use-popup", ("entity", args.Performer)), args.Performer, args.Performer, type: PopupType.SmallCaution);
|
_popup.PopupPredicted(Loc.GetString("tentacle-ability-use-popup", ("entity", args.Performer)), args.Performer, args.Performer, type: PopupType.SmallCaution);
|
||||||
_stun.TryStun(args.Performer, TimeSpan.FromSeconds(0.8f), false);
|
_stun.TryAddStunDuration(args.Performer, TimeSpan.FromSeconds(0.8f));
|
||||||
|
|
||||||
var coords = args.Target;
|
var coords = args.Target;
|
||||||
List<EntityCoordinates> spawnPos = new();
|
List<EntityCoordinates> spawnPos = new();
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ using Content.Shared.Slippery;
|
|||||||
using Content.Shared.Sound;
|
using Content.Shared.Sound;
|
||||||
using Content.Shared.Sound.Components;
|
using Content.Shared.Sound.Components;
|
||||||
using Content.Shared.Speech;
|
using Content.Shared.Speech;
|
||||||
using Content.Shared.StatusEffect;
|
|
||||||
using Content.Shared.StatusEffectNew;
|
using Content.Shared.StatusEffectNew;
|
||||||
using Content.Shared.Stunnable;
|
using Content.Shared.Stunnable;
|
||||||
using Content.Shared.Traits.Assorted;
|
using Content.Shared.Traits.Assorted;
|
||||||
@@ -38,8 +37,8 @@ public sealed partial class SleepingSystem : EntitySystem
|
|||||||
[Dependency] private readonly SharedPopupSystem _popupSystem = default!;
|
[Dependency] private readonly SharedPopupSystem _popupSystem = default!;
|
||||||
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
||||||
[Dependency] private readonly SharedEmitSoundSystem _emitSound = default!;
|
[Dependency] private readonly SharedEmitSoundSystem _emitSound = default!;
|
||||||
[Dependency] private readonly StatusEffect.StatusEffectsSystem _statusEffectOld = default!;
|
[Dependency] private readonly StatusEffectsSystem _statusEffect = default!;
|
||||||
[Dependency] private readonly StatusEffectNew.StatusEffectsSystem _statusEffectNew = default!;
|
[Dependency] private readonly SharedStunSystem _stun = default!;
|
||||||
|
|
||||||
public static readonly EntProtoId SleepActionId = "ActionSleep";
|
public static readonly EntProtoId SleepActionId = "ActionSleep";
|
||||||
public static readonly EntProtoId WakeActionId = "ActionWake";
|
public static readonly EntProtoId WakeActionId = "ActionWake";
|
||||||
@@ -67,6 +66,8 @@ public sealed partial class SleepingSystem : EntitySystem
|
|||||||
SubscribeLocalEvent<SleepingComponent, ExaminedEvent>(OnExamined);
|
SubscribeLocalEvent<SleepingComponent, ExaminedEvent>(OnExamined);
|
||||||
SubscribeLocalEvent<SleepingComponent, GetVerbsEvent<AlternativeVerb>>(AddWakeVerb);
|
SubscribeLocalEvent<SleepingComponent, GetVerbsEvent<AlternativeVerb>>(AddWakeVerb);
|
||||||
SubscribeLocalEvent<SleepingComponent, InteractHandEvent>(OnInteractHand);
|
SubscribeLocalEvent<SleepingComponent, InteractHandEvent>(OnInteractHand);
|
||||||
|
SubscribeLocalEvent<SleepingComponent, StunEndAttemptEvent>(OnStunEndAttempt);
|
||||||
|
SubscribeLocalEvent<SleepingComponent, StandUpAttemptEvent>(OnStandUpAttempt);
|
||||||
|
|
||||||
SubscribeLocalEvent<ForcedSleepingStatusEffectComponent, StatusEffectAppliedEvent>(OnStatusEffectApplied);
|
SubscribeLocalEvent<ForcedSleepingStatusEffectComponent, StatusEffectAppliedEvent>(OnStatusEffectApplied);
|
||||||
SubscribeLocalEvent<SleepingComponent, UnbuckleAttemptEvent>(OnUnbuckleAttempt);
|
SubscribeLocalEvent<SleepingComponent, UnbuckleAttemptEvent>(OnUnbuckleAttempt);
|
||||||
@@ -106,9 +107,7 @@ public sealed partial class SleepingSystem : EntitySystem
|
|||||||
{
|
{
|
||||||
if (args.FellAsleep)
|
if (args.FellAsleep)
|
||||||
{
|
{
|
||||||
// Expiring status effects would remove the components needed for sleeping
|
// Just in case we're not using the sleeping status
|
||||||
_statusEffectOld.TryRemoveStatusEffect(ent.Owner, "Stun");
|
|
||||||
|
|
||||||
EnsureComp<StunnedComponent>(ent);
|
EnsureComp<StunnedComponent>(ent);
|
||||||
EnsureComp<KnockedDownComponent>(ent);
|
EnsureComp<KnockedDownComponent>(ent);
|
||||||
|
|
||||||
@@ -128,8 +127,9 @@ public sealed partial class SleepingSystem : EntitySystem
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
RemComp<StunnedComponent>(ent);
|
_stun.TryUnstun(ent.Owner);
|
||||||
RemComp<KnockedDownComponent>(ent);
|
_stun.TryStanding(ent.Owner, out _);
|
||||||
|
|
||||||
RemComp<SpamEmitSoundComponent>(ent);
|
RemComp<SpamEmitSoundComponent>(ent);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -174,6 +174,17 @@ public sealed partial class SleepingSystem : EntitySystem
|
|||||||
args.Cancelled = true;
|
args.Cancelled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnStunEndAttempt(Entity<SleepingComponent> ent, ref StunEndAttemptEvent args)
|
||||||
|
{
|
||||||
|
args.Cancelled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnStandUpAttempt(Entity<SleepingComponent> ent, ref StandUpAttemptEvent args)
|
||||||
|
{
|
||||||
|
// Shh the Urist McHands is sleeping...
|
||||||
|
args.Cancelled = true;
|
||||||
|
}
|
||||||
|
|
||||||
private void OnExamined(Entity<SleepingComponent> ent, ref ExaminedEvent args)
|
private void OnExamined(Entity<SleepingComponent> ent, ref ExaminedEvent args)
|
||||||
{
|
{
|
||||||
if (args.IsInDetailsRange)
|
if (args.IsInDetailsRange)
|
||||||
@@ -187,7 +198,6 @@ public sealed partial class SleepingSystem : EntitySystem
|
|||||||
if (!args.CanInteract || !args.CanAccess)
|
if (!args.CanInteract || !args.CanAccess)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var target = args.Target;
|
|
||||||
var user = args.User;
|
var user = args.User;
|
||||||
AlternativeVerb verb = new()
|
AlternativeVerb verb = new()
|
||||||
{
|
{
|
||||||
@@ -309,7 +319,7 @@ public sealed partial class SleepingSystem : EntitySystem
|
|||||||
if (!Resolve(ent, ref ent.Comp, false))
|
if (!Resolve(ent, ref ent.Comp, false))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!force && _statusEffectNew.HasEffectComp<ForcedSleepingStatusEffectComponent>(ent))
|
if (!force && _statusEffect.HasEffectComp<ForcedSleepingStatusEffectComponent>(ent))
|
||||||
{
|
{
|
||||||
if (user != null)
|
if (user != null)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -571,7 +571,7 @@ public sealed partial class ClimbSystem : VirtualController
|
|||||||
|
|
||||||
_damageableSystem.TryChangeDamage(args.Climber, component.ClimberDamage, origin: args.Climber);
|
_damageableSystem.TryChangeDamage(args.Climber, component.ClimberDamage, origin: args.Climber);
|
||||||
_damageableSystem.TryChangeDamage(uid, component.TableDamage, origin: args.Climber);
|
_damageableSystem.TryChangeDamage(uid, component.TableDamage, origin: args.Climber);
|
||||||
_stunSystem.TryParalyze(args.Climber, TimeSpan.FromSeconds(component.StunTime), true);
|
_stunSystem.TryUpdateParalyzeDuration(args.Climber, TimeSpan.FromSeconds(component.StunTime));
|
||||||
|
|
||||||
// Not shown to the user, since they already get a 'you climb on the glass table' popup
|
// Not shown to the user, since they already get a 'you climb on the glass table' popup
|
||||||
_popupSystem.PopupEntity(
|
_popupSystem.PopupEntity(
|
||||||
|
|||||||
@@ -129,7 +129,7 @@ public sealed class ClumsySystem : EntitySystem
|
|||||||
if (ent.Comp.GunShootFailDamage != null)
|
if (ent.Comp.GunShootFailDamage != null)
|
||||||
_damageable.TryChangeDamage(ent, ent.Comp.GunShootFailDamage, origin: ent);
|
_damageable.TryChangeDamage(ent, ent.Comp.GunShootFailDamage, origin: ent);
|
||||||
|
|
||||||
_stun.TryParalyze(ent, ent.Comp.GunShootFailStunTime, true);
|
_stun.TryUpdateParalyzeDuration(ent, ent.Comp.GunShootFailStunTime);
|
||||||
|
|
||||||
// Apply salt to the wound ("Honk!") (No idea what this comment means)
|
// Apply salt to the wound ("Honk!") (No idea what this comment means)
|
||||||
_audio.PlayPvs(ent.Comp.GunShootFailSound, ent);
|
_audio.PlayPvs(ent.Comp.GunShootFailSound, ent);
|
||||||
@@ -202,7 +202,7 @@ public sealed class ClumsySystem : EntitySystem
|
|||||||
_damageable.TryChangeDamage(target, bonkComp.BonkDamage, true);
|
_damageable.TryChangeDamage(target, bonkComp.BonkDamage, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
_stun.TryParalyze(target, stunTime, true);
|
_stun.TryUpdateParalyzeDuration(target, stunTime);
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ public sealed class DamageOnHighSpeedImpactSystem : EntitySystem
|
|||||||
component.LastHit = _gameTiming.CurTime;
|
component.LastHit = _gameTiming.CurTime;
|
||||||
|
|
||||||
if (_robustRandom.Prob(component.StunChance))
|
if (_robustRandom.Prob(component.StunChance))
|
||||||
_stun.TryStun(uid, TimeSpan.FromSeconds(component.StunSeconds), true);
|
_stun.TryUpdateStunDuration(uid, TimeSpan.FromSeconds(component.StunSeconds));
|
||||||
|
|
||||||
var damageScale = component.SpeedDamageFactor * speed / component.MinimumSpeed;
|
var damageScale = component.SpeedDamageFactor * speed / component.MinimumSpeed;
|
||||||
|
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ public sealed class DamageOnInteractSystem : EntitySystem
|
|||||||
|
|
||||||
// Attempt to paralyze the user after they have taken damage
|
// Attempt to paralyze the user after they have taken damage
|
||||||
if (_random.Prob(entity.Comp.StunChance))
|
if (_random.Prob(entity.Comp.StunChance))
|
||||||
_stun.TryParalyze(args.User, TimeSpan.FromSeconds(entity.Comp.StunSeconds), true);
|
_stun.TryUpdateParalyzeDuration(args.User, TimeSpan.FromSeconds(entity.Comp.StunSeconds));
|
||||||
}
|
}
|
||||||
// Check if the entity's Throw bool is false, or if the entity has the PullableComponent, then if the entity is currently being pulled.
|
// Check if the entity's Throw bool is false, or if the entity has the PullableComponent, then if the entity is currently being pulled.
|
||||||
// BeingPulled must be checked because the entity will be spastically thrown around without this.
|
// BeingPulled must be checked because the entity will be spastically thrown around without this.
|
||||||
|
|||||||
@@ -8,9 +8,12 @@ using Content.Shared.Damage.Events;
|
|||||||
using Content.Shared.Database;
|
using Content.Shared.Database;
|
||||||
using Content.Shared.Effects;
|
using Content.Shared.Effects;
|
||||||
using Content.Shared.FixedPoint;
|
using Content.Shared.FixedPoint;
|
||||||
|
using Content.Shared.Movement.Components;
|
||||||
|
using Content.Shared.Movement.Systems;
|
||||||
using Content.Shared.Projectiles;
|
using Content.Shared.Projectiles;
|
||||||
using Content.Shared.Rejuvenate;
|
using Content.Shared.Rejuvenate;
|
||||||
using Content.Shared.Rounding;
|
using Content.Shared.Rounding;
|
||||||
|
using Content.Shared.StatusEffectNew;
|
||||||
using Content.Shared.Stunnable;
|
using Content.Shared.Stunnable;
|
||||||
using Content.Shared.Throwing;
|
using Content.Shared.Throwing;
|
||||||
using Content.Shared.Weapons.Melee.Events;
|
using Content.Shared.Weapons.Melee.Events;
|
||||||
@@ -20,6 +23,7 @@ using Robust.Shared.Audio.Systems;
|
|||||||
using Robust.Shared.Configuration;
|
using Robust.Shared.Configuration;
|
||||||
using Robust.Shared.Network;
|
using Robust.Shared.Network;
|
||||||
using Robust.Shared.Player;
|
using Robust.Shared.Player;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
using Robust.Shared.Serialization;
|
using Robust.Shared.Serialization;
|
||||||
using Robust.Shared.Timing;
|
using Robust.Shared.Timing;
|
||||||
|
|
||||||
@@ -27,15 +31,19 @@ namespace Content.Shared.Damage.Systems;
|
|||||||
|
|
||||||
public abstract partial class SharedStaminaSystem : EntitySystem
|
public abstract partial class SharedStaminaSystem : EntitySystem
|
||||||
{
|
{
|
||||||
|
public static readonly EntProtoId StaminaLow = "StatusEffectStaminaLow";
|
||||||
|
|
||||||
|
[Dependency] private readonly IConfigurationManager _config = default!;
|
||||||
[Dependency] protected readonly IGameTiming Timing = default!;
|
[Dependency] protected readonly IGameTiming Timing = default!;
|
||||||
[Dependency] private readonly INetManager _net = default!;
|
[Dependency] private readonly INetManager _net = default!;
|
||||||
[Dependency] private readonly ISharedAdminLogManager _adminLogger = default!;
|
[Dependency] private readonly ISharedAdminLogManager _adminLogger = default!;
|
||||||
[Dependency] private readonly AlertsSystem _alerts = default!;
|
[Dependency] private readonly AlertsSystem _alerts = default!;
|
||||||
[Dependency] private readonly MetaDataSystem _metadata = default!;
|
[Dependency] private readonly MetaDataSystem _metadata = default!;
|
||||||
[Dependency] private readonly SharedColorFlashEffectSystem _color = default!;
|
[Dependency] private readonly MovementModStatusSystem _movementMod = default!;
|
||||||
[Dependency] protected readonly SharedStunSystem StunSystem = default!;
|
|
||||||
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
||||||
[Dependency] private readonly IConfigurationManager _config = default!;
|
[Dependency] private readonly SharedColorFlashEffectSystem _color = default!;
|
||||||
|
[Dependency] private readonly StatusEffectsSystem _status = default!;
|
||||||
|
[Dependency] protected readonly SharedStunSystem StunSystem = default!;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// How much of a buffer is there between the stun duration and when stuns can be re-applied.
|
/// How much of a buffer is there between the stun duration and when stuns can be re-applied.
|
||||||
@@ -113,8 +121,9 @@ public abstract partial class SharedStaminaSystem : EntitySystem
|
|||||||
}
|
}
|
||||||
|
|
||||||
entity.Comp.StaminaDamage = 0;
|
entity.Comp.StaminaDamage = 0;
|
||||||
AdjustSlowdown(entity.Owner);
|
AdjustStatus(entity.Owner);
|
||||||
RemComp<ActiveStaminaComponent>(entity);
|
RemComp<ActiveStaminaComponent>(entity);
|
||||||
|
_status.TryRemoveStatusEffect(entity, StaminaLow);
|
||||||
UpdateStaminaVisuals(entity);
|
UpdateStaminaVisuals(entity);
|
||||||
Dirty(entity);
|
Dirty(entity);
|
||||||
}
|
}
|
||||||
@@ -284,7 +293,7 @@ public abstract partial class SharedStaminaSystem : EntitySystem
|
|||||||
component.NextUpdate = nextUpdate;
|
component.NextUpdate = nextUpdate;
|
||||||
}
|
}
|
||||||
|
|
||||||
AdjustSlowdown(uid);
|
AdjustStatus(uid);
|
||||||
|
|
||||||
UpdateStaminaVisuals((uid, component));
|
UpdateStaminaVisuals((uid, component));
|
||||||
|
|
||||||
@@ -292,6 +301,7 @@ public abstract partial class SharedStaminaSystem : EntitySystem
|
|||||||
if (component.AfterCritical && oldDamage > component.StaminaDamage && component.StaminaDamage <= 0f)
|
if (component.AfterCritical && oldDamage > component.StaminaDamage && component.StaminaDamage <= 0f)
|
||||||
{
|
{
|
||||||
component.AfterCritical = false; // Since the recovery from the crit has been completed, we are no longer 'after crit'
|
component.AfterCritical = false; // Since the recovery from the crit has been completed, we are no longer 'after crit'
|
||||||
|
_status.TryRemoveStatusEffect(uid, StaminaLow);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!component.Critical)
|
if (!component.Critical)
|
||||||
@@ -384,7 +394,7 @@ public abstract partial class SharedStaminaSystem : EntitySystem
|
|||||||
component.Critical = true;
|
component.Critical = true;
|
||||||
component.StaminaDamage = component.CritThreshold;
|
component.StaminaDamage = component.CritThreshold;
|
||||||
|
|
||||||
if (StunSystem.TryParalyze(uid, component.StunTime, true))
|
if (StunSystem.TryUpdateParalyzeDuration(uid, component.StunTime))
|
||||||
StunSystem.TrySeeingStars(uid);
|
StunSystem.TrySeeingStars(uid);
|
||||||
|
|
||||||
// Give them buffer before being able to be re-stunned
|
// Give them buffer before being able to be re-stunned
|
||||||
@@ -412,18 +422,19 @@ public abstract partial class SharedStaminaSystem : EntitySystem
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adjusts the movement speed of an entity based on its current <see cref="StaminaComponent.StaminaDamage"/> value.
|
/// Adjusts the modifiers of the <see cref="StaminaLow"/> status effect entity and applies relevant statuses.
|
||||||
/// If the entity has a <see cref="SlowOnDamageComponent"/>, its custom damage-to-speed thresholds are used,
|
/// System iterates through the <see cref="StaminaComponent.StunModifierThresholds"/> to find correct movement modifer.
|
||||||
/// otherwise, a default set of thresholds is applied.
|
/// This modifier is saved to the Stamina Low Status Effect entity's <see cref="MovementModStatusEffectComponent"/>.
|
||||||
/// The method determines the closest applicable damage threshold below the crit limit and applies the corresponding
|
|
||||||
/// speed modifier using the stun system. If no threshold is met then the entity's speed is restored to normal.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="ent">Entity to update</param>
|
/// <param name="ent">Entity to update</param>
|
||||||
private void AdjustSlowdown(Entity<StaminaComponent?> ent)
|
private void AdjustStatus(Entity<StaminaComponent?> ent)
|
||||||
{
|
{
|
||||||
if (!Resolve(ent, ref ent.Comp))
|
if (!Resolve(ent, ref ent.Comp))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (!_status.TrySetStatusEffectDuration(ent, StaminaLow, out var status))
|
||||||
|
return;
|
||||||
|
|
||||||
var closest = FixedPoint2.Zero;
|
var closest = FixedPoint2.Zero;
|
||||||
|
|
||||||
// Iterate through the dictionary in the similar way as in Damage.SlowOnDamageSystem.OnRefreshMovespeed
|
// Iterate through the dictionary in the similar way as in Damage.SlowOnDamageSystem.OnRefreshMovespeed
|
||||||
@@ -435,7 +446,7 @@ public abstract partial class SharedStaminaSystem : EntitySystem
|
|||||||
closest = thres.Key;
|
closest = thres.Key;
|
||||||
}
|
}
|
||||||
|
|
||||||
StunSystem.UpdateStunModifiers(ent, ent.Comp.StunModifierThresholds[closest]);
|
_movementMod.TryUpdateMovementStatus(ent.Owner, status.Value, ent.Comp.StunModifierThresholds[closest]);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Serializable, NetSerializable]
|
[Serializable, NetSerializable]
|
||||||
|
|||||||
@@ -534,7 +534,7 @@ public abstract partial class SharedDoorSystem : EntitySystem
|
|||||||
if (door.CrushDamage != null)
|
if (door.CrushDamage != null)
|
||||||
_damageableSystem.TryChangeDamage(entity, door.CrushDamage, origin: uid);
|
_damageableSystem.TryChangeDamage(entity, door.CrushDamage, origin: uid);
|
||||||
|
|
||||||
_stunSystem.TryParalyze(entity, stunTime, true);
|
_stunSystem.TryUpdateParalyzeDuration(entity, stunTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (door.CurrentlyCrushing.Count == 0)
|
if (door.CurrentlyCrushing.Count == 0)
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
using Content.Shared.EntityEffects;
|
|
||||||
using Content.Shared.Stunnable;
|
using Content.Shared.Stunnable;
|
||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
@@ -14,9 +13,11 @@ public sealed partial class Paralyze : EntityEffect
|
|||||||
[DataField] public bool Refresh = true;
|
[DataField] public bool Refresh = true;
|
||||||
|
|
||||||
protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys)
|
protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys)
|
||||||
=> Loc.GetString("reagent-effect-guidebook-paralyze",
|
=> Loc.GetString(
|
||||||
|
"reagent-effect-guidebook-paralyze",
|
||||||
("chance", Probability),
|
("chance", Probability),
|
||||||
("time", ParalyzeTime));
|
("time", ParalyzeTime)
|
||||||
|
);
|
||||||
|
|
||||||
public override void Effect(EntityEffectBaseArgs args)
|
public override void Effect(EntityEffectBaseArgs args)
|
||||||
{
|
{
|
||||||
@@ -27,7 +28,10 @@ public sealed partial class Paralyze : EntityEffect
|
|||||||
paralyzeTime *= (double)reagentArgs.Scale;
|
paralyzeTime *= (double)reagentArgs.Scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
args.EntityManager.System<SharedStunSystem>().TryParalyze(args.TargetEntity, TimeSpan.FromSeconds(paralyzeTime), Refresh);
|
var stunSystem = args.EntityManager.System<SharedStunSystem>();
|
||||||
|
_ = Refresh
|
||||||
|
? stunSystem.TryUpdateParalyzeDuration(args.TargetEntity, TimeSpan.FromSeconds(paralyzeTime))
|
||||||
|
: stunSystem.TryAddParalyzeDuration(args.TargetEntity, TimeSpan.FromSeconds(paralyzeTime));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ using Robust.Shared.Prototypes;
|
|||||||
using Robust.Shared.Random;
|
using Robust.Shared.Random;
|
||||||
using Robust.Shared.Timing;
|
using Robust.Shared.Timing;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Content.Shared.Movement.Systems;
|
||||||
|
|
||||||
namespace Content.Shared.Flash;
|
namespace Content.Shared.Flash;
|
||||||
|
|
||||||
@@ -33,6 +34,7 @@ public abstract class SharedFlashSystem : EntitySystem
|
|||||||
[Dependency] private readonly ExamineSystemShared _examine = default!;
|
[Dependency] private readonly ExamineSystemShared _examine = default!;
|
||||||
[Dependency] private readonly SharedPopupSystem _popup = default!;
|
[Dependency] private readonly SharedPopupSystem _popup = default!;
|
||||||
[Dependency] private readonly SharedStunSystem _stun = default!;
|
[Dependency] private readonly SharedStunSystem _stun = default!;
|
||||||
|
[Dependency] private readonly MovementModStatusSystem _movementMod = default!;
|
||||||
[Dependency] private readonly TagSystem _tag = default!;
|
[Dependency] private readonly TagSystem _tag = default!;
|
||||||
[Dependency] private readonly StatusEffectsSystem _statusEffectsSystem = default!;
|
[Dependency] private readonly StatusEffectsSystem _statusEffectsSystem = default!;
|
||||||
[Dependency] private readonly IGameTiming _timing = default!;
|
[Dependency] private readonly IGameTiming _timing = default!;
|
||||||
@@ -163,9 +165,9 @@ public abstract class SharedFlashSystem : EntitySystem
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (stunDuration != null)
|
if (stunDuration != null)
|
||||||
_stun.TryParalyze(target, stunDuration.Value, true);
|
_stun.TryUpdateParalyzeDuration(target, stunDuration.Value);
|
||||||
else
|
else
|
||||||
_stun.TrySlowdown(target, flashDuration, true, slowTo, slowTo);
|
_movementMod.TryUpdateMovementSpeedModDuration(target, MovementModStatusSystem.FlashSlowdown, flashDuration, slowTo);
|
||||||
|
|
||||||
if (displayPopup && user != null && target != user && Exists(user.Value))
|
if (displayPopup && user != null && target != user && Exists(user.Value))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -510,8 +510,8 @@ public abstract class SharedMagicSystem : EntitySystem
|
|||||||
_mind.TransferTo(tarMind, ev.Performer);
|
_mind.TransferTo(tarMind, ev.Performer);
|
||||||
}
|
}
|
||||||
|
|
||||||
_stun.TryParalyze(ev.Target, ev.TargetStunDuration, true);
|
_stun.TryUpdateParalyzeDuration(ev.Target, ev.TargetStunDuration);
|
||||||
_stun.TryParalyze(ev.Performer, ev.PerformerStunDuration, true);
|
_stun.TryUpdateParalyzeDuration(ev.Performer, ev.PerformerStunDuration);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
using Content.Shared.Movement.Systems;
|
||||||
|
using Robust.Shared.GameStates;
|
||||||
|
|
||||||
|
namespace Content.Shared.Movement.Components;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This is used to store a movement speed modifier attached to a status effect entity so it can be applied via statuses.
|
||||||
|
/// To be used in conjunction with <see cref="MovementModStatusSystem"/>.
|
||||||
|
/// See <see cref="MovementModStatusComponent"/> for the component applied to the entity.
|
||||||
|
/// </summary>
|
||||||
|
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState, Access(typeof(MovementModStatusSystem))]
|
||||||
|
public sealed partial class MovementModStatusEffectComponent : Component
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Multiplicative sprint modifier, with bounds of [0, 1)
|
||||||
|
/// </summary>
|
||||||
|
[DataField, AutoNetworkedField]
|
||||||
|
public float SprintSpeedModifier = 0.5f;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Multiplicative walk modifier, with bounds of [0, 1)
|
||||||
|
/// </summary>
|
||||||
|
[DataField, AutoNetworkedField]
|
||||||
|
public float WalkSpeedModifier = 0.5f;
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
using Content.Shared.Movement.Components;
|
using Content.Shared.Movement.Components;
|
||||||
using Content.Shared.Movement.Events;
|
using Content.Shared.Movement.Events;
|
||||||
using Content.Shared.StatusEffectNew;
|
using Content.Shared.StatusEffectNew;
|
||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
@@ -6,23 +6,54 @@ using Robust.Shared.Prototypes;
|
|||||||
namespace Content.Shared.Movement.Systems;
|
namespace Content.Shared.Movement.Systems;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This handles the application of movement and friction modifiers to an entity as status effects.
|
/// This handles the slowed status effect and other movement status effects.
|
||||||
|
/// <see cref="MovementModStatusEffectComponent"/> holds a modifier for a status effect which is relayed to a mob's
|
||||||
|
/// All effects of this kinda are multiplicative.
|
||||||
|
/// Each 'source' of speed modification usually should have separate effect prototype.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Movement modifying status effects should by default be separate effect prototypes, and their effects
|
||||||
|
/// should stack with each other (multiply). In case multiplicative effect is undesirable - such effects
|
||||||
|
/// could occupy same prototype, but be aware that this will make controlling duration of effect
|
||||||
|
/// extra 'challenging', as it will be shared too.
|
||||||
|
/// </remarks>
|
||||||
public sealed class MovementModStatusSystem : EntitySystem
|
public sealed class MovementModStatusSystem : EntitySystem
|
||||||
{
|
{
|
||||||
|
public static readonly EntProtoId VomitingSlowdown = "VomitingSlowdownStatusEffect";
|
||||||
|
public static readonly EntProtoId TaserSlowdown = "TaserSlowdownStatusEffect";
|
||||||
|
public static readonly EntProtoId FlashSlowdown = "FlashSlowdownStatusEffect";
|
||||||
public static readonly EntProtoId StatusEffectFriction = "StatusEffectFriction";
|
public static readonly EntProtoId StatusEffectFriction = "StatusEffectFriction";
|
||||||
|
|
||||||
[Dependency] private readonly MovementSpeedModifierSystem _movementSpeedModifier = default!;
|
[Dependency] private readonly MovementSpeedModifierSystem _movementSpeedModifier = default!;
|
||||||
[Dependency] private readonly StatusEffectsSystem _status = default!;
|
[Dependency] private readonly StatusEffectsSystem _status = default!;
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
|
SubscribeLocalEvent<MovementModStatusEffectComponent, StatusEffectRemovedEvent>(OnMovementModRemoved);
|
||||||
|
SubscribeLocalEvent<MovementModStatusEffectComponent, StatusEffectRelayedEvent<RefreshMovementSpeedModifiersEvent>>(OnRefreshRelay);
|
||||||
SubscribeLocalEvent<FrictionStatusEffectComponent, StatusEffectRemovedEvent>(OnFrictionStatusEffectRemoved);
|
SubscribeLocalEvent<FrictionStatusEffectComponent, StatusEffectRemovedEvent>(OnFrictionStatusEffectRemoved);
|
||||||
SubscribeLocalEvent<FrictionStatusEffectComponent, StatusEffectRelayedEvent<RefreshFrictionModifiersEvent>>(OnRefreshFrictionStatus);
|
SubscribeLocalEvent<FrictionStatusEffectComponent, StatusEffectRelayedEvent<RefreshFrictionModifiersEvent>>(OnRefreshFrictionStatus);
|
||||||
SubscribeLocalEvent<FrictionStatusEffectComponent, StatusEffectRelayedEvent<TileFrictionEvent>>(OnRefreshTileFrictionStatus);
|
SubscribeLocalEvent<FrictionStatusEffectComponent, StatusEffectRelayedEvent<TileFrictionEvent>>(OnRefreshTileFrictionStatus);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnMovementModRemoved(Entity<MovementModStatusEffectComponent> ent, ref StatusEffectRemovedEvent args)
|
||||||
|
{
|
||||||
|
TryUpdateMovementStatus(args.Target, (ent, ent), 1f);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnFrictionStatusEffectRemoved(Entity<FrictionStatusEffectComponent> entity, ref StatusEffectRemovedEvent args)
|
||||||
|
{
|
||||||
|
TrySetFrictionStatus(entity!, 1f, args.Target);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnRefreshRelay(
|
||||||
|
Entity<MovementModStatusEffectComponent> entity,
|
||||||
|
ref StatusEffectRelayedEvent<RefreshMovementSpeedModifiersEvent> args
|
||||||
|
)
|
||||||
|
{
|
||||||
|
args.Args.ModifySpeed(entity.Comp.WalkSpeedModifier, entity.Comp.WalkSpeedModifier);
|
||||||
|
}
|
||||||
|
|
||||||
private void OnRefreshFrictionStatus(Entity<FrictionStatusEffectComponent> ent, ref StatusEffectRelayedEvent<RefreshFrictionModifiersEvent> args)
|
private void OnRefreshFrictionStatus(Entity<FrictionStatusEffectComponent> ent, ref StatusEffectRelayedEvent<RefreshFrictionModifiersEvent> args)
|
||||||
{
|
{
|
||||||
var ev = args.Args;
|
var ev = args.Args;
|
||||||
@@ -39,28 +70,169 @@ public sealed class MovementModStatusSystem : EntitySystem
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Applies a friction de-buff to the player.
|
/// Apply mob's walking/running speed modifier with provided duration, or increment duration of existing.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool TryFriction(EntityUid uid,
|
/// <param name="uid">Target entity, for which speed should be modified.</param>
|
||||||
TimeSpan time,
|
/// <param name="effectProtoId">Slowdown effect to be used.</param>
|
||||||
bool refresh,
|
/// <param name="duration">Duration of speed modifying effect.</param>
|
||||||
float friction,
|
/// <param name="speedModifier">Multiplier by which walking/sprinting speed should be modified.</param>
|
||||||
float acceleration)
|
/// <returns>True if entity have slowdown effect applied now or previously and duration was modified.</returns>
|
||||||
|
public bool TryAddMovementSpeedModDuration(
|
||||||
|
EntityUid uid,
|
||||||
|
EntProtoId effectProtoId,
|
||||||
|
TimeSpan duration,
|
||||||
|
float speedModifier
|
||||||
|
)
|
||||||
{
|
{
|
||||||
if (time <= TimeSpan.Zero)
|
return TryAddMovementSpeedModDuration(uid, effectProtoId, duration, speedModifier, speedModifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Apply mob's walking/running speed modifier with provided duration, or increment duration of existing.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="uid">Target entity, for which speed should be modified.</param>
|
||||||
|
/// <param name="effectProtoId">Slowdown effect to be used.</param>
|
||||||
|
/// <param name="duration">Duration of speed modifying effect.</param>
|
||||||
|
/// <param name="walkSpeedModifier">Multiplier by which walking speed should be modified.</param>
|
||||||
|
/// <param name="sprintSpeedModifier">Multiplier by which sprinting speed should be modified.</param>
|
||||||
|
/// <returns>True if entity have slowdown effect applied now or previously and duration was modified.</returns>
|
||||||
|
public bool TryAddMovementSpeedModDuration(
|
||||||
|
EntityUid uid,
|
||||||
|
EntProtoId effectProtoId,
|
||||||
|
TimeSpan duration,
|
||||||
|
float walkSpeedModifier,
|
||||||
|
float sprintSpeedModifier
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return _status.TryAddStatusEffectDuration(uid, effectProtoId, out var status, duration)
|
||||||
|
&& TryUpdateMovementStatus(uid, status!.Value, walkSpeedModifier, sprintSpeedModifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Apply mob's walking/running speed modifier with provided duration,
|
||||||
|
/// or update duration of existing if it is lesser than provided duration.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="uid">Target entity, for which speed should be modified.</param>
|
||||||
|
/// <param name="effectProtoId">Slowdown effect to be used.</param>
|
||||||
|
/// <param name="duration">Duration of speed modifying effect.</param>
|
||||||
|
/// <param name="speedModifier">Multiplier by which walking/sprinting speed should be modified.</param>
|
||||||
|
/// <returns>True if entity have slowdown effect applied now or previously and duration was modified.</returns>
|
||||||
|
public bool TryUpdateMovementSpeedModDuration(
|
||||||
|
EntityUid uid,
|
||||||
|
EntProtoId effectProtoId,
|
||||||
|
TimeSpan duration,
|
||||||
|
float speedModifier
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return TryUpdateMovementSpeedModDuration(uid, effectProtoId, duration, speedModifier, speedModifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Apply mob's walking/running speed modifier with provided duration,
|
||||||
|
/// or update duration of existing if it is lesser than provided duration.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="uid">Target entity, for which speed should be modified.</param>
|
||||||
|
/// <param name="effectProtoId">Slowdown effect to be used.</param>
|
||||||
|
/// <param name="duration">Duration of speed modifying effect.</param>
|
||||||
|
/// <param name="walkSpeedModifier">Multiplier by which walking speed should be modified.</param>
|
||||||
|
/// <param name="sprintSpeedModifier">Multiplier by which sprinting speed should be modified.</param>
|
||||||
|
/// <returns>True if entity have slowdown effect applied now or previously and duration was modified.</returns>
|
||||||
|
public bool TryUpdateMovementSpeedModDuration(
|
||||||
|
EntityUid uid,
|
||||||
|
EntProtoId effectProtoId,
|
||||||
|
TimeSpan? duration,
|
||||||
|
float walkSpeedModifier,
|
||||||
|
float sprintSpeedModifier
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return _status.TryUpdateStatusEffectDuration(uid, effectProtoId, out var status, duration)
|
||||||
|
&& TryUpdateMovementStatus(uid, status!.Value, walkSpeedModifier, sprintSpeedModifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Updates entity's movement speed using <see cref="MovementModStatusEffectComponent"/> to provided values.
|
||||||
|
/// Then refreshes the movement speed of the entity.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="uid">Entity whose component we're updating</param>
|
||||||
|
/// <param name="status">Status effect entity whose modifiers we are updating</param>
|
||||||
|
/// <param name="walkSpeedModifier">New walkSpeedModifer we're applying</param>
|
||||||
|
/// <param name="sprintSpeedModifier">New sprintSpeedModifier we're applying</param>
|
||||||
|
public bool TryUpdateMovementStatus(
|
||||||
|
EntityUid uid,
|
||||||
|
Entity<MovementModStatusEffectComponent?> status,
|
||||||
|
float walkSpeedModifier,
|
||||||
|
float sprintSpeedModifier
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (!Resolve(status, ref status.Comp))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (refresh)
|
status.Comp.SprintSpeedModifier = sprintSpeedModifier;
|
||||||
|
status.Comp.WalkSpeedModifier = walkSpeedModifier;
|
||||||
|
|
||||||
|
_movementSpeedModifier.RefreshMovementSpeedModifiers(uid);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Updates entity's movement speed using <see cref="MovementModStatusEffectComponent"/> to provided value.
|
||||||
|
/// Then refreshes the movement speed of the entity.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="uid">Entity whose component we're updating</param>
|
||||||
|
/// <param name="status">Status effect entity whose modifiers we are updating</param>
|
||||||
|
/// <param name="speedModifier">
|
||||||
|
/// Multiplier by which speed should be modified.
|
||||||
|
/// Will be applied to both walking and running speed.
|
||||||
|
/// </param>
|
||||||
|
public bool TryUpdateMovementStatus(
|
||||||
|
EntityUid uid,
|
||||||
|
Entity<MovementModStatusEffectComponent?> status,
|
||||||
|
float speedModifier
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return _status.TryUpdateStatusEffectDuration(uid, StatusEffectFriction, out var status, time)
|
return TryUpdateMovementStatus(uid, status, speedModifier, speedModifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Apply friction modifier with provided duration,
|
||||||
|
/// or incrementing duration of existing.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="uid">Target entity, for which friction modifier should be applied.</param>
|
||||||
|
/// <param name="duration">Duration of speed modifying effect.</param>
|
||||||
|
/// <param name="friction">Multiplier by which walking speed should be modified.</param>
|
||||||
|
/// <param name="acceleration">Multiplier by which sprinting speed should be modified.</param>
|
||||||
|
/// <returns>True if entity have slowdown effect applied now or previously and duration was modified.</returns>
|
||||||
|
public bool TryAddFrictionModDuration(
|
||||||
|
EntityUid uid,
|
||||||
|
TimeSpan duration,
|
||||||
|
float friction,
|
||||||
|
float acceleration
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return _status.TryAddStatusEffectDuration(uid, StatusEffectFriction, out var status, duration)
|
||||||
&& TrySetFrictionStatus(status.Value, friction, acceleration, uid);
|
&& TrySetFrictionStatus(status.Value, friction, acceleration, uid);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
/// <summary>
|
||||||
|
/// Apply friction modifier with provided duration,
|
||||||
|
/// or update duration of existing if it is lesser than provided duration.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="uid">Target entity, for which friction modifier should be applied.</param>
|
||||||
|
/// <param name="duration">Duration of speed modifying effect.</param>
|
||||||
|
/// <param name="friction">Multiplier by which walking speed should be modified.</param>
|
||||||
|
/// <param name="acceleration">Multiplier by which sprinting speed should be modified.</param>
|
||||||
|
/// <returns>True if entity have slowdown effect applied now or previously and duration was modified.</returns>
|
||||||
|
public bool TryUpdateFrictionModDuration(
|
||||||
|
EntityUid uid,
|
||||||
|
TimeSpan duration,
|
||||||
|
float friction,
|
||||||
|
float acceleration
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return _status.TryAddStatusEffectDuration(uid, StatusEffectFriction, out var status, time)
|
return _status.TryUpdateStatusEffectDuration(uid, StatusEffectFriction, out var status, duration)
|
||||||
&& TrySetFrictionStatus(status.Value, friction, acceleration, uid);
|
&& TrySetFrictionStatus(status.Value, friction, acceleration, uid);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sets the friction status modifiers for a status effect.
|
/// Sets the friction status modifiers for a status effect.
|
||||||
@@ -92,9 +264,4 @@ public sealed class MovementModStatusSystem : EntitySystem
|
|||||||
_movementSpeedModifier.RefreshFrictionModifiers(entity);
|
_movementSpeedModifier.RefreshFrictionModifiers(entity);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnFrictionStatusEffectRemoved(Entity<FrictionStatusEffectComponent> entity, ref StatusEffectRemovedEvent args)
|
|
||||||
{
|
|
||||||
TrySetFrictionStatus(entity!, 1f, args.Target);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ namespace Content.Shared.Nutrition.EntitySystems
|
|||||||
|
|
||||||
CreamedEntity(uid, creamPied, args);
|
CreamedEntity(uid, creamPied, args);
|
||||||
|
|
||||||
_stunSystem.TryParalyze(uid, TimeSpan.FromSeconds(creamPie.ParalyzeTime), true);
|
_stunSystem.TryUpdateParalyzeDuration(uid, TimeSpan.FromSeconds(creamPie.ParalyzeTime));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void CreamedEntity(EntityUid uid, CreamPiedComponent creamPied, ThrowHitByEvent args) {}
|
protected virtual void CreamedEntity(EntityUid uid, CreamPiedComponent creamPied, ThrowHitByEvent args) {}
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ public abstract class SharedRevolutionarySystem : EntitySystem
|
|||||||
var stunTime = TimeSpan.FromSeconds(4);
|
var stunTime = TimeSpan.FromSeconds(4);
|
||||||
var name = Identity.Entity(uid, EntityManager);
|
var name = Identity.Entity(uid, EntityManager);
|
||||||
RemComp<RevolutionaryComponent>(uid);
|
RemComp<RevolutionaryComponent>(uid);
|
||||||
_sharedStun.TryParalyze(uid, stunTime, true);
|
_sharedStun.TryUpdateParalyzeDuration(uid, stunTime);
|
||||||
_popupSystem.PopupEntity(Loc.GetString("rev-break-control", ("name", name)), uid);
|
_popupSystem.PopupEntity(Loc.GetString("rev-break-control", ("name", name)), uid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using Content.Shared.Emag.Systems;
|
using Content.Shared.Emag.Systems;
|
||||||
using Content.Shared.Mind;
|
using Content.Shared.Mind;
|
||||||
using Content.Shared.Popups;
|
using Content.Shared.Popups;
|
||||||
using Content.Shared.Silicons.Laws.Components;
|
using Content.Shared.Silicons.Laws.Components;
|
||||||
@@ -57,7 +57,7 @@ public abstract partial class SharedSiliconLawSystem : EntitySystem
|
|||||||
if(_mind.TryGetMind(uid, out var mindId, out _))
|
if(_mind.TryGetMind(uid, out var mindId, out _))
|
||||||
EnsureSubvertedSiliconRole(mindId);
|
EnsureSubvertedSiliconRole(mindId);
|
||||||
|
|
||||||
_stunSystem.TryParalyze(uid, component.StunTime, true);
|
_stunSystem.TryUpdateParalyzeDuration(uid, component.StunTime);
|
||||||
|
|
||||||
args.Handled = true;
|
args.Handled = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,11 +2,9 @@ using Content.Shared.Administration.Logs;
|
|||||||
using Content.Shared.Damage.Systems;
|
using Content.Shared.Damage.Systems;
|
||||||
using Content.Shared.Database;
|
using Content.Shared.Database;
|
||||||
using Content.Shared.Inventory;
|
using Content.Shared.Inventory;
|
||||||
using Robust.Shared.Network;
|
|
||||||
using Content.Shared.Movement.Components;
|
using Content.Shared.Movement.Components;
|
||||||
using Content.Shared.Movement.Systems;
|
using Content.Shared.Movement.Systems;
|
||||||
using Content.Shared.Popups;
|
using Content.Shared.StatusEffectNew;
|
||||||
using Content.Shared.StatusEffect;
|
|
||||||
using Content.Shared.StepTrigger.Systems;
|
using Content.Shared.StepTrigger.Systems;
|
||||||
using Content.Shared.Stunnable;
|
using Content.Shared.Stunnable;
|
||||||
using Content.Shared.Throwing;
|
using Content.Shared.Throwing;
|
||||||
@@ -16,7 +14,6 @@ using Robust.Shared.Containers;
|
|||||||
using Robust.Shared.Physics.Components;
|
using Robust.Shared.Physics.Components;
|
||||||
using Robust.Shared.Physics.Systems;
|
using Robust.Shared.Physics.Systems;
|
||||||
using Robust.Shared.Physics.Events;
|
using Robust.Shared.Physics.Events;
|
||||||
using Robust.Shared.Utility;
|
|
||||||
|
|
||||||
namespace Content.Shared.Slippery;
|
namespace Content.Shared.Slippery;
|
||||||
|
|
||||||
@@ -27,8 +24,8 @@ public sealed class SlipperySystem : EntitySystem
|
|||||||
[Dependency] private readonly MovementModStatusSystem _movementMod = default!;
|
[Dependency] private readonly MovementModStatusSystem _movementMod = default!;
|
||||||
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
||||||
[Dependency] private readonly SharedStunSystem _stun = default!;
|
[Dependency] private readonly SharedStunSystem _stun = default!;
|
||||||
|
[Dependency] private readonly StatusEffectsSystem _status = default!;
|
||||||
[Dependency] private readonly SharedStaminaSystem _stamina = default!;
|
[Dependency] private readonly SharedStaminaSystem _stamina = default!;
|
||||||
[Dependency] private readonly StatusEffectsSystem _statusEffects = default!;
|
|
||||||
[Dependency] private readonly SharedContainerSystem _container = default!;
|
[Dependency] private readonly SharedContainerSystem _container = default!;
|
||||||
[Dependency] private readonly SharedPhysicsSystem _physics = default!;
|
[Dependency] private readonly SharedPhysicsSystem _physics = default!;
|
||||||
[Dependency] private readonly SpeedModifierContactsSystem _speedModifier = default!;
|
[Dependency] private readonly SpeedModifierContactsSystem _speedModifier = default!;
|
||||||
@@ -90,7 +87,7 @@ public sealed class SlipperySystem : EntitySystem
|
|||||||
private bool CanSlip(EntityUid uid, EntityUid toSlip)
|
private bool CanSlip(EntityUid uid, EntityUid toSlip)
|
||||||
{
|
{
|
||||||
return !_container.IsEntityInContainer(uid)
|
return !_container.IsEntityInContainer(uid)
|
||||||
&& _statusEffects.CanApplyEffect(toSlip, "Stun"); //Should be KnockedDown instead?
|
&& _status.CanAddStatusEffect(toSlip, SharedStunSystem.StunId); //Should be KnockedDown instead?
|
||||||
}
|
}
|
||||||
|
|
||||||
public void TrySlip(EntityUid uid, SlipperyComponent component, EntityUid other, bool requiresContact = true)
|
public void TrySlip(EntityUid uid, SlipperyComponent component, EntityUid other, bool requiresContact = true)
|
||||||
@@ -125,12 +122,18 @@ public sealed class SlipperySystem : EntitySystem
|
|||||||
// Preventing from playing the slip sound and stunning when you are already knocked down.
|
// Preventing from playing the slip sound and stunning when you are already knocked down.
|
||||||
if (!HasComp<KnockedDownComponent>(other))
|
if (!HasComp<KnockedDownComponent>(other))
|
||||||
{
|
{
|
||||||
_stun.TryStun(other, component.SlipData.StunTime, true);
|
_stun.TryUpdateStunDuration(other, component.SlipData.StunTime);
|
||||||
_stamina.TakeStaminaDamage(other, component.StaminaDamage); // Note that this can stamCrit
|
_stamina.TakeStaminaDamage(other, component.StaminaDamage); // Note that this can stamCrit
|
||||||
_movementMod.TryFriction(other, component.FrictionStatusTime, true, component.SlipData.SlipFriction, component.SlipData.SlipFriction);
|
_movementMod.TryUpdateFrictionModDuration(
|
||||||
|
other,
|
||||||
|
component.FrictionStatusTime,
|
||||||
|
component.SlipData.SlipFriction,
|
||||||
|
component.SlipData.SlipFriction
|
||||||
|
);
|
||||||
_audio.PlayPredicted(component.SlipSound, other, other);
|
_audio.PlayPredicted(component.SlipSound, other, other);
|
||||||
}
|
}
|
||||||
_stun.TryKnockdown(other, component.SlipData.KnockdownTime, true, true);
|
|
||||||
|
_stun.TryKnockdown(other, component.SlipData.KnockdownTime, true, force: true);
|
||||||
|
|
||||||
_adminLogger.Add(LogType.Slip, LogImpact.Low, $"{ToPrettyString(other):mob} slipped on collision with {ToPrettyString(uid):entity}");
|
_adminLogger.Add(LogType.Slip, LogImpact.Low, $"{ToPrettyString(other):mob} slipped on collision with {ToPrettyString(uid):entity}");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ public sealed partial class ReformSystem : EntitySystem
|
|||||||
{
|
{
|
||||||
// Stun them when they use the action for the amount of reform time.
|
// Stun them when they use the action for the amount of reform time.
|
||||||
if (comp.ShouldStun)
|
if (comp.ShouldStun)
|
||||||
_stunSystem.TryStun(uid, TimeSpan.FromSeconds(comp.ReformTime), true);
|
_stunSystem.TryUpdateStunDuration(uid, TimeSpan.FromSeconds(comp.ReformTime));
|
||||||
_popupSystem.PopupClient(Loc.GetString(comp.PopupText, ("name", uid)), uid, uid);
|
_popupSystem.PopupClient(Loc.GetString(comp.PopupText, ("name", uid)), uid, uid);
|
||||||
|
|
||||||
// Create a doafter & start it
|
// Create a doafter & start it
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ public sealed partial class StatusEffectsSystem
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
///<inheritdoc cref="TryAddStatusEffectDuration(Robust.Shared.GameObjects.EntityUid,Robust.Shared.Prototypes.EntProtoId,out Robust.Shared.GameObjects.EntityUid?,System.TimeSpan)"/>
|
///<inheritdoc cref="TryAddStatusEffectDuration(EntityUid,EntProtoId,out EntityUid?,TimeSpan)"/>
|
||||||
public bool TryAddStatusEffectDuration(EntityUid target, EntProtoId effectProto, TimeSpan duration)
|
public bool TryAddStatusEffectDuration(EntityUid target, EntProtoId effectProto, TimeSpan duration)
|
||||||
{
|
{
|
||||||
return TryAddStatusEffectDuration(target, effectProto, out _, duration);
|
return TryAddStatusEffectDuration(target, effectProto, out _, duration);
|
||||||
@@ -61,7 +61,7 @@ public sealed partial class StatusEffectsSystem
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc cref="TrySetStatusEffectDuration(Robust.Shared.GameObjects.EntityUid,Robust.Shared.Prototypes.EntProtoId,out Robust.Shared.GameObjects.EntityUid?,System.TimeSpan?)"/>
|
/// <inheritdoc cref="TrySetStatusEffectDuration(EntityUid,EntProtoId,out EntityUid?,TimeSpan?)"/>
|
||||||
public bool TrySetStatusEffectDuration(EntityUid target, EntProtoId effectProto, TimeSpan? duration = null)
|
public bool TrySetStatusEffectDuration(EntityUid target, EntProtoId effectProto, TimeSpan? duration = null)
|
||||||
{
|
{
|
||||||
return TrySetStatusEffectDuration(target, effectProto, out _, duration);
|
return TrySetStatusEffectDuration(target, effectProto, out _, duration);
|
||||||
@@ -91,7 +91,7 @@ public sealed partial class StatusEffectsSystem
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc cref="TryUpdateStatusEffectDuration(Robust.Shared.GameObjects.EntityUid,Robust.Shared.Prototypes.EntProtoId,out Robust.Shared.GameObjects.EntityUid?,System.TimeSpan?)"/>
|
/// <inheritdoc cref="TryUpdateStatusEffectDuration(EntityUid,EntProtoId,out EntityUid?,TimeSpan?)"/>
|
||||||
public bool TryUpdateStatusEffectDuration(EntityUid target, EntProtoId effectProto, TimeSpan? duration = null)
|
public bool TryUpdateStatusEffectDuration(EntityUid target, EntProtoId effectProto, TimeSpan? duration = null)
|
||||||
{
|
{
|
||||||
return TryUpdateStatusEffectDuration(target, effectProto, out _, duration);
|
return TryUpdateStatusEffectDuration(target, effectProto, out _, duration);
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using Content.Shared.Movement.Events;
|
using Content.Shared.Movement.Events;
|
||||||
using Content.Shared.Movement.Systems;
|
using Content.Shared.Movement.Systems;
|
||||||
using Content.Shared.StatusEffectNew.Components;
|
using Content.Shared.StatusEffectNew.Components;
|
||||||
|
using Content.Shared.Stunnable;
|
||||||
using Robust.Shared.Player;
|
using Robust.Shared.Player;
|
||||||
|
|
||||||
namespace Content.Shared.StatusEffectNew;
|
namespace Content.Shared.StatusEffectNew;
|
||||||
@@ -12,8 +13,14 @@ public sealed partial class StatusEffectsSystem
|
|||||||
SubscribeLocalEvent<StatusEffectContainerComponent, LocalPlayerAttachedEvent>(RelayStatusEffectEvent);
|
SubscribeLocalEvent<StatusEffectContainerComponent, LocalPlayerAttachedEvent>(RelayStatusEffectEvent);
|
||||||
SubscribeLocalEvent<StatusEffectContainerComponent, LocalPlayerDetachedEvent>(RelayStatusEffectEvent);
|
SubscribeLocalEvent<StatusEffectContainerComponent, LocalPlayerDetachedEvent>(RelayStatusEffectEvent);
|
||||||
|
|
||||||
|
SubscribeLocalEvent<StatusEffectContainerComponent, RefreshMovementSpeedModifiersEvent>(RelayStatusEffectEvent);
|
||||||
|
SubscribeLocalEvent<StatusEffectContainerComponent, UpdateCanMoveEvent>(RelayStatusEffectEvent);
|
||||||
|
|
||||||
SubscribeLocalEvent<StatusEffectContainerComponent, RefreshFrictionModifiersEvent>(RefRelayStatusEffectEvent);
|
SubscribeLocalEvent<StatusEffectContainerComponent, RefreshFrictionModifiersEvent>(RefRelayStatusEffectEvent);
|
||||||
SubscribeLocalEvent<StatusEffectContainerComponent, TileFrictionEvent>(RefRelayStatusEffectEvent);
|
SubscribeLocalEvent<StatusEffectContainerComponent, TileFrictionEvent>(RefRelayStatusEffectEvent);
|
||||||
|
|
||||||
|
SubscribeLocalEvent<StatusEffectContainerComponent, StandUpAttemptEvent>(RefRelayStatusEffectEvent);
|
||||||
|
SubscribeLocalEvent<StatusEffectContainerComponent, StunEndAttemptEvent>(RefRelayStatusEffectEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RefRelayStatusEffectEvent<T>(EntityUid uid, StatusEffectContainerComponent component, ref T args) where T : struct
|
private void RefRelayStatusEffectEvent<T>(EntityUid uid, StatusEffectContainerComponent component, ref T args) where T : struct
|
||||||
|
|||||||
@@ -156,7 +156,7 @@ public sealed partial class StatusEffectsSystem : EntitySystem
|
|||||||
Dirty(effect, effectComp);
|
Dirty(effect, effectComp);
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool CanAddStatusEffect(EntityUid uid, EntProtoId effectProto)
|
public bool CanAddStatusEffect(EntityUid uid, EntProtoId effectProto)
|
||||||
{
|
{
|
||||||
if (!_proto.TryIndex(effectProto, out var effectProtoData))
|
if (!_proto.TryIndex(effectProto, out var effectProtoData))
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
using Robust.Shared.GameStates;
|
||||||
|
|
||||||
|
namespace Content.Shared.Stunnable;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Knockdown as a status effect.
|
||||||
|
/// </summary>
|
||||||
|
[RegisterComponent, NetworkedComponent, Access(typeof(SharedStunSystem))]
|
||||||
|
public sealed partial class KnockdownStatusEffectComponent : Component;
|
||||||
@@ -51,7 +51,7 @@ public abstract partial class SharedStunSystem
|
|||||||
|
|
||||||
// Action blockers
|
// Action blockers
|
||||||
SubscribeLocalEvent<KnockedDownComponent, BuckleAttemptEvent>(OnBuckleAttempt);
|
SubscribeLocalEvent<KnockedDownComponent, BuckleAttemptEvent>(OnBuckleAttempt);
|
||||||
SubscribeLocalEvent<KnockedDownComponent, StandAttemptEvent>(OnStandUpAttempt);
|
SubscribeLocalEvent<KnockedDownComponent, StandAttemptEvent>(OnStandAttempt);
|
||||||
|
|
||||||
// Updating movement a friction
|
// Updating movement a friction
|
||||||
SubscribeLocalEvent<KnockedDownComponent, RefreshMovementSpeedModifiersEvent>(OnRefreshKnockedSpeed);
|
SubscribeLocalEvent<KnockedDownComponent, RefreshMovementSpeedModifiersEvent>(OnRefreshKnockedSpeed);
|
||||||
@@ -452,7 +452,7 @@ public abstract partial class SharedStunSystem
|
|||||||
|
|
||||||
#region Action Blockers
|
#region Action Blockers
|
||||||
|
|
||||||
private void OnStandUpAttempt(Entity<KnockedDownComponent> entity, ref StandAttemptEvent args)
|
private void OnStandAttempt(Entity<KnockedDownComponent> entity, ref StandAttemptEvent args)
|
||||||
{
|
{
|
||||||
if (entity.Comp.LifeStage <= ComponentLifeStage.Running)
|
if (entity.Comp.LifeStage <= ComponentLifeStage.Running)
|
||||||
args.Cancel();
|
args.Cancel();
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ using Content.Shared.Alert;
|
|||||||
using Content.Shared.Interaction.Events;
|
using Content.Shared.Interaction.Events;
|
||||||
using Content.Shared.Inventory.Events;
|
using Content.Shared.Inventory.Events;
|
||||||
using Content.Shared.Item;
|
using Content.Shared.Item;
|
||||||
using Content.Shared.Damage.Components;
|
|
||||||
using Content.Shared.Damage.Systems;
|
using Content.Shared.Damage.Systems;
|
||||||
using Content.Shared.Database;
|
using Content.Shared.Database;
|
||||||
using Content.Shared.DoAfter;
|
using Content.Shared.DoAfter;
|
||||||
@@ -14,35 +13,35 @@ using Content.Shared.Mobs.Components;
|
|||||||
using Content.Shared.Movement.Events;
|
using Content.Shared.Movement.Events;
|
||||||
using Content.Shared.Movement.Systems;
|
using Content.Shared.Movement.Systems;
|
||||||
using Content.Shared.Standing;
|
using Content.Shared.Standing;
|
||||||
using Content.Shared.StatusEffect;
|
using Content.Shared.StatusEffectNew;
|
||||||
using Content.Shared.Throwing;
|
using Content.Shared.Throwing;
|
||||||
using Content.Shared.Whitelist;
|
using Content.Shared.Whitelist;
|
||||||
using Robust.Shared.Audio.Systems;
|
using Robust.Shared.Audio.Systems;
|
||||||
using Robust.Shared.Physics.Events;
|
using Robust.Shared.Physics.Events;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
using Robust.Shared.Timing;
|
using Robust.Shared.Timing;
|
||||||
|
|
||||||
namespace Content.Shared.Stunnable;
|
namespace Content.Shared.Stunnable;
|
||||||
|
|
||||||
public abstract partial class SharedStunSystem : EntitySystem
|
public abstract partial class SharedStunSystem : EntitySystem
|
||||||
{
|
{
|
||||||
[Dependency] protected readonly ActionBlockerSystem Blocker = default!;
|
public static readonly EntProtoId StunId = "StatusEffectStunned";
|
||||||
[Dependency] protected readonly AlertsSystem Alerts = default!;
|
public static readonly EntProtoId KnockdownId = "StatusEffectKnockdown";
|
||||||
|
|
||||||
[Dependency] protected readonly IGameTiming GameTiming = default!;
|
[Dependency] protected readonly IGameTiming GameTiming = default!;
|
||||||
[Dependency] private readonly ISharedAdminLogManager _adminLogger = default!;
|
[Dependency] private readonly ISharedAdminLogManager _adminLogger = default!;
|
||||||
|
[Dependency] protected readonly ActionBlockerSystem Blocker = default!;
|
||||||
|
[Dependency] protected readonly AlertsSystem Alerts = default!;
|
||||||
[Dependency] private readonly EntityWhitelistSystem _entityWhitelist = default!;
|
[Dependency] private readonly EntityWhitelistSystem _entityWhitelist = default!;
|
||||||
[Dependency] private readonly MovementSpeedModifierSystem _movementSpeedModifier = default!;
|
[Dependency] private readonly MovementSpeedModifierSystem _movementSpeedModifier = default!;
|
||||||
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
||||||
[Dependency] protected readonly SharedAppearanceSystem Appearance = default!;
|
[Dependency] protected readonly SharedAppearanceSystem Appearance = default!;
|
||||||
[Dependency] protected readonly SharedDoAfterSystem DoAfter = default!;
|
[Dependency] protected readonly SharedDoAfterSystem DoAfter = default!;
|
||||||
[Dependency] protected readonly SharedStaminaSystem Stamina = default!;
|
[Dependency] protected readonly SharedStaminaSystem Stamina = default!;
|
||||||
[Dependency] private readonly StatusEffectsSystem _statusEffect = default!;
|
[Dependency] private readonly StatusEffectsSystem _status = default!;
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
SubscribeLocalEvent<SlowedDownComponent, ComponentInit>(OnSlowInit);
|
|
||||||
SubscribeLocalEvent<SlowedDownComponent, ComponentShutdown>(OnSlowRemove);
|
|
||||||
SubscribeLocalEvent<SlowedDownComponent, RefreshMovementSpeedModifiersEvent>(OnRefreshMovespeed);
|
|
||||||
|
|
||||||
SubscribeLocalEvent<StunnedComponent, ComponentStartup>(UpdateCanMove);
|
SubscribeLocalEvent<StunnedComponent, ComponentStartup>(UpdateCanMove);
|
||||||
SubscribeLocalEvent<StunnedComponent, ComponentShutdown>(OnStunShutdown);
|
SubscribeLocalEvent<StunnedComponent, ComponentShutdown>(OnStunShutdown);
|
||||||
|
|
||||||
@@ -61,6 +60,14 @@ public abstract partial class SharedStunSystem : EntitySystem
|
|||||||
SubscribeLocalEvent<StunnedComponent, IsUnequippingAttemptEvent>(OnUnequipAttempt);
|
SubscribeLocalEvent<StunnedComponent, IsUnequippingAttemptEvent>(OnUnequipAttempt);
|
||||||
SubscribeLocalEvent<MobStateComponent, MobStateChangedEvent>(OnMobStateChanged);
|
SubscribeLocalEvent<MobStateComponent, MobStateChangedEvent>(OnMobStateChanged);
|
||||||
|
|
||||||
|
// New Status Effect subscriptions
|
||||||
|
SubscribeLocalEvent<StunnedStatusEffectComponent, StatusEffectAppliedEvent>(OnStunEffectApplied);
|
||||||
|
SubscribeLocalEvent<StunnedStatusEffectComponent, StatusEffectRemovedEvent>(OnStunStatusRemoved);
|
||||||
|
SubscribeLocalEvent<StunnedStatusEffectComponent, StatusEffectRelayedEvent<StunEndAttemptEvent>>(OnStunEndAttempt);
|
||||||
|
|
||||||
|
SubscribeLocalEvent<KnockdownStatusEffectComponent, StatusEffectRelayedEvent<StandUpAttemptEvent>>(OnStandUpAttempt);
|
||||||
|
|
||||||
|
// Stun Appearance Data
|
||||||
InitializeKnockdown();
|
InitializeKnockdown();
|
||||||
InitializeAppearance();
|
InitializeAppearance();
|
||||||
}
|
}
|
||||||
@@ -72,10 +79,6 @@ public abstract partial class SharedStunSystem : EntitySystem
|
|||||||
|
|
||||||
private void OnMobStateChanged(EntityUid uid, MobStateComponent component, MobStateChangedEvent args)
|
private void OnMobStateChanged(EntityUid uid, MobStateComponent component, MobStateChangedEvent args)
|
||||||
{
|
{
|
||||||
if (!TryComp<StatusEffectsComponent>(uid, out var status))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
switch (args.NewMobState)
|
switch (args.NewMobState)
|
||||||
{
|
{
|
||||||
case MobState.Alive:
|
case MobState.Alive:
|
||||||
@@ -84,12 +87,12 @@ public abstract partial class SharedStunSystem : EntitySystem
|
|||||||
}
|
}
|
||||||
case MobState.Critical:
|
case MobState.Critical:
|
||||||
{
|
{
|
||||||
_statusEffect.TryRemoveStatusEffect(uid, "Stun");
|
_status.TryRemoveStatusEffect(uid, StunId);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MobState.Dead:
|
case MobState.Dead:
|
||||||
{
|
{
|
||||||
_statusEffect.TryRemoveStatusEffect(uid, "Stun");
|
_status.TryRemoveStatusEffect(uid, StunId);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MobState.Invalid:
|
case MobState.Invalid:
|
||||||
@@ -119,71 +122,95 @@ public abstract partial class SharedStunSystem : EntitySystem
|
|||||||
if (_entityWhitelist.IsBlacklistPass(ent.Comp.Blacklist, args.OtherEntity))
|
if (_entityWhitelist.IsBlacklistPass(ent.Comp.Blacklist, args.OtherEntity))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!TryComp<StatusEffectsComponent>(args.OtherEntity, out var status))
|
TryUpdateStunDuration(args.OtherEntity, ent.Comp.Duration);
|
||||||
return;
|
TryKnockdown(args.OtherEntity, ent.Comp.Duration, true, force: true);
|
||||||
|
|
||||||
TryStun(args.OtherEntity, ent.Comp.Duration, true, status);
|
|
||||||
TryKnockdown(args.OtherEntity, ent.Comp.Duration, ent.Comp.Refresh, ent.Comp.AutoStand);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnSlowInit(EntityUid uid, SlowedDownComponent component, ComponentInit args)
|
|
||||||
{
|
|
||||||
_movementSpeedModifier.RefreshMovementSpeedModifiers(uid);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnSlowRemove(EntityUid uid, SlowedDownComponent component, ComponentShutdown args)
|
|
||||||
{
|
|
||||||
component.SprintSpeedModifier = 1f;
|
|
||||||
component.WalkSpeedModifier = 1f;
|
|
||||||
_movementSpeedModifier.RefreshMovementSpeedModifiers(uid);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO STUN: Make events for different things. (Getting modifiers, attempt events, informative events...)
|
// TODO STUN: Make events for different things. (Getting modifiers, attempt events, informative events...)
|
||||||
|
public bool TryAddStunDuration(EntityUid uid, TimeSpan duration)
|
||||||
/// <summary>
|
|
||||||
/// Stuns the entity, disallowing it from doing many interactions temporarily.
|
|
||||||
/// </summary>
|
|
||||||
public bool TryStun(EntityUid uid, TimeSpan time, bool refresh, StatusEffectsComponent? status = null)
|
|
||||||
{
|
{
|
||||||
if (time <= TimeSpan.Zero)
|
if (!_status.TryAddStatusEffectDuration(uid, StunId, duration))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!Resolve(uid, ref status, false))
|
OnStunnedSuccessfully(uid, duration);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool TryUpdateStunDuration(EntityUid uid, TimeSpan? duration)
|
||||||
|
{
|
||||||
|
if (!_status.TryUpdateStatusEffectDuration(uid, StunId, duration))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!_statusEffect.TryAddStatusEffect<StunnedComponent>(uid, "Stun", time, refresh))
|
OnStunnedSuccessfully(uid, duration);
|
||||||
return false;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
var ev = new StunnedEvent();
|
private void OnStunnedSuccessfully(EntityUid uid, TimeSpan? duration)
|
||||||
|
{
|
||||||
|
var ev = new StunnedEvent(); // todo: rename event or change how it is raised - this event is raised each time duration of stun was externally changed
|
||||||
RaiseLocalEvent(uid, ref ev);
|
RaiseLocalEvent(uid, ref ev);
|
||||||
|
|
||||||
_adminLogger.Add(LogType.Stamina, LogImpact.Medium, $"{ToPrettyString(uid):user} stunned for {time.Seconds} seconds");
|
var timeForLogs = duration.HasValue
|
||||||
|
? duration.Value.Seconds.ToString()
|
||||||
|
: "Infinite";
|
||||||
|
_adminLogger.Add(LogType.Stamina, LogImpact.Medium, $"{ToPrettyString(uid):user} stunned for {timeForLogs} seconds");
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool TryAddKnockdownDuration(EntityUid uid, TimeSpan duration)
|
||||||
|
{
|
||||||
|
if (!_status.TryAddStatusEffectDuration(uid, KnockdownId, duration))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
TryKnockdown(uid, duration, true, force: true);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool TryUpdateKnockdownDuration(EntityUid uid, TimeSpan? duration)
|
||||||
|
{
|
||||||
|
if (!_status.TryUpdateStatusEffectDuration(uid, KnockdownId, duration))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return TryKnockdown(uid, duration, true, force: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <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, bool refresh, bool autoStand = true, bool drop = true)
|
public bool TryKnockdown(Entity<StandingStateComponent?> entity, TimeSpan? time, bool refresh, bool autoStand = true, bool drop = true, bool force = false)
|
||||||
{
|
{
|
||||||
if (time <= TimeSpan.Zero)
|
if (time <= TimeSpan.Zero)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Can't fall down if you can't actually be downed.
|
// Can't fall down if you can't actually be downed.
|
||||||
if (!HasComp<StandingStateComponent>(uid))
|
if (!Resolve(entity, ref entity.Comp, false))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if (!force)
|
||||||
|
{
|
||||||
var evAttempt = new KnockDownAttemptEvent(autoStand, drop);
|
var evAttempt = new KnockDownAttemptEvent(autoStand, drop);
|
||||||
RaiseLocalEvent(uid, ref evAttempt);
|
RaiseLocalEvent(entity, ref evAttempt);
|
||||||
|
|
||||||
if (evAttempt.Cancelled)
|
if (evAttempt.Cancelled)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Initialize our component with the relevant data we need if we don't have it
|
autoStand = evAttempt.AutoStand;
|
||||||
if (EnsureComp<KnockedDownComponent>(uid, out var component))
|
drop = evAttempt.Drop;
|
||||||
|
}
|
||||||
|
|
||||||
|
Knockdown(entity!, time, autoStand, drop);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Knockdown(Entity<StandingStateComponent> entity, TimeSpan? time, bool refresh, bool autoStand = true, bool drop = true)
|
||||||
{
|
{
|
||||||
RefreshKnockedMovement((uid, component));
|
// Initialize our component with the relevant data we need if we don't have it
|
||||||
CancelKnockdownDoAfter((uid, component));
|
if (EnsureComp<KnockedDownComponent>(entity, out var component))
|
||||||
|
{
|
||||||
|
RefreshKnockedMovement((entity, component));
|
||||||
|
CancelKnockdownDoAfter((entity, component));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -191,127 +218,87 @@ public abstract partial class SharedStunSystem : EntitySystem
|
|||||||
if (drop)
|
if (drop)
|
||||||
{
|
{
|
||||||
var ev = new DropHandItemsEvent();
|
var ev = new DropHandItemsEvent();
|
||||||
RaiseLocalEvent(uid, ref ev);
|
RaiseLocalEvent(entity, ref ev);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only update Autostand value if it's our first time being knocked down...
|
// Only update Autostand value if it's our first time being knocked down...
|
||||||
SetAutoStand((uid, component), evAttempt.AutoStand);
|
SetAutoStand((entity, component), autoStand);
|
||||||
}
|
}
|
||||||
|
|
||||||
var knockedEv = new KnockedDownEvent(time);
|
var knockedEv = new KnockedDownEvent(time);
|
||||||
RaiseLocalEvent(uid, ref knockedEv);
|
RaiseLocalEvent(entity, ref knockedEv);
|
||||||
|
|
||||||
UpdateKnockdownTime((uid, component), knockedEv.Time, refresh);
|
if (time != null)
|
||||||
|
{
|
||||||
|
UpdateKnockdownTime((entity, component), time.Value, refresh);
|
||||||
|
_adminLogger.Add(LogType.Stamina, LogImpact.Medium, $"{ToPrettyString(entity):user} knocked down for {time.Value.Seconds} seconds");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
_adminLogger.Add(LogType.Stamina, LogImpact.Medium, $"{ToPrettyString(entity):user} knocked down for an indefinite amount of time");
|
||||||
|
|
||||||
Alerts.ShowAlert(uid, KnockdownAlert, null, (GameTiming.CurTime, component.NextUpdate));
|
Alerts.ShowAlert(entity, KnockdownAlert, null, (GameTiming.CurTime, component.NextUpdate));
|
||||||
|
}
|
||||||
|
|
||||||
_adminLogger.Add(LogType.Stamina, LogImpact.Medium, $"{ToPrettyString(uid):user} knocked down for {time.Seconds} seconds");
|
public bool TryAddParalyzeDuration(EntityUid uid, TimeSpan duration)
|
||||||
|
{
|
||||||
|
var knockdown = TryAddKnockdownDuration(uid, duration);
|
||||||
|
var stunned = TryAddStunDuration(uid, duration);
|
||||||
|
|
||||||
|
return knockdown || stunned;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool TryUpdateParalyzeDuration(EntityUid uid, TimeSpan? duration)
|
||||||
|
{
|
||||||
|
var knockdown = TryUpdateKnockdownDuration(uid, duration);
|
||||||
|
var stunned = TryUpdateStunDuration(uid, duration);
|
||||||
|
|
||||||
|
return knockdown || stunned;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool TryUnstun(Entity<StunnedComponent?> entity)
|
||||||
|
{
|
||||||
|
if (!Resolve(entity, ref entity.Comp, logMissing: false))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
var ev = new StunEndAttemptEvent();
|
||||||
|
RaiseLocalEvent(entity, ref ev);
|
||||||
|
|
||||||
|
return !ev.Cancelled && RemComp<StunnedComponent>(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
private void OnStunEffectApplied(Entity<StunnedStatusEffectComponent> entity, ref StatusEffectAppliedEvent args)
|
||||||
/// Applies knockdown and stun to the entity temporarily.
|
|
||||||
/// </summary>
|
|
||||||
public bool TryParalyze(EntityUid uid, TimeSpan time, bool refresh,
|
|
||||||
StatusEffectsComponent? status = null)
|
|
||||||
{
|
{
|
||||||
if (!Resolve(uid, ref status, false))
|
if (GameTiming.ApplyingState)
|
||||||
return false;
|
|
||||||
|
|
||||||
return TryKnockdown(uid, time, refresh) && TryStun(uid, time, refresh, status);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Slows down the mob's walking/running speed temporarily
|
|
||||||
/// </summary>
|
|
||||||
public bool TrySlowdown(EntityUid uid, TimeSpan time, bool refresh,
|
|
||||||
float walkSpeedMod = 1f, float sprintSpeedMod = 1f,
|
|
||||||
StatusEffectsComponent? status = null)
|
|
||||||
{
|
|
||||||
if (!Resolve(uid, ref status, false))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (time <= TimeSpan.Zero)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (_statusEffect.TryAddStatusEffect<SlowedDownComponent>(uid, "SlowedDown", time, refresh, status))
|
|
||||||
{
|
|
||||||
var slowed = Comp<SlowedDownComponent>(uid);
|
|
||||||
// Doesn't make much sense to have the "TrySlowdown" method speed up entities now does it?
|
|
||||||
walkSpeedMod = Math.Clamp(walkSpeedMod, 0f, 1f);
|
|
||||||
sprintSpeedMod = Math.Clamp(sprintSpeedMod, 0f, 1f);
|
|
||||||
|
|
||||||
slowed.WalkSpeedModifier *= walkSpeedMod;
|
|
||||||
slowed.SprintSpeedModifier *= sprintSpeedMod;
|
|
||||||
|
|
||||||
_movementSpeedModifier.RefreshMovementSpeedModifiers(uid);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Updates the movement speed modifiers of an entity by applying or removing the <see cref="SlowedDownComponent"/>.
|
|
||||||
/// If both walk and run modifiers are approximately 1 (i.e. normal speed) and <see cref="StaminaComponent.StaminaDamage"/> is 0,
|
|
||||||
/// or if the both modifiers are 0, the slowdown component is removed to restore normal movement.
|
|
||||||
/// Otherwise, the slowdown component is created or updated with the provided modifiers,
|
|
||||||
/// and the movement speed is refreshed accordingly.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="ent">Entity whose movement speed should be updated.</param>
|
|
||||||
/// <param name="walkSpeedModifier">New walk speed modifier. Default is 1f (normal speed).</param>
|
|
||||||
/// <param name="runSpeedModifier">New run (sprint) speed modifier. Default is 1f (normal speed).</param>
|
|
||||||
public void UpdateStunModifiers(Entity<StaminaComponent?> ent,
|
|
||||||
float walkSpeedModifier = 1f,
|
|
||||||
float runSpeedModifier = 1f)
|
|
||||||
{
|
|
||||||
if (!Resolve(ent, ref ent.Comp))
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (
|
EnsureComp<StunnedComponent>(args.Target);
|
||||||
(MathHelper.CloseTo(walkSpeedModifier, 1f) && MathHelper.CloseTo(runSpeedModifier, 1f) && ent.Comp.StaminaDamage == 0f) ||
|
}
|
||||||
(walkSpeedModifier == 0f && runSpeedModifier == 0f)
|
|
||||||
)
|
private void OnStunStatusRemoved(Entity<StunnedStatusEffectComponent> entity, ref StatusEffectRemovedEvent args)
|
||||||
{
|
{
|
||||||
RemComp<SlowedDownComponent>(ent);
|
TryUnstun(args.Target);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnStunEndAttempt(Entity<StunnedStatusEffectComponent> entity, ref StatusEffectRelayedEvent<StunEndAttemptEvent> args)
|
||||||
|
{
|
||||||
|
if (args.Args.Cancelled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
var ev = args.Args;
|
||||||
|
ev.Cancelled = true;
|
||||||
|
args.Args = ev;
|
||||||
}
|
}
|
||||||
|
|
||||||
EnsureComp<SlowedDownComponent>(ent, out var comp);
|
private void OnStandUpAttempt(Entity<KnockdownStatusEffectComponent> entity, ref StatusEffectRelayedEvent<StandUpAttemptEvent> args)
|
||||||
|
|
||||||
comp.WalkSpeedModifier = walkSpeedModifier;
|
|
||||||
|
|
||||||
comp.SprintSpeedModifier = runSpeedModifier;
|
|
||||||
|
|
||||||
_movementSpeedModifier.RefreshMovementSpeedModifiers(ent);
|
|
||||||
|
|
||||||
Dirty(ent);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// A convenience overload of <see cref="UpdateStunModifiers(EntityUid, float, float, StaminaComponent?)"/> that sets both
|
|
||||||
/// walk and run speed modifiers to the same value.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="ent">Entity whose movement speed should be updated.</param>
|
|
||||||
/// <param name="speedModifier">New walk and run speed modifier. Default is 1f (normal speed).</param>
|
|
||||||
/// <param name="component">
|
|
||||||
/// Optional <see cref="StaminaComponent"/> of the entity.
|
|
||||||
/// </param>
|
|
||||||
public void UpdateStunModifiers(Entity<StaminaComponent?> ent, float speedModifier = 1f)
|
|
||||||
{
|
{
|
||||||
UpdateStunModifiers(ent, speedModifier, speedModifier);
|
if (args.Args.Cancelled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var ev = args.Args;
|
||||||
|
ev.Cancelled = true;
|
||||||
|
args.Args = ev;
|
||||||
}
|
}
|
||||||
|
|
||||||
#region friction and movement listeners
|
|
||||||
|
|
||||||
private void OnRefreshMovespeed(EntityUid ent, SlowedDownComponent comp, RefreshMovementSpeedModifiersEvent args)
|
|
||||||
{
|
|
||||||
args.ModifySpeed(comp.WalkSpeedModifier, comp.SprintSpeedModifier);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Attempt Event Handling
|
#region Attempt Event Handling
|
||||||
|
|
||||||
private void OnMoveAttempt(EntityUid uid, StunnedComponent stunned, UpdateCanMoveEvent args)
|
private void OnMoveAttempt(EntityUid uid, StunnedComponent stunned, UpdateCanMoveEvent args)
|
||||||
|
|||||||
@@ -1,14 +0,0 @@
|
|||||||
using Robust.Shared.GameStates;
|
|
||||||
using Robust.Shared.Serialization;
|
|
||||||
|
|
||||||
namespace Content.Shared.Stunnable;
|
|
||||||
|
|
||||||
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState, Access(typeof(SharedStunSystem))]
|
|
||||||
public sealed partial class SlowedDownComponent : Component
|
|
||||||
{
|
|
||||||
[ViewVariables, DataField("sprintSpeedModifier"), AutoNetworkedField]
|
|
||||||
public float SprintSpeedModifier = 0.5f;
|
|
||||||
|
|
||||||
[ViewVariables, DataField("walkSpeedModifier"), AutoNetworkedField]
|
|
||||||
public float WalkSpeedModifier = 0.5f;
|
|
||||||
}
|
|
||||||
@@ -15,6 +15,12 @@ namespace Content.Shared.Stunnable;
|
|||||||
[ByRefEvent]
|
[ByRefEvent]
|
||||||
public record struct StunnedEvent;
|
public record struct StunnedEvent;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Raised on a stunned entity when something wants to remove the stunned component.
|
||||||
|
/// </summary>
|
||||||
|
[ByRefEvent]
|
||||||
|
public record struct StunEndAttemptEvent(bool Cancelled);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Raised directed on an entity before it is knocked down to see if it should be cancelled, and to determine
|
/// Raised directed on an entity before it is knocked down to see if it should be cancelled, and to determine
|
||||||
/// knocked down arguments.
|
/// knocked down arguments.
|
||||||
@@ -29,7 +35,7 @@ public record struct KnockDownAttemptEvent(bool AutoStand, bool Drop)
|
|||||||
/// Raised directed on an entity when it is knocked down.
|
/// Raised directed on an entity when it is knocked down.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[ByRefEvent]
|
[ByRefEvent]
|
||||||
public record struct KnockedDownEvent(TimeSpan Time);
|
public record struct KnockedDownEvent(TimeSpan? Time);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Raised on an entity that needs to refresh its knockdown modifiers
|
/// Raised on an entity that needs to refresh its knockdown modifiers
|
||||||
|
|||||||
@@ -2,5 +2,8 @@ using Robust.Shared.GameStates;
|
|||||||
|
|
||||||
namespace Content.Shared.Stunnable;
|
namespace Content.Shared.Stunnable;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This is used to temporarily prevent an entity from moving or acting.
|
||||||
|
/// </summary>
|
||||||
[RegisterComponent, NetworkedComponent, Access(typeof(SharedStunSystem))]
|
[RegisterComponent, NetworkedComponent, Access(typeof(SharedStunSystem))]
|
||||||
public sealed partial class StunnedComponent : Component;
|
public sealed partial class StunnedComponent : Component;
|
||||||
|
|||||||
9
Content.Shared/Stunnable/StunnedStatusEffectComponent.cs
Normal file
9
Content.Shared/Stunnable/StunnedStatusEffectComponent.cs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
using Robust.Shared.GameStates;
|
||||||
|
|
||||||
|
namespace Content.Shared.Stunnable;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Stun as a status effect.
|
||||||
|
/// </summary>
|
||||||
|
[RegisterComponent, NetworkedComponent, Access(typeof(SharedStunSystem))]
|
||||||
|
public sealed partial class StunnedStatusEffectComponent : Component;
|
||||||
@@ -97,7 +97,7 @@ public sealed class MeleeThrowOnHitSystem : EntitySystem
|
|||||||
RaiseLocalEvent(target, ref startEvent);
|
RaiseLocalEvent(target, ref startEvent);
|
||||||
|
|
||||||
if (ent.Comp.StunTime != null)
|
if (ent.Comp.StunTime != null)
|
||||||
_stun.TryParalyze(target, ent.Comp.StunTime.Value, false);
|
_stun.TryAddParalyzeDuration(target, ent.Comp.StunTime.Value);
|
||||||
|
|
||||||
if (direction == Vector2.Zero)
|
if (direction == Vector2.Zero)
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -143,8 +143,6 @@
|
|||||||
- type: Body
|
- type: Body
|
||||||
- type: StatusEffects
|
- type: StatusEffects
|
||||||
allowed:
|
allowed:
|
||||||
- Stun
|
|
||||||
- SlowedDown
|
|
||||||
- Flashed
|
- Flashed
|
||||||
- type: TypingIndicator
|
- type: TypingIndicator
|
||||||
proto: robot
|
proto: robot
|
||||||
|
|||||||
@@ -19,9 +19,7 @@
|
|||||||
group: GenericNumber
|
group: GenericNumber
|
||||||
- type: StatusEffects
|
- type: StatusEffects
|
||||||
allowed:
|
allowed:
|
||||||
- SlowedDown
|
|
||||||
- Stutter
|
- Stutter
|
||||||
- Stun
|
|
||||||
- Electrocution
|
- Electrocution
|
||||||
- TemporaryBlindness
|
- TemporaryBlindness
|
||||||
- RadiationProtection
|
- RadiationProtection
|
||||||
|
|||||||
@@ -35,8 +35,6 @@
|
|||||||
bodyType: KinematicController # Same for all inheritors
|
bodyType: KinematicController # Same for all inheritors
|
||||||
- type: StatusEffects
|
- type: StatusEffects
|
||||||
allowed:
|
allowed:
|
||||||
- Stun
|
|
||||||
- SlowedDown
|
|
||||||
- Stutter
|
- Stutter
|
||||||
- Electrocution
|
- Electrocution
|
||||||
- type: Pullable
|
- type: Pullable
|
||||||
@@ -385,7 +383,6 @@
|
|||||||
chemicalMaxVolume: 100
|
chemicalMaxVolume: 100
|
||||||
- type: StatusEffects
|
- type: StatusEffects
|
||||||
allowed:
|
allowed:
|
||||||
- SlowedDown
|
|
||||||
- Electrocution
|
- Electrocution
|
||||||
- type: MeleeWeapon
|
- type: MeleeWeapon
|
||||||
soundHit:
|
soundHit:
|
||||||
@@ -408,6 +405,7 @@
|
|||||||
- FootstepSound
|
- FootstepSound
|
||||||
- CannotSuicide
|
- CannotSuicide
|
||||||
- DoorBumpOpener
|
- DoorBumpOpener
|
||||||
|
- StunImmune
|
||||||
- type: NoSlip
|
- type: NoSlip
|
||||||
- type: ZombieImmune
|
- type: ZombieImmune
|
||||||
- type: ExaminableSolution
|
- type: ExaminableSolution
|
||||||
|
|||||||
@@ -48,7 +48,6 @@
|
|||||||
BaseUnshaded: dead_glow
|
BaseUnshaded: dead_glow
|
||||||
- type: StatusEffects
|
- type: StatusEffects
|
||||||
allowed:
|
allowed:
|
||||||
- Stun
|
|
||||||
- Corporeal
|
- Corporeal
|
||||||
- Electrocution
|
- Electrocution
|
||||||
- StaminaModifier
|
- StaminaModifier
|
||||||
@@ -91,6 +90,7 @@
|
|||||||
- type: Tag
|
- type: Tag
|
||||||
tags:
|
tags:
|
||||||
- FootstepSound
|
- FootstepSound
|
||||||
|
- SlowImmune
|
||||||
- type: Destructible
|
- type: Destructible
|
||||||
thresholds:
|
thresholds:
|
||||||
- trigger:
|
- trigger:
|
||||||
|
|||||||
@@ -20,7 +20,6 @@
|
|||||||
- state: active
|
- state: active
|
||||||
- type: StatusEffects
|
- type: StatusEffects
|
||||||
allowed:
|
allowed:
|
||||||
- Stun
|
|
||||||
- Corporeal
|
- Corporeal
|
||||||
- type: Damageable
|
- type: Damageable
|
||||||
damageContainer: ManifestedSpirit
|
damageContainer: ManifestedSpirit
|
||||||
@@ -83,3 +82,7 @@
|
|||||||
- type: Reactive
|
- type: Reactive
|
||||||
groups:
|
groups:
|
||||||
Acidic: [Touch]
|
Acidic: [Touch]
|
||||||
|
- type: Tag
|
||||||
|
tags:
|
||||||
|
- SlowImmune
|
||||||
|
- KnockdownImmune
|
||||||
|
|||||||
@@ -15,8 +15,6 @@
|
|||||||
bodyType: KinematicController # Same for all inheritors
|
bodyType: KinematicController # Same for all inheritors
|
||||||
- type: StatusEffects
|
- type: StatusEffects
|
||||||
allowed:
|
allowed:
|
||||||
- Stun
|
|
||||||
- SlowedDown
|
|
||||||
- Stutter
|
- Stutter
|
||||||
- Electrocution
|
- Electrocution
|
||||||
- type: Repairable
|
- type: Repairable
|
||||||
|
|||||||
@@ -19,7 +19,6 @@
|
|||||||
baseSprintSpeed : 4
|
baseSprintSpeed : 4
|
||||||
- type: StatusEffects
|
- type: StatusEffects
|
||||||
allowed:
|
allowed:
|
||||||
- SlowedDown
|
|
||||||
- Stutter
|
- Stutter
|
||||||
- Electrocution
|
- Electrocution
|
||||||
- TemporaryBlindness
|
- TemporaryBlindness
|
||||||
@@ -32,6 +31,7 @@
|
|||||||
- type: Tag
|
- type: Tag
|
||||||
tags:
|
tags:
|
||||||
- DoorBumpOpener
|
- DoorBumpOpener
|
||||||
|
- StunImmune
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
abstract: true
|
abstract: true
|
||||||
@@ -93,8 +93,6 @@
|
|||||||
baseDecayRate: 0.04
|
baseDecayRate: 0.04
|
||||||
- type: StatusEffects
|
- type: StatusEffects
|
||||||
allowed:
|
allowed:
|
||||||
- Stun
|
|
||||||
- SlowedDown
|
|
||||||
- Stutter
|
- Stutter
|
||||||
- Electrocution
|
- Electrocution
|
||||||
- TemporaryBlindness
|
- TemporaryBlindness
|
||||||
|
|||||||
@@ -100,7 +100,6 @@
|
|||||||
types: {}
|
types: {}
|
||||||
- type: StatusEffects # Overwriting basesimplemob to remove flash, getting flashed as dragon just feelsbad
|
- type: StatusEffects # Overwriting basesimplemob to remove flash, getting flashed as dragon just feelsbad
|
||||||
allowed:
|
allowed:
|
||||||
- SlowedDown
|
|
||||||
- Stutter
|
- Stutter
|
||||||
- Electrocution
|
- Electrocution
|
||||||
- TemporaryBlindness
|
- TemporaryBlindness
|
||||||
@@ -154,6 +153,7 @@
|
|||||||
tags:
|
tags:
|
||||||
- CannotSuicide
|
- CannotSuicide
|
||||||
- DoorBumpOpener
|
- DoorBumpOpener
|
||||||
|
- StunImmune
|
||||||
- type: Puller
|
- type: Puller
|
||||||
needsHands: false
|
needsHands: false
|
||||||
- type: RandomMetadata
|
- type: RandomMetadata
|
||||||
|
|||||||
@@ -119,9 +119,6 @@
|
|||||||
- !type:WashCreamPieReaction
|
- !type:WashCreamPieReaction
|
||||||
- type: StatusEffects
|
- type: StatusEffects
|
||||||
allowed:
|
allowed:
|
||||||
- Stun
|
|
||||||
- Friction
|
|
||||||
- SlowedDown
|
|
||||||
- Stutter
|
- Stutter
|
||||||
- Electrocution
|
- Electrocution
|
||||||
- Drunk
|
- Drunk
|
||||||
|
|||||||
@@ -19,6 +19,21 @@
|
|||||||
components:
|
components:
|
||||||
- MobState
|
- MobState
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
parent: StatusEffectBase
|
||||||
|
id: MobStandStatusEffectBase
|
||||||
|
abstract: true
|
||||||
|
components:
|
||||||
|
- type: StatusEffect
|
||||||
|
whitelist:
|
||||||
|
components:
|
||||||
|
- MobState
|
||||||
|
- StandingState
|
||||||
|
requireAll: true
|
||||||
|
blacklist: # This blacklist exists because mob prototypes are smelly and everything needs a standing state component.
|
||||||
|
tags:
|
||||||
|
- KnockdownImmune
|
||||||
|
|
||||||
# The creature sleeps so heavily that nothing can wake him up. Not even its own death.
|
# The creature sleeps so heavily that nothing can wake him up. Not even its own death.
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: MobStatusEffectBase
|
parent: MobStatusEffectBase
|
||||||
@@ -26,6 +41,8 @@
|
|||||||
name: forced sleep
|
name: forced sleep
|
||||||
components:
|
components:
|
||||||
- type: ForcedSleepingStatusEffect
|
- type: ForcedSleepingStatusEffect
|
||||||
|
- type: StunnedStatusEffect
|
||||||
|
- type: KnockdownStatusEffect
|
||||||
|
|
||||||
# This creature is asleep because it's disconnected from the game.
|
# This creature is asleep because it's disconnected from the game.
|
||||||
- type: entity
|
- type: entity
|
||||||
@@ -34,6 +51,8 @@
|
|||||||
name: forced sleep
|
name: forced sleep
|
||||||
components:
|
components:
|
||||||
- type: ForcedSleepingStatusEffect
|
- type: ForcedSleepingStatusEffect
|
||||||
|
- type: StunnedStatusEffect
|
||||||
|
- type: KnockdownStatusEffect
|
||||||
|
|
||||||
# Blurs your vision and makes you randomly fall asleep
|
# Blurs your vision and makes you randomly fall asleep
|
||||||
- type: entity
|
- type: entity
|
||||||
@@ -43,14 +62,6 @@
|
|||||||
components:
|
components:
|
||||||
- type: DrowsinessStatusEffect
|
- type: DrowsinessStatusEffect
|
||||||
|
|
||||||
# Makes you more slippery, or perhaps less slippery.
|
|
||||||
- type: entity
|
|
||||||
parent: MobStatusEffectBase
|
|
||||||
id: StatusEffectFriction
|
|
||||||
name: friction
|
|
||||||
components:
|
|
||||||
- type: FrictionStatusEffect
|
|
||||||
|
|
||||||
# Adds drugs overlay
|
# Adds drugs overlay
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: MobStatusEffectBase
|
parent: MobStatusEffectBase
|
||||||
|
|||||||
67
Resources/Prototypes/Entities/StatusEffects/movement.yml
Normal file
67
Resources/Prototypes/Entities/StatusEffects/movement.yml
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
- type: entity
|
||||||
|
parent: MobStatusEffectBase
|
||||||
|
id: StatusEffectSlowdown
|
||||||
|
abstract: true
|
||||||
|
name: slowdown
|
||||||
|
components:
|
||||||
|
- type: StatusEffect
|
||||||
|
whitelist:
|
||||||
|
components:
|
||||||
|
- MobState
|
||||||
|
blacklist:
|
||||||
|
tags:
|
||||||
|
- SlowImmune
|
||||||
|
- type: MovementModStatusEffect
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
parent: StatusEffectSlowdown
|
||||||
|
id: VomitingSlowdownStatusEffect
|
||||||
|
name: vomiting slowdown
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
parent: StatusEffectSlowdown
|
||||||
|
id: TaserSlowdownStatusEffect
|
||||||
|
name: shot by taser slowdown
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
parent: StatusEffectSlowdown
|
||||||
|
id: FlashSlowdownStatusEffect
|
||||||
|
name: affected by flash slowdown
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
parent: StatusEffectSlowdown
|
||||||
|
id: StatusEffectStaminaLow
|
||||||
|
name: stamina low
|
||||||
|
|
||||||
|
# Makes you more slippery, or perhaps less slippery.
|
||||||
|
- type: entity
|
||||||
|
parent: MobStatusEffectBase
|
||||||
|
id: StatusEffectFriction
|
||||||
|
name: friction
|
||||||
|
components:
|
||||||
|
- type: FrictionStatusEffect
|
||||||
|
|
||||||
|
# Stunnable Status Effect
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
parent: MobStatusEffectBase
|
||||||
|
id: StatusEffectStunned
|
||||||
|
name: stunned
|
||||||
|
components:
|
||||||
|
- type: StatusEffect
|
||||||
|
whitelist:
|
||||||
|
components:
|
||||||
|
- MobState
|
||||||
|
blacklist:
|
||||||
|
tags:
|
||||||
|
- StunImmune
|
||||||
|
- type: StatusEffectAlert
|
||||||
|
alert: Stun
|
||||||
|
- type: StunnedStatusEffect
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
parent: MobStandStatusEffectBase
|
||||||
|
id: StatusEffectKnockdown
|
||||||
|
name: knocked down
|
||||||
|
components:
|
||||||
|
- type: KnockdownStatusEffect
|
||||||
@@ -831,6 +831,9 @@
|
|||||||
- type: Tag
|
- type: Tag
|
||||||
id: Knife
|
id: Knife
|
||||||
|
|
||||||
|
- type: Tag
|
||||||
|
id: KnockdownImmune
|
||||||
|
|
||||||
- type: Tag
|
- type: Tag
|
||||||
id: LavaBrig
|
id: LavaBrig
|
||||||
|
|
||||||
@@ -1268,6 +1271,9 @@
|
|||||||
- type: Tag
|
- type: Tag
|
||||||
id: Slice # sliced fruit, vegetables, pizza etc.
|
id: Slice # sliced fruit, vegetables, pizza etc.
|
||||||
|
|
||||||
|
- type: Tag
|
||||||
|
id: SlowImmune
|
||||||
|
|
||||||
- type: Tag
|
- type: Tag
|
||||||
id: SmallAIChip
|
id: SmallAIChip
|
||||||
|
|
||||||
@@ -1331,6 +1337,9 @@
|
|||||||
- type: Tag
|
- type: Tag
|
||||||
id: StringInstrument
|
id: StringInstrument
|
||||||
|
|
||||||
|
- type: Tag
|
||||||
|
id: StunImmune
|
||||||
|
|
||||||
- type: Tag
|
- type: Tag
|
||||||
id: SubdermalImplant
|
id: SubdermalImplant
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user