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>))]
|
[DataField("board", customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>))]
|
||||||
public string? BoardPrototype { get; private set; }
|
public string? BoardPrototype { get; private set; }
|
||||||
|
|
||||||
|
[ViewVariables]
|
||||||
public Container BoardContainer = default!;
|
public Container BoardContainer = default!;
|
||||||
|
[ViewVariables]
|
||||||
public Container PartContainer = default!;
|
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>
|
/// </summary>
|
||||||
public object? UserFinishedEvent { get; set; }
|
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>
|
/// <summary>
|
||||||
/// Event to be raised directed to the <see cref="Target"/> entity when the DoAfter is cancelled.
|
/// Event to be raised directed to the <see cref="Target"/> entity when the DoAfter is cancelled.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -153,6 +153,9 @@ namespace Content.Server.DoAfter
|
|||||||
if(EntityManager.EntityExists(doAfter.EventArgs.User) && doAfter.EventArgs.UserCancelledEvent != null)
|
if(EntityManager.EntityExists(doAfter.EventArgs.User) && doAfter.EventArgs.UserCancelledEvent != null)
|
||||||
RaiseLocalEvent(doAfter.EventArgs.User, doAfter.EventArgs.UserCancelledEvent, false);
|
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)
|
if(doAfter.EventArgs.Target is {} target && EntityManager.EntityExists(target) && doAfter.EventArgs.TargetCancelledEvent != null)
|
||||||
RaiseLocalEvent(target, doAfter.EventArgs.TargetCancelledEvent, false);
|
RaiseLocalEvent(target, doAfter.EventArgs.TargetCancelledEvent, false);
|
||||||
|
|
||||||
@@ -167,6 +170,9 @@ namespace Content.Server.DoAfter
|
|||||||
if(EntityManager.EntityExists(doAfter.EventArgs.User) && doAfter.EventArgs.UserFinishedEvent != null)
|
if(EntityManager.EntityExists(doAfter.EventArgs.User) && doAfter.EventArgs.UserFinishedEvent != null)
|
||||||
RaiseLocalEvent(doAfter.EventArgs.User, doAfter.EventArgs.UserFinishedEvent, false);
|
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)
|
if(doAfter.EventArgs.Target is {} target && EntityManager.EntityExists(target) && doAfter.EventArgs.TargetFinishedEvent != null)
|
||||||
RaiseLocalEvent(target, doAfter.EventArgs.TargetFinishedEvent, false);
|
RaiseLocalEvent(target, doAfter.EventArgs.TargetFinishedEvent, false);
|
||||||
|
|
||||||
|
|||||||
@@ -7,3 +7,8 @@
|
|||||||
license: "CC-BY-SA-3.0"
|
license: "CC-BY-SA-3.0"
|
||||||
copyright: "Time immemorial"
|
copyright: "Time immemorial"
|
||||||
source: "https://github.com/tgstation/tgstation/blob/172b533d0257fcc1f8a05406f1c9fad514c14d88/sound/items/trayhit2.ogg"
|
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
|
- FireAlarmElectronics
|
||||||
- MailingUnitElectronics
|
- MailingUnitElectronics
|
||||||
- HolofanProjector
|
- HolofanProjector
|
||||||
|
- RPED
|
||||||
|
|
||||||
- type: technology
|
- type: technology
|
||||||
name: technologies-material-sheet-printing
|
name: technologies-material-sheet-printing
|
||||||
@@ -438,7 +439,6 @@
|
|||||||
requiredPoints: 8000
|
requiredPoints: 8000
|
||||||
requiredTechnologies:
|
requiredTechnologies:
|
||||||
- BasicPartsTechnology
|
- BasicPartsTechnology
|
||||||
- IndustrialEngineering
|
|
||||||
- PowerCellBasic
|
- PowerCellBasic
|
||||||
unlockedRecipes:
|
unlockedRecipes:
|
||||||
- AdvancedCapacitorStockPart
|
- 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
|
Glass: 350
|
||||||
Plastic: 150
|
Plastic: 150
|
||||||
Gold: 10
|
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