diff --git a/Content.Client/IgnoredComponents.cs b/Content.Client/IgnoredComponents.cs index 9df1ab57ce..b1a223cee4 100644 --- a/Content.Client/IgnoredComponents.cs +++ b/Content.Client/IgnoredComponents.cs @@ -1,4 +1,4 @@ -namespace Content.Client +namespace Content.Client { public static class IgnoredComponents { @@ -225,7 +225,8 @@ "MachineFrame", "MachineBoard", "ChemicalAmmo", - "BiologicalSurgeryData" + "BiologicalSurgeryData", + "CargoTelepad", }; } } diff --git a/Content.Client/UserInterface/Cargo/CargoConsoleMenu.cs b/Content.Client/UserInterface/Cargo/CargoConsoleMenu.cs index b955ec5493..697c73a689 100644 --- a/Content.Client/UserInterface/Cargo/CargoConsoleMenu.cs +++ b/Content.Client/UserInterface/Cargo/CargoConsoleMenu.cs @@ -109,7 +109,8 @@ namespace Content.Client.UserInterface.Cargo var buttons = new HBoxContainer(); CallShuttleButton = new Button() { - Text = Loc.GetString("Call Shuttle"), + //Text = Loc.GetString("Call Shuttle"), + Text = Loc.GetString("Activate Telepad"), //Shuttle code pending TextAlign = Label.AlignMode.Center, SizeFlagsHorizontal = SizeFlags.FillExpand }; diff --git a/Content.Server/GameObjects/Components/Cargo/CargoConsoleComponent.cs b/Content.Server/GameObjects/Components/Cargo/CargoConsoleComponent.cs index 35c9577c7a..b48ebd83bb 100644 --- a/Content.Server/GameObjects/Components/Cargo/CargoConsoleComponent.cs +++ b/Content.Server/GameObjects/Components/Cargo/CargoConsoleComponent.cs @@ -1,4 +1,4 @@ -#nullable enable +#nullable enable using Content.Server.Cargo; using Content.Server.GameObjects.Components.Power.ApcNetComponents; using Content.Server.GameObjects.EntitySystems; @@ -10,10 +10,15 @@ using Robust.Server.GameObjects.Components.UserInterface; using Robust.Server.Interfaces.GameObjects; using Robust.Shared.GameObjects; using Robust.Shared.GameObjects.Systems; +using Robust.Shared.Interfaces.GameObjects; +using Robust.Shared.Interfaces.Map; using Robust.Shared.IoC; using Robust.Shared.Log; +using Robust.Shared.Maths; using Robust.Shared.Serialization; using Robust.Shared.ViewVariables; +using System.Collections.Generic; +using System.Linq; namespace Content.Server.GameObjects.Components.Cargo { @@ -22,6 +27,7 @@ namespace Content.Server.GameObjects.Components.Cargo public class CargoConsoleComponent : SharedCargoConsoleComponent, IActivate { [Dependency] private readonly ICargoOrderDataManager _cargoOrderDataManager = default!; + [Dependency] private readonly IMapManager _mapManager = default!; [ViewVariables] public int Points = 1000; @@ -113,59 +119,88 @@ namespace Content.Server.GameObjects.Components.Cargo switch (message) { case CargoConsoleAddOrderMessage msg: - { - if (msg.Amount <= 0 || _bankAccount == null) { - break; - } - - _cargoOrderDataManager.AddOrder(orders.Database.Id, msg.Requester, msg.Reason, msg.ProductId, msg.Amount, _bankAccount.Id); - break; - } - case CargoConsoleRemoveOrderMessage msg: - { - _cargoOrderDataManager.RemoveOrder(orders.Database.Id, msg.OrderNumber); - break; - } - case CargoConsoleApproveOrderMessage msg: - { - if (_requestOnly || - !orders.Database.TryGetOrder(msg.OrderNumber, out var order) || - _bankAccount == null) - { - break; - } - - PrototypeManager.TryIndex(order.ProductId, out CargoProductPrototype product); - if (product == null!) - break; - var capacity = _cargoOrderDataManager.GetCapacity(orders.Database.Id); - if (capacity.CurrentCapacity == capacity.MaxCapacity) - break; - if (!_cargoConsoleSystem.ChangeBalance(_bankAccount.Id, (-product.PointCost) * order.Amount)) - break; - _cargoOrderDataManager.ApproveOrder(orders.Database.Id, msg.OrderNumber); - UpdateUIState(); - break; - } - case CargoConsoleShuttleMessage _: - { - var approvedOrders = _cargoOrderDataManager.RemoveAndGetApprovedFrom(orders.Database); - orders.Database.ClearOrderCapacity(); - // TODO replace with shuttle code - - // TEMPORARY loop for spawning stuff on top of console - foreach (var order in approvedOrders) - { - if (!PrototypeManager.TryIndex(order.ProductId, out CargoProductPrototype product)) - continue; - for (var i = 0; i < order.Amount; i++) + if (msg.Amount <= 0 || _bankAccount == null) { - Owner.EntityManager.SpawnEntity(product.Product, Owner.Transform.Coordinates); + break; } + + _cargoOrderDataManager.AddOrder(orders.Database.Id, msg.Requester, msg.Reason, msg.ProductId, msg.Amount, _bankAccount.Id); + break; + } + case CargoConsoleRemoveOrderMessage msg: + { + _cargoOrderDataManager.RemoveOrder(orders.Database.Id, msg.OrderNumber); + break; + } + case CargoConsoleApproveOrderMessage msg: + { + if (_requestOnly || + !orders.Database.TryGetOrder(msg.OrderNumber, out var order) || + _bankAccount == null) + { + break; + } + + PrototypeManager.TryIndex(order.ProductId, out CargoProductPrototype product); + if (product == null!) + break; + var capacity = _cargoOrderDataManager.GetCapacity(orders.Database.Id); + if (capacity.CurrentCapacity == capacity.MaxCapacity) + break; + if (!_cargoConsoleSystem.ChangeBalance(_bankAccount.Id, (-product.PointCost) * order.Amount)) + break; + _cargoOrderDataManager.ApproveOrder(orders.Database.Id, msg.OrderNumber); + UpdateUIState(); + break; + } + case CargoConsoleShuttleMessage _: + { + //var approvedOrders = _cargoOrderDataManager.RemoveAndGetApprovedFrom(orders.Database); + //orders.Database.ClearOrderCapacity(); + + // TODO replace with shuttle code + // TEMPORARY loop for spawning stuff on telepad (looks for a telepad adjacent to the console) + IEntity? cargoTelepad = null; + var indices = Owner.Transform.Coordinates.ToVector2i(Owner.EntityManager, _mapManager); + var offsets = new Vector2i[] { new Vector2i(0, 1), new Vector2i(1, 1), new Vector2i(1, 0), new Vector2i(1, -1), + new Vector2i(0, -1), new Vector2i(-1, -1), new Vector2i(-1, 0), new Vector2i(-1, 1), }; + var adjacentEntities = new List>(); //Probably better than IEnumerable.concat + foreach (var offset in offsets) + { + adjacentEntities.Add((indices+offset).GetEntitiesInTileFast(Owner.Transform.GridID)); + } + + foreach (var enumerator in adjacentEntities) + { + foreach (IEntity entity in enumerator) + { + if (entity.HasComponent() && entity.TryGetComponent(out var powerReceiver) && powerReceiver.Powered) + { + cargoTelepad = entity; + break; + } + } + } + if (cargoTelepad != null) + { + if (cargoTelepad.TryGetComponent(out var telepadComponent)) + { + var approvedOrders = _cargoOrderDataManager.RemoveAndGetApprovedFrom(orders.Database); + orders.Database.ClearOrderCapacity(); + foreach (var order in approvedOrders) + { + if (!PrototypeManager.TryIndex(order.ProductId, out CargoProductPrototype product)) + continue; + for (var i = 0; i < order.Amount; i++) + { + telepadComponent.QueueTeleport(product); + } + } + } + } + break; } - break; - } } } diff --git a/Content.Server/GameObjects/Components/Cargo/CargoTelepadComponent.cs b/Content.Server/GameObjects/Components/Cargo/CargoTelepadComponent.cs new file mode 100644 index 0000000000..a85c8386a3 --- /dev/null +++ b/Content.Server/GameObjects/Components/Cargo/CargoTelepadComponent.cs @@ -0,0 +1,101 @@ +#nullable enable +using Content.Server.GameObjects.Components.Power.ApcNetComponents; +using Content.Shared.Interfaces.GameObjects.Components; +using Content.Shared.Prototypes.Cargo; +using Robust.Server.GameObjects; +using Robust.Server.GameObjects.EntitySystems; +using Robust.Shared.Audio; +using Robust.Shared.GameObjects; +using Robust.Shared.GameObjects.Components.Timers; +using Robust.Shared.GameObjects.Systems; +using System.Collections.Generic; + +namespace Content.Server.GameObjects.Components.Cargo +{ + + //This entire class is a PLACEHOLDER for the cargo shuttle. + + [RegisterComponent] + public class CargoTelepadComponent : Component + { + public override string Name => "CargoTelepad"; + + private const float TeleportDuration = 0.5f; + private const float TeleportDelay = 15f; + private List _teleportQueue = new List(); + private CargoTelepadState _currentState = CargoTelepadState.Unpowered; + + + public override void OnAdd() + { + base.OnAdd(); + + var receiver = Owner.EnsureComponent(); + receiver.OnPowerStateChanged += PowerUpdate; + } + + public override void OnRemove() + { + if (Owner.TryGetComponent(out PowerReceiverComponent? receiver)) + { + receiver.OnPowerStateChanged -= PowerUpdate; + } + base.OnRemove(); + } + + public void QueueTeleport(CargoProductPrototype product) + { + _teleportQueue.Add(product); + TeleportLoop(); + } + + private void PowerUpdate(object? sender, PowerStateEventArgs args) + { + if (args.Powered && _currentState == CargoTelepadState.Unpowered) { + _currentState = CargoTelepadState.Idle; + if(Owner.TryGetComponent(out var spriteComponent)) + spriteComponent.LayerSetState(0, "pad-idle"); + TeleportLoop(); + } + else if (!args.Powered) + { + _currentState = CargoTelepadState.Unpowered; + if (Owner.TryGetComponent(out var spriteComponent)) + spriteComponent.LayerSetState(0, "pad-offline"); + } + } + private void TeleportLoop() + { + if (_currentState == CargoTelepadState.Idle && _teleportQueue.Count > 0) + { + _currentState = CargoTelepadState.Charging; + if (Owner.TryGetComponent(out var spriteComponent)) + spriteComponent.LayerSetState(0, "pad-idle"); + Owner.SpawnTimer((int) (TeleportDelay * 1000), () => + { + if (!Deleted && !Owner.Deleted && _currentState == CargoTelepadState.Charging && _teleportQueue.Count > 0) + { + _currentState = CargoTelepadState.Teleporting; + if (Owner.TryGetComponent(out var spriteComponent)) + spriteComponent.LayerSetState(0, "pad-beam"); + Owner.SpawnTimer((int) (TeleportDuration * 1000), () => + { + if (!Deleted && !Owner.Deleted && _currentState == CargoTelepadState.Teleporting && _teleportQueue.Count > 0) + { + EntitySystem.Get().PlayFromEntity("/Audio/machines/phasein.ogg", Owner, AudioParams.Default.WithVolume(-8f)); + Owner.EntityManager.SpawnEntity(_teleportQueue[0].Product, Owner.Transform.Coordinates); + _teleportQueue.RemoveAt(0); + if (Owner.TryGetComponent(out var spriteComponent)) + spriteComponent.LayerSetState(0, "pad-idle"); + _currentState = CargoTelepadState.Idle; + TeleportLoop(); + } + }); + } + }); + } + } + + private enum CargoTelepadState { Unpowered, Idle, Charging, Teleporting }; + } +} diff --git a/Resources/Audio/Machines/phasein.ogg b/Resources/Audio/Machines/phasein.ogg new file mode 100644 index 0000000000..9bb4d443f0 Binary files /dev/null and b/Resources/Audio/Machines/phasein.ogg differ diff --git a/Resources/Audio/Misc/windowsXP_error.ogg b/Resources/Audio/Misc/windowsXP_error.ogg new file mode 100644 index 0000000000..83a0ccc0b4 Binary files /dev/null and b/Resources/Audio/Misc/windowsXP_error.ogg differ diff --git a/Resources/Audio/Misc/windowsXP_shutdown.ogg b/Resources/Audio/Misc/windowsXP_shutdown.ogg new file mode 100644 index 0000000000..acbb9a64e1 Binary files /dev/null and b/Resources/Audio/Misc/windowsXP_shutdown.ogg differ diff --git a/Resources/Audio/Misc/windowsXP_startup.ogg b/Resources/Audio/Misc/windowsXP_startup.ogg new file mode 100644 index 0000000000..32cd462de3 Binary files /dev/null and b/Resources/Audio/Misc/windowsXP_startup.ogg differ diff --git a/Resources/Prototypes/Entities/Constructible/Specific/cargo_telepad.yml b/Resources/Prototypes/Entities/Constructible/Specific/cargo_telepad.yml new file mode 100644 index 0000000000..7e7ec8d028 --- /dev/null +++ b/Resources/Prototypes/Entities/Constructible/Specific/cargo_telepad.yml @@ -0,0 +1,26 @@ +- type: entity + name: cargo telepad + id: cargoTelepad + description: "Temporary cargo delivery for developing Nanotrasen stations! Warning: destroying this while goods are in transit will lose them forever!" + placement: + mode: SnapgridCenter + components: + - type: Clickable + - type: InteractionOutline + - type: Physics + mass: 25 + anchored: true + shapes: + - !type:PhysShapeAabb + bounds: "-0.45, -0.45, 0.00, 0.45" + layer: [ Passable ] + - type: Sprite + sprite: Constructible/Power/cargo_teleporter.rsi + state: pad-offline + - type: Destructible + deadThreshold: 75 + resistances: metallicResistances + - type: Anchorable + - type: Pullable + - type: PowerReceiver + - type: CargoTelepad \ No newline at end of file diff --git a/Resources/Textures/Constructible/Power/cargo_teleporter.rsi/meta.json b/Resources/Textures/Constructible/Power/cargo_teleporter.rsi/meta.json new file mode 100644 index 0000000000..668446e50b --- /dev/null +++ b/Resources/Textures/Constructible/Power/cargo_teleporter.rsi/meta.json @@ -0,0 +1,45 @@ +{ + "version":1, + "size":{ + "x":32, + "y":32 + }, + "license":"CC-BY-SA-3.0", + "copyright":"Taken from /vg/station at commit 5c50dee8fb2a55d6be3b3c9c90a782a618a5506e", + "states":[ + { + "name":"pad-beam", + "directions":1, + "delays":[ + [ + 0.1, + 0.1, + 0.1, + 0.1, + 0.1 + ] + ] + }, + { + "name":"pad-idle", + "directions":1, + "delays":[ + [ + 0.2, + 0.2, + 0.2, + 0.2 + ] + ] + }, + { + "name":"pad-offline", + "directions":1, + "delays":[ + [ + 1.0 + ] + ] + } + ] +} \ No newline at end of file diff --git a/Resources/Textures/Constructible/Power/cargo_teleporter.rsi/pad-beam.png b/Resources/Textures/Constructible/Power/cargo_teleporter.rsi/pad-beam.png new file mode 100644 index 0000000000..08e4dd0eda Binary files /dev/null and b/Resources/Textures/Constructible/Power/cargo_teleporter.rsi/pad-beam.png differ diff --git a/Resources/Textures/Constructible/Power/cargo_teleporter.rsi/pad-idle.png b/Resources/Textures/Constructible/Power/cargo_teleporter.rsi/pad-idle.png new file mode 100644 index 0000000000..bf79fade7d Binary files /dev/null and b/Resources/Textures/Constructible/Power/cargo_teleporter.rsi/pad-idle.png differ diff --git a/Resources/Textures/Constructible/Power/cargo_teleporter.rsi/pad-offline.png b/Resources/Textures/Constructible/Power/cargo_teleporter.rsi/pad-offline.png new file mode 100644 index 0000000000..e701d9994d Binary files /dev/null and b/Resources/Textures/Constructible/Power/cargo_teleporter.rsi/pad-offline.png differ