diff --git a/Content.Server/Chat/ChatManager.cs b/Content.Server/Chat/ChatManager.cs index e1b614f017..d4235b55dc 100644 --- a/Content.Server/Chat/ChatManager.cs +++ b/Content.Server/Chat/ChatManager.cs @@ -4,6 +4,7 @@ using Content.Server.Administration; using Content.Server.GameObjects.Components.GUI; using Content.Server.GameObjects.Components.Headset; using Content.Server.GameObjects.Components.Items.Storage; +using Content.Server.GameObjects.Components.Mobs.Speech; using Content.Server.GameObjects.Components.Observer; using Content.Server.GameObjects.EntitySystems; using Content.Server.Interfaces; diff --git a/Content.Server/Commands/MakeSentientCommand.cs b/Content.Server/Commands/MakeSentientCommand.cs index aa9c99cdb0..7882fde7ba 100644 --- a/Content.Server/Commands/MakeSentientCommand.cs +++ b/Content.Server/Commands/MakeSentientCommand.cs @@ -1,8 +1,10 @@ #nullable enable using Content.Server.Administration; using Content.Server.GameObjects.Components.Mobs; +using Content.Server.GameObjects.Components.Mobs.Speech; using Content.Server.GameObjects.Components.Movement; using Content.Shared.Administration; +using Content.Shared.GameObjects.Components.Mobs.Speech; using Robust.Server.Interfaces.Player; using Robust.Shared.Console; using Robust.Shared.GameObjects; @@ -47,6 +49,8 @@ namespace Content.Server.Commands entity.EnsureComponent(); entity.EnsureComponent(); + entity.EnsureComponent(); + entity.EnsureComponent(); } } } diff --git a/Content.Server/GameObjects/Components/Mobs/Speech/SpeechComponent.cs b/Content.Server/GameObjects/Components/Mobs/Speech/IAccentComponent.cs similarity index 51% rename from Content.Server/GameObjects/Components/Mobs/Speech/SpeechComponent.cs rename to Content.Server/GameObjects/Components/Mobs/Speech/IAccentComponent.cs index 35ab69ed11..92efa89b8d 100644 --- a/Content.Server/GameObjects/Components/Mobs/Speech/SpeechComponent.cs +++ b/Content.Server/GameObjects/Components/Mobs/Speech/IAccentComponent.cs @@ -1,4 +1,11 @@ -namespace Content.Server.GameObjects.Components.Mobs.Speech +#nullable enable +using Content.Shared.GameObjects.Components.Mobs.Speech; +using Content.Shared.GameObjects.EntitySystems.ActionBlocker; +using Robust.Shared.GameObjects; +using Robust.Shared.Interfaces.GameObjects; +using Robust.Shared.Serialization; + +namespace Content.Server.GameObjects.Components.Mobs.Speech { internal interface IAccentComponent { diff --git a/Content.Shared/GameObjects/Components/Mobs/Speech/SharedEmotingComponent.cs b/Content.Shared/GameObjects/Components/Mobs/Speech/SharedEmotingComponent.cs new file mode 100644 index 0000000000..edf003a196 --- /dev/null +++ b/Content.Shared/GameObjects/Components/Mobs/Speech/SharedEmotingComponent.cs @@ -0,0 +1,33 @@ +using Content.Shared.GameObjects.EntitySystems.ActionBlocker; +using Robust.Shared.GameObjects; +using Robust.Shared.Serialization; + +namespace Content.Shared.GameObjects.Components.Mobs.Speech +{ + [RegisterComponent] + public class SharedEmotingComponent : Component, IActionBlocker + { + private bool _enabled = true; + public override string Name => "Emoting"; + + public bool Enabled + { + get => _enabled; + set + { + if (_enabled == value) return; + _enabled = value; + Dirty(); + } + } + + bool IActionBlocker.CanEmote() => Enabled; + + public override void ExposeData(ObjectSerializer serializer) + { + base.ExposeData(serializer); + + serializer.DataField(this, x => x.Enabled, "enabled", true); + } + } +} diff --git a/Content.Shared/GameObjects/Components/Mobs/Speech/SharedSpeechComponent.cs b/Content.Shared/GameObjects/Components/Mobs/Speech/SharedSpeechComponent.cs new file mode 100644 index 0000000000..12a7a77995 --- /dev/null +++ b/Content.Shared/GameObjects/Components/Mobs/Speech/SharedSpeechComponent.cs @@ -0,0 +1,36 @@ +using Content.Shared.GameObjects.EntitySystems.ActionBlocker; +using Robust.Shared.GameObjects; +using Robust.Shared.Serialization; + +namespace Content.Shared.GameObjects.Components.Mobs.Speech +{ + /// + /// Component required for entities to be able to speak. + /// + [RegisterComponent] + public class SharedSpeechComponent : Component, IActionBlocker + { + private bool _enabled = true; + public override string Name => "Speech"; + + public bool Enabled + { + get => _enabled; + set + { + if (_enabled == value) return; + _enabled = value; + Dirty(); + } + } + + bool IActionBlocker.CanSpeak() => Enabled; + + public override void ExposeData(ObjectSerializer serializer) + { + base.ExposeData(serializer); + + serializer.DataField(this, x => x.Enabled, "enabled", true); + } + } +} diff --git a/Content.Shared/GameObjects/EntitySystems/ActionBlocker/ActionBlockerSystem.cs b/Content.Shared/GameObjects/EntitySystems/ActionBlocker/ActionBlockerSystem.cs index 63367caa19..b2adcf73e1 100644 --- a/Content.Shared/GameObjects/EntitySystems/ActionBlocker/ActionBlockerSystem.cs +++ b/Content.Shared/GameObjects/EntitySystems/ActionBlocker/ActionBlockerSystem.cs @@ -1,4 +1,5 @@ -using Content.Shared.GameObjects.EntitySystems.EffectBlocker; +using Content.Shared.GameObjects.Components.Mobs.Speech; +using Content.Shared.GameObjects.EntitySystems.EffectBlocker; using JetBrains.Annotations; using Robust.Shared.GameObjects.Systems; using Robust.Shared.Interfaces.GameObjects; @@ -62,6 +63,9 @@ namespace Content.Shared.GameObjects.EntitySystems.ActionBlocker public static bool CanSpeak(IEntity entity) { + if (!entity.HasComponent()) + return false; + var canSpeak = true; foreach (var blocker in entity.GetAllComponents()) @@ -98,6 +102,9 @@ namespace Content.Shared.GameObjects.EntitySystems.ActionBlocker public static bool CanEmote(IEntity entity) { + if (!entity.HasComponent()) + return false; + var canEmote = true; foreach (var blocker in entity.GetAllComponents()) diff --git a/Resources/Prototypes/Entities/Mobs/Species/human.yml b/Resources/Prototypes/Entities/Mobs/Species/human.yml index 4291e33116..c4ec747fc5 100644 --- a/Resources/Prototypes/Entities/Mobs/Species/human.yml +++ b/Resources/Prototypes/Entities/Mobs/Species/human.yml @@ -210,6 +210,8 @@ meat: FoodMeat - type: Recyclable safe: false + - type: Speech + - type: Emoting - type: entity save: false