diff --git a/Content.Client/Entry/IgnoredComponents.cs b/Content.Client/Entry/IgnoredComponents.cs index 2ee9e2f2e6..96669d2bb5 100644 --- a/Content.Client/Entry/IgnoredComponents.cs +++ b/Content.Client/Entry/IgnoredComponents.cs @@ -144,6 +144,7 @@ namespace Content.Client.Entry "MovedByPressure", "Spray", "Vapor", + "AddAccentClothing", "DamageOnHighSpeedImpact", "SolutionContainerManager", "RefillableSolution", diff --git a/Content.Server/Chat/Managers/ChatManager.cs b/Content.Server/Chat/Managers/ChatManager.cs index 299709bc48..09aeb75338 100644 --- a/Content.Server/Chat/Managers/ChatManager.cs +++ b/Content.Server/Chat/Managers/ChatManager.cs @@ -173,16 +173,16 @@ namespace Content.Server.Chat.Managers return; } + message = message.Trim(); + + message = SanitizeMessageCapital(source, message); + foreach (var handler in _chatTransformHandlers) { //TODO: rather return a bool and use a out var? message = handler(source, message); } - message = message.Trim(); - - message = SanitizeMessageCapital(source, message); - var listeners = EntitySystem.Get(); listeners.PingListeners(source, message); @@ -211,16 +211,16 @@ namespace Content.Server.Chat.Managers return; } + message = message.Trim(); + + message = SanitizeMessageCapital(source, message); + foreach (var handler in _chatTransformHandlers) { //TODO: rather return a bool and use a out var? message = handler(source, message); } - message = message.Trim(); - - message = SanitizeMessageCapital(source, message); - var listeners = EntitySystem.Get(); listeners.PingListeners(source, message); diff --git a/Content.Server/Speech/Components/AddAccentClothingComponent.cs b/Content.Server/Speech/Components/AddAccentClothingComponent.cs new file mode 100644 index 0000000000..280ee16273 --- /dev/null +++ b/Content.Server/Speech/Components/AddAccentClothingComponent.cs @@ -0,0 +1,32 @@ +using Robust.Shared.GameObjects; +using Robust.Shared.Serialization.Manager.Attributes; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; + +namespace Content.Server.Speech.Components; + +/// +/// Applies accent to user while they wear entity as a clothing. +/// +[RegisterComponent] +public class AddAccentClothingComponent : Component +{ + public override string Name => "AddAccentClothing"; + + /// + /// Component name for accent that will be applied. + /// + [DataField("accent", required: true)] + public string Accent = default!; + + /// + /// What to use. + /// Will be applied only with . + /// + [DataField("replacement", customTypeSerializer: typeof(PrototypeIdSerializer))] + public string? ReplacementPrototype; + + /// + /// Is that clothing is worn and affecting someones accent? + /// + public bool IsActive = false; +} diff --git a/Content.Server/Speech/EntitySystems/AddAccentClothingSystem.cs b/Content.Server/Speech/EntitySystems/AddAccentClothingSystem.cs new file mode 100644 index 0000000000..263752f82b --- /dev/null +++ b/Content.Server/Speech/EntitySystems/AddAccentClothingSystem.cs @@ -0,0 +1,60 @@ +using Content.Server.Clothing.Components; +using Content.Server.Speech.Components; +using Content.Shared.Inventory.Events; +using Robust.Shared.GameObjects; +using Robust.Shared.IoC; + +namespace Content.Server.Speech.EntitySystems; + +public class AddAccentClothingSystem : EntitySystem +{ + [Dependency] private readonly IComponentFactory _componentFactory = default!; + + public override void Initialize() + { + base.Initialize(); + SubscribeLocalEvent(OnGotEquipped); + SubscribeLocalEvent(OnGotUnequipped); + } + + private void OnGotEquipped(EntityUid uid, AddAccentClothingComponent component, GotEquippedEvent args) + { + if (!TryComp(uid, out ClothingComponent? clothing)) + return; + + // check if entity was actually used as clothing + // not just taken in pockets or something + var isCorrectSlot = clothing.SlotFlags.HasFlag(args.SlotFlags); + if (!isCorrectSlot) return; + + // does the user already has this accent? + var componentType = _componentFactory.GetRegistration(component.Accent).Type; + if (EntityManager.HasComponent(args.Equipee, componentType)) return; + + // add accent to the user + var accentComponent = (Component) _componentFactory.GetComponent(componentType); + accentComponent.Owner = args.Equipee; + EntityManager.AddComponent(args.Equipee, accentComponent); + + // snowflake case for replacement accent + if (accentComponent is ReplacementAccentComponent rep) + rep.Accent = component.ReplacementPrototype!; + + component.IsActive = true; + } + + private void OnGotUnequipped(EntityUid uid, AddAccentClothingComponent component, GotUnequippedEvent args) + { + if (!component.IsActive) + return; + + // try to remove accent + var componentType = _componentFactory.GetRegistration(component.Accent).Type; + if (EntityManager.HasComponent(args.Equipee, componentType)) + { + EntityManager.RemoveComponent(args.Equipee, componentType); + } + + component.IsActive = false; + } +} diff --git a/Resources/Prototypes/Catalog/Fills/Lockers/wardrobe_job.yml b/Resources/Prototypes/Catalog/Fills/Lockers/wardrobe_job.yml index 2691af310c..e517a4c8f0 100644 --- a/Resources/Prototypes/Catalog/Fills/Lockers/wardrobe_job.yml +++ b/Resources/Prototypes/Catalog/Fills/Lockers/wardrobe_job.yml @@ -12,6 +12,8 @@ amount: 2 - id: ClothingShoesColorBlack amount: 2 + - id: ClothingMaskMuzzle + amount: 1 #- type: entity # id: WardrobePajamaFilled @@ -75,8 +77,8 @@ prob: 0.5 - id: CrowbarRed #The jojoke - hit video game Half-Life prob: 0.1 - - + + - type: entity id: WardrobeBotanistFilled suffix: Filled @@ -139,7 +141,7 @@ amount: 1 - id: ClothingUniformJumpskirtChaplain amount: 1 - + - type: entity id: WardrobeSecurityFilled @@ -182,7 +184,7 @@ amount: 1 - id: ClothingUniformJumpskirtCargo amount: 1 - + # - type: entity # id: WardrobeAtmosphericsFilled diff --git a/Resources/Prototypes/Entities/Clothing/Masks/masks.yml b/Resources/Prototypes/Entities/Clothing/Masks/masks.yml index 9112452d8e..a932f5d072 100644 --- a/Resources/Prototypes/Entities/Clothing/Masks/masks.yml +++ b/Resources/Prototypes/Entities/Clothing/Masks/masks.yml @@ -72,3 +72,18 @@ sprite: Clothing/Mask/sterile.rsi - type: BreathMask - type: IngestionBlocker + +- type: entity + parent: ClothingMaskBase + id: ClothingMaskMuzzle + name: muzzle + description: To stop that awful noise. + components: + - type: Sprite + sprite: Clothing/Mask/muzzle.rsi + - type: Clothing + sprite: Clothing/Mask/muzzle.rsi + - type: IngestionBlocker + - type: AddAccentClothing + accent: ReplacementAccent + replacement: mumble diff --git a/Resources/Prototypes/accents.yml b/Resources/Prototypes/accents.yml index 9a95284724..decc7210b7 100644 --- a/Resources/Prototypes/accents.yml +++ b/Resources/Prototypes/accents.yml @@ -23,3 +23,10 @@ - Piep! - Chuu! - Eeee! + +- type: accent + id: mumble + words: + - Mmfph! + - Mmmf mrrfff! + - Mmmf mnnf! diff --git a/Resources/Textures/Clothing/Mask/muzzle.rsi/equipped-MASK.png b/Resources/Textures/Clothing/Mask/muzzle.rsi/equipped-MASK.png new file mode 100644 index 0000000000..117476873b Binary files /dev/null and b/Resources/Textures/Clothing/Mask/muzzle.rsi/equipped-MASK.png differ diff --git a/Resources/Textures/Clothing/Mask/muzzle.rsi/icon.png b/Resources/Textures/Clothing/Mask/muzzle.rsi/icon.png new file mode 100644 index 0000000000..9f1b19ecdf Binary files /dev/null and b/Resources/Textures/Clothing/Mask/muzzle.rsi/icon.png differ diff --git a/Resources/Textures/Clothing/Mask/muzzle.rsi/inhand-left.png b/Resources/Textures/Clothing/Mask/muzzle.rsi/inhand-left.png new file mode 100644 index 0000000000..99abbac3a7 Binary files /dev/null and b/Resources/Textures/Clothing/Mask/muzzle.rsi/inhand-left.png differ diff --git a/Resources/Textures/Clothing/Mask/muzzle.rsi/inhand-right.png b/Resources/Textures/Clothing/Mask/muzzle.rsi/inhand-right.png new file mode 100644 index 0000000000..a3c20a67a4 Binary files /dev/null and b/Resources/Textures/Clothing/Mask/muzzle.rsi/inhand-right.png differ diff --git a/Resources/Textures/Clothing/Mask/muzzle.rsi/meta.json b/Resources/Textures/Clothing/Mask/muzzle.rsi/meta.json new file mode 100644 index 0000000000..a1e3d6e733 --- /dev/null +++ b/Resources/Textures/Clothing/Mask/muzzle.rsi/meta.json @@ -0,0 +1,26 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from tgstation at commit https://github.com/tgstation/tgstation/commit/4f6190e2895e09116663ef282d3ce1d8b35c032e", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "icon" + }, + { + "name": "equipped-MASK", + "directions": 4 + }, + { + "name": "inhand-left", + "directions": 4 + }, + { + "name": "inhand-right", + "directions": 4 + } + ] +} \ No newline at end of file