Add space lube tube (#17387)
72
Content.Server/Lube/LubeSystem.cs
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
using Content.Server.Chemistry.EntitySystems;
|
||||||
|
using Content.Server.Nutrition.Components;
|
||||||
|
using Content.Shared.IdentityManagement;
|
||||||
|
using Content.Shared.Interaction;
|
||||||
|
using Content.Shared.Item;
|
||||||
|
using Content.Shared.Lube;
|
||||||
|
using Content.Shared.Popups;
|
||||||
|
using Robust.Shared.Random;
|
||||||
|
|
||||||
|
namespace Content.Server.Lube;
|
||||||
|
|
||||||
|
public sealed class LubeSystem : EntitySystem
|
||||||
|
{
|
||||||
|
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
||||||
|
[Dependency] private readonly SharedPopupSystem _popup = default!;
|
||||||
|
[Dependency] private readonly SolutionContainerSystem _solutionContainer = default!;
|
||||||
|
[Dependency] private readonly IRobustRandom _random = default!;
|
||||||
|
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
base.Initialize();
|
||||||
|
|
||||||
|
SubscribeLocalEvent<LubeComponent, AfterInteractEvent>(OnInteract);
|
||||||
|
}
|
||||||
|
|
||||||
|
// When glue bottle is used on item it will apply the glued and unremoveable components.
|
||||||
|
private void OnInteract(EntityUid uid, LubeComponent component, AfterInteractEvent args)
|
||||||
|
{
|
||||||
|
if (args.Handled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!args.CanReach || args.Target is not { Valid: true } target)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (TryComp<DrinkComponent>(uid, out var drink) && !drink.Opened)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TryLube(uid, component, target))
|
||||||
|
{
|
||||||
|
args.Handled = true;
|
||||||
|
_audio.PlayPvs(component.Squeeze, uid);
|
||||||
|
_popup.PopupEntity(Loc.GetString("lube-success", ("target", Identity.Entity(target, EntityManager))), args.User, args.User, PopupType.Medium);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_popup.PopupEntity(Loc.GetString("lube-failure", ("target", Identity.Entity(target, EntityManager))), args.User, args.User, PopupType.Medium);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool TryLube(EntityUid uid, LubeComponent component, EntityUid target)
|
||||||
|
{
|
||||||
|
if (HasComp<LubedComponent>(target) || !HasComp<ItemComponent>(target))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (HasComp<ItemComponent>(target) && _solutionContainer.TryGetSolution(uid, component.Solution, out var solution))
|
||||||
|
{
|
||||||
|
var quantity = solution.RemoveReagent(component.Reagent, component.Consumption);
|
||||||
|
if (quantity > 0)
|
||||||
|
{
|
||||||
|
var lubed = EnsureComp<LubedComponent>(target);
|
||||||
|
lubed.SlipsLeft = _random.Next(component.MinSlips * quantity.Int(), component.MaxSlips * quantity.Int());
|
||||||
|
lubed.SlipStrength = component.SlipStrength;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
49
Content.Server/Lube/LubedSystem.cs
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
using Content.Shared.IdentityManagement;
|
||||||
|
using Content.Shared.Lube;
|
||||||
|
using Content.Shared.Popups;
|
||||||
|
using Content.Shared.Throwing;
|
||||||
|
using Robust.Shared.Containers;
|
||||||
|
using Robust.Shared.Random;
|
||||||
|
|
||||||
|
namespace Content.Server.Lube;
|
||||||
|
|
||||||
|
public sealed class LubedSystem : EntitySystem
|
||||||
|
{
|
||||||
|
[Dependency] private readonly MetaDataSystem _metaData = default!;
|
||||||
|
[Dependency] private readonly ThrowingSystem _throwing = default!;
|
||||||
|
[Dependency] private readonly IRobustRandom _random = default!;
|
||||||
|
[Dependency] private readonly SharedTransformSystem _transform = default!;
|
||||||
|
[Dependency] private readonly SharedPopupSystem _popup = default!;
|
||||||
|
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
base.Initialize();
|
||||||
|
|
||||||
|
SubscribeLocalEvent<LubedComponent, ComponentInit>(OnInit);
|
||||||
|
SubscribeLocalEvent<LubedComponent, ContainerGettingInsertedAttemptEvent>(OnHandPickUp);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnInit(EntityUid uid, LubedComponent component, ComponentInit args)
|
||||||
|
{
|
||||||
|
var meta = MetaData(uid);
|
||||||
|
var name = meta.EntityName;
|
||||||
|
component.BeforeLubedEntityName = meta.EntityName;
|
||||||
|
_metaData.SetEntityName(uid, Loc.GetString("lubed-name-prefix", ("target", name)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnHandPickUp(EntityUid uid, LubedComponent component, ContainerGettingInsertedAttemptEvent args)
|
||||||
|
{
|
||||||
|
if (component.SlipsLeft <= 0)
|
||||||
|
{
|
||||||
|
RemComp<LubedComponent>(uid);
|
||||||
|
_metaData.SetEntityName(uid, component.BeforeLubedEntityName);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
component.SlipsLeft--;
|
||||||
|
args.Cancel();
|
||||||
|
var user = args.Container.Owner;
|
||||||
|
_transform.SetCoordinates(uid, Transform(user).Coordinates);
|
||||||
|
_throwing.TryThrow(uid, _random.NextVector2(), strength: component.SlipStrength);
|
||||||
|
_popup.PopupEntity(Loc.GetString("lube-slip", ("target", Identity.Entity(uid, EntityManager))), user, user, PopupType.MediumCaution);
|
||||||
|
}
|
||||||
|
}
|
||||||
47
Content.Shared/Lube/LubeComponent.cs
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
using Content.Shared.Chemistry.Reagent;
|
||||||
|
using Content.Shared.FixedPoint;
|
||||||
|
using Robust.Shared.Audio;
|
||||||
|
using Robust.Shared.GameStates;
|
||||||
|
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||||
|
|
||||||
|
namespace Content.Shared.Lube;
|
||||||
|
|
||||||
|
[RegisterComponent, NetworkedComponent]
|
||||||
|
public sealed class LubeComponent : Component
|
||||||
|
{
|
||||||
|
[DataField("squeeze")]
|
||||||
|
public SoundSpecifier Squeeze = new SoundPathSpecifier("/Audio/Items/squeezebottle.ogg");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Solution on the entity that contains the glue.
|
||||||
|
/// </summary>
|
||||||
|
[DataField("solution")]
|
||||||
|
public string Solution = "drink";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reagent that will be used as glue.
|
||||||
|
/// </summary>
|
||||||
|
[DataField("reagent", customTypeSerializer: typeof(PrototypeIdSerializer<ReagentPrototype>))]
|
||||||
|
public string Reagent = "SpaceLube";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reagent consumption per use.
|
||||||
|
/// </summary>
|
||||||
|
[DataField("consumption"), ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
public FixedPoint2 Consumption = FixedPoint2.New(3);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Min slips per unit
|
||||||
|
/// </summary>
|
||||||
|
[DataField("minSlips"), ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
public int MinSlips = 1;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Max slips per unit
|
||||||
|
/// </summary>
|
||||||
|
[DataField("maxSlips"), ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
public int MaxSlips = 6;
|
||||||
|
|
||||||
|
[DataField("slipStrength"), ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
public int SlipStrength = 10;
|
||||||
|
}
|
||||||
17
Content.Shared/Lube/LubedComponent.cs
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
namespace Content.Shared.Lube;
|
||||||
|
|
||||||
|
[RegisterComponent]
|
||||||
|
public sealed class LubedComponent : Component
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Reverts name to before prefix event (essentially removes prefix).
|
||||||
|
/// </summary>
|
||||||
|
[DataField("beforeLubedEntityName")]
|
||||||
|
public string BeforeLubedEntityName = string.Empty;
|
||||||
|
|
||||||
|
[DataField("slipsLeft"), ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
public int SlipsLeft;
|
||||||
|
|
||||||
|
[DataField("slipStrength"), ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
public int SlipStrength;
|
||||||
|
}
|
||||||
4
Resources/Locale/en-US/lube/lube.ftl
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
lube-success = {THE($target)} has been covered in lube!
|
||||||
|
lubed-name-prefix = Lubed {$target}
|
||||||
|
lube-failure = Can't cover {THE($target)} in lube!
|
||||||
|
lube-slip = {THE($target)} slips out of your hands!
|
||||||
@@ -129,6 +129,8 @@
|
|||||||
prob: 0.20
|
prob: 0.20
|
||||||
- id: DrinkSpaceGlue
|
- id: DrinkSpaceGlue
|
||||||
prob: 0.20
|
prob: 0.20
|
||||||
|
- id: DrinkSpaceLube
|
||||||
|
prob: 0.20
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
id: ClosetWallMaintenanceFilledRandom
|
id: ClosetWallMaintenanceFilledRandom
|
||||||
|
|||||||
@@ -29,3 +29,36 @@
|
|||||||
- type: SolutionContainerVisuals
|
- type: SolutionContainerVisuals
|
||||||
maxFillLevels: 6
|
maxFillLevels: 6
|
||||||
fillBaseName: fill
|
fillBaseName: fill
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
parent: DrinkBase
|
||||||
|
id: DrinkSpaceLube
|
||||||
|
name: space lube tube
|
||||||
|
description: High performance lubricant intended for maintenance of extremely complex mechanical equipment.
|
||||||
|
components:
|
||||||
|
- type: Drink
|
||||||
|
isOpen: false
|
||||||
|
openSounds:
|
||||||
|
collection: packetOpenSounds
|
||||||
|
- type: Sprite
|
||||||
|
sprite: Objects/Consumable/Drinks/lube-tube.rsi
|
||||||
|
layers:
|
||||||
|
- state: icon
|
||||||
|
map: [ "enum.SolutionContainerLayers.Base" ]
|
||||||
|
- state: fill1
|
||||||
|
map: [ "enum.SolutionContainerLayers.Fill" ]
|
||||||
|
visible: false
|
||||||
|
- state: icon-front
|
||||||
|
map: [ "enum.SolutionContainerLayers.Overlay" ]
|
||||||
|
- type: Appearance
|
||||||
|
- type: SolutionContainerManager
|
||||||
|
solutions:
|
||||||
|
drink:
|
||||||
|
maxVol: 30
|
||||||
|
reagents:
|
||||||
|
- ReagentId: SpaceLube
|
||||||
|
Quantity: 30
|
||||||
|
- type: SolutionContainerVisuals
|
||||||
|
maxFillLevels: 6
|
||||||
|
fillBaseName: fill
|
||||||
|
- type: Lube
|
||||||
|
|||||||
|
After Width: | Height: | Size: 717 B |
|
After Width: | Height: | Size: 718 B |
|
After Width: | Height: | Size: 717 B |
|
After Width: | Height: | Size: 717 B |
|
After Width: | Height: | Size: 718 B |
|
After Width: | Height: | Size: 680 B |
|
After Width: | Height: | Size: 712 B |
|
After Width: | Height: | Size: 713 B |
@@ -0,0 +1,35 @@
|
|||||||
|
{
|
||||||
|
"version": 1,
|
||||||
|
"size": {
|
||||||
|
"x": 32,
|
||||||
|
"y": 32
|
||||||
|
},
|
||||||
|
"license": "CC-BY-NC-SA-4.0",
|
||||||
|
"copyright": "Created by discord: brainfood#7460 / github: brainfood1183.",
|
||||||
|
"states": [
|
||||||
|
{
|
||||||
|
"name": "icon"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "icon-front"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "fill1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "fill2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "fill3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "fill4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "fill5"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "fill6"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||