Adds cow milking (#5293)
This commit is contained in:
@@ -310,6 +310,7 @@ namespace Content.Client.Entry
|
|||||||
"NukeCodePaper",
|
"NukeCodePaper",
|
||||||
"GhostRadio",
|
"GhostRadio",
|
||||||
"Armor",
|
"Armor",
|
||||||
|
"Udder",
|
||||||
"PneumaticCannon"
|
"PneumaticCannon"
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
48
Content.Server/Animals/Components/UdderComponent.cs
Normal file
48
Content.Server/Animals/Components/UdderComponent.cs
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
using System;
|
||||||
|
using Content.Server.Animals.Systems;
|
||||||
|
using Content.Shared.FixedPoint;
|
||||||
|
using Robust.Shared.Analyzers;
|
||||||
|
using Robust.Shared.GameObjects;
|
||||||
|
using Robust.Shared.Serialization.Manager.Attributes;
|
||||||
|
using Robust.Shared.ViewVariables;
|
||||||
|
|
||||||
|
namespace Content.Server.Animals.Components
|
||||||
|
{
|
||||||
|
[RegisterComponent, Friend(typeof(UdderSystem))]
|
||||||
|
internal class UdderComponent : Component
|
||||||
|
{
|
||||||
|
public override string Name => "Udder";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The reagent to produce.
|
||||||
|
/// </summary>
|
||||||
|
[ViewVariables(VVAccess.ReadOnly)]
|
||||||
|
[DataField("reagentId")]
|
||||||
|
public string ReagentId = "Milk";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The solution to add reagent to.
|
||||||
|
/// </summary>
|
||||||
|
[ViewVariables(VVAccess.ReadOnly)]
|
||||||
|
[DataField("targetSolution")]
|
||||||
|
public string TargetSolutionName = "udder";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The amount of reagent to be generated on update.
|
||||||
|
/// </summary>
|
||||||
|
[ViewVariables(VVAccess.ReadOnly)]
|
||||||
|
[DataField("quantity")]
|
||||||
|
public FixedPoint2 QuantityPerUpdate = 1;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The time between updates (in seconds).
|
||||||
|
/// </summary>
|
||||||
|
[ViewVariables(VVAccess.ReadOnly)]
|
||||||
|
[DataField("updateRate")]
|
||||||
|
public float UpdateRate = 5;
|
||||||
|
|
||||||
|
public float AccumulatedFrameTime;
|
||||||
|
|
||||||
|
public bool BeingMilked;
|
||||||
|
}
|
||||||
|
}
|
||||||
154
Content.Server/Animals/Systems/UdderSystem.cs
Normal file
154
Content.Server/Animals/Systems/UdderSystem.cs
Normal file
@@ -0,0 +1,154 @@
|
|||||||
|
using System;
|
||||||
|
using Content.Server.Animals.Components;
|
||||||
|
using Robust.Shared.GameObjects;
|
||||||
|
using Robust.Shared.IoC;
|
||||||
|
using Content.Server.Chemistry.EntitySystems;
|
||||||
|
using Content.Server.Nutrition.Components;
|
||||||
|
using Content.Shared.Nutrition.Components;
|
||||||
|
using Content.Server.Chemistry.Components.SolutionManager;
|
||||||
|
using Content.Server.DoAfter;
|
||||||
|
using Robust.Shared.Localization;
|
||||||
|
using Content.Shared.Verbs;
|
||||||
|
using Robust.Shared.Player;
|
||||||
|
using Content.Server.Popups;
|
||||||
|
|
||||||
|
namespace Content.Server.Animals.Systems
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gives ability to living beings with acceptable hunger level to produce milkable reagents.
|
||||||
|
/// </summary>
|
||||||
|
internal class UdderSystem : EntitySystem
|
||||||
|
{
|
||||||
|
[Dependency] private readonly SolutionContainerSystem _solutionContainerSystem = default!;
|
||||||
|
[Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
|
||||||
|
[Dependency] private readonly PopupSystem _popupSystem = default!;
|
||||||
|
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
base.Initialize();
|
||||||
|
|
||||||
|
SubscribeLocalEvent<UdderComponent, GetAlternativeVerbsEvent>(AddMilkVerb);
|
||||||
|
SubscribeLocalEvent<UdderComponent, MilkingFinishedEvent>(OnMilkingFinished);
|
||||||
|
SubscribeLocalEvent<UdderComponent, MilkingFailEvent>(OnMilkingFailed);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Update(float frameTime)
|
||||||
|
{
|
||||||
|
foreach (var udder in EntityManager.EntityQuery<UdderComponent>(false))
|
||||||
|
{
|
||||||
|
udder.AccumulatedFrameTime += frameTime;
|
||||||
|
|
||||||
|
if (udder.AccumulatedFrameTime < udder.UpdateRate)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Actually there is food digestion so no problem with instant reagent generation "OnFeed"
|
||||||
|
if (udder.Owner.TryGetComponent<HungerComponent>(out var hunger))
|
||||||
|
{
|
||||||
|
hunger.HungerThresholds.TryGetValue(HungerThreshold.Peckish, out var targetThreshold);
|
||||||
|
|
||||||
|
// Is there enough nutrition to produce reagent?
|
||||||
|
if (hunger.CurrentHunger < targetThreshold)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_solutionContainerSystem.TryGetSolution(udder.OwnerUid, udder.TargetSolutionName, out var solution))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
//TODO: toxins from bloodstream !?
|
||||||
|
_solutionContainerSystem.TryAddReagent(udder.OwnerUid, solution, udder.ReagentId, udder.QuantityPerUpdate, out var accepted);
|
||||||
|
udder.AccumulatedFrameTime = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AttemptMilk(EntityUid uid, EntityUid userUid, EntityUid containerUid, UdderComponent? udder = null)
|
||||||
|
{
|
||||||
|
if (!Resolve(uid, ref udder))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (udder.BeingMilked)
|
||||||
|
{
|
||||||
|
_popupSystem.PopupEntity(Loc.GetString("udder-system-already-milking"), uid, Filter.Entities(userUid));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
udder.BeingMilked = true;
|
||||||
|
|
||||||
|
var doargs = new DoAfterEventArgs(userUid, 5, default, uid)
|
||||||
|
{
|
||||||
|
BreakOnUserMove = true,
|
||||||
|
BreakOnDamage = true,
|
||||||
|
BreakOnStun = true,
|
||||||
|
BreakOnTargetMove = true,
|
||||||
|
MovementThreshold = 1.0f,
|
||||||
|
TargetFinishedEvent = new MilkingFinishedEvent(userUid, containerUid),
|
||||||
|
TargetCancelledEvent = new MilkingFailEvent()
|
||||||
|
};
|
||||||
|
|
||||||
|
_doAfterSystem.DoAfter(doargs);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnMilkingFinished(EntityUid uid, UdderComponent udder, MilkingFinishedEvent ev)
|
||||||
|
{
|
||||||
|
udder.BeingMilked = false;
|
||||||
|
|
||||||
|
if (!_solutionContainerSystem.TryGetSolution(uid, udder.TargetSolutionName, out var solution))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!_solutionContainerSystem.TryGetRefillableSolution(ev.ContainerUid, out var targetSolution))
|
||||||
|
return;
|
||||||
|
|
||||||
|
var quantity = solution.TotalVolume;
|
||||||
|
if(quantity == 0)
|
||||||
|
{
|
||||||
|
_popupSystem.PopupEntity(Loc.GetString("udder-system-dry"), uid, Filter.Entities(ev.UserUid));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (quantity > targetSolution.AvailableVolume)
|
||||||
|
quantity = targetSolution.AvailableVolume;
|
||||||
|
|
||||||
|
var split = _solutionContainerSystem.SplitSolution(uid, solution, quantity);
|
||||||
|
_solutionContainerSystem.TryAddSolution(ev.ContainerUid, targetSolution, split);
|
||||||
|
|
||||||
|
var container = EntityManager.GetEntity(ev.ContainerUid);
|
||||||
|
_popupSystem.PopupEntity(Loc.GetString("udder-system-success", ("amount", quantity), ("target", container)), uid, Filter.Entities(ev.UserUid));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnMilkingFailed(EntityUid uid, UdderComponent component, MilkingFailEvent ev)
|
||||||
|
{
|
||||||
|
component.BeingMilked = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AddMilkVerb(EntityUid uid, UdderComponent component, GetAlternativeVerbsEvent args)
|
||||||
|
{
|
||||||
|
if (args.Using == null ||
|
||||||
|
!args.CanInteract ||
|
||||||
|
!args.Using.HasComponent<RefillableSolutionComponent>())
|
||||||
|
return;
|
||||||
|
|
||||||
|
Verb verb = new();
|
||||||
|
verb.Act = () =>
|
||||||
|
{
|
||||||
|
AttemptMilk(uid, args.User.Uid, args.Using.Uid, component);
|
||||||
|
};
|
||||||
|
verb.Text = Loc.GetString("udder-system-verb-milk");
|
||||||
|
verb.Priority = 2;
|
||||||
|
args.Verbs.Add(verb);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class MilkingFinishedEvent : EntityEventArgs
|
||||||
|
{
|
||||||
|
public EntityUid UserUid;
|
||||||
|
public EntityUid ContainerUid;
|
||||||
|
|
||||||
|
public MilkingFinishedEvent(EntityUid userUid, EntityUid containerUid)
|
||||||
|
{
|
||||||
|
UserUid = userUid;
|
||||||
|
ContainerUid = containerUid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class MilkingFailEvent : EntityEventArgs
|
||||||
|
{ }
|
||||||
|
}
|
||||||
|
}
|
||||||
7
Resources/Locale/en-US/animals/udder/udder-system.ftl
Normal file
7
Resources/Locale/en-US/animals/udder/udder-system.ftl
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
### Udder system
|
||||||
|
|
||||||
|
udder-system-already-milking = The udder is already being milked.
|
||||||
|
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
|
||||||
@@ -177,6 +177,18 @@
|
|||||||
normal: cow
|
normal: cow
|
||||||
crit: dead
|
crit: dead
|
||||||
dead: dead
|
dead: dead
|
||||||
|
- type: SolutionContainerManager
|
||||||
|
solutions:
|
||||||
|
udder:
|
||||||
|
maxVol: 250
|
||||||
|
reagents:
|
||||||
|
- ReagentId: Milk
|
||||||
|
Quantity: 30
|
||||||
|
- type: Udder
|
||||||
|
reagentId: Milk
|
||||||
|
targetSolution: udder
|
||||||
|
quantity: 25
|
||||||
|
updateRate: 30
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
name: crab
|
name: crab
|
||||||
|
|||||||
Reference in New Issue
Block a user