mirror of
https://github.com/space-syndicate/space-station-14.git
synced 2026-10-09 10:21:18 +03:00
Muted StatusEffects (#43668)
* MutedStatusEffects * Update species_base.yml * System * refactor * yml fix * fix component * review * fix yml * Update disabilities.yml * StatusEffectMuted -> TraitStatusEffectMuted * Update misc.yml * merge * RemoveStatusEffect * more review * cleanup * merge * oops * Send it --------- Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> Co-authored-by: AJCM-git <ajcm_mail@disroot.org>
This commit is contained in:
parent
5781283a9c
commit
b38e363d41
27 changed files with 230 additions and 132 deletions
|
|
@ -5,9 +5,10 @@ using Content.Shared.Chat;
|
|||
using Content.Shared.Mobs;
|
||||
using Content.Shared.Mobs.Components;
|
||||
using Content.Shared.Mobs.Systems;
|
||||
using Content.Shared.Speech.Muting;
|
||||
using Content.Shared.StatusEffectNew;
|
||||
using Robust.Server.Console;
|
||||
using Robust.Shared.Player;
|
||||
using Content.Shared.Speech.Muting;
|
||||
|
||||
namespace Content.Server.Mobs;
|
||||
|
||||
|
|
@ -22,6 +23,7 @@ public sealed partial class CritMobActionsSystem : EntitySystem
|
|||
[Dependency] private MobStateSystem _mobState = default!;
|
||||
[Dependency] private PopupSystem _popupSystem = default!;
|
||||
[Dependency] private QuickDialogSystem _quickDialog = default!;
|
||||
[Dependency] private StatusEffectsSystem _statusEffects = default!;
|
||||
|
||||
private const int MaxLastWordsLength = 30;
|
||||
|
||||
|
|
@ -48,7 +50,7 @@ public sealed partial class CritMobActionsSystem : EntitySystem
|
|||
if (!_mobState.IsCritical(uid))
|
||||
return;
|
||||
|
||||
if (HasComp<MutedComponent>(uid))
|
||||
if (_statusEffects.HasEffectComp<MutedStatusEffectComponent>(uid))
|
||||
{
|
||||
_popupSystem.PopupEntity(Loc.GetString("fake-death-muted"), uid, uid);
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
using Content.Server.Chat.Systems;
|
||||
using Content.Server.Chat.Systems;
|
||||
using Content.Shared.Mobs;
|
||||
using Content.Shared.Speech.Muting;
|
||||
using Content.Shared.StatusEffectNew;
|
||||
|
||||
namespace Content.Server.Mobs;
|
||||
|
||||
|
|
@ -11,6 +12,7 @@ namespace Content.Server.Mobs;
|
|||
public sealed partial class DeathgaspSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private ChatSystem _chat = default!;
|
||||
[Dependency] private StatusEffectsSystem _statusEffects = default!;
|
||||
|
||||
[SubscribeLocalEvent]
|
||||
private void OnMobStateChanged(Entity<DeathgaspComponent> ent, ref MobStateChangedEvent args)
|
||||
|
|
@ -30,7 +32,7 @@ public sealed partial class DeathgaspSystem : EntitySystem
|
|||
if (!Resolve(uid, ref component, false))
|
||||
return false;
|
||||
|
||||
if (HasComp<MutedComponent>(uid))
|
||||
if (_statusEffects.HasEffectComp<MutedStatusEffectComponent>(uid))
|
||||
return false;
|
||||
|
||||
_chat.TryEmoteWithChat(uid, component.Prototype, ignoreActionBlocker: true);
|
||||
|
|
|
|||
|
|
@ -4,7 +4,8 @@ using Content.Shared.CombatMode;
|
|||
using Content.Shared.Hands;
|
||||
using Content.Shared.Interaction.Events;
|
||||
using Content.Shared.Puppet;
|
||||
using Content.Shared.Speech.Muting;
|
||||
using Content.Shared.StatusEffectNew;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server.Puppet;
|
||||
|
||||
|
|
@ -13,9 +14,10 @@ namespace Content.Server.Puppet;
|
|||
/// </summary>
|
||||
public sealed partial class VentriloquistPuppetSystem : SharedVentriloquistPuppetSystem
|
||||
{
|
||||
[Dependency] private PopupSystem _popupSystem = default!;
|
||||
public static readonly EntProtoId MutedEffect = "StatusEffectVentriloquistPuppetMuted";
|
||||
|
||||
[Dependency] private EntityQuery<MutedComponent> _mutedQuery;
|
||||
[Dependency] private PopupSystem _popupSystem = default!;
|
||||
[Dependency] private StatusEffectsSystem _statusEffects = default!;
|
||||
|
||||
/// <summary>
|
||||
/// When used user inserts hand into dummy and the dummy can speak, when used again the user removes hand
|
||||
|
|
@ -31,7 +33,7 @@ public sealed partial class VentriloquistPuppetSystem : SharedVentriloquistPuppe
|
|||
// TODO disable dummy when the user dies or cannot interact.
|
||||
// Then again, this is all quite cursed code, so maybe its a cursed ventriloquist puppet.
|
||||
|
||||
if (!RemComp<MutedComponent>(ent))
|
||||
if (!_statusEffects.TryRemoveStatusEffect(ent, MutedEffect))
|
||||
{
|
||||
_popupSystem.PopupEntity(Loc.GetString("ventriloquist-puppet-remove-hand"), ent, args.User);
|
||||
MuteDummy(ent);
|
||||
|
|
@ -60,7 +62,7 @@ public sealed partial class VentriloquistPuppetSystem : SharedVentriloquistPuppe
|
|||
[SubscribeLocalEvent]
|
||||
private void OnDropped(Entity<VentriloquistPuppetComponent> ent, ref DroppedEvent args)
|
||||
{
|
||||
if (_mutedQuery.HasComp(ent))
|
||||
if (_statusEffects.HasStatusEffect(ent, MutedEffect))
|
||||
return;
|
||||
|
||||
_popupSystem.PopupEntity(Loc.GetString("ventriloquist-puppet-remove-hand"), ent, args.User);
|
||||
|
|
@ -73,7 +75,7 @@ public sealed partial class VentriloquistPuppetSystem : SharedVentriloquistPuppe
|
|||
[SubscribeLocalEvent]
|
||||
private void OnUnequippedHand(Entity<VentriloquistPuppetComponent> ent, ref GotUnequippedHandEvent args)
|
||||
{
|
||||
if (_mutedQuery.HasComp(ent))
|
||||
if (_statusEffects.HasStatusEffect(ent, MutedEffect))
|
||||
return;
|
||||
|
||||
_popupSystem.PopupEntity(Loc.GetString("ventriloquist-puppet-remove-hand"), ent, args.User);
|
||||
|
|
@ -86,7 +88,7 @@ public sealed partial class VentriloquistPuppetSystem : SharedVentriloquistPuppe
|
|||
private void MuteDummy(Entity<VentriloquistPuppetComponent> ent)
|
||||
{
|
||||
_popupSystem.PopupEntity(Loc.GetString("ventriloquist-puppet-removed-hand"), ent, ent);
|
||||
EnsureComp<MutedComponent>(ent);
|
||||
_statusEffects.TrySetStatusEffectDuration(ent, MutedEffect);
|
||||
RemComp<CombatModeComponent>(ent);
|
||||
RemComp<GhostTakeoverAvailableComponent>(ent);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -54,9 +54,6 @@ public sealed partial class MimePowersComponent : Component
|
|||
[DataField, AutoNetworkedField]
|
||||
public TimeSpan VowCooldown = TimeSpan.FromMinutes(5);
|
||||
|
||||
[DataField]
|
||||
public ProtoId<AlertPrototype> VowAlert = "VowOfSilence";
|
||||
|
||||
[DataField]
|
||||
public ProtoId<AlertPrototype> VowBrokenAlert = "VowBroken";
|
||||
|
||||
|
|
|
|||
|
|
@ -7,18 +7,22 @@ using Content.Shared.IdentityManagement;
|
|||
using Content.Shared.Maps;
|
||||
using Content.Shared.Paper;
|
||||
using Content.Shared.Physics;
|
||||
using Content.Shared.Speech.Muting;
|
||||
using Content.Shared.StatusEffectNew;
|
||||
using Robust.Shared.Containers;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Timing;
|
||||
|
||||
namespace Content.Shared.Abilities.Mime;
|
||||
|
||||
public sealed partial class MimePowersSystem : EntitySystem
|
||||
{
|
||||
public static readonly EntProtoId MutedEffect = "StatusEffectMimeMuted";
|
||||
|
||||
[Dependency] private SharedPopupSystem _popupSystem = default!;
|
||||
[Dependency] private SharedActionsSystem _actionsSystem = default!;
|
||||
[Dependency] private AlertsSystem _alertsSystem = default!;
|
||||
[Dependency] private StatusEffectsSystem _statusEffects = default!;
|
||||
[Dependency] private TurfSystem _turf = default!;
|
||||
[Dependency] private SharedContainerSystem _container = default!;
|
||||
[Dependency] private IGameTiming _timing = default!;
|
||||
|
|
@ -27,7 +31,7 @@ public sealed partial class MimePowersSystem : EntitySystem
|
|||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<MimePowersComponent, ComponentInit>(OnComponentInit);
|
||||
SubscribeLocalEvent<MimePowersComponent, MapInitEvent>(OnMapInit);
|
||||
SubscribeLocalEvent<MimePowersComponent, ComponentShutdown>(OnComponentShutdown);
|
||||
SubscribeLocalEvent<MimePowersComponent, InvisibleWallActionEvent>(OnInvisibleWall);
|
||||
|
||||
|
|
@ -55,9 +59,10 @@ public sealed partial class MimePowersSystem : EntitySystem
|
|||
}
|
||||
}
|
||||
|
||||
private void OnComponentInit(Entity<MimePowersComponent> ent, ref ComponentInit args)
|
||||
private void OnMapInit(Entity<MimePowersComponent> ent, ref MapInitEvent args)
|
||||
{
|
||||
EnsureComp<MutedComponent>(ent);
|
||||
if (!ent.Comp.VowBroken)
|
||||
_statusEffects.TrySetStatusEffectDuration(ent, MutedEffect);
|
||||
|
||||
if (ent.Comp.PreventWriting)
|
||||
{
|
||||
|
|
@ -66,12 +71,12 @@ public sealed partial class MimePowersSystem : EntitySystem
|
|||
Dirty(ent, illiterateComponent);
|
||||
}
|
||||
|
||||
_alertsSystem.ShowAlert(ent.Owner, ent.Comp.VowAlert);
|
||||
_actionsSystem.AddAction(ent, ref ent.Comp.InvisibleWallActionEntity, ent.Comp.InvisibleWallAction);
|
||||
}
|
||||
|
||||
private void OnComponentShutdown(Entity<MimePowersComponent> ent, ref ComponentShutdown args)
|
||||
{
|
||||
_statusEffects.TryRemoveStatusEffect(ent, MutedEffect);
|
||||
_actionsSystem.RemoveAction(ent.Owner, ent.Comp.InvisibleWallActionEntity);
|
||||
}
|
||||
|
||||
|
|
@ -144,11 +149,10 @@ public sealed partial class MimePowersSystem : EntitySystem
|
|||
mimePowers.VowBroken = true;
|
||||
mimePowers.VowRepentTime = _timing.CurTime + mimePowers.VowCooldown;
|
||||
Dirty(uid, mimePowers);
|
||||
RemComp<MutedComponent>(uid);
|
||||
_statusEffects.TryRemoveStatusEffect(uid, MutedEffect);
|
||||
if (mimePowers.PreventWriting)
|
||||
RemComp<BlockWritingComponent>(uid);
|
||||
|
||||
_alertsSystem.ClearAlert(uid, mimePowers.VowAlert);
|
||||
_alertsSystem.ShowAlert(uid, mimePowers.VowBrokenAlert);
|
||||
_actionsSystem.RemoveAction(uid, mimePowers.InvisibleWallActionEntity);
|
||||
}
|
||||
|
|
@ -171,7 +175,7 @@ public sealed partial class MimePowersSystem : EntitySystem
|
|||
mimePowers.ReadyToRepent = false;
|
||||
mimePowers.VowBroken = false;
|
||||
Dirty(uid, mimePowers);
|
||||
AddComp<MutedComponent>(uid);
|
||||
_statusEffects.TrySetStatusEffectDuration(uid, MutedEffect);
|
||||
if (mimePowers.PreventWriting)
|
||||
{
|
||||
EnsureComp<BlockWritingComponent>(uid, out var illiterateComponent);
|
||||
|
|
@ -180,7 +184,6 @@ public sealed partial class MimePowersSystem : EntitySystem
|
|||
}
|
||||
|
||||
_alertsSystem.ClearAlert(uid, mimePowers.VowBrokenAlert);
|
||||
_alertsSystem.ShowAlert(uid, mimePowers.VowAlert);
|
||||
_actionsSystem.AddAction(uid, ref mimePowers.InvisibleWallActionEntity, mimePowers.InvisibleWallAction, uid);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -141,6 +141,11 @@ namespace Content.Shared.ActionBlocker
|
|||
return !itemEv.Cancelled;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Whether a player is able to speak.
|
||||
/// This only checks if something blocks them from speaking, not if they had the ability to do so in the first place.
|
||||
/// </summary>
|
||||
/// <param name="uid">The mob to check.</param>
|
||||
public bool CanSpeak(EntityUid uid)
|
||||
{
|
||||
// This one is used as broadcast
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using System.Numerics;
|
||||
using Content.Shared.ActionBlocker;
|
||||
using Content.Shared.Charges.Components;
|
||||
using Content.Shared.Charges.Systems;
|
||||
using Content.Shared.Coordinates.Helpers;
|
||||
|
|
@ -48,6 +49,7 @@ public abstract partial class SharedMagicSystem : EntitySystem
|
|||
[Dependency] private ISerializationManager _seriMan = default!;
|
||||
[Dependency] private SharedMapSystem _mapSystem = default!;
|
||||
[Dependency] private IRobustRandom _random = default!;
|
||||
[Dependency] private ActionBlockerSystem _actionBlocker = default!;
|
||||
[Dependency] private SharedGunSystem _gunSystem = default!;
|
||||
[Dependency] private SharedPhysicsSystem _physics = default!;
|
||||
[Dependency] private SharedTransformSystem _transform = default!;
|
||||
|
|
@ -109,7 +111,7 @@ public abstract partial class SharedMagicSystem : EntitySystem
|
|||
}
|
||||
}
|
||||
|
||||
if (comp.RequiresSpeech && HasComp<MutedComponent>(args.Performer))
|
||||
if (comp.RequiresSpeech && !_actionBlocker.CanSpeak(args.Performer))
|
||||
hasReqs = false;
|
||||
|
||||
if (hasReqs)
|
||||
|
|
|
|||
|
|
@ -1,12 +1,13 @@
|
|||
using Content.Shared.Speech.Components;
|
||||
using Content.Shared.Actions.Events;
|
||||
using Content.Shared.ActionBlocker;
|
||||
using Content.Shared.Chat;
|
||||
using Content.Shared.Speech.Muting;
|
||||
|
||||
namespace Content.Shared.Speech.EntitySystems;
|
||||
|
||||
public sealed partial class SpeakOnActionSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private ActionBlockerSystem _actionBlocker = default!;
|
||||
[Dependency] private SharedChatSystem _chat = default!;
|
||||
|
||||
[SubscribeLocalEvent]
|
||||
|
|
@ -15,7 +16,7 @@ public sealed partial class SpeakOnActionSystem : EntitySystem
|
|||
var user = args.Performer;
|
||||
|
||||
// If we can't speak, we can't speak.
|
||||
if (!HasComp<SpeechComponent>(user) || HasComp<MutedComponent>(user))
|
||||
if (!HasComp<SpeechComponent>(user) || !_actionBlocker.CanSpeak(user))
|
||||
return;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(ent.Comp.Sentence))
|
||||
|
|
|
|||
|
|
@ -1,10 +0,0 @@
|
|||
using Robust.Shared.GameStates;
|
||||
|
||||
namespace Content.Shared.Speech.Muting
|
||||
{
|
||||
[RegisterComponent, NetworkedComponent]
|
||||
public sealed partial class MutedComponent : Component
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
22
Content.Shared/Speech/Muting/MutedStatusEffectComponent.cs
Normal file
22
Content.Shared/Speech/Muting/MutedStatusEffectComponent.cs
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
using Robust.Shared.GameStates;
|
||||
|
||||
namespace Content.Shared.Speech.Muting;
|
||||
|
||||
/// <summary>
|
||||
/// Marks a status effect that prevents speaking, screaming, and vocal emotes.
|
||||
/// </summary>
|
||||
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
|
||||
public sealed partial class MutedStatusEffectComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// Popup shown when speech is blocked.
|
||||
/// </summary>
|
||||
[DataField, AutoNetworkedField]
|
||||
public LocId SpeakPopup = "speech-muted";
|
||||
|
||||
/// <summary>
|
||||
/// Popup shown when screaming is blocked.
|
||||
/// </summary>
|
||||
[DataField, AutoNetworkedField]
|
||||
public LocId ActionPopup = "speech-muted";
|
||||
}
|
||||
62
Content.Shared/Speech/Muting/MutedStatusEffectSystem.cs
Normal file
62
Content.Shared/Speech/Muting/MutedStatusEffectSystem.cs
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
using Content.Shared.Chat;
|
||||
using Content.Shared.Chat.Prototypes;
|
||||
using Content.Shared.Popups;
|
||||
using Content.Shared.StatusEffectNew;
|
||||
using Content.Shared.StatusEffectNew.Components;
|
||||
|
||||
namespace Content.Shared.Speech.Muting;
|
||||
|
||||
/// <summary>
|
||||
/// Handles the speech restrictions imposed by <see cref="MutedStatusEffectComponent"/>.
|
||||
/// </summary>
|
||||
public sealed partial class MutedStatusEffectSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private SharedPopupSystem _popup = default!;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Initialize()
|
||||
{
|
||||
SubscribeLocalEvent<MutedStatusEffectComponent, StatusEffectRelayedEvent<SpeakAttemptEvent>>(OnSpeakAttempt);
|
||||
SubscribeLocalEvent<MutedStatusEffectComponent, StatusEffectRelayedEvent<EmoteEvent>>(OnEmote);
|
||||
SubscribeLocalEvent<MutedStatusEffectComponent, StatusEffectRelayedEvent<EmoteActionEvent>>(OnEmoteAction);
|
||||
}
|
||||
|
||||
private void OnEmote(Entity<MutedStatusEffectComponent> ent, ref StatusEffectRelayedEvent<EmoteEvent> args)
|
||||
{
|
||||
if (args.Args.Handled)
|
||||
return;
|
||||
|
||||
// Still leaves the text so it looks like they are pantomiming a laugh.
|
||||
if (args.Args.Emote.Category.HasFlag(EmoteCategory.Vocal))
|
||||
{
|
||||
args.Args = args.Args with { Handled = true };
|
||||
}
|
||||
}
|
||||
|
||||
private void OnEmoteAction(Entity<MutedStatusEffectComponent> ent, ref StatusEffectRelayedEvent<EmoteActionEvent> args)
|
||||
{
|
||||
if (args.Args.Handled)
|
||||
return;
|
||||
|
||||
if (!TryComp<StatusEffectComponent>(ent, out var statusEffect))
|
||||
return;
|
||||
|
||||
if (statusEffect.AppliedTo is not { } target)
|
||||
return;
|
||||
|
||||
_popup.PopupEntity(Loc.GetString(ent.Comp.ActionPopup), target, target);
|
||||
args.Args.Handled = true;
|
||||
}
|
||||
|
||||
private void OnSpeakAttempt(Entity<MutedStatusEffectComponent> ent, ref StatusEffectRelayedEvent<SpeakAttemptEvent> args)
|
||||
{
|
||||
if (args.Args.Cancelled)
|
||||
return;
|
||||
|
||||
var target = args.Args.Uid;
|
||||
|
||||
_popup.PopupEntity(Loc.GetString(ent.Comp.SpeakPopup), target, target);
|
||||
|
||||
args.Args.Cancel();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,72 +0,0 @@
|
|||
using Content.Shared.Abilities.Mime;
|
||||
using Content.Shared.Chat;
|
||||
using Content.Shared.Chat.Prototypes;
|
||||
using Content.Shared.Popups;
|
||||
using Content.Shared.Puppet;
|
||||
using Content.Shared.Speech.EntitySystems;
|
||||
|
||||
namespace Content.Shared.Speech.Muting;
|
||||
|
||||
/// <summary>
|
||||
/// A system to prevent muted characters from talking.
|
||||
/// </summary>
|
||||
/// <seealso cref="MutedComponent"/>
|
||||
public sealed partial class MutingSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private SharedPopupSystem _popup = default!;
|
||||
|
||||
[Dependency] private EntityQuery<MimePowersComponent> _mimePowersQuery;
|
||||
[Dependency] private EntityQuery<VentriloquistPuppetComponent> _puppetQuery;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<MutedComponent, EmoteEvent>(OnEmote, before: new[] { typeof(VocalSystem), typeof(MumbleAccentSystem) });
|
||||
SubscribeLocalEvent<MutedComponent, EmoteActionEvent>(OnEmoteAction, before: new[] { typeof(VocalSystem) });
|
||||
}
|
||||
|
||||
private void OnEmote(Entity<MutedComponent> ent, ref EmoteEvent args)
|
||||
{
|
||||
if (args.Handled)
|
||||
return;
|
||||
|
||||
//still leaves the text so it looks like they are pantomiming a laugh
|
||||
if (args.Emote.Category.HasFlag(EmoteCategory.Vocal))
|
||||
args.Handled = true;
|
||||
}
|
||||
|
||||
private void OnEmoteAction(Entity<MutedComponent> ent, ref EmoteActionEvent args)
|
||||
{
|
||||
if (args.Handled)
|
||||
return;
|
||||
|
||||
if (!ProtoMan.Resolve(args.Emote, out var emote))
|
||||
return;
|
||||
|
||||
if (!emote.Category.HasFlag(EmoteCategory.Vocal))
|
||||
return;
|
||||
|
||||
if (_mimePowersQuery.HasComp(ent))
|
||||
_popup.PopupEntity(Loc.GetString("mime-cant-speak"), ent, ent);
|
||||
else
|
||||
_popup.PopupEntity(Loc.GetString("speech-muted"), ent, ent);
|
||||
|
||||
args.Handled = true;
|
||||
}
|
||||
|
||||
[SubscribeLocalEvent]
|
||||
private void OnSpeakAttempt(Entity<MutedComponent> ent, ref SpeakAttemptEvent args)
|
||||
{
|
||||
// TODO something better than this.
|
||||
if (_mimePowersQuery.HasComp(ent))
|
||||
_popup.PopupEntity(Loc.GetString("mime-cant-speak"), ent, ent);
|
||||
else if (_puppetQuery.HasComp(ent))
|
||||
_popup.PopupEntity(Loc.GetString("ventriloquist-puppet-cant-speak"), ent, ent);
|
||||
else
|
||||
_popup.PopupEntity(Loc.GetString("speech-muted"), ent, ent);
|
||||
|
||||
args.Cancel();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Shared.StatusEffectNew.Components;
|
||||
|
||||
/// <summary>
|
||||
/// Applies a set of permanent status effects while this component exists.
|
||||
/// </summary>
|
||||
[RegisterComponent, NetworkedComponent]
|
||||
public sealed partial class PermanentStatusEffectsComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// The status effects to apply.
|
||||
/// </summary>
|
||||
[DataField(required: true)]
|
||||
public HashSet<EntProtoId> StatusEffects = new();
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
using Content.Shared.StatusEffectNew.Components;
|
||||
|
||||
namespace Content.Shared.StatusEffectNew;
|
||||
|
||||
/// <summary>
|
||||
/// Keeps permanent status effects from <see cref="PermanentStatusEffectsComponent"/> applied
|
||||
/// for as long as the owning component exists.
|
||||
/// </summary>
|
||||
public sealed partial class PermanentStatusEffectsSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private StatusEffectsSystem _statusEffects = default!;
|
||||
|
||||
[SubscribeLocalEvent]
|
||||
private void OnMapInit(Entity<PermanentStatusEffectsComponent> ent, ref MapInitEvent args)
|
||||
{
|
||||
foreach (var effect in ent.Comp.StatusEffects)
|
||||
{
|
||||
_statusEffects.TrySetStatusEffectDuration(ent, effect);
|
||||
}
|
||||
}
|
||||
|
||||
[SubscribeLocalEvent]
|
||||
private void OnRemove(Entity<PermanentStatusEffectsComponent> ent, ref ComponentRemove args)
|
||||
{
|
||||
foreach (var effect in ent.Comp.StatusEffects)
|
||||
{
|
||||
_statusEffects.TryRemoveStatusEffect(ent, effect);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,14 +1,16 @@
|
|||
using Content.Shared.Body.Events;
|
||||
using Content.Shared.Chat;
|
||||
using Content.Shared.Damage.Events;
|
||||
using Content.Shared.Damage.Systems;
|
||||
using Content.Shared.Eye.Blinding.Systems;
|
||||
using Content.Shared.Flash;
|
||||
using Content.Shared.Mobs.Events;
|
||||
using Content.Shared.Mobs;
|
||||
using Content.Shared.Mobs.Events;
|
||||
using Content.Shared.Movement.Events;
|
||||
using Content.Shared.Movement.Systems;
|
||||
using Content.Shared.Rejuvenate;
|
||||
using Content.Shared.Speech;
|
||||
using Content.Shared.Speech.EntitySystems;
|
||||
using Content.Shared.StatusEffectNew.Components;
|
||||
using Content.Shared.Stunnable;
|
||||
using Robust.Shared.Player;
|
||||
|
|
@ -40,8 +42,11 @@ public sealed partial class StatusEffectsSystem
|
|||
|
||||
SubscribeLocalEvent<StatusEffectContainerComponent, BeforeForceSayEvent>(RelayStatusEffectEvent);
|
||||
SubscribeLocalEvent<StatusEffectContainerComponent, BeforeAlertSeverityCheckEvent>(RelayStatusEffectEvent);
|
||||
SubscribeLocalEvent<StatusEffectContainerComponent, SpeakAttemptEvent>(RelayStatusEffectEvent);
|
||||
|
||||
SubscribeLocalEvent<StatusEffectContainerComponent, EmoteActionEvent>(RelayStatusEffectEvent, before: new[] { typeof(VocalSystem) });
|
||||
SubscribeLocalEvent<StatusEffectContainerComponent, AccentGetEvent>(RefRelayStatusEffectEvent);
|
||||
SubscribeLocalEvent<StatusEffectContainerComponent, EmoteEvent>(RefRelayStatusEffectEvent, before: new[] { typeof(VocalSystem), typeof(MumbleAccentSystem) });
|
||||
|
||||
SubscribeLocalEvent<StatusEffectContainerComponent, BleedModifierEvent>(RefRelayStatusEffectEvent);
|
||||
SubscribeLocalEvent<StatusEffectContainerComponent, DamageModifyEvent>(RelayStatusEffectEvent);
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
entity-effect-status-effect-KnockedDown = knockdown
|
||||
entity-effect-status-effect-Jitter = jittering
|
||||
entity-effect-status-effect-SeeingRainbows = hallucinations
|
||||
entity-effect-status-effect-Muted = inability to speak
|
||||
entity-effect-status-effect-Stutter = stuttering
|
||||
entity-effect-status-effect-ForcedSleep = unconsciousness
|
||||
entity-effect-status-effect-Drunk = drunkenness
|
||||
|
|
|
|||
|
|
@ -73,7 +73,6 @@
|
|||
allowed:
|
||||
- Electrocution
|
||||
- PressureImmunity
|
||||
- Muted
|
||||
- Pacified
|
||||
- Flashed
|
||||
- Adrenaline
|
||||
|
|
|
|||
|
|
@ -21,7 +21,6 @@
|
|||
- Narcolepsy
|
||||
- ImpairedMobility
|
||||
# - LegsParalyzed (you get healed)
|
||||
- Muted
|
||||
- PermanentBlindness
|
||||
- Snoring
|
||||
- Unrevivable
|
||||
|
|
|
|||
|
|
@ -431,13 +431,15 @@
|
|||
accentHColor: "#333333"
|
||||
- type: Icon
|
||||
state: pda-mime
|
||||
- type: Muted # for random sentience event
|
||||
- type: EntityTableContainerFill
|
||||
containers:
|
||||
preinstalled-program-container: !type:AllSelector
|
||||
children:
|
||||
- id: CrewManifestCartridge
|
||||
- id: NewsReaderCartridge
|
||||
- type: PermanentStatusEffects # for random sentience event
|
||||
statusEffects:
|
||||
- TraitStatusEffectMuted
|
||||
|
||||
- type: entity
|
||||
name: chaplain PDA
|
||||
|
|
|
|||
|
|
@ -167,7 +167,9 @@
|
|||
- type: VentriloquistPuppet
|
||||
- type: Item
|
||||
size: Normal
|
||||
- type: Muted
|
||||
- type: PermanentStatusEffects
|
||||
statusEffects:
|
||||
- StatusEffectVentriloquistPuppetMuted
|
||||
- type: TypingIndicator
|
||||
proto: robot
|
||||
- type: Actions
|
||||
|
|
|
|||
|
|
@ -63,6 +63,38 @@
|
|||
- type: StunnedStatusEffect
|
||||
- type: KnockdownStatusEffect
|
||||
|
||||
# Prevents speaking and vocal emotes.
|
||||
- type: entity
|
||||
abstract: true
|
||||
parent: MobStatusEffectBase
|
||||
id: MutedStatusEffectBase
|
||||
name: muted
|
||||
components:
|
||||
- type: StatusEffectAlert
|
||||
alert: Muted
|
||||
- type: MutedStatusEffect
|
||||
|
||||
- type: entity
|
||||
parent: [ MutedStatusEffectBase, MobStatusEffectDebuff ]
|
||||
id: StatusEffectMuted
|
||||
|
||||
- type: entity
|
||||
parent: MutedStatusEffectBase
|
||||
id: StatusEffectMimeMuted
|
||||
components:
|
||||
- type: StatusEffectAlert
|
||||
alert: VowOfSilence
|
||||
- type: MutedStatusEffect
|
||||
speakPopup: mime-cant-speak
|
||||
actionPopup: mime-cant-speak
|
||||
|
||||
- type: entity
|
||||
parent: MutedStatusEffectBase
|
||||
id: StatusEffectVentriloquistPuppetMuted
|
||||
components:
|
||||
- type: MutedStatusEffect
|
||||
speakPopup: ventriloquist-puppet-cant-speak
|
||||
|
||||
# Blurs your vision and makes you randomly fall asleep
|
||||
- type: entity
|
||||
parent: MobStatusEffectDebuff
|
||||
|
|
|
|||
|
|
@ -22,3 +22,6 @@
|
|||
id: TraitStatusEffectPainNumbness
|
||||
name: pain numbness
|
||||
|
||||
- type: entity
|
||||
parent: [ MutedStatusEffectBase, TraitStatusEffectBase ]
|
||||
id: TraitStatusEffectMuted
|
||||
|
|
|
|||
|
|
@ -1540,9 +1540,8 @@
|
|||
metabolisms:
|
||||
Digestion:
|
||||
effects:
|
||||
- !type:GenericStatusEffect
|
||||
key: Muted
|
||||
component: Muted
|
||||
- !type:ModifyStatusEffect
|
||||
effectProto: StatusEffectMuted
|
||||
- !type:SatiateThirst
|
||||
factor: 2
|
||||
|
||||
|
|
@ -2051,9 +2050,8 @@
|
|||
metabolites:
|
||||
Ethanol: 0.14
|
||||
effects:
|
||||
- !type:GenericStatusEffect
|
||||
key: Muted
|
||||
component: Muted
|
||||
- !type:ModifyStatusEffect
|
||||
effectProto: StatusEffectMuted
|
||||
- !type:SatiateThirst
|
||||
factor: 2
|
||||
|
||||
|
|
|
|||
|
|
@ -123,9 +123,8 @@
|
|||
type: Add
|
||||
Digestion:
|
||||
effects:
|
||||
- !type:GenericStatusEffect
|
||||
key: Muted
|
||||
component: Muted
|
||||
- !type:ModifyStatusEffect
|
||||
effectProto: StatusEffectMuted
|
||||
time: 5
|
||||
footstepSound:
|
||||
collection: FootstepSlime
|
||||
|
|
|
|||
|
|
@ -343,9 +343,8 @@
|
|||
metabolisms:
|
||||
Bloodstream:
|
||||
effects:
|
||||
- !type:GenericStatusEffect
|
||||
key: Muted
|
||||
component: Muted
|
||||
- !type:ModifyStatusEffect
|
||||
effectProto: StatusEffectMuted
|
||||
type: Add
|
||||
time: 10
|
||||
|
||||
|
|
|
|||
|
|
@ -62,8 +62,10 @@
|
|||
blacklist:
|
||||
components:
|
||||
- BorgChassis
|
||||
components:
|
||||
- type: Muted
|
||||
specials:
|
||||
- !type:ApplyStatusEffectSpecial
|
||||
statusEffects:
|
||||
- TraitStatusEffectMuted
|
||||
|
||||
- type: trait
|
||||
id: Paracusia
|
||||
|
|
|
|||
|
|
@ -30,10 +30,6 @@
|
|||
- type: statusEffect
|
||||
id: PressureImmunity
|
||||
|
||||
- type: statusEffect
|
||||
id: Muted
|
||||
alert: Muted
|
||||
|
||||
- type: statusEffect
|
||||
id: Corporeal
|
||||
alert: Corporeal
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue