From 20a68cfaf0c42c38f30e5f168d5c2702cc818b06 Mon Sep 17 00:00:00 2001 From: sirionaut Date: Fri, 21 Jun 2024 12:04:00 +0200 Subject: [PATCH 01/17] Changed comments to be more clear and uniform. EggLayer uses NextGrowth instead of frame accumulation. Egglayer uses much less energy to make eggs, and lay time is randomized for player and AI chicken. --- .../Animals/Components/EggLayerComponent.cs | 52 ++++++++++++------- .../Animals/Components/UdderComponent.cs | 3 +- .../Animals/Components/WoolyComponent.cs | 3 +- .../Animals/Systems/EggLayerSystem.cs | 24 +++++---- Content.Server/Animals/Systems/UdderSystem.cs | 4 +- Content.Server/Animals/Systems/WoolySystem.cs | 4 +- 6 files changed, 55 insertions(+), 35 deletions(-) diff --git a/Content.Server/Animals/Components/EggLayerComponent.cs b/Content.Server/Animals/Components/EggLayerComponent.cs index a0f7de676e5f..3b61fd7e3e43 100644 --- a/Content.Server/Animals/Components/EggLayerComponent.cs +++ b/Content.Server/Animals/Components/EggLayerComponent.cs @@ -1,6 +1,10 @@ +using Content.Server.Animals.Systems; using Content.Shared.Storage; using Robust.Shared.Audio; using Robust.Shared.Prototypes; +using Content.Shared.FixedPoint; +using Robust.Shared.Prototypes; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom; namespace Content.Server.Animals.Components; @@ -9,44 +13,52 @@ namespace Content.Server.Animals.Components; /// It also grants an action to players who are controlling these entities, allowing them to do it manually. /// -[RegisterComponent] +[RegisterComponent, Access(typeof(EggLayerSystem))] public sealed partial class EggLayerComponent : Component { - [DataField] - public EntProtoId EggLayAction = "ActionAnimalLayEgg"; + /// + /// The item that gets laid/spawned, retrieved from animal prototype. + /// + [DataField(required: true), ViewVariables(VVAccess.ReadWrite)] + public List EggSpawn = default!; /// - /// The amount of nutrient consumed on update. + /// Player action. /// - [DataField, ViewVariables(VVAccess.ReadWrite)] - public float HungerUsage = 60f; + [DataField] + public EntProtoId EggLayAction = "ActionAnimalLayEgg"; + + [DataField] + public SoundSpecifier EggLaySound = new SoundPathSpecifier("/Audio/Effects/pop.ogg"); /// /// Minimum cooldown used for the automatic egg laying. /// [DataField, ViewVariables(VVAccess.ReadWrite)] - public float EggLayCooldownMin = 60f; + public float EggLayCooldownMin = 45f; /// /// Maximum cooldown used for the automatic egg laying. /// [DataField, ViewVariables(VVAccess.ReadWrite)] - public float EggLayCooldownMax = 120f; + public float EggLayCooldownMax = 90f; /// - /// Set during component init. + /// The amount of nutrient consumed on update. /// - [ViewVariables(VVAccess.ReadWrite)] - public float CurrentEggLayCooldown; - - [DataField(required: true), ViewVariables(VVAccess.ReadWrite)] - public List EggSpawn = default!; - - [DataField] - public SoundSpecifier EggLaySound = new SoundPathSpecifier("/Audio/Effects/pop.ogg"); - - [DataField] - public float AccumulatedFrametime; + [DataField, ViewVariables(VVAccess.ReadWrite)] + public float HungerUsage = 10f; [DataField] public EntityUid? Action; + /// + /// How long to wait before producing. + /// + [DataField, ViewVariables(VVAccess.ReadWrite)] + public TimeSpan GrowthDelay = TimeSpan.FromMinutes(1); + + /// + /// When to next try to produce. + /// + [DataField(customTypeSerializer: typeof(TimeOffsetSerializer)), ViewVariables(VVAccess.ReadWrite)] + public TimeSpan NextGrowth = TimeSpan.FromSeconds(0); } diff --git a/Content.Server/Animals/Components/UdderComponent.cs b/Content.Server/Animals/Components/UdderComponent.cs index 620f4572a712..527215fc14e7 100644 --- a/Content.Server/Animals/Components/UdderComponent.cs +++ b/Content.Server/Animals/Components/UdderComponent.cs @@ -8,7 +8,8 @@ namespace Content.Server.Animals.Components /// -/// Lets an entity produce milk. Uses hunger if present. +/// Gives the ability to produce a solution; +/// produces endlessly if the owner does not have a HungerComponent. /// { [RegisterComponent, Access(typeof(UdderSystem))] diff --git a/Content.Server/Animals/Components/WoolyComponent.cs b/Content.Server/Animals/Components/WoolyComponent.cs index c09c6f5e089e..6d3ccfb113ec 100644 --- a/Content.Server/Animals/Components/WoolyComponent.cs +++ b/Content.Server/Animals/Components/WoolyComponent.cs @@ -8,7 +8,8 @@ namespace Content.Server.Animals.Components; /// -/// Lets an entity produce wool fibers. Uses hunger if present. +/// Gives the ability to produce wool fibers; +/// produces endlessly if the owner does not have a HungerComponent. /// [RegisterComponent, Access(typeof(WoolySystem))] diff --git a/Content.Server/Animals/Systems/EggLayerSystem.cs b/Content.Server/Animals/Systems/EggLayerSystem.cs index 55d63808a4b9..521fbda0c2df 100644 --- a/Content.Server/Animals/Systems/EggLayerSystem.cs +++ b/Content.Server/Animals/Systems/EggLayerSystem.cs @@ -7,15 +7,15 @@ using Content.Shared.Nutrition.EntitySystems; using Content.Shared.Storage; using Robust.Server.Audio; -using Robust.Server.GameObjects; using Robust.Shared.Player; using Robust.Shared.Random; +using Robust.Shared.Timing; namespace Content.Server.Animals.Systems; /// -/// Gives ability to produce eggs, produces endless if the -/// owner has no HungerComponent +/// Gives the ability to lay eggs/other things ; +/// produces endlessly if the owner does not have a HungerComponent. /// public sealed class EggLayerSystem : EntitySystem { @@ -23,6 +23,7 @@ public sealed class EggLayerSystem : EntitySystem [Dependency] private readonly ActionsSystem _actions = default!; [Dependency] private readonly AudioSystem _audio = default!; [Dependency] private readonly HungerSystem _hunger = default!; + [Dependency] private readonly IGameTiming _timing = default!; [Dependency] private readonly PopupSystem _popup = default!; [Dependency] private readonly MobStateSystem _mobState = default!; @@ -39,19 +40,24 @@ public override void Update(float frameTime) base.Update(frameTime); var query = EntityQueryEnumerator(); + var now = _timing.CurTime; while (query.MoveNext(out var uid, out var eggLayer)) { // Players should be using the action. if (HasComp(uid)) continue; - eggLayer.AccumulatedFrametime += frameTime; + if (now < eggLayer.NextGrowth) + continue; + + // Randomize next growth time for more organic egglaying. + eggLayer.NextGrowth = now + TimeSpan.FromSeconds(_random.NextFloat(eggLayer.EggLayCooldownMin, eggLayer.EggLayCooldownMax)); - if (eggLayer.AccumulatedFrametime < eggLayer.CurrentEggLayCooldown) + if (_mobState.IsDead(uid)) continue; - eggLayer.AccumulatedFrametime -= eggLayer.CurrentEggLayCooldown; - eggLayer.CurrentEggLayCooldown = _random.NextFloat(eggLayer.EggLayCooldownMin, eggLayer.EggLayCooldownMax); + // Hungerlevel check/modification is done in TryLayEgg() + // so its used for player controlled chickens as well. TryLayEgg(uid, eggLayer); } @@ -60,7 +66,7 @@ public override void Update(float frameTime) private void OnMapInit(EntityUid uid, EggLayerComponent component, MapInitEvent args) { _actions.AddAction(uid, ref component.Action, component.EggLayAction); - component.CurrentEggLayCooldown = _random.NextFloat(component.EggLayCooldownMin, component.EggLayCooldownMax); + component.NextGrowth = TimeSpan.FromSeconds(_random.NextFloat(component.EggLayCooldownMin, component.EggLayCooldownMax)); } private void OnEggLayAction(EntityUid uid, EggLayerComponent egglayer, EggLayInstantActionEvent args) @@ -76,7 +82,7 @@ public bool TryLayEgg(EntityUid uid, EggLayerComponent? egglayer) if (_mobState.IsDead(uid)) return false; - // Allow infinitely laying eggs if they can't get hungry + // Allow infinitely laying eggs if they can't get hungry. if (TryComp(uid, out var hunger)) { if (hunger.CurrentHunger < egglayer.HungerUsage) diff --git a/Content.Server/Animals/Systems/UdderSystem.cs b/Content.Server/Animals/Systems/UdderSystem.cs index b7856e904230..6f6e763bbc25 100644 --- a/Content.Server/Animals/Systems/UdderSystem.cs +++ b/Content.Server/Animals/Systems/UdderSystem.cs @@ -15,8 +15,8 @@ namespace Content.Server.Animals.Systems; /// -/// Gives ability to produce milkable reagents, produces endless if the -/// owner has no HungerComponent +/// Gives the ability to produce milkable reagents; +/// produces endlessly if the owner does not have a HungerComponent. /// internal sealed class UdderSystem : EntitySystem { diff --git a/Content.Server/Animals/Systems/WoolySystem.cs b/Content.Server/Animals/Systems/WoolySystem.cs index cbe959fb560b..deec5e262863 100644 --- a/Content.Server/Animals/Systems/WoolySystem.cs +++ b/Content.Server/Animals/Systems/WoolySystem.cs @@ -9,8 +9,8 @@ namespace Content.Server.Animals.Systems; /// -/// Gives ability to produce fiber reagents, produces endless if the -/// owner has no HungerComponent +/// Gives ability to produce fiber reagents; produces endlessly if the +/// owner has no HungerComponent. /// public sealed class WoolySystem : EntitySystem { From c703afc025cecc14c6d2ed53e25729bd39f9e6f9 Mon Sep 17 00:00:00 2001 From: sirionaut Date: Fri, 21 Jun 2024 16:13:17 +0200 Subject: [PATCH 02/17] UdderComponent ReagentId can be changed now UdderSystem and WoolySystem use SharedSolutionContainerSystem now --- Content.Server/Animals/Components/EggLayerComponent.cs | 4 +--- Content.Server/Animals/Components/UdderComponent.cs | 6 +++--- Content.Server/Animals/Components/WoolyComponent.cs | 2 +- Content.Server/Animals/Systems/EggLayerSystem.cs | 3 ++- Content.Server/Animals/Systems/UdderSystem.cs | 4 ++-- Content.Server/Animals/Systems/WoolySystem.cs | 4 ++-- 6 files changed, 11 insertions(+), 12 deletions(-) diff --git a/Content.Server/Animals/Components/EggLayerComponent.cs b/Content.Server/Animals/Components/EggLayerComponent.cs index 3b61fd7e3e43..010efbf204fd 100644 --- a/Content.Server/Animals/Components/EggLayerComponent.cs +++ b/Content.Server/Animals/Components/EggLayerComponent.cs @@ -2,8 +2,6 @@ using Content.Shared.Storage; using Robust.Shared.Audio; using Robust.Shared.Prototypes; -using Content.Shared.FixedPoint; -using Robust.Shared.Prototypes; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom; namespace Content.Server.Animals.Components; @@ -47,7 +45,7 @@ public sealed partial class EggLayerComponent : Component /// The amount of nutrient consumed on update. /// [DataField, ViewVariables(VVAccess.ReadWrite)] - public float HungerUsage = 10f; + public float HungerUsage = 25f; [DataField] public EntityUid? Action; /// diff --git a/Content.Server/Animals/Components/UdderComponent.cs b/Content.Server/Animals/Components/UdderComponent.cs index 527215fc14e7..f6b009f234e0 100644 --- a/Content.Server/Animals/Components/UdderComponent.cs +++ b/Content.Server/Animals/Components/UdderComponent.cs @@ -18,8 +18,8 @@ internal sealed partial class UdderComponent : Component /// /// The reagent to produce. /// - [DataField, ViewVariables(VVAccess.ReadOnly)] - public ProtoId ReagentId = "Milk"; + [DataField, ViewVariables(VVAccess.ReadWrite)] + public ProtoId ReagentId = default!; /// /// The name of . @@ -36,7 +36,7 @@ internal sealed partial class UdderComponent : Component /// /// The amount of reagent to be generated on update. /// - [DataField, ViewVariables(VVAccess.ReadOnly)] + [DataField, ViewVariables(VVAccess.ReadWrite)] public FixedPoint2 QuantityPerUpdate = 25; /// diff --git a/Content.Server/Animals/Components/WoolyComponent.cs b/Content.Server/Animals/Components/WoolyComponent.cs index 6d3ccfb113ec..7466c71898e5 100644 --- a/Content.Server/Animals/Components/WoolyComponent.cs +++ b/Content.Server/Animals/Components/WoolyComponent.cs @@ -36,7 +36,7 @@ public sealed partial class WoolyComponent : Component /// /// The amount of reagent to be generated on update. /// - [DataField, ViewVariables(VVAccess.ReadOnly)] + [DataField, ViewVariables(VVAccess.ReadWrite)] public FixedPoint2 Quantity = 25; /// diff --git a/Content.Server/Animals/Systems/EggLayerSystem.cs b/Content.Server/Animals/Systems/EggLayerSystem.cs index 521fbda0c2df..ae8cc72d1301 100644 --- a/Content.Server/Animals/Systems/EggLayerSystem.cs +++ b/Content.Server/Animals/Systems/EggLayerSystem.cs @@ -14,7 +14,7 @@ namespace Content.Server.Animals.Systems; /// -/// Gives the ability to lay eggs/other things ; +/// Gives the ability to lay eggs/other things; /// produces endlessly if the owner does not have a HungerComponent. /// public sealed class EggLayerSystem : EntitySystem @@ -71,6 +71,7 @@ private void OnMapInit(EntityUid uid, EggLayerComponent component, MapInitEvent private void OnEggLayAction(EntityUid uid, EggLayerComponent egglayer, EggLayInstantActionEvent args) { + // Cooldown is handeled by ActionAnimalLayEgg in types.yml. args.Handled = TryLayEgg(uid, egglayer); } diff --git a/Content.Server/Animals/Systems/UdderSystem.cs b/Content.Server/Animals/Systems/UdderSystem.cs index 6f6e763bbc25..60e5d2ff02d0 100644 --- a/Content.Server/Animals/Systems/UdderSystem.cs +++ b/Content.Server/Animals/Systems/UdderSystem.cs @@ -1,7 +1,7 @@ using Content.Server.Animals.Components; -using Content.Server.Chemistry.Containers.EntitySystems; using Content.Server.Popups; using Content.Shared.Chemistry.Components; +using Content.Shared.Chemistry.EntitySystems; using Content.Shared.DoAfter; using Content.Shared.IdentityManagement; using Content.Shared.Mobs.Systems; @@ -25,7 +25,7 @@ internal sealed class UdderSystem : EntitySystem [Dependency] private readonly MobStateSystem _mobState = default!; [Dependency] private readonly PopupSystem _popupSystem = default!; [Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!; - [Dependency] private readonly SolutionContainerSystem _solutionContainerSystem = default!; + [Dependency] private readonly SharedSolutionContainerSystem _solutionContainerSystem = default!; public override void Initialize() { diff --git a/Content.Server/Animals/Systems/WoolySystem.cs b/Content.Server/Animals/Systems/WoolySystem.cs index deec5e262863..378b8cb8a23d 100644 --- a/Content.Server/Animals/Systems/WoolySystem.cs +++ b/Content.Server/Animals/Systems/WoolySystem.cs @@ -1,6 +1,6 @@ using Content.Server.Animals.Components; -using Content.Server.Chemistry.Containers.EntitySystems; using Content.Server.Nutrition; +using Content.Shared.Chemistry.EntitySystems; using Content.Shared.Mobs.Systems; using Content.Shared.Nutrition.Components; using Content.Shared.Nutrition.EntitySystems; @@ -17,7 +17,7 @@ public sealed class WoolySystem : EntitySystem [Dependency] private readonly HungerSystem _hunger = default!; [Dependency] private readonly IGameTiming _timing = default!; [Dependency] private readonly MobStateSystem _mobState = default!; - [Dependency] private readonly SolutionContainerSystem _solutionContainer = default!; + [Dependency] private readonly SharedSolutionContainerSystem _solutionContainer = default!; public override void Initialize() { From f6fbfd760ba064a995a91b7c1cb80b25dbf3cb25 Mon Sep 17 00:00:00 2001 From: sirionaut Date: Fri, 21 Jun 2024 17:39:42 +0200 Subject: [PATCH 03/17] Entities with udders can be examined to see a rough hunger level udders and wooly stop reagent generation/extra nutrient usage once the solution container is full --- .../Animals/Components/EggLayerComponent.cs | 5 ---- .../Animals/Systems/EggLayerSystem.cs | 2 +- Content.Server/Animals/Systems/UdderSystem.cs | 27 ++++++++++++++++--- Content.Server/Animals/Systems/WoolySystem.cs | 9 ++++--- .../en-US/animals/udder/udder-system.ftl | 4 +++ 5 files changed, 35 insertions(+), 12 deletions(-) diff --git a/Content.Server/Animals/Components/EggLayerComponent.cs b/Content.Server/Animals/Components/EggLayerComponent.cs index 010efbf204fd..a97c27a5053c 100644 --- a/Content.Server/Animals/Components/EggLayerComponent.cs +++ b/Content.Server/Animals/Components/EggLayerComponent.cs @@ -48,11 +48,6 @@ public sealed partial class EggLayerComponent : Component public float HungerUsage = 25f; [DataField] public EntityUid? Action; - /// - /// How long to wait before producing. - /// - [DataField, ViewVariables(VVAccess.ReadWrite)] - public TimeSpan GrowthDelay = TimeSpan.FromMinutes(1); /// /// When to next try to produce. diff --git a/Content.Server/Animals/Systems/EggLayerSystem.cs b/Content.Server/Animals/Systems/EggLayerSystem.cs index ae8cc72d1301..a2499a746667 100644 --- a/Content.Server/Animals/Systems/EggLayerSystem.cs +++ b/Content.Server/Animals/Systems/EggLayerSystem.cs @@ -57,7 +57,7 @@ public override void Update(float frameTime) continue; // Hungerlevel check/modification is done in TryLayEgg() - // so its used for player controlled chickens as well. + // so it's used for player controlled chickens as well. TryLayEgg(uid, eggLayer); } diff --git a/Content.Server/Animals/Systems/UdderSystem.cs b/Content.Server/Animals/Systems/UdderSystem.cs index 60e5d2ff02d0..ac08b9078649 100644 --- a/Content.Server/Animals/Systems/UdderSystem.cs +++ b/Content.Server/Animals/Systems/UdderSystem.cs @@ -3,6 +3,7 @@ using Content.Shared.Chemistry.Components; using Content.Shared.Chemistry.EntitySystems; using Content.Shared.DoAfter; +using Content.Shared.Examine; using Content.Shared.IdentityManagement; using Content.Shared.Mobs.Systems; using Content.Shared.Nutrition.Components; @@ -33,6 +34,7 @@ public override void Initialize() SubscribeLocalEvent>(AddMilkVerb); SubscribeLocalEvent(OnDoAfter); + SubscribeLocalEvent(OnExamine); } public override void Update(float frameTime) @@ -51,6 +53,12 @@ public override void Update(float frameTime) if (_mobState.IsDead(uid)) continue; + if (!_solutionContainerSystem.ResolveSolution(uid, udder.SolutionName, ref udder.Solution, out var solution)) + continue; + + if (solution.AvailableVolume == 0) + continue; + // Actually there is food digestion so no problem with instant reagent generation "OnFeed" if (EntityManager.TryGetComponent(uid, out HungerComponent? hunger)) { @@ -61,9 +69,6 @@ public override void Update(float frameTime) _hunger.ModifyHunger(uid, -udder.HungerUsage, hunger); } - if (!_solutionContainerSystem.ResolveSolution(uid, udder.SolutionName, ref udder.Solution)) - continue; - //TODO: toxins from bloodstream !? _solutionContainerSystem.TryAddReagent(udder.Solution.Value, udder.ReagentId, udder.QuantityPerUpdate, out _); } @@ -134,4 +139,20 @@ private void AddMilkVerb(Entity entity, ref GetVerbsEvent entity, ref ExaminedEvent args) + { + if (EntityManager.TryGetComponent(entity, out HungerComponent? hunger)) + { + if (_hunger.GetHungerThreshold(hunger) == HungerThreshold.Overfed) + args.PushMarkup(Loc.GetString("udder-system-examine-overfed")); + + if (_hunger.GetHungerThreshold(hunger) <= HungerThreshold.Peckish) + args.PushMarkup(Loc.GetString("udder-system-examine-hungry")); + } + else + { + args.PushMarkup(Loc.GetString("udder-system-examine-none")); + } + } } diff --git a/Content.Server/Animals/Systems/WoolySystem.cs b/Content.Server/Animals/Systems/WoolySystem.cs index 378b8cb8a23d..46ecd8fd8a60 100644 --- a/Content.Server/Animals/Systems/WoolySystem.cs +++ b/Content.Server/Animals/Systems/WoolySystem.cs @@ -42,6 +42,12 @@ public override void Update(float frameTime) if (_mobState.IsDead(uid)) continue; + if (!_solutionContainer.ResolveSolution(uid, wooly.SolutionName, ref wooly.Solution, out var solution)) + continue; + + if (solution.AvailableVolume == 0) + continue; + // Actually there is food digestion so no problem with instant reagent generation "OnFeed" if (EntityManager.TryGetComponent(uid, out HungerComponent? hunger)) { @@ -52,9 +58,6 @@ public override void Update(float frameTime) _hunger.ModifyHunger(uid, -wooly.HungerUsage, hunger); } - if (!_solutionContainer.ResolveSolution(uid, wooly.SolutionName, ref wooly.Solution)) - continue; - _solutionContainer.TryAddReagent(wooly.Solution.Value, wooly.ReagentId, wooly.Quantity, out _); } } diff --git a/Resources/Locale/en-US/animals/udder/udder-system.ftl b/Resources/Locale/en-US/animals/udder/udder-system.ftl index 8479ae08bff0..5c3db2d7ec8a 100644 --- a/Resources/Locale/en-US/animals/udder/udder-system.ftl +++ b/Resources/Locale/en-US/animals/udder/udder-system.ftl @@ -5,3 +5,7 @@ udder-system-success = You fill {THE($target)} with {$amount}u from the udder. udder-system-dry = The udder is dry. udder-system-verb-milk = Milk + +udder-system-examine-overfed = This animal looks overfed +udder-system-examine-hungry = This animal looks hungry +udder-system-examine-none = This animal seems to not get hungry From 24cfd2db30ba15e1255797fde5436eaf95ff39d3 Mon Sep 17 00:00:00 2001 From: sirionaut Date: Sat, 22 Jun 2024 11:09:58 +0200 Subject: [PATCH 04/17] Moved stuff to Shared AutoPausedField now --- .../Animals/Components/EggLayerComponent.cs | 15 +- .../Animals/Components/UdderComponent.cs | 60 +------ .../Animals/Components/WoolyComponent.cs | 57 +----- .../Animals/Systems/EggLayerSystem.cs | 2 +- Content.Server/Animals/Systems/UdderSystem.cs | 156 +---------------- Content.Server/Animals/Systems/WoolySystem.cs | 68 +------- Content.Server/Nutrition/IngestionEvents.cs | 12 +- Content.Shared/Animal/SharedUdderComponent.cs | 60 +++++++ Content.Shared/Animal/SharedUdderSystem.cs | 162 ++++++++++++++++++ Content.Shared/Animal/SharedWoolyComponent.cs | 61 +++++++ Content.Shared/Animal/SharedWoolySystem.cs.cs | 72 ++++++++ .../Nutrition/SharedIngestionEvents.cs | 36 ++++ .../en-US/animals/udder/udder-system.ftl | 6 +- 13 files changed, 418 insertions(+), 349 deletions(-) create mode 100644 Content.Shared/Animal/SharedUdderComponent.cs create mode 100644 Content.Shared/Animal/SharedUdderSystem.cs create mode 100644 Content.Shared/Animal/SharedWoolyComponent.cs create mode 100644 Content.Shared/Animal/SharedWoolySystem.cs.cs create mode 100644 Content.Shared/Nutrition/SharedIngestionEvents.cs diff --git a/Content.Server/Animals/Components/EggLayerComponent.cs b/Content.Server/Animals/Components/EggLayerComponent.cs index a97c27a5053c..fbba2667ba2b 100644 --- a/Content.Server/Animals/Components/EggLayerComponent.cs +++ b/Content.Server/Animals/Components/EggLayerComponent.cs @@ -2,7 +2,6 @@ using Content.Shared.Storage; using Robust.Shared.Audio; using Robust.Shared.Prototypes; -using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom; namespace Content.Server.Animals.Components; @@ -11,13 +10,13 @@ namespace Content.Server.Animals.Components; /// It also grants an action to players who are controlling these entities, allowing them to do it manually. /// -[RegisterComponent, Access(typeof(EggLayerSystem))] +[RegisterComponent, Access(typeof(EggLayerSystem)), AutoGenerateComponentPause] public sealed partial class EggLayerComponent : Component { /// /// The item that gets laid/spawned, retrieved from animal prototype. /// - [DataField(required: true), ViewVariables(VVAccess.ReadWrite)] + [DataField(required: true)] public List EggSpawn = default!; /// @@ -32,19 +31,19 @@ public sealed partial class EggLayerComponent : Component /// /// Minimum cooldown used for the automatic egg laying. /// - [DataField, ViewVariables(VVAccess.ReadWrite)] + [DataField] public float EggLayCooldownMin = 45f; /// /// Maximum cooldown used for the automatic egg laying. /// - [DataField, ViewVariables(VVAccess.ReadWrite)] + [DataField] public float EggLayCooldownMax = 90f; /// /// The amount of nutrient consumed on update. /// - [DataField, ViewVariables(VVAccess.ReadWrite)] + [DataField] public float HungerUsage = 25f; [DataField] public EntityUid? Action; @@ -52,6 +51,6 @@ public sealed partial class EggLayerComponent : Component /// /// When to next try to produce. /// - [DataField(customTypeSerializer: typeof(TimeOffsetSerializer)), ViewVariables(VVAccess.ReadWrite)] - public TimeSpan NextGrowth = TimeSpan.FromSeconds(0); + [AutoPausedField] + public TimeSpan NextGrowth = TimeSpan.Zero; } diff --git a/Content.Server/Animals/Components/UdderComponent.cs b/Content.Server/Animals/Components/UdderComponent.cs index f6b009f234e0..4c1ea5f15fb1 100644 --- a/Content.Server/Animals/Components/UdderComponent.cs +++ b/Content.Server/Animals/Components/UdderComponent.cs @@ -1,60 +1,8 @@ -using Content.Server.Animals.Systems; -using Content.Shared.Chemistry.Components; -using Content.Shared.Chemistry.Reagent; -using Content.Shared.FixedPoint; -using Robust.Shared.Prototypes; -using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom; +using Content.Shared.Animals; -namespace Content.Server.Animals.Components +namespace Content.Server.Animals.Components; -/// -/// Gives the ability to produce a solution; -/// produces endlessly if the owner does not have a HungerComponent. -/// +[Access(typeof(SharedUdderComponent))] +public sealed partial class UdderComponent : SharedUdderComponent { - [RegisterComponent, Access(typeof(UdderSystem))] - internal sealed partial class UdderComponent : Component - { - /// - /// The reagent to produce. - /// - [DataField, ViewVariables(VVAccess.ReadWrite)] - public ProtoId ReagentId = default!; - - /// - /// The name of . - /// - [DataField, ViewVariables(VVAccess.ReadOnly)] - public string SolutionName = "udder"; - - /// - /// The solution to add reagent to. - /// - [DataField] - public Entity? Solution = null; - - /// - /// The amount of reagent to be generated on update. - /// - [DataField, ViewVariables(VVAccess.ReadWrite)] - public FixedPoint2 QuantityPerUpdate = 25; - - /// - /// The amount of nutrient consumed on update. - /// - [DataField, ViewVariables(VVAccess.ReadWrite)] - public float HungerUsage = 10f; - - /// - /// How long to wait before producing. - /// - [DataField, ViewVariables(VVAccess.ReadWrite)] - public TimeSpan GrowthDelay = TimeSpan.FromMinutes(1); - - /// - /// When to next try to produce. - /// - [DataField(customTypeSerializer: typeof(TimeOffsetSerializer)), ViewVariables(VVAccess.ReadWrite)] - public TimeSpan NextGrowth = TimeSpan.FromSeconds(0); - } } diff --git a/Content.Server/Animals/Components/WoolyComponent.cs b/Content.Server/Animals/Components/WoolyComponent.cs index 7466c71898e5..5e83a0babb41 100644 --- a/Content.Server/Animals/Components/WoolyComponent.cs +++ b/Content.Server/Animals/Components/WoolyComponent.cs @@ -1,59 +1,8 @@ -using Content.Server.Animals.Systems; -using Content.Shared.Chemistry.Components; -using Content.Shared.Chemistry.Reagent; -using Content.Shared.FixedPoint; -using Robust.Shared.Prototypes; -using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom; +using Content.Shared.Animals; namespace Content.Server.Animals.Components; -/// -/// Gives the ability to produce wool fibers; -/// produces endlessly if the owner does not have a HungerComponent. -/// - -[RegisterComponent, Access(typeof(WoolySystem))] -public sealed partial class WoolyComponent : Component +[Access(typeof(SharedWoolyComponent))] +public sealed partial class WoolyComponent : SharedWoolyComponent { - /// - /// The reagent to grow. - /// - [DataField, ViewVariables(VVAccess.ReadOnly)] - public ProtoId ReagentId = "Fiber"; - - /// - /// The name of . - /// - [DataField, ViewVariables(VVAccess.ReadOnly)] - public string SolutionName = "wool"; - - /// - /// The solution to add reagent to. - /// - [DataField] - public Entity? Solution; - - /// - /// The amount of reagent to be generated on update. - /// - [DataField, ViewVariables(VVAccess.ReadWrite)] - public FixedPoint2 Quantity = 25; - - /// - /// The amount of nutrient consumed on update. - /// - [DataField, ViewVariables(VVAccess.ReadWrite)] - public float HungerUsage = 10f; - - /// - /// How long to wait before growing wool. - /// - [DataField, ViewVariables(VVAccess.ReadWrite)] - public TimeSpan GrowthDelay = TimeSpan.FromMinutes(1); - - /// - /// When to next try growing wool. - /// - [DataField(customTypeSerializer: typeof(TimeOffsetSerializer)), ViewVariables(VVAccess.ReadWrite)] - public TimeSpan NextGrowth = TimeSpan.FromSeconds(0); } diff --git a/Content.Server/Animals/Systems/EggLayerSystem.cs b/Content.Server/Animals/Systems/EggLayerSystem.cs index a2499a746667..0f99d6428a68 100644 --- a/Content.Server/Animals/Systems/EggLayerSystem.cs +++ b/Content.Server/Animals/Systems/EggLayerSystem.cs @@ -66,7 +66,7 @@ public override void Update(float frameTime) private void OnMapInit(EntityUid uid, EggLayerComponent component, MapInitEvent args) { _actions.AddAction(uid, ref component.Action, component.EggLayAction); - component.NextGrowth = TimeSpan.FromSeconds(_random.NextFloat(component.EggLayCooldownMin, component.EggLayCooldownMax)); + component.NextGrowth = _timing.CurTime + TimeSpan.FromSeconds(_random.NextFloat(component.EggLayCooldownMin, component.EggLayCooldownMax)); } private void OnEggLayAction(EntityUid uid, EggLayerComponent egglayer, EggLayInstantActionEvent args) diff --git a/Content.Server/Animals/Systems/UdderSystem.cs b/Content.Server/Animals/Systems/UdderSystem.cs index ac08b9078649..69c45d128f40 100644 --- a/Content.Server/Animals/Systems/UdderSystem.cs +++ b/Content.Server/Animals/Systems/UdderSystem.cs @@ -1,158 +1,6 @@ -using Content.Server.Animals.Components; -using Content.Server.Popups; -using Content.Shared.Chemistry.Components; -using Content.Shared.Chemistry.EntitySystems; -using Content.Shared.DoAfter; -using Content.Shared.Examine; -using Content.Shared.IdentityManagement; -using Content.Shared.Mobs.Systems; -using Content.Shared.Nutrition.Components; -using Content.Shared.Nutrition.EntitySystems; -using Content.Shared.Popups; -using Content.Shared.Udder; -using Content.Shared.Verbs; -using Robust.Shared.Timing; +using Content.Shared.Animals; namespace Content.Server.Animals.Systems; - -/// -/// Gives the ability to produce milkable reagents; -/// produces endlessly if the owner does not have a HungerComponent. -/// -internal sealed class UdderSystem : EntitySystem +public sealed class UdderSystem : SharedUdderSystem { - [Dependency] private readonly HungerSystem _hunger = default!; - [Dependency] private readonly IGameTiming _timing = default!; - [Dependency] private readonly MobStateSystem _mobState = default!; - [Dependency] private readonly PopupSystem _popupSystem = default!; - [Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!; - [Dependency] private readonly SharedSolutionContainerSystem _solutionContainerSystem = default!; - - public override void Initialize() - { - base.Initialize(); - - SubscribeLocalEvent>(AddMilkVerb); - SubscribeLocalEvent(OnDoAfter); - SubscribeLocalEvent(OnExamine); - } - - public override void Update(float frameTime) - { - base.Update(frameTime); - - var query = EntityQueryEnumerator(); - var now = _timing.CurTime; - while (query.MoveNext(out var uid, out var udder)) - { - if (now < udder.NextGrowth) - continue; - - udder.NextGrowth = now + udder.GrowthDelay; - - if (_mobState.IsDead(uid)) - continue; - - if (!_solutionContainerSystem.ResolveSolution(uid, udder.SolutionName, ref udder.Solution, out var solution)) - continue; - - if (solution.AvailableVolume == 0) - continue; - - // Actually there is food digestion so no problem with instant reagent generation "OnFeed" - if (EntityManager.TryGetComponent(uid, out HungerComponent? hunger)) - { - // Is there enough nutrition to produce reagent? - if (_hunger.GetHungerThreshold(hunger) < HungerThreshold.Okay) - continue; - - _hunger.ModifyHunger(uid, -udder.HungerUsage, hunger); - } - - //TODO: toxins from bloodstream !? - _solutionContainerSystem.TryAddReagent(udder.Solution.Value, udder.ReagentId, udder.QuantityPerUpdate, out _); - } - } - - private void AttemptMilk(Entity udder, EntityUid userUid, EntityUid containerUid) - { - if (!Resolve(udder, ref udder.Comp)) - return; - - var doargs = new DoAfterArgs(EntityManager, userUid, 5, new MilkingDoAfterEvent(), udder, udder, used: containerUid) - { - BreakOnMove = true, - BreakOnDamage = true, - MovementThreshold = 1.0f, - }; - - _doAfterSystem.TryStartDoAfter(doargs); - } - - private void OnDoAfter(Entity entity, ref MilkingDoAfterEvent args) - { - if (args.Cancelled || args.Handled || args.Args.Used == null) - return; - - if (!_solutionContainerSystem.ResolveSolution(entity.Owner, entity.Comp.SolutionName, ref entity.Comp.Solution, out var solution)) - return; - - if (!_solutionContainerSystem.TryGetRefillableSolution(args.Args.Used.Value, out var targetSoln, out var targetSolution)) - return; - - args.Handled = true; - var quantity = solution.Volume; - if (quantity == 0) - { - _popupSystem.PopupEntity(Loc.GetString("udder-system-dry"), entity.Owner, args.Args.User); - return; - } - - if (quantity > targetSolution.AvailableVolume) - quantity = targetSolution.AvailableVolume; - - var split = _solutionContainerSystem.SplitSolution(entity.Comp.Solution.Value, quantity); - _solutionContainerSystem.TryAddSolution(targetSoln.Value, split); - - _popupSystem.PopupEntity(Loc.GetString("udder-system-success", ("amount", quantity), ("target", Identity.Entity(args.Args.Used.Value, EntityManager))), entity.Owner, - args.Args.User, PopupType.Medium); - } - - private void AddMilkVerb(Entity entity, ref GetVerbsEvent args) - { - if (args.Using == null || - !args.CanInteract || - !EntityManager.HasComponent(args.Using.Value)) - return; - - var uid = entity.Owner; - var user = args.User; - var used = args.Using.Value; - AlternativeVerb verb = new() - { - Act = () => - { - AttemptMilk(uid, user, used); - }, - Text = Loc.GetString("udder-system-verb-milk"), - Priority = 2 - }; - args.Verbs.Add(verb); - } - - private void OnExamine(Entity entity, ref ExaminedEvent args) - { - if (EntityManager.TryGetComponent(entity, out HungerComponent? hunger)) - { - if (_hunger.GetHungerThreshold(hunger) == HungerThreshold.Overfed) - args.PushMarkup(Loc.GetString("udder-system-examine-overfed")); - - if (_hunger.GetHungerThreshold(hunger) <= HungerThreshold.Peckish) - args.PushMarkup(Loc.GetString("udder-system-examine-hungry")); - } - else - { - args.PushMarkup(Loc.GetString("udder-system-examine-none")); - } - } } diff --git a/Content.Server/Animals/Systems/WoolySystem.cs b/Content.Server/Animals/Systems/WoolySystem.cs index 46ecd8fd8a60..5b5760ad8e30 100644 --- a/Content.Server/Animals/Systems/WoolySystem.cs +++ b/Content.Server/Animals/Systems/WoolySystem.cs @@ -1,70 +1,6 @@ -using Content.Server.Animals.Components; -using Content.Server.Nutrition; -using Content.Shared.Chemistry.EntitySystems; -using Content.Shared.Mobs.Systems; -using Content.Shared.Nutrition.Components; -using Content.Shared.Nutrition.EntitySystems; -using Robust.Shared.Timing; +using Content.Shared.Animals; namespace Content.Server.Animals.Systems; - -/// -/// Gives ability to produce fiber reagents; produces endlessly if the -/// owner has no HungerComponent. -/// -public sealed class WoolySystem : EntitySystem +public sealed class WoolySystem : SharedWoolySystem { - [Dependency] private readonly HungerSystem _hunger = default!; - [Dependency] private readonly IGameTiming _timing = default!; - [Dependency] private readonly MobStateSystem _mobState = default!; - [Dependency] private readonly SharedSolutionContainerSystem _solutionContainer = default!; - - public override void Initialize() - { - base.Initialize(); - - SubscribeLocalEvent(OnBeforeFullyEaten); - } - - public override void Update(float frameTime) - { - base.Update(frameTime); - - var query = EntityQueryEnumerator(); - var now = _timing.CurTime; - while (query.MoveNext(out var uid, out var wooly)) - { - if (now < wooly.NextGrowth) - continue; - - wooly.NextGrowth = now + wooly.GrowthDelay; - - if (_mobState.IsDead(uid)) - continue; - - if (!_solutionContainer.ResolveSolution(uid, wooly.SolutionName, ref wooly.Solution, out var solution)) - continue; - - if (solution.AvailableVolume == 0) - continue; - - // Actually there is food digestion so no problem with instant reagent generation "OnFeed" - if (EntityManager.TryGetComponent(uid, out HungerComponent? hunger)) - { - // Is there enough nutrition to produce reagent? - if (_hunger.GetHungerThreshold(hunger) < HungerThreshold.Okay) - continue; - - _hunger.ModifyHunger(uid, -wooly.HungerUsage, hunger); - } - - _solutionContainer.TryAddReagent(wooly.Solution.Value, wooly.ReagentId, wooly.Quantity, out _); - } - } - - private void OnBeforeFullyEaten(Entity ent, ref BeforeFullyEatenEvent args) - { - // don't want moths to delete goats after eating them - args.Cancel(); - } } diff --git a/Content.Server/Nutrition/IngestionEvents.cs b/Content.Server/Nutrition/IngestionEvents.cs index ae1d22fb71f4..e1cd15b49f5b 100644 --- a/Content.Server/Nutrition/IngestionEvents.cs +++ b/Content.Server/Nutrition/IngestionEvents.cs @@ -1,36 +1,34 @@ +using Content.Shared.Nutrition; + namespace Content.Server.Nutrition; /// /// Raised directed at the consumer when attempting to ingest something. /// -public sealed class IngestionAttemptEvent : CancellableEntityEventArgs +public sealed class IngestionAttemptEvent : SharedIngestionAttemptEvent { /// /// The equipment that is blocking consumption. Should only be non-null if the event was canceled. /// - public EntityUid? Blocker = null; } - /// /// Raised directed at the food after finishing eating a food before it's deleted. /// Cancel this if you want to do something special before a food is deleted. /// -public sealed class BeforeFullyEatenEvent : CancellableEntityEventArgs +public sealed class BeforeFullyEatenEvent : SharedBeforeFullyEatenEvent { /// /// The person that ate the food. /// - public EntityUid User; } /// /// Raised directed at the food being sliced before it's deleted. /// Cancel this if you want to do something special before a food is deleted. /// -public sealed class BeforeFullySlicedEvent : CancellableEntityEventArgs +public sealed class BeforeFullySlicedEvent : SharedBeforeFullySlicedEvent { /// /// The person slicing the food. /// - public EntityUid User; } diff --git a/Content.Shared/Animal/SharedUdderComponent.cs b/Content.Shared/Animal/SharedUdderComponent.cs new file mode 100644 index 000000000000..5f0dd5be02e3 --- /dev/null +++ b/Content.Shared/Animal/SharedUdderComponent.cs @@ -0,0 +1,60 @@ +using Content.Shared.Chemistry.Components; +using Content.Shared.Chemistry.Reagent; +using Content.Shared.FixedPoint; +using Robust.Shared.Prototypes; + +namespace Content.Shared.Animals; + +/// +/// Gives the ability to produce a solution; +/// produces endlessly if the owner does not have a HungerComponent. +/// +[RegisterComponent] +[Virtual] +[Access(typeof(SharedUdderComponent)), AutoGenerateComponentPause] +public partial class SharedUdderComponent : Component +{ + /// + /// The reagent to produce. + /// + [DataField] + public ProtoId ReagentId = default!; + + /// + /// The name of . + /// + [DataField, ViewVariables(VVAccess.ReadOnly)] + public string SolutionName = "udder"; + + /// + /// The solution to add reagent to. + /// + [DataField] + public Entity? Solution = null; + + /// + /// The amount of reagent to be generated on update. + /// + [DataField] + public FixedPoint2 QuantityPerUpdate = 25; + + /// + /// The amount of nutrient consumed on update. + /// + [DataField] + public float HungerUsage = 10f; + + /// + /// How long to wait before producing. + /// + [DataField] + public TimeSpan GrowthDelay = TimeSpan.FromMinutes(1); + + /// + /// When to next try to produce. + /// + //[DataField(customTypeSerializer: typeof(TimeOffsetSerializer)), Access(typeof(SharedUdderSystem))] + //public TimeSpan NextGrowth = TimeSpan.FromSeconds(0); + [AutoPausedField, Access(typeof(SharedUdderSystem))] + public TimeSpan NextGrowth = TimeSpan.Zero; +} diff --git a/Content.Shared/Animal/SharedUdderSystem.cs b/Content.Shared/Animal/SharedUdderSystem.cs new file mode 100644 index 000000000000..ca828428909b --- /dev/null +++ b/Content.Shared/Animal/SharedUdderSystem.cs @@ -0,0 +1,162 @@ +using Content.Shared.Popups; +using Content.Shared.Chemistry.Components; +using Content.Shared.Chemistry.EntitySystems; +using Content.Shared.DoAfter; +using Content.Shared.Examine; +using Content.Shared.IdentityManagement; +using Content.Shared.Mobs.Systems; +using Content.Shared.Nutrition.Components; +using Content.Shared.Nutrition.EntitySystems; + +using Content.Shared.Udder; +using Content.Shared.Verbs; +using Robust.Shared.Timing; + +namespace Content.Shared.Animals; +/// +/// Gives the ability to produce milkable reagents; +/// produces endlessly if the owner does not have a HungerComponent. +/// +[Access(typeof(SharedUdderSystem))] +public abstract class SharedUdderSystem : EntitySystem +{ + [Dependency] private readonly HungerSystem _hunger = default!; + [Dependency] private readonly IGameTiming _timing = default!; + [Dependency] private readonly MobStateSystem _mobState = default!; + [Dependency] private readonly SharedPopupSystem _popupSystem = default!; + [Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!; + [Dependency] private readonly SharedSolutionContainerSystem _solutionContainerSystem = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent>(AddMilkVerb); + SubscribeLocalEvent(OnDoAfter); + SubscribeLocalEvent(OnExamine); + } + + public override void Update(float frameTime) + { + base.Update(frameTime); + + var query = EntityQueryEnumerator(); + var now = _timing.CurTime; + while (query.MoveNext(out var uid, out var udder)) + { + if (now < udder.NextGrowth) + continue; + + udder.NextGrowth = now + udder.GrowthDelay; + + if (_mobState.IsDead(uid)) + continue; + + if (!_solutionContainerSystem.ResolveSolution(uid, udder.SolutionName, ref udder.Solution, out var solution)) + continue; + + if (solution.AvailableVolume == 0) + continue; + + // Actually there is food digestion so no problem with instant reagent generation "OnFeed" + if (EntityManager.TryGetComponent(uid, out HungerComponent? hunger)) + { + // Is there enough nutrition to produce reagent? + if (_hunger.GetHungerThreshold(hunger) < HungerThreshold.Okay) + continue; + + _hunger.ModifyHunger(uid, -udder.HungerUsage, hunger); + } + + //TODO: toxins from bloodstream !? + _solutionContainerSystem.TryAddReagent(udder.Solution.Value, udder.ReagentId, udder.QuantityPerUpdate, out _); + } + } + + private void AttemptMilk(Entity udder, EntityUid userUid, EntityUid containerUid) + { + if (!Resolve(udder, ref udder.Comp)) + return; + + var doargs = new DoAfterArgs(EntityManager, userUid, 5, new MilkingDoAfterEvent(), udder, udder, used: containerUid) + { + BreakOnMove = true, + BreakOnDamage = true, + MovementThreshold = 1.0f, + }; + + _doAfterSystem.TryStartDoAfter(doargs); + } + + private void OnDoAfter(Entity entity, ref MilkingDoAfterEvent args) + { + if (args.Cancelled || args.Handled || args.Args.Used == null) + return; + + if (!_solutionContainerSystem.ResolveSolution(entity.Owner, entity.Comp.SolutionName, ref entity.Comp.Solution, out var solution)) + return; + + if (!_solutionContainerSystem.TryGetRefillableSolution(args.Args.Used.Value, out var targetSoln, out var targetSolution)) + return; + + args.Handled = true; + var quantity = solution.Volume; + if (quantity == 0) + { + _popupSystem.PopupEntity(Loc.GetString("udder-system-dry"), entity.Owner, args.Args.User); + return; + } + + if (quantity > targetSolution.AvailableVolume) + quantity = targetSolution.AvailableVolume; + + var split = _solutionContainerSystem.SplitSolution(entity.Comp.Solution.Value, quantity); + _solutionContainerSystem.TryAddSolution(targetSoln.Value, split); + + _popupSystem.PopupEntity(Loc.GetString("udder-system-success", ("amount", quantity), ("target", Identity.Entity(args.Args.Used.Value, EntityManager))), entity.Owner, + args.Args.User, PopupType.Medium); + } + + private void AddMilkVerb(Entity entity, ref GetVerbsEvent args) + { + if (args.Using == null || + !args.CanInteract || + !EntityManager.HasComponent(args.Using.Value)) + return; + + var uid = entity.Owner; + var user = args.User; + var used = args.Using.Value; + AlternativeVerb verb = new() + { + Act = () => + { + AttemptMilk(uid, user, used); + }, + Text = Loc.GetString("udder-system-verb-milk"), + Priority = 2 + }; + args.Verbs.Add(verb); + } + + private void OnExamine(Entity entity, ref ExaminedEvent args) + { + var entityIdentity = ("entity", Identity.Entity(args.Examined, EntityManager)); + + var message = EntityManager.TryGetComponent(entity, out HungerComponent? hunger) switch + { + true => _hunger.GetHungerThreshold(hunger) switch + { + HungerThreshold.Overfed => Loc.GetString("udder-system-examine-overfed", entityIdentity), + <= HungerThreshold.Peckish => Loc.GetString("udder-system-examine-hungry", entityIdentity), + _ => null + }, + false => Loc.GetString("udder-system-examine-none", entityIdentity) + }; + + if (message != null) + { + args.PushMarkup(message); + } + } +} diff --git a/Content.Shared/Animal/SharedWoolyComponent.cs b/Content.Shared/Animal/SharedWoolyComponent.cs new file mode 100644 index 000000000000..018dfa7f90fe --- /dev/null +++ b/Content.Shared/Animal/SharedWoolyComponent.cs @@ -0,0 +1,61 @@ +using Content.Shared.Chemistry.Components; +using Content.Shared.Chemistry.Reagent; +using Content.Shared.FixedPoint; +using Robust.Shared.Prototypes; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom; + +namespace Content.Shared.Animals; + +/// +/// Gives the ability to produce wool fibers; +/// produces endlessly if the owner does not have a HungerComponent. +/// +[RegisterComponent] +[Virtual] +[Access(typeof(SharedWoolyComponent)), AutoGenerateComponentPause] +public partial class SharedWoolyComponent : Component +{ + /// + /// The reagent to grow. + /// + [DataField, ViewVariables(VVAccess.ReadOnly)] + public ProtoId ReagentId = "Fiber"; + + /// + /// The name of . + /// + [DataField, ViewVariables(VVAccess.ReadOnly)] + public string SolutionName = "wool"; + + /// + /// The solution to add reagent to. + /// + [DataField] + public Entity? Solution; + + /// + /// The amount of reagent to be generated on update. + /// + [DataField] + public FixedPoint2 Quantity = 25; + + /// + /// The amount of nutrient consumed on update. + /// + [DataField] + public float HungerUsage = 10f; + + /// + /// How long to wait before growing wool. + /// + [DataField] + public TimeSpan GrowthDelay = TimeSpan.FromMinutes(1); + + /// + /// When to next try growing wool. + /// + //[DataField(customTypeSerializer: typeof(TimeOffsetSerializer)), Access(typeof(SharedWoolySystem))] + //public TimeSpan NextGrowth = TimeSpan.FromSeconds(0); + [AutoPausedField, Access(typeof(SharedWoolySystem))] + public TimeSpan NextGrowth = TimeSpan.Zero; +} diff --git a/Content.Shared/Animal/SharedWoolySystem.cs.cs b/Content.Shared/Animal/SharedWoolySystem.cs.cs new file mode 100644 index 000000000000..091f51cb4f40 --- /dev/null +++ b/Content.Shared/Animal/SharedWoolySystem.cs.cs @@ -0,0 +1,72 @@ +using Content.Shared.Chemistry.EntitySystems; +using Content.Shared.Mobs.Systems; +using Content.Shared.Nutrition; +using Content.Shared.Nutrition.Components; +using Content.Shared.Nutrition.EntitySystems; +using Robust.Shared.Timing; + +namespace Content.Shared.Animals; + +/// +/// Gives ability to produce fiber reagents; +/// produces endlessly if the owner has no HungerComponent. +/// +[Access(typeof(SharedWoolySystem))] +public abstract class SharedWoolySystem : EntitySystem +{ + [Dependency] private readonly HungerSystem _hunger = default!; + [Dependency] private readonly IGameTiming _timing = default!; + [Dependency] private readonly MobStateSystem _mobState = default!; + [Dependency] private readonly SharedSolutionContainerSystem _solutionContainer = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnBeforeFullyEaten); + Logger.Info("Subscribed to SharedBeforeFullyEatenEvent for SharedWoolyComponent"); + } + + public override void Update(float frameTime) + { + base.Update(frameTime); + + var query = EntityQueryEnumerator(); + var now = _timing.CurTime; + while (query.MoveNext(out var uid, out var wooly)) + { + if (now < wooly.NextGrowth) + continue; + + wooly.NextGrowth = now + wooly.GrowthDelay; + + if (_mobState.IsDead(uid)) + continue; + + if (!_solutionContainer.ResolveSolution(uid, wooly.SolutionName, ref wooly.Solution, out var solution)) + continue; + + if (solution.AvailableVolume == 0) + continue; + + // Actually there is food digestion so no problem with instant reagent generation "OnFeed" + if (EntityManager.TryGetComponent(uid, out HungerComponent? hunger)) + { + // Is there enough nutrition to produce reagent? + if (_hunger.GetHungerThreshold(hunger) < HungerThreshold.Okay) + continue; + + _hunger.ModifyHunger(uid, -wooly.HungerUsage, hunger); + } + + _solutionContainer.TryAddReagent(wooly.Solution.Value, wooly.ReagentId, wooly.Quantity, out _); + } + } + + private void OnBeforeFullyEaten(Entity ent, ref SharedBeforeFullyEatenEvent args) + { + // don't want moths to delete goats after eating them + Logger.Info($"OnBeforeFullyEaten called for entity {ent}"); + args.Cancel(); + } +} diff --git a/Content.Shared/Nutrition/SharedIngestionEvents.cs b/Content.Shared/Nutrition/SharedIngestionEvents.cs new file mode 100644 index 000000000000..b4568f297c97 --- /dev/null +++ b/Content.Shared/Nutrition/SharedIngestionEvents.cs @@ -0,0 +1,36 @@ +namespace Content.Shared.Nutrition; + +/// +/// Raised directed at the consumer when attempting to ingest something. +/// +public abstract class SharedIngestionAttemptEvent : CancellableEntityEventArgs +{ + /// + /// The equipment that is blocking consumption. Should only be non-null if the event was canceled. + /// + public EntityUid? Blocker = null; +} + +/// +/// Raised directed at the food after finishing eating a food before it's deleted. +/// Cancel this if you want to do something special before a food is deleted. +/// +public abstract class SharedBeforeFullyEatenEvent : CancellableEntityEventArgs +{ + /// + /// The person that ate the food. + /// + public EntityUid User; +} + +/// +/// Raised directed at the food being sliced before it's deleted. +/// Cancel this if you want to do something special before a food is deleted. +/// +public abstract class SharedBeforeFullySlicedEvent : CancellableEntityEventArgs +{ + /// + /// The person slicing the food. + /// + public EntityUid User; +} diff --git a/Resources/Locale/en-US/animals/udder/udder-system.ftl b/Resources/Locale/en-US/animals/udder/udder-system.ftl index 5c3db2d7ec8a..c4b9f4f4c60b 100644 --- a/Resources/Locale/en-US/animals/udder/udder-system.ftl +++ b/Resources/Locale/en-US/animals/udder/udder-system.ftl @@ -6,6 +6,6 @@ udder-system-dry = The udder is dry. udder-system-verb-milk = Milk -udder-system-examine-overfed = This animal looks overfed -udder-system-examine-hungry = This animal looks hungry -udder-system-examine-none = This animal seems to not get hungry +udder-system-examine-overfed = {CAPITALIZE(SUBJECT($entity))} looks overfed +udder-system-examine-hungry = {CAPITALIZE(SUBJECT($entity))} looks hungry +udder-system-examine-none = {CAPITALIZE(SUBJECT($entity))} seems not to get hungry From a62e795cf519faffb93d086396ebfce2c108fb60 Mon Sep 17 00:00:00 2001 From: Tayrtahn Date: Sat, 22 Jun 2024 16:32:20 -0400 Subject: [PATCH 05/17] Cleanup moving stuff to Shared --- .../Animals/Components/UdderComponent.cs | 8 ----- .../Animals/Components/WoolyComponent.cs | 8 ----- Content.Server/Animals/Systems/UdderSystem.cs | 6 ---- Content.Server/Animals/Systems/WoolySystem.cs | 6 ---- Content.Server/Nutrition/IngestionEvents.cs | 34 ------------------- .../Polymorph/Systems/PolymorphSystem.cs | 2 +- ...redUdderComponent.cs => UdderComponent.cs} | 12 +++---- .../{SharedUdderSystem.cs => UdderSystem.cs} | 19 +++++------ ...redWoolyComponent.cs => WoolyComponent.cs} | 8 ++--- ...redWoolySystem.cs.cs => WoolySystem.cs.cs} | 9 +++-- ...dIngestionEvents.cs => IngestionEvents.cs} | 6 ++-- 11 files changed, 25 insertions(+), 93 deletions(-) delete mode 100644 Content.Server/Animals/Components/UdderComponent.cs delete mode 100644 Content.Server/Animals/Components/WoolyComponent.cs delete mode 100644 Content.Server/Animals/Systems/UdderSystem.cs delete mode 100644 Content.Server/Animals/Systems/WoolySystem.cs delete mode 100644 Content.Server/Nutrition/IngestionEvents.cs rename Content.Shared/Animal/{SharedUdderComponent.cs => UdderComponent.cs} (88%) rename Content.Shared/Animal/{SharedUdderSystem.cs => UdderSystem.cs} (86%) rename Content.Shared/Animal/{SharedWoolyComponent.cs => WoolyComponent.cs} (86%) rename Content.Shared/Animal/{SharedWoolySystem.cs.cs => WoolySystem.cs.cs} (85%) rename Content.Shared/Nutrition/{SharedIngestionEvents.cs => IngestionEvents.cs} (79%) diff --git a/Content.Server/Animals/Components/UdderComponent.cs b/Content.Server/Animals/Components/UdderComponent.cs deleted file mode 100644 index 4c1ea5f15fb1..000000000000 --- a/Content.Server/Animals/Components/UdderComponent.cs +++ /dev/null @@ -1,8 +0,0 @@ -using Content.Shared.Animals; - -namespace Content.Server.Animals.Components; - -[Access(typeof(SharedUdderComponent))] -public sealed partial class UdderComponent : SharedUdderComponent -{ -} diff --git a/Content.Server/Animals/Components/WoolyComponent.cs b/Content.Server/Animals/Components/WoolyComponent.cs deleted file mode 100644 index 5e83a0babb41..000000000000 --- a/Content.Server/Animals/Components/WoolyComponent.cs +++ /dev/null @@ -1,8 +0,0 @@ -using Content.Shared.Animals; - -namespace Content.Server.Animals.Components; - -[Access(typeof(SharedWoolyComponent))] -public sealed partial class WoolyComponent : SharedWoolyComponent -{ -} diff --git a/Content.Server/Animals/Systems/UdderSystem.cs b/Content.Server/Animals/Systems/UdderSystem.cs deleted file mode 100644 index 69c45d128f40..000000000000 --- a/Content.Server/Animals/Systems/UdderSystem.cs +++ /dev/null @@ -1,6 +0,0 @@ -using Content.Shared.Animals; - -namespace Content.Server.Animals.Systems; -public sealed class UdderSystem : SharedUdderSystem -{ -} diff --git a/Content.Server/Animals/Systems/WoolySystem.cs b/Content.Server/Animals/Systems/WoolySystem.cs deleted file mode 100644 index 5b5760ad8e30..000000000000 --- a/Content.Server/Animals/Systems/WoolySystem.cs +++ /dev/null @@ -1,6 +0,0 @@ -using Content.Shared.Animals; - -namespace Content.Server.Animals.Systems; -public sealed class WoolySystem : SharedWoolySystem -{ -} diff --git a/Content.Server/Nutrition/IngestionEvents.cs b/Content.Server/Nutrition/IngestionEvents.cs deleted file mode 100644 index e1cd15b49f5b..000000000000 --- a/Content.Server/Nutrition/IngestionEvents.cs +++ /dev/null @@ -1,34 +0,0 @@ -using Content.Shared.Nutrition; - -namespace Content.Server.Nutrition; - -/// -/// Raised directed at the consumer when attempting to ingest something. -/// -public sealed class IngestionAttemptEvent : SharedIngestionAttemptEvent -{ - /// - /// The equipment that is blocking consumption. Should only be non-null if the event was canceled. - /// -} -/// -/// Raised directed at the food after finishing eating a food before it's deleted. -/// Cancel this if you want to do something special before a food is deleted. -/// -public sealed class BeforeFullyEatenEvent : SharedBeforeFullyEatenEvent -{ - /// - /// The person that ate the food. - /// -} - -/// -/// Raised directed at the food being sliced before it's deleted. -/// Cancel this if you want to do something special before a food is deleted. -/// -public sealed class BeforeFullySlicedEvent : SharedBeforeFullySlicedEvent -{ - /// - /// The person slicing the food. - /// -} diff --git a/Content.Server/Polymorph/Systems/PolymorphSystem.cs b/Content.Server/Polymorph/Systems/PolymorphSystem.cs index d4a9159d44ff..a5b80b9a10a5 100644 --- a/Content.Server/Polymorph/Systems/PolymorphSystem.cs +++ b/Content.Server/Polymorph/Systems/PolymorphSystem.cs @@ -2,7 +2,6 @@ using Content.Server.Humanoid; using Content.Server.Inventory; using Content.Server.Mind.Commands; -using Content.Server.Nutrition; using Content.Server.Polymorph.Components; using Content.Shared.Actions; using Content.Shared.Buckle; @@ -13,6 +12,7 @@ using Content.Shared.Mind; using Content.Shared.Mobs.Components; using Content.Shared.Mobs.Systems; +using Content.Shared.Nutrition; using Content.Shared.Polymorph; using Content.Shared.Popups; using Robust.Server.Audio; diff --git a/Content.Shared/Animal/SharedUdderComponent.cs b/Content.Shared/Animal/UdderComponent.cs similarity index 88% rename from Content.Shared/Animal/SharedUdderComponent.cs rename to Content.Shared/Animal/UdderComponent.cs index 5f0dd5be02e3..d7c5b22bc234 100644 --- a/Content.Shared/Animal/SharedUdderComponent.cs +++ b/Content.Shared/Animal/UdderComponent.cs @@ -10,26 +10,24 @@ namespace Content.Shared.Animals; /// produces endlessly if the owner does not have a HungerComponent. /// [RegisterComponent] -[Virtual] -[Access(typeof(SharedUdderComponent)), AutoGenerateComponentPause] -public partial class SharedUdderComponent : Component +[AutoGenerateComponentPause] +public sealed partial class UdderComponent : Component { /// /// The reagent to produce. /// - [DataField] + [DataField, ViewVariables(VVAccess.ReadOnly)] public ProtoId ReagentId = default!; /// /// The name of . /// - [DataField, ViewVariables(VVAccess.ReadOnly)] + [DataField] public string SolutionName = "udder"; /// /// The solution to add reagent to. /// - [DataField] public Entity? Solution = null; /// @@ -55,6 +53,6 @@ public partial class SharedUdderComponent : Component /// //[DataField(customTypeSerializer: typeof(TimeOffsetSerializer)), Access(typeof(SharedUdderSystem))] //public TimeSpan NextGrowth = TimeSpan.FromSeconds(0); - [AutoPausedField, Access(typeof(SharedUdderSystem))] + [AutoPausedField, Access(typeof(UdderSystem))] public TimeSpan NextGrowth = TimeSpan.Zero; } diff --git a/Content.Shared/Animal/SharedUdderSystem.cs b/Content.Shared/Animal/UdderSystem.cs similarity index 86% rename from Content.Shared/Animal/SharedUdderSystem.cs rename to Content.Shared/Animal/UdderSystem.cs index ca828428909b..899b80831fbf 100644 --- a/Content.Shared/Animal/SharedUdderSystem.cs +++ b/Content.Shared/Animal/UdderSystem.cs @@ -17,8 +17,7 @@ namespace Content.Shared.Animals; /// Gives the ability to produce milkable reagents; /// produces endlessly if the owner does not have a HungerComponent. /// -[Access(typeof(SharedUdderSystem))] -public abstract class SharedUdderSystem : EntitySystem +public abstract class UdderSystem : EntitySystem { [Dependency] private readonly HungerSystem _hunger = default!; [Dependency] private readonly IGameTiming _timing = default!; @@ -31,16 +30,16 @@ public override void Initialize() { base.Initialize(); - SubscribeLocalEvent>(AddMilkVerb); - SubscribeLocalEvent(OnDoAfter); - SubscribeLocalEvent(OnExamine); + SubscribeLocalEvent>(AddMilkVerb); + SubscribeLocalEvent(OnDoAfter); + SubscribeLocalEvent(OnExamine); } public override void Update(float frameTime) { base.Update(frameTime); - var query = EntityQueryEnumerator(); + var query = EntityQueryEnumerator(); var now = _timing.CurTime; while (query.MoveNext(out var uid, out var udder)) { @@ -73,7 +72,7 @@ public override void Update(float frameTime) } } - private void AttemptMilk(Entity udder, EntityUid userUid, EntityUid containerUid) + private void AttemptMilk(Entity udder, EntityUid userUid, EntityUid containerUid) { if (!Resolve(udder, ref udder.Comp)) return; @@ -88,7 +87,7 @@ private void AttemptMilk(Entity udder, EntityUid userUid, _doAfterSystem.TryStartDoAfter(doargs); } - private void OnDoAfter(Entity entity, ref MilkingDoAfterEvent args) + private void OnDoAfter(Entity entity, ref MilkingDoAfterEvent args) { if (args.Cancelled || args.Handled || args.Args.Used == null) return; @@ -117,7 +116,7 @@ private void OnDoAfter(Entity entity, ref MilkingDoAfterEv args.Args.User, PopupType.Medium); } - private void AddMilkVerb(Entity entity, ref GetVerbsEvent args) + private void AddMilkVerb(Entity entity, ref GetVerbsEvent args) { if (args.Using == null || !args.CanInteract || @@ -139,7 +138,7 @@ private void AddMilkVerb(Entity entity, ref GetVerbsEvent< args.Verbs.Add(verb); } - private void OnExamine(Entity entity, ref ExaminedEvent args) + private void OnExamine(Entity entity, ref ExaminedEvent args) { var entityIdentity = ("entity", Identity.Entity(args.Examined, EntityManager)); diff --git a/Content.Shared/Animal/SharedWoolyComponent.cs b/Content.Shared/Animal/WoolyComponent.cs similarity index 86% rename from Content.Shared/Animal/SharedWoolyComponent.cs rename to Content.Shared/Animal/WoolyComponent.cs index 018dfa7f90fe..2a89b15c8736 100644 --- a/Content.Shared/Animal/SharedWoolyComponent.cs +++ b/Content.Shared/Animal/WoolyComponent.cs @@ -2,7 +2,6 @@ using Content.Shared.Chemistry.Reagent; using Content.Shared.FixedPoint; using Robust.Shared.Prototypes; -using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom; namespace Content.Shared.Animals; @@ -11,9 +10,8 @@ namespace Content.Shared.Animals; /// produces endlessly if the owner does not have a HungerComponent. /// [RegisterComponent] -[Virtual] -[Access(typeof(SharedWoolyComponent)), AutoGenerateComponentPause] -public partial class SharedWoolyComponent : Component +[AutoGenerateComponentPause] +public sealed partial class WoolyComponent : Component { /// /// The reagent to grow. @@ -56,6 +54,6 @@ public partial class SharedWoolyComponent : Component /// //[DataField(customTypeSerializer: typeof(TimeOffsetSerializer)), Access(typeof(SharedWoolySystem))] //public TimeSpan NextGrowth = TimeSpan.FromSeconds(0); - [AutoPausedField, Access(typeof(SharedWoolySystem))] + [AutoPausedField, Access(typeof(WoolySystem))] public TimeSpan NextGrowth = TimeSpan.Zero; } diff --git a/Content.Shared/Animal/SharedWoolySystem.cs.cs b/Content.Shared/Animal/WoolySystem.cs.cs similarity index 85% rename from Content.Shared/Animal/SharedWoolySystem.cs.cs rename to Content.Shared/Animal/WoolySystem.cs.cs index 091f51cb4f40..4521115a9ed4 100644 --- a/Content.Shared/Animal/SharedWoolySystem.cs.cs +++ b/Content.Shared/Animal/WoolySystem.cs.cs @@ -11,8 +11,7 @@ namespace Content.Shared.Animals; /// Gives ability to produce fiber reagents; /// produces endlessly if the owner has no HungerComponent. /// -[Access(typeof(SharedWoolySystem))] -public abstract class SharedWoolySystem : EntitySystem +public sealed class WoolySystem : EntitySystem { [Dependency] private readonly HungerSystem _hunger = default!; [Dependency] private readonly IGameTiming _timing = default!; @@ -23,7 +22,7 @@ public override void Initialize() { base.Initialize(); - SubscribeLocalEvent(OnBeforeFullyEaten); + SubscribeLocalEvent(OnBeforeFullyEaten); Logger.Info("Subscribed to SharedBeforeFullyEatenEvent for SharedWoolyComponent"); } @@ -31,7 +30,7 @@ public override void Update(float frameTime) { base.Update(frameTime); - var query = EntityQueryEnumerator(); + var query = EntityQueryEnumerator(); var now = _timing.CurTime; while (query.MoveNext(out var uid, out var wooly)) { @@ -63,7 +62,7 @@ public override void Update(float frameTime) } } - private void OnBeforeFullyEaten(Entity ent, ref SharedBeforeFullyEatenEvent args) + private void OnBeforeFullyEaten(Entity ent, ref BeforeFullyEatenEvent args) { // don't want moths to delete goats after eating them Logger.Info($"OnBeforeFullyEaten called for entity {ent}"); diff --git a/Content.Shared/Nutrition/SharedIngestionEvents.cs b/Content.Shared/Nutrition/IngestionEvents.cs similarity index 79% rename from Content.Shared/Nutrition/SharedIngestionEvents.cs rename to Content.Shared/Nutrition/IngestionEvents.cs index b4568f297c97..488605522ac7 100644 --- a/Content.Shared/Nutrition/SharedIngestionEvents.cs +++ b/Content.Shared/Nutrition/IngestionEvents.cs @@ -3,7 +3,7 @@ namespace Content.Shared.Nutrition; /// /// Raised directed at the consumer when attempting to ingest something. /// -public abstract class SharedIngestionAttemptEvent : CancellableEntityEventArgs +public sealed class IngestionAttemptEvent : CancellableEntityEventArgs { /// /// The equipment that is blocking consumption. Should only be non-null if the event was canceled. @@ -15,7 +15,7 @@ public abstract class SharedIngestionAttemptEvent : CancellableEntityEventArgs /// Raised directed at the food after finishing eating a food before it's deleted. /// Cancel this if you want to do something special before a food is deleted. /// -public abstract class SharedBeforeFullyEatenEvent : CancellableEntityEventArgs +public sealed class BeforeFullyEatenEvent : CancellableEntityEventArgs { /// /// The person that ate the food. @@ -27,7 +27,7 @@ public abstract class SharedBeforeFullyEatenEvent : CancellableEntityEventArgs /// Raised directed at the food being sliced before it's deleted. /// Cancel this if you want to do something special before a food is deleted. /// -public abstract class SharedBeforeFullySlicedEvent : CancellableEntityEventArgs +public sealed class BeforeFullySlicedEvent : CancellableEntityEventArgs { /// /// The person slicing the food. From 52e55f67043cba6e8764c75c10cdd5905c0de1ac Mon Sep 17 00:00:00 2001 From: Tayrtahn Date: Sat, 22 Jun 2024 16:56:43 -0400 Subject: [PATCH 06/17] Oops. Make UdderSystem sealed instead of abstract. --- Content.Shared/Animal/UdderSystem.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Content.Shared/Animal/UdderSystem.cs b/Content.Shared/Animal/UdderSystem.cs index 899b80831fbf..89819f21b930 100644 --- a/Content.Shared/Animal/UdderSystem.cs +++ b/Content.Shared/Animal/UdderSystem.cs @@ -17,7 +17,7 @@ namespace Content.Shared.Animals; /// Gives the ability to produce milkable reagents; /// produces endlessly if the owner does not have a HungerComponent. /// -public abstract class UdderSystem : EntitySystem +public sealed class UdderSystem : EntitySystem { [Dependency] private readonly HungerSystem _hunger = default!; [Dependency] private readonly IGameTiming _timing = default!; From 9162ac8e2ffa4c4def818ef9cbfe99b818736231 Mon Sep 17 00:00:00 2001 From: Tayrtahn Date: Sat, 22 Jun 2024 17:00:18 -0400 Subject: [PATCH 07/17] Switch PopupEntity for PopupClient --- Content.Shared/Animal/UdderSystem.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Content.Shared/Animal/UdderSystem.cs b/Content.Shared/Animal/UdderSystem.cs index 89819f21b930..333353688a55 100644 --- a/Content.Shared/Animal/UdderSystem.cs +++ b/Content.Shared/Animal/UdderSystem.cs @@ -102,7 +102,7 @@ private void OnDoAfter(Entity entity, ref MilkingDoAfterEvent ar var quantity = solution.Volume; if (quantity == 0) { - _popupSystem.PopupEntity(Loc.GetString("udder-system-dry"), entity.Owner, args.Args.User); + _popupSystem.PopupClient(Loc.GetString("udder-system-dry"), entity.Owner, args.Args.User); return; } @@ -112,7 +112,7 @@ private void OnDoAfter(Entity entity, ref MilkingDoAfterEvent ar var split = _solutionContainerSystem.SplitSolution(entity.Comp.Solution.Value, quantity); _solutionContainerSystem.TryAddSolution(targetSoln.Value, split); - _popupSystem.PopupEntity(Loc.GetString("udder-system-success", ("amount", quantity), ("target", Identity.Entity(args.Args.Used.Value, EntityManager))), entity.Owner, + _popupSystem.PopupClient(Loc.GetString("udder-system-success", ("amount", quantity), ("target", Identity.Entity(args.Args.Used.Value, EntityManager))), entity.Owner, args.Args.User, PopupType.Medium); } From 5ee777cfe97c8bc1b8f6b51332ae4bb80f4f75e2 Mon Sep 17 00:00:00 2001 From: Tayrtahn Date: Sat, 22 Jun 2024 17:39:43 -0400 Subject: [PATCH 08/17] Didn't mean to delete Access --- Content.Shared/Animal/WoolyComponent.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Content.Shared/Animal/WoolyComponent.cs b/Content.Shared/Animal/WoolyComponent.cs index 2a89b15c8736..c395b7d9ccc3 100644 --- a/Content.Shared/Animal/WoolyComponent.cs +++ b/Content.Shared/Animal/WoolyComponent.cs @@ -9,7 +9,7 @@ namespace Content.Shared.Animals; /// Gives the ability to produce wool fibers; /// produces endlessly if the owner does not have a HungerComponent. /// -[RegisterComponent] +[RegisterComponent, Access(typeof(WoolySystem))] [AutoGenerateComponentPause] public sealed partial class WoolyComponent : Component { From c0619553e3a47acaa4e58c2b926c28a8d1c84aca Mon Sep 17 00:00:00 2001 From: sirionaut Date: Tue, 25 Jun 2024 15:13:18 +0200 Subject: [PATCH 09/17] new() instead of default! prototype revert egglayer balance change NextGrowth += timespan in egglayer --- Content.Server/Animals/Components/EggLayerComponent.cs | 8 ++++---- Content.Server/Animals/Systems/EggLayerSystem.cs | 2 +- Content.Shared/Animal/UdderComponent.cs | 7 ++----- Content.Shared/Animal/WoolyComponent.cs | 5 +---- Content.Shared/Animal/WoolySystem.cs.cs | 2 -- 5 files changed, 8 insertions(+), 16 deletions(-) diff --git a/Content.Server/Animals/Components/EggLayerComponent.cs b/Content.Server/Animals/Components/EggLayerComponent.cs index fbba2667ba2b..ffd8b62833ee 100644 --- a/Content.Server/Animals/Components/EggLayerComponent.cs +++ b/Content.Server/Animals/Components/EggLayerComponent.cs @@ -17,7 +17,7 @@ public sealed partial class EggLayerComponent : Component /// The item that gets laid/spawned, retrieved from animal prototype. /// [DataField(required: true)] - public List EggSpawn = default!; + public List EggSpawn = new(); /// /// Player action. @@ -32,19 +32,19 @@ public sealed partial class EggLayerComponent : Component /// Minimum cooldown used for the automatic egg laying. /// [DataField] - public float EggLayCooldownMin = 45f; + public float EggLayCooldownMin = 60f; /// /// Maximum cooldown used for the automatic egg laying. /// [DataField] - public float EggLayCooldownMax = 90f; + public float EggLayCooldownMax = 120f; /// /// The amount of nutrient consumed on update. /// [DataField] - public float HungerUsage = 25f; + public float HungerUsage = 60f; [DataField] public EntityUid? Action; diff --git a/Content.Server/Animals/Systems/EggLayerSystem.cs b/Content.Server/Animals/Systems/EggLayerSystem.cs index 0f99d6428a68..c86e57d6cf51 100644 --- a/Content.Server/Animals/Systems/EggLayerSystem.cs +++ b/Content.Server/Animals/Systems/EggLayerSystem.cs @@ -51,7 +51,7 @@ public override void Update(float frameTime) continue; // Randomize next growth time for more organic egglaying. - eggLayer.NextGrowth = now + TimeSpan.FromSeconds(_random.NextFloat(eggLayer.EggLayCooldownMin, eggLayer.EggLayCooldownMax)); + eggLayer.NextGrowth += TimeSpan.FromSeconds(_random.NextFloat(eggLayer.EggLayCooldownMin, eggLayer.EggLayCooldownMax)); if (_mobState.IsDead(uid)) continue; diff --git a/Content.Shared/Animal/UdderComponent.cs b/Content.Shared/Animal/UdderComponent.cs index d7c5b22bc234..f6b717c2cc51 100644 --- a/Content.Shared/Animal/UdderComponent.cs +++ b/Content.Shared/Animal/UdderComponent.cs @@ -9,15 +9,14 @@ namespace Content.Shared.Animals; /// Gives the ability to produce a solution; /// produces endlessly if the owner does not have a HungerComponent. /// -[RegisterComponent] -[AutoGenerateComponentPause] +[RegisterComponent, AutoGenerateComponentPause] public sealed partial class UdderComponent : Component { /// /// The reagent to produce. /// [DataField, ViewVariables(VVAccess.ReadOnly)] - public ProtoId ReagentId = default!; + public ProtoId ReagentId = new(); /// /// The name of . @@ -51,8 +50,6 @@ public sealed partial class UdderComponent : Component /// /// When to next try to produce. /// - //[DataField(customTypeSerializer: typeof(TimeOffsetSerializer)), Access(typeof(SharedUdderSystem))] - //public TimeSpan NextGrowth = TimeSpan.FromSeconds(0); [AutoPausedField, Access(typeof(UdderSystem))] public TimeSpan NextGrowth = TimeSpan.Zero; } diff --git a/Content.Shared/Animal/WoolyComponent.cs b/Content.Shared/Animal/WoolyComponent.cs index c395b7d9ccc3..5ffedc90a6cd 100644 --- a/Content.Shared/Animal/WoolyComponent.cs +++ b/Content.Shared/Animal/WoolyComponent.cs @@ -9,8 +9,7 @@ namespace Content.Shared.Animals; /// Gives the ability to produce wool fibers; /// produces endlessly if the owner does not have a HungerComponent. /// -[RegisterComponent, Access(typeof(WoolySystem))] -[AutoGenerateComponentPause] +[RegisterComponent, Access(typeof(WoolySystem)), AutoGenerateComponentPause] public sealed partial class WoolyComponent : Component { /// @@ -52,8 +51,6 @@ public sealed partial class WoolyComponent : Component /// /// When to next try growing wool. /// - //[DataField(customTypeSerializer: typeof(TimeOffsetSerializer)), Access(typeof(SharedWoolySystem))] - //public TimeSpan NextGrowth = TimeSpan.FromSeconds(0); [AutoPausedField, Access(typeof(WoolySystem))] public TimeSpan NextGrowth = TimeSpan.Zero; } diff --git a/Content.Shared/Animal/WoolySystem.cs.cs b/Content.Shared/Animal/WoolySystem.cs.cs index 4521115a9ed4..4f273f90b1db 100644 --- a/Content.Shared/Animal/WoolySystem.cs.cs +++ b/Content.Shared/Animal/WoolySystem.cs.cs @@ -23,7 +23,6 @@ public override void Initialize() base.Initialize(); SubscribeLocalEvent(OnBeforeFullyEaten); - Logger.Info("Subscribed to SharedBeforeFullyEatenEvent for SharedWoolyComponent"); } public override void Update(float frameTime) @@ -65,7 +64,6 @@ public override void Update(float frameTime) private void OnBeforeFullyEaten(Entity ent, ref BeforeFullyEatenEvent args) { // don't want moths to delete goats after eating them - Logger.Info($"OnBeforeFullyEaten called for entity {ent}"); args.Cancel(); } } From 0f5aaf2a07ad5edf88b6d3be32a63e9b1f44e798 Mon Sep 17 00:00:00 2001 From: sirionaut Date: Tue, 25 Jun 2024 15:33:46 +0200 Subject: [PATCH 10/17] forgot [Datafield] for NextGrowth --- Content.Server/Animals/Components/EggLayerComponent.cs | 2 +- Content.Shared/Animal/UdderComponent.cs | 2 +- Content.Shared/Animal/WoolyComponent.cs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Content.Server/Animals/Components/EggLayerComponent.cs b/Content.Server/Animals/Components/EggLayerComponent.cs index ffd8b62833ee..899bc97f47bb 100644 --- a/Content.Server/Animals/Components/EggLayerComponent.cs +++ b/Content.Server/Animals/Components/EggLayerComponent.cs @@ -51,6 +51,6 @@ public sealed partial class EggLayerComponent : Component /// /// When to next try to produce. /// - [AutoPausedField] + [DataField, AutoPausedField] public TimeSpan NextGrowth = TimeSpan.Zero; } diff --git a/Content.Shared/Animal/UdderComponent.cs b/Content.Shared/Animal/UdderComponent.cs index f6b717c2cc51..371c380f22b8 100644 --- a/Content.Shared/Animal/UdderComponent.cs +++ b/Content.Shared/Animal/UdderComponent.cs @@ -50,6 +50,6 @@ public sealed partial class UdderComponent : Component /// /// When to next try to produce. /// - [AutoPausedField, Access(typeof(UdderSystem))] + [DataField, AutoPausedField, Access(typeof(UdderSystem))] public TimeSpan NextGrowth = TimeSpan.Zero; } diff --git a/Content.Shared/Animal/WoolyComponent.cs b/Content.Shared/Animal/WoolyComponent.cs index 5ffedc90a6cd..1cdfed96572c 100644 --- a/Content.Shared/Animal/WoolyComponent.cs +++ b/Content.Shared/Animal/WoolyComponent.cs @@ -51,6 +51,6 @@ public sealed partial class WoolyComponent : Component /// /// When to next try growing wool. /// - [AutoPausedField, Access(typeof(WoolySystem))] + [DataField, AutoPausedField, Access(typeof(WoolySystem))] public TimeSpan NextGrowth = TimeSpan.Zero; } From e10c506336553ae96022f9a020b1bc321395c382 Mon Sep 17 00:00:00 2001 From: sirionaut Date: Thu, 27 Jun 2024 10:38:11 +0200 Subject: [PATCH 11/17] forgot NetworkedComponent again... --- Content.Shared/Animal/UdderComponent.cs | 3 ++- Content.Shared/Animal/WoolyComponent.cs | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Content.Shared/Animal/UdderComponent.cs b/Content.Shared/Animal/UdderComponent.cs index 371c380f22b8..5ae62acd39b1 100644 --- a/Content.Shared/Animal/UdderComponent.cs +++ b/Content.Shared/Animal/UdderComponent.cs @@ -1,6 +1,7 @@ using Content.Shared.Chemistry.Components; using Content.Shared.Chemistry.Reagent; using Content.Shared.FixedPoint; +using Robust.Shared.GameStates; using Robust.Shared.Prototypes; namespace Content.Shared.Animals; @@ -9,7 +10,7 @@ namespace Content.Shared.Animals; /// Gives the ability to produce a solution; /// produces endlessly if the owner does not have a HungerComponent. /// -[RegisterComponent, AutoGenerateComponentPause] +[RegisterComponent, AutoGenerateComponentPause, NetworkedComponent] public sealed partial class UdderComponent : Component { /// diff --git a/Content.Shared/Animal/WoolyComponent.cs b/Content.Shared/Animal/WoolyComponent.cs index 1cdfed96572c..edbf159d465b 100644 --- a/Content.Shared/Animal/WoolyComponent.cs +++ b/Content.Shared/Animal/WoolyComponent.cs @@ -1,6 +1,7 @@ using Content.Shared.Chemistry.Components; using Content.Shared.Chemistry.Reagent; using Content.Shared.FixedPoint; +using Robust.Shared.GameStates; using Robust.Shared.Prototypes; namespace Content.Shared.Animals; @@ -9,7 +10,7 @@ namespace Content.Shared.Animals; /// Gives the ability to produce wool fibers; /// produces endlessly if the owner does not have a HungerComponent. /// -[RegisterComponent, Access(typeof(WoolySystem)), AutoGenerateComponentPause] +[RegisterComponent, Access(typeof(WoolySystem)), AutoGenerateComponentPause, NetworkedComponent] public sealed partial class WoolyComponent : Component { /// From 2dc2708b61b1fda64c64b9c7622bd3a647aa894c Mon Sep 17 00:00:00 2001 From: Baa14453 Date: Sat, 19 Oct 2024 18:28:49 +0100 Subject: [PATCH 12/17] Renaming Shared Animal to Shared Animals to match Server Hopefully also resolve merge conflicts. --- Content.Shared/{Animal => Animals}/UdderComponent.cs | 0 Content.Shared/{Animal => Animals}/UdderSystem.cs | 0 Content.Shared/{Animal => Animals}/WoolyComponent.cs | 0 Content.Shared/{Animal => Animals}/WoolySystem.cs.cs | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename Content.Shared/{Animal => Animals}/UdderComponent.cs (100%) rename Content.Shared/{Animal => Animals}/UdderSystem.cs (100%) rename Content.Shared/{Animal => Animals}/WoolyComponent.cs (100%) rename Content.Shared/{Animal => Animals}/WoolySystem.cs.cs (100%) diff --git a/Content.Shared/Animal/UdderComponent.cs b/Content.Shared/Animals/UdderComponent.cs similarity index 100% rename from Content.Shared/Animal/UdderComponent.cs rename to Content.Shared/Animals/UdderComponent.cs diff --git a/Content.Shared/Animal/UdderSystem.cs b/Content.Shared/Animals/UdderSystem.cs similarity index 100% rename from Content.Shared/Animal/UdderSystem.cs rename to Content.Shared/Animals/UdderSystem.cs diff --git a/Content.Shared/Animal/WoolyComponent.cs b/Content.Shared/Animals/WoolyComponent.cs similarity index 100% rename from Content.Shared/Animal/WoolyComponent.cs rename to Content.Shared/Animals/WoolyComponent.cs diff --git a/Content.Shared/Animal/WoolySystem.cs.cs b/Content.Shared/Animals/WoolySystem.cs.cs similarity index 100% rename from Content.Shared/Animal/WoolySystem.cs.cs rename to Content.Shared/Animals/WoolySystem.cs.cs From bc0248786a2ecb0305d6eb9c3a3b6cb0b5c44691 Mon Sep 17 00:00:00 2001 From: Baa14453 Date: Sun, 20 Oct 2024 00:05:16 +0100 Subject: [PATCH 13/17] Fix incorrect filename --- Content.Shared/Animals/{WoolySystem.cs.cs => WoolySystem.cs} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename Content.Shared/Animals/{WoolySystem.cs.cs => WoolySystem.cs} (100%) diff --git a/Content.Shared/Animals/WoolySystem.cs.cs b/Content.Shared/Animals/WoolySystem.cs similarity index 100% rename from Content.Shared/Animals/WoolySystem.cs.cs rename to Content.Shared/Animals/WoolySystem.cs From 105b319dee53031eaaca9f52feb6faaf08020e46 Mon Sep 17 00:00:00 2001 From: Baa14453 Date: Tue, 12 Nov 2024 21:46:41 +0000 Subject: [PATCH 14/17] Update with requested changes Put UdderSystem dependencies in alphabetical order. Initialise NextGrowth for Udder and Wooly components on MapInitEvent. Clean-up EggLayerSystem a little. Re-write OnExamine function for UdderSystem, improving clarity. Add full stops to end of udder examine locales. And more :) --- .../Animals/Systems/EggLayerSystem.cs | 4 +- Content.Shared/Animals/UdderComponent.cs | 9 +-- Content.Shared/Animals/UdderSystem.cs | 56 +++++++++++++------ Content.Shared/Animals/WoolyComponent.cs | 10 ++-- Content.Shared/Animals/WoolySystem.cs | 11 +++- .../en-US/animals/udder/udder-system.ftl | 6 +- 6 files changed, 60 insertions(+), 36 deletions(-) diff --git a/Content.Server/Animals/Systems/EggLayerSystem.cs b/Content.Server/Animals/Systems/EggLayerSystem.cs index c86e57d6cf51..3e552f1b387f 100644 --- a/Content.Server/Animals/Systems/EggLayerSystem.cs +++ b/Content.Server/Animals/Systems/EggLayerSystem.cs @@ -38,16 +38,14 @@ public override void Initialize() public override void Update(float frameTime) { base.Update(frameTime); - var query = EntityQueryEnumerator(); - var now = _timing.CurTime; while (query.MoveNext(out var uid, out var eggLayer)) { // Players should be using the action. if (HasComp(uid)) continue; - if (now < eggLayer.NextGrowth) + if (_timing.CurTime < eggLayer.NextGrowth) continue; // Randomize next growth time for more organic egglaying. diff --git a/Content.Shared/Animals/UdderComponent.cs b/Content.Shared/Animals/UdderComponent.cs index 5ae62acd39b1..a0589c9bc858 100644 --- a/Content.Shared/Animals/UdderComponent.cs +++ b/Content.Shared/Animals/UdderComponent.cs @@ -10,13 +10,13 @@ namespace Content.Shared.Animals; /// Gives the ability to produce a solution; /// produces endlessly if the owner does not have a HungerComponent. /// -[RegisterComponent, AutoGenerateComponentPause, NetworkedComponent] +[RegisterComponent, AutoGenerateComponentState, AutoGenerateComponentPause, NetworkedComponent] public sealed partial class UdderComponent : Component { /// /// The reagent to produce. /// - [DataField, ViewVariables(VVAccess.ReadOnly)] + [DataField, AutoNetworkedField] public ProtoId ReagentId = new(); /// @@ -28,6 +28,7 @@ public sealed partial class UdderComponent : Component /// /// The solution to add reagent to. /// + [DataField, ViewVariables(VVAccess.ReadOnly)] public Entity? Solution = null; /// @@ -39,13 +40,13 @@ public sealed partial class UdderComponent : Component /// /// The amount of nutrient consumed on update. /// - [DataField] + [DataField, AutoNetworkedField] public float HungerUsage = 10f; /// /// How long to wait before producing. /// - [DataField] + [DataField, AutoNetworkedField] public TimeSpan GrowthDelay = TimeSpan.FromMinutes(1); /// diff --git a/Content.Shared/Animals/UdderSystem.cs b/Content.Shared/Animals/UdderSystem.cs index 333353688a55..90aa368a3d3c 100644 --- a/Content.Shared/Animals/UdderSystem.cs +++ b/Content.Shared/Animals/UdderSystem.cs @@ -1,4 +1,3 @@ -using Content.Shared.Popups; using Content.Shared.Chemistry.Components; using Content.Shared.Chemistry.EntitySystems; using Content.Shared.DoAfter; @@ -7,7 +6,7 @@ using Content.Shared.Mobs.Systems; using Content.Shared.Nutrition.Components; using Content.Shared.Nutrition.EntitySystems; - +using Content.Shared.Popups; using Content.Shared.Udder; using Content.Shared.Verbs; using Robust.Shared.Timing; @@ -30,23 +29,27 @@ public override void Initialize() { base.Initialize(); + SubscribeLocalEvent(OnMapInit); SubscribeLocalEvent>(AddMilkVerb); SubscribeLocalEvent(OnDoAfter); SubscribeLocalEvent(OnExamine); } + private void OnMapInit(EntityUid uid, UdderComponent component, MapInitEvent args) + { + component.NextGrowth = _timing.CurTime + component.GrowthDelay; + } + public override void Update(float frameTime) { base.Update(frameTime); - var query = EntityQueryEnumerator(); - var now = _timing.CurTime; while (query.MoveNext(out var uid, out var udder)) { - if (now < udder.NextGrowth) + if (_timing.CurTime < udder.NextGrowth) continue; - udder.NextGrowth = now + udder.GrowthDelay; + udder.NextGrowth += udder.GrowthDelay; if (_mobState.IsDead(uid)) continue; @@ -138,24 +141,41 @@ private void AddMilkVerb(Entity entity, ref GetVerbsEvent + /// Defines the text provided on examine. + /// Changes depending on the amount of hunger the target has. + /// private void OnExamine(Entity entity, ref ExaminedEvent args) { - var entityIdentity = ("entity", Identity.Entity(args.Examined, EntityManager)); - var message = EntityManager.TryGetComponent(entity, out HungerComponent? hunger) switch - { - true => _hunger.GetHungerThreshold(hunger) switch - { - HungerThreshold.Overfed => Loc.GetString("udder-system-examine-overfed", entityIdentity), - <= HungerThreshold.Peckish => Loc.GetString("udder-system-examine-hungry", entityIdentity), - _ => null - }, - false => Loc.GetString("udder-system-examine-none", entityIdentity) - }; + var entityIdentity = Identity.Entity(args.Examined, EntityManager); + + string message; - if (message != null) + // Check if the target has hunger, otherwise return not hungry. + if (!TryComp(entity, out var hunger)) { + message = Loc.GetString("udder-system-examine-none", ("entity", entityIdentity)); args.PushMarkup(message); + return; } + + // Choose the correct examine string based on HungerThreshold. + switch (_hunger.GetHungerThreshold(hunger)) + { + case HungerThreshold.Overfed: + message = Loc.GetString("udder-system-examine-overfed", ("entity", entityIdentity)); + break; + + case <= HungerThreshold.Peckish: + message = Loc.GetString("udder-system-examine-hungry", ("entity", entityIdentity)); + break; + + default: + message = Loc.GetString("udder-system-examine-none", ("entity", entityIdentity)); + break; + } + + args.PushMarkup(message); } } diff --git a/Content.Shared/Animals/WoolyComponent.cs b/Content.Shared/Animals/WoolyComponent.cs index edbf159d465b..cd3061258917 100644 --- a/Content.Shared/Animals/WoolyComponent.cs +++ b/Content.Shared/Animals/WoolyComponent.cs @@ -10,13 +10,13 @@ namespace Content.Shared.Animals; /// Gives the ability to produce wool fibers; /// produces endlessly if the owner does not have a HungerComponent. /// -[RegisterComponent, Access(typeof(WoolySystem)), AutoGenerateComponentPause, NetworkedComponent] +[RegisterComponent, AutoGenerateComponentState, AutoGenerateComponentPause, NetworkedComponent] public sealed partial class WoolyComponent : Component { /// /// The reagent to grow. /// - [DataField, ViewVariables(VVAccess.ReadOnly)] + [DataField, AutoNetworkedField] public ProtoId ReagentId = "Fiber"; /// @@ -28,7 +28,7 @@ public sealed partial class WoolyComponent : Component /// /// The solution to add reagent to. /// - [DataField] + [DataField, ViewVariables(VVAccess.ReadOnly)] public Entity? Solution; /// @@ -40,13 +40,13 @@ public sealed partial class WoolyComponent : Component /// /// The amount of nutrient consumed on update. /// - [DataField] + [DataField, AutoNetworkedField] public float HungerUsage = 10f; /// /// How long to wait before growing wool. /// - [DataField] + [DataField, AutoNetworkedField] public TimeSpan GrowthDelay = TimeSpan.FromMinutes(1); /// diff --git a/Content.Shared/Animals/WoolySystem.cs b/Content.Shared/Animals/WoolySystem.cs index 4f273f90b1db..b7e0f52982ca 100644 --- a/Content.Shared/Animals/WoolySystem.cs +++ b/Content.Shared/Animals/WoolySystem.cs @@ -23,6 +23,12 @@ public override void Initialize() base.Initialize(); SubscribeLocalEvent(OnBeforeFullyEaten); + SubscribeLocalEvent(OnMapInit); + } + + private void OnMapInit(EntityUid uid, WoolyComponent component, MapInitEvent args) + { + component.NextGrowth = _timing.CurTime + component.GrowthDelay; } public override void Update(float frameTime) @@ -30,13 +36,12 @@ public override void Update(float frameTime) base.Update(frameTime); var query = EntityQueryEnumerator(); - var now = _timing.CurTime; while (query.MoveNext(out var uid, out var wooly)) { - if (now < wooly.NextGrowth) + if (_timing.CurTime < wooly.NextGrowth) continue; - wooly.NextGrowth = now + wooly.GrowthDelay; + wooly.NextGrowth += wooly.GrowthDelay; if (_mobState.IsDead(uid)) continue; diff --git a/Resources/Locale/en-US/animals/udder/udder-system.ftl b/Resources/Locale/en-US/animals/udder/udder-system.ftl index c4b9f4f4c60b..b3f5b5af26c7 100644 --- a/Resources/Locale/en-US/animals/udder/udder-system.ftl +++ b/Resources/Locale/en-US/animals/udder/udder-system.ftl @@ -6,6 +6,6 @@ udder-system-dry = The udder is dry. udder-system-verb-milk = Milk -udder-system-examine-overfed = {CAPITALIZE(SUBJECT($entity))} looks overfed -udder-system-examine-hungry = {CAPITALIZE(SUBJECT($entity))} looks hungry -udder-system-examine-none = {CAPITALIZE(SUBJECT($entity))} seems not to get hungry +udder-system-examine-overfed = {CAPITALIZE(SUBJECT($entity))} looks overfed. +udder-system-examine-hungry = {CAPITALIZE(SUBJECT($entity))} looks hungry. +udder-system-examine-none = {CAPITALIZE(SUBJECT($entity))} seems not to get hungry. From 75abf083e32d942f8f828e8d7b5ee01f826ef0ba Mon Sep 17 00:00:00 2001 From: Baa14453 Date: Wed, 13 Nov 2024 00:38:11 +0000 Subject: [PATCH 15/17] Add some additional descriptions for cow hunger levels. --- Content.Shared/Animals/UdderSystem.cs | 15 +++++++++++---- .../Locale/en-US/animals/udder/udder-system.ftl | 4 +++- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/Content.Shared/Animals/UdderSystem.cs b/Content.Shared/Animals/UdderSystem.cs index 90aa368a3d3c..a900fb766eb2 100644 --- a/Content.Shared/Animals/UdderSystem.cs +++ b/Content.Shared/Animals/UdderSystem.cs @@ -163,17 +163,24 @@ private void OnExamine(Entity entity, ref ExaminedEvent args) // Choose the correct examine string based on HungerThreshold. switch (_hunger.GetHungerThreshold(hunger)) { - case HungerThreshold.Overfed: + case >= HungerThreshold.Overfed: message = Loc.GetString("udder-system-examine-overfed", ("entity", entityIdentity)); break; - case <= HungerThreshold.Peckish: + case HungerThreshold.Okay: + message = Loc.GetString("udder-system-examine-okay", ("entity", entityIdentity)); + break; + + case HungerThreshold.Peckish: message = Loc.GetString("udder-system-examine-hungry", ("entity", entityIdentity)); break; - default: - message = Loc.GetString("udder-system-examine-none", ("entity", entityIdentity)); + case HungerThreshold.Starving: + message = Loc.GetString("udder-system-examine-starved", ("entity", entityIdentity)); break; + + default: + return; } args.PushMarkup(message); diff --git a/Resources/Locale/en-US/animals/udder/udder-system.ftl b/Resources/Locale/en-US/animals/udder/udder-system.ftl index b3f5b5af26c7..959a4fef5915 100644 --- a/Resources/Locale/en-US/animals/udder/udder-system.ftl +++ b/Resources/Locale/en-US/animals/udder/udder-system.ftl @@ -6,6 +6,8 @@ udder-system-dry = The udder is dry. udder-system-verb-milk = Milk -udder-system-examine-overfed = {CAPITALIZE(SUBJECT($entity))} looks overfed. +udder-system-examine-overfed = {CAPITALIZE(SUBJECT($entity))} looks stuffed! +udder-system-examine-okay = {CAPITALIZE(SUBJECT($entity))} looks content. udder-system-examine-hungry = {CAPITALIZE(SUBJECT($entity))} looks hungry. +udder-system-examine-starved = {CAPITALIZE(SUBJECT($entity))} looks starved! udder-system-examine-none = {CAPITALIZE(SUBJECT($entity))} seems not to get hungry. From e9ee66623274684fad8efdded985447ca3a84ef5 Mon Sep 17 00:00:00 2001 From: Baa14453 Date: Wed, 13 Nov 2024 00:47:18 +0000 Subject: [PATCH 16/17] Add Udder and Wooly quantity to AutoNetworkedField --- Content.Shared/Animals/UdderComponent.cs | 2 +- Content.Shared/Animals/WoolyComponent.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Content.Shared/Animals/UdderComponent.cs b/Content.Shared/Animals/UdderComponent.cs index a0589c9bc858..d2767b089605 100644 --- a/Content.Shared/Animals/UdderComponent.cs +++ b/Content.Shared/Animals/UdderComponent.cs @@ -34,7 +34,7 @@ public sealed partial class UdderComponent : Component /// /// The amount of reagent to be generated on update. /// - [DataField] + [DataField, AutoNetworkedField] public FixedPoint2 QuantityPerUpdate = 25; /// diff --git a/Content.Shared/Animals/WoolyComponent.cs b/Content.Shared/Animals/WoolyComponent.cs index cd3061258917..1dfe523001ed 100644 --- a/Content.Shared/Animals/WoolyComponent.cs +++ b/Content.Shared/Animals/WoolyComponent.cs @@ -34,7 +34,7 @@ public sealed partial class WoolyComponent : Component /// /// The amount of reagent to be generated on update. /// - [DataField] + [DataField, AutoNetworkedField] public FixedPoint2 Quantity = 25; /// From b5699970d64e7df84b508e7f0c547f698ca7a072 Mon Sep 17 00:00:00 2001 From: Baa14453 Date: Wed, 13 Nov 2024 00:51:58 +0000 Subject: [PATCH 17/17] Account for less than starving threshold. --- Content.Shared/Animals/UdderSystem.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Content.Shared/Animals/UdderSystem.cs b/Content.Shared/Animals/UdderSystem.cs index a900fb766eb2..cb6e5b307fe9 100644 --- a/Content.Shared/Animals/UdderSystem.cs +++ b/Content.Shared/Animals/UdderSystem.cs @@ -175,7 +175,8 @@ private void OnExamine(Entity entity, ref ExaminedEvent args) message = Loc.GetString("udder-system-examine-hungry", ("entity", entityIdentity)); break; - case HungerThreshold.Starving: + // There's a final hunger threshold called "dead" but animals don't actually die so we'll re-use this. + case <= HungerThreshold.Starving: message = Loc.GetString("udder-system-examine-starved", ("entity", entityIdentity)); break;