diff --git a/Content.Client/EntryPoint.cs b/Content.Client/EntryPoint.cs index a4edb0736c..006199f5e7 100644 --- a/Content.Client/EntryPoint.cs +++ b/Content.Client/EntryPoint.cs @@ -18,6 +18,7 @@ using Content.Shared.GameObjects.Components.Chemistry.ChemMaster; using Content.Shared.GameObjects.Components.Chemistry.ReagentDispenser; using Content.Shared.GameObjects.Components.Gravity; using Content.Shared.GameObjects.Components.Markers; +using Content.Shared.GameObjects.Components.Power.AME; using Content.Shared.GameObjects.Components.Research; using Content.Shared.GameObjects.Components.VendingMachines; using Content.Shared.Kitchen; @@ -72,6 +73,7 @@ namespace Content.Client factory.Register(); factory.Register(); factory.Register(); + factory.Register(); prototypes.RegisterIgnore("material"); prototypes.RegisterIgnore("reaction"); //Chemical reactions only needed by server. Reactions checks are server-side. diff --git a/Content.Client/GameObjects/Components/Power/AME/AMEControllerBoundUserInterface.cs b/Content.Client/GameObjects/Components/Power/AME/AMEControllerBoundUserInterface.cs new file mode 100644 index 0000000000..ff0bcff85e --- /dev/null +++ b/Content.Client/GameObjects/Components/Power/AME/AMEControllerBoundUserInterface.cs @@ -0,0 +1,62 @@ +using Robust.Client.GameObjects.Components.UserInterface; +using Robust.Shared.GameObjects.Components.UserInterface; +using static Content.Shared.GameObjects.Components.Power.AME.SharedAMEControllerComponent; + +namespace Content.Client.GameObjects.Components.Power.AME +{ + public class AMEControllerBoundUserInterface : BoundUserInterface + { + private AMEWindow _window; + + public AMEControllerBoundUserInterface(ClientUserInterfaceComponent owner, object uiKey) : base(owner, uiKey) + { + + } + + protected override void Open() + { + base.Open(); + + _window = new AMEWindow(); + _window.OnClose += Close; + _window.OpenCentered(); + + _window.EjectButton.OnPressed += _ => ButtonPressed(UiButton.Eject); + _window.ToggleInjection.OnPressed += _ => ButtonPressed(UiButton.ToggleInjection); + _window.IncreaseFuelButton.OnPressed += _ => ButtonPressed(UiButton.IncreaseFuel); + _window.DecreaseFuelButton.OnPressed += _ => ButtonPressed(UiButton.DecreaseFuel); + _window.RefreshPartsButton.OnPressed += _ => ButtonPressed(UiButton.RefreshParts); + } + + + /// + /// Update the ui each time new state data is sent from the server. + /// + /// + /// Data of the that this ui represents. + /// Sent from the server. + /// + protected override void UpdateState(BoundUserInterfaceState state) + { + base.UpdateState(state); + + var castState = (AMEControllerBoundUserInterfaceState) state; + _window?.UpdateState(castState); //Update window state + } + + private void ButtonPressed(UiButton button, int dispenseIndex = -1) + { + SendMessage(new UiButtonPressedMessage(button)); + } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + + if (disposing) + { + _window.Dispose(); + } + } + } +} diff --git a/Content.Client/GameObjects/Components/Power/AME/AMEControllerVisualizer.cs b/Content.Client/GameObjects/Components/Power/AME/AMEControllerVisualizer.cs new file mode 100644 index 0000000000..4345b68f5b --- /dev/null +++ b/Content.Client/GameObjects/Components/Power/AME/AMEControllerVisualizer.cs @@ -0,0 +1,57 @@ +using Robust.Client.GameObjects; +using Robust.Client.Interfaces.GameObjects.Components; +using Robust.Shared.Interfaces.GameObjects; +using System; +using System.Collections.Generic; +using System.Text; +using static Content.Shared.GameObjects.Components.Power.AME.SharedAMEControllerComponent; + +namespace Content.Client.GameObjects.Components.Power.AME +{ + public class AMEControllerVisualizer : AppearanceVisualizer + { + public override void InitializeEntity(IEntity entity) + { + base.InitializeEntity(entity); + var sprite = entity.GetComponent(); + + sprite.LayerMapSet(Layers.Display, sprite.AddLayerState("control_on")); + sprite.LayerSetVisible(Layers.Display, false); + } + + public override void OnChangeData(AppearanceComponent component) + { + base.OnChangeData(component); + var sprite = component.Owner.GetComponent(); + if (component.TryGetData(AMEControllerVisuals.DisplayState, out var state)) + { + switch (state) + { + case "on": + sprite.LayerSetState(Layers.Display, "control_on"); + sprite.LayerSetVisible(Layers.Display, true); + break; + case "critical": + sprite.LayerSetState(Layers.Display, "control_critical"); + sprite.LayerSetVisible(Layers.Display, true); + break; + case "fuck": + sprite.LayerSetState(Layers.Display, "control_fuck"); + sprite.LayerSetVisible(Layers.Display, true); + break; + case "off": + sprite.LayerSetVisible(Layers.Display, false); + break; + default: + sprite.LayerSetVisible(Layers.Display, false); + break; + } + } + } + + enum Layers + { + Display, + } + } +} diff --git a/Content.Client/GameObjects/Components/Power/AME/AMEVisualizer.cs b/Content.Client/GameObjects/Components/Power/AME/AMEVisualizer.cs new file mode 100644 index 0000000000..45104ed27a --- /dev/null +++ b/Content.Client/GameObjects/Components/Power/AME/AMEVisualizer.cs @@ -0,0 +1,63 @@ +using Robust.Client.GameObjects; +using Robust.Client.Interfaces.GameObjects.Components; +using Robust.Shared.Interfaces.GameObjects; +using System; +using System.Collections.Generic; +using System.Text; +using static Content.Shared.GameObjects.Components.Power.AME.SharedAMEShieldComponent; + +namespace Content.Client.GameObjects.Components.Power.AME +{ + public class AMEVisualizer : AppearanceVisualizer + { + public override void InitializeEntity(IEntity entity) + { + base.InitializeEntity(entity); + var sprite = entity.GetComponent(); + sprite.LayerMapSet(Layers.Core, sprite.AddLayerState("core")); + sprite.LayerSetVisible(Layers.Core, false); + sprite.LayerMapSet(Layers.CoreState, sprite.AddLayerState("core_weak")); + sprite.LayerSetVisible(Layers.CoreState, false); + } + + public override void OnChangeData(AppearanceComponent component) + { + base.OnChangeData(component); + var sprite = component.Owner.GetComponent(); + if (component.TryGetData(AMEShieldVisuals.Core, out var core)) + { + if (core == "isCore") + { + sprite.LayerSetState(Layers.Core, "core"); + sprite.LayerSetVisible(Layers.Core, true); + } + else + { + sprite.LayerSetVisible(Layers.Core, false); + } + } + + if (component.TryGetData(AMEShieldVisuals.CoreState, out var coreState)) + switch (coreState) + { + case "weak": + sprite.LayerSetState(Layers.CoreState, "core_weak"); + sprite.LayerSetVisible(Layers.CoreState, true); + break; + case "strong": + sprite.LayerSetState(Layers.CoreState, "core_strong"); + sprite.LayerSetVisible(Layers.CoreState, true); + break; + case "off": + sprite.LayerSetVisible(Layers.CoreState, false); + break; + } + } + } + + enum Layers + { + Core, + CoreState, + } +} diff --git a/Content.Client/GameObjects/Components/Power/AME/AMEWindow.cs b/Content.Client/GameObjects/Components/Power/AME/AMEWindow.cs new file mode 100644 index 0000000000..8a588035ab --- /dev/null +++ b/Content.Client/GameObjects/Components/Power/AME/AMEWindow.cs @@ -0,0 +1,162 @@ +using Content.Client.UserInterface.Stylesheets; +using Robust.Client.UserInterface; +using Robust.Client.UserInterface.Controls; +using Robust.Client.UserInterface.CustomControls; +using Robust.Shared.GameObjects.Components.UserInterface; +using Robust.Shared.IoC; +using Robust.Shared.Localization; +using System; +using System.Collections.Generic; +using System.Text; +using static Content.Shared.GameObjects.Components.Power.AME.SharedAMEControllerComponent; + +namespace Content.Client.GameObjects.Components.Power.AME +{ + public class AMEWindow : SS14Window + { + public Label InjectionStatus { get; set; } + public Button EjectButton { get; set; } + public Button ToggleInjection { get; set; } + public Button IncreaseFuelButton { get; set; } + public Button DecreaseFuelButton { get; set; } + public Button RefreshPartsButton { get; set; } + public ProgressBar FuelMeter { get; set; } + public Label FuelAmount { get; set; } + public Label InjectionAmount { get; set; } + public Label CoreCount { get; set; } + + + public AMEWindow() + { + IoCManager.InjectDependencies(this); + + Title = "Antimatter Control Unit"; + Contents.AddChild(new VBoxContainer + { + Children = + { + new HBoxContainer + { + Children = + { + new Label {Text = Loc.GetString("Engine Status") + ": "}, + (InjectionStatus = new Label {Text = "Not Injecting"}) + } + }, + new HBoxContainer + { + Children = + { + (ToggleInjection = new Button {Text = "Toggle Injection", StyleClasses = {StyleBase.ButtonOpenBoth}, Disabled = true}), + } + }, + new HBoxContainer + { + Children = + { + new Label {Text = Loc.GetString("Fuel Status") + ": "}, + (FuelAmount = new Label {Text = "No fuel inserted"}) + } + }, + new HBoxContainer + { + Children = + { + (EjectButton = new Button {Text = "Eject", StyleClasses = {StyleBase.ButtonOpenBoth}, Disabled = true}), + } + }, + new HBoxContainer + { + Children = + { + new Label {Text = Loc.GetString("Injection amount") + ": "}, + (InjectionAmount = new Label {Text = "0"}) + } + }, + new HBoxContainer + { + Children = + { + (IncreaseFuelButton = new Button {Text = "Increase", StyleClasses = {StyleBase.ButtonOpenRight}}), + (DecreaseFuelButton = new Button {Text = "Decrease", StyleClasses = {StyleBase.ButtonOpenLeft}}), + } + }, + new HBoxContainer + { + Children = + { + (RefreshPartsButton = new Button {Text = "Refresh Parts", StyleClasses = {StyleBase.ButtonOpenBoth }, Disabled = true }), + new Label { Text = Loc.GetString("Core count") + ": "}, + (CoreCount = new Label { Text = "0"}), + } + } + } + }); + + } + + + /// + /// This searches recursively through all the children of "parent" + /// and sets the Disabled value of any buttons found to "val" + /// + /// The control which childrens get searched + /// The value to which disabled gets set + private void SetButtonDisabledRecursive(Control parent, bool val) + { + foreach (var child in parent.Children) + { + if (child is Button but) + { + but.Disabled = val; + continue; + } + + if (child.Children != null) + { + SetButtonDisabledRecursive(child, val); + } + } + } + + /// + /// Update the UI state when new state data is received from the server. + /// + /// State data sent by the server. + public void UpdateState(BoundUserInterfaceState state) + { + var castState = (AMEControllerBoundUserInterfaceState) state; + + // Disable all buttons if not powered + if (Contents.Children != null) + { + SetButtonDisabledRecursive(Contents, !castState.HasPower); + EjectButton.Disabled = false; + } + + if(!castState.HasFuelJar) + { + EjectButton.Disabled = true; + ToggleInjection.Disabled = true; + FuelAmount.Text = Loc.GetString("No fuel inserted"); + } + else + { + EjectButton.Disabled = false; + ToggleInjection.Disabled = false; + FuelAmount.Text = $"{castState.FuelAmount}"; + } + + if(!castState.IsMaster) + { + ToggleInjection.Disabled = true; + } + + RefreshPartsButton.Disabled = castState.Injecting; + + CoreCount.Text = $"{castState.CoreCount}"; + InjectionAmount.Text = $"{castState.InjectionAmount}"; + + } + } +} diff --git a/Content.Client/IgnoredComponents.cs b/Content.Client/IgnoredComponents.cs index 5d3cca4938..9aceb3988d 100644 --- a/Content.Client/IgnoredComponents.cs +++ b/Content.Client/IgnoredComponents.cs @@ -160,6 +160,9 @@ "Metabolism", "AiFactionTag", "PressureProtection", + "AMEPart", + "AMEFuelContainer", + "AMEShield", "DebugPump", "DebugVent", "DebugSiphon", diff --git a/Content.Server/GameObjects/Components/NodeContainer/NodeGroups/AMENodeGroup.cs b/Content.Server/GameObjects/Components/NodeContainer/NodeGroups/AMENodeGroup.cs new file mode 100644 index 0000000000..93fcaae955 --- /dev/null +++ b/Content.Server/GameObjects/Components/NodeContainer/NodeGroups/AMENodeGroup.cs @@ -0,0 +1,152 @@ +using Content.Server.Explosions; +using Content.Server.GameObjects.Components.NodeContainer.Nodes; +using Content.Server.GameObjects.Components.Power.AME; +using Robust.Shared.GameObjects.Components.Transform; +using Robust.Shared.ViewVariables; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Content.Server.GameObjects.Components.NodeContainer.NodeGroups +{ + /// + /// Node group class for handling the Antimatter Engine's console and parts. + /// + [NodeGroup(NodeGroupID.AMEngine)] + public class AMENodeGroup : BaseNodeGroup + { + /// + /// The AME controller which is currently in control of this node group. + /// This could be tracked a few different ways, but this is most convenient, + /// since any part connected to the node group can easily find the master. + /// + [ViewVariables] + private AMEControllerComponent _masterController; + + public AMEControllerComponent MasterController => _masterController; + + private List _cores = new List(); + + public int CoreCount => _cores.Count; + + protected override void OnAddNode(Node node) + { + base.OnAddNode(node); + if (_masterController == null) + { + node.Owner.TryGetComponent(out var controller); + _masterController = controller; + } + } + + protected override void OnRemoveNode(Node node) + { + base.OnRemoveNode(node); + RefreshAMENodes(_masterController); + if (_masterController != null && _masterController?.Owner == node.Owner) { _masterController = null; } + } + + public void RefreshAMENodes(AMEControllerComponent controller) + { + if(_masterController == null && controller != null) + { + _masterController = controller; + } + + if (_cores != null) { + foreach (AMEShieldComponent core in _cores) + { + core.UnsetCore(); + } + _cores.Clear(); + } + + //Check each shield node to see if it meets core criteria + foreach (Node node in Nodes) + { + if (!node.Owner.TryGetComponent(out var shield)) { continue; } + var nodeNeighbors = node.Owner + .GetComponent() + .GetCellsInSquareArea() + .Select(sgc => sgc.Owner) + .Where(entity => entity != node.Owner) + .Select(entity => entity.TryGetComponent(out var adjshield) ? adjshield : null) + .Where(adjshield => adjshield != null); + + if (nodeNeighbors.Count() >= 8) { _cores.Add(shield); } + } + + if (_cores == null) { return; } + + foreach (AMEShieldComponent core in _cores) + { + core.SetCore(); + } + } + + public void UpdateCoreVisuals(int injectionAmount, bool injecting) + { + + var injectionStrength = CoreCount > 0 ? injectionAmount / CoreCount : 0; + + foreach (AMEShieldComponent core in _cores) + { + core.UpdateCoreVisuals(injectionStrength, injecting); + } + } + + public int InjectFuel(int injectionAmount) + { + if(injectionAmount > 0 && CoreCount > 0) + { + var instability = 2 * (injectionAmount / CoreCount); + foreach(AMEShieldComponent core in _cores) + { + core.CoreIntegrity -= instability; + } + return CoreCount * injectionAmount * 15000; //2 core engine injecting 2 fuel per core = 60kW(?) + } + return 0; + } + + public int GetTotalStability() + { + if(CoreCount < 1) { return 100; } + var stability = 0; + + foreach(AMEShieldComponent core in _cores) + { + stability += core.CoreIntegrity; + } + + stability = stability / CoreCount; + + return stability; + } + + public void ExplodeCores() + { + if(_cores.Count < 1 || MasterController == null) { return; } + + var intensity = 0; + + /* + * todo: add an exact to the shielding and make this find the core closest to the controller + * so they chain explode, after helpers have been added to make it not cancer + */ + var epicenter = _cores.First(); + + foreach (AMEShieldComponent core in _cores) + { + intensity += MasterController.InjectionAmount; + } + + intensity = Math.Min(intensity, 8); + + ExplosionHelper.SpawnExplosion(epicenter.Owner.Transform.GridPosition, intensity / 2, intensity, intensity * 2, intensity * 3); + + } + + } +} diff --git a/Content.Server/GameObjects/Components/NodeContainer/NodeGroups/NodeGroupFactory.cs b/Content.Server/GameObjects/Components/NodeContainer/NodeGroups/NodeGroupFactory.cs index 2133f67134..557035524f 100644 --- a/Content.Server/GameObjects/Components/NodeContainer/NodeGroups/NodeGroupFactory.cs +++ b/Content.Server/GameObjects/Components/NodeContainer/NodeGroups/NodeGroupFactory.cs @@ -62,6 +62,7 @@ namespace Content.Server.GameObjects.Components.NodeContainer.NodeGroups HVPower, MVPower, Apc, + AMEngine, Pipe, } } diff --git a/Content.Server/GameObjects/Components/Power/AME/AMEControllerComponent.cs b/Content.Server/GameObjects/Components/Power/AME/AMEControllerComponent.cs new file mode 100644 index 0000000000..92ab6732fd --- /dev/null +++ b/Content.Server/GameObjects/Components/Power/AME/AMEControllerComponent.cs @@ -0,0 +1,369 @@ +#nullable enable +using Content.Server.GameObjects.Components.GUI; +using Content.Server.GameObjects.Components.Items.Storage; +using Content.Server.GameObjects.Components.NodeContainer; +using Content.Server.GameObjects.Components.NodeContainer.NodeGroups; +using Content.Server.GameObjects.Components.NodeContainer.Nodes; +using Content.Server.GameObjects.Components.Power.ApcNetComponents; +using Content.Server.GameObjects.Components.Power.PowerNetComponents; +using Content.Server.Interfaces; +using Content.Server.Interfaces.GameObjects.Components.Items; +using Content.Server.Utility; +using Content.Shared.GameObjects.Components.Power.AME; +using Content.Shared.GameObjects.EntitySystems; +using Content.Shared.Interfaces.GameObjects.Components; +using Microsoft.EntityFrameworkCore.Internal; +using Robust.Server.GameObjects; +using Robust.Server.GameObjects.Components.Container; +using Robust.Server.GameObjects.Components.UserInterface; +using Robust.Server.GameObjects.EntitySystems; +using Robust.Server.Interfaces.GameObjects; +using Robust.Shared.Audio; +using Robust.Shared.GameObjects; +using Robust.Shared.GameObjects.Components.Transform; +using Robust.Shared.GameObjects.Systems; +using Robust.Shared.Interfaces.GameObjects; +using Robust.Shared.Interfaces.GameObjects.Components; +using Robust.Shared.IoC; +using Robust.Shared.Localization; +using Robust.Shared.ViewVariables; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Content.Server.GameObjects.Components.Power.AME +{ + [RegisterComponent] + [ComponentReference(typeof(IActivate))] + [ComponentReference(typeof(IInteractUsing))] + public class AMEControllerComponent : SharedAMEControllerComponent, IActivate, IInteractUsing + { + [Dependency] private readonly IServerNotifyManager _notifyManager = default!; + + [ViewVariables] private BoundUserInterface? UserInterface => Owner.GetUIOrNull(AMEControllerUiKey.Key); + [ViewVariables] private bool _injecting; + [ViewVariables] public int InjectionAmount; + + private AppearanceComponent? _appearance; + private PowerSupplierComponent? _powerSupplier; + + private bool Powered => !Owner.TryGetComponent(out PowerReceiverComponent? receiver) || receiver.Powered; + + [ViewVariables] + private int _stability = 100; + + private ContainerSlot _jarSlot = default!; + [ViewVariables] private bool HasJar => _jarSlot.ContainedEntity != null; + + public override void Initialize() + { + base.Initialize(); + + if (UserInterface != null) + { + UserInterface.OnReceiveMessage += OnUiReceiveMessage; + } + + Owner.TryGetComponent(out _appearance); + + if (Owner.TryGetComponent(out PowerReceiverComponent? receiver)) + { + receiver.OnPowerStateChanged += OnPowerChanged; + } + + Owner.TryGetComponent(out _powerSupplier); + + _injecting = false; + InjectionAmount = 2; + _jarSlot = ContainerManagerComponent.Ensure($"{Name}-fuelJarContainer", Owner); + } + + internal void OnUpdate(float frameTime) + { + if(!_injecting) + { + return; + } + + _jarSlot.ContainedEntity.TryGetComponent(out var fuelJar); + if(fuelJar != null && _powerSupplier != null && fuelJar.FuelAmount > InjectionAmount) + { + _powerSupplier.SupplyRate = GetAMENodeGroup().InjectFuel(InjectionAmount); + fuelJar.FuelAmount -= InjectionAmount; + InjectSound(); + UpdateUserInterface(); + } + + _stability = GetAMENodeGroup().GetTotalStability(); + + UpdateDisplay(_stability); + + if(_stability <= 0) { GetAMENodeGroup().ExplodeCores(); } + + } + + /// + /// Called when you click the owner entity with an empty hand. Opens the UI client-side if possible. + /// + /// Data relevant to the event such as the actor which triggered it. + void IActivate.Activate(ActivateEventArgs args) + { + if (!args.User.TryGetComponent(out IActorComponent? actor)) + { + return; + } + + if (!args.User.TryGetComponent(out IHandsComponent? hands)) + { + _notifyManager.PopupMessage(Owner.Transform.GridPosition, args.User, + Loc.GetString("You have no hands.")); + return; + } + + var activeHandEntity = hands.GetActiveHand?.Owner; + if (activeHandEntity == null) + { + UserInterface?.Open(actor.playerSession); + } + } + + private void OnPowerChanged(object? sender, PowerStateEventArgs e) + { + UpdateUserInterface(); + } + + private AMEControllerBoundUserInterfaceState GetUserInterfaceState() + { + var jar = _jarSlot.ContainedEntity; + if (jar == null) + { + return new AMEControllerBoundUserInterfaceState(Powered, IsMasterController(), false, HasJar, 0, InjectionAmount, GetCoreCount()); + } + + var jarcomponent = jar.GetComponent(); + return new AMEControllerBoundUserInterfaceState(Powered, IsMasterController(), _injecting, HasJar, jarcomponent.FuelAmount, InjectionAmount, GetCoreCount()); + } + + /// + /// Checks whether the player entity is able to use the controller. + /// + /// The player entity. + /// Returns true if the entity can use the controller, and false if it cannot. + private bool PlayerCanUseController(IEntity playerEntity, bool needsPower = true) + { + //Need player entity to check if they are still able to use the dispenser + if (playerEntity == null) + return false; + //Check if player can interact in their current state + if (!ActionBlockerSystem.CanInteract(playerEntity) || !ActionBlockerSystem.CanUse(playerEntity)) + return false; + //Check if device is powered + if (needsPower && !Powered) + return false; + + return true; + } + + private void UpdateUserInterface() + { + var state = GetUserInterfaceState(); + UserInterface?.SetState(state); + } + + /// + /// Handles ui messages from the client. For things such as button presses + /// which interact with the world and require server action. + /// + /// A user interface message from the client. + private void OnUiReceiveMessage(ServerBoundUserInterfaceMessage obj) + { + if (obj.Session.AttachedEntity == null) + { + return; + } + + var msg = (UiButtonPressedMessage) obj.Message; + var needsPower = msg.Button switch + { + UiButton.Eject => false, + _ => true, + }; + + if (!PlayerCanUseController(obj.Session.AttachedEntity, needsPower)) + return; + + switch (msg.Button) + { + case UiButton.Eject: + TryEject(obj.Session.AttachedEntity); + break; + case UiButton.ToggleInjection: + ToggleInjection(); + break; + case UiButton.IncreaseFuel: + InjectionAmount += 2; + break; + case UiButton.DecreaseFuel: + InjectionAmount = InjectionAmount > 0 ? InjectionAmount -= 2 : 0; + break; + case UiButton.RefreshParts: + RefreshParts(); + break; + } + + GetAMENodeGroup().UpdateCoreVisuals(InjectionAmount, _injecting); + + UpdateUserInterface(); + ClickSound(); + } + + private void TryEject(IEntity user) + { + if (!HasJar || _injecting) + return; + + var jar = _jarSlot.ContainedEntity; + _jarSlot.Remove(_jarSlot.ContainedEntity); + UpdateUserInterface(); + + if (!user.TryGetComponent(out var hands) || !jar.TryGetComponent(out var item)) + return; + if (hands.CanPutInHand(item)) + hands.PutInHand(item); + } + + private void ToggleInjection() + { + if (!_injecting) + { + _appearance?.SetData(AMEControllerVisuals.DisplayState, "on"); + } + else + { + _appearance?.SetData(AMEControllerVisuals.DisplayState, "off"); + if (_powerSupplier != null) + { + _powerSupplier.SupplyRate = 0; + } + } + _injecting = !_injecting; + UpdateUserInterface(); + } + + + private void UpdateDisplay(int stability) + { + if(_appearance == null) { return; } + + _appearance.TryGetData(AMEControllerVisuals.DisplayState, out var state); + + var newState = "on"; + if (stability < 50) { newState = "critical"; } + if (stability < 10) { newState = "fuck"; } + + if (state != newState) + { + _appearance?.SetData(AMEControllerVisuals.DisplayState, newState); + } + + } + + private void RefreshParts() + { + GetAMENodeGroup().RefreshAMENodes(this); + UpdateUserInterface(); + } + + private AMENodeGroup GetAMENodeGroup() + { + Owner.TryGetComponent(out NodeContainerComponent? nodeContainer); + + var engineNodeGroup = nodeContainer?.Nodes + .Select(node => node.NodeGroup) + .OfType() + .First(); + + return engineNodeGroup ?? default!; + } + + private bool IsMasterController() + { + if(GetAMENodeGroup().MasterController == this) + { + return true; + } + + return false; + } + + private int GetCoreCount() + { + var coreCount = 0; + + if(GetAMENodeGroup() != null) + { + coreCount = GetAMENodeGroup().CoreCount; + } + + return coreCount; + } + + + private void ClickSound() + { + + EntitySystem.Get().PlayFromEntity("/Audio/Machines/machine_switch.ogg", Owner, AudioParams.Default.WithVolume(-2f)); + + } + + private void InjectSound() + { + EntitySystem.Get().PlayFromEntity("/Audio/Effects/bang.ogg", Owner, AudioParams.Default.WithVolume(0f)); + } + + async Task IInteractUsing.InteractUsing(InteractUsingEventArgs args) + { + if (!args.User.TryGetComponent(out IHandsComponent? hands)) + { + _notifyManager.PopupMessage(Owner.Transform.GridPosition, args.User, + Loc.GetString("You have no hands.")); + return true; + } + + if (hands.GetActiveHand == null) + { + _notifyManager.PopupMessage(Owner.Transform.GridPosition, args.User, + Loc.GetString("You have nothing on your hand.")); + return false; + } + + var activeHandEntity = hands.GetActiveHand.Owner; + if (activeHandEntity.TryGetComponent(out var fuelContainer)) + { + if (HasJar) + { + _notifyManager.PopupMessage(Owner.Transform.GridPosition, args.User, + Loc.GetString("The controller already has a jar loaded.")); + } + + else + { + _jarSlot.Insert(activeHandEntity); + _notifyManager.PopupMessage(Owner.Transform.GridPosition, args.User, + Loc.GetString("You insert the jar into the fuel slot.")); + UpdateUserInterface(); + } + } + else + { + _notifyManager.PopupMessage(Owner.Transform.GridPosition, args.User, + Loc.GetString("You can't put that in the controller...")); + } + + return true; + } + } + +} diff --git a/Content.Server/GameObjects/Components/Power/AME/AMEFuelContainerComponent.cs b/Content.Server/GameObjects/Components/Power/AME/AMEFuelContainerComponent.cs new file mode 100644 index 0000000000..af88584187 --- /dev/null +++ b/Content.Server/GameObjects/Components/Power/AME/AMEFuelContainerComponent.cs @@ -0,0 +1,45 @@ +using Robust.Shared.GameObjects; +using Robust.Shared.ViewVariables; +using System; +using System.Collections.Generic; +using System.Text; + +namespace Content.Server.GameObjects.Components.Power.AME +{ + [RegisterComponent] + public class AMEFuelContainerComponent : Component + { + public override string Name => "AMEFuelContainer"; + + private int _fuelAmount; + private int _maxFuelAmount; + + /// + /// The amount of fuel in the jar. + /// + [ViewVariables(VVAccess.ReadWrite)] + public int FuelAmount + { + get => _fuelAmount; + set => _fuelAmount = value; + } + + /// + /// The maximum fuel capacity of the jar. + /// + [ViewVariables(VVAccess.ReadWrite)] + public int MaxFuelAmount + { + get => _maxFuelAmount; + set => _maxFuelAmount = value; + } + + public override void Initialize() + { + base.Initialize(); + _maxFuelAmount = 1000; + _fuelAmount = 1000; + } + + } +} diff --git a/Content.Server/GameObjects/Components/Power/AME/AMEPartComponent.cs b/Content.Server/GameObjects/Components/Power/AME/AMEPartComponent.cs new file mode 100644 index 0000000000..45d951d203 --- /dev/null +++ b/Content.Server/GameObjects/Components/Power/AME/AMEPartComponent.cs @@ -0,0 +1,51 @@ +using Content.Server.GameObjects.Components.Interactable; +using Content.Server.Interfaces; +using Content.Server.Interfaces.GameObjects.Components.Items; +using Content.Shared.GameObjects.Components.Interactable; +using Content.Shared.Interfaces.GameObjects.Components; +using Robust.Server.Interfaces.GameObjects; +using Robust.Shared.GameObjects; +using Robust.Shared.GameObjects.Components.Transform; +using Robust.Shared.Interfaces.Map; +using Robust.Shared.IoC; +using Robust.Shared.Localization; +using System.Threading.Tasks; + +namespace Content.Server.GameObjects.Components.Power.AME +{ + [RegisterComponent] + [ComponentReference(typeof(IInteractUsing))] + public class AMEPartComponent : Component, IInteractUsing + { + [Dependency] private readonly IMapManager _mapManager = default!; + [Dependency] private readonly IServerEntityManager _serverEntityManager = default!; + [Dependency] private readonly IServerNotifyManager _notifyManager = default!; + public override string Name => "AMEPart"; + + async Task IInteractUsing.InteractUsing(InteractUsingEventArgs args) + { + if (!args.User.TryGetComponent(out IHandsComponent hands)) + { + _notifyManager.PopupMessage(Owner.Transform.GridPosition, args.User, + Loc.GetString("You have no hands.")); + return true; + } + + var activeHandEntity = hands.GetActiveHand.Owner; + if (activeHandEntity.TryGetComponent(out var multitool) && multitool.Qualities == ToolQuality.Multitool) + { + + var mapGrid = _mapManager.GetGrid(args.ClickLocation.GridID); + var tile = mapGrid.GetTileRef(args.ClickLocation); + var snapPos = mapGrid.SnapGridCellFor(args.ClickLocation, SnapGridOffset.Center); + + var ent = _serverEntityManager.SpawnEntity("AMEShielding", mapGrid.GridTileToLocal(snapPos)); + ent.Transform.LocalRotation = Owner.Transform.LocalRotation; + + Owner.Delete(); + } + + return true; + } + } +} diff --git a/Content.Server/GameObjects/Components/Power/AME/AMEShieldComponent.cs b/Content.Server/GameObjects/Components/Power/AME/AMEShieldComponent.cs new file mode 100644 index 0000000000..7ae88049df --- /dev/null +++ b/Content.Server/GameObjects/Components/Power/AME/AMEShieldComponent.cs @@ -0,0 +1,73 @@ +#nullable enable +using Content.Shared.GameObjects.Components.Power.AME; +using Robust.Server.GameObjects; +using Robust.Shared.GameObjects; +using Robust.Shared.ViewVariables; +using System; +using System.Collections.Generic; +using System.Text; + +namespace Content.Server.GameObjects.Components.Power.AME +{ + [RegisterComponent] + public class AMEShieldComponent : SharedAMEShieldComponent + { + + private bool _isCore = false; + + [ViewVariables] + public int CoreIntegrity = 100; + + private AppearanceComponent? _appearance; + private PointLightComponent? _pointLight; + + public override void Initialize() + { + base.Initialize(); + Owner.TryGetComponent(out _appearance); + Owner.TryGetComponent(out _pointLight); + } + + internal void OnUpdate(float frameTime) + { + throw new NotImplementedException(); + } + + public void SetCore() + { + if(_isCore) { return; } + _isCore = true; + _appearance?.SetData(AMEShieldVisuals.Core, "isCore"); + } + + public void UnsetCore() + { + _isCore = false; + _appearance?.SetData(AMEShieldVisuals.Core, "isNotCore"); + } + + public void UpdateCoreVisuals(int injectionStrength, bool injecting) + { + if (!injecting) + { + _appearance?.SetData(AMEShieldVisuals.CoreState, "off"); + if (_pointLight != null) { _pointLight.Enabled = false; } + return; + } + + if (_pointLight != null) + { + _pointLight.Radius = Math.Clamp(injectionStrength, 1, 12); + _pointLight.Enabled = true; + } + + if (injectionStrength > 2) + { + _appearance?.SetData(AMEShieldVisuals.CoreState, "strong"); + return; + } + + _appearance?.SetData(AMEShieldVisuals.CoreState, "weak"); + } + } +} diff --git a/Content.Server/GameObjects/EntitySystems/AntimatterEngineSystem.cs b/Content.Server/GameObjects/EntitySystems/AntimatterEngineSystem.cs new file mode 100644 index 0000000000..0b29c0f3e7 --- /dev/null +++ b/Content.Server/GameObjects/EntitySystems/AntimatterEngineSystem.cs @@ -0,0 +1,32 @@ +using Content.Server.GameObjects.Components.Power.AME; +using JetBrains.Annotations; +using Robust.Shared.GameObjects.Systems; + +namespace Content.Server.GameObjects.EntitySystems +{ + [UsedImplicitly] + public class AntimatterEngineSystem : EntitySystem + { + private float _accumulatedFrameTime; + + public override void Initialize() + { + base.Initialize(); + } + + public override void Update(float frameTime) + { + base.Update(frameTime); + _accumulatedFrameTime += frameTime; + if (_accumulatedFrameTime >= 10) + { + foreach (var comp in ComponentManager.EntityQuery()) + { + comp.OnUpdate(frameTime); + } + _accumulatedFrameTime -= 10; + } + + } + } +} diff --git a/Content.Shared/GameObjects/Components/Power/AME/SharedAMEControllerComponent.cs b/Content.Shared/GameObjects/Components/Power/AME/SharedAMEControllerComponent.cs new file mode 100644 index 0000000000..e89789e363 --- /dev/null +++ b/Content.Shared/GameObjects/Components/Power/AME/SharedAMEControllerComponent.cs @@ -0,0 +1,69 @@ +using Robust.Shared.GameObjects; +using Robust.Shared.GameObjects.Components.UserInterface; +using Robust.Shared.Serialization; +using System; +using System.Collections.Generic; +using System.Text; + +namespace Content.Shared.GameObjects.Components.Power.AME +{ + public class SharedAMEControllerComponent : Component + { + public override string Name => "AMEController"; + + [Serializable, NetSerializable] + public class AMEControllerBoundUserInterfaceState : BoundUserInterfaceState + { + public readonly bool HasPower; + public readonly bool IsMaster; + public readonly bool Injecting; + public readonly bool HasFuelJar; + public readonly int FuelAmount; + public readonly int InjectionAmount; + public readonly int CoreCount; + + public AMEControllerBoundUserInterfaceState(bool hasPower, bool isMaster, bool injecting, bool hasFuelJar, int fuelAmount, int injectionAmount, int coreCount) + { + HasPower = hasPower; + IsMaster = isMaster; + Injecting = injecting; + HasFuelJar = hasFuelJar; + FuelAmount = fuelAmount; + InjectionAmount = injectionAmount; + CoreCount = coreCount; + } + } + + [Serializable, NetSerializable] + public class UiButtonPressedMessage : BoundUserInterfaceMessage + { + public readonly UiButton Button; + + public UiButtonPressedMessage(UiButton button) + { + Button = button; + } + } + + [Serializable, NetSerializable] + public enum AMEControllerUiKey + { + Key + } + + public enum UiButton + { + Eject, + ToggleInjection, + IncreaseFuel, + DecreaseFuel, + RefreshParts + } + + [Serializable, NetSerializable] + public enum AMEControllerVisuals + { + DisplayState, + } + } +} diff --git a/Content.Shared/GameObjects/Components/Power/AME/SharedAMEShieldComponent.cs b/Content.Shared/GameObjects/Components/Power/AME/SharedAMEShieldComponent.cs new file mode 100644 index 0000000000..f9af4d12ac --- /dev/null +++ b/Content.Shared/GameObjects/Components/Power/AME/SharedAMEShieldComponent.cs @@ -0,0 +1,27 @@ +using Robust.Shared.GameObjects; +using Robust.Shared.Serialization; +using System; +using System.Collections.Generic; +using System.Text; + +namespace Content.Shared.GameObjects.Components.Power.AME +{ + public class SharedAMEShieldComponent : Component + { + public override string Name => "AMEShield"; + + [Serializable, NetSerializable] + public enum AMEShieldVisuals + { + Core, + CoreState + } + + public enum AMECoreState + { + Off, + Weak, + Strong + } + } +} diff --git a/Resources/Prototypes/Entities/Constructible/Power/AME/ame_controller.yml b/Resources/Prototypes/Entities/Constructible/Power/AME/ame_controller.yml new file mode 100644 index 0000000000..53c4c42f14 --- /dev/null +++ b/Resources/Prototypes/Entities/Constructible/Power/AME/ame_controller.yml @@ -0,0 +1,44 @@ +- type: entity + id: AMEController + name: AME Controller + placement: + mode: SnapgridCenter + components: + - type: Clickable + - type: Icon + sprite: Constructible/Power/ame_controller.rsi + state: control + - type: Sprite + sprite: Constructible/Power/ame_controller.rsi + state: control + - type: Collidable + shapes: + - !type:PhysShapeAabb + layer: + - Opaque + - Impassable + - MobImpassable + - VaultImpassable + - SmallImpassable + - type: Destructible + maxHP: 500 + - type: SnapGrid + offset: Center + - type: Anchorable + - type: AMEController + - type: UserInterface + interfaces: + - key: enum.AMEControllerUiKey.Key + type: AMEControllerBoundUserInterface + - type: Appearance + visuals: + - type: AMEControllerVisualizer + - type: NodeContainer + nodes: + - !type:AdjacentNode + nodeGroupID: AMEngine + - !type:AdjacentNode + nodeGroupID: HVPower + - type: PowerReceiver + - type: PowerSupplier + supplyRate: 0 \ No newline at end of file diff --git a/Resources/Prototypes/Entities/Constructible/Power/AME/ame_structure.yml b/Resources/Prototypes/Entities/Constructible/Power/AME/ame_structure.yml new file mode 100644 index 0000000000..93c9b23a5f --- /dev/null +++ b/Resources/Prototypes/Entities/Constructible/Power/AME/ame_structure.yml @@ -0,0 +1,46 @@ +- type: entity + id: AMEShielding + name: AME shielding + description: Keeps the antimatter in and the matter out. + placement: + mode: SnapgridCenter + components: + - type: Clickable + - type: Sprite + drawdepth: Walls + sprite: Constructible/Power/ame_shielding.rsi + state: shield_0 + - type: Icon + texture: Constructible/Power/ame_shielding_base.png + - type: Collidable + shapes: + - !type:PhysShapeAabb + layer: + - Opaque + - Impassable + - MobImpassable + - VaultImpassable + - SmallImpassable + - type: Destructible + maxHP: 500 + spawnondestroy: AMEPart + - type: SnapGrid + offset: Center + - type: Airtight + - type: IconSmooth + mode: CardinalFlags + base: shield_ + key: ame_shield + - type: AMEShield + - type: NodeContainer + nodes: + - !type:AdjacentNode + nodeGroupID: AMEngine + - type: PointLight + enabled: false + radius: 5 + energy: 0.5 + color: "#00AAFF" + - type: Appearance + visuals: + - type: AMEVisualizer \ No newline at end of file diff --git a/Resources/Prototypes/Entities/Objects/Power/antimatter_jar.yml b/Resources/Prototypes/Entities/Objects/Power/antimatter_jar.yml new file mode 100644 index 0000000000..37c7d7f639 --- /dev/null +++ b/Resources/Prototypes/Entities/Objects/Power/antimatter_jar.yml @@ -0,0 +1,16 @@ +- type: entity + id: AMEJar + name: Antimatter Fuel Jar + parent: BaseItem + description: A hermetically sealed jar containing antimatter for use in an antimatter reactor. + components: + - type: Item + size: 5 + sprite: Objects/Power/AME/ame_jar.rsi + - type: Sprite + sprite: Objects/Power/AME/ame_jar.rsi + state: jar + - type: Icon + sprite: Objects/Power/AME/ame_jar.rsi + state: jar + - type: AMEFuelContainer \ No newline at end of file diff --git a/Resources/Prototypes/Entities/Objects/Power/antimatter_part.yml b/Resources/Prototypes/Entities/Objects/Power/antimatter_part.yml new file mode 100644 index 0000000000..2c17c51179 --- /dev/null +++ b/Resources/Prototypes/Entities/Objects/Power/antimatter_part.yml @@ -0,0 +1,16 @@ +- type: entity + id: AMEPart + name: Antimatter Engine Part + parent: BaseItem + description: "A flatpack used for constructing an antimatter engine reactor.\nUse a multitool to unpack it." + components: + - type: Item + size: 5 + sprite: Objects/Power/AME/ame_part.rsi + - type: Sprite + sprite: Objects/Power/AME/ame_part.rsi + state: box + - type: Icon + sprite: Objects/Power/AME/ame_part.rsi + state: box + - type: AMEPart \ No newline at end of file diff --git a/Resources/Textures/Constructible/Power/ame_controller.rsi/control.png b/Resources/Textures/Constructible/Power/ame_controller.rsi/control.png new file mode 100644 index 0000000000..5f2255983d Binary files /dev/null and b/Resources/Textures/Constructible/Power/ame_controller.rsi/control.png differ diff --git a/Resources/Textures/Constructible/Power/ame_controller.rsi/control_critical.png b/Resources/Textures/Constructible/Power/ame_controller.rsi/control_critical.png new file mode 100644 index 0000000000..24de7e92b3 Binary files /dev/null and b/Resources/Textures/Constructible/Power/ame_controller.rsi/control_critical.png differ diff --git a/Resources/Textures/Constructible/Power/ame_controller.rsi/control_fuck.png b/Resources/Textures/Constructible/Power/ame_controller.rsi/control_fuck.png new file mode 100644 index 0000000000..895ca15c49 Binary files /dev/null and b/Resources/Textures/Constructible/Power/ame_controller.rsi/control_fuck.png differ diff --git a/Resources/Textures/Constructible/Power/ame_controller.rsi/control_on.png b/Resources/Textures/Constructible/Power/ame_controller.rsi/control_on.png new file mode 100644 index 0000000000..3bfda8869c Binary files /dev/null and b/Resources/Textures/Constructible/Power/ame_controller.rsi/control_on.png differ diff --git a/Resources/Textures/Constructible/Power/ame_controller.rsi/meta.json b/Resources/Textures/Constructible/Power/ame_controller.rsi/meta.json new file mode 100644 index 0000000000..6bf6b7f12e --- /dev/null +++ b/Resources/Textures/Constructible/Power/ame_controller.rsi/meta.json @@ -0,0 +1,120 @@ +{ + "version": 1, + "size": { + "x": 32, + "y": 32 + }, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from https://github.com/vgstation-coders/vgstation13/blob/Bleeding-Edge/icons/obj/machines/new_ame.dmi at 1b7952787c06c21ef1623e494dcfe7cb1f46e041", + "states": [ + { + "name": "control", + "directions": 1, + "delays": [ + [ + 1.0 + ] + ] + }, + { + "name": "control_critical", + "directions": 1, + "delays": [ + [ + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1 + ] + ] + }, + { + "name": "control_fuck", + "directions": 1, + "delays": [ + [ + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1 + ] + ] + }, + { + "name": "control_on", + "directions": 1, + "delays": [ + [ + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1 + ] + ] + } + ] +} \ No newline at end of file diff --git a/Resources/Textures/Constructible/Power/ame_shielding.rsi/core.png b/Resources/Textures/Constructible/Power/ame_shielding.rsi/core.png new file mode 100644 index 0000000000..36c0349b82 Binary files /dev/null and b/Resources/Textures/Constructible/Power/ame_shielding.rsi/core.png differ diff --git a/Resources/Textures/Constructible/Power/ame_shielding.rsi/core_strong.png b/Resources/Textures/Constructible/Power/ame_shielding.rsi/core_strong.png new file mode 100644 index 0000000000..a6a1f109d4 Binary files /dev/null and b/Resources/Textures/Constructible/Power/ame_shielding.rsi/core_strong.png differ diff --git a/Resources/Textures/Constructible/Power/ame_shielding.rsi/core_weak.png b/Resources/Textures/Constructible/Power/ame_shielding.rsi/core_weak.png new file mode 100644 index 0000000000..a8cc73bb9c Binary files /dev/null and b/Resources/Textures/Constructible/Power/ame_shielding.rsi/core_weak.png differ diff --git a/Resources/Textures/Constructible/Power/ame_shielding.rsi/meta.json b/Resources/Textures/Constructible/Power/ame_shielding.rsi/meta.json new file mode 100644 index 0000000000..1ce0d8402b --- /dev/null +++ b/Resources/Textures/Constructible/Power/ame_shielding.rsi/meta.json @@ -0,0 +1,192 @@ +{ + "version": 1, + "size": { + "x": 32, + "y": 32 + }, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from https://github.com/vgstation-coders/vgstation13/blob/Bleeding-Edge/icons/obj/machines/new_ame.dmi at 1b7952787c06c21ef1623e494dcfe7cb1f46e041", + "states": [ + { + "name": "shield_0", + "directions": 1, + "delays": [ + [ + 1.0 + ] + ] + }, + { + "name": "shield_1", + "directions": 1, + "delays": [ + [ + 1.0 + ] + ] + }, + { + "name": "shield_10", + "directions": 1, + "delays": [ + [ + 1.0 + ] + ] + }, + { + "name": "shield_11", + "directions": 1, + "delays": [ + [ + 1.0 + ] + ] + }, + { + "name": "shield_12", + "directions": 1, + "delays": [ + [ + 1.0 + ] + ] + }, + { + "name": "shield_13", + "directions": 1, + "delays": [ + [ + 1.0 + ] + ] + }, + { + "name": "shield_14", + "directions": 1, + "delays": [ + [ + 1.0 + ] + ] + }, + { + "name": "shield_15", + "directions": 1, + "delays": [ + [ + 1.0 + ] + ] + }, + { + "name": "shield_2", + "directions": 1, + "delays": [ + [ + 1.0 + ] + ] + }, + { + "name": "shield_3", + "directions": 1, + "delays": [ + [ + 1.0 + ] + ] + }, + { + "name": "shield_4", + "directions": 1, + "delays": [ + [ + 1.0 + ] + ] + }, + { + "name": "shield_5", + "directions": 1, + "delays": [ + [ + 1.0 + ] + ] + }, + { + "name": "shield_6", + "directions": 1, + "delays": [ + [ + 1.0 + ] + ] + }, + { + "name": "shield_7", + "directions": 1, + "delays": [ + [ + 1.0 + ] + ] + }, + { + "name": "shield_8", + "directions": 1, + "delays": [ + [ + 1.0 + ] + ] + }, + { + "name": "core", + "directions": 1, + "delays": [ + [ + 1.0 + ] + ] + }, + { + "name": "shield_9", + "directions": 1, + "delays": [ + [ + 1.0 + ] + ] + }, + { + "name": "core_weak", + "directions": 1, + "delays": [ + [ + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1 + ] + ] + }, + { + "name": "core_strong", + "directions": 1, + "delays": [ + [ + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1 + ] + ] + } + ] +} \ No newline at end of file diff --git a/Resources/Textures/Constructible/Power/ame_shielding.rsi/shield_0.png b/Resources/Textures/Constructible/Power/ame_shielding.rsi/shield_0.png new file mode 100644 index 0000000000..cd62067877 Binary files /dev/null and b/Resources/Textures/Constructible/Power/ame_shielding.rsi/shield_0.png differ diff --git a/Resources/Textures/Constructible/Power/ame_shielding.rsi/shield_1.png b/Resources/Textures/Constructible/Power/ame_shielding.rsi/shield_1.png new file mode 100644 index 0000000000..4fa79f44d4 Binary files /dev/null and b/Resources/Textures/Constructible/Power/ame_shielding.rsi/shield_1.png differ diff --git a/Resources/Textures/Constructible/Power/ame_shielding.rsi/shield_10.png b/Resources/Textures/Constructible/Power/ame_shielding.rsi/shield_10.png new file mode 100644 index 0000000000..8c6ab600e7 Binary files /dev/null and b/Resources/Textures/Constructible/Power/ame_shielding.rsi/shield_10.png differ diff --git a/Resources/Textures/Constructible/Power/ame_shielding.rsi/shield_11.png b/Resources/Textures/Constructible/Power/ame_shielding.rsi/shield_11.png new file mode 100644 index 0000000000..155f3ca3ec Binary files /dev/null and b/Resources/Textures/Constructible/Power/ame_shielding.rsi/shield_11.png differ diff --git a/Resources/Textures/Constructible/Power/ame_shielding.rsi/shield_12.png b/Resources/Textures/Constructible/Power/ame_shielding.rsi/shield_12.png new file mode 100644 index 0000000000..87a8784187 Binary files /dev/null and b/Resources/Textures/Constructible/Power/ame_shielding.rsi/shield_12.png differ diff --git a/Resources/Textures/Constructible/Power/ame_shielding.rsi/shield_13.png b/Resources/Textures/Constructible/Power/ame_shielding.rsi/shield_13.png new file mode 100644 index 0000000000..fe6f214f17 Binary files /dev/null and b/Resources/Textures/Constructible/Power/ame_shielding.rsi/shield_13.png differ diff --git a/Resources/Textures/Constructible/Power/ame_shielding.rsi/shield_14.png b/Resources/Textures/Constructible/Power/ame_shielding.rsi/shield_14.png new file mode 100644 index 0000000000..6fad2a5c92 Binary files /dev/null and b/Resources/Textures/Constructible/Power/ame_shielding.rsi/shield_14.png differ diff --git a/Resources/Textures/Constructible/Power/ame_shielding.rsi/shield_15.png b/Resources/Textures/Constructible/Power/ame_shielding.rsi/shield_15.png new file mode 100644 index 0000000000..cd62067877 Binary files /dev/null and b/Resources/Textures/Constructible/Power/ame_shielding.rsi/shield_15.png differ diff --git a/Resources/Textures/Constructible/Power/ame_shielding.rsi/shield_2.png b/Resources/Textures/Constructible/Power/ame_shielding.rsi/shield_2.png new file mode 100644 index 0000000000..7c558be6d1 Binary files /dev/null and b/Resources/Textures/Constructible/Power/ame_shielding.rsi/shield_2.png differ diff --git a/Resources/Textures/Constructible/Power/ame_shielding.rsi/shield_3.png b/Resources/Textures/Constructible/Power/ame_shielding.rsi/shield_3.png new file mode 100644 index 0000000000..54c89f787a Binary files /dev/null and b/Resources/Textures/Constructible/Power/ame_shielding.rsi/shield_3.png differ diff --git a/Resources/Textures/Constructible/Power/ame_shielding.rsi/shield_4.png b/Resources/Textures/Constructible/Power/ame_shielding.rsi/shield_4.png new file mode 100644 index 0000000000..e9b362b9a4 Binary files /dev/null and b/Resources/Textures/Constructible/Power/ame_shielding.rsi/shield_4.png differ diff --git a/Resources/Textures/Constructible/Power/ame_shielding.rsi/shield_5.png b/Resources/Textures/Constructible/Power/ame_shielding.rsi/shield_5.png new file mode 100644 index 0000000000..ac07397a5d Binary files /dev/null and b/Resources/Textures/Constructible/Power/ame_shielding.rsi/shield_5.png differ diff --git a/Resources/Textures/Constructible/Power/ame_shielding.rsi/shield_6.png b/Resources/Textures/Constructible/Power/ame_shielding.rsi/shield_6.png new file mode 100644 index 0000000000..960673f636 Binary files /dev/null and b/Resources/Textures/Constructible/Power/ame_shielding.rsi/shield_6.png differ diff --git a/Resources/Textures/Constructible/Power/ame_shielding.rsi/shield_7.png b/Resources/Textures/Constructible/Power/ame_shielding.rsi/shield_7.png new file mode 100644 index 0000000000..3a6884eb29 Binary files /dev/null and b/Resources/Textures/Constructible/Power/ame_shielding.rsi/shield_7.png differ diff --git a/Resources/Textures/Constructible/Power/ame_shielding.rsi/shield_8.png b/Resources/Textures/Constructible/Power/ame_shielding.rsi/shield_8.png new file mode 100644 index 0000000000..e91dd03b1b Binary files /dev/null and b/Resources/Textures/Constructible/Power/ame_shielding.rsi/shield_8.png differ diff --git a/Resources/Textures/Constructible/Power/ame_shielding.rsi/shield_9.png b/Resources/Textures/Constructible/Power/ame_shielding.rsi/shield_9.png new file mode 100644 index 0000000000..9636902933 Binary files /dev/null and b/Resources/Textures/Constructible/Power/ame_shielding.rsi/shield_9.png differ diff --git a/Resources/Textures/Constructible/Power/ame_shielding_base.png b/Resources/Textures/Constructible/Power/ame_shielding_base.png new file mode 100644 index 0000000000..cd62067877 Binary files /dev/null and b/Resources/Textures/Constructible/Power/ame_shielding_base.png differ diff --git a/Resources/Textures/Objects/Power/AME/ame_jar.rsi/jar.png b/Resources/Textures/Objects/Power/AME/ame_jar.rsi/jar.png new file mode 100644 index 0000000000..ede7ec4094 Binary files /dev/null and b/Resources/Textures/Objects/Power/AME/ame_jar.rsi/jar.png differ diff --git a/Resources/Textures/Objects/Power/AME/ame_jar.rsi/meta.json b/Resources/Textures/Objects/Power/AME/ame_jar.rsi/meta.json new file mode 100644 index 0000000000..38c5df1bfe --- /dev/null +++ b/Resources/Textures/Objects/Power/AME/ame_jar.rsi/meta.json @@ -0,0 +1,20 @@ +{ + "version": 1, + "size": { + "x": 32, + "y": 32 + }, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from https://github.com/vgstation-coders/vgstation13/blob/Bleeding-Edge/icons/obj/machines/new_ame.dmi at 1b7952787c06c21ef1623e494dcfe7cb1f46e041", + "states": [ + { + "name": "jar", + "directions": 1, + "delays": [ + [ + 1.0 + ] + ] + } + ] +} \ No newline at end of file diff --git a/Resources/Textures/Objects/Power/AME/ame_part.rsi/box.png b/Resources/Textures/Objects/Power/AME/ame_part.rsi/box.png new file mode 100644 index 0000000000..320d84905c Binary files /dev/null and b/Resources/Textures/Objects/Power/AME/ame_part.rsi/box.png differ diff --git a/Resources/Textures/Objects/Power/AME/ame_part.rsi/meta.json b/Resources/Textures/Objects/Power/AME/ame_part.rsi/meta.json new file mode 100644 index 0000000000..423746d2a2 --- /dev/null +++ b/Resources/Textures/Objects/Power/AME/ame_part.rsi/meta.json @@ -0,0 +1,20 @@ +{ + "version": 1, + "size": { + "x": 32, + "y": 32 + }, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from https://github.com/vgstation-coders/vgstation13/blob/Bleeding-Edge/icons/obj/machines/new_ame.dmi at 1b7952787c06c21ef1623e494dcfe7cb1f46e041", + "states": [ + { + "name": "box", + "directions": 1, + "delays": [ + [ + 1.0 + ] + ] + } + ] +} \ No newline at end of file