From 5a1e317e0f926a0f0c336e8630f3d95b27137d3d Mon Sep 17 00:00:00 2001 From: Ed <96445749+TheShuEd@users.noreply.github.com> Date: Fri, 22 Dec 2023 12:54:00 +0300 Subject: [PATCH] It's time to build a barbershop! (#22565) * barber! * 5% change to maintenance --- .../MagicMirrorBoundUserInterface.cs | 11 ++ .../MagicMirror/MagicMirrorComponent.cs | 19 ++ .../MagicMirror/MagicMirrorSystem.cs | 165 +++++++++++++----- .../MagicMirror/SharedMagicMirrorSystem.cs | 49 ++++++ Resources/Audio/Items/attributions.yml | 7 +- Resources/Audio/Items/scissors.ogg | Bin 0 -> 20596 bytes .../catalog/fills/crates/service-crates.ftl | 2 +- .../Catalog/Fills/Crates/service.yml | 1 + .../Prototypes/Catalog/Fills/Lockers/misc.yml | 2 + .../Objects/Specific/Service/barber.yml | 25 +++ .../Objects/Tools/scissors.rsi/icon.png | Bin 0 -> 446 bytes .../Objects/Tools/scissors.rsi/meta.json | 14 ++ 12 files changed, 253 insertions(+), 42 deletions(-) create mode 100644 Resources/Audio/Items/scissors.ogg create mode 100644 Resources/Prototypes/Entities/Objects/Specific/Service/barber.yml create mode 100644 Resources/Textures/Objects/Tools/scissors.rsi/icon.png create mode 100644 Resources/Textures/Objects/Tools/scissors.rsi/meta.json diff --git a/Content.Client/MagicMirror/MagicMirrorBoundUserInterface.cs b/Content.Client/MagicMirror/MagicMirrorBoundUserInterface.cs index ba4362a472..ebb6780853 100644 --- a/Content.Client/MagicMirror/MagicMirrorBoundUserInterface.cs +++ b/Content.Client/MagicMirror/MagicMirrorBoundUserInterface.cs @@ -64,5 +64,16 @@ public sealed class MagicMirrorBoundUserInterface : BoundUserInterface _window.UpdateState(data); } + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + if (!disposing) + return; + + if (_window != null) + _window.OnClose -= Close; + + _window?.Dispose(); + } } diff --git a/Content.Server/MagicMirror/MagicMirrorComponent.cs b/Content.Server/MagicMirror/MagicMirrorComponent.cs index d9c2fff6da..b974b513cd 100644 --- a/Content.Server/MagicMirror/MagicMirrorComponent.cs +++ b/Content.Server/MagicMirror/MagicMirrorComponent.cs @@ -1,6 +1,25 @@ +using Content.Shared.Humanoid; +using Robust.Shared.Audio; + namespace Content.Server.MagicMirror; [RegisterComponent] public sealed partial class MagicMirrorComponent : Component { + public Entity? Target; + + [DataField, ViewVariables(VVAccess.ReadWrite)] + public float AddSlotTime = 5f; + + [DataField, ViewVariables(VVAccess.ReadWrite)] + public float RemoveSlotTime = 2f; + + [DataField, ViewVariables(VVAccess.ReadWrite)] + public float SelectSlotTime = 3f; + + [DataField, ViewVariables(VVAccess.ReadWrite)] + public float ChangeSlotTime = 1f; + + [DataField, ViewVariables(VVAccess.ReadWrite)] + public SoundSpecifier ChangeHairSound = new SoundPathSpecifier("/Audio/Items/scissors.ogg"); } diff --git a/Content.Server/MagicMirror/MagicMirrorSystem.cs b/Content.Server/MagicMirror/MagicMirrorSystem.cs index a599a2c868..eb989eafd6 100644 --- a/Content.Server/MagicMirror/MagicMirrorSystem.cs +++ b/Content.Server/MagicMirror/MagicMirrorSystem.cs @@ -1,16 +1,22 @@ using System.Linq; +using Content.Server.DoAfter; using Content.Server.Humanoid; using Content.Server.UserInterface; +using Content.Shared.DoAfter; using Content.Shared.Humanoid; using Content.Shared.Humanoid.Markings; +using Content.Shared.Interaction; using Content.Shared.MagicMirror; using Robust.Server.GameObjects; +using Robust.Shared.Audio.Systems; using Robust.Shared.Player; namespace Content.Server.MagicMirror; public sealed class MagicMirrorSystem : EntitySystem { + [Dependency] private readonly SharedAudioSystem _audio = default!; + [Dependency] private readonly DoAfterSystem _doAfterSystem = default!; [Dependency] private readonly MarkingManager _markings = default!; [Dependency] private readonly HumanoidAppearanceSystem _humanoid = default!; [Dependency] private readonly UserInterfaceSystem _uiSystem = default!; @@ -22,9 +28,27 @@ public sealed class MagicMirrorSystem : EntitySystem SubscribeLocalEvent(OnOpenUIAttempt); SubscribeLocalEvent(AfterUIOpen); SubscribeLocalEvent(OnMagicMirrorSelect); - SubscribeLocalEvent(OnMagicMirrorChangeColor); - SubscribeLocalEvent(OnMagicMirrorAddSlot); - SubscribeLocalEvent(OnMagicMirrorRemoveSlot); + SubscribeLocalEvent(OnTryMagicMirrorChangeColor); + SubscribeLocalEvent(OnTryMagicMirrorAddSlot); + SubscribeLocalEvent(OnTryMagicMirrorRemoveSlot); + + SubscribeLocalEvent(OnMagicMirrorInteract); + + SubscribeLocalEvent(OnSelectSlotDoAfter); + SubscribeLocalEvent(OnChangeColorDoAfter); + SubscribeLocalEvent(OnRemoveSlotDoAfter); + SubscribeLocalEvent(OnAddSlotDoAfter); + } + + private void OnMagicMirrorInteract(Entity mirror, ref AfterInteractEvent args) + { + if (!TryComp(args.User, out var actor)) return; + if (TryComp(args.Target, out var humanoid)) + { + mirror.Comp.Target = new Entity(args.Target.Value, humanoid); + UpdateInterface(mirror.Owner, mirror.Comp.Target.Value.Owner, actor.PlayerSession); + Log.Debug($"Target {mirror.Comp.Target}!"); + }; } private void OnOpenUIAttempt(EntityUid uid, MagicMirrorComponent mirror, ActivatableUIOpenAttemptEvent args) @@ -33,16 +57,32 @@ public sealed class MagicMirrorSystem : EntitySystem args.Cancel(); } - private void OnMagicMirrorSelect(EntityUid uid, MagicMirrorComponent component, - MagicMirrorSelectMessage message) + private void OnMagicMirrorSelect(EntityUid uid, MagicMirrorComponent component, MagicMirrorSelectMessage message) { - if (message.Session.AttachedEntity == null || !TryComp(message.Session.AttachedEntity.Value, out var humanoid)) + if (component.Target == null) return; + if (message.Session.AttachedEntity == null) return; + + var doAfter = new SelectDoAfterEvent(message); + _doAfterSystem.TryStartDoAfter(new DoAfterArgs(EntityManager, message.Session.AttachedEntity.Value, component.SelectSlotTime, doAfter, uid, target: component.Target.Value.Owner, used: uid) { + BreakOnTargetMove = true, + BreakOnDamage = true, + BreakOnHandChange = false, + BreakOnUserMove = true, + BreakOnWeightlessMove = false, + NeedHand = true + }); + + _audio.PlayPvs(component.ChangeHairSound, uid); + } + private void OnSelectSlotDoAfter(EntityUid uid, MagicMirrorComponent component, SelectDoAfterEvent args) + { + if (args.Handled || args.Args.Target == null || args.Cancelled) return; - } + if (component.Target == null) return; var category = MarkingCategories.Hair; - switch (message.Category) + switch (args.Message.Category) { case MagicMirrorCategory.Hair: category = MarkingCategories.Hair; @@ -54,21 +94,35 @@ public sealed class MagicMirrorSystem : EntitySystem return; } - _humanoid.SetMarkingId(message.Session.AttachedEntity.Value, category, message.Slot, message.Marking); + _humanoid.SetMarkingId(component.Target.Value.Owner, category, args.Message.Slot, args.Message.Marking); - UpdateInterface(uid, message.Session.AttachedEntity.Value, message.Session); + UpdateInterface(uid, component.Target.Value.Owner, args.Message.Session); } - private void OnMagicMirrorChangeColor(EntityUid uid, MagicMirrorComponent component, - MagicMirrorChangeColorMessage message) + private void OnTryMagicMirrorChangeColor(EntityUid uid, MagicMirrorComponent component, MagicMirrorChangeColorMessage message) { - if (message.Session.AttachedEntity == null || !TryComp(message.Session.AttachedEntity.Value, out var humanoid)) + if (component.Target == null) return; + if (message.Session.AttachedEntity == null) return; + + var doAfter = new ChangeColorDoAfterEvent(message); + _doAfterSystem.TryStartDoAfter(new DoAfterArgs(EntityManager, message.Session.AttachedEntity.Value, component.ChangeSlotTime, doAfter, uid, target: component.Target.Value.Owner, used: uid) { + BreakOnTargetMove = true, + BreakOnDamage = true, + BreakOnHandChange = false, + BreakOnUserMove = true, + BreakOnWeightlessMove = false, + NeedHand = true + }); + } + private void OnChangeColorDoAfter(EntityUid uid, MagicMirrorComponent component, ChangeColorDoAfterEvent args) + { + if (args.Handled || args.Args.Target == null || args.Cancelled) return; - } + if (component.Target == null) return; var category = MarkingCategories.Hair; - switch (message.Category) + switch (args.Message.Category) { case MagicMirrorCategory.Hair: category = MarkingCategories.Hair; @@ -80,22 +134,39 @@ public sealed class MagicMirrorSystem : EntitySystem return; } - _humanoid.SetMarkingColor(message.Session.AttachedEntity.Value, category, message.Slot, message.Colors); + _humanoid.SetMarkingColor(component.Target.Value.Owner, category, args.Message.Slot, args.Message.Colors); // using this makes the UI feel like total ass - // UpdateInterface(uid, message.Session.AttachedEntity.Value, message.Session); + // UpdateInterface(uid, component.Target, message.Session); } - private void OnMagicMirrorRemoveSlot(EntityUid uid, MagicMirrorComponent component, - MagicMirrorRemoveSlotMessage message) + private void OnTryMagicMirrorRemoveSlot(EntityUid uid, MagicMirrorComponent component, MagicMirrorRemoveSlotMessage message) { - if (message.Session.AttachedEntity == null || !TryComp(message.Session.AttachedEntity.Value, out var humanoid)) + if (component.Target == null) return; + if (message.Session.AttachedEntity == null) return; + + var doAfter = new RemoveSlotDoAfterEvent(message); + _doAfterSystem.TryStartDoAfter(new DoAfterArgs(EntityManager, message.Session.AttachedEntity.Value, component.RemoveSlotTime, doAfter, uid, target: component.Target.Value.Owner, used: uid) { + BreakOnTargetMove = true, + BreakOnDamage = true, + BreakOnHandChange = false, + BreakOnUserMove = true, + BreakOnWeightlessMove = false, + NeedHand = true + }); + + _audio.PlayPvs(component.ChangeHairSound, uid); + } + private void OnRemoveSlotDoAfter(EntityUid uid, MagicMirrorComponent component, RemoveSlotDoAfterEvent args) + { + if (args.Handled || args.Args.Target == null || args.Cancelled) return; - } + + if (component.Target == null) return; var category = MarkingCategories.Hair; - switch (message.Category) + switch (args.Message.Category) { case MagicMirrorCategory.Hair: category = MarkingCategories.Hair; @@ -107,21 +178,37 @@ public sealed class MagicMirrorSystem : EntitySystem return; } - _humanoid.RemoveMarking(message.Session.AttachedEntity.Value, category, message.Slot); + _humanoid.RemoveMarking(component.Target.Value.Owner, category, args.Message.Slot); - UpdateInterface(uid, message.Session.AttachedEntity.Value, message.Session); + UpdateInterface(uid, component.Target.Value.Owner, args.Message.Session); } - private void OnMagicMirrorAddSlot(EntityUid uid, MagicMirrorComponent component, - MagicMirrorAddSlotMessage message) + private void OnTryMagicMirrorAddSlot(EntityUid uid, MagicMirrorComponent component, MagicMirrorAddSlotMessage message) { - if (message.Session.AttachedEntity == null || !TryComp(message.Session.AttachedEntity.Value, out var humanoid)) + if (component.Target == null) return; + if (message.Session.AttachedEntity == null) return; + + var doAfter = new AddSlotDoAfterEvent(message); + _doAfterSystem.TryStartDoAfter(new DoAfterArgs(EntityManager, message.Session.AttachedEntity.Value, component.AddSlotTime, doAfter, uid, target: component.Target.Value.Owner, used: uid) { + BreakOnTargetMove = true, + BreakOnDamage = true, + BreakOnHandChange = false, + BreakOnUserMove = true, + BreakOnWeightlessMove = false, + NeedHand = true + }); + _audio.PlayPvs(component.ChangeHairSound, uid); + } + private void OnAddSlotDoAfter(EntityUid uid, MagicMirrorComponent component, AddSlotDoAfterEvent args) + { + if (args.Handled || args.Args.Target == null || args.Cancelled) return; - } + + if (component.Target == null) return; var category = MarkingCategories.Hair; - switch (message.Category) + switch (args.Message.Category) { case MagicMirrorCategory.Hair: category = MarkingCategories.Hair; @@ -133,23 +220,21 @@ public sealed class MagicMirrorSystem : EntitySystem return; } - var marking = _markings.MarkingsByCategoryAndSpecies(category, humanoid.Species).Keys.FirstOrDefault(); + var marking = _markings.MarkingsByCategoryAndSpecies(category, component.Target.Value.Comp.Species).Keys.FirstOrDefault(); if (string.IsNullOrEmpty(marking)) { return; } - _humanoid.AddMarking(message.Session.AttachedEntity.Value, marking, Color.Black); + _humanoid.AddMarking(component.Target.Value.Owner, marking, Color.Black); - UpdateInterface(uid, message.Session.AttachedEntity.Value, message.Session); + UpdateInterface(uid, component.Target.Value.Owner, args.Message.Session); } - private void UpdateInterface(EntityUid uid, EntityUid playerUid, ICommonSession session, HumanoidAppearanceComponent? humanoid = null) + private void UpdateInterface(EntityUid uid, EntityUid playerUid, ICommonSession session) { - if (!Resolve(playerUid, ref humanoid) || session is not { } player) - { - return; - } + if (!TryComp(playerUid, out var humanoid)) return; + if (session is not { } player) return; var hair = humanoid.MarkingSet.TryGetCategory(MarkingCategories.Hair, out var hairMarkings) ? new List(hairMarkings) @@ -171,9 +256,9 @@ public sealed class MagicMirrorSystem : EntitySystem private void AfterUIOpen(EntityUid uid, MagicMirrorComponent component, AfterActivatableUIOpenEvent args) { - var looks = Comp(args.User); - var actor = Comp(args.User); + if (!TryComp(args.User, out var humanoid)) return; + component.Target = new Entity(args.User, humanoid); UpdateInterface(uid, args.User, args.Session); } -} \ No newline at end of file +} diff --git a/Content.Shared/MagicMirror/SharedMagicMirrorSystem.cs b/Content.Shared/MagicMirror/SharedMagicMirrorSystem.cs index 831beb06d6..7d389c90e0 100644 --- a/Content.Shared/MagicMirror/SharedMagicMirrorSystem.cs +++ b/Content.Shared/MagicMirror/SharedMagicMirrorSystem.cs @@ -1,3 +1,4 @@ +using Content.Shared.DoAfter; using Content.Shared.Humanoid.Markings; using Robust.Shared.Serialization; @@ -104,3 +105,51 @@ public sealed class MagicMirrorUiData : BoundUserInterfaceMessage public int FacialHairSlotTotal { get; } } + +[Serializable, NetSerializable] +public sealed partial class RemoveSlotDoAfterEvent : DoAfterEvent +{ + public MagicMirrorRemoveSlotMessage Message; + + public RemoveSlotDoAfterEvent(MagicMirrorRemoveSlotMessage message) + { + Message = message; + } + public override DoAfterEvent Clone() => this; +} + +[Serializable, NetSerializable] +public sealed partial class AddSlotDoAfterEvent : DoAfterEvent +{ + public MagicMirrorAddSlotMessage Message; + + public AddSlotDoAfterEvent(MagicMirrorAddSlotMessage message) + { + Message = message; + } + public override DoAfterEvent Clone() => this; +} + +[Serializable, NetSerializable] +public sealed partial class SelectDoAfterEvent : DoAfterEvent +{ + public MagicMirrorSelectMessage Message; + + public SelectDoAfterEvent(MagicMirrorSelectMessage message) + { + Message = message; + } + public override DoAfterEvent Clone() => this; +} + +[Serializable, NetSerializable] +public sealed partial class ChangeColorDoAfterEvent : DoAfterEvent +{ + public MagicMirrorChangeColorMessage Message; + + public ChangeColorDoAfterEvent(MagicMirrorChangeColorMessage message) + { + Message = message; + } + public override DoAfterEvent Clone() => this; +} diff --git a/Resources/Audio/Items/attributions.yml b/Resources/Audio/Items/attributions.yml index 7822272424..7e186cc076 100644 --- a/Resources/Audio/Items/attributions.yml +++ b/Resources/Audio/Items/attributions.yml @@ -81,4 +81,9 @@ - files: ["ring.ogg"] license: "CC-BY-SA-3.0" copyright: "Taken from /tg/station" - source: "https://github.com/tgstation/tgstation/commit/c61c452d78425d89920b41ed5f95fd190e733a3c" \ No newline at end of file + source: "https://github.com/tgstation/tgstation/commit/c61c452d78425d89920b41ed5f95fd190e733a3c" + +- files: ["scissors.ogg"] + license: "CC0-1.0" + copyright: "User Hanbaal on freesound.org. Converted to ogg by TheShuEd" + source: "https://freesound.org/people/Hanbaal/sounds/178669/" \ No newline at end of file diff --git a/Resources/Audio/Items/scissors.ogg b/Resources/Audio/Items/scissors.ogg new file mode 100644 index 0000000000000000000000000000000000000000..1031c426acdffeff128e8ff447728523291cac20 GIT binary patch literal 20596 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 literal 0 HcmV?d00001 diff --git a/Resources/Locale/en-US/prototypes/catalog/fills/crates/service-crates.ftl b/Resources/Locale/en-US/prototypes/catalog/fills/crates/service-crates.ftl index 2bed24a4ef..d44be5e979 100644 --- a/Resources/Locale/en-US/prototypes/catalog/fills/crates/service-crates.ftl +++ b/Resources/Locale/en-US/prototypes/catalog/fills/crates/service-crates.ftl @@ -32,7 +32,7 @@ ent-CrateJanitorBiosuit = Janitor bio suit crate .desc = Contains 2 biohazard suits to ensure that no disease will distract you from cleaning. ent-CrateServiceTheatre = Theatrical performances crate - .desc = Contains a moth cloak, maid uniform, clown and mime attributes, and other performance charms. + .desc = Contains a moth cloak, barber scissors, maid uniform, clown and mime attributes, and other performance charms. ent-CrateJanitorExplosive = Janitorial bomb suit crate .desc = Supplies a bomb suit for cleaning up any explosive compounds, buy one today! diff --git a/Resources/Prototypes/Catalog/Fills/Crates/service.yml b/Resources/Prototypes/Catalog/Fills/Crates/service.yml index df789208e7..a1cb914a1a 100644 --- a/Resources/Prototypes/Catalog/Fills/Crates/service.yml +++ b/Resources/Prototypes/Catalog/Fills/Crates/service.yml @@ -76,6 +76,7 @@ - id: ClothingUniformJumpskirtJanimaid - id: ClothingNeckCloakVoid - id: RevolverCapGun + - id: BarberScissors - type: entity id: CrateServiceCustomSmokable diff --git a/Resources/Prototypes/Catalog/Fills/Lockers/misc.yml b/Resources/Prototypes/Catalog/Fills/Lockers/misc.yml index 171546052a..6acbe12af2 100644 --- a/Resources/Prototypes/Catalog/Fills/Lockers/misc.yml +++ b/Resources/Prototypes/Catalog/Fills/Lockers/misc.yml @@ -152,6 +152,8 @@ prob: 0.20 - id: DrinkSpaceLube prob: 0.20 + - id: BarberScissors + prob: 0.05 # Syndicate loot - id: null prob: 0.95 diff --git a/Resources/Prototypes/Entities/Objects/Specific/Service/barber.yml b/Resources/Prototypes/Entities/Objects/Specific/Service/barber.yml new file mode 100644 index 0000000000..e8cb94c524 --- /dev/null +++ b/Resources/Prototypes/Entities/Objects/Specific/Service/barber.yml @@ -0,0 +1,25 @@ +- type: entity + id: BarberScissors + name: barber scissors + description: is able to reshape the hairstyle of any crew cut to your liking. + parent: BaseItem + components: + - type: Sprite + sprite: Objects/Tools/scissors.rsi + state: icon + - type: MagicMirror + - type: ActivatableUI + key: enum.MagicMirrorUiKey.Key + closeOnHandDeselect: true + - type: UserInterface + interfaces: + - key: enum.MagicMirrorUiKey.Key + type: MagicMirrorBoundUserInterface + - type: MeleeWeapon + wideAnimationRotation: -90 + attackRate: 1 + damage: + types: + Piercing: 6 + soundHit: + path: "/Audio/Weapons/bladeslice.ogg" \ No newline at end of file diff --git a/Resources/Textures/Objects/Tools/scissors.rsi/icon.png b/Resources/Textures/Objects/Tools/scissors.rsi/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..b92e52267636cee044300ffd1fd7d0e099d5ad13 GIT binary patch literal 446 zcmV;v0YUzWP)Px$cu7P-R9J=WmOo3wKp4iK6CuSmLCBWTNwWx|pTV!7P9>X#Dh>*QICXN<4sMQJ zbPNZAIOy0?aH%eJ>{bX(TI|wukb_vSvG-?D@`DfvclSK+d(R~Sa&rC?joUjWJ7>X^ zct|OW;>6T)@~Bh~80vsd^+pT~h9eWps1Z`iRND_2=)hn&f=>9f41|=Gn^HW(jK>NGD%KSjzyf9spX+wvw=v z0e;M!;u3(b>K`7Tu(`FNEXAAUuY3&u4C7 zf@-frT+2d#JVqrblPFG*zFN(;jy8adE!ca1BLJ}d`a*a&c(tO?sWS6L)L2<%>3f=+ z>nmd04(w7<+rY0G0Dx+*L(%D~*zJ)iMz+^?-OQD;<;`WB>f(f=^> oGbOc3RxVVL+CNb)a&rDWpP5#tvR_C|+5i9m07*qoM6N<$f)8rJ@c;k- literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Tools/scissors.rsi/meta.json b/Resources/Textures/Objects/Tools/scissors.rsi/meta.json new file mode 100644 index 0000000000..b544b3bc15 --- /dev/null +++ b/Resources/Textures/Objects/Tools/scissors.rsi/meta.json @@ -0,0 +1,14 @@ +{ + "version": 1, + "license": "CC0-1.0", + "copyright": "Created by TheShuEd(github) for Space Station 14", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "icon" + } + ] +} -- 2.51.2