RPED (#12008)
* RPED * sound effect * wires must be open finished me appy slices yum yum * Update Resources/Audio/Items/attributions.yml Co-authored-by: Zonespace <41448081+Zonespace27@users.noreply.github.com> * Update attributions.yml Co-authored-by: Zonespace <41448081+Zonespace27@users.noreply.github.com>
This commit is contained in:
@@ -10,7 +10,9 @@ namespace Content.Server.Construction.Components
|
||||
[DataField("board", customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>))]
|
||||
public string? BoardPrototype { get; private set; }
|
||||
|
||||
[ViewVariables]
|
||||
public Container BoardContainer = default!;
|
||||
[ViewVariables]
|
||||
public Container PartContainer = default!;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
using System.Threading;
|
||||
using Robust.Shared.Audio;
|
||||
|
||||
namespace Content.Server.Construction.Components;
|
||||
|
||||
[RegisterComponent]
|
||||
public sealed class PartExchangerComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// How long it takes to exchange the parts
|
||||
/// </summary>
|
||||
[DataField("exchangeDuration")]
|
||||
public float ExchangeDuration = 3;
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not the distance check is needed.
|
||||
/// Good for BRPED.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// I fucking hate BRPED and if you ever add it
|
||||
/// i will personally kill your dog.
|
||||
/// </remarks>
|
||||
[DataField("doDistanceCheck")]
|
||||
public bool DoDistanceCheck = true;
|
||||
|
||||
[DataField("exchangeSound")]
|
||||
public SoundSpecifier ExchangeSound = new SoundPathSpecifier("/Audio/Items/rped.ogg");
|
||||
|
||||
public IPlayingAudioStream? AudioStream;
|
||||
|
||||
public CancellationTokenSource? Token;
|
||||
}
|
||||
142
Content.Server/Construction/PartExchangerSystem.cs
Normal file
142
Content.Server/Construction/PartExchangerSystem.cs
Normal file
@@ -0,0 +1,142 @@
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using Content.Server.Construction.Components;
|
||||
using Content.Server.DoAfter;
|
||||
using Content.Server.Storage.Components;
|
||||
using Content.Server.Storage.EntitySystems;
|
||||
using Content.Server.Wires;
|
||||
using Content.Shared.Interaction;
|
||||
using Content.Shared.Popups;
|
||||
using Robust.Shared.Containers;
|
||||
using Robust.Shared.Player;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Server.Construction;
|
||||
|
||||
public sealed class PartExchangerSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly ConstructionSystem _construction = default!;
|
||||
[Dependency] private readonly DoAfterSystem _doAfter = default!;
|
||||
[Dependency] private readonly SharedPopupSystem _popup = default!;
|
||||
[Dependency] private readonly SharedContainerSystem _container = default!;
|
||||
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
||||
[Dependency] private readonly StorageSystem _storage = default!;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void Initialize()
|
||||
{
|
||||
SubscribeLocalEvent<PartExchangerComponent, AfterInteractEvent>(OnAfterInteract);
|
||||
SubscribeLocalEvent<PartExchangerComponent, RpedExchangeFinishedEvent>(OnFinished);
|
||||
SubscribeLocalEvent<PartExchangerComponent, RpedExchangeCancelledEvent>(OnCancelled);
|
||||
}
|
||||
|
||||
private void OnFinished(EntityUid uid, PartExchangerComponent component, RpedExchangeFinishedEvent args)
|
||||
{
|
||||
component.Token = null;
|
||||
component.AudioStream?.Stop();
|
||||
|
||||
if (!TryComp<MachineComponent>(args.Target, out var machine))
|
||||
return;
|
||||
|
||||
if (!TryComp<ServerStorageComponent>(uid, out var storage) || storage.Storage == null)
|
||||
return; //the parts are stored in here
|
||||
|
||||
var board = machine.BoardContainer.ContainedEntities.FirstOrNull();
|
||||
|
||||
if (board == null || !TryComp<MachineBoardComponent>(board, out var macBoardComp))
|
||||
return;
|
||||
|
||||
var machineParts = new List<MachinePartComponent>();
|
||||
|
||||
foreach (var ent in storage.Storage.ContainedEntities) //get parts in RPED
|
||||
{
|
||||
if (TryComp<MachinePartComponent>(ent, out var part))
|
||||
machineParts.Add(part);
|
||||
}
|
||||
foreach (var ent in new List<EntityUid>(machine.PartContainer.ContainedEntities)) //clone so don't modify during enumeration
|
||||
{
|
||||
if (TryComp<MachinePartComponent>(ent, out var part))
|
||||
{
|
||||
machineParts.Add(part);
|
||||
_container.RemoveEntity(machine.Owner, ent);
|
||||
}
|
||||
}
|
||||
|
||||
//order by highest rating
|
||||
machineParts = machineParts.OrderByDescending(p => p.Rating).ToList();
|
||||
|
||||
var updatedParts = new List<MachinePartComponent>();
|
||||
foreach (var (type, amount) in macBoardComp.Requirements)
|
||||
{
|
||||
var target = machineParts.Where(p => p.PartType == type).Take(amount);
|
||||
updatedParts.AddRange(target);
|
||||
}
|
||||
foreach (var part in updatedParts)
|
||||
{
|
||||
machine.PartContainer.Insert(part.Owner, EntityManager);
|
||||
machineParts.Remove(part);
|
||||
}
|
||||
|
||||
//put the unused parts back into rped. (this also does the "swapping")
|
||||
foreach (var unused in machineParts)
|
||||
{
|
||||
storage.Storage.Insert(unused.Owner);
|
||||
_storage.Insert(uid, unused.Owner, null, false);
|
||||
}
|
||||
_construction.RefreshParts(machine);
|
||||
}
|
||||
|
||||
private void OnCancelled(EntityUid uid, PartExchangerComponent component, RpedExchangeCancelledEvent args)
|
||||
{
|
||||
component.Token = null;
|
||||
component.AudioStream?.Stop();
|
||||
}
|
||||
|
||||
private void OnAfterInteract(EntityUid uid, PartExchangerComponent component, AfterInteractEvent args)
|
||||
{
|
||||
if (component.Token != null)
|
||||
return;
|
||||
|
||||
if (component.DoDistanceCheck && !args.CanReach)
|
||||
return;
|
||||
|
||||
if (args.Target == null)
|
||||
return;
|
||||
|
||||
if (!HasComp<MachineComponent>(args.Target))
|
||||
return;
|
||||
|
||||
if (TryComp<WiresComponent>(args.Target, out var wires) && !wires.IsPanelOpen)
|
||||
{
|
||||
_popup.PopupEntity(Loc.GetString("construction-step-condition-wire-panel-open"),
|
||||
args.Target.Value, Filter.Pvs(args.Target.Value, entityManager: EntityManager));
|
||||
return;
|
||||
}
|
||||
|
||||
component.AudioStream = _audio.PlayPvs(component.ExchangeSound, uid);
|
||||
|
||||
component.Token = new CancellationTokenSource();
|
||||
_doAfter.DoAfter(new DoAfterEventArgs(args.User, component.ExchangeDuration, component.Token.Token, args.Target, args.Used)
|
||||
{
|
||||
BreakOnDamage = true,
|
||||
BreakOnStun = true,
|
||||
BreakOnUserMove = true,
|
||||
UsedFinishedEvent = new RpedExchangeFinishedEvent(args.Target.Value),
|
||||
UsedCancelledEvent = new RpedExchangeCancelledEvent()
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class RpedExchangeFinishedEvent : EntityEventArgs
|
||||
{
|
||||
public readonly EntityUid Target;
|
||||
|
||||
public RpedExchangeFinishedEvent(EntityUid target)
|
||||
{
|
||||
Target = target;
|
||||
}
|
||||
}
|
||||
|
||||
public readonly struct RpedExchangeCancelledEvent
|
||||
{
|
||||
}
|
||||
@@ -89,6 +89,16 @@ namespace Content.Server.DoAfter
|
||||
/// </summary>
|
||||
public object? UserFinishedEvent { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Event to be raised directed to the <see cref="Used"/> entity when the DoAfter is cancelled.
|
||||
/// </summary>
|
||||
public object? UsedCancelledEvent { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Event to be raised directed to the <see cref="Used"/> entity when the DoAfter is finished successfully.
|
||||
/// </summary>
|
||||
public object? UsedFinishedEvent { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Event to be raised directed to the <see cref="Target"/> entity when the DoAfter is cancelled.
|
||||
/// </summary>
|
||||
|
||||
@@ -153,6 +153,9 @@ namespace Content.Server.DoAfter
|
||||
if(EntityManager.EntityExists(doAfter.EventArgs.User) && doAfter.EventArgs.UserCancelledEvent != null)
|
||||
RaiseLocalEvent(doAfter.EventArgs.User, doAfter.EventArgs.UserCancelledEvent, false);
|
||||
|
||||
if (doAfter.EventArgs.Used is {} used && EntityManager.EntityExists(used) && doAfter.EventArgs.UsedCancelledEvent != null)
|
||||
RaiseLocalEvent(used, doAfter.EventArgs.UsedCancelledEvent);
|
||||
|
||||
if(doAfter.EventArgs.Target is {} target && EntityManager.EntityExists(target) && doAfter.EventArgs.TargetCancelledEvent != null)
|
||||
RaiseLocalEvent(target, doAfter.EventArgs.TargetCancelledEvent, false);
|
||||
|
||||
@@ -167,6 +170,9 @@ namespace Content.Server.DoAfter
|
||||
if(EntityManager.EntityExists(doAfter.EventArgs.User) && doAfter.EventArgs.UserFinishedEvent != null)
|
||||
RaiseLocalEvent(doAfter.EventArgs.User, doAfter.EventArgs.UserFinishedEvent, false);
|
||||
|
||||
if(doAfter.EventArgs.Used is {} used && EntityManager.EntityExists(used) && doAfter.EventArgs.UsedFinishedEvent != null)
|
||||
RaiseLocalEvent(used, doAfter.EventArgs.UsedFinishedEvent);
|
||||
|
||||
if(doAfter.EventArgs.Target is {} target && EntityManager.EntityExists(target) && doAfter.EventArgs.TargetFinishedEvent != null)
|
||||
RaiseLocalEvent(target, doAfter.EventArgs.TargetFinishedEvent, false);
|
||||
|
||||
|
||||
@@ -7,3 +7,8 @@
|
||||
license: "CC-BY-SA-3.0"
|
||||
copyright: "Time immemorial"
|
||||
source: "https://github.com/tgstation/tgstation/blob/172b533d0257fcc1f8a05406f1c9fad514c14d88/sound/items/trayhit2.ogg"
|
||||
|
||||
- files: ["rped.ogg"]
|
||||
license: "CC-BY-SA-3.0"
|
||||
copyright: "Time immemorial"
|
||||
source: "https://github.com/tgstation/tgstation/blob/172b533d0257fcc1f8a05406f1c9fad514c14d88/sound/items/rped.ogg"
|
||||
|
||||
BIN
Resources/Audio/Items/rped.ogg
Normal file
BIN
Resources/Audio/Items/rped.ogg
Normal file
Binary file not shown.
@@ -245,6 +245,7 @@
|
||||
- FireAlarmElectronics
|
||||
- MailingUnitElectronics
|
||||
- HolofanProjector
|
||||
- RPED
|
||||
|
||||
- type: technology
|
||||
name: technologies-material-sheet-printing
|
||||
@@ -438,7 +439,6 @@
|
||||
requiredPoints: 8000
|
||||
requiredTechnologies:
|
||||
- BasicPartsTechnology
|
||||
- IndustrialEngineering
|
||||
- PowerCellBasic
|
||||
unlockedRecipes:
|
||||
- AdvancedCapacitorStockPart
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
- type: entity
|
||||
parent: BaseStorageItem
|
||||
id: RPED
|
||||
name: RPED
|
||||
description: A Rapid Part Exchange Device, perfect for quickly upgrading machines.
|
||||
components:
|
||||
- type: Sprite
|
||||
sprite: Objects/Specific/Research/rped.rsi
|
||||
state: icon
|
||||
- type: Item
|
||||
sprite: Objects/Specific/Research/rped.rsi
|
||||
size: 50
|
||||
- type: PartExchanger
|
||||
- type: Storage
|
||||
capacity: 150
|
||||
whitelist:
|
||||
components:
|
||||
- MachinePart
|
||||
@@ -189,3 +189,15 @@
|
||||
Glass: 350
|
||||
Plastic: 150
|
||||
Gold: 10
|
||||
|
||||
- type: latheRecipe
|
||||
id: RPED
|
||||
icon:
|
||||
sprite: Objects/Specific/Research/rped.rsi
|
||||
state: icon
|
||||
result: RPED
|
||||
completetime: 10
|
||||
materials:
|
||||
Steel: 650
|
||||
Plastic: 150
|
||||
Gold: 50
|
||||
|
||||
BIN
Resources/Textures/Objects/Specific/Research/rped.rsi/icon.png
Normal file
BIN
Resources/Textures/Objects/Specific/Research/rped.rsi/icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.0 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 996 B |
Binary file not shown.
|
After Width: | Height: | Size: 1002 B |
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"version": 1,
|
||||
"license": "CC-BY-SA-3.0",
|
||||
"copyright": "Taken from tgstation at https://github.com/tgstation/tgstation/commit/40d89d11ea4a5cb81d61dc1018b46f4e7d32c62a, inhands created by EmoGarbage404",
|
||||
"size": {
|
||||
"x": 32,
|
||||
"y": 32
|
||||
},
|
||||
"states": [
|
||||
{
|
||||
"name": "icon"
|
||||
},
|
||||
{
|
||||
"name": "inhand-left",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "inhand-right",
|
||||
"directions": 4
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user