From aadcc48ddc88e6a5f8f44699fb3fb69da7b4eb89 Mon Sep 17 00:00:00 2001 From: Slava0135 <40753025+Slava0135@users.noreply.github.com> Date: Fri, 30 Jun 2023 22:07:44 +0300 Subject: [PATCH] Better glue (#17381) --- Content.Server/Glue/GlueSystem.cs | 125 ++++++++++++------ Content.Server/Glue/GluedSystem.cs | 60 --------- Content.Shared/Glue/GlueComponent.cs | 47 +++++-- Content.Shared/Glue/GluedComponent.cs | 34 +---- Content.Shared/Glue/SharedGlueSystem.cs | 5 + Resources/Locale/en-US/glue/glue.ftl | 4 +- .../Objects/Consumable/Drinks/drinks_fun.yml | 1 + .../Prototypes/Entities/Objects/Fun/toys.yml | 36 ++--- .../Textures/Objects/Fun/glue.rsi/icon-1.png | Bin 16122 -> 0 bytes .../Fun/glue.rsi/{icon-0.png => icon.png} | Bin .../Textures/Objects/Fun/glue.rsi/meta.json | 5 +- 11 files changed, 148 insertions(+), 169 deletions(-) delete mode 100644 Content.Server/Glue/GluedSystem.cs create mode 100644 Content.Shared/Glue/SharedGlueSystem.cs delete mode 100644 Resources/Textures/Objects/Fun/glue.rsi/icon-1.png rename Resources/Textures/Objects/Fun/glue.rsi/{icon-0.png => icon.png} (100%) diff --git a/Content.Server/Glue/GlueSystem.cs b/Content.Server/Glue/GlueSystem.cs index fbd2800704..1017c7290a 100644 --- a/Content.Server/Glue/GlueSystem.cs +++ b/Content.Server/Glue/GlueSystem.cs @@ -1,59 +1,106 @@ using Content.Shared.IdentityManagement; using Content.Shared.Popups; using Content.Shared.Item; -using Content.Shared.Interaction.Components; using Content.Shared.Glue; -using Content.Server.Nutrition.EntitySystems; using Content.Shared.Interaction; +using Content.Server.Chemistry.EntitySystems; using Content.Server.Nutrition.Components; +using Content.Shared.Hands; +using Robust.Shared.Timing; +using Content.Shared.Interaction.Components; -namespace Content.Server.Glue +namespace Content.Server.Glue; + +public sealed class GlueSystem : SharedGlueSystem { - public sealed class GlueSystem : EntitySystem + [Dependency] private readonly SharedAudioSystem _audio = default!; + [Dependency] private readonly SharedPopupSystem _popup = default!; + [Dependency] private readonly SolutionContainerSystem _solutionContainer = default!; + [Dependency] private readonly IGameTiming _timing = default!; + [Dependency] private readonly MetaDataSystem _metaData = default!; + + public override void Initialize() { - [Dependency] private readonly SharedAudioSystem _audio = default!; - [Dependency] private readonly SharedPopupSystem _popup = default!; - [Dependency] private readonly FoodSystem _food = default!; + base.Initialize(); + SubscribeLocalEvent(OnInteract); + SubscribeLocalEvent(OnGluedInit); + SubscribeLocalEvent(OnHandPickUp); + } - public override void Initialize() + // When glue bottle is used on item it will apply the glued and unremoveable components. + private void OnInteract(EntityUid uid, GlueComponent component, AfterInteractEvent args) + { + if (args.Handled) + return; + + if (!args.CanReach || args.Target is not { Valid: true } target) + return; + + if (TryComp(uid, out var drink) && !drink.Opened) { - base.Initialize(); - - SubscribeLocalEvent(OnInteract); + return; } - // When glue bottle is used on item it will apply the glued and unremoveable components. - private void OnInteract(EntityUid uid, GlueComponent component, AfterInteractEvent args) + if (TryGlue(uid, component, target)) { - if (args.Handled) - return; - - if (!args.CanReach || args.Target is not { Valid: true } target) - return; - - if (HasComp(target)) - { - _popup.PopupEntity(Loc.GetString("glue-failure", ("target", Identity.Entity(target, EntityManager))), args.User, - args.User, PopupType.Medium); - return; - } - - if (HasComp(target)) - { - _audio.PlayPvs(component.Squeeze, uid); - _popup.PopupEntity(Loc.GetString("glue-success", ("target", Identity.Entity(target, EntityManager))), args.User, - args.User, PopupType.Medium); - EnsureComp(target); - } - - if (TryComp(uid, out var food)) - { - _food.DeleteAndSpawnTrash(food, uid, args.User); - } - args.Handled = true; + _audio.PlayPvs(component.Squeeze, uid); + _popup.PopupEntity(Loc.GetString("glue-success", ("target", target)), args.User, args.User, PopupType.Medium); + } + else + { + _popup.PopupEntity(Loc.GetString("glue-failure", ("target", target)), args.User, args.User, PopupType.Medium); + } + } + + private bool TryGlue(EntityUid uid, GlueComponent component, EntityUid target) + { + // if item is glued then don't apply glue again so it can be removed for reasonable time + if (HasComp(target) || !HasComp(target)) + { + return false; } + if (HasComp(target) && _solutionContainer.TryGetSolution(uid, component.Solution, out var solution)) + { + var quantity = solution.RemoveReagent(component.Reagent, component.ConsumptionUnit); + if (quantity > 0) + { + EnsureComp(target).Duration = quantity.Double() * component.DurationPerUnit; + return true; + } + } + return false; + } + + public override void Update(float frameTime) + { + base.Update(frameTime); + + var query = EntityQueryEnumerator(); + while (query.MoveNext(out var uid, out var glue, out _)) + { + if (_timing.CurTime < glue.Until) + continue; + + _metaData.SetEntityName(uid, glue.BeforeGluedEntityName); + RemComp(uid); + RemComp(uid); + } + } + + private void OnGluedInit(EntityUid uid, GluedComponent component, ComponentInit args) + { + var meta = MetaData(uid); + var name = meta.EntityName; + component.BeforeGluedEntityName = meta.EntityName; + _metaData.SetEntityName(uid, Loc.GetString("glued-name-prefix", ("target", name))); + } + + private void OnHandPickUp(EntityUid uid, GluedComponent component, GotEquippedHandEvent args) + { + EnsureComp(uid); + component.Until = _timing.CurTime + component.Duration; } } diff --git a/Content.Server/Glue/GluedSystem.cs b/Content.Server/Glue/GluedSystem.cs deleted file mode 100644 index 6a7516cd79..0000000000 --- a/Content.Server/Glue/GluedSystem.cs +++ /dev/null @@ -1,60 +0,0 @@ -using Content.Shared.Interaction.Components; -using Robust.Shared.Timing; -using Content.Shared.Glue; -using Content.Shared.Hands; - -namespace Content.Server.Glue; - -public sealed class GluedSystem : EntitySystem -{ - [Dependency] private readonly SharedAudioSystem _audio = default!; - [Dependency] private readonly IGameTiming _timing = default!; - - public override void Initialize() - { - base.Initialize(); - - SubscribeLocalEvent(OnGluedInit); - SubscribeLocalEvent(OnHandPickUp); - } - - // Timing to remove glued and unremoveable. - public override void Update(float frameTime) - { - base.Update(frameTime); - - - var query = EntityQueryEnumerator(); - while (query.MoveNext(out var uid, out var glue)) - { - if (!glue.GlueBroken || glue.Glued) - continue; - - if (_timing.CurTime < glue.GlueTime) - continue; - - glue.Glued = false; - glue.GlueBroken = false; - MetaData(uid).EntityName = glue.BeforeGluedEntityName; - RemComp(uid); - RemComp(uid); - } - } - - //Adds the prefix on init. - private void OnGluedInit(EntityUid uid, GluedComponent component, ComponentInit args) - { - var meta = MetaData(uid); - var name = meta.EntityName; - component.BeforeGluedEntityName = meta.EntityName; - meta.EntityName = Loc.GetString("glued-name-prefix", ("target", name)); - } - - // Timers start only when the glued item is picked up. - private void OnHandPickUp(EntityUid uid, GluedComponent component, GotEquippedHandEvent args) - { - EnsureComp(uid); - component.GlueBroken = true; - component.GlueTime = _timing.CurTime + component.GlueCooldown; - } -} diff --git a/Content.Shared/Glue/GlueComponent.cs b/Content.Shared/Glue/GlueComponent.cs index 89a2c39789..b9a5ff70ad 100644 --- a/Content.Shared/Glue/GlueComponent.cs +++ b/Content.Shared/Glue/GlueComponent.cs @@ -1,15 +1,42 @@ +using Content.Shared.Chemistry.Reagent; +using Content.Shared.FixedPoint; using Robust.Shared.Audio; using Robust.Shared.GameStates; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; -namespace Content.Shared.Glue +namespace Content.Shared.Glue; + +[RegisterComponent, NetworkedComponent] +[Access(typeof(SharedGlueSystem))] +public sealed class GlueComponent : Component { - [RegisterComponent, NetworkedComponent] - public sealed class GlueComponent : Component - { - /// - /// Noise made when glue applied. - /// - [DataField("squeeze")] - public SoundSpecifier Squeeze = new SoundPathSpecifier("/Audio/Items/squeezebottle.ogg"); - } + /// + /// Noise made when glue applied. + /// + [DataField("squeeze")] + public SoundSpecifier Squeeze = new SoundPathSpecifier("/Audio/Items/squeezebottle.ogg"); + + /// + /// Solution on the entity that contains the glue. + /// + [DataField("solution")] + public string Solution = "drink"; + + /// + /// Reagent that will be used as glue. + /// + [DataField("reagent", customTypeSerializer: typeof(PrototypeIdSerializer))] + public string Reagent = "SpaceGlue"; + + /// + /// Reagent consumption per use. + /// + [DataField("consumptionUnit"), ViewVariables(VVAccess.ReadWrite)] + public FixedPoint2 ConsumptionUnit = FixedPoint2.New(5); + + /// + /// Duration per unit + /// + [DataField("durationPerUnit"), ViewVariables(VVAccess.ReadWrite)] + public TimeSpan DurationPerUnit = TimeSpan.FromSeconds(6); } diff --git a/Content.Shared/Glue/GluedComponent.cs b/Content.Shared/Glue/GluedComponent.cs index e9fcead70f..9d34d9722e 100644 --- a/Content.Shared/Glue/GluedComponent.cs +++ b/Content.Shared/Glue/GluedComponent.cs @@ -1,42 +1,20 @@ -using Robust.Shared.Audio; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom; namespace Content.Shared.Glue; [RegisterComponent] +[Access(typeof(SharedGlueSystem))] public sealed class GluedComponent : Component { /// /// Reverts name to before prefix event (essentially removes prefix). /// [DataField("beforeGluedEntityName"), ViewVariables(VVAccess.ReadOnly)] - public string BeforeGluedEntityName = String.Empty; + public string BeforeGluedEntityName = string.Empty; - /// - /// Sound made when glue applied. - /// - [DataField("squeeze")] - public SoundSpecifier Squeeze = new SoundPathSpecifier("/Audio/Items/squeezebottle.ogg"); + [DataField("until", customTypeSerializer: typeof(TimeOffsetSerializer)), ViewVariables(VVAccess.ReadWrite)] + public TimeSpan Until; - /// - /// Timings for glue duration and removal. - /// - [DataField("nextGlueTime", customTypeSerializer: typeof(TimeOffsetSerializer)), ViewVariables(VVAccess.ReadWrite)] - public TimeSpan? NextGlueTime; - - [DataField("glueTime", customTypeSerializer: typeof(TimeOffsetSerializer))] - public TimeSpan GlueTime = TimeSpan.Zero; - - [DataField("glueCooldown")] - public TimeSpan GlueCooldown = TimeSpan.FromSeconds(20); - - - /// - /// Bools which control timings and when to apply the glue effect. - /// - public bool GlueBroken = false; - - [DataField("glued")] - [ViewVariables(VVAccess.ReadWrite)] - public bool Glued = false; + [DataField("duration", customTypeSerializer: typeof(TimeOffsetSerializer)), ViewVariables(VVAccess.ReadWrite)] + public TimeSpan Duration; } diff --git a/Content.Shared/Glue/SharedGlueSystem.cs b/Content.Shared/Glue/SharedGlueSystem.cs new file mode 100644 index 0000000000..d8b413a1e1 --- /dev/null +++ b/Content.Shared/Glue/SharedGlueSystem.cs @@ -0,0 +1,5 @@ +namespace Content.Shared.Glue; + +public abstract class SharedGlueSystem : EntitySystem +{ +} diff --git a/Resources/Locale/en-US/glue/glue.ftl b/Resources/Locale/en-US/glue/glue.ftl index 2f12083a14..1d0db515cb 100644 --- a/Resources/Locale/en-US/glue/glue.ftl +++ b/Resources/Locale/en-US/glue/glue.ftl @@ -1,3 +1,3 @@ -glue-success = {THE($target)} has been covered in glue. +glue-success = {THE($target)} has been covered in glue! glued-name-prefix = Glued {$target} -glue-failure = {THE($target)} is already covered in glue. +glue-failure = Can't cover {THE($target)} in glue! diff --git a/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks_fun.yml b/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks_fun.yml index cfdc5a6b54..edbe6e6865 100644 --- a/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks_fun.yml +++ b/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks_fun.yml @@ -19,6 +19,7 @@ - state: icon-front map: [ "enum.SolutionContainerLayers.Overlay" ] - type: Appearance + - type: Glue - type: SolutionContainerManager solutions: drink: diff --git a/Resources/Prototypes/Entities/Objects/Fun/toys.yml b/Resources/Prototypes/Entities/Objects/Fun/toys.yml index e487a1651b..e6f1dc8a74 100644 --- a/Resources/Prototypes/Entities/Objects/Fun/toys.yml +++ b/Resources/Prototypes/Entities/Objects/Fun/toys.yml @@ -1144,43 +1144,27 @@ Quantity: 100 - type: entity - parent: FoodProduceBase + parent: DrinkBase id: CrazyGlue name: crazy glue description: A bottle of crazy glue manufactured by Honk! Co. components: - - type: FlavorProfile - flavors: - - glue - - type: Food - trash: CrazyGlueEmpty + - type: Drink + isOpen: false + openSounds: + collection: packetOpenSounds - type: Sprite sprite: Objects/Fun/glue.rsi - state: icon-0 + state: icon - type: Appearance - type: Glue + consumptionUnit: 10 - type: Item sprite: Objects/Fun/glue.rsi - type: SolutionContainerManager solutions: - food: - maxVol: 15 + drink: + maxVol: 100 reagents: - ReagentId: SpaceGlue - Quantity: 6 - -- type: entity - name: empty crazy glue - parent: BaseItem - id: CrazyGlueEmpty - components: - - type: Sprite - sprite: Objects/Fun/glue.rsi - state: icon-1 - - type: Item - sprite: Objects/Fun/glue.rsi - - type: Tag - tags: - - Recyclable - - Trash - - type: SpaceGarbage + Quantity: 100 diff --git a/Resources/Textures/Objects/Fun/glue.rsi/icon-1.png b/Resources/Textures/Objects/Fun/glue.rsi/icon-1.png deleted file mode 100644 index b648e9eb40fb82ad0bfdd7c7b22e967f340710a2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16122 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 Ugc~{JznwnVKNNpr-NfDh1_-sMumAu6 diff --git a/Resources/Textures/Objects/Fun/glue.rsi/icon-0.png b/Resources/Textures/Objects/Fun/glue.rsi/icon.png similarity index 100% rename from Resources/Textures/Objects/Fun/glue.rsi/icon-0.png rename to Resources/Textures/Objects/Fun/glue.rsi/icon.png diff --git a/Resources/Textures/Objects/Fun/glue.rsi/meta.json b/Resources/Textures/Objects/Fun/glue.rsi/meta.json index be4241324e..d2ae18500a 100644 --- a/Resources/Textures/Objects/Fun/glue.rsi/meta.json +++ b/Resources/Textures/Objects/Fun/glue.rsi/meta.json @@ -8,10 +8,7 @@ }, "states": [ { - "name": "icon-0" - }, - { - "name": "icon-1" + "name": "icon" }, { "name": "inhand-left",