From 5c723ea70e9109148f40bd5a6e09d4592c75329a Mon Sep 17 00:00:00 2001 From: Kmc2000 Date: Fri, 17 Jul 2020 09:42:05 +0100 Subject: [PATCH] RCD (#912) --- .../Components/Items/RCDComponent.cs | 156 ++++++++++++++++++ Resources/Prototypes/Entities/Items/tools.yml | 17 ++ .../Objects/Tools/rcd.rsi/inhand-left.png | Bin 0 -> 157 bytes .../Objects/Tools/rcd.rsi/inhand-right.png | Bin 0 -> 163 bytes .../Textures/Objects/Tools/rcd.rsi/meta.json | 1 + .../Textures/Objects/Tools/rcd.rsi/rcd.png | Bin 0 -> 317 bytes RobustToolbox | 2 +- 7 files changed, 175 insertions(+), 1 deletion(-) create mode 100644 Content.Server/GameObjects/Components/Items/RCDComponent.cs create mode 100644 Resources/Textures/Objects/Tools/rcd.rsi/inhand-left.png create mode 100644 Resources/Textures/Objects/Tools/rcd.rsi/inhand-right.png create mode 100644 Resources/Textures/Objects/Tools/rcd.rsi/meta.json create mode 100644 Resources/Textures/Objects/Tools/rcd.rsi/rcd.png diff --git a/Content.Server/GameObjects/Components/Items/RCDComponent.cs b/Content.Server/GameObjects/Components/Items/RCDComponent.cs new file mode 100644 index 0000000000..657addaba8 --- /dev/null +++ b/Content.Server/GameObjects/Components/Items/RCDComponent.cs @@ -0,0 +1,156 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Content.Server.GameObjects.EntitySystems; +using Content.Server.GameObjects.EntitySystems.Click; +using Content.Server.Interfaces; +using Content.Server.Interfaces.GameObjects.Components.Interaction; +using Content.Server.Utility; +using Content.Shared.Construction; +using Content.Shared.Maps; +using Microsoft.EntityFrameworkCore.Internal; +using Robust.Server.GameObjects.EntitySystems; +using Robust.Server.Interfaces.GameObjects; +using Robust.Shared.GameObjects; +using Robust.Shared.GameObjects.Components.Transform; +using Robust.Shared.Interfaces.GameObjects; +using Robust.Shared.Interfaces.Map; +using Robust.Shared.IoC; +using Robust.Shared.Localization; +using Robust.Shared.Map; +using Robust.Shared.Prototypes; +using Robust.Shared.Serialization; +using Robust.Shared.Utility; + +namespace Content.Server.GameObjects.Components.Items +{ + [RegisterComponent] + public class RCDComponent : Component, IAfterInteract, IUse, IExamine + { + +#pragma warning disable 649 + [Dependency] private readonly ITileDefinitionManager _tileDefinitionManager; + [Dependency] private readonly IEntitySystemManager _entitySystemManager; + [Dependency] private readonly IMapManager _mapManager; + [Dependency] private readonly IServerEntityManager _serverEntityManager; + [Dependency] private IServerNotifyManager _serverNotifyManager; +#pragma warning restore 649 + public override string Name => "RCD"; + private string _outputTile = "floor_steel"; + private RcdMode _mode = 0; //What mode are we on? Can be floors, walls, deconstruct. + private readonly RcdMode[] _modes = (RcdMode[]) Enum.GetValues(typeof(RcdMode)); + private int _ammo = 5; //How much "ammo" we have left. You can refille this with RCD ammo. + + ///Enum to store the different mode states for clarity. + private enum RcdMode + { + Floors, + Walls, + Deconstruct + } + + public override void ExposeData(ObjectSerializer serializer) + { + base.ExposeData(serializer); + serializer.DataField(ref _outputTile, "output", "floor_steel"); + } + + + /// + /// Method called when the RCD is clicked in-hand, this will swap the RCD's mode from "floors" to "walls". + /// + + public bool UseEntity(UseEntityEventArgs eventArgs) + { + SwapMode(eventArgs); + return true; + } + + /// + ///Method to allow the user to swap the mode of the RCD by clicking it in hand, the actual in hand clicking bit is done over on UseEntity() + ///@param UseEntityEventArgs = The entity which triggered this method call, used to know where to play the "click" sound. + /// + + public void SwapMode(UseEntityEventArgs eventArgs) + { + _entitySystemManager.GetEntitySystem().PlayFromEntity("/Audio/items/genhit.ogg", Owner); + int mode = (int) this._mode; //Firstly, cast our RCDmode mode to an int (enums are backed by ints anyway by default) + mode = (++mode) % _modes.Length; //Then, do a rollover on the value so it doesnt hit an invalid state + this._mode = (RcdMode) mode; //Finally, cast the newly acquired int mode to an RCDmode so we can use it. + switch (this._mode) + { + case RcdMode.Floors: + _outputTile = "floor_steel"; + break; + case RcdMode.Walls: + _outputTile = "base_wall"; + break; + case RcdMode.Deconstruct: + _outputTile = "space"; + break; + } + _serverNotifyManager.PopupMessage(Owner, eventArgs.User, $"The RCD is now set to {this._mode} mode."); //Prints an overhead message above the RCD + } + + /// + ///Method called when the user examines this object, it'll simply add the mode that it's in to the object's description + ///@params message = The original message from examining, like ..() in BYOND's examine + /// + + public void Examine(FormattedMessage message, bool inDetailsRange) + { + message.AddMarkup(Loc.GetString("It's currently on {0} mode, and holds {1} charges.",_mode.ToString(), this._ammo)); + } + + /// + /// Method to handle clicking on a tile to then appropriately RCD it. This can have several behaviours depending on mode. + /// @param eventAargs = An action event telling us what tile was clicked on. We use this to exrapolate where to place the new tile / remove the old one etc. + /// + + public void AfterInteract(AfterInteractEventArgs eventArgs) + { + var mapGrid = _mapManager.GetGrid(eventArgs.ClickLocation.GridID); + var tile = mapGrid.GetTileRef(eventArgs.ClickLocation); + var coordinates = mapGrid.GridTileToLocal(tile.GridIndices); + //Less expensive checks first. Failing those ones, we need to check that the tile isn't obstructed. + if (_ammo <= 0 || coordinates == GridCoordinates.InvalidGrid || !InteractionChecks.InRangeUnobstructed(eventArgs)) + { + return; + } + + var targetTile = (ContentTileDefinition) _tileDefinitionManager[tile.Tile.TypeId]; + + var canPlaceTile = targetTile.IsSubFloor; //Boolean to check if we're able to build the desired tile. This defaults to checking for subfloors, but is overridden by "deconstruct" which sets it to the inverse. + + switch (this._mode) + { + //Floor mode just needs the tile to be a space tile (subFloor) + case RcdMode.Floors: + break; + //We don't want to place a space tile on something that's already a space tile. Let's do the inverse of the last check. + case RcdMode.Deconstruct: + canPlaceTile = !targetTile.IsSubFloor; + break; + //Walls are a special behaviour, and require us to build a new object with a transform rather than setting a grid tile, thus we early return to avoid the tile set code. + case RcdMode.Walls: + var snapPos = mapGrid.SnapGridCellFor(eventArgs.ClickLocation, SnapGridOffset.Center); + var ent = _serverEntityManager.SpawnEntity("solid_wall", mapGrid.GridTileToLocal(snapPos)); + ent.Transform.LocalRotation = Owner.Transform.LocalRotation; //Now apply icon smoothing. + _entitySystemManager.GetEntitySystem().PlayFromEntity("/Audio/items/deconstruct.ogg", Owner); + _ammo--; + return; //Alright we're done here + default: + return; //I don't know why this would happen, but sure I guess. Get out of here invalid state! + } + + ITileDefinition desiredTile = null; + desiredTile = _tileDefinitionManager[_outputTile]; + if (canPlaceTile) //If desiredTile is null by this point, something has gone horribly wrong and you need to fix it. + { + mapGrid.SetTile(eventArgs.ClickLocation, new Tile(desiredTile.TileId)); + _entitySystemManager.GetEntitySystem().PlayFromEntity("/Audio/items/deconstruct.ogg", Owner); + _ammo--; + } + } + } +} diff --git a/Resources/Prototypes/Entities/Items/tools.yml b/Resources/Prototypes/Entities/Items/tools.yml index b7be1f5173..01cad99583 100644 --- a/Resources/Prototypes/Entities/Items/tools.yml +++ b/Resources/Prototypes/Entities/Items/tools.yml @@ -244,3 +244,20 @@ state: drill_bolt useSound: /Audio/Items/drill_use.ogg changeSound: /Audio/Items/change_drill.ogg +- type: entity + name: RCD + parent: BaseItem + id: RCD + description: An advanced construction device which can place floors / walls down quickly. + components: + - type: RCD + - type: UseDelay + delay: 1.0 + - type: Sprite + sprite: Objects/Tools/rcd.rsi + state: rcd + - type: Icon + sprite: Objects/Tools/rcd.rsi + state: rcd + - type: Item + sprite: Objects/Tools/rcd.rsi diff --git a/Resources/Textures/Objects/Tools/rcd.rsi/inhand-left.png b/Resources/Textures/Objects/Tools/rcd.rsi/inhand-left.png new file mode 100644 index 0000000000000000000000000000000000000000..1873ca3ccb7ddad83f0be5ac687606ef60825e9c GIT binary patch literal 157 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=DV{ElAr*7p-U{SxaNuz{$bBe# zmC>uEVtmXh0vh$kO!uU2Yy~P~V6a=YN>;FXk*MJARc=w?efEoH?%Y+qvd$@? F2>=#3J6Qk# literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Tools/rcd.rsi/meta.json b/Resources/Textures/Objects/Tools/rcd.rsi/meta.json new file mode 100644 index 0000000000..1cfaa7b48f --- /dev/null +++ b/Resources/Textures/Objects/Tools/rcd.rsi/meta.json @@ -0,0 +1 @@ +{"version": 1, "size": {"x": 32, "y": 32}, "states": [{"name": "inhand-left", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "inhand-right", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "rcd", "directions": 1, "delays": [[1.0]]}]} \ No newline at end of file diff --git a/Resources/Textures/Objects/Tools/rcd.rsi/rcd.png b/Resources/Textures/Objects/Tools/rcd.rsi/rcd.png new file mode 100644 index 0000000000000000000000000000000000000000..fe1b33a4cf3f221db7329025a82e60bb7eb24e95 GIT binary patch literal 317 zcmV-D0mA-?P) z0ImQ4K0ZE7OiY-10I`Jtb-FVw00001bW%=J06^y0W&i*Hqe(72YH1ghp;%6rTXQc}41Kb