diff --git a/Content.Client/ADT/_RMC14/Attachable/Components/AttachableHolderVisualsComponent.cs b/Content.Client/ADT/_RMC14/Attachable/Components/AttachableHolderVisualsComponent.cs new file mode 100644 index 00000000000..d1a1351691d --- /dev/null +++ b/Content.Client/ADT/_RMC14/Attachable/Components/AttachableHolderVisualsComponent.cs @@ -0,0 +1,17 @@ +using Content.Client._RMC14.Attachable.Systems; +using System.Numerics; + +namespace Content.Client._RMC14.Attachable.Components; + +[RegisterComponent, AutoGenerateComponentState] +[Access(typeof(AttachableHolderVisualsSystem))] +public sealed partial class AttachableHolderVisualsComponent : Component +{ + /// + /// This dictionary contains a list of offsets for every slot that should display the attachable placed into it. + /// If a slot is not in this dictionary, the attachable inside will not be displayed. + /// The list of valid slot names can be found in AttachableHolderComponent.cs + /// + [DataField(required: true), AutoNetworkedField] + public Dictionary Offsets = new(); +} diff --git a/Content.Client/ADT/_RMC14/Attachable/Components/AttachableVisualsComponent.cs b/Content.Client/ADT/_RMC14/Attachable/Components/AttachableVisualsComponent.cs new file mode 100644 index 00000000000..51100e8a74c --- /dev/null +++ b/Content.Client/ADT/_RMC14/Attachable/Components/AttachableVisualsComponent.cs @@ -0,0 +1,66 @@ +using Content.Client._RMC14.Attachable.Systems; +using System.Numerics; +using Robust.Shared.Utility; + +namespace Content.Client._RMC14.Attachable.Components; + +[RegisterComponent, AutoGenerateComponentState] +[Access(typeof(AttachableHolderVisualsSystem))] +public sealed partial class AttachableVisualsComponent : Component +{ + /// + /// Optional, only used if the item's own state should not be used. + /// The path to the RSI file that contains all the attached states. + /// + [DataField, AutoNetworkedField] + public ResPath? Rsi; + + /// + /// Optional, only used if the item's own state should not be used. + /// This prefix is added to the name of the slot the attachable is installed in. + /// The prefix must be in kebab-case and end with a dash, like so: example-prefix- + /// The RSI must contain a state for every slot the attachable fits into. + /// If the attachment only fits into one slot, it should be named as follows: normal-state_suffix. + /// The slot names can be found in AttachableHolderComponent.cs + /// + [DataField, AutoNetworkedField] + public string? Prefix; + + /// + /// Optional, only used if the item's own state should not be used. + /// This suffix is added to the name of the slot the attachable is installed in. + /// The RSI must contain a state for every slot the attachable fits into. + /// If the attachment only fits into one slot, it should be named as follows: normal-state_suffix. + /// The slot names can be found in AttachableHolderComponent.cs + /// + [DataField, AutoNetworkedField] + public string? Suffix = "_a"; + + /// + /// If true, will include the holder's slot name to find this attachment's state + /// in its RSI. + /// In this case, there must be a separate state for each slot the attachment fits into. + /// The states should be named as follows: prefix-slot-name-suffix. + /// + [DataField, AutoNetworkedField] + public bool IncludeSlotName; + + /// + /// If this is toggled on and the item has an AttachableToggleableComponent, then the visualisation system will try to show a different sprite when it's active. + /// Each active state must have "-on" appended to the end of its name. + /// + [DataField, AutoNetworkedField] + public bool ShowActive; + + /// + /// If this is set to true, the attachment will be redrawn on its holder every time it receives an AppearanceChangeEvent. Useful for things like the UGL. + /// + [DataField, AutoNetworkedField] + public bool RedrawOnAppearanceChange; + + [DataField, AutoNetworkedField] + public int Layer; + + [DataField, AutoNetworkedField] + public Vector2 Offset; +} diff --git a/Content.Client/ADT/_RMC14/Attachable/Systems/AttachableHolderVisualsSystem.cs b/Content.Client/ADT/_RMC14/Attachable/Systems/AttachableHolderVisualsSystem.cs new file mode 100644 index 00000000000..b083f1ca2b6 --- /dev/null +++ b/Content.Client/ADT/_RMC14/Attachable/Systems/AttachableHolderVisualsSystem.cs @@ -0,0 +1,155 @@ +using Content.Client._RMC14.Attachable.Components; +using Content.Shared._RMC14.Attachable; +using Content.Shared._RMC14.Attachable.Components; +using Content.Shared._RMC14.Attachable.Events; +using Content.Shared._RMC14.Attachable.Systems; +using Robust.Client.GameObjects; +using Robust.Shared.Containers; + +namespace Content.Client._RMC14.Attachable.Systems; + +public sealed class AttachableHolderVisualsSystem : EntitySystem +{ + [Dependency] private readonly AttachableHolderSystem _attachableHolderSystem = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnDetached); + SubscribeLocalEvent(OnAttachablesAltered); + + SubscribeLocalEvent(OnAttachableAppearanceChange); + } + + private void OnDetached(Entity holder, ref EntRemovedFromContainerMessage args) + { + if (!HasComp(args.Entity) || !_attachableHolderSystem.HasSlot(holder.Owner, args.Container.ID)) + return; + + var holderEv = new AttachableHolderAttachablesAlteredEvent(args.Entity, args.Container.ID, AttachableAlteredType.Detached); + RaiseLocalEvent(holder, ref holderEv); + } + + private void OnAttachablesAltered(Entity holder, + ref AttachableHolderAttachablesAlteredEvent args) + { + if (!TryComp(args.Attachable, out AttachableVisualsComponent? attachableComponent)) + return; + + string suffix = ""; + if (attachableComponent.ShowActive && TryComp(args.Attachable, out AttachableToggleableComponent? toggleableComponent) && toggleableComponent.Active) + suffix = "-on"; + + var attachable = new Entity(args.Attachable, attachableComponent); + switch (args.Alteration) + { + case AttachableAlteredType.Attached: + SetAttachableOverlay(holder, attachable, args.SlotId, suffix); + break; + + case AttachableAlteredType.Detached: + RemoveAttachableOverlay(holder, args.SlotId); + break; + + case AttachableAlteredType.Activated: + if (!attachableComponent.ShowActive) + break; + + SetAttachableOverlay(holder, attachable, args.SlotId, suffix); + break; + + case AttachableAlteredType.Deactivated: + if (!attachableComponent.ShowActive) + break; + + SetAttachableOverlay(holder, attachable, args.SlotId, suffix); + break; + + case AttachableAlteredType.Interrupted: + if (!attachableComponent.ShowActive) + break; + + SetAttachableOverlay(holder, attachable, args.SlotId); + break; + + case AttachableAlteredType.AppearanceChanged: + SetAttachableOverlay(holder, attachable, args.SlotId, suffix); + break; + } + } + + private void RemoveAttachableOverlay(Entity holder, string slotId) + { + if (!holder.Comp.Offsets.ContainsKey(slotId) || !TryComp(holder, out SpriteComponent? spriteComponent)) + return; + + if (!spriteComponent.LayerMapTryGet(slotId, out var index)) + return; + + spriteComponent.LayerMapRemove(slotId); + spriteComponent.RemoveLayer(index); + } + + private void SetAttachableOverlay(Entity holder, + Entity attachable, + string slotId, + string suffix = "") + { + if (!holder.Comp.Offsets.ContainsKey(slotId) || + !TryComp(holder, out SpriteComponent? holderSprite)) + { + return; + } + + if (!TryComp(attachable, out SpriteComponent? attachableSprite)) + return; + + var rsi = attachableSprite.LayerGetActualRSI(attachable.Comp.Layer)?.Path; + var state = attachableSprite.LayerGetState(attachable.Comp.Layer).ToString(); + if (attachable.Comp.Rsi is { } rsiPath) + { + rsi = rsiPath; + } + + if (!string.IsNullOrWhiteSpace(attachable.Comp.Prefix)) + state = attachable.Comp.Prefix; + + if (attachable.Comp.IncludeSlotName) + state += slotId; + + if (!string.IsNullOrWhiteSpace(attachable.Comp.Suffix)) + state += attachable.Comp.Suffix; + + state += suffix; + + var layerData = new PrototypeLayerData() + { + RsiPath = rsi.ToString(), + State = state, + Offset = holder.Comp.Offsets[slotId] + attachable.Comp.Offset, + Visible = true, + }; + + if (holderSprite.LayerMapTryGet(slotId, out var index)) + { + holderSprite.LayerSetData(index, layerData); + return; + } + + holderSprite.LayerMapSet(slotId, holderSprite.AddLayer(layerData)); + } + + private void OnAttachableAppearanceChange(Entity attachable, ref AppearanceChangeEvent args) + { + if (!attachable.Comp.RedrawOnAppearanceChange || + !_attachableHolderSystem.TryGetHolder(attachable.Owner, out var holderUid) || + !_attachableHolderSystem.TryGetSlotId(holderUid.Value, attachable.Owner, out var slotId)) + { + return; + } + + var holderEvent = new AttachableHolderAttachablesAlteredEvent(attachable.Owner, slotId, AttachableAlteredType.AppearanceChanged); + RaiseLocalEvent(holderUid.Value, ref holderEvent); + } +} diff --git a/Content.Client/ADT/_RMC14/Attachable/Ui/AttachableHolderChooseSlotMenu.xaml b/Content.Client/ADT/_RMC14/Attachable/Ui/AttachableHolderChooseSlotMenu.xaml new file mode 100644 index 00000000000..c2ff1b5b704 --- /dev/null +++ b/Content.Client/ADT/_RMC14/Attachable/Ui/AttachableHolderChooseSlotMenu.xaml @@ -0,0 +1,9 @@ + + + diff --git a/Content.Client/ADT/_RMC14/Attachable/Ui/AttachableHolderChooseSlotMenu.xaml.cs b/Content.Client/ADT/_RMC14/Attachable/Ui/AttachableHolderChooseSlotMenu.xaml.cs new file mode 100644 index 00000000000..27c30ab2274 --- /dev/null +++ b/Content.Client/ADT/_RMC14/Attachable/Ui/AttachableHolderChooseSlotMenu.xaml.cs @@ -0,0 +1,58 @@ +using Content.Client.UserInterface.Controls; +using Content.Shared._RMC14.Attachable; +using Robust.Client.AutoGenerated; +using Robust.Client.UserInterface; +using Robust.Client.UserInterface.Controls; +using Robust.Client.UserInterface.XAML; + +namespace Content.Client.ADT._RMC14.Attachable.Ui; + +[GenerateTypedNameReferences] +public sealed partial class AttachableHolderChooseSlotMenu : FancyWindow +{ + private readonly AttachmentChooseSlotBui _boundUI; + private readonly Dictionary _attachableSlotControls; + + public AttachableHolderChooseSlotMenu(AttachmentChooseSlotBui boundUI) + { + RobustXamlLoader.Load(this); + + _boundUI = boundUI; + _attachableSlotControls = new Dictionary(); + OnClose += boundUI.Close; + } + + public void UpdateMenu(List attachableSlots) + { + foreach (var slotId in attachableSlots) + { + if (!_attachableSlotControls.ContainsKey(slotId)) + AddSlotControl(slotId); + } + } + + private void AddSlotControl(string slotId) + { + var slotControl = new AttachableSlotControl(this, _boundUI, slotId); + SlotsContainer.AddChild(slotControl); + _attachableSlotControls.Add(slotId, slotControl); + } + + private sealed class AttachableSlotControl : Control + { + public AttachableSlotControl(AttachableHolderChooseSlotMenu slotMenu, + AttachmentChooseSlotBui boundUI, + string slotId) + { + var button = new Button { Text = Loc.GetString(slotId) }; + + button.OnPressed += _ => + { + boundUI.SendMessage(new AttachableHolderAttachToSlotMessage(slotId)); + slotMenu.Close(); + }; + + AddChild(button); + } + } +} diff --git a/Content.Client/ADT/_RMC14/Attachable/Ui/AttachableHolderStripMenu.xaml b/Content.Client/ADT/_RMC14/Attachable/Ui/AttachableHolderStripMenu.xaml new file mode 100644 index 00000000000..a21514abeda --- /dev/null +++ b/Content.Client/ADT/_RMC14/Attachable/Ui/AttachableHolderStripMenu.xaml @@ -0,0 +1,9 @@ + + + diff --git a/Content.Client/ADT/_RMC14/Attachable/Ui/AttachableHolderStripMenu.xaml.cs b/Content.Client/ADT/_RMC14/Attachable/Ui/AttachableHolderStripMenu.xaml.cs new file mode 100644 index 00000000000..0f045d1068f --- /dev/null +++ b/Content.Client/ADT/_RMC14/Attachable/Ui/AttachableHolderStripMenu.xaml.cs @@ -0,0 +1,95 @@ +using System.Numerics; +using Content.Client.Stylesheets; +using Content.Client.UserInterface.Controls; +using Content.Shared._RMC14.Attachable; +using Robust.Client.AutoGenerated; +using Robust.Client.UserInterface; +using Robust.Client.UserInterface.Controls; +using Robust.Client.UserInterface.XAML; +using static Robust.Client.UserInterface.Controls.BoxContainer; + +namespace Content.Client.ADT._RMC14.Attachable.Ui; + +[GenerateTypedNameReferences] +public sealed partial class AttachableHolderStripMenu : FancyWindow +{ + private readonly AttachmentStripBui _boundUI; + private readonly Dictionary _attachableSlotControls; + + public AttachableHolderStripMenu(AttachmentStripBui boundUI) + { + RobustXamlLoader.Load(this); + + _boundUI = boundUI; + _attachableSlotControls = new Dictionary(); + OnClose += boundUI.Close; + } + + public void UpdateMenu(Dictionary attachableSlots) + { + foreach (var slotId in attachableSlots.Keys) + { + if (!_attachableSlotControls.ContainsKey(slotId)) + AddSlotControl(slotId); + + _attachableSlotControls[slotId].Update(attachableSlots[slotId].attachableName, attachableSlots[slotId].locked); + } + } + + private void AddSlotControl(string slotId, string? attachableName = null) + { + var slotControl = new AttachableSlotControl(_boundUI, slotId); + AttachablesContainer.AddChild(slotControl); + _attachableSlotControls.Add(slotId, slotControl); + } + + private sealed class AttachableSlotControl : Control + { + private readonly Button AttachableButton; + + public AttachableSlotControl(AttachmentStripBui boundUI, string slotId) + { + var slotLabel = new Label + { + Text = Loc.GetString(slotId) + ':', + HorizontalAlignment = HAlignment.Left + }; + + AttachableButton = new Button + { + Text = Loc.GetString("rmc-attachable-holder-strip-ui-empty-slot"), + HorizontalExpand = true, + HorizontalAlignment = HAlignment.Right, + StyleClasses = { StyleBase.ButtonOpenRight } + }; + + var hBox = new BoxContainer + { + Orientation = LayoutOrientation.Horizontal, + Children = + { + new Control { MinSize = new Vector2(5, 0) }, + slotLabel, + new Control { MinSize = new Vector2(5, 0) }, + AttachableButton, + }, + }; + + AttachableButton.OnPressed += _ => boundUI.SendMessage(new AttachableHolderDetachMessage(slotId)); + AddChild(hBox); + } + + public void Update(string? attachableName, bool slotLocked) + { + if (attachableName == null) + { + AttachableButton.Text = Loc.GetString("rmc-attachable-holder-strip-ui-empty-slot"); + AttachableButton.Disabled = true; + return; + } + + AttachableButton.Text = attachableName; + AttachableButton.Disabled = slotLocked; + } + } +} diff --git a/Content.Client/ADT/_RMC14/Attachable/Ui/AttachmentChooseSlotBui.cs b/Content.Client/ADT/_RMC14/Attachable/Ui/AttachmentChooseSlotBui.cs new file mode 100644 index 00000000000..6d46808bb7b --- /dev/null +++ b/Content.Client/ADT/_RMC14/Attachable/Ui/AttachmentChooseSlotBui.cs @@ -0,0 +1,45 @@ +using Content.Shared._RMC14.Attachable; + +namespace Content.Client.ADT._RMC14.Attachable.Ui; + +public sealed class AttachmentChooseSlotBui : BoundUserInterface +{ + [ViewVariables] + private AttachableHolderChooseSlotMenu? _menu; + + public AttachmentChooseSlotBui(EntityUid owner, Enum uiKey) : base(owner, uiKey) { } + + protected override void Open() + { + base.Open(); + + _menu = new AttachableHolderChooseSlotMenu(this); + var metaQuery = EntMan.GetEntityQuery(); + if (metaQuery.TryGetComponent(Owner, out var metadata)) + _menu.Title = metadata.EntityName; + + _menu.OpenCentered(); + } + + protected override void UpdateState(BoundUserInterfaceState state) + { + base.UpdateState(state); + + if (state is not AttachableHolderChooseSlotUserInterfaceState msg) + return; + + if (_menu == null) + return; + + _menu.UpdateMenu(msg.AttachableSlots); + } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + if (!disposing) + return; + + _menu?.Dispose(); + } +} diff --git a/Content.Client/ADT/_RMC14/Attachable/Ui/AttachmentStripBui.cs b/Content.Client/ADT/_RMC14/Attachable/Ui/AttachmentStripBui.cs new file mode 100644 index 00000000000..b4a9a1afcdd --- /dev/null +++ b/Content.Client/ADT/_RMC14/Attachable/Ui/AttachmentStripBui.cs @@ -0,0 +1,45 @@ +using Content.Shared._RMC14.Attachable; + +namespace Content.Client.ADT._RMC14.Attachable.Ui; + +public sealed class AttachmentStripBui : BoundUserInterface +{ + private AttachableHolderStripMenu? _menu; + + public AttachmentStripBui(EntityUid owner, Enum uiKey) : base(owner, uiKey) { } + + protected override void Open() + { + base.Open(); + + _menu = new AttachableHolderStripMenu(this); + + var metaQuery = EntMan.GetEntityQuery(); + if (metaQuery.TryGetComponent(Owner, out var metadata)) + _menu.Title = metadata.EntityName; + + _menu.OpenCentered(); + } + + protected override void UpdateState(BoundUserInterfaceState state) + { + base.UpdateState(state); + + if (state is not AttachableHolderStripUserInterfaceState msg) + return; + + if (_menu == null) + return; + + _menu.UpdateMenu(msg.AttachableSlots); + } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + if (!disposing) + return; + + _menu?.Dispose(); + } +} diff --git a/Content.Client/ADT/_RMC14/Scoping/ScopeSystem.cs b/Content.Client/ADT/_RMC14/Scoping/ScopeSystem.cs new file mode 100644 index 00000000000..5483c9a9baa --- /dev/null +++ b/Content.Client/ADT/_RMC14/Scoping/ScopeSystem.cs @@ -0,0 +1,5 @@ +using Content.Shared._RMC14.Scoping; + +namespace Content.Client._RMC14.Scoping; + +public sealed class ScopeSystem : SharedScopeSystem; diff --git a/Content.Client/ADT/_RMC14/Weapons/Ranged/PumpActionSystem.cs b/Content.Client/ADT/_RMC14/Weapons/Ranged/PumpActionSystem.cs new file mode 100644 index 00000000000..ffe6ad56286 --- /dev/null +++ b/Content.Client/ADT/_RMC14/Weapons/Ranged/PumpActionSystem.cs @@ -0,0 +1,35 @@ +using Content.Shared._RMC14.Input; +using Content.Shared._RMC14.Weapons.Ranged; +using Content.Shared.Examine; +using Content.Shared.Popups; +using Content.Shared.Weapons.Ranged.Systems; +using Robust.Client.Input; + +namespace Content.Client._RMC14.Weapons.Ranged; + +public sealed class PumpActionSystem : SharedPumpActionSystem +{ + [Dependency] private readonly IInputManager _input = default!; + [Dependency] private readonly SharedPopupSystem _popup = default!; + + protected override void OnExamined(Entity ent, ref ExaminedEvent args) + { + if (!_input.TryGetKeyBinding(CMKeyFunctions.CMUniqueAction, out var bind)) + return; + + args.PushMarkup(Loc.GetString(ent.Comp.Examine), 1); + } + + protected override void OnAttemptShoot(Entity ent, ref AttemptShootEvent args) + { + base.OnAttemptShoot(ent, ref args); + + if (!ent.Comp.Pumped) + { + var message = _input.TryGetKeyBinding(CMKeyFunctions.CMUniqueAction, out var bind) + ? Loc.GetString(ent.Comp.PopupKey, ("key", bind.GetKeyString())) + : Loc.GetString(ent.Comp.Popup); + _popup.PopupClient(message, args.User, args.User); + } + } +} diff --git a/Content.Client/Input/ContentContexts.cs b/Content.Client/Input/ContentContexts.cs index 4ae0ee62efa..3fa68d7e815 100644 --- a/Content.Client/Input/ContentContexts.cs +++ b/Content.Client/Input/ContentContexts.cs @@ -1,5 +1,6 @@ using Content.Shared.Input; using Robust.Shared.Input; +using Content.Shared._RMC14.Input; // ADT TWEAK namespace Content.Client.Input { @@ -124,6 +125,21 @@ public static void SetupContexts(IInputContextContainer contexts) common.AddFunction(ContentKeyFunctions.OpenDecalSpawnWindow); common.AddFunction(ContentKeyFunctions.OpenAdminMenu); common.AddFunction(ContentKeyFunctions.OpenGuidebook); + + CMFunctions(contexts); // ADT TWEAK + } + + // ADT TWEAK START: + private static void CMFunctions(IInputContextContainer contexts) + { + var human = contexts.GetContext("human"); + human.AddFunction(CMKeyFunctions.RMCActivateAttachableBarrel); + human.AddFunction(CMKeyFunctions.RMCActivateAttachableRail); + human.AddFunction(CMKeyFunctions.RMCActivateAttachableStock); + human.AddFunction(CMKeyFunctions.RMCActivateAttachableUnderbarrel); + human.AddFunction(CMKeyFunctions.RMCFieldStripHeldItem); + human.AddFunction(CMKeyFunctions.CMUniqueAction); } + // ADT TWEAK END. } } diff --git a/Content.Client/Options/UI/Tabs/KeyRebindTab.xaml.cs b/Content.Client/Options/UI/Tabs/KeyRebindTab.xaml.cs index 20b4330e985..f940815634a 100644 --- a/Content.Client/Options/UI/Tabs/KeyRebindTab.xaml.cs +++ b/Content.Client/Options/UI/Tabs/KeyRebindTab.xaml.cs @@ -13,6 +13,7 @@ using Robust.Shared.Timing; using Robust.Shared.Utility; using static Robust.Client.UserInterface.Controls.BoxContainer; +using Content.Shared._RMC14.Input; // ADT TWEAK namespace Content.Client.Options.UI.Tabs { @@ -150,6 +151,15 @@ void AddCheckBox(string checkBoxName, bool currentState, Action _xformQuery; + + private const string MeleeLungeKey = "melee-lunge"; + + public override void Initialize() + { + base.Initialize(); + _xformQuery = GetEntityQuery(); + SubscribeNetworkEvent(OnMeleeLunge); + UpdatesOutsidePrediction = true; + } + + public override void FrameUpdate(float frameTime) + { + base.FrameUpdate(frameTime); + UpdateEffects(); + } + public override void Update(float frameTime) + { + base.Update(frameTime); + + if (!Timing.IsFirstTimePredicted) + return; + + var entityNull = _player.LocalEntity; + + if (entityNull == null) + return; + + var entity = entityNull.Value; + + if (!TryGetWeapon(entity, out var weaponUid, out var weapon)) + return; + + if (!CombatMode.IsInCombatMode(entity) || !Blocker.CanAttack(entity, weapon: (weaponUid, weapon))) + { + weapon.Attacking = false; + return; + } + var useDown = _inputSystem.CmdStates.GetState(EngineKeyFunctions.Use); + var altDown = _inputSystem.CmdStates.GetState(EngineKeyFunctions.UseSecondary); + + if (weapon.AutoAttack || useDown != BoundKeyState.Down && altDown != BoundKeyState.Down) + { + if (weapon.Attacking) + { + RaisePredictiveEvent(new StopAttackEvent(GetNetEntity(weaponUid))); + } + } + + if (weapon.Attacking || weapon.NextAttack > Timing.CurTime) + { + return; + } + + // TODO using targeted actions while combat mode is enabled should NOT trigger attacks. + var mousePos = _eyeManager.PixelToMap(_inputManager.MouseScreenPosition); + + if (mousePos.MapId == MapId.Nullspace) + { + return; + } + + EntityCoordinates coordinates; + + if (MapManager.TryFindGridAt(mousePos, out var gridUid, out _)) + { + coordinates = TransformSystem.ToCoordinates(gridUid, mousePos); + } + else + { + coordinates = TransformSystem.ToCoordinates(_map.GetMap(mousePos.MapId), mousePos); + } + + // If the gun has AltFireMeleeComponent, it can be used to attack. + if (TryComp(weaponUid, out var gun) && gun.UseKey) + { + if (!TryComp(weaponUid, out var altFireComponent) || altDown != BoundKeyState.Down) + return; + + switch (altFireComponent.AttackType) + { + case AltFireAttackType.Light: + ClientLightAttack(entity, mousePos, coordinates, weaponUid, weapon); + break; + + case AltFireAttackType.Heavy: + ClientHeavyAttack(entity, coordinates, weaponUid, weapon); + break; + + case AltFireAttackType.Disarm: + ClientDisarm(entity, mousePos, coordinates); + break; + } + + return; + } + + // Heavy attack. + if (altDown == BoundKeyState.Down) + { + // If it's an unarmed attack then do a disarm + if (weapon.AltDisarm && weaponUid == entity) + { + ClientDisarm(entity, mousePos, coordinates); + return; + } + + ClientHeavyAttack(entity, coordinates, weaponUid, weapon); + return; + } + + // Light attack + if (useDown == BoundKeyState.Down) + ClientLightAttack(entity, mousePos, coordinates, weaponUid, weapon); + } + + protected override bool InRange(EntityUid user, EntityUid target, float range, ICommonSession? session) + { + var xform = Transform(target); + var targetCoordinates = xform.Coordinates; + var targetLocalAngle = xform.LocalRotation; + + return Interaction.InRangeUnobstructed(user, target, targetCoordinates, targetLocalAngle, range); + } + + protected override void DoDamageEffect(List targets, EntityUid? user, TransformComponent targetXform) + { + // Server never sends the event to us for predictiveeevent. + _color.RaiseEffect(Color.Red, targets, Filter.Local()); + } + + protected override bool DoDisarm(EntityUid user, DisarmAttackEvent ev, EntityUid meleeUid, MeleeWeaponComponent component, ICommonSession? session) + { + if (!base.DoDisarm(user, ev, meleeUid, component, session)) + return false; + + if (!TryComp(user, out var combatMode) || + combatMode.CanDisarm != true) + { + return false; + } + + var target = GetEntity(ev.Target); + + // They need to either have hands... + if (!HasComp(target!.Value)) + { + // or just be able to be shoved over. + if (TryComp(target, out var status) && status.AllowedEffects.Contains("KnockedDown")) + return true; + + if (Timing.IsFirstTimePredicted && HasComp(target.Value)) + PopupSystem.PopupEntity(Loc.GetString("disarm-action-disarmable", ("targetName", target.Value)), target.Value); + + return false; + } + + return true; + } + + /// + /// Raises a heavy attack event with the relevant attacked entities. + /// This is to avoid lag effecting the client's perspective too much. + /// + public void ClientHeavyAttack(EntityUid user, EntityCoordinates coordinates, EntityUid meleeUid, MeleeWeaponComponent component) + { + // Only run on first prediction to avoid the potential raycast entities changing. + if (!_xformQuery.TryGetComponent(user, out var userXform) || + !Timing.IsFirstTimePredicted) + { + return; + } + + var targetMap = TransformSystem.ToMapCoordinates(coordinates); + + if (targetMap.MapId != userXform.MapID) + return; + + var userPos = TransformSystem.GetWorldPosition(userXform); + var direction = targetMap.Position - userPos; + var distance = MathF.Min(component.Range, direction.Length()); + + // This should really be improved. GetEntitiesInArc uses pos instead of bounding boxes. + // Server will validate it with InRangeUnobstructed. + var entities = GetNetEntityList(ArcRayCast(userPos, direction.ToWorldAngle(), component.Angle, distance, userXform.MapID, user).ToList()); + RaisePredictiveEvent(new HeavyAttackEvent(GetNetEntity(meleeUid), entities.GetRange(0, Math.Min(MaxTargets, entities.Count)), GetNetCoordinates(coordinates))); + } + + private void ClientDisarm(EntityUid attacker, MapCoordinates mousePos, EntityCoordinates coordinates) + { + EntityUid? target = null; + + if (_stateManager.CurrentState is GameplayStateBase screen) + target = screen.GetClickedEntity(mousePos); + + RaisePredictiveEvent(new DisarmAttackEvent(GetNetEntity(target), GetNetCoordinates(coordinates))); + } + + private void ClientLightAttack(EntityUid attacker, MapCoordinates mousePos, EntityCoordinates coordinates, EntityUid weaponUid, MeleeWeaponComponent meleeComponent) + { + var attackerPos = TransformSystem.GetMapCoordinates(attacker); + + if (mousePos.MapId != attackerPos.MapId || (attackerPos.Position - mousePos.Position).Length() > meleeComponent.Range) + return; + + EntityUid? target = null; + + if (_stateManager.CurrentState is GameplayStateBase screen) + target = screen.GetClickedEntity(mousePos); + + // Don't light-attack if interaction will be handling this instead + if (Interaction.CombatModeCanHandInteract(attacker, target)) + return; + + RaisePredictiveEvent(new LightAttackEvent(GetNetEntity(target), GetNetEntity(weaponUid), GetNetCoordinates(coordinates))); + } + // ADT TWEAK END private void OnMeleeLunge(MeleeLungeEvent ev) { var ent = GetEntity(ev.Entity); diff --git a/Content.Server/ADT/_RMC14/Scoping/ScopeSystem.cs b/Content.Server/ADT/_RMC14/Scoping/ScopeSystem.cs new file mode 100644 index 00000000000..91a49c34bea --- /dev/null +++ b/Content.Server/ADT/_RMC14/Scoping/ScopeSystem.cs @@ -0,0 +1,52 @@ +using Content.Shared._RMC14.Scoping; +using Robust.Server.GameObjects; +using Robust.Shared.Player; + +namespace Content.Server._RMC14.Scoping; + +public sealed class ScopeSystem : SharedScopeSystem +{ + [Dependency] private readonly ViewSubscriberSystem _viewSubscriber = default!; + + protected override Direction? StartScoping(Entity scope, EntityUid user) + { + if (base.StartScoping(scope, user) is not { } direction) + return null; + + scope.Comp.User = user; + + if (TryComp(user, out ActorComponent? actor)) + { + var coords = Transform(user).Coordinates; + var offset = GetScopeOffset(scope, direction); + scope.Comp.RelayEntity = SpawnAtPosition(null, coords.Offset(offset)); + _viewSubscriber.AddViewSubscriber(scope.Comp.RelayEntity.Value, actor.PlayerSession); + } + + return direction; + } + + protected override bool Unscope(Entity scope) + { + var user = scope.Comp.User; + if (!base.Unscope(scope)) + return false; + + DeleteRelay(scope, user); + return true; + } + + protected override void DeleteRelay(Entity scope, EntityUid? user) + { + if (scope.Comp.RelayEntity is not { } relay) + return; + + scope.Comp.RelayEntity = null; + + if (TryComp(user, out ActorComponent? actor)) + _viewSubscriber.RemoveViewSubscriber(relay, actor.PlayerSession); + + if (!TerminatingOrDeleted(relay)) + QueueDel(relay); + } +} diff --git a/Content.Server/ADT/_RMC14/Trigger/ActiveTriggerOnThrowEndComponent.cs b/Content.Server/ADT/_RMC14/Trigger/ActiveTriggerOnThrowEndComponent.cs new file mode 100644 index 00000000000..7d19414b305 --- /dev/null +++ b/Content.Server/ADT/_RMC14/Trigger/ActiveTriggerOnThrowEndComponent.cs @@ -0,0 +1,12 @@ +using Robust.Shared.GameStates; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom; + +namespace Content.Server._RMC14.Trigger; + +[RegisterComponent, AutoGenerateComponentPause] +[Access(typeof(RMCTriggerSystem))] +public sealed partial class ActiveTriggerOnThrowEndComponent : Component +{ + [DataField(customTypeSerializer: typeof(TimeOffsetSerializer)), AutoPausedField] + public TimeSpan TriggerAt; +} diff --git a/Content.Server/ADT/_RMC14/Trigger/OnShootTriggerAmmoTimerComponent.cs b/Content.Server/ADT/_RMC14/Trigger/OnShootTriggerAmmoTimerComponent.cs new file mode 100644 index 00000000000..0e9a0e9376b --- /dev/null +++ b/Content.Server/ADT/_RMC14/Trigger/OnShootTriggerAmmoTimerComponent.cs @@ -0,0 +1,20 @@ +using Robust.Shared.Audio; + +namespace Content.Server._RMC14.Trigger; + +[RegisterComponent] +[Access(typeof(RMCTriggerSystem))] +public sealed partial class OnShootTriggerAmmoTimerComponent : Component +{ + [DataField] + public float Delay; + + [DataField] + public float BeepInterval; + + [DataField] + public float? InitialBeepDelay; + + [DataField] + public SoundSpecifier? BeepSound; +} diff --git a/Content.Server/ADT/_RMC14/Trigger/RMCTriggerSystem.cs b/Content.Server/ADT/_RMC14/Trigger/RMCTriggerSystem.cs new file mode 100644 index 00000000000..d225aa96071 --- /dev/null +++ b/Content.Server/ADT/_RMC14/Trigger/RMCTriggerSystem.cs @@ -0,0 +1,48 @@ +using Content.Server.Explosion.EntitySystems; +using Content.Shared._RMC14.Weapons.Ranged; +using Content.Shared.Throwing; +using Content.Shared.Weapons.Ranged.Events; +using Robust.Shared.Timing; + +namespace Content.Server._RMC14.Trigger; + +public sealed class RMCTriggerSystem : EntitySystem +{ + [Dependency] private readonly IGameTiming _timing = default!; + [Dependency] private readonly TriggerSystem _trigger = default!; + + public override void Initialize() + { + SubscribeLocalEvent(OnTriggerTimerAmmoShot); + SubscribeLocalEvent(OnTriggerOnFixedDistanceStop); + } + + private void OnTriggerTimerAmmoShot(Entity ent, ref AmmoShotEvent args) + { + foreach (var projectile in args.FiredProjectiles) + { + _trigger.HandleTimerTrigger(projectile, null, ent.Comp.Delay, ent.Comp.BeepInterval, ent.Comp.InitialBeepDelay, ent.Comp.BeepSound); + } + } + + private void OnTriggerOnFixedDistanceStop(Entity ent, ref ProjectileFixedDistanceStopEvent args) + { + var active = EnsureComp(ent); + active.TriggerAt = _timing.CurTime + ent.Comp.Delay; + } + + public override void Update(float frameTime) + { + var time = _timing.CurTime; + var query = EntityQueryEnumerator(); + while (query.MoveNext(out var uid, out var active)) + { + if (time < active.TriggerAt) + continue; + + _trigger.Trigger(uid); + if (!EntityManager.IsQueuedForDeletion(uid) && !TerminatingOrDeleted(uid)) + QueueDel(uid); + } + } +} diff --git a/Content.Server/ADT/_RMC14/Trigger/TriggerOnFixedDistanceStopComponent.cs b/Content.Server/ADT/_RMC14/Trigger/TriggerOnFixedDistanceStopComponent.cs new file mode 100644 index 00000000000..f3346372fa2 --- /dev/null +++ b/Content.Server/ADT/_RMC14/Trigger/TriggerOnFixedDistanceStopComponent.cs @@ -0,0 +1,11 @@ +using Robust.Shared.GameStates; + +namespace Content.Server._RMC14.Trigger; + +[RegisterComponent] +[Access(typeof(RMCTriggerSystem))] +public sealed partial class TriggerOnFixedDistanceStopComponent : Component +{ + [DataField] + public TimeSpan Delay; +} diff --git a/Content.Server/ADT/_RMC14/Weapons/Melee/RMCMeleeWeaponSystem.cs b/Content.Server/ADT/_RMC14/Weapons/Melee/RMCMeleeWeaponSystem.cs new file mode 100644 index 00000000000..7df99629895 --- /dev/null +++ b/Content.Server/ADT/_RMC14/Weapons/Melee/RMCMeleeWeaponSystem.cs @@ -0,0 +1,5 @@ +using Content.Shared._RMC14.Weapons.Melee; + +namespace Content.Server._RMC14.Weapons.Melee; + +public sealed class RMCMeleeWeaponSystem : SharedRMCMeleeWeaponSystem; diff --git a/Content.Server/ADT/_RMC14/Weapons/Ranged/PumpActionSystem.cs b/Content.Server/ADT/_RMC14/Weapons/Ranged/PumpActionSystem.cs new file mode 100644 index 00000000000..b1b08add8d6 --- /dev/null +++ b/Content.Server/ADT/_RMC14/Weapons/Ranged/PumpActionSystem.cs @@ -0,0 +1,5 @@ +using Content.Shared._RMC14.Weapons.Ranged; + +namespace Content.Server._RMC14.Weapons.Ranged; + +public sealed class PumpActionSystem : SharedPumpActionSystem; diff --git a/Content.Shared/ADT/Crawling/Components/AntiLyingWarriorComponent.cs b/Content.Shared/ADT/Crawling/Components/AntiLyingWarriorComponent.cs new file mode 100644 index 00000000000..a983e677250 --- /dev/null +++ b/Content.Shared/ADT/Crawling/Components/AntiLyingWarriorComponent.cs @@ -0,0 +1,8 @@ +using Robust.Shared.GameStates; + +namespace Content.Shared.ADT.Crawling; + +[RegisterComponent, NetworkedComponent] +public sealed partial class AntiLyingWarriorComponent : Component +{ +} diff --git a/Content.Shared/ADT/_RMC14/Actions/ActionCooldownComponent.cs b/Content.Shared/ADT/_RMC14/Actions/ActionCooldownComponent.cs new file mode 100644 index 00000000000..0b9637ea10c --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Actions/ActionCooldownComponent.cs @@ -0,0 +1,11 @@ +using Robust.Shared.GameStates; + +namespace Content.Shared._RMC14.Actions; + +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +[Access(typeof(RMCActionsSystem))] +public sealed partial class ActionCooldownComponent : Component +{ + [DataField, AutoNetworkedField] + public TimeSpan Cooldown; +} diff --git a/Content.Shared/ADT/_RMC14/Actions/ActionReducedUseDelayComponent.cs b/Content.Shared/ADT/_RMC14/Actions/ActionReducedUseDelayComponent.cs new file mode 100644 index 00000000000..381b3db3d4b --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Actions/ActionReducedUseDelayComponent.cs @@ -0,0 +1,18 @@ +using Content.Shared.FixedPoint; +using Robust.Shared.GameStates; +using Robust.Shared.Prototypes; + +namespace Content.Shared._RMC14.Actions; + +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +[Access(typeof(RMCActionsSystem))] +public sealed partial class ActionReducedUseDelayComponent : Component +{ + // Default cooldown without reductions + [DataField, AutoNetworkedField] + public TimeSpan? UseDelayBase = default!; + + // Cooldown reduction percentage + [DataField, AutoNetworkedField] + public FixedPoint2 UseDelayReduction = default!; +} diff --git a/Content.Shared/ADT/_RMC14/Actions/ActionReducedUseDelayEvent.cs b/Content.Shared/ADT/_RMC14/Actions/ActionReducedUseDelayEvent.cs new file mode 100644 index 00000000000..b4a1ceab71f --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Actions/ActionReducedUseDelayEvent.cs @@ -0,0 +1,7 @@ +using Content.Shared.FixedPoint; + +namespace Content.Shared._RMC14.Actions; + +// If amount is 0, will reset usedelay to default value +// If amount is between 0 and 1, will reduce usedelay +public record struct ActionReducedUseDelayEvent(FixedPoint2 Amount); diff --git a/Content.Shared/ADT/_RMC14/Actions/ActionSharedCooldownComponent.cs b/Content.Shared/ADT/_RMC14/Actions/ActionSharedCooldownComponent.cs new file mode 100644 index 00000000000..1db4e0888bc --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Actions/ActionSharedCooldownComponent.cs @@ -0,0 +1,21 @@ +using Robust.Shared.GameStates; +using Robust.Shared.Prototypes; + +namespace Content.Shared._RMC14.Actions; + +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +[Access(typeof(RMCActionsSystem))] +public sealed partial class ActionSharedCooldownComponent : Component +{ + [DataField, AutoNetworkedField] + public EntProtoId? Id; + + [DataField, AutoNetworkedField] + public HashSet Ids = new(); + + [DataField, AutoNetworkedField] + public TimeSpan Cooldown; + + [DataField, AutoNetworkedField] + public bool OnPerform = true; +} diff --git a/Content.Shared/ADT/_RMC14/Actions/RMCActionUseAttemptEvent.cs b/Content.Shared/ADT/_RMC14/Actions/RMCActionUseAttemptEvent.cs new file mode 100644 index 00000000000..cea0989c2b4 --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Actions/RMCActionUseAttemptEvent.cs @@ -0,0 +1,4 @@ +namespace Content.Shared._RMC14.Actions; + +[ByRefEvent] +public record struct RMCActionUseAttemptEvent(EntityUid User, bool Cancelled = false); diff --git a/Content.Shared/ADT/_RMC14/Actions/RMCActionUseEvent.cs b/Content.Shared/ADT/_RMC14/Actions/RMCActionUseEvent.cs new file mode 100644 index 00000000000..cb3490f8e3c --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Actions/RMCActionUseEvent.cs @@ -0,0 +1,4 @@ +namespace Content.Shared._RMC14.Actions; + +[ByRefEvent] +public readonly record struct RMCActionUseEvent(EntityUid User); diff --git a/Content.Shared/ADT/_RMC14/Actions/RMCActionsSystem.cs b/Content.Shared/ADT/_RMC14/Actions/RMCActionsSystem.cs new file mode 100644 index 00000000000..a5f77834033 --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Actions/RMCActionsSystem.cs @@ -0,0 +1,126 @@ +using Content.Shared.Actions; +using Content.Shared.Actions.Events; +using Content.Shared.FixedPoint; + +namespace Content.Shared._RMC14.Actions; + +public sealed class RMCActionsSystem : EntitySystem +{ + [Dependency] private readonly SharedActionsSystem _actions = default!; + + private EntityQuery _actionSharedCooldownQuery; + + public override void Initialize() + { + _actionSharedCooldownQuery = GetEntityQuery(); + + SubscribeLocalEvent(OnSharedCooldownPerformed); + + SubscribeLocalEvent(OnCooldownUse); + + SubscribeLocalEvent(OnReducedUseDelayEvent); + SubscribeLocalEvent(OnReducedUseDelayEvent); + SubscribeLocalEvent(OnReducedUseDelayEvent); + SubscribeLocalEvent(OnReducedUseDelayEvent); + } + + private void OnSharedCooldownPerformed(Entity ent, ref ActionPerformedEvent args) + { + if (ent.Comp.OnPerform) + ActivateSharedCooldown((ent, ent), args.Performer); + } + + public void ActivateSharedCooldown(Entity action, EntityUid performer) + { + if (!Resolve(action, ref action.Comp, false)) + return; + + if (action.Comp.Cooldown == TimeSpan.Zero) + return; + + foreach (var (actionId, _) in _actions.GetActions(performer)) + { + if (!_actionSharedCooldownQuery.TryComp(actionId, out var shared)) + continue; + + // Same ID or primary ID found in subset of other action's ids + if ((shared.Id != null && shared.Id == action.Comp.Id) || (action.Comp.Id != null && shared.Ids.Contains(action.Comp.Id.Value))) + _actions.SetIfBiggerCooldown(actionId, action.Comp.Cooldown); + } + } + + private void OnReducedUseDelayEvent(EntityUid uid, T component, ActionReducedUseDelayEvent args) where T : BaseActionComponent + { + if (!TryComp(uid, out ActionReducedUseDelayComponent? comp)) + return; + + if (args.Amount < 0 || args.Amount > 1) + return; + + comp.UseDelayReduction = args.Amount; + + if (TryComp(uid, out ActionSharedCooldownComponent? shared)) + { + if (comp.UseDelayBase == null) + comp.UseDelayBase = shared.Cooldown; + + RefreshSharedUseDelay((uid, comp), shared); + return; + } + + // Should be fine to only set this once as the base use delay should remain constant + if (comp.UseDelayBase == null) + comp.UseDelayBase = component.UseDelay; + + RefreshUseDelay((uid, comp)); + } + + private void RefreshUseDelay(Entity ent) + { + if (ent.Comp.UseDelayBase is not { } delayBase) + return; + + var reduction = ent.Comp.UseDelayReduction.Double(); + var delayNew = delayBase.Multiply(1 - reduction); + + _actions.SetUseDelay(ent.Owner, delayNew); + } + + private void RefreshSharedUseDelay(Entity ent, ActionSharedCooldownComponent shared) + { + if (ent.Comp.UseDelayBase is not { } delayBase) + return; + + var reduction = ent.Comp.UseDelayReduction.Double(); + var delayNew = delayBase.Multiply(1 - reduction); + + shared.Cooldown = delayNew; + } + + private void OnCooldownUse(Entity ent, ref RMCActionUseEvent args) + { + _actions.SetIfBiggerCooldown(ent, ent.Comp.Cooldown); + } + + public bool CanUseActionPopup(EntityUid user, EntityUid action) + { + var ev = new RMCActionUseAttemptEvent(user); + RaiseLocalEvent(action, ref ev); + return !ev.Cancelled; + } + + public void ActionUsed(EntityUid user, EntityUid action) + { + var ev = new RMCActionUseEvent(user); + RaiseLocalEvent(action, ref ev); + } + + public bool TryUseAction(EntityUid user, EntityUid action) + { + if (!CanUseActionPopup(user, action)) + return false; + + ActionUsed(user, action); + return true; + } +} diff --git a/Content.Shared/ADT/_RMC14/Armor/Magnetic/RMCMagneticItemComponent.cs b/Content.Shared/ADT/_RMC14/Armor/Magnetic/RMCMagneticItemComponent.cs new file mode 100644 index 00000000000..dc3bf644f13 --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Armor/Magnetic/RMCMagneticItemComponent.cs @@ -0,0 +1,12 @@ +using Content.Shared.Inventory; +using Robust.Shared.GameStates; + +namespace Content.Shared._RMC14.Armor.Magnetic; + +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +[Access(typeof(RMCMagneticSystem))] +public sealed partial class RMCMagneticItemComponent : Component +{ + [DataField, AutoNetworkedField] + public SlotFlags MagnetizeToSlots = SlotFlags.SUITSTORAGE; +} diff --git a/Content.Shared/ADT/_RMC14/Armor/Magnetic/RMCMagneticSystem.cs b/Content.Shared/ADT/_RMC14/Armor/Magnetic/RMCMagneticSystem.cs new file mode 100644 index 00000000000..d70d58ea8c7 --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Armor/Magnetic/RMCMagneticSystem.cs @@ -0,0 +1,78 @@ +using Content.Shared.Hands; +using Content.Shared.Interaction.Events; +using Content.Shared.Inventory; +using Content.Shared.Popups; + +namespace Content.Shared._RMC14.Armor.Magnetic; + +public sealed class RMCMagneticSystem : EntitySystem +{ + [Dependency] private readonly InventorySystem _inventory = default!; + [Dependency] private readonly SharedPopupSystem _popup = default!; + + public override void Initialize() + { + SubscribeLocalEvent(OnMagneticItemDropped); + SubscribeLocalEvent(OnMagneticItemDropAttempt); + } + + private void OnMagneticItemDropped(Entity ent, ref DroppedEvent args) + { + TryReturn(ent, args.User); + } + + private void OnMagneticItemDropAttempt(Entity ent, ref DropAttemptEvent args) + { + args.Cancel(); + } + + private bool TryReturn(Entity ent, EntityUid user) + { + var returnComp = EnsureComp(ent); + returnComp.User = user; + + Dirty(ent, returnComp); + return true; + } + + public void SetMagnetizeToSlots(Entity ent, SlotFlags slots) + { + ent.Comp.MagnetizeToSlots = slots; + Dirty(ent); + } + + public override void Update(float frameTime) + { + var query = EntityQueryEnumerator(); + while (query.MoveNext(out var uid, out var comp)) + { + if (comp.Returned) + continue; + + var user = comp.User; + if (!TerminatingOrDeleted(user)) + { + var slots = _inventory.GetSlotEnumerator(user, SlotFlags.SUITSTORAGE); + while (slots.MoveNext(out var slot)) + { + if (_inventory.TryGetSlotEntity(user, "outerClothing", out _)) + { + if (_inventory.TryEquip(user, uid, slot.ID, force: true)) + { + var popup = Loc.GetString("rmc-magnetize-return", + ("item", uid), + ("user", user)); + _popup.PopupClient(popup, user, user, PopupType.Medium); + + comp.Returned = true; + Dirty(uid, comp); + break; + } + } + } + } + + RemCompDeferred(uid); + } + } +} diff --git a/Content.Shared/ADT/_RMC14/Armor/Magnetic/RMCReturnToInventoryComponent.cs b/Content.Shared/ADT/_RMC14/Armor/Magnetic/RMCReturnToInventoryComponent.cs new file mode 100644 index 00000000000..23dbc58ac0d --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Armor/Magnetic/RMCReturnToInventoryComponent.cs @@ -0,0 +1,14 @@ +using Robust.Shared.GameStates; + +namespace Content.Shared._RMC14.Armor.Magnetic; + +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +[Access(typeof(RMCMagneticSystem))] +public sealed partial class RMCReturnToInventoryComponent : Component +{ + [DataField, AutoNetworkedField] + public EntityUid User; + + [DataField, AutoNetworkedField] + public bool Returned; +} diff --git a/Content.Shared/ADT/_RMC14/Attachable/AttachableData.cs b/Content.Shared/ADT/_RMC14/Attachable/AttachableData.cs new file mode 100644 index 00000000000..24719659bd6 --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Attachable/AttachableData.cs @@ -0,0 +1,79 @@ +using Content.Shared.Damage; +using Content.Shared.FixedPoint; +using Content.Shared.Weapons.Ranged.Components; +using Content.Shared.Whitelist; +using Robust.Shared.Prototypes; +using Robust.Shared.Serialization; + +namespace Content.Shared._RMC14.Attachable; + +[DataRecord, Serializable, NetSerializable] +public record struct AttachableSlot( + bool Locked, + EntityWhitelist Whitelist, + ProtoId? StartingAttachable +); + +[DataRecord, Serializable, NetSerializable] +public record struct AttachableModifierConditions( + bool UnwieldedOnly, + bool WieldedOnly, + bool ActiveOnly, + bool InactiveOnly, + EntityWhitelist? Whitelist, + EntityWhitelist? Blacklist +); + +[DataRecord, Serializable, NetSerializable] +public record struct AttachableWeaponMeleeModifierSet( + AttachableModifierConditions? Conditions, + DamageSpecifier? BonusDamage, + DamageSpecifier? DecreaseDamage +); + +[DataRecord, Serializable, NetSerializable] +public record struct AttachableWeaponRangedModifierSet( + AttachableModifierConditions? Conditions, + FixedPoint2 AccuracyAddMult, // Not implemented yet. Added to have all the values already on our attachments, so whoever implements this doesn't need to dig through CM13. Remove this comment once implemented. + FixedPoint2 AccuracyMovementPenaltyAddMult, // As above. + FixedPoint2 DamageFalloffAddMult, // This affects the damage falloff of all shots fired by the weapon. Conversion to RMC: damage_falloff_mod + double BurstScatterAddMult, // This affects scatter during burst and full-auto fire. Conversion to RMC: burst_scatter_mod + int ShotsPerBurstFlat, // Modifies the maximum number of shots in a burst. + FixedPoint2 DamageAddMult, // Additive multiplier to damage. + float RecoilFlat, // How much the camera shakes when you shoot. + double ScatterFlat, // Scatter in degrees. This is how far bullets go from where you aim. Conversion to RMC: CM_SCATTER * 2 + float FireDelayFlat, // The delay between each shot. Conversion to RMC: CM_FIRE_DELAY / 10 + float ProjectileSpeedFlat // How fast the projectiles move. Conversion to RMC: CM_PROJECTILE_SPEED * 10 +); + +[DataRecord, Serializable, NetSerializable] +public record struct AttachableWeaponFireModesModifierSet( + AttachableModifierConditions? Conditions, + SelectiveFire ExtraFireModes, + SelectiveFire SetFireMode +); + +// SS13 has move delay instead of speed. Move delay isn't implemented here, and approximating it through maths like fire delay is scuffed because of how the events used to change speed work. +// So instead we take the default speed values and use them to convert it to a multiplier beforehand. +// Converting from move delay to additive multiplier: 1 / (1 / SS14_SPEED + SS13_MOVE_DELAY / 10) / SS14_SPEED - 1 +// Speed and move delay are inversely proportional. So 1 divided by speed is move delay and vice versa. +// We then add the ss13 move delay, and divide 1 by the result to convert it back into speed. +// Then we divide it by the original speed and subtract 1 from the result to get the additive multiplier. +[DataRecord, Serializable, NetSerializable] +public record struct AttachableSpeedModifierSet( + AttachableModifierConditions? Conditions, + float Walk, // Default human walk speed: 2.5f + float Sprint // Default human sprint speed: 4.5f +); + +[DataRecord, Serializable, NetSerializable] +public record struct AttachableSizeModifierSet( + AttachableModifierConditions? Conditions, + int Size +); + +[DataRecord, Serializable, NetSerializable] +public record struct AttachableWieldDelayModifierSet( + AttachableModifierConditions? Conditions, + TimeSpan Delay +); diff --git a/Content.Shared/ADT/_RMC14/Attachable/AttachableUI.cs b/Content.Shared/ADT/_RMC14/Attachable/AttachableUI.cs new file mode 100644 index 00000000000..4bab6dbb2b8 --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Attachable/AttachableUI.cs @@ -0,0 +1,35 @@ +using Robust.Shared.Serialization; + +namespace Content.Shared._RMC14.Attachable; + +[Serializable, NetSerializable] +public sealed class AttachableHolderStripUserInterfaceState(Dictionary attachableSlots) + : BoundUserInterfaceState +{ + public Dictionary AttachableSlots = attachableSlots; +} + +[Serializable, NetSerializable] +public sealed class AttachableHolderChooseSlotUserInterfaceState(List attachableSlots) : BoundUserInterfaceState +{ + public List AttachableSlots = attachableSlots; +} + +[Serializable, NetSerializable] +public sealed class AttachableHolderDetachMessage(string slot) : BoundUserInterfaceMessage +{ + public readonly string Slot = slot; +} + +[Serializable, NetSerializable] +public sealed class AttachableHolderAttachToSlotMessage(string slot) : BoundUserInterfaceMessage +{ + public readonly string Slot = slot; +} + +[Serializable, NetSerializable] +public enum AttachmentUI : byte +{ + StripKey, + ChooseSlotKey, +} diff --git a/Content.Shared/ADT/_RMC14/Attachable/Components/AttachableAntiLyingWarriorComponent.cs b/Content.Shared/ADT/_RMC14/Attachable/Components/AttachableAntiLyingWarriorComponent.cs new file mode 100644 index 00000000000..4a4d3d6c963 --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Attachable/Components/AttachableAntiLyingWarriorComponent.cs @@ -0,0 +1,9 @@ +using Content.Shared._RMC14.Attachable.Systems; +using Robust.Shared.GameStates; + +namespace Content.Shared._RMC14.Attachable.Components; + +[RegisterComponent, NetworkedComponent] +public sealed partial class AttachableAntiLyingWarriorComponent : Component +{ +} diff --git a/Content.Shared/ADT/_RMC14/Attachable/Components/AttachableComponent.cs b/Content.Shared/ADT/_RMC14/Attachable/Components/AttachableComponent.cs new file mode 100644 index 00000000000..31cd00678e9 --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Attachable/Components/AttachableComponent.cs @@ -0,0 +1,19 @@ +using Content.Shared._RMC14.Attachable.Systems; +using Robust.Shared.Audio; +using Robust.Shared.GameStates; + +namespace Content.Shared._RMC14.Attachable.Components; + +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +[Access(typeof(AttachableHolderSystem))] +public sealed partial class AttachableComponent : Component +{ + [DataField, AutoNetworkedField] + public float AttachDoAfter = 1.5f; + + [DataField, AutoNetworkedField] + public SoundSpecifier? AttachSound = new SoundPathSpecifier("/Audio/ADT/Attachments/attachment_add.ogg", AudioParams.Default.WithVolume(-6.5f)); + + [DataField, AutoNetworkedField] + public SoundSpecifier? DetachSound = new SoundPathSpecifier("/Audio/ADT/Attachments/attachment_remove.ogg", AudioParams.Default.WithVolume(-5.5f)); +} diff --git a/Content.Shared/ADT/_RMC14/Attachable/Components/AttachableDirectionLockedComponent.cs b/Content.Shared/ADT/_RMC14/Attachable/Components/AttachableDirectionLockedComponent.cs new file mode 100644 index 00000000000..24c59fbc609 --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Attachable/Components/AttachableDirectionLockedComponent.cs @@ -0,0 +1,16 @@ +using Content.Shared._RMC14.Attachable.Systems; +using Robust.Shared.GameStates; + +namespace Content.Shared._RMC14.Attachable.Components; + +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +[Access(typeof(AttachableToggleableSystem))] +public sealed partial class AttachableDirectionLockedComponent : Component +{ + [DataField, AutoNetworkedField] + public List AttachableList = new(); + + [DataField, AutoNetworkedField] + public Direction? LockedDirection; +} + diff --git a/Content.Shared/ADT/_RMC14/Attachable/Components/AttachableGunPreventShootComponent.cs b/Content.Shared/ADT/_RMC14/Attachable/Components/AttachableGunPreventShootComponent.cs new file mode 100644 index 00000000000..b706b01b7aa --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Attachable/Components/AttachableGunPreventShootComponent.cs @@ -0,0 +1,15 @@ +using Content.Shared._RMC14.Attachable.Systems; +using Robust.Shared.GameStates; + +namespace Content.Shared._RMC14.Attachable.Components; + +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +[Access(typeof(AttachableToggleableSystem))] +public sealed partial class AttachableGunPreventShootComponent : Component +{ + [DataField, AutoNetworkedField] + public bool PreventShoot; + + [DataField, AutoNetworkedField] + public string Message = ""; +} diff --git a/Content.Shared/ADT/_RMC14/Attachable/Components/AttachableHolderComponent.cs b/Content.Shared/ADT/_RMC14/Attachable/Components/AttachableHolderComponent.cs new file mode 100644 index 00000000000..d57a17f1503 --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Attachable/Components/AttachableHolderComponent.cs @@ -0,0 +1,32 @@ +using Content.Shared._RMC14.Attachable.Systems; +using Content.Shared.Whitelist; +using Robust.Shared.GameStates; + +namespace Content.Shared._RMC14.Attachable.Components; + +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +[Access(typeof(AttachableHolderSystem))] +public sealed partial class AttachableHolderComponent : Component +{ + [DataField, AutoNetworkedField] + public EntityUid? SupercedingAttachable; + + /// + /// The key is one of the slot IDs at the bottom of this file. + /// Each key is followed by the description of the slot. + /// + [DataField, AutoNetworkedField] + public Dictionary Slots = new(); +} + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Slot IDs should be named as follows: rmc-aslot-SLOTNAME, for example: rmc-aslot-barrel. * + * Each slot ID must have a name attached to it in \Resources\Locale\en-US\_RMC14\attachable\attachable.ftl * + * The slot list is below. If you add more, list them here so others can use the comment for reference. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * GUN SLOTS: + * rmc-aslot-barrel + * rmc-aslot-rail + * rmc-aslot-stock + * rmc-aslot-underbarrel + */ diff --git a/Content.Shared/ADT/_RMC14/Attachable/Components/AttachableMagneticComponent.cs b/Content.Shared/ADT/_RMC14/Attachable/Components/AttachableMagneticComponent.cs new file mode 100644 index 00000000000..575fa3dbeb8 --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Attachable/Components/AttachableMagneticComponent.cs @@ -0,0 +1,13 @@ +using Content.Shared._RMC14.Attachable.Systems; +using Content.Shared.Inventory; +using Robust.Shared.GameStates; + +namespace Content.Shared._RMC14.Attachable.Components; + +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +[Access(typeof(AttachableMagneticSystem))] +public sealed partial class AttachableMagneticComponent : Component +{ + [DataField, AutoNetworkedField] + public SlotFlags MagnetizeToSlots = SlotFlags.SUITSTORAGE; +} diff --git a/Content.Shared/ADT/_RMC14/Attachable/Components/AttachableMovementLockedComponent.cs b/Content.Shared/ADT/_RMC14/Attachable/Components/AttachableMovementLockedComponent.cs new file mode 100644 index 00000000000..84350a654f2 --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Attachable/Components/AttachableMovementLockedComponent.cs @@ -0,0 +1,13 @@ +using Content.Shared._RMC14.Attachable.Systems; +using Robust.Shared.GameStates; + +namespace Content.Shared._RMC14.Attachable.Components; + +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +[Access(typeof(AttachableToggleableSystem))] +public sealed partial class AttachableMovementLockedComponent : Component +{ + [DataField, AutoNetworkedField] + public List AttachableList = new(); +} + diff --git a/Content.Shared/ADT/_RMC14/Attachable/Components/AttachablePreventDropToggleableComponent.cs b/Content.Shared/ADT/_RMC14/Attachable/Components/AttachablePreventDropToggleableComponent.cs new file mode 100644 index 00000000000..747ba3d7f64 --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Attachable/Components/AttachablePreventDropToggleableComponent.cs @@ -0,0 +1,8 @@ +using Content.Shared._RMC14.Attachable.Systems; +using Robust.Shared.GameStates; + +namespace Content.Shared._RMC14.Attachable.Components; + +[RegisterComponent, NetworkedComponent] +[Access(typeof(AttachablePreventDropSystem))] +public sealed partial class AttachablePreventDropToggleableComponent : Component; diff --git a/Content.Shared/ADT/_RMC14/Attachable/Components/AttachablePryingComponent.cs b/Content.Shared/ADT/_RMC14/Attachable/Components/AttachablePryingComponent.cs new file mode 100644 index 00000000000..42ce4afedb4 --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Attachable/Components/AttachablePryingComponent.cs @@ -0,0 +1,8 @@ +using Content.Shared._RMC14.Attachable.Systems; +using Robust.Shared.GameStates; + +namespace Content.Shared._RMC14.Attachable.Components; + +[RegisterComponent, NetworkedComponent] +[Access(typeof(AttachablePryingSystem))] +public sealed partial class AttachablePryingComponent : Component; diff --git a/Content.Shared/ADT/_RMC14/Attachable/Components/AttachableSideLockedComponent.cs b/Content.Shared/ADT/_RMC14/Attachable/Components/AttachableSideLockedComponent.cs new file mode 100644 index 00000000000..a2cfcaf2776 --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Attachable/Components/AttachableSideLockedComponent.cs @@ -0,0 +1,18 @@ +using Content.Shared._RMC14.Attachable.Systems; +using Robust.Shared.GameStates; + +namespace Content.Shared._RMC14.Attachable.Components; + +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +[Access(typeof(AttachableToggleableSystem))] +public sealed partial class AttachableSideLockedComponent : Component +{ + [DataField, AutoNetworkedField] + public List AttachableList = new(); + + /// + /// The cardinal direction the attachments are locked into. In this case, direction is counted as a full 180 degrees, rather than 90. + /// + [DataField, AutoNetworkedField] + public Direction? LockedDirection; +} diff --git a/Content.Shared/ADT/_RMC14/Attachable/Components/AttachableSilencerComponent.cs b/Content.Shared/ADT/_RMC14/Attachable/Components/AttachableSilencerComponent.cs new file mode 100644 index 00000000000..58fd203003b --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Attachable/Components/AttachableSilencerComponent.cs @@ -0,0 +1,13 @@ +using Content.Shared._RMC14.Attachable.Systems; +using Robust.Shared.Audio; +using Robust.Shared.GameStates; + +namespace Content.Shared._RMC14.Attachable.Components; + +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +[Access(typeof(AttachableSilencerSystem))] +public sealed partial class AttachableSilencerComponent : Component +{ + [DataField, AutoNetworkedField] + public SoundSpecifier Sound = new SoundCollectionSpecifier("ADTSilencedShoot"); +} diff --git a/Content.Shared/ADT/_RMC14/Attachable/Components/AttachableSizeModsComponent.cs b/Content.Shared/ADT/_RMC14/Attachable/Components/AttachableSizeModsComponent.cs new file mode 100644 index 00000000000..ad86fe9a910 --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Attachable/Components/AttachableSizeModsComponent.cs @@ -0,0 +1,12 @@ +using Content.Shared._RMC14.Attachable.Systems; +using Robust.Shared.GameStates; + +namespace Content.Shared._RMC14.Attachable.Components; + +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +[Access(typeof(AttachableModifiersSystem))] +public sealed partial class AttachableSizeModsComponent : Component +{ + [DataField, AutoNetworkedField] + public List Modifiers = new(); +} diff --git a/Content.Shared/ADT/_RMC14/Attachable/Components/AttachableSpeedModsComponent.cs b/Content.Shared/ADT/_RMC14/Attachable/Components/AttachableSpeedModsComponent.cs new file mode 100644 index 00000000000..7af2a4b6cf5 --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Attachable/Components/AttachableSpeedModsComponent.cs @@ -0,0 +1,13 @@ +using Content.Shared._RMC14.Attachable.Systems; +using Robust.Shared.GameStates; + +namespace Content.Shared._RMC14.Attachable.Components; + +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +[Access(typeof(AttachableModifiersSystem))] +public sealed partial class AttachableSpeedModsComponent : Component +{ + [DataField, AutoNetworkedField] + public List Modifiers = new(); +} + diff --git a/Content.Shared/ADT/_RMC14/Attachable/Components/AttachableTemporarySpeedModsComponent.cs b/Content.Shared/ADT/_RMC14/Attachable/Components/AttachableTemporarySpeedModsComponent.cs new file mode 100644 index 00000000000..aa898116ac3 --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Attachable/Components/AttachableTemporarySpeedModsComponent.cs @@ -0,0 +1,19 @@ +using Content.Shared._RMC14.Attachable.Events; +using Content.Shared._RMC14.Attachable.Systems; +using Content.Shared._RMC14.Movement; +using Robust.Shared.GameStates; + +namespace Content.Shared._RMC14.Attachable.Components; + +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +[Access(typeof(AttachableTemporarySpeedModsSystem))] +public sealed partial class AttachableTemporarySpeedModsComponent : Component +{ + [DataField, AutoNetworkedField] + public AttachableAlteredType Alteration = AttachableAlteredType.Interrupted; + + [DataField, AutoNetworkedField] + public List Modifiers = new(); +} + + diff --git a/Content.Shared/ADT/_RMC14/Attachable/Components/AttachableToggleableComponent.cs b/Content.Shared/ADT/_RMC14/Attachable/Components/AttachableToggleableComponent.cs new file mode 100644 index 00000000000..66520bbccea --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Attachable/Components/AttachableToggleableComponent.cs @@ -0,0 +1,148 @@ +using Content.Shared._RMC14.Attachable.Systems; +using Content.Shared.Whitelist; +using Robust.Shared.Audio; +using Robust.Shared.GameStates; +using Robust.Shared.Utility; + +namespace Content.Shared._RMC14.Attachable.Components; + +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +[Access(typeof(AttachableToggleableSystem))] +public sealed partial class AttachableToggleableComponent : Component +{ + /// + /// Whether the attachment is currently active. + /// + [DataField, AutoNetworkedField] + public bool Active = false; + + /// + /// If set to true, the attachment will deactivate upon switching hands. + /// + [DataField, AutoNetworkedField] + public bool NeedHand = false; + + /// + /// If set to true, the attachment will not toggle itself when its action is interrupted. Used in cases where the item toggles itself separately, like scopes. + /// + [DataField, AutoNetworkedField] + public bool DoInterrupt = false; + + /// + /// If set to true, the attachment will deactivate upon moving. + /// + [DataField, AutoNetworkedField] + public bool BreakOnMove = false; + + /// + /// If set to true, the attachment will deactivate upon rotating to any direction other than the one it was activated in. + /// + [DataField, AutoNetworkedField] + public bool BreakOnRotate = false; + + /// + /// If set to true, the attachment will deactivate upon rotating 90 degrees away from the one it was activated in. + /// + [DataField, AutoNetworkedField] + public bool BreakOnFullRotate = false; + + /// + /// If set to true, the attachment can only be toggled when the holder is wielded. + /// + [DataField, AutoNetworkedField] + public bool WieldedOnly = false; + + /// + /// If set to true, the attachment can only be used when the holder is wielded. + /// + [DataField, AutoNetworkedField] + public bool WieldedUseOnly = false; + + /// + /// If set to true, the attachment can only be activated when someone is holding it. + /// + [DataField, AutoNetworkedField] + public bool HeldOnlyActivate = false; + + /// + /// Only the person holding or wearing the holder can activate this attachment. + /// + [DataField, AutoNetworkedField] + public bool UserOnly = false; + + [DataField, AutoNetworkedField] + public TimeSpan UseDelay = TimeSpan.FromSeconds(0f); + + [DataField, AutoNetworkedField] + public float DoAfter; + + [DataField, AutoNetworkedField] + public float? DeactivateDoAfter; + + [DataField, AutoNetworkedField] + public bool DoAfterNeedHand = true; + + [DataField, AutoNetworkedField] + public bool DoAfterBreakOnMove = true; + + [DataField, AutoNetworkedField] + public AttachableInstantToggleConditions InstantToggle = AttachableInstantToggleConditions.None; + + /// + /// If set to true, this attachment will block some of the holder's functionality when active and perform it instead. + /// Used for attached weapons, like the UGL. + /// + [DataField, AutoNetworkedField] + public bool SupercedeHolder = false; + + /// + /// If set to true, this attachment's functions only work when it's attached to a holder. + /// + [DataField, AutoNetworkedField] + public bool AttachedOnly = false; + + [DataField, AutoNetworkedField] + public SoundSpecifier? ActivateSound = new SoundPathSpecifier("/Audio/ADT/Attachments/attachment_activate.ogg"); + + [DataField, AutoNetworkedField] + public SoundSpecifier? DeactivateSound = new SoundPathSpecifier("/Audio/ADT/Attachments/attachment_deactivate.ogg"); + + [DataField, AutoNetworkedField] + public bool ShowTogglePopup = true; + + [DataField, AutoNetworkedField] + public LocId ActivatePopupText = new LocId("attachable-popup-activate-generic"); + + [DataField, AutoNetworkedField] + public LocId DeactivatePopupText = new LocId("attachable-popup-deactivate-generic"); + + [DataField, AutoNetworkedField] + public EntityUid? Action; + + [DataField, AutoNetworkedField] + public string ActionId = "ADTActionToggleAttachable"; + + [DataField, AutoNetworkedField] + public string ActionName = "Toggle Attachable"; + + [DataField, AutoNetworkedField] + public string ActionDesc = "Toggle an attachable. If you're seeing this, someone forgot to set the description properly."; + + [DataField, AutoNetworkedField] + public EntityWhitelist? ActionsToRelayWhitelist; + + [DataField, AutoNetworkedField] + public SpriteSpecifier Icon = new SpriteSpecifier.Rsi(new ResPath("_RMC14/Objects/Weapons/Guns/Attachments/rail.rsi"), "flashlight"); + + [DataField, AutoNetworkedField] + public SpriteSpecifier? IconActive; + + [DataField, AutoNetworkedField] + public bool Attached = false; +} + +public enum AttachableInstantToggleConditions : byte +{ + None = 0, + Brace = 1 << 0 +} diff --git a/Content.Shared/ADT/_RMC14/Attachable/Components/AttachableToggleablePreventShootComponent.cs b/Content.Shared/ADT/_RMC14/Attachable/Components/AttachableToggleablePreventShootComponent.cs new file mode 100644 index 00000000000..82dd1ed5c36 --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Attachable/Components/AttachableToggleablePreventShootComponent.cs @@ -0,0 +1,15 @@ +using Content.Shared._RMC14.Attachable.Systems; +using Robust.Shared.GameStates; + +namespace Content.Shared._RMC14.Attachable.Components; + +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +[Access(typeof(AttachableToggleableSystem))] +public sealed partial class AttachableToggleablePreventShootComponent : Component +{ + [DataField, AutoNetworkedField] + public bool ShootWhenActive = true; + + [DataField, AutoNetworkedField] + public string Message = "You can't shoot this right now!"; +} diff --git a/Content.Shared/ADT/_RMC14/Attachable/Components/AttachableToggleableSimpleActivateComponent.cs b/Content.Shared/ADT/_RMC14/Attachable/Components/AttachableToggleableSimpleActivateComponent.cs new file mode 100644 index 00000000000..16b531a14bf --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Attachable/Components/AttachableToggleableSimpleActivateComponent.cs @@ -0,0 +1,8 @@ +using Content.Shared._RMC14.Attachable.Systems; +using Robust.Shared.GameStates; + +namespace Content.Shared._RMC14.Attachable.Components; + +[RegisterComponent, NetworkedComponent] +[Access(typeof(AttachableToggleableSystem))] +public sealed partial class AttachableToggleableSimpleActivateComponent : Component; diff --git a/Content.Shared/ADT/_RMC14/Attachable/Components/AttachableWeaponMeleeModsComponent.cs b/Content.Shared/ADT/_RMC14/Attachable/Components/AttachableWeaponMeleeModsComponent.cs new file mode 100644 index 00000000000..3f20d62f373 --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Attachable/Components/AttachableWeaponMeleeModsComponent.cs @@ -0,0 +1,12 @@ +using Content.Shared._RMC14.Attachable.Systems; +using Robust.Shared.GameStates; + +namespace Content.Shared._RMC14.Attachable.Components; + +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +[Access(typeof(AttachableModifiersSystem))] +public sealed partial class AttachableWeaponMeleeModsComponent : Component +{ + [DataField, AutoNetworkedField] + public List Modifiers = new(); +} diff --git a/Content.Shared/ADT/_RMC14/Attachable/Components/AttachableWeaponRangedModsComponent.cs b/Content.Shared/ADT/_RMC14/Attachable/Components/AttachableWeaponRangedModsComponent.cs new file mode 100644 index 00000000000..f4ba342fd31 --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Attachable/Components/AttachableWeaponRangedModsComponent.cs @@ -0,0 +1,15 @@ +using Content.Shared._RMC14.Attachable.Systems; +using Robust.Shared.GameStates; + +namespace Content.Shared._RMC14.Attachable.Components; + +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +[Access(typeof(AttachableModifiersSystem))] +public sealed partial class AttachableWeaponRangedModsComponent : Component +{ + [DataField, AutoNetworkedField] + public List Modifiers = new(); + + [DataField, AutoNetworkedField] + public List? FireModeMods; +} diff --git a/Content.Shared/ADT/_RMC14/Attachable/Components/AttachableWieldDelayModsComponent.cs b/Content.Shared/ADT/_RMC14/Attachable/Components/AttachableWieldDelayModsComponent.cs new file mode 100644 index 00000000000..de609b9e813 --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Attachable/Components/AttachableWieldDelayModsComponent.cs @@ -0,0 +1,13 @@ +using Content.Shared._RMC14.Attachable.Systems; +using Robust.Shared.GameStates; + +namespace Content.Shared._RMC14.Attachable.Components; + +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +[Access(typeof(AttachableModifiersSystem))] +public sealed partial class AttachableWieldDelayModsComponent : Component +{ + [DataField, AutoNetworkedField] + public List Modifiers = new(); +} + diff --git a/Content.Shared/ADT/_RMC14/Attachable/Events/AttachableAlteredEvent.cs b/Content.Shared/ADT/_RMC14/Attachable/Events/AttachableAlteredEvent.cs new file mode 100644 index 00000000000..838ca6cc4cf --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Attachable/Events/AttachableAlteredEvent.cs @@ -0,0 +1,21 @@ +namespace Content.Shared._RMC14.Attachable.Events; + +[ByRefEvent] +public readonly record struct AttachableAlteredEvent( + EntityUid Holder, + AttachableAlteredType Alteration, + EntityUid? User = null +); + +public enum AttachableAlteredType : byte +{ + Attached = 1 << 0, + Detached = 1 << 1, + Wielded = 1 << 2, + Unwielded = 1 << 3, + Activated = 1 << 4, + Deactivated = 1 << 5, + Interrupted = 1 << 6, // This is used when a toggleable attachment is deactivated by something other than its hotkey or action. + AppearanceChanged = 1 << 7, + DetachedDeactivated = Detached | Deactivated, +} diff --git a/Content.Shared/ADT/_RMC14/Attachable/Events/AttachableAttachDoAfterEvent.cs b/Content.Shared/ADT/_RMC14/Attachable/Events/AttachableAttachDoAfterEvent.cs new file mode 100644 index 00000000000..124ac4ba79d --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Attachable/Events/AttachableAttachDoAfterEvent.cs @@ -0,0 +1,15 @@ +using Content.Shared.DoAfter; +using Robust.Shared.Serialization; + +namespace Content.Shared._RMC14.Attachable.Events; + +[Serializable, NetSerializable] +public sealed partial class AttachableAttachDoAfterEvent : SimpleDoAfterEvent +{ + public readonly string SlotId; + + public AttachableAttachDoAfterEvent(string slotId) + { + SlotId = slotId; + } +} diff --git a/Content.Shared/ADT/_RMC14/Attachable/Events/AttachableDetachDoAfterEvent.cs b/Content.Shared/ADT/_RMC14/Attachable/Events/AttachableDetachDoAfterEvent.cs new file mode 100644 index 00000000000..bbe430752b4 --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Attachable/Events/AttachableDetachDoAfterEvent.cs @@ -0,0 +1,7 @@ +using Content.Shared.DoAfter; +using Robust.Shared.Serialization; + +namespace Content.Shared._RMC14.Attachable.Events; + +[Serializable, NetSerializable] +public sealed partial class AttachableDetachDoAfterEvent : SimpleDoAfterEvent; diff --git a/Content.Shared/ADT/_RMC14/Attachable/Events/AttachableGetExamineDataEvent.cs b/Content.Shared/ADT/_RMC14/Attachable/Events/AttachableGetExamineDataEvent.cs new file mode 100644 index 00000000000..6becd4e87fc --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Attachable/Events/AttachableGetExamineDataEvent.cs @@ -0,0 +1,4 @@ +namespace Content.Shared._RMC14.Attachable.Events; + +[ByRefEvent] +public readonly record struct AttachableGetExamineDataEvent(Dictionary effectStrings)> Data); diff --git a/Content.Shared/ADT/_RMC14/Attachable/Events/AttachableHolderAttachablesAlteredEvent.cs b/Content.Shared/ADT/_RMC14/Attachable/Events/AttachableHolderAttachablesAlteredEvent.cs new file mode 100644 index 00000000000..0d60bfd8da9 --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Attachable/Events/AttachableHolderAttachablesAlteredEvent.cs @@ -0,0 +1,8 @@ +namespace Content.Shared._RMC14.Attachable.Events; + +[ByRefEvent] +public readonly record struct AttachableHolderAttachablesAlteredEvent( + EntityUid Attachable, + string SlotId, + AttachableAlteredType Alteration +); diff --git a/Content.Shared/ADT/_RMC14/Attachable/Events/AttachableRelayedEvent.cs b/Content.Shared/ADT/_RMC14/Attachable/Events/AttachableRelayedEvent.cs new file mode 100644 index 00000000000..d2842104ee4 --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Attachable/Events/AttachableRelayedEvent.cs @@ -0,0 +1,16 @@ +namespace Content.Shared._RMC14.Attachable.Events; + +/// +/// Wrapper for events relayed to attachables by their holder. +/// +public sealed class AttachableRelayedEvent : EntityEventArgs +{ + public TEvent Args; + public EntityUid Holder; + + public AttachableRelayedEvent(TEvent args, EntityUid holder) + { + Args = args; + Holder = holder; + } +} diff --git a/Content.Shared/ADT/_RMC14/Attachable/Events/AttachableToggleDoAfterEvent.cs b/Content.Shared/ADT/_RMC14/Attachable/Events/AttachableToggleDoAfterEvent.cs new file mode 100644 index 00000000000..1fb9f1e1318 --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Attachable/Events/AttachableToggleDoAfterEvent.cs @@ -0,0 +1,17 @@ +using Content.Shared.DoAfter; +using Robust.Shared.Serialization; + +namespace Content.Shared._RMC14.Attachable.Events; + +[Serializable, NetSerializable] +public sealed partial class AttachableToggleDoAfterEvent : SimpleDoAfterEvent +{ + public readonly string SlotId; + public readonly string PopupText; + + public AttachableToggleDoAfterEvent(string slotId, string popupText) + { + SlotId = slotId; + PopupText = popupText; + } +} diff --git a/Content.Shared/ADT/_RMC14/Attachable/Events/AttachableToggleStartedEvent.cs b/Content.Shared/ADT/_RMC14/Attachable/Events/AttachableToggleStartedEvent.cs new file mode 100644 index 00000000000..0ec1cba3cd3 --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Attachable/Events/AttachableToggleStartedEvent.cs @@ -0,0 +1,10 @@ +using Content.Shared._RMC14.Attachable.Components; + +namespace Content.Shared._RMC14.Attachable.Events; + +[ByRefEvent] +public readonly record struct AttachableToggleStartedEvent( + EntityUid Holder, + EntityUid User, + string SlotId +); diff --git a/Content.Shared/ADT/_RMC14/Attachable/Events/AttachableToggleableInterruptEvent.cs b/Content.Shared/ADT/_RMC14/Attachable/Events/AttachableToggleableInterruptEvent.cs new file mode 100644 index 00000000000..2f4bbbbcedd --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Attachable/Events/AttachableToggleableInterruptEvent.cs @@ -0,0 +1,8 @@ +using Content.Shared._RMC14.Attachable.Components; + +namespace Content.Shared._RMC14.Attachable.Events; + +[ByRefEvent] +public readonly record struct AttachableToggleableInterruptEvent( + EntityUid User +); diff --git a/Content.Shared/ADT/_RMC14/Attachable/Events/GrantAttachableActionsEvent.cs b/Content.Shared/ADT/_RMC14/Attachable/Events/GrantAttachableActionsEvent.cs new file mode 100644 index 00000000000..2a7357c61c8 --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Attachable/Events/GrantAttachableActionsEvent.cs @@ -0,0 +1,4 @@ +namespace Content.Shared._RMC14.Attachable.Events; + +[ByRefEvent] +public readonly record struct GrantAttachableActionsEvent(EntityUid User); diff --git a/Content.Shared/ADT/_RMC14/Attachable/Events/RemoveAttachableActionsEvent.cs b/Content.Shared/ADT/_RMC14/Attachable/Events/RemoveAttachableActionsEvent.cs new file mode 100644 index 00000000000..231dbfe5bba --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Attachable/Events/RemoveAttachableActionsEvent.cs @@ -0,0 +1,4 @@ +namespace Content.Shared._RMC14.Attachable.Events; + +[ByRefEvent] +public readonly record struct RemoveAttachableActionsEvent(EntityUid User); diff --git a/Content.Shared/ADT/_RMC14/Attachable/Systems/AttachableAntiLyingWarriorSystem.cs b/Content.Shared/ADT/_RMC14/Attachable/Systems/AttachableAntiLyingWarriorSystem.cs new file mode 100644 index 00000000000..8c554d558e5 --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Attachable/Systems/AttachableAntiLyingWarriorSystem.cs @@ -0,0 +1,28 @@ +using Content.Shared._RMC14.Attachable.Components; +using Content.Shared._RMC14.Attachable.Events; +using Content.Shared.ADT.Crawling; + +namespace Content.Shared._RMC14.Attachable.Systems; + +public sealed class AttachableAntiLyingWarriorSystem : EntitySystem +{ + + public override void Initialize() + { + SubscribeLocalEvent(OnAttachableAltered); + } + + private void OnAttachableAltered(Entity attachable, ref AttachableAlteredEvent args) + { + switch (args.Alteration) + { + case AttachableAlteredType.Attached: + EnsureComp(args.Holder); + break; + + case AttachableAlteredType.Detached: + RemCompDeferred(args.Holder); + break; + } + } +} diff --git a/Content.Shared/ADT/_RMC14/Attachable/Systems/AttachableHolderSystem.cs b/Content.Shared/ADT/_RMC14/Attachable/Systems/AttachableHolderSystem.cs new file mode 100644 index 00000000000..f3e31709adb --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Attachable/Systems/AttachableHolderSystem.cs @@ -0,0 +1,741 @@ +using System.Diagnostics.CodeAnalysis; +using System.Numerics; +using Content.Shared._RMC14.Attachable.Components; +using Content.Shared._RMC14.Attachable.Events; +using Content.Shared._RMC14.Input; +using Content.Shared._RMC14.Item; +using Content.Shared._RMC14.Weapons.Common; +using Content.Shared._RMC14.Weapons.Ranged; +using Content.Shared._RMC14.Wieldable.Events; +using Content.Shared.ActionBlocker; +using Content.Shared.Containers; +using Content.Shared.DoAfter; +using Content.Shared.Hands; +using Content.Shared.Hands.Components; +using Content.Shared.Hands.EntitySystems; +using Content.Shared.Interaction; +using Content.Shared.Verbs; +using Content.Shared.Weapons.Melee.Events; +using Content.Shared.Weapons.Ranged.Components; +using Content.Shared.Weapons.Ranged.Events; +using Content.Shared.Weapons.Ranged.Systems; +using Content.Shared.Whitelist; +using Content.Shared.Wieldable; +using Robust.Shared.Audio.Systems; +using Robust.Shared.Containers; +using Robust.Shared.Input.Binding; +using Robust.Shared.Map; + +namespace Content.Shared._RMC14.Attachable.Systems; + +public sealed class AttachableHolderSystem : EntitySystem +{ + [Dependency] private readonly ActionBlockerSystem _actionBlocker = default!; + [Dependency] private readonly EntityWhitelistSystem _whitelist = default!; + [Dependency] private readonly SharedAudioSystem _audio = default!; + [Dependency] private readonly SharedContainerSystem _container = default!; + [Dependency] private readonly SharedDoAfterSystem _doAfter = default!; + [Dependency] private readonly SharedGunSystem _gun = default!; + [Dependency] private readonly SharedHandsSystem _hands = default!; + [Dependency] private readonly SharedUserInterfaceSystem _ui = default!; + [Dependency] private readonly SharedVerbSystem _verbSystem = default!; + + public override void Initialize() + { + SubscribeLocalEvent(OnAttachDoAfter); + SubscribeLocalEvent(OnDetachDoAfter); + SubscribeLocalEvent(OnAttachableHolderAttachToSlotMessage); + SubscribeLocalEvent(OnAttachableHolderDetachMessage); + SubscribeLocalEvent(OnAttachableHolderAttemptShoot); + SubscribeLocalEvent(RelayEvent); + SubscribeLocalEvent(OnAttachableHolderUiOpened); + SubscribeLocalEvent(OnAttached); + SubscribeLocalEvent(OnHolderMapInit, + after: new[] { typeof(ContainerFillSystem) }); + SubscribeLocalEvent>(OnAttachableHolderGetVerbs); + SubscribeLocalEvent(RelayEvent); + SubscribeLocalEvent(RelayEvent); + SubscribeLocalEvent(RelayEvent, + after: new[] { typeof(WieldableSystem) }); + SubscribeLocalEvent(OnAttachableHolderInteractUsing); + SubscribeLocalEvent(OnAttachableHolderInteractInWorld); + SubscribeLocalEvent(OnHolderWielded); + SubscribeLocalEvent(OnHolderUnwielded); + SubscribeLocalEvent(OnAttachableHolderUniqueAction); + SubscribeLocalEvent(RelayEvent); + SubscribeLocalEvent(RelayEvent); + SubscribeLocalEvent(RelayEvent); + SubscribeLocalEvent(RelayEvent); + SubscribeLocalEvent(RelayEvent); + SubscribeLocalEvent(RelayEvent); + SubscribeLocalEvent(RelayEvent); + SubscribeLocalEvent(RelayEvent); + SubscribeLocalEvent(RelayEvent); + SubscribeLocalEvent(RelayEvent); + SubscribeLocalEvent(RelayEvent); + SubscribeLocalEvent(RelayEvent); + SubscribeLocalEvent(RelayEvent); + + + CommandBinds.Builder + .Bind(CMKeyFunctions.RMCActivateAttachableBarrel, + InputCmdHandler.FromDelegate(session => + { + if (session?.AttachedEntity is { } userUid) + ToggleAttachable(userUid, "rmc-aslot-barrel"); + }, + handle: false)) + .Bind(CMKeyFunctions.RMCActivateAttachableRail, + InputCmdHandler.FromDelegate(session => + { + if (session?.AttachedEntity is { } userUid) + ToggleAttachable(userUid, "rmc-aslot-rail"); + }, + handle: false)) + .Bind(CMKeyFunctions.RMCActivateAttachableStock, + InputCmdHandler.FromDelegate(session => + { + if (session?.AttachedEntity is { } userUid) + ToggleAttachable(userUid, "rmc-aslot-stock"); + }, + handle: false)) + .Bind(CMKeyFunctions.RMCActivateAttachableUnderbarrel, + InputCmdHandler.FromDelegate(session => + { + if (session?.AttachedEntity is { } userUid) + ToggleAttachable(userUid, "rmc-aslot-underbarrel"); + }, + handle: false)) + .Bind(CMKeyFunctions.RMCFieldStripHeldItem, + InputCmdHandler.FromDelegate(session => + { + if (session?.AttachedEntity is { } userUid) + FieldStripHeldItem(userUid); + }, + handle: false)) + .Register(); + } + + public override void Shutdown() + { + CommandBinds.Unregister(); + } + + private void OnHolderMapInit(Entity holder, ref MapInitEvent args) + { + var xform = Transform(holder.Owner); + var coords = new EntityCoordinates(holder.Owner, Vector2.Zero); + + foreach (var slotId in holder.Comp.Slots.Keys) + { + if (holder.Comp.Slots[slotId].StartingAttachable == null) + continue; + + var container = _container.EnsureContainer(holder, slotId); + container.OccludesLight = false; + + var attachableUid = Spawn(holder.Comp.Slots[slotId].StartingAttachable, coords); + if (!_container.Insert(attachableUid, container, containerXform: xform)) + continue; + } + + Dirty(holder); + } + + private void OnAttachableHolderInteractUsing(Entity holder, ref InteractUsingEvent args) + { + if (CanAttach(holder, args.Used)) + { + StartAttach(holder, args.Used, args.User); + args.Handled = true; + } + + if (holder.Comp.SupercedingAttachable == null) + return; + + var interactUsingEvent = new InteractUsingEvent(args.User, + args.Used, + holder.Comp.SupercedingAttachable.Value, + args.ClickLocation); + RaiseLocalEvent(holder.Comp.SupercedingAttachable.Value, interactUsingEvent); + + if (interactUsingEvent.Handled) + { + args.Handled = true; + return; + } + + var afterInteractEvent = new AfterInteractEvent(args.User, + args.Used, + holder.Comp.SupercedingAttachable.Value, + args.ClickLocation, + true); + RaiseLocalEvent(args.Used, afterInteractEvent); + + if (afterInteractEvent.Handled) + args.Handled = true; + } + + private void OnAttachableHolderInteractInWorld(Entity holder, ref ActivateInWorldEvent args) + { + if (args.Handled || holder.Comp.SupercedingAttachable == null) + return; + + var activateInWorldEvent = new ActivateInWorldEvent(args.User, holder.Comp.SupercedingAttachable.Value, args.Complex); + RaiseLocalEvent(holder.Comp.SupercedingAttachable.Value, activateInWorldEvent); + + args.Handled = activateInWorldEvent.Handled; + } + + private void OnAttachableHolderAttemptShoot(Entity holder, ref AttemptShootEvent args) + { + if (args.Cancelled) + return; + + if (holder.Comp.SupercedingAttachable == null) + return; + + args.Cancelled = true; + + if (!TryComp(holder.Owner, out var holderGunComponent) || + holderGunComponent.ShootCoordinates == null || + !TryComp(holder.Comp.SupercedingAttachable, + out var attachableGunComponent)) + { + return; + } + + _gun.AttemptShoot(args.User, + holder.Comp.SupercedingAttachable.Value, + attachableGunComponent, + holderGunComponent.ShootCoordinates.Value); + } + + private void OnAttachableHolderUniqueAction(Entity holder, ref UniqueActionEvent args) + { + if (holder.Comp.SupercedingAttachable == null || args.Handled) + return; + + RaiseLocalEvent(holder.Comp.SupercedingAttachable.Value, new UniqueActionEvent(args.UserUid)); + args.Handled = true; + } + + private void OnHolderWielded(Entity holder, ref ItemWieldedEvent args) + { + AlterAllAttachables(holder, AttachableAlteredType.Wielded); + } + + private void OnHolderUnwielded(Entity holder, ref ItemUnwieldedEvent args) + { + AlterAllAttachables(holder, AttachableAlteredType.Unwielded); + } + + private void OnAttachableHolderDetachMessage(EntityUid holderUid, + AttachableHolderComponent holderComponent, + AttachableHolderDetachMessage args) + { + StartDetach((holderUid, holderComponent), args.Slot, args.Actor); + } + + private void OnAttachableHolderGetVerbs(Entity holder, ref GetVerbsEvent args) + { + + EnsureSlots(holder); + var userUid = args.User; + + foreach (var slotId in holder.Comp.Slots.Keys) + { + if (_container.TryGetContainer(holder.Owner, slotId, out var container)) + { + foreach (var contained in container.ContainedEntities) + { + if (!TryComp(contained, out AttachableToggleableComponent? toggleableComponent)) + continue; + + if (toggleableComponent.UserOnly && + (!TryComp(holder.Owner, out TransformComponent? transformComponent) || !transformComponent.ParentUid.Valid || transformComponent.ParentUid != userUid)) + { + continue; + } + + var verb = new EquipmentVerb() + { + Text = toggleableComponent.ActionName, + IconEntity = GetNetEntity(contained), + Act = () => + { + var ev = new AttachableToggleStartedEvent(holder.Owner, userUid, slotId); + RaiseLocalEvent(contained, ref ev); + } + }; + + args.Verbs.Add(verb); + } + } + } + } + + private void OnAttachableHolderAttachToSlotMessage(EntityUid holderUid, + AttachableHolderComponent holderComponent, + AttachableHolderAttachToSlotMessage args) + { + TryComp(args.Actor, out var handsComponent); + + if (handsComponent == null) + return; + + _hands.TryGetActiveItem((args.Actor, handsComponent), out var attachableUid); + + if (attachableUid == null) + return; + + StartAttach((holderUid, holderComponent), attachableUid.Value, args.Actor, args.Slot); + } + + private void OnAttachableHolderUiOpened(EntityUid holderUid, + AttachableHolderComponent holderComponent, + BoundUIOpenedEvent args) + { + UpdateStripUi(holderUid); + } + + public void StartAttach(Entity holder, + EntityUid attachableUid, + EntityUid userUid, + string slotId = "") + { + + var validSlots = GetValidSlots(holder, attachableUid); + + if (validSlots.Count == 0) + return; + + if (string.IsNullOrEmpty(slotId)) + { + if (validSlots.Count > 1) + { + TryComp(holder.Owner, + out var userInterfaceComponent); + _ui.OpenUi((holder.Owner, userInterfaceComponent), AttachmentUI.ChooseSlotKey, userUid); + + var state = + new AttachableHolderChooseSlotUserInterfaceState(validSlots); + _ui.SetUiState(holder.Owner, AttachmentUI.ChooseSlotKey, state); + return; + } + + slotId = validSlots[0]; + } + + _doAfter.TryStartDoAfter(new DoAfterArgs( + EntityManager, + userUid, + Comp(attachableUid).AttachDoAfter, + new AttachableAttachDoAfterEvent(slotId), + holder, + target: holder.Owner, + used: attachableUid) + { + NeedHand = true, + BreakOnMove = true, + }); + } + + private void OnAttachDoAfter(EntityUid uid, AttachableHolderComponent component, AttachableAttachDoAfterEvent args) + { + if (args.Cancelled || args.Handled) + return; + + if (args.Target is not { } target || args.Used is not { } used) + return; + + if (!TryComp(args.Target, out AttachableHolderComponent? holder) || + !HasComp(args.Used)) + return; + + if (Attach((target, holder), used, args.User, args.SlotId)) + args.Handled = true; + } + + public bool Attach(Entity holder, + EntityUid attachableUid, + EntityUid userUid, + string slotId = "") + { + if (!CanAttach(holder, attachableUid, ref slotId)) + return false; + + var container = _container.EnsureContainer(holder, slotId); + container.OccludesLight = false; + + if (container.Count > 0 && !Detach(holder, container.ContainedEntities[0], userUid, slotId)) + return false; + + if (!_container.Insert(attachableUid, container)) + return false; + + if (_hands.IsHolding(userUid, holder.Owner)) + { + var addEv = new GrantAttachableActionsEvent(userUid); + RaiseLocalEvent(attachableUid, ref addEv); + } + + Dirty(holder); + + _gun.RefreshModifiers(holder.Owner); + _audio.PlayPredicted(Comp(attachableUid).AttachSound, + holder, + userUid); + + return true; + } + + private void OnAttached(Entity holder, ref EntInsertedIntoContainerMessage args) + { + if (!TryComp(args.Entity, out AttachableComponent? attachableComponent) || !holder.Comp.Slots.ContainsKey(args.Container.ID)) + return; + + UpdateStripUi(holder.Owner, holder.Comp); + + var ev = new AttachableAlteredEvent(holder.Owner, AttachableAlteredType.Attached); + RaiseLocalEvent(args.Entity, ref ev); + + var holderEv = new AttachableHolderAttachablesAlteredEvent(args.Entity, args.Container.ID, AttachableAlteredType.Attached); + RaiseLocalEvent(holder, ref holderEv); + } + + //Detaching + public void StartDetach(Entity holder, string slotId, EntityUid userUid) + { + if (TryGetAttachable(holder, slotId, out var attachable) && holder.Comp.Slots.ContainsKey(slotId) && !holder.Comp.Slots[slotId].Locked) + StartDetach(holder, attachable.Owner, userUid); + } + + public void StartDetach(Entity holder, EntityUid attachableUid, EntityUid userUid) + { + + var delay = Comp(attachableUid).AttachDoAfter; + var args = new DoAfterArgs( + EntityManager, + userUid, + delay, + new AttachableDetachDoAfterEvent(), + holder, + holder.Owner, + attachableUid) + { + NeedHand = true, + BreakOnMove = true, + }; + + _doAfter.TryStartDoAfter(args); + } + + private void OnDetachDoAfter(EntityUid uid, AttachableHolderComponent component, AttachableDetachDoAfterEvent args) + { + if (args.Cancelled || args.Handled || args.Target == null || args.Used == null) + return; + + if (!TryComp(args.Target, out AttachableHolderComponent? holderComponent) || !HasComp(args.Used)) + return; + + if (!Detach((args.Target.Value, holderComponent), args.Used.Value, args.User)) + return; + + args.Handled = true; + } + + public bool Detach(Entity holder, + EntityUid attachableUid, + EntityUid userUid, + string? slotId = null) + { + if (TerminatingOrDeleted(holder) || !holder.Comp.Running) + return false; + + if (string.IsNullOrEmpty(slotId) && !TryGetSlotId(holder.Owner, attachableUid, out slotId)) + return false; + + if (!_container.TryGetContainer(holder, slotId, out var container) || container.Count <= 0) + return false; + + if (!TryGetAttachable(holder, slotId, out var attachable)) + return false; + + if (!_container.Remove(attachable.Owner, container, force: true)) + return false; + + UpdateStripUi(holder.Owner, holder.Comp); + + var ev = new AttachableAlteredEvent(holder.Owner, AttachableAlteredType.Detached, userUid); + RaiseLocalEvent(attachableUid, ref ev); + + var holderEv = new AttachableHolderAttachablesAlteredEvent(attachableUid, slotId, AttachableAlteredType.Detached); + RaiseLocalEvent(holder.Owner, ref holderEv); + + var removeEv = new RemoveAttachableActionsEvent(userUid); + RaiseLocalEvent(attachableUid, ref removeEv); + + _audio.PlayPredicted(Comp(attachableUid).DetachSound, + holder, + userUid); + + Dirty(holder); + _gun.RefreshModifiers(holder.Owner); + _hands.TryPickupAnyHand(userUid, attachable); + return true; + } + + private bool CanAttach(Entity holder, EntityUid attachableUid) + { + var slotId = ""; + return CanAttach(holder, attachableUid, ref slotId); + } + + private bool CanAttach(Entity holder, EntityUid attachableUid, ref string slotId) + { + if (!HasComp(attachableUid)) + return false; + + if (!string.IsNullOrWhiteSpace(slotId)) + return _whitelist.IsWhitelistPass(holder.Comp.Slots[slotId].Whitelist, attachableUid); + + foreach (var key in holder.Comp.Slots.Keys) + { + if (_whitelist.IsWhitelistPass(holder.Comp.Slots[key].Whitelist, attachableUid)) + { + slotId = key; + return true; + } + } + + return false; + } + + private Dictionary GetSlotsForStripUi(Entity holder) + { + var result = new Dictionary(); + var metaQuery = GetEntityQuery(); + + foreach (var slotId in holder.Comp.Slots.Keys) + { + if (TryGetAttachable(holder, slotId, out var attachable) && + metaQuery.TryGetComponent(attachable.Owner, out var metadata)) + { + result.Add(slotId, (metadata.EntityName, holder.Comp.Slots[slotId].Locked)); + } + else + { + result.Add(slotId, (null, holder.Comp.Slots[slotId].Locked)); + } + } + + return result; + } + + public bool TryGetAttachable(Entity holder, + string slotId, + out Entity attachable) + { + attachable = default; + + if (!_container.TryGetContainer(holder, slotId, out var container) || container.Count <= 0) + return false; + + var ent = container.ContainedEntities[0]; + if (!TryComp(ent, out AttachableComponent? attachableComp)) + return false; + + attachable = (ent, attachableComp); + return true; + } + + private void UpdateStripUi(EntityUid holderUid, AttachableHolderComponent? holderComponent = null) + { + if (!Resolve(holderUid, ref holderComponent)) + return; + + var state = + new AttachableHolderStripUserInterfaceState(GetSlotsForStripUi((holderUid, holderComponent))); + _ui.SetUiState(holderUid, AttachmentUI.StripKey, state); + } + + private void EnsureSlots(Entity holder) + { + foreach (var slotId in holder.Comp.Slots.Keys) + { + var container = _container.EnsureContainer(holder, slotId); + container.OccludesLight = false; + } + } + + private List GetValidSlots(Entity holder, EntityUid attachableUid, bool ignoreLock = false) + { + var list = new List(); + + if (!HasComp(attachableUid)) + return list; + + foreach (var slotId in holder.Comp.Slots.Keys) + { + if (_whitelist.IsWhitelistPass(holder.Comp.Slots[slotId].Whitelist, attachableUid) && (!ignoreLock || !holder.Comp.Slots[slotId].Locked)) + list.Add(slotId); + } + + return list; + } + + private void ToggleAttachable(EntityUid userUid, string slotId) + { + if (!TryComp(userUid, out var handsComponent) || + !TryComp(handsComponent.ActiveHandEntity, out var holderComponent)) + { + return; + } + + var active = handsComponent.ActiveHandEntity; + if (!holderComponent.Running || !_actionBlocker.CanInteract(userUid, active)) + return; + + if (!_container.TryGetContainer(active.Value, + slotId, + out var container) || container.Count <= 0) + return; + + var attachableUid = container.ContainedEntities[0]; + + if (!HasComp(attachableUid)) + return; + + if (!TryComp(attachableUid, out var toggleableComponent)) + return; + + var ev = new AttachableToggleStartedEvent(active.Value, userUid, slotId); + RaiseLocalEvent(attachableUid, ref ev); + } + + private void FieldStripHeldItem(EntityUid userUid) + { + if (!TryComp(userUid, out var handsComponent) || + !TryComp(handsComponent.ActiveHandEntity, out var holderComponent)) + { + return; + } + + EntityUid holderUid = handsComponent.ActiveHandEntity.Value; + + if (!holderComponent.Running || !_actionBlocker.CanInteract(userUid, holderUid)) + return; + + foreach (var verb in _verbSystem.GetLocalVerbs(holderUid, userUid, typeof(Verb))) + { + if (!verb.Text.Equals(Loc.GetString("rmc-verb-strip-attachables"))) + continue; + + _verbSystem.ExecuteVerb(verb, userUid, holderUid); + break; + } + } + + public void SetSupercedingAttachable(Entity holder, EntityUid? supercedingAttachable) + { + holder.Comp.SupercedingAttachable = supercedingAttachable; + Dirty(holder); + } + + public bool TryGetSlotId(EntityUid holderUid, EntityUid attachableUid, [NotNullWhen(true)] out string? slotId) + { + slotId = null; + + if (!TryComp(holderUid, out var holderComponent) || + !TryComp(attachableUid, out _)) + { + return false; + } + + foreach (var id in holderComponent.Slots.Keys) + { + if (!_container.TryGetContainer(holderUid, id, out var container) || container.Count <= 0) + continue; + + if (container.ContainedEntities[0] != attachableUid) + continue; + + slotId = id; + return true; + } + + return false; + } + + public bool HasSlot(Entity holder, string slotId) + { + if (holder.Comp == null) + { + if (!TryComp(holder.Owner, out AttachableHolderComponent? holderComponent)) + return false; + + holder.Comp = holderComponent; + } + + return holder.Comp.Slots.ContainsKey(slotId); + } + + public bool TryGetHolder(EntityUid attachable, [NotNullWhen(true)] out EntityUid? holderUid) + { + if (!TryComp(attachable, out TransformComponent? transformComponent) || + !transformComponent.ParentUid.Valid || + !HasComp(transformComponent.ParentUid)) + { + holderUid = null; + return false; + } + + holderUid = transformComponent.ParentUid; + return true; + } + + public bool TryGetUser(EntityUid attachable, [NotNullWhen(true)] out EntityUid? userUid) + { + userUid = null; + + if (!TryGetHolder(attachable, out var holderUid)) + return false; + + if (!TryComp(holderUid, out TransformComponent? transformComponent) || !transformComponent.ParentUid.Valid) + return false; + + userUid = transformComponent.ParentUid; + return true; + } + + public void RelayEvent(Entity holder, ref T args) where T : notnull + { + var ev = new AttachableRelayedEvent(args, holder.Owner); + + foreach (var slot in holder.Comp.Slots.Keys) + { + if (_container.TryGetContainer(holder, slot, out var container)) + { + foreach (var contained in container.ContainedEntities) + { + RaiseLocalEvent(contained, ev); + } + } + } + + args = ev.Args; + } + + private void AlterAllAttachables(Entity holder, AttachableAlteredType alteration) + { + foreach (var slotId in holder.Comp.Slots.Keys) + { + if (!_container.TryGetContainer(holder, slotId, out var container) || container.Count <= 0) + continue; + + var ev = new AttachableAlteredEvent(holder.Owner, alteration); + RaiseLocalEvent(container.ContainedEntities[0], ref ev); + } + } +} diff --git a/Content.Shared/ADT/_RMC14/Attachable/Systems/AttachableMagneticSystem.cs b/Content.Shared/ADT/_RMC14/Attachable/Systems/AttachableMagneticSystem.cs new file mode 100644 index 00000000000..4ec3042de9a --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Attachable/Systems/AttachableMagneticSystem.cs @@ -0,0 +1,30 @@ +using Content.Shared._RMC14.Armor.Magnetic; +using Content.Shared._RMC14.Attachable.Components; +using Content.Shared._RMC14.Attachable.Events; + +namespace Content.Shared._RMC14.Attachable.Systems; + +public sealed class AttachableMagneticSystem : EntitySystem +{ + [Dependency] private readonly RMCMagneticSystem _magneticSystem = default!; + + public override void Initialize() + { + SubscribeLocalEvent(OnAttachableAltered); + } + + private void OnAttachableAltered(Entity attachable, ref AttachableAlteredEvent args) + { + switch (args.Alteration) + { + case AttachableAlteredType.Attached: + var comp = EnsureComp(args.Holder); + _magneticSystem.SetMagnetizeToSlots((args.Holder, comp), attachable.Comp.MagnetizeToSlots); + break; + + case AttachableAlteredType.Detached: + RemCompDeferred(args.Holder); + break; + } + } +} diff --git a/Content.Shared/ADT/_RMC14/Attachable/Systems/AttachableModifiersSystem.Melee.cs b/Content.Shared/ADT/_RMC14/Attachable/Systems/AttachableModifiersSystem.Melee.cs new file mode 100644 index 00000000000..38f44989db5 --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Attachable/Systems/AttachableModifiersSystem.Melee.cs @@ -0,0 +1,102 @@ +using Content.Shared._RMC14.Attachable.Components; +using Content.Shared._RMC14.Attachable.Events; +using Content.Shared.FixedPoint; +using Content.Shared.Weapons.Melee.Events; + +namespace Content.Shared._RMC14.Attachable.Systems; + +public sealed partial class AttachableModifiersSystem : EntitySystem +{ + private readonly Dictionary _damage = new(); + + private void InitializeMelee() + { + SubscribeLocalEvent(OnMeleeModsGetExamineData); + SubscribeLocalEvent>(OnMeleeModsHitEvent); + } + + private void OnMeleeModsGetExamineData(Entity attachable, ref AttachableGetExamineDataEvent args) + { + foreach (var modSet in attachable.Comp.Modifiers) + { + var key = GetExamineKey(modSet.Conditions); + + if (!args.Data.ContainsKey(key)) + args.Data[key] = new (modSet.Conditions, GetEffectStrings(modSet)); + else + args.Data[key].effectStrings.AddRange(GetEffectStrings(modSet)); + } + } + + private List GetEffectStrings(AttachableWeaponMeleeModifierSet modSet) + { + var result = new List(); + + + if (modSet.BonusDamage != null) + { + var bonusDamage = modSet.BonusDamage.GetTotal(); + if (bonusDamage != 0) + result.Add(Loc.GetString("rmc-attachable-examine-melee-damage", + ("colour", modifierExamineColour), ("sign", bonusDamage > 0 ? '+' : ""), ("damage", bonusDamage))); + } + + return result; + } + + private void OnMeleeModsHitEvent(Entity attachable, ref AttachableRelayedEvent args) + { + foreach(var modSet in attachable.Comp.Modifiers) + { + ApplyModifierSet(attachable, modSet, ref args.Args); + } + } + + private void ApplyModifierSet(Entity attachable, AttachableWeaponMeleeModifierSet modSet, ref MeleeHitEvent args) + { + if (!_attachableHolderSystem.TryGetHolder(attachable, out _) || + !CanApplyModifiers(attachable.Owner, modSet.Conditions)) + { + return; + } + + if (modSet.BonusDamage != null) + args.BonusDamage += modSet.BonusDamage; + + if (modSet.DecreaseDamage != null) + { + foreach (var (decreaseId, decreaseDmg) in modSet.DecreaseDamage.DamageDict) + { + if (decreaseDmg <= FixedPoint2.Zero) + continue; + + if (args.BaseDamage.DamageDict.TryGetValue(decreaseId, out var baseDamage)) + args.BaseDamage.DamageDict[decreaseId] = FixedPoint2.Max(baseDamage - decreaseDmg, FixedPoint2.Zero); + } + } + + if (args.BonusDamage.GetTotal() < FixedPoint2.Zero) + { + _damage.Clear(); + foreach (var (bonusId, bonusDmg) in args.BonusDamage.DamageDict) + { + if (bonusDmg > FixedPoint2.Zero) + continue; + + if (!args.BaseDamage.DamageDict.TryGetValue(bonusId, out var baseDamage)) + { + _damage[bonusId] = -bonusDmg; + continue; + } + + if (-bonusDmg > baseDamage) + _damage[bonusId] = -bonusDmg - baseDamage; + } + + foreach (var (bonusId, bonusDmg) in _damage) + { + args.BonusDamage.DamageDict[bonusId] = -bonusDmg; + } + } + } +} diff --git a/Content.Shared/ADT/_RMC14/Attachable/Systems/AttachableModifiersSystem.Ranged.cs b/Content.Shared/ADT/_RMC14/Attachable/Systems/AttachableModifiersSystem.Ranged.cs new file mode 100644 index 00000000000..4652539d339 --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Attachable/Systems/AttachableModifiersSystem.Ranged.cs @@ -0,0 +1,165 @@ +using Content.Shared._RMC14.Attachable.Components; +using Content.Shared._RMC14.Attachable.Events; +using Content.Shared._RMC14.Weapons.Ranged; +using Content.Shared.Weapons.Ranged.Components; +using Content.Shared.Weapons.Ranged.Events; + +namespace Content.Shared._RMC14.Attachable.Systems; + +public sealed partial class AttachableModifiersSystem : EntitySystem +{ + private void InitializeRanged() + { + SubscribeLocalEvent(OnRangedModsAltered); + SubscribeLocalEvent(OnRangedModsGetExamineData); + SubscribeLocalEvent>(OnRangedGetFireModes); + SubscribeLocalEvent>(OnRangedModsGetFireModeValues); + SubscribeLocalEvent>(OnRangedModsGetDamageFalloff); + SubscribeLocalEvent>(OnRangedModsGetGunDamage); + SubscribeLocalEvent>(OnRangedModsRefreshModifiers); + } + + private void OnRangedModsGetExamineData(Entity attachable, ref AttachableGetExamineDataEvent args) + { + foreach (var modSet in attachable.Comp.Modifiers) + { + var key = GetExamineKey(modSet.Conditions); + + if (!args.Data.ContainsKey(key)) + args.Data[key] = new (modSet.Conditions, GetEffectStrings(modSet)); + else + args.Data[key].effectStrings.AddRange(GetEffectStrings(modSet)); + } + } + + private List GetEffectStrings(AttachableWeaponRangedModifierSet modSet) + { + var result = new List(); + + if (modSet.ScatterFlat != 0) + result.Add(Loc.GetString("rmc-attachable-examine-ranged-scatter", + ("colour", modifierExamineColour), ("sign", modSet.ScatterFlat > 0 ? '+' : ""), ("scatter", modSet.ScatterFlat))); + + if (modSet.BurstScatterAddMult != 0) + result.Add(Loc.GetString("rmc-attachable-examine-ranged-burst-scatter", + ("colour", modifierExamineColour), ("sign", modSet.BurstScatterAddMult > 0 ? '+' : ""), ("burstScatterMult", modSet.BurstScatterAddMult))); + + if (modSet.ShotsPerBurstFlat != 0) + result.Add(Loc.GetString("rmc-attachable-examine-ranged-shots-per-burst", + ("colour", modifierExamineColour), ("sign", modSet.ShotsPerBurstFlat > 0 ? '+' : ""), ("shots", modSet.ShotsPerBurstFlat))); + + if (modSet.FireDelayFlat != 0) + result.Add(Loc.GetString("rmc-attachable-examine-ranged-fire-delay", + ("colour", modifierExamineColour), ("sign", modSet.FireDelayFlat > 0 ? '+' : ""), ("fireDelay", modSet.FireDelayFlat))); + + if (modSet.RecoilFlat != 0) + result.Add(Loc.GetString("rmc-attachable-examine-ranged-recoil", + ("colour", modifierExamineColour), ("sign", modSet.RecoilFlat > 0 ? '+' : ""), ("recoil", modSet.RecoilFlat))); + + if (modSet.DamageAddMult != 0) + result.Add(Loc.GetString("rmc-attachable-examine-ranged-damage", + ("colour", modifierExamineColour), ("sign", modSet.DamageAddMult > 0 ? '+' : ""), ("damage", modSet.DamageAddMult))); + + if (modSet.ProjectileSpeedFlat != 0) + result.Add(Loc.GetString("rmc-attachable-examine-ranged-projectile-speed", + ("colour", modifierExamineColour), ("sign", modSet.ProjectileSpeedFlat > 0 ? '+' : ""), ("projectileSpeed", modSet.ProjectileSpeedFlat))); + + if (modSet.DamageFalloffAddMult != 0) + result.Add(Loc.GetString("rmc-attachable-examine-ranged-damage-falloff", + ("colour", modifierExamineColour), ("sign", modSet.DamageFalloffAddMult > 0 ? '+' : ""), ("falloff", modSet.DamageFalloffAddMult))); + + return result; + } + + private void OnRangedModsAltered(Entity attachable, ref AttachableAlteredEvent args) + { + switch(args.Alteration) + { + case AttachableAlteredType.AppearanceChanged: + break; + + case AttachableAlteredType.DetachedDeactivated: + break; + + default: + + if (attachable.Comp.FireModeMods != null) + { + _rmcSelectiveFireSystem.RefreshFireModes(args.Holder, true); + break; + } + + _rmcSelectiveFireSystem.RefreshModifiableFireModeValues(args.Holder); + break; + } + } + + private void OnRangedModsRefreshModifiers(Entity attachable, ref AttachableRelayedEvent args) + { + foreach(var modSet in attachable.Comp.Modifiers) + { + if (!CanApplyModifiers(attachable.Owner, modSet.Conditions)) + continue; + + args.Args.ShotsPerBurst = Math.Max(args.Args.ShotsPerBurst + modSet.ShotsPerBurstFlat, 1); + args.Args.CameraRecoilScalar = Math.Max(args.Args.CameraRecoilScalar + modSet.RecoilFlat, 0); + args.Args.MinAngle = Angle.FromDegrees(Math.Max(args.Args.MinAngle.Degrees + modSet.ScatterFlat, 0.0)); + args.Args.MaxAngle = Angle.FromDegrees(Math.Max(args.Args.MaxAngle.Degrees + modSet.ScatterFlat, args.Args.MinAngle)); + args.Args.ProjectileSpeed += modSet.ProjectileSpeedFlat; + + // Fire delay doesn't work quite like SS14 fire rate, so we're having to do maths: + // Fire rate is shots per second. Fire delay is the interval between shots. They are inversely proportionate to each other. + // First we divide 1 second by the fire rate to get our current fire delay, then we add the delay modifier, then we divide 1 by the result again to get the modified fire rate. + var fireDelayMod = args.Args.Gun.Comp.SelectedMode == SelectiveFire.Burst ? modSet.FireDelayFlat / 2f : modSet.FireDelayFlat; + args.Args.FireRate = 1f / (1f / args.Args.FireRate + fireDelayMod); + } + } + + private void OnRangedGetFireModes(Entity attachable, ref AttachableRelayedEvent args) + { + if (attachable.Comp.FireModeMods == null) + return; + + foreach (var modSet in attachable.Comp.FireModeMods) + { + if (!CanApplyModifiers(attachable.Owner, modSet.Conditions)) + continue; + + args.Args.Modes |= modSet.ExtraFireModes; + args.Args.Set = modSet.SetFireMode; + } + } + + private void OnRangedModsGetDamageFalloff(Entity attachable, ref AttachableRelayedEvent args) + { + foreach (var modSet in attachable.Comp.Modifiers) + { + if (!CanApplyModifiers(attachable.Owner, modSet.Conditions)) + continue; + + args.Args.FalloffMultiplier += modSet.DamageFalloffAddMult; + } + } + + private void OnRangedModsGetGunDamage(Entity attachable, ref AttachableRelayedEvent args) + { + foreach (var modSet in attachable.Comp.Modifiers) + { + if (!CanApplyModifiers(attachable.Owner, modSet.Conditions)) + continue; + + args.Args.Multiplier += modSet.DamageAddMult; + } + } + + private void OnRangedModsGetFireModeValues(Entity attachable, ref AttachableRelayedEvent args) + { + foreach (var modSet in attachable.Comp.Modifiers) + { + if (!CanApplyModifiers(attachable.Owner, modSet.Conditions)) + continue; + + args.Args.BurstScatterMult += modSet.BurstScatterAddMult; + } + } +} diff --git a/Content.Shared/ADT/_RMC14/Attachable/Systems/AttachableModifiersSystem.Size.cs b/Content.Shared/ADT/_RMC14/Attachable/Systems/AttachableModifiersSystem.Size.cs new file mode 100644 index 00000000000..a5ddbfdac4b --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Attachable/Systems/AttachableModifiersSystem.Size.cs @@ -0,0 +1,71 @@ +using Content.Shared._RMC14.Attachable.Components; +using Content.Shared._RMC14.Attachable.Events; +using Content.Shared._RMC14.Item; + +namespace Content.Shared._RMC14.Attachable.Systems; + +public sealed partial class AttachableModifiersSystem : EntitySystem +{ + [Dependency] private readonly ItemSizeChangeSystem _itemSizeChangeSystem = default!; + + private void InitializeSize() + { + SubscribeLocalEvent(OnSizeModsGetExamineData); + SubscribeLocalEvent(OnAttachableAltered); + SubscribeLocalEvent>(OnGetItemSizeModifiers); + } + + private void OnSizeModsGetExamineData(Entity attachable, ref AttachableGetExamineDataEvent args) + { + foreach (var modSet in attachable.Comp.Modifiers) + { + var key = GetExamineKey(modSet.Conditions); + + if (!args.Data.ContainsKey(key)) + args.Data[key] = new (modSet.Conditions, GetEffectStrings(modSet)); + else + args.Data[key].effectStrings.AddRange(GetEffectStrings(modSet)); + } + } + + private List GetEffectStrings(AttachableSizeModifierSet modSet) + { + var result = new List(); + + if (modSet.Size != 0) + result.Add(Loc.GetString("rmc-attachable-examine-size", + ("colour", modifierExamineColour), ("sign", modSet.Size > 0 ? '+' : ""), ("size", modSet.Size))); + + return result; + } + + private void OnAttachableAltered(Entity attachable, ref AttachableAlteredEvent args) + { + if (attachable.Comp.Modifiers.Count == 0) + return; + + switch (args.Alteration) + { + case AttachableAlteredType.AppearanceChanged: + break; + + case AttachableAlteredType.DetachedDeactivated: + break; + + default: + _itemSizeChangeSystem.RefreshItemSizeModifiers(args.Holder); + break; + } + } + + private void OnGetItemSizeModifiers(Entity attachable, ref AttachableRelayedEvent args) + { + foreach(var modSet in attachable.Comp.Modifiers) + { + if (!CanApplyModifiers(attachable.Owner, modSet.Conditions)) + return; + + args.Args.Size += modSet.Size; + } + } +} diff --git a/Content.Shared/ADT/_RMC14/Attachable/Systems/AttachableModifiersSystem.Speed.cs b/Content.Shared/ADT/_RMC14/Attachable/Systems/AttachableModifiersSystem.Speed.cs new file mode 100644 index 00000000000..3bfd981f66c --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Attachable/Systems/AttachableModifiersSystem.Speed.cs @@ -0,0 +1,78 @@ +using Content.Shared._RMC14.Attachable.Components; +using Content.Shared._RMC14.Attachable.Events; +using Content.Shared._RMC14.Wieldable; +using Content.Shared._RMC14.Wieldable.Events; +using Content.Shared.Wieldable.Components; + +namespace Content.Shared._RMC14.Attachable.Systems; + +public sealed partial class AttachableModifiersSystem : EntitySystem +{ + private void InitializeSpeed() + { + SubscribeLocalEvent(OnSpeedModsGetExamineData); + SubscribeLocalEvent(OnAttachableAltered); + SubscribeLocalEvent>(OnGetSpeedModifiers); + } + + private void OnSpeedModsGetExamineData(Entity attachable, ref AttachableGetExamineDataEvent args) + { + foreach (var modSet in attachable.Comp.Modifiers) + { + var key = GetExamineKey(modSet.Conditions); + + if (!args.Data.ContainsKey(key)) + args.Data[key] = new (modSet.Conditions, GetEffectStrings(modSet)); + else + args.Data[key].effectStrings.AddRange(GetEffectStrings(modSet)); + } + } + + private List GetEffectStrings(AttachableSpeedModifierSet modSet) + { + var result = new List(); + + if (modSet.Walk != 0) + result.Add(Loc.GetString("rmc-attachable-examine-speed-walk", + ("colour", modifierExamineColour), ("sign", modSet.Walk > 0 ? '+' : ""), ("speed", modSet.Walk))); + + if (modSet.Sprint != 0) + result.Add(Loc.GetString("rmc-attachable-examine-speed-sprint", + ("colour", modifierExamineColour), ("sign", modSet.Sprint > 0 ? '+' : ""), ("speed", modSet.Sprint))); + + return result; + } + + private void OnAttachableAltered(Entity attachable, ref AttachableAlteredEvent args) + { + switch(args.Alteration) + { + case AttachableAlteredType.AppearanceChanged: + break; + + case AttachableAlteredType.DetachedDeactivated: + break; + + default: + _wieldableSystem.RefreshSpeedModifiers(args.Holder); + break; + } + } + + private void OnGetSpeedModifiers(Entity attachable, ref AttachableRelayedEvent args) + { + foreach(var modSet in attachable.Comp.Modifiers) + { + ApplyModifierSet(attachable, modSet, ref args.Args); + } + } + + private void ApplyModifierSet(Entity attachable, AttachableSpeedModifierSet modSet, ref GetWieldableSpeedModifiersEvent args) + { + if (!CanApplyModifiers(attachable.Owner, modSet.Conditions)) + return; + + args.Walk += modSet.Walk; + args.Sprint += modSet.Sprint; + } +} diff --git a/Content.Shared/ADT/_RMC14/Attachable/Systems/AttachableModifiersSystem.WieldDelay.cs b/Content.Shared/ADT/_RMC14/Attachable/Systems/AttachableModifiersSystem.WieldDelay.cs new file mode 100644 index 00000000000..bfa3d627e3b --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Attachable/Systems/AttachableModifiersSystem.WieldDelay.cs @@ -0,0 +1,77 @@ +using Content.Shared._RMC14.Attachable.Components; +using Content.Shared._RMC14.Attachable.Events; +using Content.Shared._RMC14.Wieldable.Events; + +namespace Content.Shared._RMC14.Attachable.Systems; + +public sealed partial class AttachableModifiersSystem : EntitySystem +{ + private void InitializeWieldDelay() + { + SubscribeLocalEvent(OnWieldDelayModsGetExamineData); + SubscribeLocalEvent(OnAttachableAltered); + SubscribeLocalEvent>(OnGetWieldDelay); + } + + private void OnWieldDelayModsGetExamineData(Entity attachable, ref AttachableGetExamineDataEvent args) + { + foreach (var modSet in attachable.Comp.Modifiers) + { + var key = GetExamineKey(modSet.Conditions); + + if (!args.Data.ContainsKey(key)) + args.Data[key] = new (modSet.Conditions, GetEffectStrings(modSet)); + else + args.Data[key].effectStrings.AddRange(GetEffectStrings(modSet)); + } + } + + private List GetEffectStrings(AttachableWieldDelayModifierSet modSet) + { + var result = new List(); + + if (modSet.Delay != TimeSpan.Zero) + result.Add(Loc.GetString("rmc-attachable-examine-wield-delay", + ("colour", modifierExamineColour), ("sign", modSet.Delay.TotalSeconds > 0 ? '+' : ""), ("delay", modSet.Delay.TotalSeconds))); + + return result; + } + + private void OnAttachableAltered(Entity attachable, ref AttachableAlteredEvent args) + { + switch(args.Alteration) + { + case AttachableAlteredType.AppearanceChanged: + break; + + case AttachableAlteredType.DetachedDeactivated: + break; + + case AttachableAlteredType.Wielded: + break; + + case AttachableAlteredType.Unwielded: + break; + + default: + _wieldableSystem.RefreshWieldDelay(args.Holder); + break; + } + } + + private void OnGetWieldDelay(Entity attachable, ref AttachableRelayedEvent args) + { + foreach(var modSet in attachable.Comp.Modifiers) + { + ApplyModifierSet(attachable, modSet, ref args.Args); + } + } + + private void ApplyModifierSet(Entity attachable, AttachableWieldDelayModifierSet modSet, ref GetWieldDelayEvent args) + { + if (!CanApplyModifiers(attachable.Owner, modSet.Conditions)) + return; + + args.Delay += modSet.Delay; + } +} diff --git a/Content.Shared/ADT/_RMC14/Attachable/Systems/AttachableModifiersSystem.cs b/Content.Shared/ADT/_RMC14/Attachable/Systems/AttachableModifiersSystem.cs new file mode 100644 index 00000000000..605c146d740 --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Attachable/Systems/AttachableModifiersSystem.cs @@ -0,0 +1,215 @@ +using Content.Shared._RMC14.Attachable.Components; +using Content.Shared._RMC14.Attachable.Events; +using Content.Shared._RMC14.Weapons.Ranged; +using Content.Shared._RMC14.Wieldable; +using Content.Shared.Examine; +using Content.Shared.Verbs; +using Content.Shared.Weapons.Ranged.Systems; +using Content.Shared.Whitelist; +using Content.Shared.Wieldable.Components; +using Robust.Shared.Utility; + +namespace Content.Shared._RMC14.Attachable.Systems; + +public sealed partial class AttachableModifiersSystem : EntitySystem +{ + [Dependency] private readonly AttachableHolderSystem _attachableHolderSystem = default!; + [Dependency] private readonly EntityWhitelistSystem _whitelistSystem = default!; + [Dependency] private readonly ExamineSystemShared _examineSystem = default!; + [Dependency] private readonly RMCSelectiveFireSystem _rmcSelectiveFireSystem = default!; + [Dependency] private readonly RMCWieldableSystem _wieldableSystem = default!; + [Dependency] private readonly SharedGunSystem _gunSystem = default!; + + private const string modifierExamineColour = "yellow"; + + public override void Initialize() + { + SubscribeLocalEvent>(OnAttachableGetExamineVerbs); + + InitializeMelee(); + InitializeRanged(); + InitializeSize(); + InitializeSpeed(); + InitializeWieldDelay(); + } + + private void OnAttachableGetExamineVerbs(Entity attachable, ref GetVerbsEvent args) + { + if (!args.CanInteract || !args.CanAccess) + return; + + var ev = new AttachableGetExamineDataEvent(new Dictionary effectStrings)>()); + RaiseLocalEvent(attachable.Owner, ref ev); + + var message = new FormattedMessage(); + foreach (var key in ev.Data.Keys) + { + message.TryAddMarkup(GetExamineConditionText(attachable, ev.Data[key].conditions), out _); + message.PushNewline(); + + foreach (var effectText in ev.Data[key].effectStrings) + { + message.TryAddMarkup(" " + effectText, out _); + message.PushNewline(); + } + } + + if (!message.IsEmpty) + { + _examineSystem.AddDetailedExamineVerb(args, attachable.Comp, message, + Loc.GetString("rmc-attachable-examinable-verb-text"), + "/Textures/Interface/VerbIcons/information.svg.192dpi.png", + Loc.GetString("rmc-attachable-examinable-verb-message") + ); + } + } + + private string GetExamineConditionText(Entity attachable, AttachableModifierConditions? conditions) + { + string conditionText = Loc.GetString("rmc-attachable-examine-condition-always"); + + if (conditions == null) + return conditionText; + + AttachableModifierConditions cond = conditions.Value; + + bool conditionPlaced = false; + conditionText = Loc.GetString("rmc-attachable-examine-condition-when") + ' '; + + ExamineConditionAddEntry(cond.WieldedOnly, Loc.GetString("rmc-attachable-examine-condition-wielded"), ref conditionText, ref conditionPlaced); + ExamineConditionAddEntry(cond.UnwieldedOnly, Loc.GetString("rmc-attachable-examine-condition-unwielded"), ref conditionText, ref conditionPlaced); + + ExamineConditionAddEntry( + cond.ActiveOnly, + Loc.GetString("rmc-attachable-examine-condition-active", ("attachable", attachable.Owner)), + ref conditionText, + ref conditionPlaced); + + ExamineConditionAddEntry( + cond.InactiveOnly, + Loc.GetString("rmc-attachable-examine-condition-inactive", ("attachable", attachable.Owner)), + ref conditionText, + ref conditionPlaced); + + if (cond.Whitelist != null) + { + EntityWhitelist whitelist = cond.Whitelist; + + if (whitelist.Registrations != null) + ExamineConditionAddEntry( + cond.Whitelist != null, + Loc.GetString("rmc-attachable-examine-condition-whitelist-comps", ("compNumber", whitelist.RequireAll ? "all" : "one"), ("comps", String.Join(", ", whitelist.Registrations))), + ref conditionText, + ref conditionPlaced); + + if (whitelist.Sizes != null) + ExamineConditionAddEntry( + cond.Whitelist != null, + Loc.GetString("rmc-attachable-examine-condition-whitelist-sizes", ("sizes", String.Join(", ", whitelist.Sizes))), + ref conditionText, + ref conditionPlaced); + + if (whitelist.Tags != null) + ExamineConditionAddEntry( + cond.Whitelist != null, + Loc.GetString("rmc-attachable-examine-condition-whitelist-tags", ("tagNumber", whitelist.RequireAll ? "all" : "one"), ("tags", String.Join(", ", whitelist.Tags))), + ref conditionText, + ref conditionPlaced); + } + + if (cond.Blacklist != null && cond.Blacklist.Tags != null) + { + EntityWhitelist blacklist = cond.Blacklist; + + if (blacklist.Registrations != null) + ExamineConditionAddEntry( + cond.Blacklist != null, + Loc.GetString("rmc-attachable-examine-condition-blacklist-comps", ("compNumber", blacklist.RequireAll ? "one" : "all"), ("comps", String.Join(", ", blacklist.Registrations))), + ref conditionText, + ref conditionPlaced); + + if (blacklist.Sizes != null) + ExamineConditionAddEntry( + cond.Blacklist != null, + Loc.GetString("rmc-attachable-examine-condition-blacklist-sizes", ("sizes", String.Join(", ", blacklist.Sizes))), + ref conditionText, + ref conditionPlaced); + + if (blacklist.Tags != null) + ExamineConditionAddEntry( + cond.Blacklist != null, + Loc.GetString("rmc-attachable-examine-condition-blacklist-tags", ("tagNumber", blacklist.RequireAll ? "one" : "all"), ("tags", String.Join(", ", blacklist.Tags))), + ref conditionText, + ref conditionPlaced); + } + + conditionText += ':'; + + return conditionText; + } + + private void ExamineConditionAddEntry(bool condition, string text, ref string conditionText, ref bool conditionPlaced) + { + if (!condition) + return; + + if (conditionPlaced) + conditionText += "; "; + conditionText += text; + conditionPlaced = true; + } + + private byte GetExamineKey(AttachableModifierConditions? conditions) + { + byte key = 0; + + if (conditions == null) + return key; + + key |= conditions.Value.WieldedOnly ? (byte)(1 << 0) : (byte)0; + key |= conditions.Value.UnwieldedOnly ? (byte)(1 << 1) : (byte)0; + key |= conditions.Value.ActiveOnly ? (byte)(1 << 2) : (byte)0; + key |= conditions.Value.InactiveOnly ? (byte)(1 << 3) : (byte)0; + key |= conditions.Value.Whitelist != null ? (byte)(1 << 4) : (byte)0; + key |= conditions.Value.Blacklist != null ? (byte)(1 << 5) : (byte)0; + + return key; + } + + private bool CanApplyModifiers(EntityUid attachableUid, AttachableModifierConditions? conditions) + { + if (conditions == null) + return true; + + _attachableHolderSystem.TryGetHolder(attachableUid, out var holderUid); + + if (holderUid != null) + { + TryComp(holderUid, out WieldableComponent? wieldableComponent); + + if (conditions.Value.UnwieldedOnly && wieldableComponent != null && wieldableComponent.Wielded) + return false; + else if (conditions.Value.WieldedOnly && (wieldableComponent == null || !wieldableComponent.Wielded)) + return false; + } + + TryComp(attachableUid, out AttachableToggleableComponent? toggleableComponent); + + if (conditions.Value.InactiveOnly && toggleableComponent != null && toggleableComponent.Active) + return false; + else if (conditions.Value.ActiveOnly && (toggleableComponent == null || !toggleableComponent.Active)) + return false; + + + if (holderUid != null) + { + if (conditions.Value.Whitelist != null && _whitelistSystem.IsWhitelistFail(conditions.Value.Whitelist, holderUid.Value)) + return false; + + if (conditions.Value.Blacklist != null && _whitelistSystem.IsWhitelistPass(conditions.Value.Blacklist, holderUid.Value)) + return false; + } + + return true; + } +} diff --git a/Content.Shared/ADT/_RMC14/Attachable/Systems/AttachablePreventDropSystem.cs b/Content.Shared/ADT/_RMC14/Attachable/Systems/AttachablePreventDropSystem.cs new file mode 100644 index 00000000000..488eae5db06 --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Attachable/Systems/AttachablePreventDropSystem.cs @@ -0,0 +1,33 @@ +using Content.Shared._RMC14.Attachable.Components; +using Content.Shared._RMC14.Attachable.Events; +using Content.Shared.Interaction.Components; + +namespace Content.Shared._RMC14.Attachable.Systems; + +public sealed class AttachablePreventDropSystem : EntitySystem +{ + public override void Initialize() + { + SubscribeLocalEvent(OnAttachableAltered); + } + + private void OnAttachableAltered(Entity attachable, ref AttachableAlteredEvent args) + { + switch (args.Alteration) + { + case AttachableAlteredType.Activated: + var comp = EnsureComp(args.Holder); + comp.DeleteOnDrop = false; + Dirty(args.Holder, comp); + break; + + case AttachableAlteredType.Deactivated: + RemCompDeferred(args.Holder); + break; + + case AttachableAlteredType.DetachedDeactivated: + RemCompDeferred(args.Holder); + break; + } + } +} diff --git a/Content.Shared/ADT/_RMC14/Attachable/Systems/AttachablePryingSystem.cs b/Content.Shared/ADT/_RMC14/Attachable/Systems/AttachablePryingSystem.cs new file mode 100644 index 00000000000..398e85b2daa --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Attachable/Systems/AttachablePryingSystem.cs @@ -0,0 +1,46 @@ +using Content.Shared._RMC14.Attachable.Components; +using Content.Shared._RMC14.Attachable.Events; +using Content.Shared.Prying.Components; +using Content.Shared.Tools.Components; +using Robust.Shared.Audio; +using Robust.Shared.Prototypes; +using Robust.Shared.Timing; + +namespace Content.Shared._RMC14.Attachable.Systems; + +public sealed class AttachablePryingSystem : EntitySystem +{ + [Dependency] private readonly IPrototypeManager _prototype = default!; + [Dependency] private readonly IGameTiming _timing = default!; + + public override void Initialize() + { + SubscribeLocalEvent(OnAttachableAltered); + } + + private void OnAttachableAltered(Entity ent, ref AttachableAlteredEvent args) + { + if (_timing.ApplyingState) + return; + + switch (args.Alteration) + { + case AttachableAlteredType.Attached: + var prying = EnsureComp(args.Holder); + var tool = EnsureComp(args.Holder); +#pragma warning disable RA0002 + prying.SpeedModifier = 0.5f; + tool.Qualities.Add("Prying", _prototype); + tool.UseSound = new SoundPathSpecifier("/Audio/Items/crowbar.ogg"); +#pragma warning restore RA0002 + + Dirty(args.Holder, prying); + Dirty(args.Holder, tool); + break; + case AttachableAlteredType.Detached: + RemCompDeferred(args.Holder); + RemCompDeferred(args.Holder); + break; + } + } +} diff --git a/Content.Shared/ADT/_RMC14/Attachable/Systems/AttachableSilencerSystem.cs b/Content.Shared/ADT/_RMC14/Attachable/Systems/AttachableSilencerSystem.cs new file mode 100644 index 00000000000..5c4a7d19a8c --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Attachable/Systems/AttachableSilencerSystem.cs @@ -0,0 +1,24 @@ +using Content.Shared._RMC14.Attachable.Components; +using Content.Shared._RMC14.Attachable.Events; +using Content.Shared.Weapons.Ranged.Events; + +namespace Content.Shared._RMC14.Attachable.Systems; + +public sealed class AttachableSilencerSystem : EntitySystem +{ + public override void Initialize() + { + SubscribeLocalEvent>(OnSilencerRefreshModifiers); + SubscribeLocalEvent>(OnSilencerMuzzleFlash); + } + + private void OnSilencerRefreshModifiers(Entity ent, ref AttachableRelayedEvent args) + { + args.Args.SoundGunshot = ent.Comp.Sound; + } + + private void OnSilencerMuzzleFlash(Entity ent, ref AttachableRelayedEvent args) + { + args.Args.Cancelled = true; + } +} diff --git a/Content.Shared/ADT/_RMC14/Attachable/Systems/AttachableTemporarySpeedModsSystem.cs b/Content.Shared/ADT/_RMC14/Attachable/Systems/AttachableTemporarySpeedModsSystem.cs new file mode 100644 index 00000000000..23288ac8e3b --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Attachable/Systems/AttachableTemporarySpeedModsSystem.cs @@ -0,0 +1,24 @@ +using Content.Shared._RMC14.Attachable.Components; +using Content.Shared._RMC14.Attachable.Events; +using Content.Shared._RMC14.Movement; + +namespace Content.Shared._RMC14.Attachable.Systems; + +public sealed class AttachableTemporarySpeedModsSystem : EntitySystem +{ + [Dependency] private readonly TemporarySpeedModifiersSystem _temporarySpeedModifiersSystem = default!; + [Dependency] private readonly AttachableHolderSystem _attachableHolderSystem = default!; + + public override void Initialize() + { + SubscribeLocalEvent(OnAttachableAltered); + } + + private void OnAttachableAltered(Entity attachable, ref AttachableAlteredEvent args) + { + if ((attachable.Comp.Alteration & args.Alteration) != attachable.Comp.Alteration || !_attachableHolderSystem.TryGetUser(attachable.Owner, out var userUid)) + return; + + _temporarySpeedModifiersSystem.ModifySpeed(userUid.Value, attachable.Comp.Modifiers); + } +} diff --git a/Content.Shared/ADT/_RMC14/Attachable/Systems/AttachableToggleableSystem.cs b/Content.Shared/ADT/_RMC14/Attachable/Systems/AttachableToggleableSystem.cs new file mode 100644 index 00000000000..1f21cf1b50b --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Attachable/Systems/AttachableToggleableSystem.cs @@ -0,0 +1,790 @@ +using System.Numerics; +using Content.Shared._RMC14.Attachable.Components; +using Content.Shared._RMC14.Attachable.Events; +using Content.Shared._RMC14.Weapons.Ranged; +using Content.Shared.Actions; +using Content.Shared.Actions.Events; +using Content.Shared.DoAfter; +using Content.Shared.Hands; +using Content.Shared.Hands.EntitySystems; +using Content.Shared.Interaction; +using Content.Shared.Light; +using Content.Shared.Movement.Events; +using Content.Shared.Physics; +using Content.Shared.Popups; +using Content.Shared.Timing; +using Content.Shared.Toggleable; +using Content.Shared.Weapons.Ranged.Systems; +using Content.Shared.Whitelist; +using Content.Shared.Wieldable.Components; +using Robust.Shared.Audio.Systems; +using Robust.Shared.Map; +using Robust.Shared.Physics; +using Robust.Shared.Timing; +using Content.Shared._RMC14.Weapons.Common; + +namespace Content.Shared._RMC14.Attachable.Systems; + +public sealed class AttachableToggleableSystem : EntitySystem +{ + [Dependency] private readonly IGameTiming _gameTiming = default!; + [Dependency] private readonly ActionContainerSystem _actionContainerSystem = default!; + [Dependency] private readonly EntityLookupSystem _entityLookupSystem = default!; + [Dependency] private readonly EntityWhitelistSystem _entityWhitelistSystem = default!; + [Dependency] private readonly MetaDataSystem _metaDataSystem = default!; + [Dependency] private readonly SharedActionsSystem _actionsSystem = default!; + [Dependency] private readonly AttachableHolderSystem _attachableHolderSystem = default!; + [Dependency] private readonly SharedAudioSystem _audioSystem = default!; + [Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!; + [Dependency] private readonly SharedHandsSystem _handsSystem = default!; + [Dependency] private readonly SharedPopupSystem _popupSystem = default!; + [Dependency] private readonly SharedTransformSystem _transformSystem = default!; + [Dependency] private readonly UseDelaySystem _useDelaySystem = default!; + + private const string attachableToggleUseDelayID = "RMCAttachableToggle"; + + private const int bracingInvalidCollisionGroup = (int)CollisionGroup.ThrownItem; + private const int bracingRequiredCollisionGroup = (int)CollisionGroup.MidImpassable; + + public override void Initialize() + { + SubscribeLocalEvent(OnActivateInWorld); + SubscribeLocalEvent(OnAttachableAltered, + after: new[] { typeof(AttachableModifiersSystem) }); + SubscribeLocalEvent(OnAttachableToggleableInterrupt); + SubscribeLocalEvent(OnAttachableToggleAction); + SubscribeLocalEvent(OnAttachableToggleDoAfter); + SubscribeLocalEvent(OnAttachableToggleStarted); + SubscribeLocalEvent(OnAttemptShoot); + SubscribeLocalEvent>(OnGunShot); + SubscribeLocalEvent(OnGunShot); + SubscribeLocalEvent(OnToggleAction, + before: new[] { typeof(SharedHandheldLightSystem) }); + SubscribeLocalEvent(OnUniqueAction); + SubscribeLocalEvent(OnGrantAttachableActions); + SubscribeLocalEvent(OnRemoveAttachableActions); + SubscribeLocalEvent>(OnHandDeselected); + SubscribeLocalEvent>(OnGotEquippedHand); + SubscribeLocalEvent>(OnGotUnequippedHand); + + SubscribeLocalEvent(OnAttachableMovementLockedMoveInput); + + SubscribeLocalEvent(OnAttachableAltered, + after: new[] { typeof(AttachableModifiersSystem) }); + + SubscribeLocalEvent(OnAttachableAltered, + after: new[] { typeof(AttachableModifiersSystem) }); + + SubscribeLocalEvent(OnAttemptShoot); + } + +#region AttachableAlteredEvent handling + private void OnAttachableAltered(Entity attachable, ref AttachableAlteredEvent args) + { + switch (args.Alteration) + { + case AttachableAlteredType.Detached: + if (attachable.Comp.SupercedeHolder && + TryComp(args.Holder, out AttachableHolderComponent? holderComponent) && + holderComponent.SupercedingAttachable == attachable.Owner) + { + _attachableHolderSystem.SetSupercedingAttachable((args.Holder, holderComponent), null); + } + + if (attachable.Comp.Active) + { + var ev = args with { Alteration = AttachableAlteredType.DetachedDeactivated }; + RaiseLocalEvent(attachable.Owner, ref ev); + } + + attachable.Comp.Attached = false; + attachable.Comp.Active = false; + Dirty(attachable); + break; + + case AttachableAlteredType.Attached: + attachable.Comp.Attached = true; + break; + + case AttachableAlteredType.Unwielded: + if (!attachable.Comp.WieldedOnly || !attachable.Comp.Active) + break; + + Toggle(attachable, args.User, attachable.Comp.DoInterrupt); + break; + } + + if (attachable.Comp.Action == null || + !TryComp(attachable.Comp.Action, out InstantActionComponent? actionComponent)) + { + return; + } + + _actionsSystem.SetToggled(attachable.Comp.Action, attachable.Comp.Active); + actionComponent.Enabled = attachable.Comp.Attached; + } + + private void OnAttachableAltered(Entity attachable, ref AttachableAlteredEvent args) + { + if (args.User == null) + return; + + switch (args.Alteration) + { + case AttachableAlteredType.Activated: + RaiseLocalEvent(attachable.Owner, new ActivateInWorldEvent(args.User.Value, args.Holder, true)); + break; + + case AttachableAlteredType.Deactivated: + RaiseLocalEvent(attachable.Owner, new ActivateInWorldEvent(args.User.Value, args.Holder, true)); + break; + + case AttachableAlteredType.DetachedDeactivated: + RaiseLocalEvent(attachable.Owner, new ActivateInWorldEvent(args.User.Value, args.Holder, true)); + break; + } + } + + private void OnAttachableAltered(Entity attachable, ref AttachableAlteredEvent args) + { + if (!TryComp(attachable.Owner, out AttachableToggleableComponent? toggleableComponent)) + return; + + EnsureComp(args.Holder, out AttachableGunPreventShootComponent preventShootComponent); + + switch (args.Alteration) + { + case AttachableAlteredType.Attached: + preventShootComponent.Message = attachable.Comp.Message; + preventShootComponent.PreventShoot = attachable.Comp.ShootWhenActive && !toggleableComponent.Active || !attachable.Comp.ShootWhenActive && toggleableComponent.Active; + break; + + case AttachableAlteredType.Detached: + preventShootComponent.Message = ""; + preventShootComponent.PreventShoot = false; + break; + + case AttachableAlteredType.Activated: + preventShootComponent.PreventShoot = !attachable.Comp.ShootWhenActive; + break; + + case AttachableAlteredType.Deactivated: + preventShootComponent.PreventShoot = attachable.Comp.ShootWhenActive; + break; + + case AttachableAlteredType.DetachedDeactivated: + preventShootComponent.PreventShoot = false; + break; + } + + Dirty(args.Holder, preventShootComponent); + } +#endregion + + private void OnGotEquippedHand(Entity attachable, ref AttachableRelayedEvent args) + { + if (!attachable.Comp.Attached) + return; + + args.Args.Handled = true; + + var addEv = new GrantAttachableActionsEvent(args.Args.User); + RaiseLocalEvent(attachable, ref addEv); + } + +#region Lockouts and interrupts + private void OnActivateInWorld(Entity attachable, ref ActivateInWorldEvent args) + { + if (attachable.Comp.AttachedOnly && !attachable.Comp.Attached) + args.Handled = true; + } + + private void OnAttemptShoot(Entity attachable, ref AttemptShootEvent args) + { + if (args.Cancelled) + return; + + if (attachable.Comp.AttachedOnly && !attachable.Comp.Attached) + { + args.Cancelled = true; + return; + } + + if (attachable.Comp.WieldedUseOnly && + (!_attachableHolderSystem.TryGetHolder(attachable.Owner, out EntityUid? holderUid) || + !TryComp(holderUid, out WieldableComponent? wieldableComponent) || + !wieldableComponent.Wielded)) + { + args.Cancelled = true; + + if (holderUid == null) + return; + + _popupSystem.PopupClient( + Loc.GetString("rmc-attachable-shoot-fail-not-wielded", ("holder", holderUid), ("attachable", attachable)), + args.User, + args.User); + return; + } + } + + private void OnGunShot(Entity attachable, ref AttachableRelayedEvent args) + { + CheckUserBreakOnRotate(args.Args.User); + CheckUserBreakOnFullRotate(args.Args.User, args.Args.FromCoordinates, args.Args.ToCoordinates); + } + + private void OnGunShot(Entity attachable, ref GunShotEvent args) + { + CheckUserBreakOnRotate(args.User); + CheckUserBreakOnFullRotate(args.User, args.FromCoordinates, args.ToCoordinates); + } + + private void OnAttemptShoot(Entity gun, ref AttemptShootEvent args) + { + if (args.Cancelled || !gun.Comp.PreventShoot) + return; + + args.Cancelled = true; + + _popupSystem.PopupClient(gun.Comp.Message, args.User, args.User); + } + + private void OnUniqueAction(Entity attachable, ref UniqueActionEvent args) + { + if (attachable.Comp.AttachedOnly && !attachable.Comp.Attached) + args.Handled = true; + } + + private void OnHandDeselected(Entity attachable, ref AttachableRelayedEvent args) + { + if (!attachable.Comp.Attached) + return; + + args.Args.Handled = true; + + if (!attachable.Comp.NeedHand || !attachable.Comp.Active) + return; + + Toggle(attachable, args.Args.User, attachable.Comp.DoInterrupt); + } + + private void OnAttachableToggleableInterrupt(Entity attachable, ref AttachableToggleableInterruptEvent args) + { + if (!attachable.Comp.Active) + return; + + Toggle(attachable, args.User, attachable.Comp.DoInterrupt); + } + + private void OnGotUnequippedHand(Entity attachable, ref AttachableRelayedEvent args) + { + if (!attachable.Comp.Attached) + return; + + args.Args.Handled = true; + + if (attachable.Comp.NeedHand && attachable.Comp.Active) + Toggle(attachable, args.Args.User, attachable.Comp.DoInterrupt); + + + var removeEv = new RemoveAttachableActionsEvent(args.Args.User); + RaiseLocalEvent(attachable, ref removeEv); + } + + private void OnAttachableMovementLockedMoveInput(Entity user, ref MoveInputEvent args) + { + if (!args.HasDirectionalMovement) + return; + + foreach (var attachableUid in user.Comp.AttachableList) + { + if (!TryComp(attachableUid, out AttachableToggleableComponent? toggleableComponent) || + !toggleableComponent.Active || + !toggleableComponent.BreakOnMove) + { + continue; + } + + Toggle((attachableUid, toggleableComponent), user.Owner, toggleableComponent.DoInterrupt); + } + + RemCompDeferred(user); + } + + private void CheckUserBreakOnRotate(Entity user) + { + if (user.Comp == null) + { + if (!TryComp(user.Owner, out AttachableDirectionLockedComponent? lockedComponent)) + return; + + user.Comp = lockedComponent; + } + + if (Transform(user.Owner).LocalRotation.GetCardinalDir() == user.Comp.LockedDirection) + return; + + foreach (EntityUid attachableUid in user.Comp.AttachableList) + { + if (!TryComp(attachableUid, out AttachableToggleableComponent? toggleableComponent) || + !toggleableComponent.Active || + !toggleableComponent.BreakOnRotate) + { + continue; + } + + Toggle((attachableUid, toggleableComponent), user.Owner, toggleableComponent.DoInterrupt); + } + + RemCompDeferred(user); + } + + private void CheckUserBreakOnFullRotate(Entity user, EntityCoordinates playerPos, EntityCoordinates targetPos) + { + if (user.Comp == null) + { + if (!TryComp(user.Owner, out AttachableSideLockedComponent? lockedComponent)) + return; + + user.Comp = lockedComponent; + } + + if (user.Comp.LockedDirection == null) + return; + + var initialAngle = user.Comp.LockedDirection.Value.ToAngle(); + var playerMapPos = _transformSystem.ToMapCoordinates(playerPos); + var targetMapPos = _transformSystem.ToMapCoordinates(targetPos); + var currentAngle = (targetMapPos.Position - playerMapPos.Position).ToWorldAngle(); + + var differenceFromLockedAngle = (currentAngle.Degrees - initialAngle.Degrees + 180 + 360) % 360 - 180; + + if (differenceFromLockedAngle > -90 && differenceFromLockedAngle < 90) + return; + + foreach (EntityUid attachableUid in user.Comp.AttachableList) + { + if (!TryComp(attachableUid, out AttachableToggleableComponent? toggleableComponent) || + !toggleableComponent.Active || + !toggleableComponent.BreakOnFullRotate) + { + continue; + } + + Toggle((attachableUid, toggleableComponent), user.Owner, toggleableComponent.DoInterrupt); + } + + RemCompDeferred(user); + } +#endregion + +#region Toggling + private void OnAttachableToggleStarted(Entity attachable, ref AttachableToggleStartedEvent args) + { + + if (!CanStartToggleDoAfter(attachable, ref args)) + return; + + var popupText = Loc.GetString(attachable.Comp.Active ? attachable.Comp.DeactivatePopupText : attachable.Comp.ActivatePopupText, ("attachable", attachable.Owner)); + + _doAfterSystem.TryStartDoAfter(new DoAfterArgs( + EntityManager, + args.User, + GetToggleDoAfter(attachable, args.Holder, args.User, ref popupText), + new AttachableToggleDoAfterEvent(args.SlotId, popupText), + attachable, + target: attachable.Owner, + used: args.Holder) + { + NeedHand = attachable.Comp.DoAfterNeedHand, + BreakOnMove = attachable.Comp.DoAfterBreakOnMove + }); + + Dirty(attachable); + } + + private bool CanStartToggleDoAfter(Entity attachable, ref AttachableToggleStartedEvent args, bool silent = false) + { + if (TryComp(attachable.Owner, out UseDelayComponent? useDelayComponent) && + _useDelaySystem.IsDelayed((attachable.Owner, useDelayComponent), attachableToggleUseDelayID)) + { + return false; + } + + _attachableHolderSystem.TryGetUser(attachable.Owner, out var userUid); + + if (attachable.Comp.HeldOnlyActivate && !attachable.Comp.Active && (userUid == null || !_handsSystem.IsHolding(userUid.Value, args.Holder, out _))) + { + if (!silent) + _popupSystem.PopupClient( + Loc.GetString("rmc-attachable-activation-fail-not-held", ("holder", args.Holder), ("attachable", attachable)), + args.User, + args.User); + return false; + } + + if (attachable.Comp.UserOnly && userUid != args.User) + { + if (!silent) + _popupSystem.PopupClient( + Loc.GetString("rmc-attachable-activation-fail-not-owned", ("holder", args.Holder), ("attachable", attachable)), + args.User, + args.User); + return false; + } + + if (!attachable.Comp.Active && attachable.Comp.WieldedOnly && (!TryComp(args.Holder, out WieldableComponent? wieldableComponent) || !wieldableComponent.Wielded)) + { + if (!silent) + _popupSystem.PopupClient( + Loc.GetString("rmc-attachable-activation-fail-not-wielded", ("holder", args.Holder), ("attachable", attachable)), + args.User, + args.User); + return false; + } + + return true; + } + + private TimeSpan GetToggleDoAfter(Entity attachable, EntityUid holderUid, EntityUid userUid, ref string popupText) + { + if (!TryComp(holderUid, out TransformComponent? transformComponent) || !transformComponent.ParentUid.Valid) + return TimeSpan.FromSeconds(0f); + + var extraDoAfter = transformComponent.ParentUid == userUid ? 0f : 0.5f; + + switch (attachable.Comp.InstantToggle) + { + case AttachableInstantToggleConditions.Brace: + if (attachable.Comp.Active || transformComponent.ParentUid != userUid || !TryComp(userUid, out TransformComponent? userTransform)) + break; + + TimeSpan? doAfter; + + var coords = userTransform.Coordinates; + + Func comparer = (EntityCoordinates userCoords, EntityCoordinates entCoords) => { return false; }; + var coordsShift = new Vector2(0f, 0f); + + Func, EntityUid?> GetBracingSurface = (HashSet ents) => + { + foreach (var entity in ents) + { + if (!TryComp(entity, out FixturesComponent? fixturesComponent)) + continue; + + foreach (var fixture in fixturesComponent.Fixtures.Values) + { + if ((fixture.CollisionLayer & bracingInvalidCollisionGroup) != 0 || (fixture.CollisionLayer & bracingRequiredCollisionGroup) == 0) + continue; + + if (!comparer(coords, Transform(entity).Coordinates)) + continue; + + return entity; + } + } + + return null; + }; + + switch (userTransform.LocalRotation.GetCardinalDir()) + { + case Direction.South: + comparer = (EntityCoordinates userCoords, EntityCoordinates entCoords) => { return entCoords.Y < userCoords.Y; }; + coordsShift = new Vector2(0f, -0.7f); + break; + + case Direction.North: + comparer = (EntityCoordinates userCoords, EntityCoordinates entCoords) => { return entCoords.Y > userCoords.Y; }; + coordsShift = new Vector2(0f, 0.7f); + break; + + case Direction.East: + comparer = (EntityCoordinates userCoords, EntityCoordinates entCoords) => { return entCoords.X > userCoords.X; }; + coordsShift = new Vector2(0.7f, 0f); + break; + + case Direction.West: + comparer = (EntityCoordinates userCoords, EntityCoordinates entCoords) => { return entCoords.X < userCoords.X; }; + coordsShift = new Vector2(-0.7f, 0f); + break; + + default: + break; + } + + var surface = GetBracingSurface(_entityLookupSystem.GetEntitiesInRange(coords, 0.5f, LookupFlags.Dynamic | LookupFlags.Static)); + if (surface != null) + { + popupText = Loc.GetString("attachable-popup-activate-deploy-on-generic", ("attachable", attachable.Owner), ("surface", surface)); + return TimeSpan.FromSeconds(0f); + } + + coords = new EntityCoordinates(coords.EntityId, coords.Position + coordsShift); + surface = GetBracingSurface(_entityLookupSystem.GetEntitiesInRange(coords, 0.5f, LookupFlags.Dynamic | LookupFlags.Static)); + if (surface != null) + { + popupText = Loc.GetString("attachable-popup-activate-deploy-on-generic", ("attachable", attachable.Owner), ("surface", surface)); + return TimeSpan.FromSeconds(0f); + } + + popupText = Loc.GetString("attachable-popup-activate-deploy-on-ground", ("attachable", attachable.Owner)); + break; + + default: + break; + } + + return TimeSpan.FromSeconds(Math.Max( + (attachable.Comp.DeactivateDoAfter != null && attachable.Comp.Active + ? attachable.Comp.DeactivateDoAfter.Value + : attachable.Comp.DoAfter + ) + extraDoAfter, + 0)); + } + + private void OnAttachableToggleDoAfter(Entity attachable, + ref AttachableToggleDoAfterEvent args) + { + if (args.Cancelled || args.Handled) + return; + + if (args.Target is not { } target || args.Used is not { } used) + return; + + if (!HasComp(target)) + return; + + if (!TryComp(args.Used, out AttachableHolderComponent? holderComponent)) + return; + + FinishToggle(attachable, (used, holderComponent), args.SlotId, args.User, args.PopupText); + args.Handled = true; + Dirty(attachable); + } + + private void FinishToggle( + Entity attachable, + Entity holder, + string slotId, + EntityUid? userUid, + string popupText, + bool interrupted = false) + { + attachable.Comp.Active = !attachable.Comp.Active; + + var mode = attachable.Comp.Active + ? AttachableAlteredType.Activated + : interrupted ? AttachableAlteredType.Interrupted : AttachableAlteredType.Deactivated; + var ev = new AttachableAlteredEvent(holder.Owner, mode, userUid); + RaiseLocalEvent(attachable.Owner, ref ev); + + var holderEv = new AttachableHolderAttachablesAlteredEvent(attachable.Owner, slotId, mode); + RaiseLocalEvent(holder.Owner, ref holderEv); + + _useDelaySystem.SetLength(attachable.Owner, attachable.Comp.UseDelay, attachableToggleUseDelayID); + _useDelaySystem.TryResetDelay(attachable.Owner, id: attachableToggleUseDelayID); + _actionsSystem.StartUseDelay(attachable.Comp.Action); + + if (attachable.Comp.ShowTogglePopup && userUid != null) + _popupSystem.PopupClient(popupText, userUid.Value, userUid.Value); + + _audioSystem.PlayPredicted( + attachable.Comp.Active ? attachable.Comp.ActivateSound : attachable.Comp.DeactivateSound, + attachable, + userUid); + + if (!attachable.Comp.Active) + { + if (attachable.Comp.SupercedeHolder && holder.Comp.SupercedingAttachable == attachable.Owner) + _attachableHolderSystem.SetSupercedingAttachable(holder, null); + return; + } + + if (attachable.Comp.BreakOnMove && userUid != null) + { + var movementLockedComponent = EnsureComp(userUid.Value); + movementLockedComponent.AttachableList.Add(attachable.Owner); + } + + if (attachable.Comp.BreakOnRotate && userUid != null) + { + var directionLockedComponent = EnsureComp(userUid.Value); + directionLockedComponent.AttachableList.Add(attachable.Owner); + + if (directionLockedComponent.LockedDirection == null) + directionLockedComponent.LockedDirection = Transform(userUid.Value).LocalRotation.GetCardinalDir(); + } + + if (attachable.Comp.BreakOnFullRotate && userUid != null) + { + var sideLockedComponent = EnsureComp(userUid.Value); + sideLockedComponent.AttachableList.Add(attachable.Owner); + + if (sideLockedComponent.LockedDirection == null) + sideLockedComponent.LockedDirection = Transform(userUid.Value).LocalRotation.GetCardinalDir(); + } + + if (!attachable.Comp.SupercedeHolder) + return; + + if (holder.Comp.SupercedingAttachable != null && + TryComp(holder.Comp.SupercedingAttachable, out AttachableToggleableComponent? toggleableComponent)) + { + toggleableComponent.Active = false; + ev = new AttachableAlteredEvent(holder.Owner, AttachableAlteredType.Deactivated); + RaiseLocalEvent(holder.Comp.SupercedingAttachable.Value, ref ev); + + if (_attachableHolderSystem.TryGetSlotId(holder.Owner, attachable.Owner, out var deactivatedSlot)) + { + holderEv = new AttachableHolderAttachablesAlteredEvent(holder.Comp.SupercedingAttachable.Value, + deactivatedSlot, + AttachableAlteredType.Deactivated); + RaiseLocalEvent(holder.Owner, ref holderEv); + } + } + + _attachableHolderSystem.SetSupercedingAttachable(holder, attachable.Owner); + } + + private void Toggle(Entity attachable, EntityUid? user, bool interrupted = false) + { + if (!_attachableHolderSystem.TryGetHolder(attachable.Owner, out var holderUid) || + !TryComp(holderUid, out AttachableHolderComponent? holderComponent) || + !_attachableHolderSystem.TryGetSlotId(holderUid.Value, attachable.Owner, out var slotId)) + { + return; + } + + FinishToggle( + attachable, + (holderUid.Value, holderComponent), + slotId, + user, + Loc.GetString(attachable.Comp.Active ? attachable.Comp.DeactivatePopupText : attachable.Comp.ActivatePopupText, ("attachable", attachable.Owner)), + interrupted); + Dirty(attachable); + } +#endregion + +#region Actions + private void OnGrantAttachableActions(Entity ent, ref GrantAttachableActionsEvent args) + { + GrantAttachableActions(ent, args.User); + RelayAttachableActions(ent, args.User); + } + + private void GrantAttachableActions(Entity ent, EntityUid user, bool doSecondTry = true) + { + // This is to prevent ActionContainerSystem from shitting itself if the attachment has actions other than its attachment toggle. + if (!TryComp(ent.Owner, out ActionsContainerComponent? actionsContainerComponent) || actionsContainerComponent.Container == null) + { + EnsureComp(ent.Owner); + + if (doSecondTry) + GrantAttachableActions(ent, user, false); + + return; + } + + var exists = ent.Comp.Action != null; + _actionContainerSystem.EnsureAction(ent, ref ent.Comp.Action, ent.Comp.ActionId, actionsContainerComponent); + + if (ent.Comp.Action is not { } actionId) + return; + + _actionsSystem.GrantContainedAction(user, ent.Owner, actionId); + + if (exists) + return; + + _metaDataSystem.SetEntityName(actionId, ent.Comp.ActionName); + _metaDataSystem.SetEntityDescription(actionId, ent.Comp.ActionDesc); + + if (_actionsSystem.TryGetActionData(actionId, out var action)) + { + action.Icon = ent.Comp.Icon; + action.IconOn = ent.Comp.IconActive; + action.Enabled = ent.Comp.Attached; + action.UseDelay = ent.Comp.UseDelay; + Dirty(actionId, action); + } + + Dirty(ent); + } + + private void RelayAttachableActions(Entity attachable, EntityUid user) + { + if (attachable.Comp.ActionsToRelayWhitelist == null || !TryComp(attachable.Owner, out ActionsContainerComponent? actionsContainerComponent)) + return; + + foreach (var actionUid in actionsContainerComponent.Container.ContainedEntities) + { + if (!_entityWhitelistSystem.IsWhitelistPass(attachable.Comp.ActionsToRelayWhitelist, actionUid)) + continue; + + _actionsSystem.GrantContainedAction(user, (attachable.Owner, actionsContainerComponent), actionUid); + } + } + + private void OnRemoveAttachableActions(Entity ent, ref RemoveAttachableActionsEvent args) + { + RemoveAttachableActions(ent, args.User); + RemoveRelayedActions(ent, args.User); + } + + private void RemoveAttachableActions(Entity ent, EntityUid user) + { + if (ent.Comp.Action is not { } action) + return; + + if (!TryComp(action, out InstantActionComponent? actionComponent) || actionComponent.AttachedEntity != user) + return; + + _actionsSystem.RemoveProvidedAction(user, ent, action); + } + + private void RemoveRelayedActions(Entity attachable, EntityUid user) + { + if (attachable.Comp.ActionsToRelayWhitelist == null || !TryComp(attachable.Owner, out ActionsContainerComponent? actionsContainerComponent)) + return; + + foreach (var actionUid in actionsContainerComponent.Container.ContainedEntities) + { + if (!_entityWhitelistSystem.IsWhitelistPass(attachable.Comp.ActionsToRelayWhitelist, actionUid)) + continue; + + _actionsSystem.RemoveProvidedAction(user, attachable.Owner, actionUid); + } + } + + private void OnAttachableToggleAction(Entity attachable, + ref AttachableToggleActionEvent args) + { + args.Handled = true; + + if (!attachable.Comp.Attached) + return; + + if (!_attachableHolderSystem.TryGetHolder(attachable.Owner, out var holderUid) || + !TryComp(holderUid, out AttachableHolderComponent? holderComponent) || + !_attachableHolderSystem.TryGetSlotId(holderUid.Value, attachable.Owner, out var slotId)) + { + return; + } + + var ev = new AttachableToggleStartedEvent(holderUid.Value, + args.Performer, + slotId); + RaiseLocalEvent(attachable.Owner, ref ev); + } + + private void OnToggleAction(Entity attachable, ref ToggleActionEvent args) + { + if (attachable.Comp.AttachedOnly && !attachable.Comp.Attached) + args.Handled = true; + } +#endregion +} diff --git a/Content.Shared/ADT/_RMC14/Input/CMKeyFunctions.cs b/Content.Shared/ADT/_RMC14/Input/CMKeyFunctions.cs new file mode 100644 index 00000000000..1fb151bf921 --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Input/CMKeyFunctions.cs @@ -0,0 +1,15 @@ +using Robust.Shared.Input; + +namespace Content.Shared._RMC14.Input; + +[KeyFunctions] +public sealed class CMKeyFunctions +{ + public static readonly BoundKeyFunction RMCActivateAttachableBarrel = "RMCActivateAttachableBarrel"; + public static readonly BoundKeyFunction RMCActivateAttachableRail = "RMCActivateAttachableRail"; + public static readonly BoundKeyFunction RMCActivateAttachableStock = "RMCActivateAttachableStock"; + public static readonly BoundKeyFunction RMCActivateAttachableUnderbarrel = "RMCActivateAttachableUnderbarrel"; + public static readonly BoundKeyFunction RMCFieldStripHeldItem = "RMCFieldStripHeldItem"; + public static readonly BoundKeyFunction RMCCycleFireMode = "RMCCycleFireMode"; + public static readonly BoundKeyFunction CMUniqueAction = "CMUniqueAction"; +} diff --git a/Content.Shared/ADT/_RMC14/Item/FixedItemSizeStorageComponent.cs b/Content.Shared/ADT/_RMC14/Item/FixedItemSizeStorageComponent.cs new file mode 100644 index 00000000000..b02eb9880ac --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Item/FixedItemSizeStorageComponent.cs @@ -0,0 +1,16 @@ +using Content.Shared.Item; +using Robust.Shared.GameStates; + +namespace Content.Shared._RMC14.Item; + +// TODO RMC14 rename to slot storage +// TODO RMC14 upstream this +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +[Access(typeof(SharedItemSystem))] +public sealed partial class FixedItemSizeStorageComponent : Component +{ + [DataField, AutoNetworkedField] + public Vector2i Size = new(2, 2); + + public Box2i[]? CachedSize; +} diff --git a/Content.Shared/ADT/_RMC14/Item/GetItemSizeModifiersEvent.cs b/Content.Shared/ADT/_RMC14/Item/GetItemSizeModifiersEvent.cs new file mode 100644 index 00000000000..d02f9569b75 --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Item/GetItemSizeModifiersEvent.cs @@ -0,0 +1,4 @@ +namespace Content.Shared._RMC14.Item; + +[ByRefEvent] +public record struct GetItemSizeModifiersEvent(int Size); diff --git a/Content.Shared/ADT/_RMC14/Item/ItemSizeChangeComponent.cs b/Content.Shared/ADT/_RMC14/Item/ItemSizeChangeComponent.cs new file mode 100644 index 00000000000..a2282c898d7 --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Item/ItemSizeChangeComponent.cs @@ -0,0 +1,11 @@ +using Robust.Shared.GameStates; + +namespace Content.Shared._RMC14.Item; + +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +[Access(typeof(ItemSizeChangeSystem))] +public sealed partial class ItemSizeChangeComponent : Component +{ + [DataField, AutoNetworkedField] + public int? BaseSize; +} diff --git a/Content.Shared/ADT/_RMC14/Item/ItemSizeChangeSystem.cs b/Content.Shared/ADT/_RMC14/Item/ItemSizeChangeSystem.cs new file mode 100644 index 00000000000..0e86bd598e6 --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Item/ItemSizeChangeSystem.cs @@ -0,0 +1,100 @@ +using Content.Shared._RMC14.Attachable.Systems; +using Content.Shared.Item; +using Robust.Shared.Prototypes; + +namespace Content.Shared._RMC14.Item; + +public sealed partial class ItemSizeChangeSystem : EntitySystem +{ + [Dependency] private readonly IPrototypeManager _prototypeManager = default!; + [Dependency] private readonly SharedItemSystem _itemSystem = default!; + + private readonly List _sortedSizes = new(); + + public override void Initialize() + { + SubscribeLocalEvent(OnPrototypesReloaded); + + SubscribeLocalEvent(OnMapInit, + before: new[] { typeof(AttachableHolderSystem) }); + + InitItemSizes(); + } + + private void OnPrototypesReloaded(PrototypesReloadedEventArgs args) + { + if (!args.ByType.ContainsKey(typeof(ItemSizePrototype)) && args.Removed?.ContainsKey(typeof(ItemSizePrototype)) != true) + return; + + InitItemSizes(); + } + + private void InitItemSizes() + { + _sortedSizes.Clear(); + + foreach (var prototype in _prototypeManager.EnumeratePrototypes()) + { + if (prototype.ID.Equals("Invalid")) + continue; + + _sortedSizes.Add(prototype); + } + + _sortedSizes.Sort(); + } + + private void OnMapInit(Entity item, ref MapInitEvent args) + { + InitItem(item); + RefreshItemSizeModifiers((item.Owner, item.Comp)); + } + + public void RefreshItemSizeModifiers(Entity item) + { + if (item.Comp == null) + item.Comp = EnsureComp(item.Owner); + else if (!InitItem((item.Owner, item.Comp))) + return; + + if (item.Comp == null || item.Comp.BaseSize == null) + return; + + var ev = new GetItemSizeModifiersEvent(item.Comp.BaseSize.Value); + RaiseLocalEvent(item.Owner, ref ev); + + ev.Size = Math.Clamp(ev.Size, 0, _sortedSizes.Count > 0 ? _sortedSizes.Count - 1 : 0); + + if (_sortedSizes.Count <= ev.Size) + return; + + _itemSystem.SetSize(item, _sortedSizes[ev.Size]); + } + + private bool InitItem(Entity item, bool onlyNull = false) + { + if (!onlyNull && item.Comp.BaseSize != null) + return true; + + if (_sortedSizes.Count <= 0) + { + InitItemSizes(); + + if (_sortedSizes.Count <= 0) + return false; + } + + if (!TryComp(item.Owner, out ItemComponent? itemComponent) || !_prototypeManager.TryIndex(itemComponent.Size, out ItemSizePrototype? prototype)) + return false; + + var size = _sortedSizes.IndexOf(prototype); + + if (size < 0) + return false; + + item.Comp.BaseSize = size; + Dirty(item); + + return true; + } +} diff --git a/Content.Shared/ADT/_RMC14/Item/ItemToggle/RMCItemToggleClothingVisualsComponent.cs b/Content.Shared/ADT/_RMC14/Item/ItemToggle/RMCItemToggleClothingVisualsComponent.cs new file mode 100644 index 00000000000..96d036e4132 --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Item/ItemToggle/RMCItemToggleClothingVisualsComponent.cs @@ -0,0 +1,11 @@ +using Robust.Shared.Audio; +using Robust.Shared.GameStates; + +namespace Content.Shared._RMC14.Item.ItemToggle; + +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +public sealed partial class RMCItemToggleClothingVisualsComponent : Component +{ + [DataField, AutoNetworkedField] + public string Prefix = "on"; +} diff --git a/Content.Shared/ADT/_RMC14/Item/ItemToggle/RMCItemToggleSystem.cs b/Content.Shared/ADT/_RMC14/Item/ItemToggle/RMCItemToggleSystem.cs new file mode 100644 index 00000000000..a9172ab4b0a --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Item/ItemToggle/RMCItemToggleSystem.cs @@ -0,0 +1,29 @@ +using Content.Shared.Clothing.EntitySystems; +using Content.Shared.Item; +using Content.Shared.Item.ItemToggle.Components; + +namespace Content.Shared._RMC14.Item.ItemToggle; + +public sealed class RMCItemToggleSystem : EntitySystem +{ + [Dependency] private readonly ClothingSystem _clothing = default!; + [Dependency] private readonly SharedItemSystem _item = default!; + + private EntityQuery _query; + + public override void Initialize() + { + base.Initialize(); + + _query = GetEntityQuery(); + + SubscribeLocalEvent(OnToggled); + } + + private void OnToggled(Entity ent, ref ItemToggledEvent args) + { + var prefix = args.Activated ? ent.Comp.Prefix : null; + _item.SetHeldPrefix(ent, prefix); + _clothing.SetEquippedPrefix(ent, prefix); + } +} diff --git a/Content.Shared/ADT/_RMC14/Item/MultiHandedHolderComponent.cs b/Content.Shared/ADT/_RMC14/Item/MultiHandedHolderComponent.cs new file mode 100644 index 00000000000..59266223886 --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Item/MultiHandedHolderComponent.cs @@ -0,0 +1,11 @@ +using Robust.Shared.GameStates; + +namespace Content.Shared._RMC14.Item; + +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +[Access(typeof(MultiHandedHolderSystem))] +public sealed partial class MultiHandedHolderComponent : Component +{ + [DataField, AutoNetworkedField] + public List Items = new(); +} diff --git a/Content.Shared/ADT/_RMC14/Item/MultiHandedHolderSystem.cs b/Content.Shared/ADT/_RMC14/Item/MultiHandedHolderSystem.cs new file mode 100644 index 00000000000..063702205e8 --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Item/MultiHandedHolderSystem.cs @@ -0,0 +1,81 @@ +using Content.Shared.Hands; +using Content.Shared.Hands.Components; +using Content.Shared.Hands.EntitySystems; +using Content.Shared.Inventory.VirtualItem; +using Content.Shared.Item; +using Content.Shared.Popups; +using Content.Shared.Whitelist; +using Robust.Shared.Timing; + +namespace Content.Shared._RMC14.Item; + +public sealed class MultiHandedHolderSystem : EntitySystem +{ + [Dependency] private readonly SharedHandsSystem _hands = default!; + [Dependency] private readonly SharedPopupSystem _popup = default!; + [Dependency] private readonly IGameTiming _timing = default!; + [Dependency] private readonly SharedVirtualItemSystem _virtualItem = default!; + [Dependency] private readonly EntityWhitelistSystem _whitelist = default!; + + public override void Initialize() + { + SubscribeLocalEvent(OnPickupAttempt); + SubscribeLocalEvent(OnVirtualItemDeleted); + SubscribeLocalEvent(OnEquipped); + SubscribeLocalEvent(OnUnequipped); + } + + private void OnPickupAttempt(Entity holder, ref PickupAttemptEvent args) + { + if (GetHandsNeeded(holder, args.Item) is not { } needed) + return; + + if (TryComp(args.User, out var hands) && + hands.CountFreeHands() >= needed) + { + return; + } + + args.Cancel(); + if (_timing.IsFirstTimePredicted) + { + _popup.PopupCursor(Loc.GetString("multi-handed-item-pick-up-fail", + ("number", needed - 1), ("item", args.Item)), args.User); + } + } + + private void OnVirtualItemDeleted(Entity ent, ref VirtualItemDeletedEvent args) + { + if (args.User != ent.Owner) + return; + + _hands.TryDrop(args.User, args.BlockingEntity); + } + + private void OnEquipped(Entity holder, ref DidEquipHandEvent args) + { + if (GetHandsNeeded(holder, args.Equipped) is not { } hands) + return; + + for (var i = 0; i < hands - 1; i++) + { + _virtualItem.TrySpawnVirtualItemInHand(args.Equipped, args.User); + } + } + + private void OnUnequipped(Entity holder, ref DidUnequipHandEvent args) + { + _virtualItem.DeleteInHandsMatching(args.User, args.Unequipped); + } + + private int? GetHandsNeeded(Entity holder, EntityUid item) + { + foreach (var (hands, whitelist) in holder.Comp.Items) + { + if (_whitelist.IsValid(whitelist, item)) + return hands; + } + + return null; + } +} diff --git a/Content.Shared/ADT/_RMC14/Item/MultiHandedItem.cs b/Content.Shared/ADT/_RMC14/Item/MultiHandedItem.cs new file mode 100644 index 00000000000..765ac0c4a37 --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Item/MultiHandedItem.cs @@ -0,0 +1,8 @@ +using Content.Shared.Whitelist; +using Robust.Shared.Serialization; + +namespace Content.Shared._RMC14.Item; + +[DataRecord] +[Serializable, NetSerializable] +public record MultiHandedItem(int Hands, EntityWhitelist Whitelist); diff --git a/Content.Shared/ADT/_RMC14/Movement/TemporarySpeedModifiersComponent.cs b/Content.Shared/ADT/_RMC14/Movement/TemporarySpeedModifiersComponent.cs new file mode 100644 index 00000000000..2ab2b876770 --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Movement/TemporarySpeedModifiersComponent.cs @@ -0,0 +1,19 @@ +using Robust.Shared.GameStates; +using Robust.Shared.Serialization; + +namespace Content.Shared._RMC14.Movement; + +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +[Access(typeof(TemporarySpeedModifiersSystem))] +public sealed partial class TemporarySpeedModifiersComponent : Component +{ + [DataField, AutoNetworkedField] + public List<(TimeSpan ExpiresAt, float Walk, float Sprint)> Modifiers = new(); +} + +[DataRecord, Serializable, NetSerializable] +public record struct TemporarySpeedModifierSet( + TimeSpan Duration, + float Walk, + float Sprint +); diff --git a/Content.Shared/ADT/_RMC14/Movement/TemporarySpeedModifiersSystem.cs b/Content.Shared/ADT/_RMC14/Movement/TemporarySpeedModifiersSystem.cs new file mode 100644 index 00000000000..0a008f53f89 --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Movement/TemporarySpeedModifiersSystem.cs @@ -0,0 +1,73 @@ +using Content.Shared.Movement.Systems; +using Robust.Shared.Network; +using Robust.Shared.Timing; + +namespace Content.Shared._RMC14.Movement; + +public sealed class TemporarySpeedModifiersSystem : EntitySystem +{ + [Dependency] private readonly MovementSpeedModifierSystem _movementSpeedSystem = default!; + [Dependency] private readonly INetManager _netManager = default!; + [Dependency] private readonly IGameTiming _timing = default!; + + public override void Initialize() + { + SubscribeLocalEvent(OnRefreshMovement); + } + + private void OnRefreshMovement(Entity ent, ref RefreshMovementSpeedModifiersEvent args) + { + foreach (var modifier in ent.Comp.Modifiers) + { + if (modifier.ExpiresAt <= _timing.CurTime) + continue; + + args.ModifySpeed(modifier.Walk, modifier.Sprint); + } + } + + public override void Update(float frameTime) + { + var time = _timing.CurTime; + var speedModsQuery = EntityQueryEnumerator(); + + while (speedModsQuery.MoveNext(out var uid, out var speedModsComponent)) + { + var toRemove = new List<(TimeSpan ExpiresAt, float Walk, float Sprint)>(); + + foreach (var modifier in speedModsComponent.Modifiers) + { + if (modifier.ExpiresAt > time) + continue; + + toRemove.Add(modifier); + } + + foreach (var modifier in toRemove) + { + speedModsComponent.Modifiers.Remove(modifier); + } + + if (toRemove.Count > 0) + Dirty(uid, speedModsComponent); + + if (speedModsComponent.Modifiers.Count <= 0) + RemCompDeferred(uid); + + _movementSpeedSystem.RefreshMovementSpeedModifiers(uid); + } + } + + public void ModifySpeed(EntityUid entUid, List modifiers) + { + if (_netManager.IsClient) + return; + + var comp = EnsureComp(entUid); + + foreach (var modifier in modifiers) + { + comp.Modifiers.Add((_timing.CurTime + modifier.Duration, modifier.Walk, modifier.Sprint)); + } + } +} diff --git a/Content.Shared/ADT/_RMC14/Projectiles/DeleteOnCollideComponent.cs b/Content.Shared/ADT/_RMC14/Projectiles/DeleteOnCollideComponent.cs new file mode 100644 index 00000000000..233bee9e56f --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Projectiles/DeleteOnCollideComponent.cs @@ -0,0 +1,7 @@ +using Robust.Shared.GameStates; + +namespace Content.Shared._RMC14.Projectiles; + +[RegisterComponent, NetworkedComponent] +[Access(typeof(RMCProjectileSystem))] +public sealed partial class DeleteOnCollideComponent : Component; diff --git a/Content.Shared/ADT/_RMC14/Projectiles/ModifyTargetOnHitComponent.cs b/Content.Shared/ADT/_RMC14/Projectiles/ModifyTargetOnHitComponent.cs new file mode 100644 index 00000000000..88f6a3bffbc --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Projectiles/ModifyTargetOnHitComponent.cs @@ -0,0 +1,16 @@ +using Content.Shared.Whitelist; +using Robust.Shared.GameStates; +using Robust.Shared.Prototypes; + +namespace Content.Shared._RMC14.Projectiles; + +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +[Access(typeof(RMCProjectileSystem))] +public sealed partial class ModifyTargetOnHitComponent : Component +{ + [DataField] + public ComponentRegistry? Add; + + [DataField, AutoNetworkedField] + public EntityWhitelist? Whitelist; +} diff --git a/Content.Shared/ADT/_RMC14/Projectiles/PreventCollideWithDeadComponent.cs b/Content.Shared/ADT/_RMC14/Projectiles/PreventCollideWithDeadComponent.cs new file mode 100644 index 00000000000..7b07130a568 --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Projectiles/PreventCollideWithDeadComponent.cs @@ -0,0 +1,7 @@ +using Robust.Shared.GameStates; + +namespace Content.Shared._RMC14.Projectiles; + +[RegisterComponent, NetworkedComponent] +[Access(typeof(RMCProjectileSystem))] +public sealed partial class PreventCollideWithDeadComponent : Component; diff --git a/Content.Shared/ADT/_RMC14/Projectiles/ProjectileMaxRangeComponent.cs b/Content.Shared/ADT/_RMC14/Projectiles/ProjectileMaxRangeComponent.cs new file mode 100644 index 00000000000..903a38a378a --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Projectiles/ProjectileMaxRangeComponent.cs @@ -0,0 +1,18 @@ +using Robust.Shared.GameStates; +using Robust.Shared.Map; + +namespace Content.Shared._RMC14.Projectiles; + +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +[Access(typeof(RMCProjectileSystem))] +public sealed partial class ProjectileMaxRangeComponent : Component +{ + [DataField, AutoNetworkedField] + public EntityCoordinates? Origin; + + [DataField(required: true), AutoNetworkedField] + public float Max; + + [DataField, AutoNetworkedField] + public bool Delete = true; +} diff --git a/Content.Shared/ADT/_RMC14/Projectiles/RMCProjectileDamageFalloffComponent.cs b/Content.Shared/ADT/_RMC14/Projectiles/RMCProjectileDamageFalloffComponent.cs new file mode 100644 index 00000000000..4153d44acd0 --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Projectiles/RMCProjectileDamageFalloffComponent.cs @@ -0,0 +1,59 @@ +using Content.Shared.FixedPoint; +using Robust.Shared.GameStates; +using Robust.Shared.Map; +using Robust.Shared.Serialization; + +namespace Content.Shared._RMC14.Projectiles; + +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +[Access(typeof(RMCProjectileSystem))] +public sealed partial class RMCProjectileDamageFalloffComponent : Component +{ + /// + /// This lists all the thresholds and their falloff values. + /// + [DataField, AutoNetworkedField] + public List Thresholds = new() + { + new DamageFalloffThreshold(0f, 1, false), + new DamageFalloffThreshold(22f, 9999, true) + }; + + /// + /// This determines the minimum fraction of the projectile's original damage that must remain after falloff is applied. + /// + [DataField, AutoNetworkedField] + public FixedPoint2 MinRemainingDamageMult = 0.05f; + + /// + /// This is the additional falloff multiplier applied by the firing weapon. + /// + [DataField, AutoNetworkedField] + public FixedPoint2 WeaponMult = 1; + + /// + /// These are the coordinates from which the projectile was shot. Used to determine the distance travelled. + /// + [DataField, AutoNetworkedField] + public EntityCoordinates? ShotFrom; +} + +[DataRecord, Serializable, NetSerializable] +public record struct DamageFalloffThreshold( + /// + /// The range at which falloff starts to take effect. + /// Conversion from 13: effective_range_max + /// + float Range, + + /// + /// This is the number by which the projectile's damage is decreased for each tile travelled beyond its effective range. + /// Conversion from 13: damage_falloff + /// + FixedPoint2 Falloff, + + /// + /// This makes this falloff value ignore the firing weapon's falloff multiplier. Used primarily to simulate having a capped maximum range. Should generally be false. + /// + bool IgnoreModifiers +); diff --git a/Content.Shared/ADT/_RMC14/Projectiles/RMCProjectileSystem.cs b/Content.Shared/ADT/_RMC14/Projectiles/RMCProjectileSystem.cs new file mode 100644 index 00000000000..a10b3ca51fc --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Projectiles/RMCProjectileSystem.cs @@ -0,0 +1,181 @@ +using System.Numerics; +using Content.Shared.FixedPoint; +using Content.Shared.Mobs.Systems; +using Content.Shared.Popups; +using Content.Shared.Projectiles; +using Content.Shared.Whitelist; +using Robust.Shared.Network; +using Robust.Shared.Physics.Events; +using Robust.Shared.Physics.Systems; + +namespace Content.Shared._RMC14.Projectiles; + +public sealed class RMCProjectileSystem : EntitySystem +{ + [Dependency] private readonly MobStateSystem _mobState = default!; + [Dependency] private readonly INetManager _net = default!; + [Dependency] private readonly SharedPhysicsSystem _physics = default!; + [Dependency] private readonly SharedPopupSystem _popup = default!; + [Dependency] private readonly SharedTransformSystem _transform = default!; + [Dependency] private readonly EntityWhitelistSystem _whitelist = default!; + + public override void Initialize() + { + SubscribeLocalEvent(OnDeleteOnCollideStartCollide); + SubscribeLocalEvent(OnModifyTargetOnHit); + SubscribeLocalEvent(OnProjectileMaxRangeMapInit); + + SubscribeLocalEvent(OnFalloffProjectileMapInit); + SubscribeLocalEvent(OnFalloffProjectileHit); + + SubscribeLocalEvent(OnSpawnOnTerminatingMapInit); + SubscribeLocalEvent(OnSpawnOnTerminatingTerminate); + + SubscribeLocalEvent(OnPreventCollideWithDead); + } + + private void OnDeleteOnCollideStartCollide(Entity ent, ref StartCollideEvent args) + { + if (_net.IsServer) + QueueDel(ent); + } + + private void OnModifyTargetOnHit(Entity ent, ref ProjectileHitEvent args) + { + if (!_whitelist.IsWhitelistPassOrNull(ent.Comp.Whitelist, args.Target)) + return; + + if (ent.Comp.Add is { } add) + EntityManager.AddComponents(args.Target, add); + } + + private void OnProjectileMaxRangeMapInit(Entity ent, ref MapInitEvent args) + { + ent.Comp.Origin = _transform.GetMoverCoordinates(ent); + Dirty(ent); + } + + private void OnFalloffProjectileMapInit(Entity projectile, ref MapInitEvent args) + { + projectile.Comp.ShotFrom = _transform.GetMoverCoordinates(projectile.Owner); + Dirty(projectile); + } + + private void OnFalloffProjectileHit(Entity projectile, ref ProjectileHitEvent args) + { + if (projectile.Comp.ShotFrom == null || projectile.Comp.MinRemainingDamageMult < 0) + return; + + var distance = (_transform.GetMoverCoordinates(args.Target).Position - projectile.Comp.ShotFrom.Value.Position).Length(); + var minDamage = args.Damage.GetTotal() * projectile.Comp.MinRemainingDamageMult; + + foreach (var threshold in projectile.Comp.Thresholds) + { + var pastEffectiveRange = distance - threshold.Range; + + if (pastEffectiveRange <= 0) + continue; + + var totalDamage = args.Damage.GetTotal(); + + if (totalDamage <= minDamage) + break; + + var extraMult = threshold.IgnoreModifiers ? 1 : projectile.Comp.WeaponMult; + var minMult = FixedPoint2.Min(minDamage / totalDamage, 1); + + args.Damage *= FixedPoint2.Clamp((totalDamage - pastEffectiveRange * threshold.Falloff * extraMult) / totalDamage, minMult, 1); + + } + } + + public void SetProjectileFalloffWeaponMult(Entity projectile, FixedPoint2 mult) + { + projectile.Comp.WeaponMult = mult; + Dirty(projectile); + } + + private void OnSpawnOnTerminatingMapInit(Entity ent, ref MapInitEvent args) + { + ent.Comp.Origin = _transform.GetMoverCoordinates(ent); + Dirty(ent); + } + + private void OnSpawnOnTerminatingTerminate(Entity ent, ref EntityTerminatingEvent args) + { + if (_net.IsClient) + return; + + if (!TryComp(ent, out TransformComponent? transform)) + return; + + if (TerminatingOrDeleted(transform.ParentUid)) + return; + + var coordinates = transform.Coordinates; + if (ent.Comp.ProjectileAdjust && + ent.Comp.Origin is { } origin && + coordinates.TryDelta(EntityManager, _transform, origin, out var delta) && + delta.Length() > 0) + { + coordinates = coordinates.Offset(delta.Normalized() / -2); + } + + SpawnAtPosition(ent.Comp.Spawn, coordinates); + + if (ent.Comp.Popup is { } popup) + _popup.PopupCoordinates(Loc.GetString(popup), coordinates, ent.Comp.PopupType ?? PopupType.Small); + } + + private void OnPreventCollideWithDead(Entity ent, ref PreventCollideEvent args) + { + if (args.Cancelled) + return; + + if (_mobState.IsDead(args.OtherEntity)) + args.Cancelled = true; + } + + public void SetMaxRange(Entity ent, float max) + { + ent.Comp.Max = max; + Dirty(ent); + } + + private void StopProjectile(Entity ent) + { + if (ent.Comp.Delete) + { + if (_net.IsServer) + QueueDel(ent); + } + else + { + _physics.SetLinearVelocity(ent, Vector2.Zero); + RemCompDeferred(ent); + } + } + + public override void Update(float frameTime) + { + if (_net.IsClient) + return; + + var maxQuery = EntityQueryEnumerator(); + while (maxQuery.MoveNext(out var uid, out var comp)) + { + var coordinates = _transform.GetMoverCoordinates(uid); + if (comp.Origin is not { } origin || + !coordinates.TryDistance(EntityManager, _transform, origin, out var distance)) + { + StopProjectile((uid, comp)); + continue; + } + + if (distance < comp.Max && Math.Abs(distance - comp.Max) > 0.1f) + continue; + + StopProjectile((uid, comp)); + } + } +} diff --git a/Content.Shared/ADT/_RMC14/Projectiles/SpawnOnTerminateComponent.cs b/Content.Shared/ADT/_RMC14/Projectiles/SpawnOnTerminateComponent.cs new file mode 100644 index 00000000000..8ee0c41fcdd --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Projectiles/SpawnOnTerminateComponent.cs @@ -0,0 +1,26 @@ +using Content.Shared.Popups; +using Robust.Shared.GameStates; +using Robust.Shared.Map; +using Robust.Shared.Prototypes; + +namespace Content.Shared._RMC14.Projectiles; + +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +[Access(typeof(RMCProjectileSystem))] +public sealed partial class SpawnOnTerminateComponent : Component +{ + [DataField, AutoNetworkedField] + public EntityCoordinates? Origin; + + [DataField(required: true), AutoNetworkedField] + public EntProtoId Spawn; + + [DataField, AutoNetworkedField] + public LocId? Popup; + + [DataField, AutoNetworkedField] + public PopupType? PopupType; + + [DataField, AutoNetworkedField] + public bool ProjectileAdjust = true; +} diff --git a/Content.Shared/ADT/_RMC14/Scoping/GunScopingComponent.cs b/Content.Shared/ADT/_RMC14/Scoping/GunScopingComponent.cs new file mode 100644 index 00000000000..c1a3b9a8215 --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Scoping/GunScopingComponent.cs @@ -0,0 +1,11 @@ +using Robust.Shared.GameStates; + +namespace Content.Shared._RMC14.Scoping; + +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +[Access(typeof(SharedScopeSystem))] +public sealed partial class GunScopingComponent : Component +{ + [DataField, AutoNetworkedField] + public EntityUid? Scope; +} diff --git a/Content.Shared/ADT/_RMC14/Scoping/ScopeComponent.cs b/Content.Shared/ADT/_RMC14/Scoping/ScopeComponent.cs new file mode 100644 index 00000000000..ab5d64241a8 --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Scoping/ScopeComponent.cs @@ -0,0 +1,84 @@ +using Robust.Shared.GameStates; +using Robust.Shared.Prototypes; +using Robust.Shared.Serialization; + +namespace Content.Shared._RMC14.Scoping; + +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +[Access(typeof(SharedScopeSystem))] +public sealed partial class ScopeComponent : Component +{ + [DataField, AutoNetworkedField] + public int CurrentZoomLevel = 0; + + [DataField, AutoNetworkedField] + public List ZoomLevels = new() + { + new ScopeZoomLevel(null, 1f, 15, false, TimeSpan.FromSeconds(1)) + }; + + /// + /// The entity that's scoping + /// + [ViewVariables, AutoNetworkedField] + public EntityUid? User; + + [DataField, AutoNetworkedField] + public EntProtoId ScopingToggleAction = "ADTActionToggleScope"; + + [DataField, AutoNetworkedField] + public EntityUid? ScopingToggleActionEntity; + + [DataField, AutoNetworkedField] + public EntProtoId CycleZoomLevelAction = "ADTActionCycleZoomLevel"; + + [DataField, AutoNetworkedField] + public EntityUid? CycleZoomLevelActionEntity; + + [DataField, AutoNetworkedField] + public bool RequireWielding; + + [DataField, AutoNetworkedField] + public bool UseInHand; + + [DataField, AutoNetworkedField] + public Direction? ScopingDirection; + + [DataField, AutoNetworkedField] + public EntityUid? RelayEntity; + + [DataField, AutoNetworkedField] + public bool Attachment; +} + +[DataRecord, Serializable, NetSerializable] +public record struct ScopeZoomLevel( + /// + /// This is used in the popup when cycling through zoom levels. + /// + string? Name, + + /// + /// Value to which zoom will be set when scoped in. + /// + float Zoom, + + // TODO RMC14 scoping making this too high causes pop-in + // wait until https://github.com/space-wizards/RobustToolbox/pull/5228 is fixed to increase it + // cm13 values: 11 tile offset, 24x24 view in 4x | 6 tile offset, normal view in 2x. + // right now we are doing a mix of both and only one setting. + /// + /// How much to offset the user's view by when scoping. + /// + float Offset, + + /// + /// If set to true, the user's movement won't interrupt the scoping action. + /// + bool AllowMovement, + + /// + /// The length of the doafter to zoom in. + /// + TimeSpan DoAfter +); diff --git a/Content.Shared/ADT/_RMC14/Scoping/ScopeCycleZoomLevelEvent.cs b/Content.Shared/ADT/_RMC14/Scoping/ScopeCycleZoomLevelEvent.cs new file mode 100644 index 00000000000..c41d1bd670e --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Scoping/ScopeCycleZoomLevelEvent.cs @@ -0,0 +1,5 @@ +using Content.Shared.Actions; + +namespace Content.Shared._RMC14.Scoping; + +public sealed partial class ScopeCycleZoomLevelEvent : InstantActionEvent; diff --git a/Content.Shared/ADT/_RMC14/Scoping/ScopeDoAfterEvent.cs b/Content.Shared/ADT/_RMC14/Scoping/ScopeDoAfterEvent.cs new file mode 100644 index 00000000000..7b74523d321 --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Scoping/ScopeDoAfterEvent.cs @@ -0,0 +1,16 @@ +using Content.Shared.DoAfter; +using Robust.Shared.Serialization; + +namespace Content.Shared._RMC14.Scoping; + +[Serializable, NetSerializable] +public sealed partial class ScopeDoAfterEvent : SimpleDoAfterEvent +{ + [DataField] + public Direction Direction; + + public ScopeDoAfterEvent(Direction direction) + { + Direction = direction; + } +} diff --git a/Content.Shared/ADT/_RMC14/Scoping/ScopingComponent.cs b/Content.Shared/ADT/_RMC14/Scoping/ScopingComponent.cs new file mode 100644 index 00000000000..bdeea75630f --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Scoping/ScopingComponent.cs @@ -0,0 +1,18 @@ +using System.Numerics; +using Robust.Shared.GameStates; + +namespace Content.Shared._RMC14.Scoping; + +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +[Access(typeof(SharedScopeSystem))] +public sealed partial class ScopingComponent : Component +{ + [ViewVariables, AutoNetworkedField] + public EntityUid? Scope; + + [ViewVariables, AutoNetworkedField] + public Vector2 EyeOffset; + + [ViewVariables, AutoNetworkedField] + public bool AllowMovement; +} diff --git a/Content.Shared/ADT/_RMC14/Scoping/SharedScopeSystem.User.cs b/Content.Shared/ADT/_RMC14/Scoping/SharedScopeSystem.User.cs new file mode 100644 index 00000000000..6ad64e48054 --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Scoping/SharedScopeSystem.User.cs @@ -0,0 +1,102 @@ +using Content.Shared.Camera; +using Content.Shared.Mobs; +using Content.Shared.Movement.Events; +using Content.Shared.Movement.Pulling.Events; +using Content.Shared.Stunnable; +using Robust.Shared.Containers; +using Robust.Shared.Player; + +namespace Content.Shared._RMC14.Scoping; + +public partial class SharedScopeSystem +{ + private void InitializeUser() + { + SubscribeLocalEvent(OnRemove); + SubscribeLocalEvent(OnMoveInput); + SubscribeLocalEvent(OnPullStarted); + SubscribeLocalEvent(OnParentChanged); + SubscribeLocalEvent(OnInsertAttempt); + SubscribeLocalEvent(OnEntityTerminating); + SubscribeLocalEvent(OnGetEyeOffset); + SubscribeLocalEvent(OnPlayerDetached); + SubscribeLocalEvent(OnKnockedDown); + SubscribeLocalEvent(OnStunned); + SubscribeLocalEvent(OnMobStateChanged); + } + + private void OnRemove(Entity user, ref ComponentRemove args) + { + if (!TerminatingOrDeleted(user)) + UpdateOffset(user); + } + + private void OnMoveInput(Entity ent, ref MoveInputEvent args) + { + if (!args.HasDirectionalMovement) + return; + + if (!ent.Comp.AllowMovement) + UserStopScoping(ent); + } + + private void OnPullStarted(Entity ent, ref PullStartedMessage args) + { + if (args.PulledUid != ent.Owner) + return; + + UserStopScoping(ent); + } + + private void OnParentChanged(Entity ent, ref EntParentChangedMessage args) + { + UserStopScoping(ent); + } + + private void OnInsertAttempt(Entity ent, ref ContainerGettingInsertedAttemptEvent args) + { + UserStopScoping(ent); + } + + private void OnEntityTerminating(Entity ent, ref EntityTerminatingEvent args) + { + UserStopScoping(ent); + } + + private void OnGetEyeOffset(Entity ent, ref GetEyeOffsetEvent args) + { + args.Offset += ent.Comp.EyeOffset; + } + + private void OnPlayerDetached(Entity ent, ref PlayerDetachedEvent args) + { + UserStopScoping(ent); + } + + private void OnKnockedDown(Entity ent, ref KnockedDownEvent args) + { + UserStopScoping(ent); + } + + private void OnStunned(Entity ent, ref StunnedEvent args) + { + UserStopScoping(ent); + } + + private void OnMobStateChanged(Entity ent, ref MobStateChangedEvent args) + { + if (args.NewMobState == MobState.Alive) + return; + + UserStopScoping(ent); + } + + private void UserStopScoping(Entity ent) + { + var scope = ent.Comp.Scope; + RemCompDeferred(ent); + + if (TryComp(scope, out ScopeComponent? scopeComponent) && scopeComponent.User == ent) + Unscope((scope.Value, scopeComponent)); + } +} diff --git a/Content.Shared/ADT/_RMC14/Scoping/SharedScopeSystem.cs b/Content.Shared/ADT/_RMC14/Scoping/SharedScopeSystem.cs new file mode 100644 index 00000000000..25bc98b1046 --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Scoping/SharedScopeSystem.cs @@ -0,0 +1,402 @@ +using System.Numerics; +using Content.Shared._RMC14.Attachable.Events; +using Content.Shared.Actions; +using Content.Shared.Camera; +using Content.Shared.DoAfter; +using Content.Shared.Hands; +using Content.Shared.Hands.EntitySystems; +using Content.Shared.Interaction; +using Content.Shared.Movement.Pulling.Systems; +using Content.Shared.Movement.Systems; +using Content.Shared.Popups; +using Content.Shared.Toggleable; +using Content.Shared.Weapons.Ranged.Components; +using Content.Shared.Weapons.Ranged.Systems; +using Content.Shared.Wieldable; +using Content.Shared.Wieldable.Components; +using Robust.Shared.Containers; + +namespace Content.Shared._RMC14.Scoping; + +public abstract partial class SharedScopeSystem : EntitySystem +{ + [Dependency] private readonly ActionContainerSystem _actionContainer = default!; + [Dependency] private readonly SharedActionsSystem _actionsSystem = default!; + [Dependency] private readonly SharedContainerSystem _container = default!; + [Dependency] private readonly SharedContentEyeSystem _contentEye = default!; + [Dependency] private readonly SharedDoAfterSystem _doAfter = default!; + [Dependency] private readonly SharedEyeSystem _eye = default!; + [Dependency] private readonly SharedHandsSystem _hands = default!; + [Dependency] private readonly SharedPopupSystem _popup = default!; + [Dependency] private readonly PullingSystem _pulling = default!; + + public override void Initialize() + { + InitializeUser(); + + SubscribeLocalEvent(OnMapInit); + SubscribeLocalEvent(OnShutdown); + SubscribeLocalEvent(OnScopeEntityTerminating); + SubscribeLocalEvent(OnUnequip); + SubscribeLocalEvent(OnDeselectHand); + SubscribeLocalEvent(OnUnwielded); + SubscribeLocalEvent(OnGetActions); + SubscribeLocalEvent(OnToggleAction); + SubscribeLocalEvent(OnCycleZoomLevel); + SubscribeLocalEvent(OnActivateInWorld); + SubscribeLocalEvent(OnGunShot); + SubscribeLocalEvent(OnScopeDoAfter); + + SubscribeLocalEvent(OnGunUnequip); + SubscribeLocalEvent(OnGunDeselectHand); + SubscribeLocalEvent(OnGunUnwielded); + SubscribeLocalEvent(OnGunGunShot); + } + + private void OnMapInit(Entity ent, ref MapInitEvent args) + { + _actionContainer.EnsureAction(ent.Owner, ref ent.Comp.ScopingToggleActionEntity, ent.Comp.ScopingToggleAction); + + if (ent.Comp.ZoomLevels.Count > 1) + _actionContainer.EnsureAction(ent.Owner, ref ent.Comp.CycleZoomLevelActionEntity, ent.Comp.CycleZoomLevelAction); + + Dirty(ent.Owner, ent.Comp); + } + + private void OnShutdown(Entity ent, ref ComponentRemove args) + { + if (ent.Comp.User is not { } user) + return; + + Unscope(ent); + _actionsSystem.RemoveProvidedActions(user, ent.Owner); + } + + private void OnScopeEntityTerminating(Entity ent, ref EntityTerminatingEvent args) + { + Unscope(ent); + } + + private void OnUnequip(Entity ent, ref GotUnequippedHandEvent args) + { + Unscope(ent); + } + + private void OnDeselectHand(Entity ent, ref HandDeselectedEvent args) + { + Unscope(ent); + } + + private void OnUnwielded(Entity ent, ref ItemUnwieldedEvent args) + { + if (ent.Comp.RequireWielding) + Unscope(ent); + } + + private void OnGetActions(Entity ent, ref GetItemActionsEvent args) + { + args.AddAction(ref ent.Comp.ScopingToggleActionEntity, ent.Comp.ScopingToggleAction); + + if (ent.Comp.ZoomLevels.Count > 1) + args.AddAction(ref ent.Comp.CycleZoomLevelActionEntity, ent.Comp.CycleZoomLevelAction); + } + + private void OnToggleAction(Entity ent, ref ToggleActionEvent args) + { + if (args.Handled) + return; + + args.Handled = true; + ToggleScoping(ent, args.Performer); + } + + private void OnCycleZoomLevel(Entity scope, ref ScopeCycleZoomLevelEvent args) + { + if (args.Handled) + return; + + args.Handled = true; + + if (scope.Comp.CurrentZoomLevel >= scope.Comp.ZoomLevels.Count - 1) + scope.Comp.CurrentZoomLevel = 0; + else + ++scope.Comp.CurrentZoomLevel; + + var zoomLevel = GetCurrentZoomLevel(scope); + if (zoomLevel.Name != null) + _popup.PopupClient(Loc.GetString("rcm-action-popup-scope-cycle-zoom", ("zoom", zoomLevel.Name)), args.Performer, args.Performer); + + Dirty(scope); + } + + private void OnActivateInWorld(Entity ent, ref ActivateInWorldEvent args) + { + if (args.Handled || !args.Complex || !ent.Comp.UseInHand) + return; + + args.Handled = true; + ToggleScoping(ent, args.User); + } + + private void OnGunShot(Entity ent, ref GunShotEvent args) + { + var dir = Transform(args.User).LocalRotation.GetCardinalDir(); + if (ent.Comp.ScopingDirection != dir) + Unscope(ent); + } + + private void OnScopeDoAfter(Entity ent, ref ScopeDoAfterEvent args) + { + if (args.Handled) + return; + + args.Handled = true; + + if (args.Cancelled) + { + DeleteRelay(ent, args.User); + return; + } + + var user = args.User; + if (!CanScopePopup(ent, user)) + { + DeleteRelay(ent, args.User); + return; + } + + Scope(ent, user, args.Direction); + } + + private void OnGunUnequip(Entity ent, ref GotUnequippedHandEvent args) + { + UnscopeGun(ent); + } + + private void OnGunDeselectHand(Entity ent, ref HandDeselectedEvent args) + { + UnscopeGun(ent); + } + + private void OnGunUnwielded(Entity ent, ref ItemUnwieldedEvent args) + { + UnscopeGun(ent); + } + + private void OnGunGunShot(Entity ent, ref GunShotEvent args) + { + var dir = Transform(args.User).LocalRotation.GetCardinalDir(); + if (TryComp(ent.Comp.Scope, out ScopeComponent? scope) && scope.ScopingDirection != dir) + UnscopeGun(ent); + } + + private bool CanScopePopup(Entity scope, EntityUid user) + { + var ent = scope.Owner; + if (scope.Comp.Attachment && !TryGetActiveEntity(scope, out ent)) + { + var msgError = Loc.GetString("cm-action-popup-scoping-must-attach", ("scope", ent)); + _popup.PopupClient(msgError, user, user); + return false; + } + + if (!_hands.TryGetActiveItem(user, out var heldItem) || !scope.Comp.Attachment && heldItem != scope.Owner) + { + var msgError = Loc.GetString("cm-action-popup-scoping-user-must-hold", ("scope", ent)); + _popup.PopupClient(msgError, user, user); + return false; + } + + if (_pulling.IsPulled(user)) + { + var msgError = Loc.GetString("cm-action-popup-scoping-user-must-not-pulled", ("scope", ent)); + _popup.PopupClient(msgError, user, user); + return false; + } + + if (_container.IsEntityInContainer(user)) + { + var msgError = Loc.GetString("cm-action-popup-scoping-user-must-not-contained", ("scope", ent)); + _popup.PopupClient(msgError, user, user); + return false; + } + + if (scope.Comp.RequireWielding && + TryComp(ent, out WieldableComponent? wieldable) && + !wieldable.Wielded) + { + var msgError = Loc.GetString("cm-action-popup-scoping-user-must-wield", ("scope", ent)); + _popup.PopupClient(msgError, user, user); + return false; + } + + return true; + } + + protected virtual Direction? StartScoping(Entity scope, EntityUid user) + { + if (!CanScopePopup(scope, user)) + return null; + + // TODO RMC14 make this work properly with rotations + var xform = Transform(user); + var cardinalDir = xform.LocalRotation.GetCardinalDir(); + var ev = new ScopeDoAfterEvent(cardinalDir); + var zoomLevel = GetCurrentZoomLevel(scope); + var doAfter = new DoAfterArgs(EntityManager, user, zoomLevel.DoAfter, ev, scope, null, scope) + { + BreakOnMove = !zoomLevel.AllowMovement + }; + + if (_doAfter.TryStartDoAfter(doAfter)) + return cardinalDir; + + return null; + } + + private void Scope(Entity scope, EntityUid user, Direction direction) + { + if (TryComp(user, out ScopingComponent? scoping)) + UserStopScoping((user, scoping)); + + var zoomLevel = GetCurrentZoomLevel(scope); + + scope.Comp.User = user; + scope.Comp.ScopingDirection = direction; + + Dirty(scope); + + scoping = EnsureComp(user); + scoping.Scope = scope; + scoping.AllowMovement = zoomLevel.AllowMovement; + Dirty(user, scoping); + + if (scope.Comp.Attachment && TryGetActiveEntity(scope, out var active)) + { + var gunScoping = EnsureComp(active); + gunScoping.Scope = scope; + Dirty(active, gunScoping); + } + + var targetOffset = GetScopeOffset(scope, direction); + scoping.EyeOffset = targetOffset; + + var msgUser = Loc.GetString("cm-action-popup-scoping-user", ("scope", scope.Owner)); + _popup.PopupClient(msgUser, user, user); + + _actionsSystem.SetToggled(scope.Comp.ScopingToggleActionEntity, true); + _contentEye.SetZoom(user, Vector2.One * zoomLevel.Zoom, true); + UpdateOffset(user); + } + + protected virtual bool Unscope(Entity scope) + { + if (scope.Comp.User is not { } user) + return false; + + RemCompDeferred(user); + + if (scope.Comp.Attachment && TryGetActiveEntity(scope, out var active)) + RemCompDeferred(active); + + if (scope.Comp.Attachment && scope.Comp.User != null) + { + var interruptEvent = new AttachableToggleableInterruptEvent(scope.Comp.User.Value); + RaiseLocalEvent(scope.Owner, ref interruptEvent); + } + + scope.Comp.User = null; + scope.Comp.ScopingDirection = null; + Dirty(scope); + + var msgUser = Loc.GetString("cm-action-popup-scoping-stopping-user", ("scope", scope.Owner)); + _popup.PopupClient(msgUser, user, user); + + _actionsSystem.SetToggled(scope.Comp.ScopingToggleActionEntity, false); + _contentEye.ResetZoom(user); + return true; + } + + private void UnscopeGun(Entity gun) + { + if (TryComp(gun.Comp.Scope, out ScopeComponent? scope)) + Unscope((gun.Comp.Scope.Value, scope)); + } + + private void ToggleScoping(Entity scope, EntityUid user) + { + if (HasComp(user)) + { + Unscope(scope); + + if (TryComp(user, out ScopingComponent? scoping)) + UserStopScoping((user, scoping)); + + return; + } + + StartScoping(scope, user); + } + + private bool TryGetActiveEntity(Entity scope, out EntityUid active) + { + if (!scope.Comp.Attachment) + { + active = scope; + return true; + } + + if (!_container.TryGetContainingContainer((scope, null), out var container) || + !HasComp(container.Owner)) + { + active = default; + return false; + } + + active = container.Owner; + return true; + } + + protected Vector2 GetScopeOffset(Entity scope, Direction direction) + { + var zoomLevel = GetCurrentZoomLevel(scope); + return direction.ToVec() * ((zoomLevel.Offset * zoomLevel.Zoom - 1) / 2); + } + + protected virtual void DeleteRelay(Entity scope, EntityUid? user) + { + } + + private ScopeZoomLevel GetCurrentZoomLevel(Entity scope) + { + ValidateCurrentZoomLevel(scope); + return scope.Comp.ZoomLevels[scope.Comp.CurrentZoomLevel]; + } + + private void ValidateCurrentZoomLevel(Entity scope) + { + bool dirty = false; + + if (scope.Comp.ZoomLevels == null || scope.Comp.ZoomLevels.Count <= 0) + { + scope.Comp.ZoomLevels = new List(){ new ScopeZoomLevel(null, 1f, 15, false, TimeSpan.FromSeconds(1)) }; + dirty = true; + } + + if (scope.Comp.CurrentZoomLevel >= scope.Comp.ZoomLevels.Count) + { + scope.Comp.CurrentZoomLevel = 0; + dirty = true; + } + + if (dirty) + Dirty(scope); + } + + private void UpdateOffset(EntityUid user) + { + var ev = new GetEyeOffsetEvent(); + RaiseLocalEvent(user, ref ev); + _eye.SetOffset(user, ev.Offset); + } +} diff --git a/Content.Shared/ADT/_RMC14/Sound/CMSoundSystem.cs b/Content.Shared/ADT/_RMC14/Sound/CMSoundSystem.cs new file mode 100644 index 00000000000..91a63d4edb2 --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Sound/CMSoundSystem.cs @@ -0,0 +1,75 @@ +using Content.Shared.Mobs; +using Content.Shared.Mobs.Systems; +using Content.Shared.Sound; +using Robust.Shared.Audio.Systems; +using Robust.Shared.Network; +using Robust.Shared.Random; +using Robust.Shared.Timing; + +namespace Content.Shared._RMC14.Sound; + +public sealed class CMSoundSystem : EntitySystem +{ + [Dependency] private readonly SharedAudioSystem _audio = default!; + [Dependency] private readonly SharedEmitSoundSystem _emitSound = default!; + [Dependency] private readonly MobStateSystem _mobState = default!; + [Dependency] private readonly INetManager _net = default!; + [Dependency] private readonly IRobustRandom _random = default!; + [Dependency] private readonly IGameTiming _timing = default!; + + public override void Initialize() + { + SubscribeLocalEvent(OnRandomMapInit); + + SubscribeLocalEvent(OnDeathMobStateChanged); + + SubscribeLocalEvent(OnEmitSoundOnAction); + } + + private void OnRandomMapInit(Entity ent, ref MapInitEvent args) + { + var min = ent.Comp.Min; + var max = ent.Comp.Max; + if (max <= min) + max = min.Add(TimeSpan.FromTicks(1)); + + ent.Comp.PlayAt = _timing.CurTime + _random.Next(min, max); + Dirty(ent); + } + + private void OnDeathMobStateChanged(Entity ent, ref MobStateChangedEvent args) + { + if (args.NewMobState != MobState.Dead) + return; + + if (_net.IsServer) + _audio.PlayPvs(ent.Comp.Sound, ent); + } + + private void OnEmitSoundOnAction(Entity ent, ref SoundActionEvent args) + { + _emitSound.EmitSound(ent, ent, args.Performer); + + if (ent.Comp.Handle) + args.Handled = true; + } + + public override void Update(float frameTime) + { + if (_net.IsClient) + return; + + var time = _timing.CurTime; + var random = EntityQueryEnumerator(); + while (random.MoveNext(out var uid, out var comp)) + { + if (_mobState.IsDead(uid) || time <= comp.PlayAt) + continue; + + comp.PlayAt = time + _random.Next(comp.Min, comp.Max); + Dirty(uid, comp); + + _audio.PlayPvs(comp.Sound, uid); + } + } +} diff --git a/Content.Shared/ADT/_RMC14/Sound/EmitSoundOnActionComponent.cs b/Content.Shared/ADT/_RMC14/Sound/EmitSoundOnActionComponent.cs new file mode 100644 index 00000000000..38126704dca --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Sound/EmitSoundOnActionComponent.cs @@ -0,0 +1,23 @@ +using Robust.Shared.GameStates; +using Content.Shared.Sound.Components; + +namespace Content.Shared._RMC14.Sound; + +/// +/// Simple sound emitter that emits sound on InstantAction +/// +[RegisterComponent] +public sealed partial class EmitSoundOnActionComponent : BaseEmitSoundComponent +{ + /// + /// Whether or not to mark an interaction as handled after playing the sound. Useful if this component is + /// used to play sound for some other component with on-use functionality + /// + /// + /// If false, you should be confident that the interaction will also be handled by some other system, as + /// otherwise this might enable sound spamming, as use-delays are only initiated if the interaction was + /// handled. + /// + [DataField] + public bool Handle = true; +} diff --git a/Content.Shared/ADT/_RMC14/Sound/RandomSoundComponent.cs b/Content.Shared/ADT/_RMC14/Sound/RandomSoundComponent.cs new file mode 100644 index 00000000000..3112f521a13 --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Sound/RandomSoundComponent.cs @@ -0,0 +1,21 @@ +using Robust.Shared.Audio; +using Robust.Shared.GameStates; + +namespace Content.Shared._RMC14.Sound; + +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState, AutoGenerateComponentPause] +[Access(typeof(CMSoundSystem))] +public sealed partial class RandomSoundComponent : Component +{ + [DataField(required: true), AutoNetworkedField] + public SoundSpecifier? Sound; + + [DataField(required: true), AutoNetworkedField] + public TimeSpan Min; + + [DataField(required: true), AutoNetworkedField] + public TimeSpan Max; + + [DataField, AutoNetworkedField, AutoPausedField] + public TimeSpan? PlayAt; +} diff --git a/Content.Shared/ADT/_RMC14/Sound/SoundActionEvent.cs b/Content.Shared/ADT/_RMC14/Sound/SoundActionEvent.cs new file mode 100644 index 00000000000..9b8469f3c97 --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Sound/SoundActionEvent.cs @@ -0,0 +1,5 @@ +using Content.Shared.Actions; + +namespace Content.Shared._RMC14.Sound; + +public sealed partial class SoundActionEvent : InstantActionEvent; diff --git a/Content.Shared/ADT/_RMC14/Sound/SoundOnDeathComponent.cs b/Content.Shared/ADT/_RMC14/Sound/SoundOnDeathComponent.cs new file mode 100644 index 00000000000..c48525c9ab8 --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Sound/SoundOnDeathComponent.cs @@ -0,0 +1,12 @@ +using Robust.Shared.Audio; +using Robust.Shared.GameStates; + +namespace Content.Shared._RMC14.Sound; + +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +[Access(typeof(CMSoundSystem))] +public sealed partial class SoundOnDeathComponent : Component +{ + [DataField(required: true), AutoNetworkedField] + public SoundSpecifier? Sound; +} diff --git a/Content.Shared/ADT/_RMC14/Weapons/Common/UniqueActionComponent.cs b/Content.Shared/ADT/_RMC14/Weapons/Common/UniqueActionComponent.cs new file mode 100644 index 00000000000..83765aa250d --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Weapons/Common/UniqueActionComponent.cs @@ -0,0 +1,7 @@ +using Robust.Shared.GameStates; + +namespace Content.Shared._RMC14.Weapons.Common; + +[RegisterComponent, NetworkedComponent] +[Access(typeof(UniqueActionSystem))] +public sealed partial class UniqueActionComponent : Component; diff --git a/Content.Shared/ADT/_RMC14/Weapons/Common/UniqueActionEvent.cs b/Content.Shared/ADT/_RMC14/Weapons/Common/UniqueActionEvent.cs new file mode 100644 index 00000000000..3ea6d572a44 --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Weapons/Common/UniqueActionEvent.cs @@ -0,0 +1,6 @@ +namespace Content.Shared._RMC14.Weapons.Common; + +public sealed class UniqueActionEvent(EntityUid userUid) : HandledEntityEventArgs +{ + public readonly EntityUid UserUid = userUid; +} diff --git a/Content.Shared/ADT/_RMC14/Weapons/Common/UniqueActionSystem.cs b/Content.Shared/ADT/_RMC14/Weapons/Common/UniqueActionSystem.cs new file mode 100644 index 00000000000..d5bdb59846d --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Weapons/Common/UniqueActionSystem.cs @@ -0,0 +1,68 @@ +using Content.Shared._RMC14.Input; +using Content.Shared.ActionBlocker; +using Content.Shared.Hands.Components; +// using Content.Shared.Verbs; +using Robust.Shared.Input.Binding; + +namespace Content.Shared._RMC14.Weapons.Common; + +public sealed class UniqueActionSystem : EntitySystem +{ + [Dependency] private readonly ActionBlockerSystem _actionBlockerSystem = default!; + [Dependency] private readonly IEntityManager _entityManager = default!; + + + public override void Initialize() + { + // SubscribeLocalEvent>(OnGetVerbs); + + CommandBinds.Builder + .Bind(CMKeyFunctions.CMUniqueAction, + InputCmdHandler.FromDelegate(session => + { + if (session?.AttachedEntity is { } userUid) + TryUniqueAction(userUid); + }, + handle: false)) + .Register(); + } + + public override void Shutdown() + { + base.Shutdown(); + CommandBinds.Unregister(); + } + + // private void OnGetVerbs(Entity ent, ref GetVerbsEvent args) + // { + // if (!args.CanAccess || !args.CanInteract) + // return; + + // if (!_actionBlockerSystem.CanInteract(args.User, args.Target)) + // return; + + // var user = args.User; + // args.Verbs.Add(new InteractionVerb + // { + // Act = () => TryUniqueAction(user, ent.Owner), + // Text = "Unique action", + // }); + // } + + private void TryUniqueAction(EntityUid userUid) + { + if (!_entityManager.TryGetComponent(userUid, out HandsComponent? handsComponent) || + handsComponent.ActiveHandEntity == null) + return; + + TryUniqueAction(userUid, handsComponent.ActiveHandEntity.Value); + } + + private void TryUniqueAction(EntityUid userUid, EntityUid targetUid) + { + if (!_actionBlockerSystem.CanInteract(userUid, targetUid)) + return; + + RaiseLocalEvent(targetUid, new UniqueActionEvent(userUid)); + } +} diff --git a/Content.Shared/ADT/_RMC14/Weapons/Melee/MeleeDamageMultiplierComponent.cs b/Content.Shared/ADT/_RMC14/Weapons/Melee/MeleeDamageMultiplierComponent.cs new file mode 100644 index 00000000000..b58a21e1fa8 --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Weapons/Melee/MeleeDamageMultiplierComponent.cs @@ -0,0 +1,17 @@ +using Robust.Shared.GameStates; + +namespace Content.Shared._RMC14.Weapons.Melee; + +/// +/// For melee weapons to apply extra damage to certain entities with certain component(s). +/// +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +[Access(typeof(SharedRMCMeleeWeaponSystem))] +public sealed partial class MeleeDamageMultiplierComponent : Component +{ + /// + /// The amount the bonus damage is multipled by. For example, 0.5 would be x1.5 the weapon's base damage. + /// + [DataField, AutoNetworkedField] + public float Multiplier = 0.5f; // x1.5 extra damage +} diff --git a/Content.Shared/ADT/_RMC14/Weapons/Melee/MeleeReceivedMultiplierComponent.cs b/Content.Shared/ADT/_RMC14/Weapons/Melee/MeleeReceivedMultiplierComponent.cs new file mode 100644 index 00000000000..985478c0a9d --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Weapons/Melee/MeleeReceivedMultiplierComponent.cs @@ -0,0 +1,13 @@ +using Content.Shared.Damage; +using Content.Shared.FixedPoint; +using Robust.Shared.GameStates; + +namespace Content.Shared._RMC14.Weapons.Melee; + +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +[Access(typeof(SharedRMCMeleeWeaponSystem))] +public sealed partial class MeleeReceivedMultiplierComponent : Component +{ + [DataField(required: true), AutoNetworkedField] + public FixedPoint2 OtherMultiplier; +} diff --git a/Content.Shared/ADT/_RMC14/Weapons/Melee/MeleeResetComponent.cs b/Content.Shared/ADT/_RMC14/Weapons/Melee/MeleeResetComponent.cs new file mode 100644 index 00000000000..b9bfc232746 --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Weapons/Melee/MeleeResetComponent.cs @@ -0,0 +1,11 @@ +using Robust.Shared.GameStates; + +namespace Content.Shared._RMC14.Weapons.Melee; + +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +[Access(typeof(SharedRMCMeleeWeaponSystem))] +public sealed partial class MeleeResetComponent : Component +{ + [DataField, AutoNetworkedField] + public TimeSpan OriginalTime; +} diff --git a/Content.Shared/ADT/_RMC14/Weapons/Melee/SharedRMCMeleeWeaponSystem.cs b/Content.Shared/ADT/_RMC14/Weapons/Melee/SharedRMCMeleeWeaponSystem.cs new file mode 100644 index 00000000000..45184bcac7a --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Weapons/Melee/SharedRMCMeleeWeaponSystem.cs @@ -0,0 +1,121 @@ +using Content.Shared.Damage; +using Content.Shared.Interaction.Events; +using Content.Shared.Weapons.Melee; +using Content.Shared.Weapons.Melee.Events; +using Robust.Shared.Timing; + +namespace Content.Shared._RMC14.Weapons.Melee; + +public abstract class SharedRMCMeleeWeaponSystem : EntitySystem +{ + [Dependency] private readonly IGameTiming _timing = default!; + [Dependency] private readonly SharedMeleeWeaponSystem _melee = default!; + + private EntityQuery _meleeWeaponQuery; + + public override void Initialize() + { + _meleeWeaponQuery = GetEntityQuery(); + + SubscribeLocalEvent(OnMeleeReceivedMultiplierDamageModify); + + SubscribeLocalEvent(OnMultiplierOnHitMeleeHit); + + SubscribeAllEvent(OnLightAttack, before: new[] { typeof(SharedMeleeWeaponSystem) }); + + SubscribeAllEvent(OnHeavyAttack, before: new[] { typeof(SharedMeleeWeaponSystem) }); + + SubscribeAllEvent(OnDisarmAttack, before: new[] { typeof(SharedMeleeWeaponSystem) }); + } + + //Call this whenever you add MeleeResetComponent to anything + public void MeleeResetInit(Entity ent) + { + if (!TryComp(ent, out var weapon)) + { + RemComp(ent); + return; + } + + ent.Comp.OriginalTime = weapon.NextAttack; + weapon.NextAttack = _timing.CurTime; + Dirty(ent, weapon); + Dirty(ent, ent.Comp); + } + + private void OnMultiplierOnHitMeleeHit(Entity ent, ref MeleeHitEvent args) + { + if (!args.IsHit) + return; + + var comp = ent.Comp; + + foreach (var hit in args.HitEntities) + { + var damage = args.BaseDamage * comp.Multiplier; + args.BonusDamage += damage; + break; + } + } + + private void OnMeleeReceivedMultiplierDamageModify(Entity ent, ref DamageModifyEvent args) + { + if (!_meleeWeaponQuery.HasComp(args.Tool)) + return; + + args.Damage = args.Damage * ent.Comp.OtherMultiplier; + } + + private void OnLightAttack(LightAttackEvent msg, EntitySessionEventArgs args) + { + if (args.SenderSession.AttachedEntity is not {} user) + return; + + if (!_melee.TryGetWeapon(user, out var weaponUid, out var weapon) || + weaponUid != GetEntity(msg.Weapon)) + { + return; + } + + TryMeleeReset(weaponUid, weapon, false); + } + + private void OnHeavyAttack(HeavyAttackEvent msg, EntitySessionEventArgs args) + { + if (args.SenderSession.AttachedEntity is not {} user) + return; + + if (!_melee.TryGetWeapon(user, out var weaponUid, out var weapon) || + weaponUid != GetEntity(msg.Weapon)) + { + return; + } + + TryMeleeReset(weaponUid, weapon, false); + } + + private void OnDisarmAttack(DisarmAttackEvent msg, EntitySessionEventArgs args) + { + if (args.SenderSession.AttachedEntity is not {} user) + return; + + if (!_melee.TryGetWeapon(user, out var weaponUid, out var weapon)) + { + return; + } + + TryMeleeReset(weaponUid, weapon, true); + } + + + private void TryMeleeReset(EntityUid weaponUid, MeleeWeaponComponent weapon, bool disarm){ + if (!TryComp(weaponUid, out var reset)) + return; + + if (disarm) + weapon.NextAttack = reset.OriginalTime; + + RemComp(weaponUid); + Dirty(weaponUid, weapon); + } +} diff --git a/Content.Shared/ADT/_RMC14/Weapons/Ranged/Ammo/GunToggleAmmoActionEvent.cs b/Content.Shared/ADT/_RMC14/Weapons/Ranged/Ammo/GunToggleAmmoActionEvent.cs new file mode 100644 index 00000000000..f4ad89a5009 --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Weapons/Ranged/Ammo/GunToggleAmmoActionEvent.cs @@ -0,0 +1,5 @@ +using Content.Shared.Actions; + +namespace Content.Shared._RMC14.Weapons.Ranged.Ammo; + +public sealed partial class GunToggleAmmoActionEvent : InstantActionEvent; diff --git a/Content.Shared/ADT/_RMC14/Weapons/Ranged/Ammo/GunToggleableAmmoComponent.cs b/Content.Shared/ADT/_RMC14/Weapons/Ranged/Ammo/GunToggleableAmmoComponent.cs new file mode 100644 index 00000000000..b1f14ea9776 --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Weapons/Ranged/Ammo/GunToggleableAmmoComponent.cs @@ -0,0 +1,32 @@ +using Content.Shared.Damage; +using Robust.Shared.Audio; +using Robust.Shared.GameStates; +using Robust.Shared.Prototypes; +using Robust.Shared.Serialization; +using Robust.Shared.Utility; + +namespace Content.Shared._RMC14.Weapons.Ranged.Ammo; + +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +[Access(typeof(GunToggleableAmmoSystem))] +public sealed partial class GunToggleableAmmoComponent : Component +{ + [DataField(required: true), AutoNetworkedField] + public List Settings = new(); + + [DataField, AutoNetworkedField] + public int Setting; + + [DataField, AutoNetworkedField] + public EntProtoId ActionId = "RMCActionToggleAmmo"; + + [DataField, AutoNetworkedField] + public EntityUid? Action; + + [DataField, AutoNetworkedField] + public SoundSpecifier ToggleSound = new SoundPathSpecifier("/Audio/Items/beep.ogg"); +} + +[DataRecord] +[Serializable, NetSerializable] +public readonly record struct GunToggleableAmmoSetting(DamageSpecifier Damage, int ArmorPiercing, LocId Name, SpriteSpecifier.Rsi Icon); diff --git a/Content.Shared/ADT/_RMC14/Weapons/Ranged/Ammo/GunToggleableAmmoSystem.cs b/Content.Shared/ADT/_RMC14/Weapons/Ranged/Ammo/GunToggleableAmmoSystem.cs new file mode 100644 index 00000000000..9f01a294b25 --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Weapons/Ranged/Ammo/GunToggleableAmmoSystem.cs @@ -0,0 +1,95 @@ +using System.Runtime.InteropServices; +using Content.Shared._RMC14.Armor; +using Content.Shared._RMC14.Weapons.Common; +using Content.Shared.Actions; +using Content.Shared.Damage; +using Content.Shared.Popups; +using Content.Shared.Projectiles; +using Content.Shared.Weapons.Ranged.Events; +using Robust.Shared.Audio.Systems; + +namespace Content.Shared._RMC14.Weapons.Ranged.Ammo; + +public sealed class GunToggleableAmmoSystem : EntitySystem +{ + [Dependency] private readonly SharedActionsSystem _actions = default!; + [Dependency] private readonly SharedAudioSystem _audio = default!; + [Dependency] private readonly SharedPopupSystem _popup = default!; + + private EntityQuery _projectileQuery; + + public override void Initialize() + { + _projectileQuery = GetEntityQuery(); + + SubscribeLocalEvent(OnGetItemActions); + SubscribeLocalEvent(OnToggleAmmoAction); + SubscribeLocalEvent(OnAmmoShot); + SubscribeLocalEvent(OnUniqueAction); + } + + private void OnGetItemActions(Entity ent, ref GetItemActionsEvent args) + { + args.AddAction(ref ent.Comp.Action, ent.Comp.ActionId); + Dirty(ent); + } + + private void OnToggleAmmoAction(Entity ent, ref GunToggleAmmoActionEvent args) + { + if (ToggleAmmo(ent, args.Performer)) + args.Handled = true; + } + + private void OnAmmoShot(Entity ent, ref AmmoShotEvent args) + { + var settingIndex = ent.Comp.Setting; + if (settingIndex < 0 || settingIndex >= ent.Comp.Settings.Count) + return; + + ref var setting = ref CollectionsMarshal.AsSpan(ent.Comp.Settings)[settingIndex]; + foreach (var projectile in args.FiredProjectiles) + { + if (_projectileQuery.TryComp(projectile, out var projectileComp)) + { + projectileComp.Damage = new DamageSpecifier(setting.Damage); + Dirty(projectile, projectileComp); + } + } + } + + private void OnUniqueAction(Entity ent, ref UniqueActionEvent args) + { + if (args.Handled) + return; + + if (ToggleAmmo(ent, args.UserUid)) + args.Handled = true; + } + + private bool ToggleAmmo(Entity ent, EntityUid user) + { + if (ent.Comp.Settings.Count == 0) + return false; + + ref var settingIndex = ref ent.Comp.Setting; + settingIndex++; + if (settingIndex >= ent.Comp.Settings.Count) + settingIndex = 0; + + var setting = ent.Comp.Settings[settingIndex]; + var popup = Loc.GetString("rmc-toggleable-ammo-firing", ("ammo", Loc.GetString(setting.Name))); + _popup.PopupClient(popup, user, user, PopupType.Large); + + _audio.PlayPredicted(ent.Comp.ToggleSound, ent, user); + + if (_actions.TryGetActionData(ent.Comp.Action, out var action)) + { + action.Icon = setting.Icon; + Dirty(ent.Comp.Action.Value, action); + _actions.UpdateAction(ent.Comp.Action, action); + } + + Dirty(ent); + return true; + } +} diff --git a/Content.Shared/ADT/_RMC14/Weapons/Ranged/BreechLoadedComponent.cs b/Content.Shared/ADT/_RMC14/Weapons/Ranged/BreechLoadedComponent.cs new file mode 100644 index 00000000000..1fae1555f26 --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Weapons/Ranged/BreechLoadedComponent.cs @@ -0,0 +1,37 @@ +using Robust.Shared.Audio; +using Robust.Shared.GameStates; +using Robust.Shared.Serialization; + +namespace Content.Shared._RMC14.Weapons.Ranged; + +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +[Access(typeof(BreechLoadedSystem))] +public sealed partial class BreechLoadedComponent : Component +{ + [DataField, AutoNetworkedField] + public bool Open; + + /// + /// If this is set to true, the user must open and close the breech between every shot. + /// + [DataField, AutoNetworkedField] + public bool NeedOpenClose; + + [DataField, AutoNetworkedField] + public bool Ready; + + [DataField, AutoNetworkedField] + public SoundSpecifier OpenSound = new SoundPathSpecifier("/Audio/_RMC14/Weapons/Guns/Breech/ugl_open.ogg", AudioParams.Default.WithVolume(-6.5f)); + + [DataField, AutoNetworkedField] + public SoundSpecifier CloseSound = new SoundPathSpecifier("/Audio/_RMC14/Weapons/Guns/Breech/ugl_close.ogg", AudioParams.Default.WithVolume(-6.5f)); + + [DataField, AutoNetworkedField] + public bool ShowBreechOpen = true; +} + +[Serializable, NetSerializable] +public enum BreechVisuals : byte +{ + Open +} diff --git a/Content.Shared/ADT/_RMC14/Weapons/Ranged/BreechLoadedSystem.cs b/Content.Shared/ADT/_RMC14/Weapons/Ranged/BreechLoadedSystem.cs new file mode 100644 index 00000000000..7d88e042ca2 --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Weapons/Ranged/BreechLoadedSystem.cs @@ -0,0 +1,95 @@ +using Content.Shared._RMC14.Weapons.Common; +using Content.Shared.Examine; +using Content.Shared.Interaction; +using Content.Shared.Popups; +using Content.Shared.Tag; +using Content.Shared.Weapons.Ranged.Components; +using Content.Shared.Weapons.Ranged.Events; +using Content.Shared.Weapons.Ranged.Systems; +using Robust.Shared.Audio.Systems; +using Robust.Shared.GameObjects; + +namespace Content.Shared._RMC14.Weapons.Ranged; + +public sealed class BreechLoadedSystem : EntitySystem +{ + [Dependency] private readonly SharedAppearanceSystem _appearanceSystem = default!; + [Dependency] private readonly SharedAudioSystem _audioSystem = default!; + [Dependency] private readonly SharedGunSystem _gunSystem = default!; + [Dependency] private readonly SharedPopupSystem _popupSystem = default!; + [Dependency] private readonly TagSystem _tagSystem = default!; + + public override void Initialize() + { + SubscribeLocalEvent(OnAttemptShoot); + SubscribeLocalEvent(OnGunShot); + SubscribeLocalEvent(OnTryAmmoEject); + SubscribeLocalEvent(OnUniqueAction); + SubscribeLocalEvent(OnInteractUsing, + before: new[] { typeof(SharedGunSystem) }); + } + + private void OnAttemptShoot(Entity gun, ref AttemptShootEvent args) + { + if (args.Cancelled || !gun.Comp.Open && (!gun.Comp.NeedOpenClose || gun.Comp.Ready)) + return; + + args.Cancelled = true; + if (gun.Comp.Open) + _popupSystem.PopupClient(Loc.GetString("rmc-breech-loaded-open-shoot-attempt"), args.User, args.User); + else + _popupSystem.PopupClient(Loc.GetString("rmc-breech-loaded-not-ready-to-shoot"), args.User, args.User); + } + + private void OnGunShot(Entity gun, ref GunShotEvent args) + { + if (!gun.Comp.NeedOpenClose) + return; + + gun.Comp.Ready = false; + Dirty(gun); + } + + private void OnTryAmmoEject(Entity gun, ref RMCTryAmmoEjectEvent args) + { + if (gun.Comp.Open) + return; + + _popupSystem.PopupClient(Loc.GetString("rmc-breech-loaded-closed-extract-attempt"), args.User, args.User); + args.Cancelled = true; + } + + private void OnUniqueAction(Entity gun, ref UniqueActionEvent args) + { + if (args.Handled) + return; + + args.Handled = true; + + gun.Comp.Open = !gun.Comp.Open; + + if (!gun.Comp.Open) + gun.Comp.Ready = true; + + if (gun.Comp.ShowBreechOpen && TryComp(gun.Owner, out AppearanceComponent? appearanceComponent)) + _appearanceSystem.SetData(gun, BreechVisuals.Open, gun.Comp.Open, appearanceComponent); + + Dirty(gun); + var sound = gun.Comp.Open ? gun.Comp.OpenSound : gun.Comp.CloseSound; + //_audioSystem.PlayPredicted(sound, gun, args.UserUid, sound.Params); + _audioSystem.PlayPredicted(sound, gun, args.UserUid); + } + + private void OnInteractUsing(Entity gun, ref InteractUsingEvent args) + { + if (gun.Comp.Open || + !TryComp(gun.Owner, out BallisticAmmoProviderComponent? ammoProviderComponent) || + ammoProviderComponent.Whitelist == null || + ammoProviderComponent.Whitelist.Tags == null || + !_tagSystem.HasAnyTag(args.Used, ammoProviderComponent.Whitelist.Tags)) + return; + + _popupSystem.PopupClient(Loc.GetString("rmc-breech-loaded-closed-load-attempt"), args.User, args.User); + args.Handled = true; + } +} diff --git a/Content.Shared/ADT/_RMC14/Weapons/Ranged/CMGunSystem.cs b/Content.Shared/ADT/_RMC14/Weapons/Ranged/CMGunSystem.cs new file mode 100644 index 00000000000..5a2b25078c7 --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Weapons/Ranged/CMGunSystem.cs @@ -0,0 +1,180 @@ +using System.Numerics; +using Content.Shared._RMC14.Weapons.Common; +using Content.Shared.Containers.ItemSlots; +using Content.Shared.Hands.EntitySystems; +using Content.Shared.Interaction; +using Content.Shared.Popups; +using Content.Shared.Projectiles; +using Content.Shared.Weapons.Ranged; +using Content.Shared.Weapons.Ranged.Components; +using Content.Shared.Weapons.Ranged.Events; +using Content.Shared.Weapons.Ranged.Systems; +using Robust.Shared.Audio.Systems; +using Robust.Shared.Containers; +using Robust.Shared.Physics.Components; +using Robust.Shared.Physics.Systems; +using Robust.Shared.Random; +using Robust.Shared.Timing; + +namespace Content.Shared._RMC14.Weapons.Ranged; +public sealed class CMGunSystem : EntitySystem +{ + [Dependency] private readonly SharedAudioSystem _audio = default!; + [Dependency] private readonly SharedContainerSystem _container = default!; + [Dependency] private readonly SharedGunSystem _gun = default!; + [Dependency] private readonly ItemSlotsSystem _slots = default!; + [Dependency] private readonly SharedHandsSystem _hands = default!; + [Dependency] private readonly SharedPopupSystem _popup = default!; + [Dependency] private readonly IRobustRandom _random = default!; + [Dependency] private readonly SharedPhysicsSystem _physics = default!; + [Dependency] private readonly SharedTransformSystem _transform = default!; + [Dependency] private readonly IGameTiming _timing = default!; + + private EntityQuery _physicsQuery; + private EntityQuery _projectileQuery; + private bool _isRevolverActionInProgress = false; + public override void Initialize() + { + _physicsQuery = GetEntityQuery(); + _projectileQuery = GetEntityQuery(); + SubscribeLocalEvent(OnShootAtFixedPointShot); + SubscribeLocalEvent(OnRevolverUniqueAction); + SubscribeLocalEvent(OnAmmoEjectActivateInWorld); + } + + private void OnAmmoEjectActivateInWorld(Entity gun, ref ActivateInWorldEvent args) + { + if (args.Handled || + !_container.TryGetContainer(gun.Owner, gun.Comp.ContainerID, out var container) || + container.ContainedEntities.Count <= 0 || + !_hands.TryGetActiveHand(args.User, out var hand) || + !hand.IsEmpty || + !_hands.CanPickupToHand(args.User, container.ContainedEntities[0], hand)) + { + return; + } + + var cancelEvent = new RMCTryAmmoEjectEvent(args.User, false); + RaiseLocalEvent(gun.Owner, ref cancelEvent); + + if (cancelEvent.Cancelled) + return; + + args.Handled = true; + + var ejectedAmmo = container.ContainedEntities[0]; + + // For guns with a BallisticAmmoProviderComponent, if you just remove the ammo from its container, the gun system thinks it's still in the gun and you can still shoot it. + // So instead I'm having to inflict this shit on our codebase. + if (TryComp(gun.Owner, out BallisticAmmoProviderComponent? ammoProviderComponent)) + { + var takeAmmoEvent = new TakeAmmoEvent(1, new List<(EntityUid?, IShootable)>(), Transform(gun.Owner).Coordinates, args.User); + RaiseLocalEvent(gun.Owner, takeAmmoEvent); + + if (takeAmmoEvent.Ammo.Count <= 0) + return; + + var ammo = takeAmmoEvent.Ammo[0].Entity; + + if (ammo == null) + return; + + ejectedAmmo = ammo.Value; + } + + if (!HasComp(gun.Owner) || !_slots.TryEject(gun.Owner, gun.Comp.ContainerID, args.User, out _, excludeUserAudio: true)) + _audio.PlayPredicted(gun.Comp.EjectSound, gun.Owner, args.User); + + _hands.TryPickup(args.User, ejectedAmmo, hand); + } + + private void OnRevolverUniqueAction(Entity gun, ref UniqueActionEvent args) + { + if (args.Handled || _isRevolverActionInProgress) + return; + + _isRevolverActionInProgress = true; + + try + { + int randomCount = _random.Next(1, gun.Comp.Capacity + 1); + + gun.Comp.CurrentIndex = (gun.Comp.CurrentIndex + randomCount) % gun.Comp.Capacity; + + _audio.PlayPredicted(gun.Comp.SoundSpin, gun.Owner, args.UserUid); + var popup = Loc.GetString("rmc-revolver-spin", ("gun", args.UserUid)); + _popup.PopupClient(popup, args.UserUid, args.UserUid, PopupType.SmallCaution); + + Dirty(gun); + } + finally + { + _isRevolverActionInProgress = false; + } + } + + /// + /// Shoot at a targeted point's coordinates. The projectile will stop at that location instead of continuing on until it hits something. + /// There is also an option to arc the projectile with ShootArcProj or ArcProj = true, making it ignore most collision. + /// + /// + /// For some reason, the engine seem to cause MaxFixedRange's conversion to actual projectile max ranges of around +1 tile. + /// As a result, conversions should be 1 less than max_range when porting, and the minimum range for this feature is around 2 tiles. + /// This could be manually tweaked try and fix it, but the math seems like it should be fine and it's predictable enough to be worked around for now. + /// + private void OnShootAtFixedPointShot(Entity ent, ref AmmoShotEvent args) + { + if (!TryComp(ent, out GunComponent? gun) || + gun.ShootCoordinates is not { } target) + { + return; + } + + // Find start and end coordinates for vector. + var from = _transform.GetMapCoordinates(ent); + var to = _transform.ToMapCoordinates(target); + // Must be same map. + if (from.MapId != to.MapId) + return; + + // Calculate vector, cancel if it ends up at 0. + var direction = to.Position - from.Position; + if (direction == Vector2.Zero) + return; + + // Check for a max range from the ShootAtFixedPointComponent. If defined, take the minimum between that and the calculated distance. + var distance = ent.Comp.MaxFixedRange != null ? Math.Min(ent.Comp.MaxFixedRange.Value, direction.Length()) : direction.Length(); + // Get current time and normalize the vector for physics math. + var time = _timing.CurTime; + var normalized = direction.Normalized(); + + // Send each FiredProjectile with a PhysicsComponent off with the same Vector. Max + foreach (var projectile in args.FiredProjectiles) + { + if (!_physicsQuery.TryComp(projectile, out var physics)) + continue; + + // Calculate needed impulse to get to target, remove all velocity from projectile, then apply. + var impulse = normalized * gun.ProjectileSpeedModified * physics.Mass; + _physics.SetLinearVelocity(projectile, Vector2.Zero, body: physics); + _physics.ApplyLinearImpulse(projectile, impulse, body: physics); + _physics.SetBodyStatus(projectile, physics, BodyStatus.InAir); + + // Apply the ProjectileFixedDistanceComponent onto each fired projectile, which both holds the FlyEndTime to be continually checked + // and will trigger the OnEventToStopProjectile function once the PFD Component is deleted at that time. See Update() + var comp = EnsureComp(projectile); + + // Transfer arcing to the projectile. + if (Comp(ent).ShootArcProj) + comp.ArcProj = true; + + // Take the lowest nonzero MaxFixedRange between projectile and gun for the capped vector length. + if (TryComp(projectile, out ProjectileComponent? normalProjectile) && normalProjectile.MaxFixedRange > 0) + { + distance = distance > 0 ? Math.Min(normalProjectile.MaxFixedRange.Value, distance) : normalProjectile.MaxFixedRange.Value; + } + // Calculate travel time and equivalent distance based either on click location or calculated max range, whichever is shorter. + comp.FlyEndTime = time + TimeSpan.FromSeconds(distance / gun.ProjectileSpeedModified); + } + } +} diff --git a/Content.Shared/ADT/_RMC14/Weapons/Ranged/GetDamageFalloffEvent.cs b/Content.Shared/ADT/_RMC14/Weapons/Ranged/GetDamageFalloffEvent.cs new file mode 100644 index 00000000000..ab26799cc93 --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Weapons/Ranged/GetDamageFalloffEvent.cs @@ -0,0 +1,8 @@ +using Content.Shared.FixedPoint; + +namespace Content.Shared._RMC14.Weapons.Ranged; + +[ByRefEvent] +public record struct GetDamageFalloffEvent( + FixedPoint2 FalloffMultiplier +); diff --git a/Content.Shared/ADT/_RMC14/Weapons/Ranged/GetFireModeValuesEvent.cs b/Content.Shared/ADT/_RMC14/Weapons/Ranged/GetFireModeValuesEvent.cs new file mode 100644 index 00000000000..433472abed5 --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Weapons/Ranged/GetFireModeValuesEvent.cs @@ -0,0 +1,5 @@ + +namespace Content.Shared._RMC14.Weapons.Ranged; + +[ByRefEvent] +public record struct GetFireModeValuesEvent(double BurstScatterMult); diff --git a/Content.Shared/ADT/_RMC14/Weapons/Ranged/GetFireModesEvent.cs b/Content.Shared/ADT/_RMC14/Weapons/Ranged/GetFireModesEvent.cs new file mode 100644 index 00000000000..5b75428729e --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Weapons/Ranged/GetFireModesEvent.cs @@ -0,0 +1,6 @@ +using Content.Shared.Weapons.Ranged.Components; + +namespace Content.Shared._RMC14.Weapons.Ranged; + +[ByRefEvent] +public record struct GetFireModesEvent(SelectiveFire Modes, SelectiveFire Set = SelectiveFire.Invalid); diff --git a/Content.Shared/ADT/_RMC14/Weapons/Ranged/GetGunDamageModifierEvent.cs b/Content.Shared/ADT/_RMC14/Weapons/Ranged/GetGunDamageModifierEvent.cs new file mode 100644 index 00000000000..37c8d401259 --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Weapons/Ranged/GetGunDamageModifierEvent.cs @@ -0,0 +1,6 @@ +using Content.Shared.FixedPoint; + +namespace Content.Shared._RMC14.Weapons.Ranged; + +[ByRefEvent] +public record struct GetGunDamageModifierEvent(FixedPoint2 Multiplier); diff --git a/Content.Shared/ADT/_RMC14/Weapons/Ranged/GunGetFireRateEvent.cs b/Content.Shared/ADT/_RMC14/Weapons/Ranged/GunGetFireRateEvent.cs new file mode 100644 index 00000000000..84767763441 --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Weapons/Ranged/GunGetFireRateEvent.cs @@ -0,0 +1,5 @@ +namespace Content.Shared._RMC14.Weapons.Ranged; + + +[ByRefEvent] +public record struct GunGetFireRateEvent(float FireRate); diff --git a/Content.Shared/ADT/_RMC14/Weapons/Ranged/ProjectileFixedDistanceComponent.cs b/Content.Shared/ADT/_RMC14/Weapons/Ranged/ProjectileFixedDistanceComponent.cs new file mode 100644 index 00000000000..b768b771ec1 --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Weapons/Ranged/ProjectileFixedDistanceComponent.cs @@ -0,0 +1,21 @@ +using Robust.Shared.GameStates; + +namespace Content.Shared._RMC14.Weapons.Ranged; + +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +[Access(typeof(CMGunSystem))] +public sealed partial class ProjectileFixedDistanceComponent : Component +{ + /// + /// Used when firing a FixedDistance to time effectively limit the range. + /// This component removes itself when CurTime = FlyEndTime to trigger that Event. + /// + [DataField, AutoNetworkedField] + public TimeSpan FlyEndTime; + /// + /// If true, the entity containing this component will ignore most collisions except for Impassable fixture layers. + /// This is granted to a fired entity by the ShootAtFixedPointComponent based on its ShootArcProj boolean. + /// + [DataField, AutoNetworkedField] + public bool ArcProj = false; +} diff --git a/Content.Shared/ADT/_RMC14/Weapons/Ranged/ProjectileFixedDistanceStopEvent.cs b/Content.Shared/ADT/_RMC14/Weapons/Ranged/ProjectileFixedDistanceStopEvent.cs new file mode 100644 index 00000000000..93f93b3c54a --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Weapons/Ranged/ProjectileFixedDistanceStopEvent.cs @@ -0,0 +1,4 @@ +namespace Content.Shared._RMC14.Weapons.Ranged; + +[ByRefEvent] +public readonly record struct ProjectileFixedDistanceStopEvent; diff --git a/Content.Shared/ADT/_RMC14/Weapons/Ranged/PumpActionComponent.cs b/Content.Shared/ADT/_RMC14/Weapons/Ranged/PumpActionComponent.cs new file mode 100644 index 00000000000..b4e7476c7e0 --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Weapons/Ranged/PumpActionComponent.cs @@ -0,0 +1,30 @@ +using Robust.Shared.Audio; +using Robust.Shared.GameStates; + +namespace Content.Shared._RMC14.Weapons.Ranged; + +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +[Access(typeof(SharedPumpActionSystem))] +public sealed partial class PumpActionComponent : Component +{ + [DataField, AutoNetworkedField] + public bool Pumped; + + [DataField, AutoNetworkedField] + public SoundSpecifier? Sound = new SoundPathSpecifier("/Audio/Corvax/Weapons/Guns/Cock/shotgun_cock.ogg"); + + [DataField, AutoNetworkedField] + public LocId Examine = "cm-gun-pump-examine"; + + [DataField, AutoNetworkedField] + public LocId Popup = "cm-gun-pump-first"; + + [DataField, AutoNetworkedField] + public LocId PopupKey = "cm-gun-pump-first-with"; + + [DataField, AutoNetworkedField] + public bool Once; + + [DataField, AutoNetworkedField] + public string ContainerId = "gun_magazine"; +} diff --git a/Content.Shared/ADT/_RMC14/Weapons/Ranged/RMCAmmoEjectComponent.cs b/Content.Shared/ADT/_RMC14/Weapons/Ranged/RMCAmmoEjectComponent.cs new file mode 100644 index 00000000000..e4837ff9fb7 --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Weapons/Ranged/RMCAmmoEjectComponent.cs @@ -0,0 +1,23 @@ +using Robust.Shared.Audio; +using Robust.Shared.GameStates; + +namespace Content.Shared._RMC14.Weapons.Ranged; + +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +[Access(typeof(CMGunSystem))] +public sealed partial class RMCAmmoEjectComponent : Component +{ + /// + /// The ID of the container from which ammo should be ejected. + /// + [DataField, AutoNetworkedField] + public string ContainerID = "gun_magazine"; + + /// + /// This is the sound that will play if the container ID does not match an item slot on the weapon. + /// Otherwise, the item slot's eject sound will play instead. + /// This field is mainly for weapons that use BallisticAmmoProviderComponent to store their ammo, like grenade launchers and pump-action shotguns. + /// + [DataField, AutoNetworkedField] + public SoundSpecifier EjectSound = new SoundPathSpecifier("/Audio/Items/beep.ogg", AudioParams.Default.WithVolume(-2f)); +} diff --git a/Content.Shared/ADT/_RMC14/Weapons/Ranged/RMCFireGroupComponent.cs b/Content.Shared/ADT/_RMC14/Weapons/Ranged/RMCFireGroupComponent.cs new file mode 100644 index 00000000000..42c54a0d0d3 --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Weapons/Ranged/RMCFireGroupComponent.cs @@ -0,0 +1,30 @@ +using Robust.Shared.Audio; +using Robust.Shared.GameStates; + +namespace Content.Shared._RMC14.Weapons.Ranged; + +/// +/// Fire group component which prevents things like shotgun juggling. +/// +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +[Access(typeof(SharedFireGroupSystem))] +public sealed partial class RMCFireGroupComponent : Component +{ + /// + /// The fire group of the item + /// + [DataField, AutoNetworkedField] + public string Group = string.Empty; + + /// + /// How long the other gun(s) are delayed for + /// + [DataField, AutoNetworkedField] + public TimeSpan Delay = TimeSpan.FromSeconds(1); + + /// + /// The UseDelay ID + /// + [DataField, AutoNetworkedField] + public string UseDelayID = "RMCFireGroupDelay"; +} \ No newline at end of file diff --git a/Content.Shared/ADT/_RMC14/Weapons/Ranged/RMCFireModeChangedEvent.cs b/Content.Shared/ADT/_RMC14/Weapons/Ranged/RMCFireModeChangedEvent.cs new file mode 100644 index 00000000000..22642ae3988 --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Weapons/Ranged/RMCFireModeChangedEvent.cs @@ -0,0 +1,6 @@ +using Content.Shared.Weapons.Ranged.Components; + +namespace Content.Shared._RMC14.Weapons.Ranged; + +[ByRefEvent] +public record struct RMCFireModeChangedEvent; diff --git a/Content.Shared/ADT/_RMC14/Weapons/Ranged/RMCSelectiveFireComponent.cs b/Content.Shared/ADT/_RMC14/Weapons/Ranged/RMCSelectiveFireComponent.cs new file mode 100644 index 00000000000..fe153c6739c --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Weapons/Ranged/RMCSelectiveFireComponent.cs @@ -0,0 +1,130 @@ +using Content.Shared.Weapons.Ranged.Components; +using Robust.Shared.GameStates; +using Robust.Shared.Serialization; + +namespace Content.Shared._RMC14.Weapons.Ranged; + +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +[Access(typeof(RMCSelectiveFireSystem))] +public sealed partial class RMCSelectiveFireComponent : Component +{ + /// + /// The base fire modes available to the weapon. This will override what's set in the weapon's GunComponent. + /// + [DataField, AutoNetworkedField] + public SelectiveFire BaseFireModes = SelectiveFire.SemiAuto; + + /// + /// The base recoil when the weapon is wielded. + /// + [DataField, AutoNetworkedField] + public float RecoilWielded = 1f; + + /// + /// The base recoil when the weapon is not wielded. + /// + [DataField, AutoNetworkedField] + public float RecoilUnwielded = 1f; + + /// + /// Equivalent to GunComponent.AngleIncrease. + /// This exists to properly reset the angle increase after switching firemodes. + /// This generally should not be changed. Instead, use ShotsToMaxScatter in the relevant firemode's entry in Modifiers. + /// + [DataField, AutoNetworkedField] + public Angle ScatterIncrease = Angle.FromDegrees(0.0); + + /// + /// Equivalent to GunComponent.AngleDecay. + /// This should not be changed. RMC guns reset their scatter to the minimum instantly after shooting. + /// This is here to make sure the scatter decay doesn't get overriden by something someone sets in the weapon's GunComponent. + /// + [DataField, AutoNetworkedField] + public Angle ScatterDecay = Angle.FromDegrees(0.0); + + /// + /// Equivalent to GunComponent.MinAngle and GunComponent.MaxAngle + /// This is the base scatter value for a wielded weapon. + /// Scatter is the angle of the cone within which your shots deviate from where your cursor is. + /// Conversion from 13 guns: scatter * 2 + /// + [DataField, AutoNetworkedField] + public Angle ScatterWielded = Angle.FromDegrees(10.0); + + /// + /// Equivalent to GunComponent.MinAngle and GunComponent.MaxAngle + /// This is the base scatter value for an unwielded weapon. + /// Scatter is the angle of the cone within which your shots deviate from where your cursor is. + /// Conversion from 13 guns: scatter_unwielded * 2 + /// + [DataField, AutoNetworkedField] + public Angle ScatterUnwielded = Angle.FromDegrees(10.0); + + /// + /// Equivalent to GunComponent.FireRate. + /// This is how many shots a weapon fires per second. + /// Conversion from 13 guns: 1 / (fire_delay / 10) + /// + [DataField, AutoNetworkedField] + public float BaseFireRate = 1.429f; + + /// + /// This is the multiplier applied to the additional scatter added by a SelectiveFireModifierSet with UseBurstScatterMult set to true. + /// Conversion from 13 guns: burst_scatter_mult + /// + [DataField, AutoNetworkedField] + public double BurstScatterMult = 4.0; + + /// + /// This is the modified burst scatter multiplier. This should not be set manually, it's handled by RMCSelectiveFireSystem. + /// + [DataField, AutoNetworkedField] + public double BurstScatterMultModified = 4.0; + + /// + /// This dictionary contains the modifiers used for different firemodes. + /// If a firemode isn't in here, it doesn't get any of the modifiers applied to it and will not have variable scatter. + /// + [DataField, AutoNetworkedField] + public Dictionary Modifiers = new() + { + { SelectiveFire.Burst, new SelectiveFireModifierSet(0.1f, 10.0, true, 2.0, 6) }, + { SelectiveFire.FullAuto, new SelectiveFireModifierSet(0f, 26.0, true, 2.0, 4) } + }; +} + +[DataRecord, Serializable, NetSerializable] +public record struct SelectiveFireModifierSet( + /// + /// Additional fire delay applied to the weapon when this mode is active. + /// A weapon's fire delay is the delay in seconds between each shot. It's inversely proportionate to the weapon's rate of fire. + /// Conversion from rate of fire: 1 / FireRate + /// Conversion from 13 guns for burst fire: burst_delay / 10 * 0.666. Due to how burst delay is handled in 13, we need the 0.666. + /// + float FireDelay, + + /// + /// A flat modifier applied to the weapon's maximum scatter. + /// This is multiplied by UnwieldedScatterMultiplier if the weapon is not wielded and by BurstScatterMultModified if UseBurstScatterMult is true. + /// This modifier will never reduce the weapon's scatter — only increase it or keep it the same — even if made negative by its multipliers. + /// Conversion from 13 guns for burst fire: 10 + /// Conversion from 13 guns for fully-automatic fire: fa_max_scatter * 2 + /// + double MaxScatterModifier, + + /// + /// If this is set to true, the additional scatter added by this modifier set will be multiplied by BurstScatterMultModified. + /// + bool UseBurstScatterMult, + + /// + /// The additional scatter added by this modifier set will be multiplied by this value if the weapon is not wielded. + /// + double UnwieldedScatterMultiplier, + + /// + /// This determines how many shots it takes to reach maximum scatter. + /// If it's set to null, the weapon will not accumulate scatter when firing. + /// + int? ShotsToMaxScatter +); diff --git a/Content.Shared/ADT/_RMC14/Weapons/Ranged/RMCSelectiveFireSystem.cs b/Content.Shared/ADT/_RMC14/Weapons/Ranged/RMCSelectiveFireSystem.cs new file mode 100644 index 00000000000..74129a495e0 --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Weapons/Ranged/RMCSelectiveFireSystem.cs @@ -0,0 +1,231 @@ +using Content.Shared._RMC14.Attachable.Systems; +using Content.Shared._RMC14.Input; +using Content.Shared.Examine; +using Content.Shared.Weapons.Ranged.Components; +using Content.Shared.Weapons.Ranged.Events; +using Content.Shared.Weapons.Ranged.Systems; +using Content.Shared.Wieldable; +using Content.Shared.Wieldable.Components; +using Robust.Shared.Input.Binding; + +namespace Content.Shared._RMC14.Weapons.Ranged; + +public sealed class RMCSelectiveFireSystem : EntitySystem +{ + [Dependency] private readonly SharedGunSystem _gunSystem = default!; + + private const string scatterExamineColour = "yellow"; + + private const SelectiveFire allFireModes = SelectiveFire.SemiAuto | SelectiveFire.Burst | SelectiveFire.FullAuto; + + public override void Initialize() + { + SubscribeAllEvent(OnStopShootRequest); + + SubscribeLocalEvent(OnExamine); + SubscribeLocalEvent(SelectiveFireRefreshWield, + after: new[] { typeof(AttachableHolderSystem) }); + SubscribeLocalEvent(SelectiveFireRefreshWield, + after: new[] { typeof(AttachableHolderSystem) }); + SubscribeLocalEvent(OnSelectiveFireMapInit); + SubscribeLocalEvent(OnSelectiveFireModeChanged); + + CommandBinds.Builder + .Bind(CMKeyFunctions.RMCCycleFireMode, + InputCmdHandler.FromDelegate(session => + { + if (session?.AttachedEntity is { } userUid && _gunSystem.TryGetGun(userUid, out var gunUid, out var gunComponent)) + { + _gunSystem.CycleFire(gunUid, gunComponent, userUid); + } + }, + handle: false)) + .Register(); + } + + private void OnStopShootRequest(RequestStopShootEvent ev, EntitySessionEventArgs args) + { + var gunUid = GetEntity(ev.Gun); + + if (args.SenderSession.AttachedEntity == null || + !TryComp(gunUid, out GunComponent? gunComponent) || + !_gunSystem.TryGetGun(args.SenderSession.AttachedEntity.Value, out _, out var userGun)) + { + return; + } + + if (userGun != gunComponent) + return; + + gunComponent.CurrentAngle = gunComponent.MinAngleModified; + Dirty(gunUid, gunComponent); + } + + private void OnExamine(Entity gun, ref ExaminedEvent args) + { + if (!args.IsInDetailsRange || !TryComp(gun.Owner, out GunComponent? gunComponent)) + return; + + using (args.PushGroup(nameof(RMCSelectiveFireComponent))) + { + args.PushMarkup(Loc.GetString("rmc-examine-text-scatter-max", ("colour", scatterExamineColour), ("scatter", gunComponent.MaxAngleModified.Degrees))); + args.PushMarkup(Loc.GetString("rmc-examine-text-scatter-min", ("colour", scatterExamineColour), ("scatter", gunComponent.MinAngleModified.Degrees))); + + if (ContainsMods(gun, gunComponent.SelectedMode)) + { + var mods = gun.Comp.Modifiers[gunComponent.SelectedMode]; + if (mods.ShotsToMaxScatter != null) + args.PushMarkup(Loc.GetString("rmc-examine-text-shots-to-max-scatter", ("colour", scatterExamineColour), ("shots", mods.ShotsToMaxScatter))); + } + } + } + +#region Refresh calls + private void OnSelectiveFireMapInit(Entity gun, ref MapInitEvent args) + { + gun.Comp.BurstScatterMultModified = gun.Comp.BurstScatterMult; + RefreshFireModes((gun.Owner, gun.Comp), true); + } + + private void OnSelectiveFireModeChanged(Entity gun, ref RMCFireModeChangedEvent args) + { + RefreshFireModeGunValues(gun); + } + + private void SelectiveFireRefreshWield(Entity gun, ref T args) where T : notnull + { + RefreshWieldableFireModeValues(gun); + } +#endregion + +#region Refresh methods + public void RefreshFireModeGunValues(Entity gun) + { + if (!TryComp(gun.Owner, out GunComponent? gunComponent)) + return; + + gunComponent.AngleIncrease = gun.Comp.ScatterIncrease; + gunComponent.AngleDecay = gun.Comp.ScatterDecay; + + var ev = new GunGetFireRateEvent(gunComponent.SelectedMode == SelectiveFire.Burst ? gun.Comp.BaseFireRate * 2 : gun.Comp.BaseFireRate); + RaiseLocalEvent(gun, ref ev); + gunComponent.FireRate = ev.FireRate; + + if (ContainsMods(gun, gunComponent.SelectedMode)) + { + var mods = gun.Comp.Modifiers[gunComponent.SelectedMode]; + ev = new GunGetFireRateEvent(1f / (1f / gunComponent.FireRate + mods.FireDelay)); + RaiseLocalEvent(gun, ref ev); + gunComponent.FireRate = ev.FireRate; + } + + RefreshWieldableFireModeValues(gun); + } + + public bool ContainsMods(Entity gun, SelectiveFire mode) + { + return gun.Comp.Modifiers.ContainsKey(mode); + } + + public void RefreshWieldableFireModeValues(Entity gun) + { + if (!TryComp(gun.Owner, out GunComponent? gunComponent)) + return; + + bool wielded = TryComp(gun.Owner, out WieldableComponent? wieldableComponent) && wieldableComponent.Wielded; + + gunComponent.CameraRecoilScalar = wielded ? gun.Comp.RecoilWielded : gun.Comp.RecoilUnwielded; + gunComponent.MinAngle = wielded ? gun.Comp.ScatterWielded : gun.Comp.ScatterUnwielded; + gunComponent.MaxAngle = gunComponent.MinAngle; + + RefreshBurstScatter((gun.Owner, gun.Comp)); + + _gunSystem.RefreshModifiers(gun.Owner); + gunComponent.CurrentAngle = gunComponent.MinAngleModified; + } + + public void RefreshFireModes(Entity gun, bool forceValueRefresh = false) + { + if (gun.Comp == null && !TryComp(gun.Owner, out gun.Comp) || !TryComp(gun.Owner, out GunComponent? gunComponent)) + return; + + var initialMode = gunComponent.SelectedMode; + + var ev = new GetFireModesEvent(gun.Comp.BaseFireModes); + RaiseLocalEvent(gun.Owner, ref ev); + + SetFireModes((gun.Owner, gunComponent), ev.Modes, !(forceValueRefresh || initialMode != gunComponent.SelectedMode)); + + if (TryComp(gun, out GunComponent? gunComp) && + (gunComp.AvailableModes & ev.Set) != SelectiveFire.Invalid) + { + _gunSystem.SelectFire(gun, gunComponent, ev.Set); + } + + if (forceValueRefresh || initialMode != gunComponent.SelectedMode) + RefreshFireModeGunValues((gun.Owner, gun.Comp)); + } + + public void RefreshModifiableFireModeValues(Entity gun) + { + if (gun.Comp == null && !TryComp(gun.Owner, out gun.Comp)) + return; + + var ev = new GetFireModeValuesEvent(gun.Comp.BurstScatterMult); + RaiseLocalEvent(gun.Owner, ref ev); + + gun.Comp.BurstScatterMultModified = ev.BurstScatterMult; + + RefreshWieldableFireModeValues((gun.Owner, gun.Comp)); + } + + private void RefreshBurstScatter(Entity gun) + { + if (!TryComp(gun.Owner, out GunComponent? gunComponent)) + return; + + bool wielded = TryComp(gun.Owner, out WieldableComponent? wieldableComponent) && wieldableComponent.Wielded; + + if (ContainsMods(gun, gunComponent.SelectedMode)) + { + var mods = gun.Comp.Modifiers[gunComponent.SelectedMode]; + var mult = mods.UseBurstScatterMult ? gun.Comp.BurstScatterMultModified : 1.0; + gunComponent.MaxAngle = wielded + ? Angle.FromDegrees(Math.Max(gunComponent.MinAngle.Degrees + mods.MaxScatterModifier * mult, gunComponent.MinAngle.Degrees)) + : Angle.FromDegrees(Math.Max(gunComponent.MinAngle.Degrees + mods.MaxScatterModifier * mult * mods.UnwieldedScatterMultiplier, gunComponent.MinAngle.Degrees)); + + if (mods.ShotsToMaxScatter != null) + gunComponent.AngleIncrease = new Angle(((double)(gunComponent.MaxAngle - gunComponent.MinAngle)) / mods.ShotsToMaxScatter.Value); + } + } +#endregion + +#region Firemode changes + public void AddFireMode(Entity gun, SelectiveFire newMode) + { + if (gun.Comp == null && !TryComp(gun.Owner, out gun.Comp)) + return; + + gun.Comp.AvailableModes |= newMode; + Dirty(gun); + } + + public void SetFireModes(Entity gun, SelectiveFire modes, bool dirty = true) + { + if (gun.Comp == null && !TryComp(gun.Owner, out gun.Comp) || (modes & allFireModes) == SelectiveFire.Invalid) + return; + + gun.Comp.AvailableModes = allFireModes; + + while ((gun.Comp.SelectedMode & modes) != gun.Comp.SelectedMode) + _gunSystem.CycleFire(gun.Owner, gun.Comp); + + gun.Comp.AvailableModes = modes; + + if (!dirty) + return; + + Dirty(gun); + } +#endregion +} diff --git a/Content.Shared/ADT/_RMC14/Weapons/Ranged/RMCTryAmmoEjectEvent.cs b/Content.Shared/ADT/_RMC14/Weapons/Ranged/RMCTryAmmoEjectEvent.cs new file mode 100644 index 00000000000..82d66ace88e --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Weapons/Ranged/RMCTryAmmoEjectEvent.cs @@ -0,0 +1,8 @@ + +namespace Content.Shared._RMC14.Weapons.Ranged; + +[ByRefEvent] +public record struct RMCTryAmmoEjectEvent( + EntityUid User, + bool Cancelled +); diff --git a/Content.Shared/ADT/_RMC14/Weapons/Ranged/SharedFireGroupSystem.cs b/Content.Shared/ADT/_RMC14/Weapons/Ranged/SharedFireGroupSystem.cs new file mode 100644 index 00000000000..41835613805 --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Weapons/Ranged/SharedFireGroupSystem.cs @@ -0,0 +1,55 @@ +using Content.Shared.Hands.EntitySystems; +using Content.Shared.Timing; +using Content.Shared.Weapons.Ranged.Events; +using Content.Shared.Weapons.Ranged.Systems; + +namespace Content.Shared._RMC14.Weapons.Ranged; + +public sealed class SharedFireGroupSystem : EntitySystem +{ + [Dependency] private readonly UseDelaySystem _delay = default!; + [Dependency] private readonly SharedHandsSystem _hands = default!; + + public override void Initialize() + { + SubscribeLocalEvent(OnGunShot); + SubscribeLocalEvent(OnShotAttempt); + } + + private void OnGunShot(Entity ent, ref GunShotEvent args) + { + var weapon = ent.Owner; + var comp = ent.Comp; + var user = args.User; + + foreach (var item in _hands.EnumerateHeld(user)) + { + if (TryComp(item, out var fireGroup)) + { + if (item == weapon) + continue; + + if (fireGroup.Group != comp.Group) + continue; + + if (!TryComp(item, out UseDelayComponent? useDelay)) + continue; + + var itemEnt = (item, useDelay); + _delay.SetLength(itemEnt, comp.Delay, comp.UseDelayID); + _delay.TryResetDelay(itemEnt, true, id: comp.UseDelayID); + } + } + } + + public void OnShotAttempt(Entity ent, ref ShotAttemptedEvent args) + { + if (!TryComp(ent.Owner, out UseDelayComponent? useDelayComponent) || + !_delay.IsDelayed((ent.Owner, useDelayComponent), ent.Comp.UseDelayID)) + { + return; + } + + args.Cancel(); + } +} \ No newline at end of file diff --git a/Content.Shared/ADT/_RMC14/Weapons/Ranged/SharedPumpActionSystem.cs b/Content.Shared/ADT/_RMC14/Weapons/Ranged/SharedPumpActionSystem.cs new file mode 100644 index 00000000000..718b33ccca8 --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Weapons/Ranged/SharedPumpActionSystem.cs @@ -0,0 +1,79 @@ +using Content.Shared._RMC14.Weapons.Common; +using Content.Shared.Examine; +using Content.Shared.Popups; +using Content.Shared.Weapons.Ranged.Events; +using Content.Shared.Weapons.Ranged.Systems; +using Robust.Shared.Audio.Systems; +using Robust.Shared.Containers; + +namespace Content.Shared._RMC14.Weapons.Ranged; + +public abstract class SharedPumpActionSystem : EntitySystem +{ + [Dependency] private readonly SharedAudioSystem _audio = default!; + [Dependency] private readonly SharedPopupSystem _popup = default!; + + public override void Initialize() + { + SubscribeLocalEvent(OnExamined, before: [typeof(SharedGunSystem)]); + SubscribeLocalEvent(OnAttemptShoot); + SubscribeLocalEvent(OnGunShot); + SubscribeLocalEvent(OnUniqueAction); + SubscribeLocalEvent(OnEntRemovedFromContainer); + } + + protected virtual void OnExamined(Entity ent, ref ExaminedEvent args) + { + // TODO RMC14 the server has no idea what this keybind is supposed to be for the client + args.PushMarkup(Loc.GetString(ent.Comp.Examine), 1); + } + + protected virtual void OnAttemptShoot(Entity ent, ref AttemptShootEvent args) + { + if (!ent.Comp.Pumped) + args.Cancelled = true; + } + + private void OnGunShot(Entity ent, ref GunShotEvent args) + { + if (ent.Comp.Once) + return; + + ent.Comp.Pumped = false; + Dirty(ent); + } + + private void OnUniqueAction(Entity ent, ref UniqueActionEvent args) + { + if (args.Handled) + return; + + var ammo = new GetAmmoCountEvent(); + RaiseLocalEvent(ent.Owner, ref ammo); + + if (ammo.Count <= 0) + { + _popup.PopupClient(Loc.GetString("cm-gun-no-ammo-message"), args.UserUid, args.UserUid); + args.Handled = true; + return; + } + + if (!ent.Comp.Running || ent.Comp.Pumped) + return; + + ent.Comp.Pumped = true; + Dirty(ent); + + args.Handled = true; + + _audio.PlayPredicted(ent.Comp.Sound, ent, args.UserUid); + } + + private void OnEntRemovedFromContainer(Entity ent, ref EntRemovedFromContainerMessage args) + { + if (args.Container.ID != ent.Comp.ContainerId || !ent.Comp.Once) + return; + + ent.Comp.Pumped = false; + } +} diff --git a/Content.Shared/ADT/_RMC14/Weapons/Ranged/ShootAtFixedPointComponent.cs b/Content.Shared/ADT/_RMC14/Weapons/Ranged/ShootAtFixedPointComponent.cs new file mode 100644 index 00000000000..14267cb6be0 --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Weapons/Ranged/ShootAtFixedPointComponent.cs @@ -0,0 +1,23 @@ +using Robust.Shared.GameStates; + +namespace Content.Shared._RMC14.Weapons.Ranged; + +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +[Access(typeof(CMGunSystem))] +public sealed partial class ShootAtFixedPointComponent : Component // TODO: Make it so weapons with this component can have arc fire disabled. +{ + /// + /// Sets the maximum range for a projectile fired with ShootAtFixedPointComponent. + /// This can be set on both the Projectile and ShootAtFixedPoint Components. + /// The default value is null for no cap. The minimum value between the two is used. + /// + [DataField, AutoNetworkedField] + public float? MaxFixedRange; + + /// + /// Should projectiles launched by a gun with this component be fired in an 'arc'? + /// If true, they will ignore most collisions except for Impassable fixture layers. + /// + [DataField, AutoNetworkedField] + public bool ShootArcProj = false; +} \ No newline at end of file diff --git a/Content.Shared/ADT/_RMC14/Weapons/Ranged/ShootUseDelayComponent.cs b/Content.Shared/ADT/_RMC14/Weapons/Ranged/ShootUseDelayComponent.cs new file mode 100644 index 00000000000..adcced44242 --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Weapons/Ranged/ShootUseDelayComponent.cs @@ -0,0 +1,6 @@ +using Robust.Shared.GameStates; + +namespace Content.Shared._RMC14.Weapons.Ranged; + +[RegisterComponent, NetworkedComponent] +public sealed partial class ShootUseDelayComponent : Component; diff --git a/Content.Shared/ADT/_RMC14/Weapons/Ranged/ShootUseDelaySystem.cs b/Content.Shared/ADT/_RMC14/Weapons/Ranged/ShootUseDelaySystem.cs new file mode 100644 index 00000000000..41d20abb757 --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Weapons/Ranged/ShootUseDelaySystem.cs @@ -0,0 +1,27 @@ +using Content.Shared.Timing; +using Content.Shared.Weapons.Ranged.Components; +using Content.Shared.Weapons.Ranged.Events; +using Content.Shared.Weapons.Ranged.Systems; + +namespace Content.Shared._RMC14.Weapons.Ranged; + +public sealed class ShootUseDelaySystem : EntitySystem +{ + [Dependency] private readonly UseDelaySystem _useDelay = default!; + + private const string shootUseDelayId = "CMShootUseDelay"; + + public override void Initialize() + { + SubscribeLocalEvent(OnGunShot); + } + + private void OnGunShot(Entity ent, ref GunShotEvent args) + { + if (!TryComp(ent, out UseDelayComponent? delayComponent) || !TryComp(ent, out GunComponent? gunComponent)) + return; + + _useDelay.SetLength((ent.Owner, delayComponent), TimeSpan.FromSeconds(1f / gunComponent.FireRate), shootUseDelayId); + _useDelay.TryResetDelay((ent.Owner, delayComponent), true, id: shootUseDelayId); + } +} diff --git a/Content.Shared/ADT/_RMC14/Wieldable/Components/WieldDelayComponent.cs b/Content.Shared/ADT/_RMC14/Wieldable/Components/WieldDelayComponent.cs new file mode 100644 index 00000000000..53ce8febf5c --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Wieldable/Components/WieldDelayComponent.cs @@ -0,0 +1,18 @@ +using Robust.Shared.GameStates; + +namespace Content.Shared._RMC14.Wieldable.Components; + +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +[Access(typeof(RMCWieldableSystem))] +public sealed partial class WieldDelayComponent : Component +{ + /// + /// The base delay which is then modified by attachments. + /// Conversion from 13: SS13_WIELD_DELAY / 10 + /// + [DataField, AutoNetworkedField] + public TimeSpan BaseDelay = TimeSpan.FromSeconds(0.4); + + [DataField, AutoNetworkedField] + public TimeSpan ModifiedDelay = TimeSpan.FromSeconds(0.4); +} diff --git a/Content.Shared/ADT/_RMC14/Wieldable/Components/WieldSlowdownCompensationComponent.cs b/Content.Shared/ADT/_RMC14/Wieldable/Components/WieldSlowdownCompensationComponent.cs new file mode 100644 index 00000000000..ef09741d814 --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Wieldable/Components/WieldSlowdownCompensationComponent.cs @@ -0,0 +1,26 @@ +using Robust.Shared.GameStates; + +namespace Content.Shared._RMC14.Wieldable; + +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +[Access(typeof(RMCWieldableSystem))] +public sealed partial class WieldSlowdownCompensationComponent : Component +{ + // The generic conversion formula from move delay to additive speed multiplier is as follows: 1 / (1 / SS14_SPEED + SS13_MOVE_DELAY / 10) / SS14_SPEED - 1 + // The formulae below already have the default human speeds inserted. Use them when converting from SS13. + /// + /// This is the amount by which the additive speed multiplier from wielded items is changed. This one applies to walking speed. + /// Converting to an additive multiplier from SS13 move delay: 1 / (0.4 + SS13_MOVE_DELAY / 10) / 2.5 - 1 + /// Since this is supposed to increase speed, take the negative of the result. + /// + [DataField, AutoNetworkedField] + public float Walk = 0f; + + /// + /// This is the amount by which the additive speed multiplier from wielded items is changed. This one applies to sprinting speed. + /// Converting to an additive multiplier from SS13 move delay: 1 / (0.22 + SS13_MOVE_DELAY / 10) / 4.5 - 1 + /// Since this is supposed to increase speed, take the negative of the result. + /// + [DataField, AutoNetworkedField] + public float Sprint = 0f; +} diff --git a/Content.Shared/ADT/_RMC14/Wieldable/Components/WieldSlowdownCompensationUserComponent.cs b/Content.Shared/ADT/_RMC14/Wieldable/Components/WieldSlowdownCompensationUserComponent.cs new file mode 100644 index 00000000000..179d69e3ca2 --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Wieldable/Components/WieldSlowdownCompensationUserComponent.cs @@ -0,0 +1,14 @@ +using Robust.Shared.GameStates; + +namespace Content.Shared._RMC14.Wieldable; + +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +[Access(typeof(RMCWieldableSystem))] +public sealed partial class WieldSlowdownCompensationUserComponent : Component +{ + [DataField, AutoNetworkedField] + public float Walk = 0f; + + [DataField, AutoNetworkedField] + public float Sprint = 0f; +} diff --git a/Content.Shared/ADT/_RMC14/Wieldable/Components/WieldableSpeedModifiersComponent.cs b/Content.Shared/ADT/_RMC14/Wieldable/Components/WieldableSpeedModifiersComponent.cs new file mode 100644 index 00000000000..e1dcf6842e4 --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Wieldable/Components/WieldableSpeedModifiersComponent.cs @@ -0,0 +1,30 @@ +using Robust.Shared.GameStates; + +namespace Content.Shared._RMC14.Wieldable.Components; + +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +[Access(typeof(RMCWieldableSystem))] +public sealed partial class WieldableSpeedModifiersComponent : Component +{ + // Generic formula: 1 / (1 / SS14_MOVE_SPEED + SS13_MOVE_DELAY / 10) / SS14_MOVE_SPEED + // Since dynamically calculating this isn't practical with how changing movespeed works, the formulae below have the default movement speeds already inserted. + /// + /// The base multiplier, which is then altered by attachments and armour movement compensation. + /// Formula for conversion from 13: 1 / (0.4 + SS13_MOVE_DELAY / 10) / 2.5 + /// + [DataField, AutoNetworkedField] + public float BaseWalk = 1f; + + [DataField, AutoNetworkedField] + public float ModifiedWalk = 1f; + + /// + /// The base multiplier, which is then altered by attachments and armour movement compensation. + /// Formula for conversion from 13: 1 / (0.22 + SS13_MOVE_DELAY / 10) / 4.5 + /// + [DataField, AutoNetworkedField] + public float BaseSprint = 1f; + + [DataField, AutoNetworkedField] + public float ModifiedSprint = 1f; +} diff --git a/Content.Shared/ADT/_RMC14/Wieldable/Events/GetWieldDelayEvent.cs b/Content.Shared/ADT/_RMC14/Wieldable/Events/GetWieldDelayEvent.cs new file mode 100644 index 00000000000..50be9d994b7 --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Wieldable/Events/GetWieldDelayEvent.cs @@ -0,0 +1,7 @@ + +namespace Content.Shared._RMC14.Wieldable.Events; + +[ByRefEvent] +public record struct GetWieldDelayEvent( + TimeSpan Delay +); diff --git a/Content.Shared/ADT/_RMC14/Wieldable/Events/GetWieldableSpeedModifiersEvent.cs b/Content.Shared/ADT/_RMC14/Wieldable/Events/GetWieldableSpeedModifiersEvent.cs new file mode 100644 index 00000000000..85617314da2 --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Wieldable/Events/GetWieldableSpeedModifiersEvent.cs @@ -0,0 +1,8 @@ + +namespace Content.Shared._RMC14.Wieldable.Events; + +[ByRefEvent] +public record struct GetWieldableSpeedModifiersEvent( + float Walk, + float Sprint +); diff --git a/Content.Shared/ADT/_RMC14/Wieldable/Events/RefreshWieldSlowdownCompensationEvent.cs b/Content.Shared/ADT/_RMC14/Wieldable/Events/RefreshWieldSlowdownCompensationEvent.cs new file mode 100644 index 00000000000..f89da3ee296 --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Wieldable/Events/RefreshWieldSlowdownCompensationEvent.cs @@ -0,0 +1,10 @@ +using Content.Shared.Inventory; + +namespace Content.Shared._RMC14.Wieldable; + +[ByRefEvent] +public record struct RefreshWieldSlowdownCompensationEvent( + SlotFlags TargetSlots, + float Walk = 0f, + float Sprint = 0f +) : IInventoryRelayEvent; diff --git a/Content.Shared/ADT/_RMC14/Wieldable/RMCWieldableSystem.cs b/Content.Shared/ADT/_RMC14/Wieldable/RMCWieldableSystem.cs new file mode 100644 index 00000000000..0c8755b06f3 --- /dev/null +++ b/Content.Shared/ADT/_RMC14/Wieldable/RMCWieldableSystem.cs @@ -0,0 +1,234 @@ +using Content.Shared._RMC14.Wieldable.Components; +using Content.Shared._RMC14.Wieldable.Events; +using Content.Shared.Hands; +using Content.Shared.Hands.Components; +using Content.Shared.Interaction.Events; +using Content.Shared.Inventory; +using Content.Shared.Inventory.Events; +using Content.Shared.Movement.Systems; +using Content.Shared.Popups; +using Content.Shared.Timing; +using Content.Shared.Weapons.Ranged.Events; +using Content.Shared.Wieldable; +using Content.Shared.Wieldable.Components; +using Robust.Shared.Containers; +using Robust.Shared.Prototypes; +using Robust.Shared.Timing; + +namespace Content.Shared._RMC14.Wieldable; + +public sealed class RMCWieldableSystem : EntitySystem +{ + [Dependency] private readonly IGameTiming _timing = default!; + [Dependency] private readonly InventorySystem _inventorySystem = default!; + [Dependency] private readonly MovementSpeedModifierSystem _movementSpeedModifierSystem = default!; + [Dependency] private readonly SharedPopupSystem _popupSystem = default!; + [Dependency] private readonly UseDelaySystem _useDelaySystem = default!; + [Dependency] private readonly SharedContainerSystem _container = default!; + + private const string WieldUseDelayID = "RMCWieldDelay"; + + public override void Initialize() + { + SubscribeLocalEvent(OnGotEquippedHand); + SubscribeLocalEvent(OnGotUnequippedHand); + SubscribeLocalEvent>(OnRefreshMovementSpeedModifiers); + SubscribeLocalEvent(OnItemUnwielded); + SubscribeLocalEvent(OnItemWielded); + SubscribeLocalEvent(OnMapInit); + + SubscribeLocalEvent(OnGotEquipped); + SubscribeLocalEvent(OnGotUnequipped); + + SubscribeLocalEvent(OnGotEquippedHand); + SubscribeLocalEvent(OnMapInit); + SubscribeLocalEvent(OnUseInHand); + SubscribeLocalEvent(OnShotAttempt); + SubscribeLocalEvent(OnItemWieldedWithDelay); + + + SubscribeLocalEvent(_inventorySystem.RelayEvent); + } + + private void OnMapInit(Entity wieldable, ref MapInitEvent args) + { + RefreshSpeedModifiers((wieldable.Owner, wieldable.Comp)); + } + + private void OnMapInit(Entity wieldable, ref MapInitEvent args) + { + wieldable.Comp.ModifiedDelay = wieldable.Comp.BaseDelay; + } + + #region Wield speed modifiers + private void OnGotEquippedHand(Entity wieldable, ref GotEquippedHandEvent args) + { + _movementSpeedModifierSystem.RefreshMovementSpeedModifiers(args.User); + } + + private void OnGotUnequippedHand(Entity wieldable, ref GotUnequippedHandEvent args) + { + _movementSpeedModifierSystem.RefreshMovementSpeedModifiers(args.User); + } + + private void OnRefreshMovementSpeedModifiers(Entity wieldable, ref HeldRelayedEvent args) + { + if (TryComp(wieldable.Owner, out TransformComponent? transformComponent) && + transformComponent.ParentUid.Valid && + TryComp(transformComponent.ParentUid, out WieldSlowdownCompensationUserComponent? userComponent)) + { + args.Args.ModifySpeed( + Math.Min(wieldable.Comp.ModifiedWalk + userComponent.Walk, 1f), + Math.Min(wieldable.Comp.ModifiedSprint + userComponent.Sprint, 1f)); + return; + } + + args.Args.ModifySpeed(wieldable.Comp.ModifiedWalk, wieldable.Comp.ModifiedSprint); + } + + public void RefreshSpeedModifiers(Entity wieldable) + { + wieldable.Comp = EnsureComp(wieldable); + + var walkSpeed = wieldable.Comp.BaseWalk; + var sprintSpeed = wieldable.Comp.BaseSprint; + + if (!TryComp(wieldable.Owner, out WieldableComponent? wieldableComponent) || !wieldableComponent.Wielded) + { + walkSpeed = 1f; + sprintSpeed = 1f; + } + + var ev = new GetWieldableSpeedModifiersEvent(walkSpeed, sprintSpeed); + RaiseLocalEvent(wieldable, ref ev); + + wieldable.Comp.ModifiedWalk = ev.Walk > 0 ? ev.Walk : 0; + wieldable.Comp.ModifiedSprint = ev.Sprint > 0 ? ev.Sprint : 0; + + RefreshModifiersOnParent(wieldable.Owner); + } + + private void OnItemUnwielded(Entity wieldable, ref ItemUnwieldedEvent args) + { + RefreshSpeedModifiers((wieldable.Owner, wieldable.Comp)); + } + + private void OnItemWielded(Entity wieldable, ref ItemWieldedEvent args) + { + RefreshSpeedModifiers((wieldable.Owner, wieldable.Comp)); + } + + private void RefreshModifiersOnParent(EntityUid wieldableUid) + { + if (!TryComp(wieldableUid, out TransformComponent? transformComponent) || + !transformComponent.ParentUid.Valid || + !TryComp(transformComponent.ParentUid, out HandsComponent? handsComponent) || + handsComponent.ActiveHandEntity != wieldableUid) + { + return; + } + + _movementSpeedModifierSystem.RefreshMovementSpeedModifiers(transformComponent.ParentUid); + } + #endregion + + + #region Wield slowdown compensation + private void OnGotEquipped(Entity armour, ref GotEquippedEvent args) + { + EnsureComp(args.Equipee, out WieldSlowdownCompensationUserComponent comp); + + RefreshWieldSlowdownCompensation((args.Equipee, comp)); + } + + private void OnGotUnequipped(Entity armour, ref GotUnequippedEvent args) + { + EnsureComp(args.Equipee, out WieldSlowdownCompensationUserComponent comp); + + RefreshWieldSlowdownCompensation((args.Equipee, comp)); + } + + private void RefreshWieldSlowdownCompensation(Entity user) + { + var ev = new RefreshWieldSlowdownCompensationEvent(~SlotFlags.POCKET); + RaiseLocalEvent(user.Owner, ref ev); + + user.Comp.Walk = ev.Walk; + user.Comp.Walk = ev.Sprint; + } + + private void OnRefreshWieldSlowdownCompensation(Entity armour, ref InventoryRelayedEvent args) + { + args.Args.Walk += armour.Comp.Walk; + args.Args.Sprint += armour.Comp.Sprint; + } + #endregion + + #region Wield delay + private void OnGotEquippedHand(Entity wieldable, ref GotEquippedHandEvent args) + { + _useDelaySystem.SetLength(wieldable.Owner, wieldable.Comp.ModifiedDelay, WieldUseDelayID); + _useDelaySystem.TryResetDelay(wieldable.Owner, id: WieldUseDelayID); + } + + private void OnUseInHand(Entity wieldable, ref UseInHandEvent args) + { + if (!TryComp(wieldable.Owner, out UseDelayComponent? useDelayComponent) || + !_useDelaySystem.IsDelayed((wieldable.Owner, useDelayComponent), WieldUseDelayID)) + { + return; + } + + args.Handled = true; + + if (!_useDelaySystem.TryGetDelayInfo((wieldable.Owner, useDelayComponent), out var info, WieldUseDelayID)) + { + return; + } + + var time = $"{(info.EndTime - _timing.CurTime).TotalSeconds:F1}"; + + _popupSystem.PopupClient(Loc.GetString("rmc-wield-use-delay", ("seconds", time), ("wieldable", wieldable.Owner)), args.User, args.User); + } + + public void RefreshWieldDelay(Entity wieldable) + { + wieldable.Comp = EnsureComp(wieldable); + + var ev = new GetWieldDelayEvent(wieldable.Comp.BaseDelay); + RaiseLocalEvent(wieldable, ref ev); + + wieldable.Comp.ModifiedDelay = ev.Delay >= TimeSpan.Zero ? ev.Delay : TimeSpan.Zero; + } + + private void OnItemWieldedWithDelay(Entity wieldable, ref ItemWieldedEvent args) + { + // TODO RMC14 +0.5s if Dazed + var skillModifiedDelay = wieldable.Comp.ModifiedDelay; + + if (_container.TryGetContainingContainer((wieldable, null), out var container)) + skillModifiedDelay -= TimeSpan.FromSeconds(0.2) * 1; // ADT ЗАТЫЧКА + + _useDelaySystem.SetLength(wieldable.Owner, skillModifiedDelay, WieldUseDelayID); + _useDelaySystem.TryResetDelay(wieldable.Owner, id: WieldUseDelayID); + } + + public void OnShotAttempt(Entity wieldable, ref ShotAttemptedEvent args) + { + if (!TryComp(wieldable.Owner, out UseDelayComponent? useDelayComponent) || + !_useDelaySystem.IsDelayed((wieldable.Owner, useDelayComponent), WieldUseDelayID) || + !_useDelaySystem.TryGetDelayInfo((wieldable.Owner, useDelayComponent), out var info, WieldUseDelayID)) + { + return; + } + + args.Cancel(); + + var time = $"{(info.EndTime - _timing.CurTime).TotalSeconds:F1}"; + + //_popupSystem.PopupClient(Loc.GetString("rmc-shoot-use-delay", ("seconds", time), ("wieldable", wieldable.Owner)), args.User, args.User); + // Uncomment when there's a cooldown on popups from a source. + } + + #endregion +} diff --git a/Content.Shared/Actions/AttachableToggleActionEvent.cs b/Content.Shared/Actions/AttachableToggleActionEvent.cs new file mode 100644 index 00000000000..7b108cf0a0f --- /dev/null +++ b/Content.Shared/Actions/AttachableToggleActionEvent.cs @@ -0,0 +1,3 @@ +namespace Content.Shared.Actions.Events; + +public sealed partial class AttachableToggleActionEvent : InstantActionEvent; diff --git a/Content.Shared/Containers/ItemSlot/ItemSlotsSystem.cs b/Content.Shared/Containers/ItemSlot/ItemSlotsSystem.cs index 479690847c3..43a33811b75 100644 --- a/Content.Shared/Containers/ItemSlot/ItemSlotsSystem.cs +++ b/Content.Shared/Containers/ItemSlot/ItemSlotsSystem.cs @@ -492,7 +492,7 @@ public bool TryGetAvailableSlot(Entity ent, return true; } - private static int SortEmpty(ItemSlot a, ItemSlot b) + public static int SortEmpty(ItemSlot a, ItemSlot b) // ADT TWEAK: PRIVATE TO PUBLIC { var aEnt = a.ContainerSlot?.ContainedEntity; var bEnt = b.ContainerSlot?.ContainedEntity; diff --git a/Content.Shared/Damage/Systems/DamageableSystem.cs b/Content.Shared/Damage/Systems/DamageableSystem.cs index 3c3e1b736df..f02d2b1021a 100644 --- a/Content.Shared/Damage/Systems/DamageableSystem.cs +++ b/Content.Shared/Damage/Systems/DamageableSystem.cs @@ -124,7 +124,7 @@ public void DamageChanged(EntityUid uid, DamageableComponent component, DamageSp /// null if the user had no applicable components that can take damage. /// public DamageSpecifier? TryChangeDamage(EntityUid? uid, DamageSpecifier damage, bool ignoreResistances = false, - bool interruptsDoAfters = true, DamageableComponent? damageable = null, EntityUid? origin = null) + bool interruptsDoAfters = true, DamageableComponent? damageable = null, EntityUid? origin = null, EntityUid? tool = null) // ADT TWEAK { if (!uid.HasValue || !_damageableQuery.Resolve(uid.Value, ref damageable, false)) { @@ -154,7 +154,7 @@ public void DamageChanged(EntityUid uid, DamageableComponent component, DamageSp damage = DamageSpecifier.ApplyModifierSet(damage, modifierSet); } - var ev = new DamageModifyEvent(damage, origin); + var ev = new DamageModifyEvent(damage, origin, tool); // ADT TWEAK RaiseLocalEvent(uid.Value, ev); damage = ev.Damage; @@ -303,12 +303,15 @@ public sealed class DamageModifyEvent : EntityEventArgs, IInventoryRelayEvent public readonly DamageSpecifier OriginalDamage; public DamageSpecifier Damage; public EntityUid? Origin; + public EntityUid? Tool; - public DamageModifyEvent(DamageSpecifier damage, EntityUid? origin = null) + + public DamageModifyEvent(DamageSpecifier damage, EntityUid? origin = null, EntityUid? tool = null) // ADT TWEAK { OriginalDamage = damage; Damage = damage; Origin = origin; + Tool = tool; // ADT TWEAK } } diff --git a/Content.Shared/Damage/Systems/RequireProjectileTargetSystem.cs b/Content.Shared/Damage/Systems/RequireProjectileTargetSystem.cs index 209704064b8..1aa3b5bef51 100644 --- a/Content.Shared/Damage/Systems/RequireProjectileTargetSystem.cs +++ b/Content.Shared/Damage/Systems/RequireProjectileTargetSystem.cs @@ -3,6 +3,8 @@ using Content.Shared.Standing; using Robust.Shared.Physics.Events; using Robust.Shared.Containers; +using Content.Shared.ADT.Crawling; // ADT Anti-Lying-Warrior +using Content.Shared.Mobs.Systems; // ADT Anti-Lying-Warrior namespace Content.Shared.Damage.Components; @@ -10,6 +12,7 @@ public sealed class RequireProjectileTargetSystem : EntitySystem { [Dependency] private readonly SharedContainerSystem _container = default!; [Dependency] private readonly EntityLookupSystem _lookup = default!; + [Dependency] private readonly MobStateSystem _mobState = default!; // ADT Anti-Lying-Warrior public override void Initialize() { @@ -21,7 +24,7 @@ public override void Initialize() private void PreventCollide(Entity ent, ref PreventCollideEvent args) { if (args.Cancelled) - return; + return; if (!ent.Comp.Active) return; @@ -37,16 +40,21 @@ private void PreventCollide(Entity ent, ref Pr if (item == ent.Owner) return; } + // ADT Crawling abuse fix end + // ADT ALW Tweak + var weapon = projectile.Weapon; + var alwTarget = targeted.Target; + if (weapon.HasValue && HasComp(weapon) && _mobState.IsDead(alwTarget)) + return; } - // ADT Crawling abuse fix end - + // ADT ALW Tweak // Prevents shooting out of while inside of crates var shooter = projectile.Shooter; if (!shooter.HasValue) return; if (!_container.IsEntityOrParentInContainer(shooter.Value)) - args.Cancelled = true; + args.Cancelled = true; } } diff --git a/Content.Shared/Projectiles/ProjectileComponent.cs b/Content.Shared/Projectiles/ProjectileComponent.cs index 8349252df2b..3de9f716863 100644 --- a/Content.Shared/Projectiles/ProjectileComponent.cs +++ b/Content.Shared/Projectiles/ProjectileComponent.cs @@ -77,6 +77,17 @@ public sealed partial class ProjectileComponent : Component /// /// Whether this projectile has already damaged an entity. /// - [DataField] + [DataField, AutoNetworkedField] public bool DamagedEntity; + + // ADT TWEAK START + /// + /// Sets the maximum range for a projectile fired with ShootAtFixedPointComponent. + /// This can be set on both the Projectile and ShootAtFixedPoint Components. + /// The default value is null for no cap. The minimum value between the two is used. + /// + [DataField, AutoNetworkedField] + public float? MaxFixedRange; + + // ADT TWEAK END } diff --git a/Content.Shared/Sound/SharedEmitSoundSystem.cs b/Content.Shared/Sound/SharedEmitSoundSystem.cs index 3e051fff317..755f8ce1298 100644 --- a/Content.Shared/Sound/SharedEmitSoundSystem.cs +++ b/Content.Shared/Sound/SharedEmitSoundSystem.cs @@ -140,6 +140,14 @@ private void OnEmitSoundOnInteractUsing(Entity +/// This is used to allow ranged weapons to make melee attacks by right-clicking. +/// +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState, Access(typeof(SharedMeleeWeaponSystem))] +public sealed partial class AltFireMeleeComponent : Component +{ + [DataField, AutoNetworkedField] + public AltFireAttackType AttackType = AltFireAttackType.Light; +} + + +[Flags] +public enum AltFireAttackType : byte +{ + Light = 0, // Standard single-target attack. + Heavy = 1 << 0, // Wide swing. + Disarm = 1 << 1 +} diff --git a/Content.Shared/Weapons/Melee/Events/MeleeHitEvent.cs b/Content.Shared/Weapons/Melee/Events/MeleeHitEvent.cs index 75c85790deb..89e8f020054 100644 --- a/Content.Shared/Weapons/Melee/Events/MeleeHitEvent.cs +++ b/Content.Shared/Weapons/Melee/Events/MeleeHitEvent.cs @@ -29,6 +29,7 @@ public sealed class MeleeHitEvent : HandledEntityEventArgs /// This might be required as damage modifier sets cannot add a new damage type to a DamageSpecifier. /// public DamageSpecifier BonusDamage = new(); + public DamageSpecifier DecreaseDamage = new(); /// /// A list containing every hit entity. Can be zero. diff --git a/Content.Shared/Weapons/Ranged/Components/GunComponent.cs b/Content.Shared/Weapons/Ranged/Components/GunComponent.cs index 98b1d2fe2a4..aa6dda0908b 100644 --- a/Content.Shared/Weapons/Ranged/Components/GunComponent.cs +++ b/Content.Shared/Weapons/Ranged/Components/GunComponent.cs @@ -5,11 +5,12 @@ using Robust.Shared.GameStates; using Robust.Shared.Map; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom; +using Content.Shared._RMC14.Weapons.Ranged; namespace Content.Shared.Weapons.Ranged.Components; [RegisterComponent, NetworkedComponent, AutoGenerateComponentState, AutoGenerateComponentPause] -[Access(typeof(SharedGunSystem))] +[Access(typeof(SharedGunSystem), typeof(RMCSelectiveFireSystem))] // ADT TWEAK public sealed partial class GunComponent : Component { #region Sound @@ -212,7 +213,7 @@ public sealed partial class GunComponent : Component /// The base value for how fast the projectile moves. /// [DataField] - public float ProjectileSpeed = 25f; + public float ProjectileSpeed = 62f; /// /// How fast the projectile moves. diff --git a/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.Interactions.cs b/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.Interactions.cs index f3ff89a660e..d8cddd05a71 100644 --- a/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.Interactions.cs +++ b/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.Interactions.cs @@ -4,6 +4,7 @@ using Content.Shared.Verbs; using Content.Shared.Weapons.Ranged.Components; using Robust.Shared.Utility; +using Content.Shared._RMC14.Weapons.Ranged; // ADT TWEAK namespace Content.Shared.Weapons.Ranged.Systems; @@ -61,7 +62,7 @@ private SelectiveFire GetNextMode(GunComponent component) return modes[(index + 1) % modes.Count]; } - private void SelectFire(EntityUid uid, GunComponent component, SelectiveFire fire, EntityUid? user = null) + public void SelectFire(EntityUid uid, GunComponent component, SelectiveFire fire, EntityUid? user = null) // ADT TWEAK: PRIVATE TO PUBLIC { if (component.SelectedMode == fire) return; @@ -82,6 +83,10 @@ private void SelectFire(EntityUid uid, GunComponent component, SelectiveFire fir Audio.PlayPredicted(component.SoundMode, uid, user); Popup(Loc.GetString("gun-selected-mode", ("mode", GetLocSelector(fire))), uid, user); + + var ev = new RMCFireModeChangedEvent(); // ADT TWEAK + RaiseLocalEvent(uid, ref ev); // ADT TWEAK + Dirty(uid, component); } diff --git a/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.cs b/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.cs index bc486b729ae..926c328e2d1 100644 --- a/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.cs +++ b/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.cs @@ -37,7 +37,6 @@ using Robust.Shared.Utility; using Content.Shared.ADT.DNAGunLocker; using Content.Shared.Electrocution; -using Content.Shared.CombatMode; namespace Content.Shared.Weapons.Ranged.Systems; @@ -425,7 +424,7 @@ private void AttemptShoot(EntityUid user, EntityUid gunUid, GunComponent gun) // Shoot confirmed - sounds also played here in case it's invalid (e.g. cartridge already spent). Shoot(gunUid, gun, ev.Ammo, fromCoordinates, toCoordinates.Value, out var userImpulse, user, throwItems: attemptEv.ThrowItems); - var shotEv = new GunShotEvent(user, ev.Ammo); + var shotEv = new GunShotEvent(user, ev.Ammo, fromCoordinates, toCoordinates.Value); // ADT TWEAK RaiseLocalEvent(gunUid, ref shotEv); if (userImpulse && TryComp(user, out var userPhysics)) @@ -629,7 +628,7 @@ public record struct AttemptShootEvent(EntityUid User, string? Message, bool Can /// /// The user that fired this gun. [ByRefEvent] -public record struct GunShotEvent(EntityUid User, List<(EntityUid? Uid, IShootable Shootable)> Ammo); +public record struct GunShotEvent(EntityUid User, List<(EntityUid? Uid, IShootable Shootable)> Ammo, EntityCoordinates FromCoordinates, EntityCoordinates ToCoordinates); // ADT TWEAK public enum EffectLayers : byte { diff --git a/Content.Shared/Wieldable/Components/WieldableComponent.cs b/Content.Shared/Wieldable/Components/WieldableComponent.cs index 5dc6abbbbea..4dce8510d4b 100644 --- a/Content.Shared/Wieldable/Components/WieldableComponent.cs +++ b/Content.Shared/Wieldable/Components/WieldableComponent.cs @@ -28,7 +28,7 @@ public sealed partial class WieldableComponent : Component /// /// Whether using the item inhand while wielding causes the item to unwield. - /// Unwielding can conflict with other inhand actions. + /// Unwielding can conflict with other inhand actions. /// [DataField] public bool UnwieldOnUse = true; diff --git a/Resources/Audio/ADT/Attachments/attachment_activate.ogg b/Resources/Audio/ADT/Attachments/attachment_activate.ogg new file mode 100644 index 00000000000..3b7d1ff2aba Binary files /dev/null and b/Resources/Audio/ADT/Attachments/attachment_activate.ogg differ diff --git a/Resources/Audio/ADT/Attachments/attachment_add.ogg b/Resources/Audio/ADT/Attachments/attachment_add.ogg new file mode 100644 index 00000000000..75ce0fabe22 Binary files /dev/null and b/Resources/Audio/ADT/Attachments/attachment_add.ogg differ diff --git a/Resources/Audio/ADT/Attachments/attachment_deactivate.ogg b/Resources/Audio/ADT/Attachments/attachment_deactivate.ogg new file mode 100644 index 00000000000..9047e9b8457 Binary files /dev/null and b/Resources/Audio/ADT/Attachments/attachment_deactivate.ogg differ diff --git a/Resources/Audio/ADT/Attachments/attachment_remove.ogg b/Resources/Audio/ADT/Attachments/attachment_remove.ogg new file mode 100644 index 00000000000..593cc6ab666 Binary files /dev/null and b/Resources/Audio/ADT/Attachments/attachment_remove.ogg differ diff --git a/Resources/Audio/ADT/Attachments/attributions.yml b/Resources/Audio/ADT/Attachments/attributions.yml new file mode 100644 index 00000000000..c01ce44d729 --- /dev/null +++ b/Resources/Audio/ADT/Attachments/attributions.yml @@ -0,0 +1,19 @@ +- files: ["attachment_add.ogg"] + license: "CC-BY-SA-3.0" + copyright: "The CM-SS13 development team" + source: "https://github.com/cmss13-devs/cmss13/blob/master/sound/handling/attachment_add.ogg" + +- files: ["attachment_remove.ogg"] + license: "CC-BY-SA-3.0" + copyright: "The CM-SS13 development team" + source: "https://github.com/cmss13-devs/cmss13/blob/master/sound/handling/attachment_remove.ogg" + +- files: ["attachment_activate.ogg"] + license: "CC-BY-SA-3.0" + copyright: "The CM-SS13 development team" + source: "https://github.com/cmss13-devs/cmss13/blob/master/sound/handling/gun_underbarrel_activate.ogg" + +- files: ["attachment_deactivate.ogg"] + license: "CC-BY-SA-3.0" + copyright: "The CM-SS13 development team" + source: "https://github.com/cmss13-devs/cmss13/blob/master/sound/handling/gun_underbarrel_deactivate.ogg" diff --git a/Resources/Audio/_RMC14/Weapons/Guns/Breech/attributions.yml b/Resources/Audio/_RMC14/Weapons/Guns/Breech/attributions.yml new file mode 100644 index 00000000000..580f900d818 --- /dev/null +++ b/Resources/Audio/_RMC14/Weapons/Guns/Breech/attributions.yml @@ -0,0 +1,9 @@ +- files: ["ugl_close.ogg"] + license: "CC-BY-SA-3.0" + copyright: "Taken from cmss13" + source: "https://github.com/cmss13-devs/cmss13/blob/master/sound/weapons/handling/ugl_close.ogg" + +- files: ["ugl_open.ogg"] + license: "CC-BY-SA-3.0" + copyright: "Taken from cmss13" + source: "https://github.com/cmss13-devs/cmss13/blob/master/sound/weapons/handling/ugl_open.ogg" diff --git a/Resources/Audio/_RMC14/Weapons/Guns/Breech/ugl_close.ogg b/Resources/Audio/_RMC14/Weapons/Guns/Breech/ugl_close.ogg new file mode 100644 index 00000000000..7ca25520cce Binary files /dev/null and b/Resources/Audio/_RMC14/Weapons/Guns/Breech/ugl_close.ogg differ diff --git a/Resources/Audio/_RMC14/Weapons/Guns/Breech/ugl_open.ogg b/Resources/Audio/_RMC14/Weapons/Guns/Breech/ugl_open.ogg new file mode 100644 index 00000000000..580df16ac2c Binary files /dev/null and b/Resources/Audio/_RMC14/Weapons/Guns/Breech/ugl_open.ogg differ diff --git a/Resources/Audio/_RMC14/Weapons/Guns/Gunshots/attributions.yml b/Resources/Audio/_RMC14/Weapons/Guns/Gunshots/attributions.yml new file mode 100644 index 00000000000..829b5e4d542 --- /dev/null +++ b/Resources/Audio/_RMC14/Weapons/Guns/Gunshots/attributions.yml @@ -0,0 +1,14 @@ +- files: ["gun_silenced_shot1.ogg"] + license: "CC-BY-SA-3.0" + copyright: "Taken from cmss13" + source: "https://github.com/cmss13-devs/cmss13/blob/97365cd3721e668f87a7b180f5bd47e8d976e451/sound/weapons/gun_silenced_shot1.ogg" + +- files: ["gun_silenced_shot2.ogg"] + license: "CC-BY-SA-3.0" + copyright: "Taken from cmss13" + source: "https://github.com/cmss13-devs/cmss13/blob/97365cd3721e668f87a7b180f5bd47e8d976e451/sound/weapons/gun_silenced_shot1.ogg" + +- files: ["gun_ugl.ogg"] + license: "CC-BY-SA-3.0" + copyright: "Taken from cmss13" + source: "https://github.com/cmss13-devs/cmss13/blob/8086109b2dbf8d1d98aec106a07d86b65fe63e1b/sound/weapons/gun_m92_attachable.ogg" \ No newline at end of file diff --git a/Resources/Audio/_RMC14/Weapons/Guns/Gunshots/gun_silenced_shot1.ogg b/Resources/Audio/_RMC14/Weapons/Guns/Gunshots/gun_silenced_shot1.ogg new file mode 100644 index 00000000000..a78d57f602e Binary files /dev/null and b/Resources/Audio/_RMC14/Weapons/Guns/Gunshots/gun_silenced_shot1.ogg differ diff --git a/Resources/Audio/_RMC14/Weapons/Guns/Gunshots/gun_silenced_shot2.ogg b/Resources/Audio/_RMC14/Weapons/Guns/Gunshots/gun_silenced_shot2.ogg new file mode 100644 index 00000000000..a5e92e7c35f Binary files /dev/null and b/Resources/Audio/_RMC14/Weapons/Guns/Gunshots/gun_silenced_shot2.ogg differ diff --git a/Resources/Audio/_RMC14/Weapons/Guns/Gunshots/gun_ugl.ogg b/Resources/Audio/_RMC14/Weapons/Guns/Gunshots/gun_ugl.ogg new file mode 100644 index 00000000000..dc260889808 Binary files /dev/null and b/Resources/Audio/_RMC14/Weapons/Guns/Gunshots/gun_ugl.ogg differ diff --git a/Resources/Audio/_RMC14/Weapons/Guns/Reload/attributions.yml b/Resources/Audio/_RMC14/Weapons/Guns/Reload/attributions.yml new file mode 100644 index 00000000000..50c70e51cd0 --- /dev/null +++ b/Resources/Audio/_RMC14/Weapons/Guns/Reload/attributions.yml @@ -0,0 +1,4 @@ +- files: ["grenade_insert.ogg"] + license: "CC-BY-SA-3.0" + copyright: "Taken from cmss13, converted to .ogg" + source: "https://github.com/cmss13-devs/cmss13/blob/master/sound/weapons/grenade_insert.wav" \ No newline at end of file diff --git a/Resources/Audio/_RMC14/Weapons/Guns/Reload/grenade_insert.ogg b/Resources/Audio/_RMC14/Weapons/Guns/Reload/grenade_insert.ogg new file mode 100644 index 00000000000..cd615939c43 Binary files /dev/null and b/Resources/Audio/_RMC14/Weapons/Guns/Reload/grenade_insert.ogg differ diff --git a/Resources/Changelog/1ChangelogADT.yml b/Resources/Changelog/1ChangelogADT.yml index 692bce7e6dd..0f4e7b55693 100644 --- a/Resources/Changelog/1ChangelogADT.yml +++ b/Resources/Changelog/1ChangelogADT.yml @@ -4836,3 +4836,33 @@ Entries: - {message: 'Подтянуты коммиты с Корвакса, 19.11.2024', type: Tweak} time: '2024-12-14T20:20:24Z' id: 605 + - author: NameLunar + changes: + - {message: Добавлен гост бар "Calm" от maksim21612., type: Add} + - {message: Удалены подозрительные подарки на карте Frontier. (Никакой больше + ядерки из подарка😥), type: Remove} + time: '2024-12-16T20:04:31Z' + id: 606 + - author: Inconnu & Пётр & Котя + changes: + - {message: 'Перенесены обвесы с колониальных маринов, а оружие на сервере претерпело + большие изменения. За подробностями — в пулл или канал вопрос-ответ.', type: Add} + - {message: Добавлены 40-мм гранатометные снаряды., type: Add} + - {message: Добавлен в аплинк ядерщиков гранатомет - аналог старой однозарядной + Чайны., type: Add} + - {message: Добавлена функция удара прикладом на ПКМ на некоторые виды оружия. + При закрепленном штыке на оружие - наносится удар им., type: Add} + - {message: Добавлен интегрированный прицел на Христов (прицелы могут работать + некорректно) и стартовые модули на хС-67., type: Add} + - {message: Подствольный гранатомет с М-90gl перенесен в отдельный модуль (ОБР + может купить его в своём аплинке на выбор между гранатометом и дробовиком). + Боеприпасы изменены на 40-мм гранаты., type: Tweak} + - {message: Боеприпасы гранатометных установок мехов изменены на 40-мм гранаты., + type: Tweak} + - {message: 'Чайна Лейк стала многозарядной, снаряды заменены на 40-мм гранаты.', + type: Tweak} + - {message: 'Исправлен револьвер ОСЩ - выстрел теперь на ЛКМ, на ПКМ - удар + рукоятью/энергоклинком револьвера.', type: Fix} + - {message: Исправлена локализация и цены в аплинке ОБР., type: Fix} + time: '2024-12-18T13:47:21Z' + id: 607 diff --git a/Resources/Locale/en-US/store/categories.ftl b/Resources/Locale/en-US/store/categories.ftl index 64ed0b5c637..9e51128cffd 100644 --- a/Resources/Locale/en-US/store/categories.ftl +++ b/Resources/Locale/en-US/store/categories.ftl @@ -3,6 +3,7 @@ store-category-debug = debug category store-category-debug2 = debug category 2 store-category-weapons = Weaponry store-category-ammo = Ammo +store-category-attachments = Attachments store-category-explosives = Explosives store-category-chemicals = Chemicals store-category-deception = Deception diff --git a/Resources/Locale/ru-RU/ADT/Objects/Specific/product-unit.ftl b/Resources/Locale/ru-RU/ADT/Objects/Specific/product-unit.ftl deleted file mode 100644 index e292734ab82..00000000000 --- a/Resources/Locale/ru-RU/ADT/Objects/Specific/product-unit.ftl +++ /dev/null @@ -1,2 +0,0 @@ -ent-Productunit = торговая единица - .desc = Кажется, этот предмет пульсирует подозрительно притягательной энергией. diff --git a/Resources/Locale/ru-RU/ADT/Objects/Weapons/Guns/launchers.ftl b/Resources/Locale/ru-RU/ADT/Objects/Weapons/Guns/launchers.ftl new file mode 100644 index 00000000000..37e3891148f --- /dev/null +++ b/Resources/Locale/ru-RU/ADT/Objects/Weapons/Guns/launchers.ftl @@ -0,0 +1,4 @@ +ent-ADTWeaponLauncherChinaLake = China Lake + .desc = БЛУП +ent-ADTWeaponLauncherRocket = РПГ-7 + .desc = Древний ручной реактивный гранатомёт. diff --git a/Resources/Locale/ru-RU/ADT/actions/scoping.ftl b/Resources/Locale/ru-RU/ADT/actions/scoping.ftl new file mode 100644 index 00000000000..81be6417e96 --- /dev/null +++ b/Resources/Locale/ru-RU/ADT/actions/scoping.ftl @@ -0,0 +1,17 @@ +rcm-action-popup-scope-cycle-zoom = Уровень приближения изменен на {$zoom}. +cm-action-popup-scoping-must-attach = {CAPITALIZE($scope)} должен быть закреплен на оружии для корректной работы! +cm-action-popup-scoping-user-must-hold = Вы должны держать {$scope} в своей активной руке, чтобы посмотреть через него. +cm-action-popup-scoping-user-must-not-pulled = Вы не можете смотреть в {$scope}, пока вас тащат! +cm-action-popup-scoping-user-must-not-contained = Вы не можете смотреть в {$scope}, будучи в ящике! +cm-action-popup-scoping-user-must-wield = Вы должны держать {$scope} в двух руках, чтобы его использовать. +cm-action-popup-scoping-user = Вы смотрите через {$scope}. +cm-action-popup-scoping-stopping-user = Вы прекращаете смотреть через {$scope}. + +action-name-basescope = Посмотреть в прицел +action-description-basescope = Воспользоваться прицелом и рассмотреть цель получше. + +action-name-hristovscope = Посмотреть в прицел Христова +action-description-hristovscope = Воспользоваться прицелом и рассмотреть цель получше. + +action-name-xc67scope = Посмотреть в прицел T2 +action-description-xc67scope = Воспользоваться прицелом и рассмотреть цель получше. diff --git a/Resources/Locale/ru-RU/ADT/attachments/attachable/attachable.ftl b/Resources/Locale/ru-RU/ADT/attachments/attachable/attachable.ftl new file mode 100644 index 00000000000..83c89b47e8b --- /dev/null +++ b/Resources/Locale/ru-RU/ADT/attachments/attachable/attachable.ftl @@ -0,0 +1,69 @@ +rmc-attachable-holder-strip-ui-title = Модули +rmc-attachable-holder-strip-ui-empty-slot = Ничего + +rmc-verb-strip-attachables = Снять модули + +rmc-aslot-barrel = Ствол +rmc-aslot-rail = Верхняя планка +rmc-aslot-stock = Приклад +rmc-aslot-underbarrel = Подствольное + +rmc-attachable-activation-fail-not-wielded = {CAPITALIZE($holder)} должен быть в обеих руках, чтобы активировать {$attachable}! +rmc-attachable-activation-fail-not-held = {CAPITALIZE($holder)} должен быть в руках, чтобы активировать {$attachable}! +rmc-attachable-activation-fail-not-owned = {CAPITALIZE($holder)} должен быть в ваших руках или экипирован, чтобы активировать {$attachable}! + +rmc-attachable-shoot-fail-not-wielded = {CAPITALIZE($holder)} должен быть экипирован, чтобы стрелять из {THE($attachable)}! + +rmc-attachable-verb-toggle = Переключить {$attachable} + +attachable-popup-activate-generic = Вы активируете {$attachable}. +attachable-popup-deactivate-generic = Вы деактивируете {$attachable}. + +attachable-popup-activate-deploy-on-generic = Вы устанавливаете {$attachable} на {$surface}. +attachable-popup-activate-deploy-on-ground = Вы устанавливаете {$attachable} на землю. +attachable-popup-deactivate-retract = Вы убираете {$attachable}. + +attachable-popup-activate-unfold = Вы разворачиваете {$attachable}. +attachable-popup-deactivate-collapse = Вы складываете {$attachable}. + +attachable-popup-activate-lock = Вы блокируете {$attachable}. +attachable-popup-deactivate-unlock = Вы разблокируете {$attachable}. + +attachable-popup-switch-to-generic = Вы переключаетесь на использование {$attachable}. +attachable-popup-switch-from-generic = Вы перестаёте использовать {$attachable}. + +rmc-attachable-examinable-verb-text = Модификаторы модулей +rmc-attachable-examinable-verb-message = Изучить модификаторы, применяемые этим модулем. + +rmc-attachable-examine-condition-always = [bold]Всегда =[/bold] +rmc-attachable-examine-condition-when = Когда +rmc-attachable-examine-condition-wielded = предмет [bold]экипирован[/bold] +rmc-attachable-examine-condition-unwielded = предмет [bold]не экипирован[/bold] +rmc-attachable-examine-condition-active = {THE($attachable)} [bold]активен[/bold] +rmc-attachable-examine-condition-inactive = {THE($attachable)} [bold]неактивен[/bold] + +rmc-attachable-examine-condition-whitelist-comps = предмет [bold]имеет {$compNumber}[/bold] из следующих компонентов = [bold]{$comps}[/bold] +rmc-attachable-examine-condition-whitelist-sizes = предмет [bold]имеет один из следующих размеров =[/bold] [bold]{$sizes}[/bold] +rmc-attachable-examine-condition-whitelist-tags = предмет [bold]имеет {$tagNumber}[/bold] из следующих тегов = [bold]{$tags}[/bold] + +rmc-attachable-examine-condition-blacklist-comps = предмет [bold]не имеет {$compNumber}[/bold] из следующих компонентов = [bold]{$comps}[/bold] +rmc-attachable-examine-condition-blacklist-sizes = предмет [bold]не имеет один из следующих размеров = [/bold][bold]{$sizes}[/bold] +rmc-attachable-examine-condition-blacklist-tags = предмет [bold]не имеет {$tagNumber}[/bold] из следующих тегов = [bold]{$tags}[/bold] + +rmc-attachable-examine-ranged-scatter = [color={$colour}]{$sign}{$scatter}[/color] градусов разброса. +rmc-attachable-examine-ranged-burst-scatter = [color={$colour}]{$sign}{$burstScatterMult}[/color] множитель разброса очереди. +rmc-attachable-examine-ranged-shots-per-burst = [color={$colour}]{$sign}{$shots}[/color] выстрелов за очередь. +rmc-attachable-examine-ranged-fire-delay = [color={$colour}]{$sign}{TOSTRING($fireDelay, "F2")}[/color] секунд задержки перед выстрелом. +rmc-attachable-examine-ranged-recoil = [color={$colour}]{$sign}{$recoil}[/color] отдача. +rmc-attachable-examine-ranged-damage = [color={$colour}]{$sign}{$damage}[/color] множитель урона. +rmc-attachable-examine-ranged-projectile-speed = [color={$colour}]{$sign}{$projectileSpeed}[/color] скорость снаряда. +rmc-attachable-examine-ranged-damage-falloff = [color={$colour}]{$sign}{$falloff}[/color] множитель снижения урона. + +rmc-attachable-examine-melee-damage = [color={$colour}]{$sign}{$damage}[/color] урон в ближнем бою. + +rmc-attachable-examine-size = [color={$colour}]{$sign}{$size}[/color] размер предмета. + +rmc-attachable-examine-speed-walk = [color={$colour}]{$sign}{TOSTRING($speed, "F2")}[/color] множитель скорости ходьбы. +rmc-attachable-examine-speed-sprint = [color={$colour}]{$sign}{TOSTRING($speed, "F2")}[/color] множитель скорости бега. + +rmc-attachable-examine-wield-delay = [color={$colour}]{$sign}{$delay}[/color] секунд задержки экипировки. diff --git a/Resources/Locale/ru-RU/ADT/attachments/weapons/guns.ftl b/Resources/Locale/ru-RU/ADT/attachments/weapons/guns.ftl new file mode 100644 index 00000000000..cf0050b0963 --- /dev/null +++ b/Resources/Locale/ru-RU/ADT/attachments/weapons/guns.ftl @@ -0,0 +1,23 @@ +cm-gun-no-ammo-message = У вас больше нет патронов! +cm-gun-use-delay = Вам нужно подождать {$seconds} секунд, прежде чем снова стрелять! +cm-gun-pump-examine = [bold]Нажмите вашу [color=cyan]уникальную клавишу действия[/color] (по умолчанию Spacebar), чтобы взвести оружие перед выстрелом.[/bold] +cm-gun-pump-first-with = Сначала нужно взвести оружие с помощью {$key}! +cm-gun-pump-first = Сначала нужно взвести оружие! + +rmc-breech-loaded-open-shoot-attempt = Сначала нужно закрыть затвор! +rmc-breech-loaded-not-ready-to-shoot = Сначала нужно открыть и закрыть затвор! +rmc-breech-loaded-closed-load-attempt = Сначала нужно открыть затвор! +rmc-breech-loaded-closed-extract-attempt = Сначала нужно открыть затвор! + +rmc-wield-use-delay = Вам нужно подождать {$seconds} секунд, прежде чем использовать {$wieldable}! +rmc-shoot-use-delay = Вам нужно подождать {$seconds} секунд, прежде чем стрелять из {$wieldable}! + +rmc-revolver-spin = Вы раскручиваете барабан. + +rmc-examine-text-scatter-max = Текущий максимальный разброс = [color={$colour}]{TOSTRING($scatter, "F1")}[/color] градусов. +rmc-examine-text-scatter-min = Текущий минимальный разброс = [color={$colour}]{TOSTRING($scatter, "F1")}[/color] градусов. +rmc-examine-text-shots-to-max-scatter = Требуется [color={$colour}]{$shots}[/color] выстрелов, чтобы достичь максимального разброса. + +rmc-gun-rack-examine = [bold]Нажмите вашу [color=cyan]уникальную клавишу действия[/color] (по умолчанию Spacebar), чтобы передёрнуть затвор перед выстрелом.[/bold] +rmc-gun-rack-first-with = Сначала нужно передёрнуть затвор с помощью {$key}! +rmc-gun-rack-first = Сначала нужно передёрнуть затвор! diff --git a/Resources/Locale/ru-RU/ADT/attachments/weapons/magnetize.ftl b/Resources/Locale/ru-RU/ADT/attachments/weapons/magnetize.ftl new file mode 100644 index 00000000000..d4c77aecb3b --- /dev/null +++ b/Resources/Locale/ru-RU/ADT/attachments/weapons/magnetize.ftl @@ -0,0 +1 @@ +rmc-magnetize-return = {CAPITALIZE($item)} притягивается на место. \ No newline at end of file diff --git a/Resources/Locale/ru-RU/ADT/escape-menu/ui/options-menu.ftl b/Resources/Locale/ru-RU/ADT/escape-menu/ui/options-menu.ftl new file mode 100644 index 00000000000..fcb19b61de5 --- /dev/null +++ b/Resources/Locale/ru-RU/ADT/escape-menu/ui/options-menu.ftl @@ -0,0 +1,13 @@ +## Кнопки работы с модулями +ui-options-header-rmc = Оружейные модули +ui-options-function-rmc-activate-attachable-barrel = Активировать модуль ствола +ui-options-function-rmc-activate-attachable-rail = Активировать модуль верхней планки +ui-options-function-rmc-activate-attachable-stock = Активировать модуль приклада +ui-options-function-rmc-activate-attachable-underbarrel = Активировать подствольный модуль +ui-options-function-rmc-field-strip-held-item = Осмотр оружейных модулей +ui-options-function-rmc-cycle-fire-mode = Циклический режим огня +ui-options-function-cm-unique-action = Передернуть затвор +ui-options-function-cm-holster-primary = Вытащить из кобуры оружие +ui-options-function-cm-holster-secondary = Вытащить из кобуры, второе оружие +ui-options-function-cm-holster-tertiary = Вытащить из кобуры, третье оружие +ui-options-function-cm-holster-quaternary = Вытащить из кобуры, четвертое оружие diff --git a/Resources/Locale/ru-RU/ADT/prototypes/Catalog/Fills/Items/weaponcases.ftl b/Resources/Locale/ru-RU/ADT/prototypes/Catalog/Fills/Items/weaponcases.ftl index 38ef5e71cb9..85483ed2d32 100644 --- a/Resources/Locale/ru-RU/ADT/prototypes/Catalog/Fills/Items/weaponcases.ftl +++ b/Resources/Locale/ru-RU/ADT/prototypes/Catalog/Fills/Items/weaponcases.ftl @@ -41,3 +41,15 @@ ent-WeaponCaseBulldog = { ent-WeaponCaseNTM90 } ent-ADTWeaponCaseAR12 = { ent-WeaponCaseNTM90 } .desc = { ent-WeaponCaseNTM90.desc }. .suffix = { "AR-12" } + +ent-WeaponCaseNTM90GrenadeLauncherAttachment = { ent-WeaponCaseNTM90 } + .desc = { ent-WeaponCaseNTM90.desc }. + .suffix = { "Подствольный гранатомёт" } + +ent-WeaponCaseNTM90UnderBarrelShotGunAttachment = { ent-WeaponCaseNTM90 } + .desc = { ent-WeaponCaseNTM90.desc }. + .suffix = { "Подствольный дробовик" } + +ent-WeaponCaseNTGunsModules = { ent-WeaponCaseNTM90 } + .desc = { ent-WeaponCaseNTM90.desc }. + .suffix = { "Оружейные модули" } diff --git a/Resources/Locale/ru-RU/ADT/prototypes/Catalog/Fills/backpacks/duffelbag.ftl b/Resources/Locale/ru-RU/ADT/prototypes/Catalog/Fills/backpacks/duffelbag.ftl index e237188eba7..4b8830bbe73 100644 --- a/Resources/Locale/ru-RU/ADT/prototypes/Catalog/Fills/backpacks/duffelbag.ftl +++ b/Resources/Locale/ru-RU/ADT/prototypes/Catalog/Fills/backpacks/duffelbag.ftl @@ -36,3 +36,6 @@ ent-ADTClothingBackpackDuffelSyndicateFilledBlackmail = набор шантаж ent-ADTClothingBackpackDuffelSyndicateFilledElite = набор элитного налетчика .desc = Содержит улучшенный скафандр Синдиката, продвинутые магнитные сапоги и энергомеч с щитом. + +ent-ADTClothingBackpackDuffelSyndicateFilledWeaponAttachments = набор оружейных модулей + .desc = Комплект из вертикальной рукояти, лазерного целеуказателя, коллиматорного и оптического прицелов. diff --git a/Resources/Locale/ru-RU/ADT/prototypes/Catalog/store/bobr.ftl b/Resources/Locale/ru-RU/ADT/prototypes/Catalog/store/bobr.ftl index 0079650754d..d84c218a2b7 100644 --- a/Resources/Locale/ru-RU/ADT/prototypes/Catalog/store/bobr.ftl +++ b/Resources/Locale/ru-RU/ADT/prototypes/Catalog/store/bobr.ftl @@ -1,65 +1,83 @@ -boobr-bulldog-name = набор бульдог -boobr-bulldog-desc = классический автоматический дробовик, заряжаемый барабанами 12х70. +boobr-bulldog-name = Набор "Бульдог" +boobr-bulldog-desc = Классический автоматический дробовик, заряжаемый барабанами 12х70. -boobr-m90-name = набор m-90 -boobr-m90-desc = Старый карабин, оборудованный подствольным гранатомётом. Разрывные и световые гранаты в комплекте. +boobr-m90-name = Набор "М-90gl" +boobr-m90-desc = Старый карабин, на который можно установить подствольный гранатомёт. -boobr-lecter-name = набор лектер +boobr-lecter-name = Набор "Лектер" boobr-lecter-desc = Первоклассная армейская штурмовая винтовка. Использует патроны калибра 6.5х39 мм TSF, входящие в набор. -boobr-ar12-name = набор AR-12 -boobr-ar12-desc = Продвинутая штурмовая винтовка подогнанная специально под быстрое уничтожение противника. Использует патроны калибра 6.5 мм ТСФ, входящие в набор. +boobr-ar12-name = Набор "АR-12" +boobr-ar12-desc = Продвинутая штурмовая винтовка. Использует патроны калибра 6.5 мм ТСФ, входящие в набор. -boobr-pulse-name = импульсный карабин -boobr-pulse-desc = Высокотехнологичный энергетический карабин, который предпочитают оперативники ОБР NT. +boobr-pulse-name = Импульсный карабин +boobr-pulse-desc = Высокотехнологичный энергетический карабин, который предпочитают оперативники ОБР NanoTrasen. -boobr-mateba-name = набор матеба -boobr-mateba-desc = Чертовски стильный и шумный револьвер, использующий .44 магнум. +boobr-mateba-name = Набор "Матеба" +boobr-mateba-desc = Чертовски стильный и шумный револьвер, использующий патроны .44 магнум. -boobr-ap-name = набор пробития брони -boobr-ap-desc = Набор из 10-ти бронебойных патронов .44 магнум, идеально подходящих для матебы и desert eagle. +boobr-ap-name = Набор бронебойщика +boobr-ap-desc = Набор из 10-ти бронебойных патронов .44 магнум, идеально подходящих для Матебы и Дезерт Игла. boobr-deagle-name = Дезерт Игл -boobr-deagle-desc = Дезерт Игл, также известный как "пустынный орёл", - это мощный пистолет калибра .44, который выглядит металлическим и блестящим. +boobr-deagle-desc = Дезерт Игл, также известный как "Пустынный Орёл", - это мощный пистолет калибра .44, который выглядит металлическим и блестящим. -boobr-disabler-name = набор дизаблеров -boobr-disabler-desc = НТ не смогли выбрать, что лучше - станнер ПП или просто станнер. Потому, они добавили в набор оба. +boobr-disabler-name = Набор станнеров +boobr-disabler-desc = NanoTrasen не смогли выбрать, что лучше - станнер-пулемет или просто станнер. Потому они добавили в набор оба. -boobr-ion-name = ионная винтовка -boobr-ion-desc = Ионно-электрическая разрушительная винтовка, специально разработана против мехов и боргов. +boobr-ion-name = Ионная винтовка +boobr-ion-desc = Ионно-электрическая винтовка, специально разработана против мехов и боргов. -boobr-drozd-name = Дрозд +boobr-drozd-name = Набор "Дрозд" boobr-drozd-desc = Превосходный, полностью автоматический, тяжёлый пистолет-пулемёт. Использует патроны калибра 9х19 мм. -boobr-riot-shield-name = противоударный щит -boobr-riot-shield-desc = Большой башенный щит на случай беспорядков. Хорошо подходит для контроля толпы. +boobr-riot-shield-name = Противоударный щит +boobr-riot-shield-desc = Большой ростовой щит на случай беспорядков. Хорошо подходит для контроля толпы. -boobr-bullet-shield-name = противопульный щит +boobr-bullet-shield-name = Противопульный щит boobr-bullet-shield-desc = Щит на случай беспорядков, созданный противостоять пулям, но не более того. -boobr-mag-boots-name = магнитные сапоги обр -boobr-mag-boots-desc = Магнитные сапоги, специально разработанные для ведения боевых действий в космосе. Данная модель выдается бойцам отрядов ОБР. +boobr-mag-boots-name = Магнитные сапоги ОБР. +boobr-mag-boots-desc = Продвинутые магнитные сапоги, специально разработанные для ведения боевых действий в космосе. Данная модель выдается бойцам отрядов ОБР. -boobr-JawsOfLife-name = челюсти жизни -boobr-JawsOfLife-desc = Набор челюстей жизни, скомпонованных при помощи магии науки. +boobr-JawsOfLife-name = Челюсти жизни +boobr-JawsOfLife-desc = Приспособление для быстрого вскрытия дверей. boobr-c4-name = C-4 boobr-c4-desc = Используйте её, чтобы разрушать стены, шлюзы. Её можно прикрепить практически к любому объекту, а таймер можно изменять, минимальное значение - 10 секунд. -boobr-grenade-name = шрапнельная граната +boobr-grenade-name = Шрапнельная граната boobr-grenade-desc = Разбрасывает вокруг себя облако шрапнели, вызывающей множественные раны и кровотечения. -boobr-jetpack-name = джетпак +boobr-jetpack-name = Джетпак boobr-jetpack-desc = Позволяет с лёгкостью передвигаться вне станции. -boobr-grappling-gun-name = крюк-кошка +boobr-grappling-gun-name = Крюк-кошка boobr-grappling-gun-desc = Для лёгкого перемещения вне станции. Меч со сменным лезвием не в комплекте. -boobr-medikit-name = продвинутая аптечка -boobr-medikit-desc = Продвинутый набор для оказания помощи при продвинутых ранах. +boobr-medikit-name = Продвинутая аптечка +boobr-medikit-desc = Продвинутый набор для оказания помощи при сильных ранах. -boobr-portable-recharger-name = переносной перезарядник -boobr-portable-recharger-desc = Переносной зарядник выделенный для своевременной зарядки в условиях боевых действий. +boobr-portable-recharger-name = Переносной зарядник +boobr-portable-recharger-desc = Переносной зарядник, выделенный для своевременной зарядки энергооружия в условиях боевых действий. -boobr-holo-projector-name = продвинутый голопроектор +boobr-holo-projector-name = Продвинутый голопроектор boobr-holo-projector-desc = Продвинутая версия обычного голопроектора, используемая для сдерживания угрозы или создания укреплений. + +boobr-m90-grenadelauncher-name = Подствольный гранатомёт GL90 +boobr-m90-grenadelauncher-desc = Один из наиболее распространенных подствольных гранатомётов, изначально разработанный для карабина M-90gl. Заряжается 40-мм выстрелами. + +boobr-m90-shotgun-name = Подствольный дробовик US90 +boobr-m90-shotgun-desc = Трехзарядный подствольный дробовик, изначально сделанный для карабина М-90gl. Прекрасно подходит для вышибания дверей или мозгов зомби. + +boobr-weapon-attachments-name = Набор оружейных модулей +boobr-weapon-attachments-desc = Кейс, в котором лежит лазерный целеуказатель, вертикальная рукоять, коллиматорный и оптический прицелы. + +boobr-weapon-attachments-antilying-name = Модуль коррекции огня +boobr-weapon-attachments-antilying-desc = Особо продвинутый модуль, позволяющий попадать даже в лежащих под укрытиями противников. + +boobr-weapon-attachments-suppressor-name = Глушитель +boobr-weapon-attachments-suppressor-desc = Устанавлаемый на ствол универсальный мультикалиберный глушитель. Существенно снижает звук от стрельбы и скрывает дульную вспышку. + +boobr-weapon-attachments-magneticharness-name = Магнитный ремень +boobr-weapon-attachments-magneticharness-description = Комплект из ремня и магнитных креплений, которые крепятся к верхней планке. В случае потери бойцом равновесия - оружие не падает на землю и остается с владельцем. diff --git a/Resources/Locale/ru-RU/ADT/prototypes/Catalog/store/uplink-catalog.ftl b/Resources/Locale/ru-RU/ADT/prototypes/Catalog/store/uplink-catalog.ftl index 6335277a276..a5e08dddd09 100644 --- a/Resources/Locale/ru-RU/ADT/prototypes/Catalog/store/uplink-catalog.ftl +++ b/Resources/Locale/ru-RU/ADT/prototypes/Catalog/store/uplink-catalog.ftl @@ -14,7 +14,7 @@ uplink-nukeopscloak-name = плащ Ядерных Оперативников uplink-nukeopscloak-desc = Защитит тебя от холода на базе. uplink-advanced-magboots = продвинутые магнитные ботинки синдиката -uplink-advanced-magboots-desc = Улучшенные магнитные ботинки синдиката. Собственность мародёров горлакса. +uplink-advanced-magboots-desc = Улучшенные магнитные ботинки синдиката. Собственность мародёров Горлакса. uplink-ADTHandDefibrillator-name = переносной дефибриллятор синдиката uplink-ADTHandDefibrillator-desc = Облегченная версия обычного дефибриллятора, более эффективен в лечении, но имеет больше сильный разряд. Можно надеть на шею. @@ -46,7 +46,7 @@ uplink-LightRifle-magazine-desc = Магазин с патронами кали # Bundles uplink-smokegrenade-bundle-name = набор дымовых гранат -uplink-smokegrenade-bundle-desc = Набор из 6 дымовых граната синдиката. Идеально подходят для кальянной вечеринки. +uplink-smokegrenade-bundle-desc = Набор из 6 дымовых граната Синдиката. Идеально подходят для кальянной вечеринки. uplink-C20-ammo-bundle-name = набор магазинов для С-20r uplink-C20-ammo-bundle-desc = Набор, содержащий 4 запасных магазина по цене 3. @@ -159,8 +159,30 @@ uplink-pirate-bullet-magnum-desc = Идеален для твоему револ uplink-pirate-lethal-shot-name = раздатчик ружейных патронов uplink-pirate-lethal-shot-desc = Полная коробка летальных ружейных патронов. +ADTuplink-grenade-launcher-bundle-name = РПГ-7 +ADTuplink-grenade-launcher-bundle-desc = Набор, содержащий в себе Ручной Противотанковый Гранатомет и 8 ракет для него! + +uplink-mask-name = Балаклава +uplink-mask-desc = Идеально, если вы террорист. + uplink-nukiesShield-name = двуручный штурмовой щит uplink-nukiesShield-desc = Массивный и опасный, двуручный щит из элитных материалов для лучшей защиты, имеет несколько рядов пластин, а также несколько шипов на основе щита. uplink-omnizinpizza-name = коробка с пиццей синдиката uplink-omnizinpizza-desc = Это коробка, с самой обычной пиццей внутри, это именно то, что используют элитные агенты для перекуса между стрельбой с капитаном, и кражей Иана. + + +uplink-attachmentsbundle-name = Набор оружейных модулей +uplink-attachmentsbundle-description = Комплект из вертикальной рукояти, лазерного целеуказателя, коллиматорного и оптического прицелов. + +uplink-lasersight-name = Лазерный целеуказатель +uplink-lasersight-description = Маломощный лазер, закрепляемый под оружием и позволяющий прицеливаться значительно быстрее, особенно с одной руки. + +uplink-attachments-antilying-name = Модуль коррекции огня +uplink-attachments-antilying-description = Особо продвинутый модуль, позволяющий попадать даже в лежащих под укрытиями противников. + +uplink-suppressor-name = Глушитель +uplink-suppressor-description = Устанавлаемый на ствол универсальный мультикалиберный глушитель. Существенно снижает звук от стрельбы и скрывает дульную вспышку. + +uplink-attachments-magneticharness-name = Магнитный ремень +uplink-attachments-magneticharness-description = Комплект из ремня и магнитных креплений, которые крепятся к верхней планке. В случае потери бойцом равновесия - оружие не падает на землю и остается с владельцем. diff --git a/Resources/Locale/ru-RU/ADT/prototypes/Entities/Clothing/Mask/mask.ftl b/Resources/Locale/ru-RU/ADT/prototypes/Entities/Clothing/Mask/mask.ftl index 1ec1b4542c8..ff0d7224ccf 100644 --- a/Resources/Locale/ru-RU/ADT/prototypes/Entities/Clothing/Mask/mask.ftl +++ b/Resources/Locale/ru-RU/ADT/prototypes/Entities/Clothing/Mask/mask.ftl @@ -64,4 +64,7 @@ ent-ADTPayDayWolfMask = маска клоуна Волка с Уолл-стри .desc = Одевая эту маску, вы почему то начинаете чувствовать разделение надвое и желание переворачивать маску совсем пропадает.. ent-ClothingMaskMadHeretic = маска бездны - .desc = Маска, созданная из страданий. Когда вы смотрите в ее глаза, она смотрит в ответ. \ No newline at end of file + .desc = Маска, созданная из страданий. Когда вы смотрите в ее глаза, она смотрит в ответ. + +ent-ADTMaskCoif = балаклава + .desc = Идеально, если вы террорист. diff --git a/Resources/Locale/ru-RU/ADT/prototypes/Entities/Clothing/Shoes/magboots.ftl b/Resources/Locale/ru-RU/ADT/prototypes/Entities/Clothing/Shoes/magboots.ftl new file mode 100644 index 00000000000..9f86824d2bf --- /dev/null +++ b/Resources/Locale/ru-RU/ADT/prototypes/Entities/Clothing/Shoes/magboots.ftl @@ -0,0 +1,2 @@ +ent-ADTClothingShoesBootsMagERT = магнитные сапоги ОБР + .desc = Продвинутые магнитные сапоги, специально разработанные для ведения боевых действий в космосе. Данная модель выдается бойцам отрядов ОБР. diff --git a/Resources/Locale/ru-RU/ADT/prototypes/Entities/Mobs/NPCs/creature.ftl b/Resources/Locale/ru-RU/ADT/prototypes/Entities/Mobs/NPCs/creatures.ftl similarity index 55% rename from Resources/Locale/ru-RU/ADT/prototypes/Entities/Mobs/NPCs/creature.ftl rename to Resources/Locale/ru-RU/ADT/prototypes/Entities/Mobs/NPCs/creatures.ftl index 2273a9ae49e..ac63f56de53 100644 --- a/Resources/Locale/ru-RU/ADT/prototypes/Entities/Mobs/NPCs/creature.ftl +++ b/Resources/Locale/ru-RU/ADT/prototypes/Entities/Mobs/NPCs/creatures.ftl @@ -1,2 +1,4 @@ ent-ADTMobCreature = существо .desc = Когда-то оно было человеком... +ent-ADTMobAngelCrying = плачущий ангел + .desc = Не моргай. diff --git a/Resources/Locale/ru-RU/ADT/prototypes/Entities/Objects/Device/binocular.ftl b/Resources/Locale/ru-RU/ADT/prototypes/Entities/Objects/Device/binocular.ftl new file mode 100644 index 00000000000..a1756d5e911 --- /dev/null +++ b/Resources/Locale/ru-RU/ADT/prototypes/Entities/Objects/Device/binocular.ftl @@ -0,0 +1,3 @@ +ent-ADTBinoculars = бинокль +.desc = Позволяет получше разглядеть противника, находящегося вдали. Или ту пару вульп в соседнем здании. +.suffix = { "ОСЩ" } diff --git a/Resources/Locale/ru-RU/ADT/prototypes/Entities/Objects/Specific/Mech/mechgun.ftl b/Resources/Locale/ru-RU/ADT/prototypes/Entities/Objects/Specific/Mech/mechgun.ftl index a1d483e76d3..9d379adb059 100644 --- a/Resources/Locale/ru-RU/ADT/prototypes/Entities/Objects/Specific/Mech/mechgun.ftl +++ b/Resources/Locale/ru-RU/ADT/prototypes/Entities/Objects/Specific/Mech/mechgun.ftl @@ -22,14 +22,14 @@ ent-ADTMechGunUltraAC2 = AC-2 "Ультра" ent-ADTMechGunMHAR21 = антиматериальная мех-винтовка mHAR-21 "Ma Deuce" .desc = Пушка под крайне разрушительный патрон .50 калибра. Равно хороша и против других мехов и иных бронированных целей, и против незащищенной агрессивной фауны. -ent-ADTMechGunSGL6 = гранатомет SGL-6 +ent-ADTMechGunSGL6 = гранатомёт SGL-6 .desc = Второе по популярности мех-оружие сил правопорядка - SGL-6. Запускает несколько светошумовых гранат и позволит в кратчайший срок вывести из боя любую группу преступников. Если они, конечно, не носят солнцезащитные очки. -ent-ADTMechGunSRM8 = ракетная установка SRM-8 +ent-ADTMechGunSRM8 = гранатомёт SRM-8 .desc = Пусковая установка для девяти 40-мм гранатометных выстрелов. -ent-ADTMechGunBRM6 = ракетная установка BRM-6 - .desc = Уменьшенный вариант пусковой установки SRM-8. Снаряжена 6 гранатометными выстрелами калибра 40 мм. +ent-ADTMechGunBRM6 = гранатомёт BRM-6 + .desc = Уменьшенный вариант пусковой установки SRM-8 для борьбы с беспорядками. Снаряжена 6 травматическими гранатометными выстрелами калибра 40 мм. ent-ADTMechGunFNX99Hades = мех-карабин FNX-99 "Аид" .desc = Пулемёт для меха под патрон 7.62 зажигательные. Лучше всего проявит себя против легковоспламенимых целей или красных бочек с топливом. diff --git a/Resources/Locale/ru-RU/ADT/prototypes/Entities/Objects/Specific/uplink_ert.ftl b/Resources/Locale/ru-RU/ADT/prototypes/Entities/Objects/Specific/uplink_ert.ftl new file mode 100644 index 00000000000..94e927d0d84 --- /dev/null +++ b/Resources/Locale/ru-RU/ADT/prototypes/Entities/Objects/Specific/uplink_ert.ftl @@ -0,0 +1,11 @@ +ent-ADTBaseUplinkBOBERT = Б.О.О.Б.Р. + .desc = Блюспейс-оружейная Отряда Быстрого Реагирования. + .suffix = 35 ЕТ + +ent-Productunit = торговая единица + .desc = Кажется, этот предмет пульсирует подозрительно притягательной энергией. + .suffix = 20 ЕТ + +ent-Productunit1 = торговая единица + .desc = Кажется, этот предмет пульсирует подозрительно притягательной энергией. + .suffix = 1 ЕТ diff --git a/Resources/Locale/ru-RU/ADT/prototypes/Entities/Objects/Weapons/Guns/Ammunition/Projectiles/projectiles.ftl b/Resources/Locale/ru-RU/ADT/prototypes/Entities/Objects/Weapons/Guns/Ammunition/Projectiles/projectiles.ftl index 201d95d9e23..86df664b194 100644 --- a/Resources/Locale/ru-RU/ADT/prototypes/Entities/Objects/Weapons/Guns/Ammunition/Projectiles/projectiles.ftl +++ b/Resources/Locale/ru-RU/ADT/prototypes/Entities/Objects/Weapons/Guns/Ammunition/Projectiles/projectiles.ftl @@ -1,3 +1,21 @@ ent-ADTBulletBibis = страйкбольный шарик .desc = Если ты увидел этот шарик в полете - ты пекуш бубиш шимбамбулеш. И выйди уже из матрицы. - .suffix = { "Страйкбол" } \ No newline at end of file + .suffix = { "Страйкбол" } + +ent-ADTBullet40mmGrenadeBaton = травматическая граната + .desc = { ent-BaseBullet.desc } + +ent-ADTBullet40mmGrenadeBlast = фугасная граната + .desc = { ent-BaseBullet.desc } + +ent-ADTBullet40mmGrenadeHEAT = кумулятивная граната + .desc = { ent-BaseBullet.desc } + +ent-ADTBullet40mmGrenadeEMP = ЭМИ граната + .desc = { ent-BaseBullet.desc } + +ent-ADTBullet40mmGrenadeFlash = светошумовая граната + .desc = { ent-BaseBullet.desc } + +ent-ADTBullet40mmGrenadeSmoke = дымовая граната + .desc = { ent-BaseBullet.desc } diff --git a/Resources/Locale/ru-RU/ADT/prototypes/Entities/Objects/Weapons/Guns/Ammunition/explosives.ftl b/Resources/Locale/ru-RU/ADT/prototypes/Entities/Objects/Weapons/Guns/Ammunition/explosives.ftl new file mode 100644 index 00000000000..2aeb335eac1 --- /dev/null +++ b/Resources/Locale/ru-RU/ADT/prototypes/Entities/Objects/Weapons/Guns/Ammunition/explosives.ftl @@ -0,0 +1,20 @@ +ent-ADTBase40mmGrenade = базовая 40-мм граната + .desc = Основа. + +ent-ADT40mmGrenadeBaton = травматическая 40-мм граната + .desc = Гранатометный выстрел нелетального действия. Гарантированно собъет с ног незащищенного противника. + +ent-ADT40mmGrenadeBlast = фугасная 40-мм граната + .desc = Фугасный гранатометный выстрел. + +ent-ADT40mmGrenadeHEAT = кумулятивная 40-мм граната + .desc = Гранатометный выстрел для разрушения структур и выведения из строя техники. Обладает слабым фугасным воздействием. + +ent-ADT40mmGrenadeEMP = ЭМИ 40-мм граната + .desc = Гранатометный выстрел, создающий при подрыве электромагнитный импульс, выводящий из строя электронику. + +ent-ADT40mmGrenadeFlash = светошумовая 40-мм граната + .desc = Гранатометный выстрел, ослепляющий и оглушающий свою цель. + +ent-ADT40mmGrenadeSmoke = дымовая 40-мм граната + .desc = Гранатометный выстрел, выпускающий при срабатывании облако дыма. diff --git a/Resources/Locale/ru-RU/ADT/prototypes/Entities/Objects/Weapons/Guns/Attachments.ftl b/Resources/Locale/ru-RU/ADT/prototypes/Entities/Objects/Weapons/Guns/Attachments.ftl new file mode 100644 index 00000000000..771def432d6 --- /dev/null +++ b/Resources/Locale/ru-RU/ADT/prototypes/Entities/Objects/Weapons/Guns/Attachments.ftl @@ -0,0 +1,39 @@ +ent-ADTAttachmentMagneticHarness = магнитный ремень +.desc = Комплект из ремня и магнитных креплений, которые крепятся к верхней планке. В случае потери бойцом равновесия - оружие не падает на землю и остается с владельцем. +.suffix = { "Оруж. модуль, Верхняя планка" } + +ent-ADTAttachmentHristovScope = прицел Христова +.desc = Штатный прицел для снайперской винтовки "Христов", с шестикратным увеличением. +.suffix = { "Оруж. модуль, Прицел" } + +ent-ADTAttachmentT2Miniscope = прицел T2 Miniscope +.desc = Оптический прицел малой кратности, подходящий для ведения боя в замкнутых пространствах. Производства Shellguard Munitions. +.suffix = { "Оруж. модуль, Прицел" } + +ent-ADTAttachmentM90GrenadeLauncher = подствольный гранатомёт GL90 +.desc = Один из наиболее распространенных подствольных гранатомётов, изначально разработанный для карабина M-90gl. Заряжается 40-мм выстрелами. +.suffix = { "Оруж. модуль, Подствольный" } + +ent-ADTAttachmentM90UnderbarrelShotgun = подствольный дробовик US90 +.desc = Трехзарядный подствольный дробовик, сделанный изначально для карабина М-90gl. Прекрасно подходит для вышибания дверей или мозгов зомби. +.suffix = { "Оруж. модуль, Подствольный" } + +ent-ADTAttachmentReflexSight = коллиматорный прицел Red Dot +.desc = Коллиматорный прицел, повышающий меткость стрельбы с одной руки и из неустойчивых положений. Производства Shellguard Munitions. +.suffix = { "Оруж. модуль, Прицел" } + +ent-ADTAttachmentVerticalGrip = вертикальная рукоять +.desc = Вертикальная рукоять, позволяющая при установке бойцу стрелять точнее. +.suffix = { "Оруж. модуль, Подствольный" } + +ent-ADTAttachmentLaserSight = лазерный целеуказатель +.desc = Устанавливаемый под ствол маленький лазер, позволяющий бойцу стрелять точнее даже без прицела и с одной руки. +.suffix = { "Оруж. модуль, Подствольный" } + +ent-ADTAttachmentSuppressor = глушитель +.desc = Устанавлаемый на ствол универсальный мультикалиберный глушитель. Существенно снижает звук от стрельбы и скрывает дульную вспышку. +.suffix = { "Оруж. модуль, Наствольный" } + +ent-ADTAttachmentAntiLyingWarrior = модуль коррекции огня +.desc = Особо продвинутый модуль со встроенными микро пИИ, анализирующим угрозы вокруг. С помощью электромагнита и магии блюспейс-технологий корректирует полет пули так, чтобы она точно попала в цель на своём пути, даже если она залегла под столом или в груде мусора. +.suffix = { "Оруж. модуль, Наствольный" } diff --git a/Resources/Locale/ru-RU/ADT/prototypes/Entities/Objects/Weapons/Melee/melee.ftl b/Resources/Locale/ru-RU/ADT/prototypes/Entities/Objects/Weapons/Melee/melee.ftl index ab0ce203d7e..087f0d3319f 100644 --- a/Resources/Locale/ru-RU/ADT/prototypes/Entities/Objects/Weapons/Melee/melee.ftl +++ b/Resources/Locale/ru-RU/ADT/prototypes/Entities/Objects/Weapons/Melee/melee.ftl @@ -30,6 +30,9 @@ ent-ADTJasonMachette = мачете Джейсона .suffix = Хеллоуин .desc = Мачете одного из самых ужасающих маньяков. Сбоку маленькая надпись "полиуретан". +ent-ADTMosinBayonet = штык от винтовки Мосина + .desc = Потому что раны от игольчатого штыка невозможно зашить... + ent-SpearReinforcedUran = копьё из закалённого урана .desc = Копьё, созданное из осколка закалённого урана, для более удобного убийства ваших оппонентов. diff --git a/Resources/Locale/ru-RU/ADT/prototypes/Entities/Structures/Decorations/statues.ftl b/Resources/Locale/ru-RU/ADT/prototypes/Entities/Structures/Decorations/statues.ftl index 26d08865026..4aa68131cd4 100644 --- a/Resources/Locale/ru-RU/ADT/prototypes/Entities/Structures/Decorations/statues.ftl +++ b/Resources/Locale/ru-RU/ADT/prototypes/Entities/Structures/Decorations/statues.ftl @@ -5,3 +5,7 @@ ent-ADTStatueBeerMessiahLeft = статуя пивного мессии ent-ADTStatueBeerMessiahRight = статуя пивного мессии .desc = Древняя гранитная статуя высшего существа, дарующего первым людям ПИВО .suffix = Октоберфест, Правая + +ent-ADTStatueCryingAngel = { ent-ADTMobAngelCrying } + .desc = { ent-ADTMobAngelCrying.desc } + .suffix = { "Статуя" } diff --git a/Resources/Locale/ru-RU/ADT/prototypes/Research/arsenal.ftl b/Resources/Locale/ru-RU/ADT/prototypes/Research/arsenal.ftl index 71f4a916310..012a3e29172 100644 --- a/Resources/Locale/ru-RU/ADT/prototypes/Research/arsenal.ftl +++ b/Resources/Locale/ru-RU/ADT/prototypes/Research/arsenal.ftl @@ -1 +1,3 @@ -research-technology-salvage-weapons-adv = Продвинутое оружие утилизаторов \ No newline at end of file +research-technology-salvage-weapons-adv = Продвинутое оружие утилизаторов +research-technology-modules-based = Базовые оружейные модули +research-technology-modules-extended = Продвинутые оружейные модули diff --git a/Resources/Locale/ru-RU/ADT/store/categories,ftl b/Resources/Locale/ru-RU/ADT/store/categories,ftl new file mode 100644 index 00000000000..808ff2f2886 --- /dev/null +++ b/Resources/Locale/ru-RU/ADT/store/categories,ftl @@ -0,0 +1,3 @@ +store-category-ert-weapon = Оружие +store-category-ert-other = Прочее +store-category-ert-attachment = Оруж. модули diff --git a/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/weapons/guns/ammunition/explosives.ftl b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/weapons/guns/ammunition/explosives.ftl index d7a6bc38422..9c1a20540ab 100644 --- a/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/weapons/guns/ammunition/explosives.ftl +++ b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/weapons/guns/ammunition/explosives.ftl @@ -2,17 +2,17 @@ ent-CartridgeRocket = выстрел ПГ-7ВЛ .desc = Выстрел для гранатомёта РПГ-7. Имеет форму трубы. ent-CartridgeRocketSlow = выстрел ПГ-7ВЛ "Улитка" .desc = Выстрел для гранатомёта РПГ-7. Необычайно медленная. -ent-BaseGrenade = базовая граната +ent-BaseGrenade = базовый снаряд .desc = { ent-BaseItem.desc } -ent-GrenadeBaton = шоковая граната +ent-GrenadeBaton = шоковый снаряд .desc = { ent-BaseGrenade.desc } -ent-GrenadeBlast = фугасная граната +ent-GrenadeBlast = фугасный снаряд .desc = { ent-BaseGrenade.desc } -ent-GrenadeFlash = светошумовая граната +ent-GrenadeFlash = светошумовой снаряд .desc = { ent-BaseGrenade.desc } -ent-GrenadeFrag = осколочная граната +ent-GrenadeFrag = осколочный снаряд .desc = { ent-BaseGrenade.desc } -ent-GrenadeEMP = ЭМИ граната +ent-GrenadeEMP = ЭМИ снаряд .desc = { ent-BaseGrenade.desc } ent-BaseCannonBall = базовое пушечное ядро .desc = { ent-BaseItem.desc } diff --git a/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/weapons/guns/ammunition/magazines/grenade.ftl b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/weapons/guns/ammunition/magazines/grenade.ftl index 79fe130a3a0..942de050093 100644 --- a/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/weapons/guns/ammunition/magazines/grenade.ftl +++ b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/weapons/guns/ammunition/magazines/grenade.ftl @@ -1,14 +1,14 @@ -ent-BaseMagazineGrenade = картридж гранат +ent-BaseMagazineGrenade = картридж снарядов .desc = { ent-BaseItem.desc } -ent-MagazineGrenadeEmpty = картридж гранат +ent-MagazineGrenadeEmpty = картридж снарядов .desc = { ent-BaseMagazineGrenade.desc } -ent-MagazineGrenadeFrag = картридж осколочных гранат +ent-MagazineGrenadeFrag = картридж осколочных снарядов .desc = { ent-BaseMagazineGrenade.desc } -ent-MagazineGrenadeEMP = картридж ЭМИ гранат +ent-MagazineGrenadeEMP = картридж ЭМИ снарядов .desc = { ent-BaseMagazineGrenade.desc } -ent-MagazineGrenadeFlash = картридж светошумовых гранат +ent-MagazineGrenadeFlash = картридж светошумовых снарядов .desc = { ent-BaseMagazineGrenade.desc } -ent-MagazineGrenadeBlast = картридж фугасных гранат +ent-MagazineGrenadeBlast = картридж фугасных снарядов .desc = { ent-BaseMagazineGrenade.desc } -ent-MagazineGrenadeBaton = картридж шоковых гранат +ent-MagazineGrenadeBaton = картридж шоковых снарядов .desc = { ent-BaseMagazineGrenade.desc } diff --git a/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/weapons/guns/projectiles/projectiles.ftl b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/weapons/guns/projectiles/projectiles.ftl index 6432f0e2ed7..0a59c0ae766 100644 --- a/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/weapons/guns/projectiles/projectiles.ftl +++ b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/weapons/guns/projectiles/projectiles.ftl @@ -52,13 +52,13 @@ ent-BulletRocket = ракета .desc = { ent-BaseBulletTrigger.desc } ent-BulletWeakRocket = слабая ракета .desc = { ent-BaseBulletTrigger.desc } -ent-BulletGrenadeBaton = шоковая граната +ent-BulletGrenadeBaton = шоковый снаряд .desc = { ent-BaseBullet.desc } -ent-BulletGrenadeBlast = фугасная граната +ent-BulletGrenadeBlast = фугасный снаряд .desc = { ent-BaseBulletTrigger.desc } -ent-BulletGrenadeFlash = светошумовая граната +ent-BulletGrenadeFlash = светошумовой снаряд .desc = { ent-BaseBulletTrigger.desc } -ent-BulletGrenadeFrag = осколочная граната +ent-BulletGrenadeFrag = осколочный снаряд .desc = { ent-BaseBulletTrigger.desc } ent-BulletGrenadeEMP = ЭМИ ракета .desc = { ent-BaseBulletTrigger.desc } diff --git a/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/weapons/guns/rifles/rifles.ftl b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/weapons/guns/rifles/rifles.ftl index 90a88612314..b355213e0e1 100644 --- a/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/weapons/guns/rifles/rifles.ftl +++ b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/weapons/guns/rifles/rifles.ftl @@ -4,7 +4,7 @@ ent-WeaponRifleAk = АКМС .desc = Культовое оружие всех войн. Использует патроны калибра 7.62х39 мм. .suffix = Автомат ent-WeaponRifleM90GrenadeLauncher = М-90gl - .desc = Карабин старой модели, выполненный по схеме булл-пап, с подствольным гранатомётом. Использует патроны калибра 6.5 мм ТСФ. + .desc = Карабин старой модели, выполненный по схеме булл-пап, с возможностью установки подствольного гранатомета. Использует патроны калибра 6.5 мм ТСФ. .suffix = Автомат ent-WeaponRifleLecter = Лектер .desc = Первоклассная армейская штурмовая винтовка. Использует патроны калибра 6.5 мм ТСФ. diff --git a/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/structures/shuttles/cannons.ftl b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/structures/shuttles/cannons.ftl index 1e08968401f..12d1fb74647 100644 --- a/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/structures/shuttles/cannons.ftl +++ b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/structures/shuttles/cannons.ftl @@ -7,10 +7,10 @@ ent-ShuttleGunPerforator = LSE-1200c "Перфоратор" .desc = Продвинутая стационарная лазерная установка. Уничтожает электроприборы и чрезвычайно опасна для здоровья! Для стрельбы использует энергоячейки. .suffix = НЕ МАППИТЬ ent-ShuttleGunFriendship = EXP-320g "Дружба" - .desc = Небольшой стационарный гранатомёт, вмещающий 2 гранаты. + .desc = Небольшое стационарное орудие, вмещающее два снаряда. .suffix = НЕ МАППИТЬ ent-ShuttleGunDuster = EXP-2100g "Дастер" - .desc = Мощный стационарный гранатомёт. Для стрельбы необходим картридж. + .desc = Мощное стационарное орудие. Для стрельбы необходим картридж. .suffix = НЕ МАППИТЬ ent-ShuttleGunPirateCannon = пушка пиратского корабля .desc = Кабум! diff --git a/Resources/Locale/ru-RU/store/categories.ftl b/Resources/Locale/ru-RU/store/categories.ftl index b18e8dd1ddc..e71f9441437 100644 --- a/Resources/Locale/ru-RU/store/categories.ftl +++ b/Resources/Locale/ru-RU/store/categories.ftl @@ -3,6 +3,7 @@ store-category-debug = debug category store-category-debug2 = debug category 2 store-category-weapons = Вооружение store-category-ammo = Боеприпасы +store-category-attachments = Оруж. модули store-category-explosives = Взрывчатка store-category-chemicals = Химикаты store-category-deception = Обман diff --git a/Resources/Maps/ADTMaps/ADTStations/NewYear/adt_frontier_newyear.yml b/Resources/Maps/ADTMaps/ADTStations/NewYear/adt_frontier_newyear.yml index 6dde8f905ba..7a42f06f296 100644 --- a/Resources/Maps/ADTMaps/ADTStations/NewYear/adt_frontier_newyear.yml +++ b/Resources/Maps/ADTMaps/ADTStations/NewYear/adt_frontier_newyear.yml @@ -12273,53 +12273,6 @@ entities: - type: Transform pos: 84.33081,-25.646828 parent: 2 -- proto: ADTPresentRandomInsaneSyndicate - entities: - - uid: 9102 - components: - - type: Transform - pos: 70.218094,-29.381462 - parent: 2 - - uid: 13019 - components: - - type: Transform - pos: 131.06863,-9.552916 - parent: 2 - - uid: 25392 - components: - - type: Transform - pos: 36.84481,-19.3418 - parent: 2 - - uid: 25425 - components: - - type: Transform - pos: 99.428696,3.47149 - parent: 2 - - uid: 25466 - components: - - type: Transform - pos: 127.16864,-0.7699356 - parent: 2 - - uid: 25647 - components: - - type: Transform - pos: 83.56486,-24.476616 - parent: 2 - - uid: 25814 - components: - - type: Transform - pos: 170.89455,20.539421 - parent: 2 - - uid: 25815 - components: - - type: Transform - pos: 170.21368,20.475594 - parent: 2 - - uid: 25996 - components: - - type: Transform - pos: 180.45126,25.427273 - parent: 2 - proto: ADTPresentRandomPurple entities: - uid: 9868 diff --git a/Resources/Maps/ADTMaps/Ghostbars/calm_ghostly_bar.yml b/Resources/Maps/ADTMaps/Ghostbars/calm_ghostly_bar.yml new file mode 100644 index 00000000000..fbb89f3fb73 --- /dev/null +++ b/Resources/Maps/ADTMaps/Ghostbars/calm_ghostly_bar.yml @@ -0,0 +1,11520 @@ +meta: + format: 6 + postmapinit: false +tilemap: + 0: Space + 1: ADTFloorBlackOrange + 7: FloorArcadeBlue + 9: FloorArcadeRed + 4: FloorAstroIce + 3: FloorAstroSnow + 25: FloorBoxing + 28: FloorBrokenWood + 30: FloorCarpetOffice + 2: FloorDesert + 56: FloorFreezer + 65: FloorGrayConcreteOutside + 66: FloorGrayConcreteOutsideMono + 67: FloorGrayConcreteOutsideSmooth + 73: FloorHydro + 76: FloorKitchen + 78: FloorLino + 88: FloorOldConcrete + 91: FloorOldConcreteOutsideMono + 95: FloorPlanetGrass + 5: FloorRGlass + 101: FloorShowroom + 102: FloorShuttleBlack + 105: FloorShuttleOrange + 106: FloorShuttlePurple + 107: FloorShuttleRed + 114: FloorSteelCheckerDark + 127: FloorTechMaint + 141: FloorWood + 143: FloorWoodChess + 145: FloorWoodChessDark + 146: FloorWoodChessLight + 155: FloorWoodParquet + 158: FloorWoodParquetLight + 162: Lattice + 163: Plating +entities: +- proto: "" + entities: + - uid: 1 + components: + - type: MetaData + name: Map Entity + - type: Transform + - type: Map + mapPaused: True + - type: PhysicsMap + - type: GridTree + - type: MovedGrids + - type: Broadphase + - type: OccluderTree + - type: LoadedMap + - uid: 2 + components: + - type: MetaData + name: grid + - type: Transform + pos: -1.8297873,0.7446809 + parent: 1 + - type: MapGrid + chunks: + 0,0: + ind: 0,0 + tiles: ngAAAAAAkgAAAAAAngAAAAAAkgAAAAAAngAAAAAAowAAAAAAQQAAAAAAQQAAAAAAWwAAAAAAWAAAAAAAWAAAAAAAWAAAAAAAWAAAAAAAWAAAAAAAWAAAAAAAowAAAAAAkgAAAAAAngAAAAAAkgAAAAAAngAAAAAAkgAAAAAAowAAAAAAQQAAAAAAQQAAAAAAWwAAAAAAWAAAAAAAWAAAAAAAWAAAAAAAWAAAAAAAWAAAAAAAWAAAAAAAowAAAAAAowAAAAAAowAAAAAAkgAAAAAAowAAAAAAowAAAAAAowAAAAAAQgAAAAAAQgAAAAAAowAAAAAAowAAAAAAowAAAAAAWwAAAAAAWwAAAAAAowAAAAAAowAAAAAAowAAAAAAjwAAAAAAjwAAAAAAjwAAAAAAjwAAAAAAjwAAAAAAjwAAAAAAjwAAAAAAjwAAAAAAowAAAAAATAAAAAAATAAAAAAATAAAAAAATAAAAAAATAAAAAAAowAAAAAAogAAAAAAjwAAAAAAjwAAAAAAjwAAAAAAjwAAAAAAjwAAAAAAjwAAAAAAjwAAAAAAjwAAAAAAQgAAAAAATAAAAAAATAAAAAAATAAAAAAATAAAAAAATAAAAAAAowAAAAAAogAAAAAAjwAAAAAAjwAAAAAABQAAAAAAjwAAAAAAjwAAAAAAjwAAAAAABQAAAAAAjwAAAAAAowAAAAAATAAAAAAATAAAAAAATAAAAAAATAAAAAAATAAAAAAAowAAAAAAogAAAAAAjwAAAAAAjwAAAAAABQAAAAAAjwAAAAAAjwAAAAAABQAAAAAABQAAAAAAjwAAAAAAQgAAAAAATAAAAAAATAAAAAAATAAAAAAATAAAAAAATAAAAAAAowAAAAAAogAAAAAAjwAAAAAAjwAAAAAABQAAAAAAjwAAAAAAjwAAAAAAjwAAAAAAjwAAAAAAjwAAAAAAQgAAAAAATAAAAAAATAAAAAAATAAAAAAATAAAAAAATAAAAAAAowAAAAAAogAAAAAAjwAAAAAAjwAAAAAAjwAAAAAAjwAAAAAAjwAAAAAAjwAAAAAAjwAAAAAAjwAAAAAAowAAAAAATAAAAAAATAAAAAAATAAAAAAATAAAAAAATAAAAAAAowAAAAAAogAAAAAAmwAAAAAAmwAAAAAAmwAAAAAAmwAAAAAAmwAAAAAAmwAAAAAAowAAAAAAowAAAAAAowAAAAAAOAAAAAAAOAAAAAAAowAAAAAAowAAAAAAowAAAAAAowAAAAAAogAAAAAAmwAAAAAAmwAAAAAAmwAAAAAAmwAAAAAAmwAAAAAAmwAAAAAAowAAAAAAowAAAAAAowAAAAAAOAAAAAAAOAAAAAAAowAAAAAAowAAAAAAowAAAAAAogAAAAAAogAAAAAAmwAAAAAAmwAAAAAAmwAAAAAAmwAAAAAAmwAAAAAAmwAAAAAAowAAAAAAowAAAAAAOAAAAAAAOAAAAAAAOAAAAAAAOAAAAAAAowAAAAAAowAAAAAAogAAAAAAAAAAAAAAmwAAAAAAmwAAAAAAmwAAAAAAmwAAAAAAmwAAAAAAmwAAAAAAowAAAAAAowAAAAAAOAAAAAAAOAAAAAAAOAAAAAAAOAAAAAAAowAAAAAAowAAAAAAogAAAAAAAAAAAAAAowAAAAAAowAAAAAAowAAAAAAowAAAAAAowAAAAAAowAAAAAAowAAAAAAowAAAAAAOAAAAAAAOAAAAAAAOAAAAAAAOAAAAAAAowAAAAAAowAAAAAAogAAAAAAAAAAAAAAogAAAAAAogAAAAAAogAAAAAAogAAAAAAogAAAAAAogAAAAAAowAAAAAAowAAAAAAowAAAAAAowAAAAAAowAAAAAAowAAAAAAowAAAAAAowAAAAAAogAAAAAAAAAAAAAAogAAAAAAogAAAAAAogAAAAAAogAAAAAAogAAAAAAogAAAAAAowAAAAAAowAAAAAAowAAAAAAowAAAAAAowAAAAAAowAAAAAAowAAAAAAowAAAAAAogAAAAAAAAAAAAAA + version: 6 + -1,0: + ind: -1,0 + tiles: AAAAAAAAAAAAAAAAogAAAAAAogAAAAAAowAAAAAAowAAAAAAawAAAAAAawAAAAAAHgAAAAAAHgAAAAAAkQAAAAAAkQAAAAAAkQAAAAAAQQAAAAAAQQAAAAAAowAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAogAAAAAAogAAAAAAowAAAAAAawAAAAAAawAAAAAAHgAAAAAAHgAAAAAAkQAAAAAAkQAAAAAAkQAAAAAAQQAAAAAAQQAAAAAAowAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAogAAAAAAowAAAAAAowAAAAAAowAAAAAAowAAAAAAowAAAAAAowAAAAAAowAAAAAAowAAAAAAQgAAAAAAQgAAAAAAowAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAogAAAAAAogAAAAAAowAAAAAATgAAAAAATgAAAAAATgAAAAAATgAAAAAATgAAAAAAowAAAAAAjwAAAAAAjwAAAAAAjwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAogAAAAAAowAAAAAATgAAAAAATgAAAAAATgAAAAAATgAAAAAATgAAAAAATgAAAAAAjwAAAAAAjwAAAAAAjwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAogAAAAAAowAAAAAATgAAAAAATgAAAAAATgAAAAAATgAAAAAATgAAAAAATgAAAAAAjwAAAAAABQAAAAAAjwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAogAAAAAAowAAAAAATgAAAAAATgAAAAAATgAAAAAATgAAAAAATgAAAAAATgAAAAAAjwAAAAAABQAAAAAABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAogAAAAAAowAAAAAATgAAAAAATgAAAAAATgAAAAAATgAAAAAATgAAAAAATgAAAAAAjwAAAAAAjwAAAAAAjwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAogAAAAAAowAAAAAATgAAAAAATgAAAAAATgAAAAAATgAAAAAATgAAAAAAowAAAAAAjwAAAAAAjwAAAAAAjwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAogAAAAAAowAAAAAAowAAAAAAowAAAAAAowAAAAAAowAAAAAAowAAAAAAowAAAAAATgAAAAAAowAAAAAAmwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAogAAAAAAogAAAAAAowAAAAAATgAAAAAATgAAAAAATgAAAAAATgAAAAAATgAAAAAATgAAAAAAowAAAAAAmwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAogAAAAAAowAAAAAATgAAAAAATgAAAAAATgAAAAAATgAAAAAATgAAAAAATgAAAAAAowAAAAAAmwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAogAAAAAAowAAAAAACQAAAAAACQAAAAAACQAAAAAABwAAAAAABwAAAAAABwAAAAAAowAAAAAAmwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAogAAAAAAowAAAAAACQAAAAAACQAAAAAACQAAAAAABwAAAAAABwAAAAAABwAAAAAAowAAAAAAowAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAogAAAAAAowAAAAAACQAAAAAACQAAAAAACQAAAAAABwAAAAAABwAAAAAABwAAAAAAowAAAAAAogAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAogAAAAAAowAAAAAAowAAAAAAowAAAAAAowAAAAAAowAAAAAAowAAAAAAowAAAAAAowAAAAAAogAAAAAA + version: 6 + -1,-1: + ind: -1,-1 + tiles: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAogAAAAAAowAAAAAAZgAAAAAAagAAAAAAZgAAAAAAQgAAAAAAQQAAAAAAQQAAAAAAowAAAAAAcgAAAAAAcgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAogAAAAAAowAAAAAAagAAAAAAZgAAAAAAagAAAAAAowAAAAAAQQAAAAAAQQAAAAAAowAAAAAAcgAAAAAAcgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAogAAAAAAowAAAAAAowAAAAAAowAAAAAAowAAAAAAowAAAAAAQQAAAAAAQQAAAAAAowAAAAAAcgAAAAAAcgAAAAAAogAAAAAAogAAAAAAogAAAAAAogAAAAAAogAAAAAAogAAAAAAogAAAAAAogAAAAAAogAAAAAAowAAAAAAQwAAAAAAQwAAAAAAQwAAAAAAQwAAAAAAQwAAAAAAQwAAAAAAowAAAAAAowAAAAAAowAAAAAAogAAAAAAogAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAogAAAAAAowAAAAAAQwAAAAAAQwAAAAAAQwAAAAAAQwAAAAAAQwAAAAAAQwAAAAAAAgAAAAAAAgAAAAAAowAAAAAAowAAAAAAogAAAAAAogAAAAAAogAAAAAAogAAAAAAogAAAAAAowAAAAAAQwAAAAAAQwAAAAAAQwAAAAAAAwAAAAAAAwAAAAAAAwAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAowAAAAAAowAAAAAAowAAAAAAowAAAAAAowAAAAAAowAAAAAAowAAAAAAQwAAAAAAQwAAAAAAAwAAAAAAAwAAAAAAAwAAAAAAAwAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAowAAAAAAQQAAAAAAQQAAAAAAQQAAAAAAQQAAAAAAQQAAAAAAQwAAAAAAQwAAAAAAAwAAAAAAAwAAAAAAAwAAAAAAAwAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAQgAAAAAAQQAAAAAAQQAAAAAAQQAAAAAAQQAAAAAAQQAAAAAAQwAAAAAAQwAAAAAAAwAAAAAAAwAAAAAAAwAAAAAAAwAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAowAAAAAAQQAAAAAAQQAAAAAAQQAAAAAAQQAAAAAAQQAAAAAAQwAAAAAAQwAAAAAAAwAAAAAAAwAAAAAAAwAAAAAAAwAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAowAAAAAAowAAAAAAowAAAAAAowAAAAAAowAAAAAAowAAAAAAowAAAAAAQwAAAAAAQwAAAAAAAwAAAAAAAwAAAAAAAwAAAAAAAwAAAAAAAgAAAAAAAgAAAAAAowAAAAAAowAAAAAASQAAAAAASQAAAAAAkQAAAAAAAQAAAAAAAQAAAAAAowAAAAAAQwAAAAAAQwAAAAAAQwAAAAAAAwAAAAAAAwAAAAAAAwAAAAAAowAAAAAAowAAAAAAowAAAAAAowAAAAAASQAAAAAASQAAAAAAkQAAAAAAAQAAAAAAAQAAAAAAowAAAAAAQwAAAAAAQwAAAAAAQwAAAAAAQwAAAAAAAwAAAAAAAwAAAAAAogAAAAAAogAAAAAAogAAAAAAowAAAAAAZQAAAAAAZQAAAAAAkQAAAAAAkQAAAAAAkQAAAAAAowAAAAAAowAAAAAAQwAAAAAAQwAAAAAAQwAAAAAAQwAAAAAAowAAAAAAAAAAAAAAAAAAAAAAogAAAAAAowAAAAAAZQAAAAAAZQAAAAAAkQAAAAAAkQAAAAAAkQAAAAAAkQAAAAAAowAAAAAAowAAAAAAQwAAAAAAQwAAAAAAQwAAAAAAowAAAAAAAAAAAAAAAAAAAAAAogAAAAAAowAAAAAAowAAAAAAkQAAAAAAkQAAAAAAkQAAAAAAkQAAAAAAkQAAAAAAkQAAAAAAowAAAAAAowAAAAAAQQAAAAAAQQAAAAAAowAAAAAA + version: 6 + 0,-1: + ind: 0,-1 + tiles: GQAAAAAAGQAAAAAAGQAAAAAAGQAAAAAAGQAAAAAAcgAAAAAAcgAAAAAAowAAAAAAQQAAAAAAQQAAAAAAjQAAAAAAjQAAAAAAjQAAAAAAjQAAAAAAowAAAAAAogAAAAAAcgAAAAAAcgAAAAAAcgAAAAAAcgAAAAAAcgAAAAAAcgAAAAAAcgAAAAAAowAAAAAAQQAAAAAAQQAAAAAAowAAAAAAjQAAAAAAjQAAAAAAjQAAAAAAowAAAAAAogAAAAAAcgAAAAAAcgAAAAAAcgAAAAAAcgAAAAAAcgAAAAAAcgAAAAAAcgAAAAAAowAAAAAAQQAAAAAAQQAAAAAAowAAAAAAowAAAAAAowAAAAAAowAAAAAAowAAAAAAogAAAAAAQwAAAAAAQwAAAAAAQwAAAAAAQwAAAAAAQwAAAAAAQwAAAAAAQwAAAAAAQwAAAAAAQwAAAAAAQwAAAAAAQwAAAAAAowAAAAAAogAAAAAAogAAAAAAogAAAAAAogAAAAAAQwAAAAAAQwAAAAAAQwAAAAAAQwAAAAAAQwAAAAAAQwAAAAAAQwAAAAAAQwAAAAAAQwAAAAAAQwAAAAAAQwAAAAAAowAAAAAAogAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAAAAwAAAAAAAwAAAAAAAwAAAAAAAwAAAAAAAwAAAAAAAwAAAAAAAwAAAAAAQwAAAAAAQwAAAAAAQwAAAAAAowAAAAAAogAAAAAAogAAAAAAogAAAAAAogAAAAAAAwAAAAAAAwAAAAAAAwAAAAAAAwAAAAAAAwAAAAAAAwAAAAAAAwAAAAAAAwAAAAAAAwAAAAAAQwAAAAAAQwAAAAAAowAAAAAAowAAAAAAowAAAAAAowAAAAAAowAAAAAAAwAAAAAAAwAAAAAAAwAAAAAAAwAAAAAAAwAAAAAAAwAAAAAABAAAAAAABAAAAAAAAwAAAAAAQwAAAAAAQwAAAAAAQQAAAAAAQQAAAAAAQQAAAAAAQQAAAAAAQQAAAAAAAwAAAAAAAwAAAAAAAwAAAAAAAwAAAAAAAwAAAAAABAAAAAAABAAAAAAABAAAAAAAAwAAAAAAQwAAAAAAQwAAAAAAQQAAAAAAQQAAAAAAQQAAAAAAQQAAAAAAQQAAAAAAAwAAAAAAAwAAAAAAAwAAAAAAAwAAAAAABAAAAAAABAAAAAAABAAAAAAABAAAAAAAAwAAAAAAQwAAAAAAQwAAAAAAQQAAAAAAQQAAAAAAQQAAAAAAQQAAAAAAQQAAAAAAAwAAAAAAAwAAAAAAAwAAAAAAAwAAAAAABAAAAAAABAAAAAAABAAAAAAAAwAAAAAAAwAAAAAAQwAAAAAAQwAAAAAAowAAAAAAowAAAAAAowAAAAAAowAAAAAAowAAAAAAAwAAAAAAAwAAAAAAAwAAAAAAAwAAAAAAAwAAAAAABAAAAAAAAwAAAAAAAwAAAAAAQwAAAAAAQwAAAAAAQwAAAAAAowAAAAAASQAAAAAASQAAAAAASQAAAAAASQAAAAAAAwAAAAAAAwAAAAAAAwAAAAAAAwAAAAAAAwAAAAAAAwAAAAAAAwAAAAAAQwAAAAAAQwAAAAAAQwAAAAAAQwAAAAAAowAAAAAASQAAAAAAWAAAAAAAWAAAAAAAWAAAAAAAowAAAAAAowAAAAAAowAAAAAAowAAAAAAowAAAAAAowAAAAAAQwAAAAAAQwAAAAAAQwAAAAAAQwAAAAAAowAAAAAAowAAAAAASQAAAAAAWAAAAAAAWAAAAAAAWAAAAAAAngAAAAAAkgAAAAAAngAAAAAAkgAAAAAAngAAAAAAowAAAAAAQwAAAAAAQwAAAAAAQwAAAAAAowAAAAAAowAAAAAAWAAAAAAAWAAAAAAAWAAAAAAAWAAAAAAASQAAAAAAkgAAAAAAngAAAAAAkgAAAAAAngAAAAAAkgAAAAAAowAAAAAAQQAAAAAAQQAAAAAAowAAAAAAowAAAAAAWAAAAAAAWAAAAAAAWAAAAAAAWAAAAAAAWAAAAAAASQAAAAAA + version: 6 + 1,-1: + ind: 1,-1 + tiles: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAogAAAAAAogAAAAAAogAAAAAAogAAAAAAogAAAAAAogAAAAAAogAAAAAAogAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAogAAAAAAogAAAAAAowAAAAAAowAAAAAAowAAAAAAowAAAAAAowAAAAAAogAAAAAAogAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAogAAAAAAowAAAAAAowAAAAAAjQAAAAAAjQAAAAAAHAAAAAAAowAAAAAAowAAAAAAogAAAAAAogAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAowAAAAAAowAAAAAAHAAAAAAAjQAAAAAAjQAAAAAAjQAAAAAAjQAAAAAAowAAAAAAowAAAAAAogAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAowAAAAAAjQAAAAAAjQAAAAAAjQAAAAAAjQAAAAAAjQAAAAAAjQAAAAAAHAAAAAAAowAAAAAAogAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQgAAAAAAjQAAAAAAjQAAAAAAjQAAAAAAHAAAAAAAjQAAAAAAjQAAAAAAjQAAAAAAowAAAAAAogAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAowAAAAAAjQAAAAAAjQAAAAAAjQAAAAAAjQAAAAAAjQAAAAAAjQAAAAAAjQAAAAAAowAAAAAAogAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAowAAAAAAowAAAAAAjQAAAAAAjQAAAAAAjQAAAAAAjQAAAAAAjQAAAAAAowAAAAAAowAAAAAAogAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAASQAAAAAAowAAAAAAowAAAAAAjQAAAAAAHAAAAAAAjQAAAAAAowAAAAAAowAAAAAAogAAAAAAogAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAASQAAAAAAowAAAAAAowAAAAAAowAAAAAAowAAAAAAowAAAAAAowAAAAAAogAAAAAAogAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAASQAAAAAAowAAAAAAogAAAAAAogAAAAAAogAAAAAAogAAAAAAogAAAAAAogAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAASQAAAAAAowAAAAAAogAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAowAAAAAAowAAAAAAogAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + version: 6 + -2,-1: + ind: -2,-1 + tiles: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAogAAAAAAogAAAAAAogAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAogAAAAAAogAAAAAAowAAAAAAowAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAogAAAAAAogAAAAAAowAAAAAAowAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAogAAAAAAowAAAAAAowAAAAAAAgAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAogAAAAAAowAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAogAAAAAAowAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAogAAAAAAowAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAogAAAAAAowAAAAAAowAAAAAAAgAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAogAAAAAAogAAAAAAowAAAAAAowAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAogAAAAAAogAAAAAAowAAAAAAowAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAogAAAAAAogAAAAAAogAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + version: 6 + -1,1: + ind: -1,1 + tiles: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAogAAAAAAogAAAAAAogAAAAAAogAAAAAAogAAAAAAogAAAAAAogAAAAAAogAAAAAAogAAAAAAogAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAogAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + version: 6 + 0,1: + ind: 0,1 + tiles: ogAAAAAAogAAAAAAogAAAAAAogAAAAAAogAAAAAAogAAAAAAogAAAAAAogAAAAAAogAAAAAAogAAAAAAogAAAAAAogAAAAAAogAAAAAAogAAAAAAogAAAAAAAAAAAAAAogAAAAAAogAAAAAAogAAAAAAogAAAAAAogAAAAAAogAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + version: 6 + 1,0: + ind: 1,0 + tiles: owAAAAAAogAAAAAAogAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAogAAAAAAogAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAogAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAogAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + version: 6 + -1,-2: + ind: -1,-2 + tiles: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAogAAAAAAogAAAAAAogAAAAAAogAAAAAAogAAAAAAogAAAAAAogAAAAAAogAAAAAAogAAAAAAogAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAogAAAAAAowAAAAAAowAAAAAAowAAAAAAowAAAAAAowAAAAAAowAAAAAAowAAAAAAowAAAAAAogAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAogAAAAAAowAAAAAAfwAAAAAAfwAAAAAAfwAAAAAAfwAAAAAAfwAAAAAAfwAAAAAAowAAAAAAogAAAAAAogAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAogAAAAAAowAAAAAAfwAAAAAAfwAAAAAAfwAAAAAAfwAAAAAAfwAAAAAAfwAAAAAAowAAAAAAAAAAAAAAowAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAogAAAAAAowAAAAAAfwAAAAAAfwAAAAAAfwAAAAAAfwAAAAAAfwAAAAAAfwAAAAAAowAAAAAAowAAAAAAowAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAogAAAAAAowAAAAAAfwAAAAAAfwAAAAAAfwAAAAAAfwAAAAAAfwAAAAAAfwAAAAAAowAAAAAAcgAAAAAAcgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAogAAAAAAowAAAAAAaQAAAAAAaQAAAAAAaQAAAAAAfwAAAAAAfwAAAAAAfwAAAAAAowAAAAAAcgAAAAAAcgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAogAAAAAAowAAAAAAaQAAAAAAaQAAAAAAaQAAAAAAfwAAAAAAfwAAAAAAfwAAAAAAowAAAAAAcgAAAAAAcgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAogAAAAAAowAAAAAAowAAAAAAowAAAAAAowAAAAAAowAAAAAAowAAAAAAowAAAAAAowAAAAAAcgAAAAAAcgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAogAAAAAAowAAAAAAagAAAAAAZgAAAAAAagAAAAAAowAAAAAAQQAAAAAAQQAAAAAAowAAAAAAcgAAAAAAcgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAogAAAAAAowAAAAAAZgAAAAAAagAAAAAAZgAAAAAAowAAAAAAQQAAAAAAQQAAAAAAowAAAAAAcgAAAAAAcgAAAAAA + version: 6 + 0,-2: + ind: 0,-2 + tiles: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAogAAAAAAogAAAAAAogAAAAAAogAAAAAAogAAAAAAogAAAAAAogAAAAAAogAAAAAAogAAAAAAogAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAogAAAAAAowAAAAAAowAAAAAAowAAAAAAowAAAAAAowAAAAAAowAAAAAAowAAAAAAowAAAAAAogAAAAAAogAAAAAAogAAAAAAogAAAAAAogAAAAAAogAAAAAAogAAAAAAogAAAAAAowAAAAAAQQAAAAAAQQAAAAAAowAAAAAAjQAAAAAAjQAAAAAAjQAAAAAAowAAAAAAogAAAAAAowAAAAAAowAAAAAAowAAAAAAowAAAAAAowAAAAAAowAAAAAAAAAAAAAAowAAAAAAQQAAAAAAQQAAAAAAjQAAAAAAjQAAAAAAjQAAAAAAjQAAAAAAowAAAAAAogAAAAAAcgAAAAAAcgAAAAAAcgAAAAAAcgAAAAAAcgAAAAAAowAAAAAAowAAAAAAowAAAAAAQQAAAAAAQQAAAAAAowAAAAAAjQAAAAAAjQAAAAAAjQAAAAAAowAAAAAAogAAAAAAcgAAAAAAcgAAAAAAcgAAAAAAcgAAAAAAcgAAAAAAcgAAAAAAcgAAAAAAowAAAAAAQQAAAAAAQQAAAAAAowAAAAAAowAAAAAAowAAAAAAowAAAAAAowAAAAAAogAAAAAAcgAAAAAAcgAAAAAAcgAAAAAAcgAAAAAAcgAAAAAAcgAAAAAAcgAAAAAAowAAAAAAQQAAAAAAQQAAAAAAowAAAAAAjQAAAAAAjQAAAAAAjQAAAAAAowAAAAAAogAAAAAAGQAAAAAAGQAAAAAAGQAAAAAAGQAAAAAAGQAAAAAAcgAAAAAAcgAAAAAAowAAAAAAQQAAAAAAQQAAAAAAjQAAAAAAjQAAAAAAjQAAAAAAjQAAAAAAowAAAAAAogAAAAAAGQAAAAAAGQAAAAAAGQAAAAAAGQAAAAAAGQAAAAAAcgAAAAAAcgAAAAAAowAAAAAAQQAAAAAAQQAAAAAAowAAAAAAjQAAAAAAjQAAAAAAjQAAAAAAowAAAAAAogAAAAAAGQAAAAAAGQAAAAAAGQAAAAAAGQAAAAAAGQAAAAAAcgAAAAAAcgAAAAAAowAAAAAAQQAAAAAAQQAAAAAAowAAAAAAowAAAAAAowAAAAAAowAAAAAAowAAAAAAogAAAAAAGQAAAAAAGQAAAAAAGQAAAAAAGQAAAAAAGQAAAAAAcgAAAAAAcgAAAAAAowAAAAAAQQAAAAAAQQAAAAAAowAAAAAAjQAAAAAAjQAAAAAAjQAAAAAAowAAAAAAogAAAAAA + version: 6 + - type: Broadphase + - type: Physics + bodyStatus: InAir + angularDamping: 0.05 + linearDamping: 0.05 + fixedRotation: False + bodyType: Dynamic + - type: Fixtures + fixtures: {} + - type: OccluderTree + - type: SpreaderGrid + - type: Shuttle + - type: GridPathfinding + - type: Gravity + gravityShakeSound: !type:SoundPathSpecifier + path: /Audio/Effects/alert.ogg + - type: DecalGrid + chunkCollection: + version: 2 + nodes: + - node: + color: '#FFFFFFFF' + id: Basalt1 + decals: + 355: 7.7978497,-1.831774 + - node: + color: '#FFFFFFFF' + id: Basalt2 + decals: + 361: -15.931272,-4.9955482 + - node: + color: '#FFFFFFFF' + id: Basalt3 + decals: + 362: -14.995103,-11.000111 + - node: + color: '#FFFFFFFF' + id: Basalt4 + decals: + 356: 9.9237,-4.8672924 + - node: + color: '#FFFFFFFF' + id: Basalt6 + decals: + 363: -13.066024,-8.817713 + - node: + color: '#FFFFFFFF' + id: Basalt7 + decals: + 364: -13.846166,-6.003291 + - node: + color: '#FFFFFFFF' + id: Basalt9 + decals: + 357: -4.602407,-11.103701 + - node: + color: '#FFFFFFFF' + id: BrickTileDarkCornerNe + decals: + 249: 13,8 + - node: + color: '#FFFFFFFF' + id: BrickTileDarkCornerSe + decals: + 101: 6,-22 + 239: 13,3 + 255: 13,3 + - node: + color: '#FFFFFFFF' + id: BrickTileDarkCornerSw + decals: + 84: -2,-22 + 240: 9,3 + - node: + color: '#FFFFFFFF' + id: BrickTileDarkInnerNw + decals: + 245: 9,4 + - node: + color: '#FFFFFFFF' + id: BrickTileDarkInnerSe + decals: + 256: 12,3 + - node: + color: '#FFFFFFFF' + id: BrickTileDarkInnerSw + decals: + 246: 9,4 + 257: 12,3 + - node: + color: '#FFFFFFFF' + id: BrickTileDarkLineE + decals: + 93: 6,-21 + 94: 6,-20 + 95: 6,-18 + 96: 6,-19 + 97: 6,-17 + 98: 6,-16 + 99: 6,-15 + 100: 6,-14 + 251: 13,7 + 252: 13,6 + 253: 13,5 + 254: 13,4 + - node: + color: '#FFFFFFFF' + id: BrickTileDarkLineN + decals: + 247: 11,8 + 248: 12,8 + - node: + color: '#FFFFFFFF' + id: BrickTileDarkLineS + decals: + 85: -1,-22 + 86: 0,-22 + 87: 1,-22 + 88: 2,-22 + 89: 3,-22 + 90: 4,-22 + 91: 5,-22 + 258: 11,3 + 259: 10,3 + - node: + color: '#FFFFFFFF' + id: BrickTileDarkLineW + decals: + 76: -2,-14 + 77: -2,-15 + 78: -2,-16 + 79: -2,-18 + 80: -2,-17 + 81: -2,-19 + 82: -2,-20 + 83: -2,-21 + 241: 9,8 + 242: 9,7 + 244: 9,5 + 260: 9,6 + - node: + color: '#D58C18FF' + id: ConcreteTrimCornerNe + decals: + 331: -4,-20 + - node: + color: '#FFFFFFFF' + id: ConcreteTrimCornerNe + decals: + 138: 15,-7 + 146: 10,-4 + 147: 9,-3 + 148: 8,-2 + 198: -4,-11 + - node: + color: '#D58C18FF' + id: ConcreteTrimCornerNw + decals: + 332: -9,-20 + - node: + color: '#FFFFFFFF' + id: ConcreteTrimCornerNw + decals: + 51: -11,-7 + 177: 8,-11 + 192: -6,-4 + 193: -5,-3 + 194: -4,-2 + - node: + color: '#D58C18FF' + id: ConcreteTrimCornerSe + decals: + 344: -4,-21 + 350: -8,-25 + - node: + color: '#FFFFFFFF' + id: ConcreteTrimCornerSe + decals: + 128: 10,-13 + 137: 15,-9 + 184: 9,-25 + 195: -3,-4 + 196: -2,-3 + 197: -4,-5 + - node: + color: '#D58C18FF' + id: ConcreteTrimCornerSw + decals: + 349: -9,-25 + - node: + color: '#FFFFFFFF' + id: ConcreteTrimCornerSw + decals: + 52: -11,-9 + 61: -6,-13 + 158: 6,-3 + 159: 7,-4 + 160: 8,-5 + 183: 8,-25 + - node: + color: '#FFFFFFFF' + id: ConcreteTrimInnerNe + decals: + 143: 10,-7 + 150: 7,-2 + 151: 8,-3 + 152: 9,-4 + 157: 7,1 + 199: -4,-12 + 210: -5,-11 + 233: 9,-24 + 234: 9,-20 + 235: 9,-16 + 238: 15,-8 + - node: + color: '#FFFFFFFF' + id: ConcreteTrimInnerNw + decals: + 178: 8,-12 + 179: 9,-11 + 189: -6,-7 + 214: -3,1 + 220: -3,-2 + 221: -4,-3 + 222: -5,-4 + 223: -11,-8 + 226: -5,-16 + - node: + color: '#D58C18FF' + id: ConcreteTrimInnerSe + decals: + 340: -8,-21 + - node: + color: '#FFFFFFFF' + id: ConcreteTrimInnerSe + decals: + 75: -4,-13 + 102: 6,-13 + 127: 9,-13 + 132: 10,-9 + 211: -5,-5 + 212: -4,-4 + 213: -3,-3 + 229: 9,-20 + 231: 9,-16 + 232: 9,-24 + 237: 15,-8 + 354: 7,0 + - node: + color: '#FFFFFFFF' + id: ConcreteTrimInnerSw + decals: + 57: -6,-9 + 72: -5,-13 + 73: -2,-13 + 104: 8,-13 + 180: 9,-5 + 181: 8,-4 + 182: 7,-3 + 224: -11,-8 + 225: -5,-16 + 353: -3,0 + - node: + color: '#D58C18FF' + id: ConcreteTrimLineE + decals: + 337: -8,-24 + 338: -8,-23 + 339: -8,-22 + - node: + color: '#FFFFFFFF' + id: ConcreteTrimLineE + decals: + 64: -4,-17 + 65: -4,-16 + 66: -4,-15 + 67: -4,-14 + 119: 9,-23 + 120: 9,-22 + 121: 9,-21 + 122: 9,-19 + 123: 9,-18 + 124: 9,-17 + 125: 9,-15 + 126: 9,-14 + 129: 10,-12 + 130: 10,-11 + 131: 10,-10 + 144: 10,-6 + 145: 10,-5 + 149: 7,-1 + 205: -5,-10 + 206: -5,-9 + 208: -5,-7 + 209: -5,-6 + 215: -2,-2 + 216: -2,-1 + 217: -2,0 + 218: -2,1 + 227: -4,-18 + 358: -5,-8 + - node: + color: '#D58C18FF' + id: ConcreteTrimLineN + decals: + 345: -5,-20 + 346: -6,-20 + 347: -7,-20 + 348: -8,-20 + - node: + color: '#FFFFFFFF' + id: ConcreteTrimLineN + decals: + 139: 14,-7 + 140: 13,-7 + 141: 12,-7 + 142: 11,-7 + 168: 7,-12 + 169: 6,-12 + 170: 5,-12 + 172: 4,-12 + 174: 2,-12 + 176: 3,-12 + 185: -10,-7 + 186: -9,-7 + 187: -8,-7 + 188: -7,-7 + 200: -3,-12 + 201: -2,-12 + 202: -1,-12 + 203: 0,-12 + 204: 1,-12 + - node: + color: '#D58C18FF' + id: ConcreteTrimLineS + decals: + 341: -7,-21 + 342: -6,-21 + 343: -5,-21 + - node: + color: '#FFFFFFFF' + id: ConcreteTrimLineS + decals: + 53: -10,-9 + 54: -9,-9 + 55: -8,-9 + 56: -7,-9 + 74: -3,-13 + 103: 7,-13 + 133: 11,-9 + 134: 12,-9 + 135: 13,-9 + 136: 14,-9 + - node: + color: '#D58C18FF' + id: ConcreteTrimLineW + decals: + 333: -9,-21 + 334: -9,-22 + 335: -9,-23 + 336: -9,-24 + - node: + color: '#FFFFFFFF' + id: ConcreteTrimLineW + decals: + 58: -6,-10 + 59: -6,-11 + 60: -6,-12 + 68: -5,-17 + 70: -5,-15 + 71: -5,-14 + 105: 8,-14 + 106: 8,-15 + 107: 8,-15 + 110: 8,-17 + 111: 8,-18 + 112: 8,-19 + 113: 8,-20 + 114: 8,-21 + 115: 8,-22 + 116: 8,-23 + 117: 8,-24 + 153: 6,-2 + 154: 6,-1 + 155: 6,0 + 156: 6,1 + 161: 9,-6 + 162: 9,-7 + 163: 9,-7 + 164: 9,-8 + 165: 9,-9 + 167: 9,-10 + 190: -6,-6 + 191: -6,-5 + 219: -3,-1 + 228: -5,-18 + 236: 8,-16 + - node: + color: '#FFFFFFFF' + id: Delivery + decals: + 351: -8,-22 + 352: -9,-22 + - node: + cleanable: True + color: '#FFFFFFFF' + id: Dirt + decals: + 360: -2,6 + - node: + color: '#54C6FF77' + id: MarkupSquare + decals: + 404: -17,-11 + 405: -17,-10 + 406: -18,-10 + 407: -17,-9 + 408: -18,-9 + 409: -19,-9 + 410: -19,-8 + 411: -18,-8 + 412: -17,-8 + 413: -17,-7 + 414: -18,-7 + 415: -19,-7 + 416: -18,-6 + 417: -17,-6 + 418: -17,-5 + - node: + color: '#FFFFFFFF' + id: SpaceStationSign1 + decals: + 37: -1,-13 + - node: + color: '#FFFFFFFF' + id: SpaceStationSign2 + decals: + 36: 0,-13 + - node: + color: '#FFFFFFFF' + id: SpaceStationSign3 + decals: + 35: 1,-13 + - node: + color: '#FFFFFFFF' + id: SpaceStationSign4 + decals: + 34: 2,-13 + - node: + color: '#FFFFFFFF' + id: SpaceStationSign5 + decals: + 33: 3,-13 + - node: + color: '#FFFFFFFF' + id: SpaceStationSign6 + decals: + 31: 4,-13 + - node: + color: '#FFFFFFFF' + id: SpaceStationSign7 + decals: + 30: 5,-13 + - node: + color: '#FFFFFFFF' + id: WoodTrimThinCornerNe + decals: + 266: 7,8 + 267: 5,12 + 315: -3,14 + - node: + color: '#FFFFFFFF' + id: WoodTrimThinCornerNw + decals: + 268: -1,12 + 316: -8,14 + - node: + color: '#FFFFFFFF' + id: WoodTrimThinCornerSe + decals: + 299: 4,9 + - node: + color: '#FFFFFFFF' + id: WoodTrimThinCornerSw + decals: + 300: 0,9 + 309: -8,10 + - node: + color: '#FFFFFFFF' + id: WoodTrimThinInnerNe + decals: + 277: -3,8 + 286: 5,8 + 288: 7,4 + - node: + color: '#FFFFFFFF' + id: WoodTrimThinInnerNw + decals: + 278: -1,8 + - node: + color: '#FFFFFFFF' + id: WoodTrimThinInnerSe + decals: + 287: 7,4 + 289: 2,3 + 297: -2,3 + 330: -6,10 + - node: + color: '#FFFFFFFF' + id: WoodTrimThinInnerSw + decals: + 290: 2,3 + 298: 6,3 + 328: -3,10 + 329: -6,10 + - node: + color: '#FFFFFFFF' + id: WoodTrimThinLineE + decals: + 262: 7,3 + 263: 7,5 + 264: 7,6 + 265: 7,7 + 283: 5,10 + 284: 5,11 + 310: -3,10 + 311: -3,11 + 312: -3,12 + 313: -3,12 + 314: -3,13 + - node: + color: '#FFFFFFFF' + id: WoodTrimThinLineN + decals: + 279: -2,8 + 285: 6,8 + 304: 0,12 + 305: 1,12 + 306: 2,12 + 307: 3,12 + 308: 4,12 + 320: -7,14 + 321: -6,14 + 322: -6,14 + 323: -4,14 + 324: -5,14 + - node: + color: '#FFFFFFFF' + id: WoodTrimThinLineS + decals: + 291: -1,3 + 292: 0,3 + 293: 1,3 + 294: 3,3 + 295: 4,3 + 296: 5,3 + 301: 1,9 + 302: 2,9 + 303: 3,9 + 325: -4,10 + 326: -5,10 + 327: -7,10 + - node: + color: '#FFFFFFFF' + id: WoodTrimThinLineW + decals: + 271: -3,3 + 272: -3,4 + 273: -3,5 + 274: -3,6 + 275: -3,7 + 276: -3,8 + 280: -1,9 + 281: -1,10 + 282: -1,11 + 317: -8,11 + 318: -8,12 + 319: -8,13 + - node: + color: '#FFFFFFFF' + id: bushsnowa1 + decals: + 38: -1.7004952,-6.153923 + - node: + color: '#FFFFFFFF' + id: bushsnowa2 + decals: + 39: 7.323595,-6.221191 + - node: + color: '#FFFFFFFF' + id: bushsnowa3 + decals: + 50: 4.1019907,-10.919083 + - node: + color: '#FFFFFFFF' + id: grasssnow01 + decals: + 40: 5.5741863,-5.285021 + - node: + color: '#FFFFFFFF' + id: grasssnow10 + decals: + 47: 3.067338,-10.949326 + - node: + color: '#FFFFFFFF' + id: grasssnow12 + decals: + 41: 5.406428,-8.858435 + - node: + color: '#FFFFFFFF' + id: grasssnowa1 + decals: + 48: -2.7391882,-10.429232 + - node: + color: '#FFFFFFFF' + id: grasssnowb1 + decals: + 46: -2.9866114,-6.6177936 + - node: + color: '#FFFFFFFF' + id: grasssnowb3 + decals: + 42: 4.156881,-5.1055326 + 49: -1.9826872,-10.372494 + - node: + color: '#FFFFFFFF' + id: grasssnowc1 + decals: + 43: -0.52734363,-9.496761 + 45: 0.523451,-4.5429635 + - node: + color: '#FFFFFFFF' + id: grasssnowc3 + decals: + 44: 4.9242334,-10.58423 + - node: + color: '#FFFFFFFF' + id: skull + decals: + 359: 2.8570566,-11.061775 + - node: + color: '#54C6FF77' + id: splatter + decals: + 375: -16.473,-8.326239 + 376: -16.485607,-7.9038587 + 377: -16.466694,-7.4055386 + 378: -16.473,-7.0209837 + 379: -16.485607,-6.4157825 + 380: -16.491913,-5.8006525 + 383: -16.466694,-9.155449 + 384: -16.454086,-9.577827 + 385: -16.485607,-10.132595 + 386: -16.548649,-10.599104 + 387: -16.441479,-11.249384 + 388: -16.491913,-10.682009 + 419: -16.475132,-6.0695796 + 420: -16.449917,-4.871786 + 421: -16.475132,-5.3004704 + - type: GridAtmosphere + version: 2 + data: + tiles: + 0,0: + 0: 61695 + 0,-1: + 0: 65295 + 0,1: + 0: 65535 + -1,0: + 0: 58999 + -1,1: + 0: 65535 + 0,2: + 0: 65535 + -1,2: + 0: 48046 + 0,3: + 0: 15 + 1: 65280 + -1,3: + 0: 827 + 1: 34816 + 0,4: + 1: 255 + 1,0: + 0: 64733 + 1,1: + 0: 65535 + 1,2: + 0: 13119 + 1,3: + 0: 3 + 1: 13056 + 1,-1: + 0: 56783 + 1,4: + 1: 63 + 2,0: + 0: 59647 + 2,1: + 0: 65519 + 2,2: + 0: 63086 + 2,3: + 0: 255 + 2,4: + 1: 15 + 2,-1: + 0: 51511 + 3,0: + 0: 12663 + 1: 32768 + 3,1: + 0: 13107 + 1: 34952 + 3,2: + 0: 3 + 1: 19592 + 3,-1: + 0: 65535 + 3,4: + 1: 7 + 3,3: + 1: 17476 + 4,0: + 1: 4406 + -4,0: + 1: 140 + -4,-1: + 1: 17520 + -3,0: + 1: 12560 + 0: 32972 + -3,-1: + 0: 61439 + -3,1: + 1: 8738 + 0: 34952 + -3,2: + 1: 17954 + 0: 8 + -3,3: + 1: 17476 + -3,4: + 1: 12 + -2,0: + 0: 61695 + -2,1: + 0: 65535 + -2,2: + 0: 65359 + -2,3: + 0: 4095 + -2,-1: + 0: 29597 + -2,4: + 1: 15 + -1,4: + 1: 143 + -1,-1: + 0: 26495 + -4,-4: + 1: 61440 + -5,-4: + 1: 57344 + -4,-3: + 0: 63280 + 1: 8 + -5,-3: + 0: 60544 + 1: 19 + -4,-2: + 0: 14335 + -5,-2: + 0: 36078 + 1: 4096 + -5,-1: + 1: 227 + -3,-4: + 1: 61986 + 0: 136 + -3,-3: + 1: 241 + 0: 57344 + -3,-2: + 0: 61679 + -3,-5: + 1: 8738 + 0: 34824 + -2,-4: + 0: 51391 + 1: 4096 + -2,-3: + 1: 17 + 0: 64716 + -2,-2: + 0: 56575 + -2,-5: + 0: 48015 + -1,-4: + 0: 64989 + -1,-3: + 0: 65535 + -1,-2: + 0: 65535 + -1,-5: + 0: 56797 + 0,-4: + 0: 65535 + 0,-3: + 0: 65535 + 0,-2: + 0: 65535 + 0,-5: + 0: 65535 + 1,-4: + 0: 63351 + 1,-3: + 0: 65535 + 1,-2: + 0: 65535 + 1,-5: + 0: 30583 + 2,-4: + 0: 29631 + 2,-3: + 0: 63351 + 2,-2: + 0: 30719 + 2,-5: + 0: 46015 + 3,-4: + 0: 51 + 1: 63624 + 3,-3: + 1: 241 + 0: 61440 + 3,-2: + 0: 61695 + 3,-5: + 0: 12339 + 1: 34952 + 4,-4: + 1: 61440 + 4,-3: + 1: 19 + 0: 60544 + 4,-2: + 0: 40175 + 4,-1: + 0: 273 + 1: 17600 + 5,-4: + 1: 61440 + 5,-3: + 0: 63280 + 1: 8 + 5,-2: + 0: 14335 + 5,-1: + 1: 248 + 6,-3: + 1: 8753 + 6,-2: + 1: 12834 + 6,-1: + 1: 1 + -6,-3: + 1: 34944 + -6,-2: + 1: 34952 + -3,-7: + 1: 8928 + 0: 32768 + -3,-6: + 1: 8738 + 0: 34952 + -2,-7: + 1: 240 + 0: 20480 + -2,-6: + 0: 61781 + -1,-7: + 1: 50288 + 0: 4096 + -1,-6: + 0: 56337 + 0,-7: + 1: 61440 + 0,-6: + 0: 65520 + 1,-7: + 1: 29888 + 1,-6: + 0: 30480 + 2,-7: + 1: 240 + 0: 45056 + 2,-6: + 0: 46015 + 3,-7: + 1: 35056 + 0: 12288 + 3,-6: + 0: 12339 + 1: 34952 + uniqueMixes: + - volume: 2500 + temperature: 293.15 + moles: + - 21.824879 + - 82.10312 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - volume: 2500 + immutable: True + moles: + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + chunkSize: 4 + - type: GasTileOverlay + - type: RadiationGridResistance + - type: NavMap +- proto: AcousticGuitarInstrument + entities: + - uid: 314 + components: + - type: Transform + pos: -0.4485035,12.618004 + parent: 2 +- proto: ADTArmchairBlack + entities: + - uid: 866 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 22.5,-6.5 + parent: 2 + - uid: 867 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 18.5,-8.5 + parent: 2 +- proto: ADTArmchairBlue2 + entities: + - uid: 864 + components: + - type: Transform + pos: 19.5,-5.5 + parent: 2 + - uid: 865 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 21.5,-9.5 + parent: 2 +- proto: ADTArmchairBrown2 + entities: + - uid: 862 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 22.5,-8.5 + parent: 2 + - uid: 863 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 18.5,-6.5 + parent: 2 +- proto: ADTArmchairWhite2 + entities: + - uid: 860 + components: + - type: Transform + pos: 21.5,-5.5 + parent: 2 + - uid: 861 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 19.5,-9.5 + parent: 2 +- proto: ADTBathBroom + entities: + - uid: 1604 + components: + - type: Transform + pos: 3.4913483,-1.4084876 + parent: 2 + - uid: 1605 + components: + - type: Transform + pos: 4.065817,-1.472317 + parent: 2 +- proto: ADTClothingNeckScarfUnrobust + entities: + - uid: 1704 + components: + - type: Transform + pos: 12.512464,-14.404398 + parent: 2 +- proto: ADTFoodFrozenPackedPopsicleMole + entities: + - uid: 1670 + components: + - type: Transform + pos: 11.377801,7.610191 + parent: 2 +- proto: ADTIconAdventureTime + entities: + - uid: 1671 + components: + - type: MetaData + desc: Чипи чипи чапа чапа дуби дуби даба даба + name: Время приключений рулит! + - type: Transform + pos: 2.6034718,16.155771 + parent: 2 +- proto: ADTPlushieJungar + entities: + - uid: 1669 + components: + - type: Transform + pos: -4.2851434,14.602755 + parent: 2 +- proto: ADTPosterContrabandLustTayaran + entities: + - uid: 889 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 10.5,-22.5 + parent: 2 +- proto: ADTPosterContrabandLustUma + entities: + - uid: 890 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 11.5,-25.5 + parent: 2 +- proto: ADTPosterContrabandUmaOnBeach + entities: + - uid: 1696 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: -18.5,-9.5 + parent: 2 +- proto: ADTPosterHalloweenSpooky + entities: + - uid: 241 + components: + - type: Transform + pos: -6.5,-2.5 + parent: 2 +- proto: ADTPosterHalloweenYummy + entities: + - uid: 242 + components: + - type: Transform + pos: -6.5,-5.5 + parent: 2 +- proto: ADTPosterLegitGreatFood + entities: + - uid: 1697 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 8.5,8.5 + parent: 2 +- proto: ADTPosterLustyMoth + entities: + - uid: 254 + components: + - type: Transform + pos: -6.5,2.5 + parent: 2 +- proto: ADTPosterNewYear + entities: + - uid: 247 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: -11.5,-0.5 + parent: 2 +- proto: ADTPosterNoGood + entities: + - uid: 1690 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: -12.5,-9.5 + parent: 2 +- proto: ADTPosterPapersPlease + entities: + - uid: 250 + components: + - type: Transform + pos: -11.5,-5.5 + parent: 2 +- proto: ADTPosterSingoPizza + entities: + - uid: 1694 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 8.5,5.5 + parent: 2 +- proto: ADTPosterTayarHalloween + entities: + - uid: 255 + components: + - type: Transform + pos: -8.5,-5.5 + parent: 2 +- proto: ADTVendingMachineHalloween + entities: + - uid: 243 + components: + - type: Transform + pos: -7.5,-4.5 + parent: 2 + - type: Emagged +- proto: ADTVendingMachineNewYear + entities: + - uid: 1720 + components: + - type: Transform + pos: -5.5,1.5 + parent: 2 +- proto: ADTVendingMachinePrazatClothing + entities: + - uid: 246 + components: + - type: Transform + pos: -7.5,1.5 + parent: 2 + - type: Emagged +- proto: AirAlarm + entities: + - uid: 1607 + components: + - type: Transform + pos: -3.5,-0.5 + parent: 2 + - type: DeviceList + devices: + - 1596 + - 1224 + - uid: 1619 + components: + - type: Transform + pos: 6.5,9.5 + parent: 2 + - type: DeviceList + devices: + - 1232 + - 1600 + - uid: 1620 + components: + - type: Transform + pos: 10.5,14.5 + parent: 2 + - type: DeviceList + devices: + - 1231 + - 1601 + - uid: 1621 + components: + - type: Transform + pos: 10.5,2.5 + parent: 2 + - type: DeviceList + devices: + - 1233 + - 1594 + - uid: 1622 + components: + - type: Transform + pos: -10.5,0.5 + parent: 2 + - type: DeviceList + devices: + - 1358 + - 1599 + - uid: 1623 + components: + - type: Transform + pos: -12.5,-5.5 + parent: 2 + - type: DeviceList + devices: + - 1432 + - 1598 + - uid: 1624 + components: + - type: Transform + pos: -6.5,-13.5 + parent: 2 + - type: DeviceList + devices: + - 1235 + - uid: 1626 + components: + - type: Transform + pos: 7.5,-13.5 + parent: 2 + - uid: 1627 + components: + - type: Transform + pos: 12.5,-13.5 + parent: 2 + - type: DeviceList + devices: + - 1225 + - uid: 1628 + components: + - type: Transform + pos: 12.5,-17.5 + parent: 2 + - type: DeviceList + devices: + - 1226 + - uid: 1629 + components: + - type: Transform + pos: 12.5,-21.5 + parent: 2 + - type: DeviceList + devices: + - 1227 + - uid: 1630 + components: + - type: Transform + pos: 17.5,-5.5 + parent: 2 + - type: DeviceList + devices: + - 1595 + - 1228 +- proto: AirCanister + entities: + - uid: 1386 + components: + - type: Transform + pos: -5.5,-19.5 + parent: 2 +- proto: Airlock + entities: + - uid: 561 + components: + - type: Transform + pos: 10.5,-19.5 + parent: 2 + - uid: 681 + components: + - type: Transform + pos: 10.5,-15.5 + parent: 2 + - uid: 682 + components: + - type: MetaData + name: ERP ROOM + - type: Transform + pos: 10.5,-23.5 + parent: 2 + - type: Door + secondsUntilStateChange: -20940.7 + state: Opening + - type: DeviceLinkSource + lastSignals: + DoorStatus: True + - uid: 959 + components: + - type: Transform + pos: 16.5,-7.5 + parent: 2 + - uid: 960 + components: + - type: Transform + pos: -11.5,-7.5 + parent: 2 +- proto: AirlockBarLocked + entities: + - uid: 680 + components: + - type: Transform + pos: -5.5,9.5 + parent: 2 +- proto: AirlockEngineeringGlass + entities: + - uid: 584 + components: + - type: Transform + pos: -4.5,-18.5 + parent: 2 + - uid: 585 + components: + - type: Transform + pos: -3.5,-18.5 + parent: 2 +- proto: AirlockFreezer + entities: + - uid: 669 + components: + - type: Transform + pos: 9.5,9.5 + parent: 2 + - uid: 671 + components: + - type: Transform + pos: 10.5,9.5 + parent: 2 +- proto: AirlockGlass + entities: + - uid: 684 + components: + - type: Transform + pos: 6.5,2.5 + parent: 2 + - uid: 685 + components: + - type: Transform + pos: 7.5,2.5 + parent: 2 + - uid: 686 + components: + - type: Transform + pos: -2.5,2.5 + parent: 2 + - uid: 687 + components: + - type: Transform + pos: -1.5,2.5 + parent: 2 + - uid: 1377 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -3.5,0.5 + parent: 2 + - uid: 1378 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -3.5,1.5 + parent: 2 +- proto: AirlockHydroGlassLocked + entities: + - uid: 284 + components: + - type: Transform + pos: 8.5,0.5 + parent: 2 + - uid: 285 + components: + - type: Transform + pos: 8.5,1.5 + parent: 2 +- proto: AirlockJanitorLocked + entities: + - uid: 91 + components: + - type: Transform + pos: -5.5,-15.5 + parent: 2 + - type: Door + secondsUntilStateChange: -21022.066 + state: Opening + - type: DeviceLinkSource + lastSignals: + DoorStatus: True +- proto: AirlockKitchenGlassLocked + entities: + - uid: 668 + components: + - type: Transform + pos: 8.5,4.5 + parent: 2 + - type: Door + secondsUntilStateChange: -16452.438 + state: Opening + - type: DeviceLinkSource + lastSignals: + DoorStatus: True +- proto: AirlockServiceGlassLocked + entities: + - uid: 92 + components: + - type: Transform + pos: 12.5,2.5 + parent: 2 +- proto: AtmosDeviceFanTiny + entities: + - uid: 1002 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 9.5,10.5 + parent: 2 + - uid: 1003 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 10.5,10.5 + parent: 2 + - uid: 1602 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 2.5,2.5 + parent: 2 +- proto: BagOfSummoningGarbage + entities: + - uid: 1055 + components: + - type: Transform + pos: -8.211578,-14.297813 + parent: 2 +- proto: Barricade + entities: + - uid: 793 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 9.5,-22.5 + parent: 2 + - uid: 794 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 8.5,-22.5 + parent: 2 +- proto: BarricadeDirectional + entities: + - uid: 791 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 9.5,-23.5 + parent: 2 +- proto: BassGuitarInstrument + entities: + - uid: 313 + components: + - type: Transform + pos: -0.7180066,12.688927 + parent: 2 +- proto: BeachBall + entities: + - uid: 1701 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -15.615554,-7.4042053 + parent: 2 +- proto: Bed + entities: + - uid: 892 + components: + - type: Transform + pos: 13.5,-22.5 + parent: 2 + - uid: 893 + components: + - type: Transform + pos: 13.5,-18.5 + parent: 2 + - uid: 894 + components: + - type: Transform + pos: 13.5,-14.5 + parent: 2 +- proto: BedsheetRed + entities: + - uid: 899 + components: + - type: Transform + pos: 13.5,-22.5 + parent: 2 +- proto: BedsheetSpawner + entities: + - uid: 900 + components: + - type: Transform + pos: 13.5,-18.5 + parent: 2 + - uid: 901 + components: + - type: Transform + pos: 13.5,-14.5 + parent: 2 +- proto: Biofabricator + entities: + - uid: 269 + components: + - type: Transform + pos: 10.5,-0.5 + parent: 2 +- proto: Biogenerator + entities: + - uid: 270 + components: + - type: Transform + pos: 11.5,-1.5 + parent: 2 +- proto: BlockGameArcade + entities: + - uid: 264 + components: + - type: Transform + pos: -6.5,14.5 + parent: 2 + - uid: 265 + components: + - type: Transform + pos: -7.5,14.5 + parent: 2 +- proto: Bonfire + entities: + - uid: 920 + components: + - type: Transform + pos: 2.5,-6.5 + parent: 2 +- proto: BookshelfFilled + entities: + - uid: 897 + components: + - type: Transform + pos: 11.5,-18.5 + parent: 2 + - uid: 898 + components: + - type: Transform + pos: 11.5,-14.5 + parent: 2 + - uid: 916 + components: + - type: Transform + pos: 11.5,-22.5 + parent: 2 + - uid: 1023 + components: + - type: Transform + pos: 23.5,-7.5 + parent: 2 + - uid: 1718 + components: + - type: Transform + pos: 23.5,-6.5 + parent: 2 + - uid: 1719 + components: + - type: Transform + pos: 23.5,-8.5 + parent: 2 +- proto: BoozeDispenser + entities: + - uid: 796 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -8.5,3.5 + parent: 2 +- proto: BoxAgrichem + entities: + - uid: 1410 + components: + - type: Transform + pos: 14.227506,-0.19314241 + parent: 2 + - uid: 1463 + components: + - type: Transform + pos: 14.908357,-0.10803652 + parent: 2 +- proto: BoxingBell + entities: + - uid: 1702 + components: + - type: Transform + pos: 7.5,-17.5 + parent: 2 +- proto: CableApcExtension + entities: + - uid: 322 + components: + - type: Transform + pos: 2.5,-0.5 + parent: 2 + - uid: 323 + components: + - type: Transform + pos: 2.5,-0.5 + parent: 2 + - uid: 324 + components: + - type: Transform + pos: 2.5,0.5 + parent: 2 + - uid: 325 + components: + - type: Transform + pos: 2.5,1.5 + parent: 2 + - uid: 326 + components: + - type: Transform + pos: 2.5,2.5 + parent: 2 + - uid: 327 + components: + - type: Transform + pos: 2.5,3.5 + parent: 2 + - uid: 328 + components: + - type: Transform + pos: 2.5,5.5 + parent: 2 + - uid: 329 + components: + - type: Transform + pos: 2.5,6.5 + parent: 2 + - uid: 330 + components: + - type: Transform + pos: 2.5,4.5 + parent: 2 + - uid: 331 + components: + - type: Transform + pos: 3.5,6.5 + parent: 2 + - uid: 332 + components: + - type: Transform + pos: 4.5,6.5 + parent: 2 + - uid: 333 + components: + - type: Transform + pos: 5.5,6.5 + parent: 2 + - uid: 334 + components: + - type: Transform + pos: 6.5,6.5 + parent: 2 + - uid: 335 + components: + - type: Transform + pos: 7.5,6.5 + parent: 2 + - uid: 336 + components: + - type: Transform + pos: 7.5,5.5 + parent: 2 + - uid: 337 + components: + - type: Transform + pos: 7.5,4.5 + parent: 2 + - uid: 338 + components: + - type: Transform + pos: 7.5,2.5 + parent: 2 + - uid: 339 + components: + - type: Transform + pos: 7.5,1.5 + parent: 2 + - uid: 340 + components: + - type: Transform + pos: 7.5,0.5 + parent: 2 + - uid: 341 + components: + - type: Transform + pos: 7.5,-0.5 + parent: 2 + - uid: 342 + components: + - type: Transform + pos: 7.5,-1.5 + parent: 2 + - uid: 343 + components: + - type: Transform + pos: 7.5,3.5 + parent: 2 + - uid: 344 + components: + - type: Transform + pos: 8.5,-1.5 + parent: 2 + - uid: 345 + components: + - type: Transform + pos: 8.5,-2.5 + parent: 2 + - uid: 346 + components: + - type: Transform + pos: 9.5,-2.5 + parent: 2 + - uid: 347 + components: + - type: Transform + pos: 9.5,-3.5 + parent: 2 + - uid: 348 + components: + - type: Transform + pos: 10.5,-3.5 + parent: 2 + - uid: 349 + components: + - type: Transform + pos: 10.5,-4.5 + parent: 2 + - uid: 350 + components: + - type: Transform + pos: 10.5,-5.5 + parent: 2 + - uid: 351 + components: + - type: Transform + pos: 10.5,-7.5 + parent: 2 + - uid: 352 + components: + - type: Transform + pos: 10.5,-6.5 + parent: 2 + - uid: 353 + components: + - type: Transform + pos: 11.5,-7.5 + parent: 2 + - uid: 354 + components: + - type: Transform + pos: 12.5,-7.5 + parent: 2 + - uid: 355 + components: + - type: Transform + pos: 13.5,-7.5 + parent: 2 + - uid: 356 + components: + - type: Transform + pos: 14.5,-7.5 + parent: 2 + - uid: 357 + components: + - type: Transform + pos: 15.5,-7.5 + parent: 2 + - uid: 358 + components: + - type: Transform + pos: 17.5,-7.5 + parent: 2 + - uid: 359 + components: + - type: Transform + pos: 18.5,-7.5 + parent: 2 + - uid: 360 + components: + - type: Transform + pos: 19.5,-7.5 + parent: 2 + - uid: 361 + components: + - type: Transform + pos: 16.5,-7.5 + parent: 2 + - uid: 362 + components: + - type: Transform + pos: 20.5,-7.5 + parent: 2 + - uid: 363 + components: + - type: Transform + pos: 10.5,-8.5 + parent: 2 + - uid: 364 + components: + - type: Transform + pos: 10.5,-10.5 + parent: 2 + - uid: 365 + components: + - type: Transform + pos: 10.5,-9.5 + parent: 2 + - uid: 366 + components: + - type: Transform + pos: 10.5,-12.5 + parent: 2 + - uid: 367 + components: + - type: Transform + pos: 10.5,-11.5 + parent: 2 + - uid: 368 + components: + - type: Transform + pos: -4.5,-12.5 + parent: 2 + - uid: 369 + components: + - type: Transform + pos: -5.5,-12.5 + parent: 2 + - uid: 370 + components: + - type: Transform + pos: 9.5,-12.5 + parent: 2 + - uid: 371 + components: + - type: Transform + pos: 8.5,-12.5 + parent: 2 + - uid: 372 + components: + - type: Transform + pos: 7.5,-12.5 + parent: 2 + - uid: 373 + components: + - type: Transform + pos: 6.5,-12.5 + parent: 2 + - uid: 374 + components: + - type: Transform + pos: 5.5,-12.5 + parent: 2 + - uid: 375 + components: + - type: Transform + pos: 4.5,-12.5 + parent: 2 + - uid: 376 + components: + - type: Transform + pos: 3.5,-12.5 + parent: 2 + - uid: 377 + components: + - type: Transform + pos: 2.5,-12.5 + parent: 2 + - uid: 378 + components: + - type: Transform + pos: 1.5,-12.5 + parent: 2 + - uid: 379 + components: + - type: Transform + pos: -0.5,-12.5 + parent: 2 + - uid: 380 + components: + - type: Transform + pos: -1.5,-12.5 + parent: 2 + - uid: 381 + components: + - type: Transform + pos: -2.5,-12.5 + parent: 2 + - uid: 382 + components: + - type: Transform + pos: 0.5,-12.5 + parent: 2 + - uid: 383 + components: + - type: Transform + pos: -3.5,-12.5 + parent: 2 + - uid: 384 + components: + - type: Transform + pos: -5.5,-11.5 + parent: 2 + - uid: 385 + components: + - type: Transform + pos: -5.5,-9.5 + parent: 2 + - uid: 386 + components: + - type: Transform + pos: -5.5,-8.5 + parent: 2 + - uid: 387 + components: + - type: Transform + pos: -5.5,-7.5 + parent: 2 + - uid: 388 + components: + - type: Transform + pos: -5.5,-5.5 + parent: 2 + - uid: 389 + components: + - type: Transform + pos: -5.5,-4.5 + parent: 2 + - uid: 390 + components: + - type: Transform + pos: -5.5,-3.5 + parent: 2 + - uid: 391 + components: + - type: Transform + pos: -5.5,-10.5 + parent: 2 + - uid: 392 + components: + - type: Transform + pos: -5.5,-6.5 + parent: 2 + - uid: 393 + components: + - type: Transform + pos: -6.5,-7.5 + parent: 2 + - uid: 394 + components: + - type: Transform + pos: -7.5,-7.5 + parent: 2 + - uid: 395 + components: + - type: Transform + pos: -8.5,-7.5 + parent: 2 + - uid: 396 + components: + - type: Transform + pos: -9.5,-7.5 + parent: 2 + - uid: 397 + components: + - type: Transform + pos: -10.5,-7.5 + parent: 2 + - uid: 398 + components: + - type: Transform + pos: -11.5,-7.5 + parent: 2 + - uid: 399 + components: + - type: Transform + pos: -12.5,-4.5 + parent: 2 + - uid: 400 + components: + - type: Transform + pos: -11.5,-5.5 + parent: 2 + - uid: 401 + components: + - type: Transform + pos: -11.5,-6.5 + parent: 2 + - uid: 402 + components: + - type: Transform + pos: -18.5,-4.5 + parent: 2 + - uid: 403 + components: + - type: Transform + pos: -4.5,-3.5 + parent: 2 + - uid: 404 + components: + - type: Transform + pos: -4.5,-2.5 + parent: 2 + - uid: 405 + components: + - type: Transform + pos: -3.5,-2.5 + parent: 2 + - uid: 406 + components: + - type: Transform + pos: -3.5,-1.5 + parent: 2 + - uid: 407 + components: + - type: Transform + pos: -2.5,-1.5 + parent: 2 + - uid: 408 + components: + - type: Transform + pos: -2.5,-0.5 + parent: 2 + - uid: 409 + components: + - type: Transform + pos: -2.5,0.5 + parent: 2 + - uid: 410 + components: + - type: Transform + pos: -2.5,1.5 + parent: 2 + - uid: 411 + components: + - type: Transform + pos: -2.5,2.5 + parent: 2 + - uid: 412 + components: + - type: Transform + pos: -2.5,3.5 + parent: 2 + - uid: 413 + components: + - type: Transform + pos: -2.5,4.5 + parent: 2 + - uid: 414 + components: + - type: Transform + pos: -2.5,5.5 + parent: 2 + - uid: 415 + components: + - type: Transform + pos: -2.5,6.5 + parent: 2 + - uid: 416 + components: + - type: Transform + pos: -2.5,7.5 + parent: 2 + - uid: 417 + components: + - type: Transform + pos: -2.5,8.5 + parent: 2 + - uid: 418 + components: + - type: Transform + pos: -1.5,8.5 + parent: 2 + - uid: 419 + components: + - type: Transform + pos: -0.5,8.5 + parent: 2 + - uid: 420 + components: + - type: Transform + pos: -0.5,9.5 + parent: 2 + - uid: 421 + components: + - type: Transform + pos: -0.5,11.5 + parent: 2 + - uid: 422 + components: + - type: Transform + pos: -0.5,12.5 + parent: 2 + - uid: 423 + components: + - type: Transform + pos: -0.5,10.5 + parent: 2 + - uid: 424 + components: + - type: Transform + pos: 0.5,12.5 + parent: 2 + - uid: 425 + components: + - type: Transform + pos: 1.5,12.5 + parent: 2 + - uid: 426 + components: + - type: Transform + pos: 2.5,12.5 + parent: 2 + - uid: 427 + components: + - type: Transform + pos: 3.5,12.5 + parent: 2 + - uid: 428 + components: + - type: Transform + pos: 4.5,12.5 + parent: 2 + - uid: 429 + components: + - type: Transform + pos: 5.5,12.5 + parent: 2 + - uid: 430 + components: + - type: Transform + pos: 5.5,11.5 + parent: 2 + - uid: 431 + components: + - type: Transform + pos: 5.5,10.5 + parent: 2 + - uid: 432 + components: + - type: Transform + pos: 5.5,9.5 + parent: 2 + - uid: 433 + components: + - type: Transform + pos: 5.5,8.5 + parent: 2 + - uid: 434 + components: + - type: Transform + pos: 1.5,6.5 + parent: 2 + - uid: 435 + components: + - type: Transform + pos: 0.5,6.5 + parent: 2 + - uid: 436 + components: + - type: Transform + pos: -0.5,6.5 + parent: 2 + - uid: 437 + components: + - type: Transform + pos: -1.5,6.5 + parent: 2 + - uid: 438 + components: + - type: Transform + pos: 6.5,8.5 + parent: 2 + - uid: 439 + components: + - type: Transform + pos: 7.5,8.5 + parent: 2 + - uid: 440 + components: + - type: Transform + pos: 7.5,7.5 + parent: 2 + - uid: 441 + components: + - type: Transform + pos: 8.5,4.5 + parent: 2 + - uid: 442 + components: + - type: Transform + pos: 9.5,4.5 + parent: 2 + - uid: 443 + components: + - type: Transform + pos: 11.5,4.5 + parent: 2 + - uid: 444 + components: + - type: Transform + pos: 10.5,4.5 + parent: 2 + - uid: 445 + components: + - type: Transform + pos: 11.5,5.5 + parent: 2 + - uid: 446 + components: + - type: Transform + pos: 11.5,6.5 + parent: 2 + - uid: 447 + components: + - type: Transform + pos: 11.5,7.5 + parent: 2 + - uid: 448 + components: + - type: Transform + pos: 10.5,7.5 + parent: 2 + - uid: 449 + components: + - type: Transform + pos: 10.5,8.5 + parent: 2 + - uid: 450 + components: + - type: Transform + pos: 10.5,9.5 + parent: 2 + - uid: 451 + components: + - type: Transform + pos: 10.5,10.5 + parent: 2 + - uid: 452 + components: + - type: Transform + pos: 10.5,11.5 + parent: 2 + - uid: 453 + components: + - type: Transform + pos: 10.5,12.5 + parent: 2 + - uid: 454 + components: + - type: Transform + pos: 8.5,1.5 + parent: 2 + - uid: 455 + components: + - type: Transform + pos: 9.5,1.5 + parent: 2 + - uid: 456 + components: + - type: Transform + pos: 10.5,1.5 + parent: 2 + - uid: 457 + components: + - type: Transform + pos: 11.5,1.5 + parent: 2 + - uid: 458 + components: + - type: Transform + pos: 12.5,1.5 + parent: 2 + - uid: 459 + components: + - type: Transform + pos: 12.5,0.5 + parent: 2 + - uid: 460 + components: + - type: Transform + pos: 13.5,0.5 + parent: 2 + - uid: 461 + components: + - type: Transform + pos: 13.5,-0.5 + parent: 2 + - uid: 462 + components: + - type: Transform + pos: 13.5,-2.5 + parent: 2 + - uid: 463 + components: + - type: Transform + pos: 13.5,-1.5 + parent: 2 + - uid: 464 + components: + - type: Transform + pos: 14.5,-2.5 + parent: 2 + - uid: 465 + components: + - type: Transform + pos: -3.5,0.5 + parent: 2 + - uid: 466 + components: + - type: Transform + pos: -4.5,0.5 + parent: 2 + - uid: 467 + components: + - type: Transform + pos: -5.5,0.5 + parent: 2 + - uid: 468 + components: + - type: Transform + pos: -6.5,0.5 + parent: 2 + - uid: 469 + components: + - type: Transform + pos: -7.5,0.5 + parent: 2 + - uid: 470 + components: + - type: Transform + pos: -7.5,-0.5 + parent: 2 + - uid: 471 + components: + - type: Transform + pos: -7.5,-1.5 + parent: 2 + - uid: 472 + components: + - type: Transform + pos: -8.5,-1.5 + parent: 2 + - uid: 473 + components: + - type: Transform + pos: -9.5,-1.5 + parent: 2 + - uid: 474 + components: + - type: Transform + pos: -9.5,-2.5 + parent: 2 + - uid: 475 + components: + - type: Transform + pos: -9.5,-3.5 + parent: 2 + - uid: 476 + components: + - type: Transform + pos: -2.5,9.5 + parent: 2 + - uid: 477 + components: + - type: Transform + pos: -2.5,11.5 + parent: 2 + - uid: 478 + components: + - type: Transform + pos: -2.5,10.5 + parent: 2 + - uid: 479 + components: + - type: Transform + pos: -2.5,12.5 + parent: 2 + - uid: 480 + components: + - type: Transform + pos: -3.5,12.5 + parent: 2 + - uid: 481 + components: + - type: Transform + pos: -4.5,12.5 + parent: 2 + - uid: 482 + components: + - type: Transform + pos: -5.5,12.5 + parent: 2 + - uid: 483 + components: + - type: Transform + pos: -6.5,12.5 + parent: 2 + - uid: 484 + components: + - type: Transform + pos: -6.5,11.5 + parent: 2 + - uid: 485 + components: + - type: Transform + pos: -6.5,9.5 + parent: 2 + - uid: 486 + components: + - type: Transform + pos: -6.5,8.5 + parent: 2 + - uid: 487 + components: + - type: Transform + pos: -6.5,10.5 + parent: 2 + - uid: 488 + components: + - type: Transform + pos: -6.5,7.5 + parent: 2 + - uid: 489 + components: + - type: Transform + pos: -6.5,6.5 + parent: 2 + - uid: 490 + components: + - type: Transform + pos: -6.5,5.5 + parent: 2 + - uid: 594 + components: + - type: Transform + pos: -5.5,-20.5 + parent: 2 + - uid: 595 + components: + - type: Transform + pos: -6.5,-20.5 + parent: 2 + - uid: 596 + components: + - type: Transform + pos: -1.5,-13.5 + parent: 2 + - uid: 597 + components: + - type: Transform + pos: -1.5,-14.5 + parent: 2 + - uid: 598 + components: + - type: Transform + pos: -1.5,-16.5 + parent: 2 + - uid: 599 + components: + - type: Transform + pos: -1.5,-17.5 + parent: 2 + - uid: 600 + components: + - type: Transform + pos: -1.5,-18.5 + parent: 2 + - uid: 601 + components: + - type: Transform + pos: -1.5,-19.5 + parent: 2 + - uid: 602 + components: + - type: Transform + pos: -1.5,-20.5 + parent: 2 + - uid: 603 + components: + - type: Transform + pos: -1.5,-21.5 + parent: 2 + - uid: 604 + components: + - type: Transform + pos: -1.5,-15.5 + parent: 2 + - uid: 605 + components: + - type: Transform + pos: -0.5,-21.5 + parent: 2 + - uid: 606 + components: + - type: Transform + pos: 1.5,-21.5 + parent: 2 + - uid: 607 + components: + - type: Transform + pos: 2.5,-21.5 + parent: 2 + - uid: 608 + components: + - type: Transform + pos: 3.5,-21.5 + parent: 2 + - uid: 609 + components: + - type: Transform + pos: 0.5,-21.5 + parent: 2 + - uid: 610 + components: + - type: Transform + pos: 4.5,-21.5 + parent: 2 + - uid: 611 + components: + - type: Transform + pos: 5.5,-21.5 + parent: 2 + - uid: 612 + components: + - type: Transform + pos: 6.5,-21.5 + parent: 2 + - uid: 613 + components: + - type: Transform + pos: 6.5,-20.5 + parent: 2 + - uid: 614 + components: + - type: Transform + pos: 6.5,-19.5 + parent: 2 + - uid: 615 + components: + - type: Transform + pos: 6.5,-18.5 + parent: 2 + - uid: 616 + components: + - type: Transform + pos: 6.5,-17.5 + parent: 2 + - uid: 617 + components: + - type: Transform + pos: 6.5,-15.5 + parent: 2 + - uid: 618 + components: + - type: Transform + pos: 6.5,-14.5 + parent: 2 + - uid: 619 + components: + - type: Transform + pos: 6.5,-13.5 + parent: 2 + - uid: 620 + components: + - type: Transform + pos: 6.5,-16.5 + parent: 2 + - uid: 621 + components: + - type: Transform + pos: 8.5,-13.5 + parent: 2 + - uid: 622 + components: + - type: Transform + pos: 8.5,-14.5 + parent: 2 + - uid: 623 + components: + - type: Transform + pos: 8.5,-16.5 + parent: 2 + - uid: 624 + components: + - type: Transform + pos: 8.5,-17.5 + parent: 2 + - uid: 625 + components: + - type: Transform + pos: 8.5,-18.5 + parent: 2 + - uid: 626 + components: + - type: Transform + pos: 8.5,-19.5 + parent: 2 + - uid: 627 + components: + - type: Transform + pos: 8.5,-20.5 + parent: 2 + - uid: 628 + components: + - type: Transform + pos: 8.5,-21.5 + parent: 2 + - uid: 629 + components: + - type: Transform + pos: 8.5,-15.5 + parent: 2 + - uid: 630 + components: + - type: Transform + pos: 8.5,-22.5 + parent: 2 + - uid: 631 + components: + - type: Transform + pos: 8.5,-23.5 + parent: 2 + - uid: 632 + components: + - type: Transform + pos: 8.5,-24.5 + parent: 2 + - uid: 633 + components: + - type: Transform + pos: 9.5,-23.5 + parent: 2 + - uid: 634 + components: + - type: Transform + pos: 11.5,-23.5 + parent: 2 + - uid: 635 + components: + - type: Transform + pos: 10.5,-23.5 + parent: 2 + - uid: 636 + components: + - type: Transform + pos: 12.5,-23.5 + parent: 2 + - uid: 637 + components: + - type: Transform + pos: 9.5,-19.5 + parent: 2 + - uid: 638 + components: + - type: Transform + pos: 11.5,-19.5 + parent: 2 + - uid: 639 + components: + - type: Transform + pos: 12.5,-19.5 + parent: 2 + - uid: 640 + components: + - type: Transform + pos: 10.5,-19.5 + parent: 2 + - uid: 641 + components: + - type: Transform + pos: 12.5,-15.5 + parent: 2 + - uid: 642 + components: + - type: Transform + pos: 11.5,-15.5 + parent: 2 + - uid: 643 + components: + - type: Transform + pos: 9.5,-15.5 + parent: 2 + - uid: 644 + components: + - type: Transform + pos: 10.5,-15.5 + parent: 2 + - uid: 645 + components: + - type: Transform + pos: -7.5,-20.5 + parent: 2 + - uid: 646 + components: + - type: Transform + pos: -4.5,-19.5 + parent: 2 + - uid: 647 + components: + - type: Transform + pos: -4.5,-18.5 + parent: 2 + - uid: 648 + components: + - type: Transform + pos: -4.5,-17.5 + parent: 2 + - uid: 649 + components: + - type: Transform + pos: -4.5,-16.5 + parent: 2 + - uid: 650 + components: + - type: Transform + pos: -4.5,-14.5 + parent: 2 + - uid: 651 + components: + - type: Transform + pos: -4.5,-13.5 + parent: 2 + - uid: 652 + components: + - type: Transform + pos: -4.5,-15.5 + parent: 2 + - uid: 653 + components: + - type: Transform + pos: -6.5,-15.5 + parent: 2 + - uid: 654 + components: + - type: Transform + pos: -7.5,-15.5 + parent: 2 + - uid: 655 + components: + - type: Transform + pos: -5.5,-15.5 + parent: 2 + - uid: 656 + components: + - type: Transform + pos: -7.5,-16.5 + parent: 2 + - uid: 663 + components: + - type: Transform + pos: -5.5,-19.5 + parent: 2 + - uid: 666 + components: + - type: Transform + pos: -5.5,-18.5 + parent: 2 + - uid: 994 + components: + - type: Transform + pos: -14.5,-3.5 + parent: 2 + - uid: 995 + components: + - type: Transform + pos: -12.5,-5.5 + parent: 2 + - uid: 996 + components: + - type: Transform + pos: -13.5,-3.5 + parent: 2 + - uid: 997 + components: + - type: Transform + pos: -17.5,-3.5 + parent: 2 + - uid: 998 + components: + - type: Transform + pos: -16.5,-3.5 + parent: 2 + - uid: 1033 + components: + - type: Transform + pos: -7.5,-21.5 + parent: 2 + - uid: 1034 + components: + - type: Transform + pos: -8.5,-21.5 + parent: 2 + - uid: 1035 + components: + - type: Transform + pos: -8.5,-23.5 + parent: 2 + - uid: 1036 + components: + - type: Transform + pos: -8.5,-24.5 + parent: 2 + - uid: 1037 + components: + - type: Transform + pos: -8.5,-22.5 + parent: 2 + - uid: 1038 + components: + - type: Transform + pos: -7.5,-24.5 + parent: 2 + - uid: 1318 + components: + - type: Transform + pos: -17.5,-4.5 + parent: 2 + - uid: 1320 + components: + - type: Transform + pos: -13.5,-4.5 + parent: 2 + - uid: 1321 + components: + - type: Transform + pos: -15.5,-3.5 + parent: 2 + - uid: 1333 + components: + - type: Transform + pos: -18.5,-5.5 + parent: 2 + - uid: 1334 + components: + - type: Transform + pos: -19.5,-7.5 + parent: 2 + - uid: 1335 + components: + - type: Transform + pos: -19.5,-5.5 + parent: 2 + - uid: 1337 + components: + - type: Transform + pos: -19.5,-6.5 + parent: 2 + - uid: 1417 + components: + - type: Transform + pos: -19.5,-8.5 + parent: 2 + - uid: 1418 + components: + - type: Transform + pos: -19.5,-9.5 + parent: 2 + - uid: 1419 + components: + - type: Transform + pos: -18.5,-9.5 + parent: 2 + - uid: 1420 + components: + - type: Transform + pos: -18.5,-10.5 + parent: 2 + - uid: 1421 + components: + - type: Transform + pos: -17.5,-10.5 + parent: 2 + - uid: 1422 + components: + - type: Transform + pos: -17.5,-11.5 + parent: 2 + - uid: 1423 + components: + - type: Transform + pos: -16.5,-11.5 + parent: 2 + - uid: 1424 + components: + - type: Transform + pos: -15.5,-11.5 + parent: 2 + - uid: 1425 + components: + - type: Transform + pos: -14.5,-11.5 + parent: 2 + - uid: 1426 + components: + - type: Transform + pos: -13.5,-11.5 + parent: 2 + - uid: 1427 + components: + - type: Transform + pos: -13.5,-10.5 + parent: 2 + - uid: 1428 + components: + - type: Transform + pos: -12.5,-10.5 + parent: 2 + - uid: 1429 + components: + - type: Transform + pos: -12.5,-9.5 + parent: 2 + - uid: 1430 + components: + - type: Transform + pos: -11.5,-9.5 + parent: 2 + - uid: 1431 + components: + - type: Transform + pos: -11.5,-8.5 + parent: 2 +- proto: CableHV + entities: + - uid: 657 + components: + - type: Transform + pos: -8.5,-24.5 + parent: 2 + - uid: 658 + components: + - type: Transform + pos: -7.5,-24.5 + parent: 2 +- proto: CableMV + entities: + - uid: 662 + components: + - type: Transform + pos: -7.5,-24.5 + parent: 2 + - uid: 672 + components: + - type: Transform + pos: -5.5,-19.5 + parent: 2 + - uid: 673 + components: + - type: Transform + pos: -5.5,-18.5 + parent: 2 + - uid: 677 + components: + - type: Transform + pos: -5.5,-20.5 + parent: 2 + - uid: 679 + components: + - type: Transform + pos: -5.5,-19.5 + parent: 2 + - uid: 1028 + components: + - type: Transform + pos: -8.5,-23.5 + parent: 2 + - uid: 1029 + components: + - type: Transform + pos: -8.5,-22.5 + parent: 2 + - uid: 1030 + components: + - type: Transform + pos: -8.5,-21.5 + parent: 2 + - uid: 1031 + components: + - type: Transform + pos: -8.5,-24.5 + parent: 2 + - uid: 1032 + components: + - type: Transform + pos: -7.5,-21.5 + parent: 2 + - uid: 1705 + components: + - type: Transform + pos: -7.5,-20.5 + parent: 2 + - uid: 1706 + components: + - type: Transform + pos: -6.5,-20.5 + parent: 2 + - uid: 1707 + components: + - type: Transform + pos: -5.5,-20.5 + parent: 2 +- proto: Carpet + entities: + - uid: 905 + components: + - type: Transform + pos: 12.5,-16.5 + parent: 2 + - uid: 906 + components: + - type: Transform + pos: 13.5,-15.5 + parent: 2 + - uid: 907 + components: + - type: Transform + pos: 11.5,-15.5 + parent: 2 +- proto: CarpetCyan + entities: + - uid: 911 + components: + - type: Transform + pos: 13.5,-20.5 + parent: 2 + - uid: 912 + components: + - type: Transform + pos: 12.5,-19.5 + parent: 2 + - uid: 913 + components: + - type: Transform + pos: 11.5,-20.5 + parent: 2 + - uid: 1448 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -15.5,-6.5 + parent: 2 + - uid: 1449 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -14.5,-6.5 + parent: 2 +- proto: CarpetOrange + entities: + - uid: 902 + components: + - type: Transform + pos: 11.5,-16.5 + parent: 2 + - uid: 903 + components: + - type: Transform + pos: 12.5,-15.5 + parent: 2 + - uid: 904 + components: + - type: Transform + pos: 13.5,-16.5 + parent: 2 +- proto: CarpetPink + entities: + - uid: 884 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 13.5,-23.5 + parent: 2 + - uid: 885 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 12.5,-22.5 + parent: 2 + - uid: 886 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 12.5,-24.5 + parent: 2 + - uid: 887 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 11.5,-23.5 + parent: 2 + - uid: 1450 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -15.5,-8.5 + parent: 2 + - uid: 1451 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -14.5,-8.5 + parent: 2 +- proto: CarpetPurple + entities: + - uid: 879 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 13.5,-24.5 + parent: 2 + - uid: 880 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 12.5,-23.5 + parent: 2 + - uid: 881 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 11.5,-24.5 + parent: 2 + - uid: 882 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 11.5,-22.5 + parent: 2 + - uid: 883 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 13.5,-22.5 + parent: 2 +- proto: CarpetSBlue + entities: + - uid: 908 + components: + - type: Transform + pos: 12.5,-20.5 + parent: 2 + - uid: 909 + components: + - type: Transform + pos: 13.5,-19.5 + parent: 2 + - uid: 910 + components: + - type: Transform + pos: 11.5,-19.5 + parent: 2 +- proto: Chair + entities: + - uid: 811 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 5.5,-19.5 + parent: 2 + - uid: 812 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 5.5,-18.5 + parent: 2 + - uid: 813 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 5.5,-17.5 + parent: 2 + - uid: 814 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 5.5,-16.5 + parent: 2 + - uid: 815 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 5.5,-15.5 + parent: 2 + - uid: 816 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -0.5,-15.5 + parent: 2 + - uid: 817 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -0.5,-16.5 + parent: 2 + - uid: 818 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -0.5,-17.5 + parent: 2 + - uid: 819 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -0.5,-18.5 + parent: 2 + - uid: 820 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -0.5,-19.5 + parent: 2 + - uid: 821 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 0.5,-20.5 + parent: 2 + - uid: 822 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 2.5,-20.5 + parent: 2 + - uid: 823 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 3.5,-20.5 + parent: 2 + - uid: 824 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 4.5,-20.5 + parent: 2 + - uid: 825 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 1.5,-20.5 + parent: 2 + - uid: 826 + components: + - type: Transform + pos: 0.5,-14.5 + parent: 2 + - uid: 827 + components: + - type: Transform + pos: 1.5,-14.5 + parent: 2 + - uid: 828 + components: + - type: Transform + pos: 2.5,-14.5 + parent: 2 + - uid: 829 + components: + - type: Transform + pos: 3.5,-14.5 + parent: 2 + - uid: 830 + components: + - type: Transform + pos: 4.5,-14.5 + parent: 2 +- proto: ChairWood + entities: + - uid: 294 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 5.5,3.5 + parent: 2 + - uid: 299 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 5.5,4.5 + parent: 2 + - uid: 300 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 3.5,4.5 + parent: 2 + - uid: 301 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 3.5,3.5 + parent: 2 + - uid: 302 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 1.5,4.5 + parent: 2 + - uid: 303 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 1.5,3.5 + parent: 2 + - uid: 304 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -0.5,3.5 + parent: 2 + - uid: 305 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -0.5,4.5 + parent: 2 +- proto: ClockworkGrille + entities: + - uid: 984 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 0.5,-2.5 + parent: 2 + - uid: 985 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 2.5,-2.5 + parent: 2 + - uid: 986 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 3.5,-2.5 + parent: 2 + - uid: 987 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 4.5,-2.5 + parent: 2 + - uid: 988 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 1.5,-2.5 + parent: 2 + - uid: 1711 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: -5.5,-21.5 + parent: 2 + - uid: 1712 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: -3.5,-21.5 + parent: 2 +- proto: ClothingBackpackChameleonFill + entities: + - uid: 1714 + components: + - type: Transform + pos: -9.874376,-0.21257377 + parent: 2 + - uid: 1715 + components: + - type: Transform + pos: -9.363737,-0.18420482 + parent: 2 + - uid: 1716 + components: + - type: Transform + pos: -9.349553,-0.6381055 + parent: 2 + - uid: 1717 + components: + - type: Transform + pos: -9.860191,-0.5955522 + parent: 2 +- proto: ClothingHandsGlovesBoxingBlue + entities: + - uid: 958 + components: + - type: Transform + pos: 0.79048026,-22.267895 + parent: 2 +- proto: ClothingHandsGlovesBoxingGreen + entities: + - uid: 956 + components: + - type: Transform + pos: 0.35549235,-22.267895 + parent: 2 +- proto: ClothingHandsGlovesBoxingRed + entities: + - uid: 957 + components: + - type: Transform + pos: 0.7431991,-22.636688 + parent: 2 +- proto: ClothingHandsGlovesBoxingYellow + entities: + - uid: 955 + components: + - type: Transform + pos: 0.41489077,-22.56883 + parent: 2 +- proto: ClothingHeadHatCatEars + entities: + - uid: 969 + components: + - type: Transform + pos: 12.439992,-23.49558 + parent: 2 +- proto: ClothingNeckCloakAce + entities: + - uid: 1703 + components: + - type: Transform + pos: 12.434296,-18.331295 + parent: 2 +- proto: ClothingUnderSocksCoder + entities: + - uid: 970 + components: + - type: Transform + pos: 12.461269,-24.49558 + parent: 2 +- proto: ClothingUniformJumpskirtElegantMaid + entities: + - uid: 949 + components: + - type: Transform + pos: 12.461269,-23.899836 + parent: 2 +- proto: ClothingUniformJumpskirtJanimaidmini + entities: + - uid: 968 + components: + - type: Transform + pos: -8.558366,-14.58568 + parent: 2 +- proto: Cobweb2 + entities: + - uid: 1636 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: -6.5,-1.5 + parent: 2 +- proto: CrateFreezer + entities: + - uid: 1004 + components: + - type: Transform + pos: 8.5,13.5 + parent: 2 +- proto: CrateFunBoardGames + entities: + - uid: 1372 + components: + - type: Transform + pos: 19.5,-10.5 + parent: 2 +- proto: CrateFunPlushie + entities: + - uid: 869 + components: + - type: Transform + pos: 21.5,-4.5 + parent: 2 +- proto: CrateFunToyBox + entities: + - uid: 868 + components: + - type: Transform + pos: 19.5,-4.5 + parent: 2 +- proto: CrateServiceJanitorialSupplies + entities: + - uid: 963 + components: + - type: Transform + pos: -6.5,-17.5 + parent: 2 +- proto: CurtainsOrange + entities: + - uid: 1632 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: -2.5,9.5 + parent: 2 +- proto: CurtainsRed + entities: + - uid: 989 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 1.5,-2.5 + parent: 2 + - uid: 990 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 2.5,-2.5 + parent: 2 + - uid: 991 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 0.5,-2.5 + parent: 2 + - uid: 992 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 3.5,-2.5 + parent: 2 + - uid: 993 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 4.5,-2.5 + parent: 2 +- proto: DawInstrument + entities: + - uid: 312 + components: + - type: Transform + pos: 3.5,12.5 + parent: 2 +- proto: DebugAPC + entities: + - uid: 665 + components: + - type: Transform + pos: -5.5,-18.5 + parent: 2 + - type: Battery + startingCharge: 50000 +- proto: DebugGenerator + entities: + - uid: 1063 + components: + - type: Transform + pos: -8.5,-24.5 + parent: 2 +- proto: DebugSubstation + entities: + - uid: 661 + components: + - type: Transform + pos: -7.5,-24.5 + parent: 2 +- proto: DisposalBend + entities: + - uid: 1099 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 5.5,-20.5 + parent: 2 + - uid: 1100 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 4.5,-21.5 + parent: 2 + - uid: 1101 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 5.5,-12.5 + parent: 2 + - uid: 1102 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 9.5,-12.5 + parent: 2 + - uid: 1103 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 9.5,-11.5 + parent: 2 + - uid: 1104 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 10.5,-11.5 + parent: 2 + - uid: 1106 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 7.5,-1.5 + parent: 2 + - uid: 1107 + components: + - type: Transform + pos: 8.5,-1.5 + parent: 2 + - uid: 1108 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 8.5,-2.5 + parent: 2 + - uid: 1109 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 9.5,-3.5 + parent: 2 + - uid: 1110 + components: + - type: Transform + pos: 10.5,-3.5 + parent: 2 + - uid: 1111 + components: + - type: Transform + pos: 9.5,-2.5 + parent: 2 + - uid: 1112 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: -2.5,-1.5 + parent: 2 + - uid: 1113 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: -3.5,-2.5 + parent: 2 + - uid: 1114 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: -4.5,-3.5 + parent: 2 + - uid: 1115 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -3.5,-1.5 + parent: 2 + - uid: 1116 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -4.5,-2.5 + parent: 2 + - uid: 1117 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -5.5,-3.5 + parent: 2 + - uid: 1119 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -9.5,-1.5 + parent: 2 + - uid: 1120 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: -6.5,-1.5 + parent: 2 + - uid: 1121 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -6.5,-0.5 + parent: 2 + - uid: 1122 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: -5.5,-0.5 + parent: 2 + - uid: 1123 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -5.5,0.5 + parent: 2 + - uid: 1124 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -5.5,4.5 + parent: 2 + - uid: 1125 + components: + - type: Transform + pos: -2.5,10.5 + parent: 2 + - uid: 1126 + components: + - type: Transform + pos: 9.5,4.5 + parent: 2 + - uid: 1127 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 11.5,-0.5 + parent: 2 + - uid: 1128 + components: + - type: Transform + pos: 11.5,0.5 + parent: 2 + - uid: 1142 + components: + - type: Transform + pos: 7.5,7.5 + parent: 2 + - uid: 1143 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 6.5,7.5 + parent: 2 + - uid: 1175 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: -0.5,-20.5 + parent: 2 + - uid: 1186 + components: + - type: Transform + pos: -0.5,-12.5 + parent: 2 + - uid: 1187 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: -5.5,-11.5 + parent: 2 + - uid: 1188 + components: + - type: Transform + pos: -4.5,-11.5 + parent: 2 + - uid: 1189 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: -4.5,-12.5 + parent: 2 + - uid: 1211 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: -3.5,-15.5 + parent: 2 + - uid: 1212 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -7.5,-15.5 + parent: 2 +- proto: DisposalJunction + entities: + - uid: 1068 + components: + - type: Transform + pos: -2.5,0.5 + parent: 2 + - uid: 1144 + components: + - type: Transform + pos: -2.5,4.5 + parent: 2 + - uid: 1190 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -3.5,-12.5 + parent: 2 + - uid: 1191 + components: + - type: Transform + pos: -5.5,-7.5 + parent: 2 +- proto: DisposalJunctionFlipped + entities: + - uid: 1069 + components: + - type: Transform + pos: 7.5,0.5 + parent: 2 + - uid: 1078 + components: + - type: Transform + pos: 10.5,-7.5 + parent: 2 + - uid: 1139 + components: + - type: Transform + pos: 7.5,4.5 + parent: 2 + - uid: 1177 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 4.5,-20.5 + parent: 2 +- proto: DisposalPipe + entities: + - uid: 660 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 20.5,-9.5 + parent: 2 + - uid: 664 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 20.5,-8.5 + parent: 2 + - uid: 675 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 18.5,-7.5 + parent: 2 + - uid: 971 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 19.5,-7.5 + parent: 2 + - uid: 1025 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 10.5,-8.5 + parent: 2 + - uid: 1079 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 17.5,-7.5 + parent: 2 + - uid: 1080 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 16.5,-7.5 + parent: 2 + - uid: 1081 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 15.5,-7.5 + parent: 2 + - uid: 1082 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 14.5,-7.5 + parent: 2 + - uid: 1083 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 13.5,-7.5 + parent: 2 + - uid: 1084 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 12.5,-7.5 + parent: 2 + - uid: 1085 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 11.5,-7.5 + parent: 2 + - uid: 1086 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 10.5,-9.5 + parent: 2 + - uid: 1087 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 10.5,-10.5 + parent: 2 + - uid: 1089 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 8.5,-12.5 + parent: 2 + - uid: 1090 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 7.5,-12.5 + parent: 2 + - uid: 1091 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 6.5,-12.5 + parent: 2 + - uid: 1092 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 5.5,-14.5 + parent: 2 + - uid: 1093 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 5.5,-16.5 + parent: 2 + - uid: 1094 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 5.5,-17.5 + parent: 2 + - uid: 1095 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 5.5,-18.5 + parent: 2 + - uid: 1096 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 5.5,-19.5 + parent: 2 + - uid: 1097 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 5.5,-15.5 + parent: 2 + - uid: 1098 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 5.5,-13.5 + parent: 2 + - uid: 1129 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 14.5,-0.5 + parent: 2 + - uid: 1130 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 13.5,-0.5 + parent: 2 + - uid: 1131 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 12.5,-0.5 + parent: 2 + - uid: 1132 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 10.5,0.5 + parent: 2 + - uid: 1133 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 9.5,0.5 + parent: 2 + - uid: 1134 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 8.5,0.5 + parent: 2 + - uid: 1135 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 7.5,-0.5 + parent: 2 + - uid: 1136 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 7.5,1.5 + parent: 2 + - uid: 1137 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 7.5,3.5 + parent: 2 + - uid: 1138 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 7.5,2.5 + parent: 2 + - uid: 1140 + components: + - type: Transform + pos: 7.5,5.5 + parent: 2 + - uid: 1141 + components: + - type: Transform + pos: 7.5,6.5 + parent: 2 + - uid: 1145 + components: + - type: Transform + pos: -2.5,5.5 + parent: 2 + - uid: 1146 + components: + - type: Transform + pos: -2.5,6.5 + parent: 2 + - uid: 1147 + components: + - type: Transform + pos: -2.5,8.5 + parent: 2 + - uid: 1148 + components: + - type: Transform + pos: -2.5,9.5 + parent: 2 + - uid: 1149 + components: + - type: Transform + pos: -2.5,7.5 + parent: 2 + - uid: 1150 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: -4.5,4.5 + parent: 2 + - uid: 1151 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: -3.5,4.5 + parent: 2 + - uid: 1152 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: -2.5,1.5 + parent: 2 + - uid: 1153 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: -2.5,3.5 + parent: 2 + - uid: 1154 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: -2.5,2.5 + parent: 2 + - uid: 1155 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -4.5,0.5 + parent: 2 + - uid: 1156 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -3.5,0.5 + parent: 2 + - uid: 1157 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -8.5,-1.5 + parent: 2 + - uid: 1158 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -7.5,-1.5 + parent: 2 + - uid: 1159 + components: + - type: Transform + pos: -9.5,-2.5 + parent: 2 + - uid: 1160 + components: + - type: Transform + pos: -9.5,-3.5 + parent: 2 + - uid: 1161 + components: + - type: Transform + pos: -5.5,-4.5 + parent: 2 + - uid: 1162 + components: + - type: Transform + pos: -5.5,-5.5 + parent: 2 + - uid: 1163 + components: + - type: Transform + pos: -5.5,-6.5 + parent: 2 + - uid: 1164 + components: + - type: Transform + pos: -5.5,-8.5 + parent: 2 + - uid: 1165 + components: + - type: Transform + pos: -5.5,-9.5 + parent: 2 + - uid: 1166 + components: + - type: Transform + pos: -5.5,-10.5 + parent: 2 + - uid: 1167 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: -2.5,-12.5 + parent: 2 + - uid: 1168 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: -1.5,-12.5 + parent: 2 + - uid: 1169 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: -0.5,-13.5 + parent: 2 + - uid: 1170 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: -0.5,-14.5 + parent: 2 + - uid: 1171 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: -0.5,-16.5 + parent: 2 + - uid: 1172 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: -0.5,-17.5 + parent: 2 + - uid: 1173 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: -0.5,-18.5 + parent: 2 + - uid: 1174 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: -0.5,-19.5 + parent: 2 + - uid: 1176 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: -0.5,-15.5 + parent: 2 + - uid: 1179 + components: + - type: Transform + pos: 2.5,-24.5 + parent: 2 + - uid: 1180 + components: + - type: Transform + pos: 2.5,-23.5 + parent: 2 + - uid: 1181 + components: + - type: Transform + pos: 2.5,-22.5 + parent: 2 + - uid: 1182 + components: + - type: Transform + pos: 2.5,-21.5 + parent: 2 + - uid: 1183 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 0.5,-20.5 + parent: 2 + - uid: 1184 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 1.5,-20.5 + parent: 2 + - uid: 1185 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 3.5,-20.5 + parent: 2 + - uid: 1193 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: -11.5,-7.5 + parent: 2 + - uid: 1194 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: -10.5,-7.5 + parent: 2 + - uid: 1195 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: -9.5,-7.5 + parent: 2 + - uid: 1196 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: -8.5,-7.5 + parent: 2 + - uid: 1197 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: -7.5,-7.5 + parent: 2 + - uid: 1198 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: -6.5,-7.5 + parent: 2 + - uid: 1200 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: -2.5,-0.5 + parent: 2 + - uid: 1201 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 10.5,-6.5 + parent: 2 + - uid: 1202 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 10.5,-5.5 + parent: 2 + - uid: 1203 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 10.5,-4.5 + parent: 2 + - uid: 1204 + components: + - type: Transform + pos: -3.5,-14.5 + parent: 2 + - uid: 1205 + components: + - type: Transform + pos: -3.5,-13.5 + parent: 2 + - uid: 1206 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: -4.5,-15.5 + parent: 2 + - uid: 1207 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: -5.5,-15.5 + parent: 2 + - uid: 1208 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: -6.5,-15.5 + parent: 2 + - uid: 1209 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: -7.5,-16.5 + parent: 2 + - uid: 1708 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 8.5,4.5 + parent: 2 +- proto: DisposalTrunk + entities: + - uid: 678 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: -9.5,-4.5 + parent: 2 + - uid: 1070 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 15.5,-0.5 + parent: 2 + - uid: 1071 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 9.5,3.5 + parent: 2 + - uid: 1072 + components: + - type: Transform + pos: 6.5,8.5 + parent: 2 + - uid: 1073 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: -5.5,3.5 + parent: 2 + - uid: 1074 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -3.5,10.5 + parent: 2 + - uid: 1075 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 6.5,-21.5 + parent: 2 + - uid: 1210 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: -7.5,-17.5 + parent: 2 + - uid: 1709 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 20.5,-10.5 + parent: 2 +- proto: DisposalUnit + entities: + - uid: 282 + components: + - type: Transform + pos: 15.5,-0.5 + parent: 2 + - uid: 1061 + components: + - type: Transform + pos: 6.5,8.5 + parent: 2 + - type: DisposalUnit + - uid: 1062 + components: + - type: Transform + pos: 9.5,3.5 + parent: 2 + - uid: 1065 + components: + - type: Transform + pos: -9.5,-4.5 + parent: 2 + - uid: 1066 + components: + - type: Transform + pos: 6.5,-21.5 + parent: 2 + - uid: 1067 + components: + - type: Transform + pos: -3.5,10.5 + parent: 2 + - uid: 1213 + components: + - type: Transform + pos: -7.5,-17.5 + parent: 2 + - uid: 1606 + components: + - type: Transform + pos: -5.5,3.5 + parent: 2 + - uid: 1710 + components: + - type: Transform + pos: 20.5,-10.5 + parent: 2 +- proto: DisposalYJunction + entities: + - uid: 1178 + components: + - type: Transform + pos: 2.5,-20.5 + parent: 2 +- proto: DresserFilled + entities: + - uid: 895 + components: + - type: Transform + pos: 12.5,-14.5 + parent: 2 + - type: UserInterface + - type: ActiveUserInterface + - uid: 896 + components: + - type: Transform + pos: 12.5,-18.5 + parent: 2 + - uid: 915 + components: + - type: Transform + pos: 12.5,-22.5 + parent: 2 +- proto: EffectHearts + entities: + - uid: 1223 + components: + - type: Transform + pos: 2.2571197,6.849076 + parent: 2 +- proto: ElectricGuitarInstrument + entities: + - uid: 315 + components: + - type: Transform + pos: -0.15654325,12.518713 + parent: 2 +- proto: Firelock + entities: + - uid: 1640 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 9.5,9.5 + parent: 2 + - uid: 1641 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 10.5,9.5 + parent: 2 +- proto: FirelockEdge + entities: + - uid: 1656 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 8.5,6.5 + parent: 2 + - uid: 1657 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 8.5,7.5 + parent: 2 + - uid: 1658 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: -3.5,7.5 + parent: 2 + - uid: 1659 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: -3.5,6.5 + parent: 2 + - uid: 1660 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: -3.5,5.5 + parent: 2 + - uid: 1661 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: -3.5,4.5 + parent: 2 +- proto: FirelockGlass + entities: + - uid: 1635 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 8.5,0.5 + parent: 2 + - uid: 1637 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 8.5,1.5 + parent: 2 + - uid: 1638 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 12.5,2.5 + parent: 2 + - uid: 1639 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 11.5,2.5 + parent: 2 + - uid: 1642 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 6.5,2.5 + parent: 2 + - uid: 1643 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 7.5,2.5 + parent: 2 + - uid: 1644 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: -1.5,2.5 + parent: 2 + - uid: 1645 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: -2.5,2.5 + parent: 2 + - uid: 1646 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: -3.5,0.5 + parent: 2 + - uid: 1647 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: -3.5,1.5 + parent: 2 + - uid: 1648 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: -11.5,-7.5 + parent: 2 + - uid: 1649 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: -4.5,-18.5 + parent: 2 + - uid: 1650 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: -3.5,-18.5 + parent: 2 + - uid: 1651 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: -5.5,-15.5 + parent: 2 + - uid: 1652 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 10.5,-19.5 + parent: 2 + - uid: 1653 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 10.5,-15.5 + parent: 2 + - uid: 1654 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 16.5,-7.5 + parent: 2 + - uid: 1655 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 8.5,4.5 + parent: 2 + - uid: 1662 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: -2.5,9.5 + parent: 2 + - uid: 1663 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: -5.5,9.5 + parent: 2 +- proto: FloorDrain + entities: + - uid: 1021 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -7.5,-16.5 + parent: 2 + - type: Fixtures + fixtures: {} + - uid: 1024 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 9.5,12.5 + parent: 2 + - type: Fixtures + fixtures: {} +- proto: FloorWaterEntity + entities: + - uid: 1433 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -16.5,-9.5 + parent: 2 + - uid: 1434 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -16.5,-7.5 + parent: 2 + - uid: 1435 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -16.5,-6.5 + parent: 2 + - uid: 1436 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -16.5,-5.5 + parent: 2 + - uid: 1437 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -16.5,-8.5 + parent: 2 + - uid: 1438 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -16.5,-10.5 + parent: 2 + - uid: 1439 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -16.5,-4.5 + parent: 2 + - uid: 1440 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -17.5,-9.5 + parent: 2 + - uid: 1441 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -17.5,-8.5 + parent: 2 + - uid: 1442 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -17.5,-7.5 + parent: 2 + - uid: 1443 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -17.5,-6.5 + parent: 2 + - uid: 1444 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -17.5,-5.5 + parent: 2 + - uid: 1445 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -18.5,-8.5 + parent: 2 + - uid: 1446 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -18.5,-7.5 + parent: 2 + - uid: 1447 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -18.5,-6.5 + parent: 2 +- proto: FloraPalmTree1 + entities: + - uid: 1453 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -15.301156,-10.461088 + parent: 2 +- proto: FloraPalmTree2 + entities: + - uid: 1452 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -14.705411,-5.418536 + parent: 2 + - uid: 1454 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -13.364986,-9.227047 + parent: 2 +- proto: FloraTreeChristmas02 + entities: + - uid: 1415 + components: + - type: Transform + pos: 1.36641,-9.669712 + parent: 2 +- proto: FloraTreeConifer01 + entities: + - uid: 1118 + components: + - type: Transform + pos: -1.1655056,-5.265457 + parent: 2 + - uid: 1412 + components: + - type: Transform + pos: 3.5791757,-10.542053 + parent: 2 +- proto: FloraTreeConifer02 + entities: + - uid: 1076 + components: + - type: Transform + pos: 7.468999,-5.5420527 + parent: 2 +- proto: FloraTreeConifer03 + entities: + - uid: 999 + components: + - type: Transform + pos: -1.9528117,-9.925032 + parent: 2 +- proto: FloraTreeSnow02 + entities: + - uid: 1064 + components: + - type: Transform + pos: -2.6548662,-6.222904 + parent: 2 + - uid: 1411 + components: + - type: Transform + pos: 5.3876867,-10.11652 + parent: 2 +- proto: FloraTreeSnow04 + entities: + - uid: 1414 + components: + - type: Transform + pos: 4.5578985,-4.5633297 + parent: 2 +- proto: FloraTreeSnow05 + entities: + - uid: 1413 + components: + - type: Transform + pos: -0.5484841,-8.818647 + parent: 2 +- proto: FloraTreeStumpConifer + entities: + - uid: 1416 + components: + - type: Transform + pos: 0.96215415,-4.222904 + parent: 2 +- proto: FluteInstrument + entities: + - uid: 320 + components: + - type: Transform + pos: 4.7901316,12.423492 + parent: 2 +- proto: GasMinerNitrogenStation + entities: + - uid: 1381 + components: + - type: Transform + pos: -5.5,-24.5 + parent: 2 +- proto: GasMinerOxygenStation + entities: + - uid: 1385 + components: + - type: Transform + pos: -3.5,-24.5 + parent: 2 +- proto: GasMixer + entities: + - uid: 1216 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: -4.5,-19.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' +- proto: GasPassiveVent + entities: + - uid: 1214 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: -3.5,-22.5 + parent: 2 + - uid: 1215 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: -5.5,-22.5 + parent: 2 + - uid: 1464 + components: + - type: Transform + pos: 2.5,14.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' +- proto: GasPipeBend + entities: + - uid: 1088 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 12.5,-19.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1199 + components: + - type: Transform + pos: 10.5,-3.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1217 + components: + - type: Transform + pos: -3.5,-19.5 + parent: 2 + - uid: 1221 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -5.5,-20.5 + parent: 2 + - uid: 1222 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: -4.5,-20.5 + parent: 2 + - uid: 1229 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 8.5,-2.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1230 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: -4.5,0.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1249 + components: + - type: Transform + pos: 1.5,-11.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1250 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 1.5,-12.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1251 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 3.5,-12.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1252 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 3.5,-11.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1259 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 10.5,-11.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1276 + components: + - type: Transform + pos: 20.5,-7.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1277 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 9.5,-3.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1278 + components: + - type: Transform + pos: 9.5,-2.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1279 + components: + - type: Transform + pos: 8.5,-1.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1280 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -3.5,-3.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1281 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -2.5,-2.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1282 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: -1.5,-2.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1289 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 12.5,0.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1311 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -2.5,5.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1319 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 7.5,-1.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1336 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: -2.5,-3.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1353 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 10.5,4.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1354 + components: + - type: Transform + pos: 7.5,5.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1357 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -6.5,-15.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1387 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 12.5,-15.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1388 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 12.5,-23.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1389 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 8.5,-23.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1465 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 2.5,13.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1467 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 1.5,13.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1474 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 1.5,3.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1475 + components: + - type: Transform + pos: 9.5,11.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1480 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 9.5,6.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1491 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -1.5,6.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1504 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: -3.5,-4.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1505 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: -3.5,-2.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1506 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -3.5,-1.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1507 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: -2.5,-1.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1508 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -4.5,-2.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1518 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -5.5,-4.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1522 + components: + - type: Transform + pos: -3.5,-10.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1531 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: -5.5,-10.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1533 + components: + - type: Transform + pos: -0.5,-12.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1543 + components: + - type: Transform + pos: 2.5,-20.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1545 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: -0.5,-20.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1551 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 5.5,-13.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1552 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 5.5,-12.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1556 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 9.5,-12.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1574 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 20.5,-6.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1576 + components: + - type: Transform + pos: 9.5,-4.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1577 + components: + - type: Transform + pos: 8.5,-3.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1578 + components: + - type: Transform + pos: 7.5,-2.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1579 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 6.5,-2.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1580 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 8.5,-4.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1581 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 7.5,-3.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' +- proto: GasPipeFourway + entities: + - uid: 1466 + components: + - type: Transform + pos: 1.5,6.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' +- proto: GasPipeStraight + entities: + - uid: 1192 + components: + - type: Transform + pos: 10.5,-4.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1218 + components: + - type: Transform + pos: -3.5,-21.5 + parent: 2 + - uid: 1219 + components: + - type: Transform + pos: -3.5,-20.5 + parent: 2 + - uid: 1220 + components: + - type: Transform + pos: -5.5,-21.5 + parent: 2 + - uid: 1234 + components: + - type: Transform + pos: -4.5,-17.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1237 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -5.5,-15.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1238 + components: + - type: Transform + pos: -4.5,-16.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1239 + components: + - type: Transform + pos: -4.5,-18.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1240 + components: + - type: Transform + pos: -4.5,-14.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1241 + components: + - type: Transform + pos: -4.5,-12.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1242 + components: + - type: Transform + pos: -4.5,-13.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1244 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -3.5,-11.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1245 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -2.5,-11.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1246 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -1.5,-11.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1247 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -0.5,-11.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1248 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 0.5,-11.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1254 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 4.5,-11.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1255 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 5.5,-11.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1256 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 7.5,-11.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1257 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 6.5,-11.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1261 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 9.5,-11.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1262 + components: + - type: Transform + pos: 10.5,-10.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1263 + components: + - type: Transform + pos: 10.5,-9.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1264 + components: + - type: Transform + pos: 10.5,-8.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1265 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 11.5,-7.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1266 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 12.5,-7.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1267 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 13.5,-7.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1268 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 14.5,-7.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1269 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 15.5,-7.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1270 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 16.5,-7.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1271 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 17.5,-7.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1272 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 18.5,-7.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1273 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 19.5,-7.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1274 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 20.5,-8.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1275 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 20.5,-9.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1283 + components: + - type: Transform + pos: 10.5,-6.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1284 + components: + - type: Transform + pos: 10.5,-5.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1285 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 8.5,0.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1286 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 9.5,0.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1287 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 10.5,0.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1288 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 11.5,0.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1291 + components: + - type: Transform + pos: -4.5,-3.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1292 + components: + - type: Transform + pos: 7.5,-0.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1293 + components: + - type: Transform + pos: 7.5,1.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1294 + components: + - type: Transform + pos: 7.5,3.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1295 + components: + - type: Transform + pos: 7.5,2.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1296 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 6.5,5.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1297 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 5.5,5.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1298 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 4.5,5.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1299 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 3.5,5.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1301 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 2.5,6.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1302 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 2.5,7.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1303 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 2.5,8.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1304 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 2.5,9.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1305 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 2.5,10.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1306 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 2.5,11.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1307 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 1.5,5.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1308 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 0.5,5.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1309 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -0.5,5.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1310 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -1.5,5.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1312 + components: + - type: Transform + pos: -2.5,3.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1313 + components: + - type: Transform + pos: -2.5,2.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1314 + components: + - type: Transform + pos: -2.5,1.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1315 + components: + - type: Transform + pos: -2.5,-0.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1316 + components: + - type: Transform + pos: -2.5,4.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1323 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: -4.5,-6.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1324 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: -4.5,-5.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1325 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: -4.5,-4.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1326 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -5.5,-7.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1327 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -6.5,-7.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1328 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -7.5,-7.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1329 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -8.5,-7.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1330 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -9.5,-7.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1331 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -10.5,-7.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1332 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -11.5,-7.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1339 + components: + - type: Transform + pos: -4.5,-9.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1340 + components: + - type: Transform + pos: -4.5,-10.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1341 + components: + - type: Transform + pos: -4.5,-8.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1343 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 8.5,4.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1344 + components: + - type: Transform + pos: 10.5,5.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1345 + components: + - type: Transform + pos: 10.5,6.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1346 + components: + - type: Transform + pos: 10.5,7.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1347 + components: + - type: Transform + pos: 10.5,9.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1348 + components: + - type: Transform + pos: 10.5,10.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1349 + components: + - type: Transform + pos: 10.5,11.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1350 + components: + - type: Transform + pos: 10.5,12.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1351 + components: + - type: Transform + pos: 10.5,8.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1352 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 9.5,4.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1355 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -3.5,0.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1392 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 9.5,-23.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1393 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 10.5,-23.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1394 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 11.5,-23.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1395 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 8.5,-22.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1396 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 8.5,-21.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1397 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 8.5,-20.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1398 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 9.5,-19.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1399 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 10.5,-19.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1400 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 11.5,-19.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1401 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 11.5,-15.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1402 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 10.5,-15.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1403 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 9.5,-15.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1404 + components: + - type: Transform + pos: 8.5,-17.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1405 + components: + - type: Transform + pos: 8.5,-18.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1406 + components: + - type: Transform + pos: 8.5,-16.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1407 + components: + - type: Transform + pos: 8.5,-14.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1408 + components: + - type: Transform + pos: 8.5,-13.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1409 + components: + - type: Transform + pos: 8.5,-12.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1468 + components: + - type: Transform + pos: 1.5,12.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1469 + components: + - type: Transform + pos: 1.5,11.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1470 + components: + - type: Transform + pos: 1.5,10.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1471 + components: + - type: Transform + pos: 1.5,9.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1472 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 1.5,5.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1473 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 1.5,4.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1476 + components: + - type: Transform + pos: 9.5,10.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1477 + components: + - type: Transform + pos: 9.5,9.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1478 + components: + - type: Transform + pos: 9.5,8.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1479 + components: + - type: Transform + pos: 9.5,7.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1481 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 8.5,6.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1482 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 7.5,6.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1484 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 5.5,6.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1485 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 4.5,6.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1486 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 3.5,6.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1487 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 2.5,6.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1488 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 1.5,7.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1489 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 1.5,8.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1490 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 0.5,6.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1492 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -0.5,6.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1493 + components: + - type: Transform + pos: -1.5,5.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1494 + components: + - type: Transform + pos: -1.5,4.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1495 + components: + - type: Transform + pos: -1.5,3.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1496 + components: + - type: Transform + pos: -1.5,2.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1498 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: -2.5,1.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1499 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: -3.5,1.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1500 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: -4.5,1.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1501 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: -1.5,0.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1502 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: -1.5,-0.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1503 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: -1.5,-1.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1509 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: -4.5,-4.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1511 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: -6.5,-6.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1512 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: -7.5,-6.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1513 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: -8.5,-6.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1514 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: -9.5,-6.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1515 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: -10.5,-6.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1516 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: -11.5,-6.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1517 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: -5.5,-5.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1519 + components: + - type: Transform + pos: -5.5,-7.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1520 + components: + - type: Transform + pos: -5.5,-8.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1521 + components: + - type: Transform + pos: -5.5,-9.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1523 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: -4.5,-10.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1525 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: -3.5,-13.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1526 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: -3.5,-14.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1527 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: -3.5,-15.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1528 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: -3.5,-16.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1529 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -2.5,-12.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1530 + components: + - type: Transform + pos: -3.5,-11.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1532 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -1.5,-12.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1535 + components: + - type: Transform + pos: -0.5,-14.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1536 + components: + - type: Transform + pos: -0.5,-15.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1537 + components: + - type: Transform + pos: -0.5,-16.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1538 + components: + - type: Transform + pos: -0.5,-17.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1539 + components: + - type: Transform + pos: -0.5,-18.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1540 + components: + - type: Transform + pos: -0.5,-19.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1541 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 0.5,-20.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1542 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 1.5,-20.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1544 + components: + - type: Transform + pos: 2.5,-21.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1546 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 0.5,-13.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1547 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 1.5,-13.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1548 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 2.5,-13.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1549 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 3.5,-13.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1550 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 4.5,-13.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1553 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 6.5,-12.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1554 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 7.5,-12.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1555 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 9.5,-11.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1557 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 8.5,-12.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1558 + components: + - type: Transform + pos: 9.5,-10.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1559 + components: + - type: Transform + pos: 9.5,-9.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1560 + components: + - type: Transform + pos: 9.5,-8.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1561 + components: + - type: Transform + pos: 9.5,-7.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1563 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 10.5,-6.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1564 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 12.5,-6.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1565 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 13.5,-6.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1566 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 14.5,-6.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1567 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 11.5,-6.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1568 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 15.5,-6.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1569 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 16.5,-6.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1570 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 17.5,-6.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1571 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 18.5,-6.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1572 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 19.5,-6.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1573 + components: + - type: Transform + pos: 20.5,-5.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1575 + components: + - type: Transform + pos: 9.5,-5.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1582 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 6.5,-0.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1583 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 6.5,-1.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1584 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 6.5,0.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1586 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 6.5,2.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1587 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 6.5,3.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1588 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 6.5,4.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1589 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 6.5,5.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1590 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 7.5,1.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1591 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 8.5,1.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1592 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 9.5,1.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1593 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 10.5,1.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' +- proto: GasPipeTJunction + entities: + - uid: 1236 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: -4.5,-15.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1243 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -4.5,-11.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1253 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 2.5,-12.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1258 + components: + - type: Transform + pos: 8.5,-11.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1260 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 10.5,-7.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1290 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 7.5,0.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1300 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 2.5,5.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1317 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: -2.5,0.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1322 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: -4.5,-7.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1342 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 7.5,4.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1390 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 8.5,-19.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1391 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 8.5,-15.5 + parent: 2 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1483 + components: + - type: Transform + pos: 6.5,6.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1497 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: -1.5,1.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1510 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: -5.5,-6.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1524 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -3.5,-12.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1534 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -0.5,-13.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1562 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 9.5,-6.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1585 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 6.5,1.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' +- proto: GasVentPump + entities: + - uid: 1224 + components: + - type: Transform + pos: 2.5,-11.5 + parent: 2 + - type: DeviceNetwork + deviceLists: + - 1607 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1225 + components: + - type: Transform + pos: 12.5,-14.5 + parent: 2 + - type: DeviceNetwork + deviceLists: + - 1627 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1226 + components: + - type: Transform + pos: 12.5,-18.5 + parent: 2 + - type: DeviceNetwork + deviceLists: + - 1628 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1227 + components: + - type: Transform + pos: 12.5,-22.5 + parent: 2 + - type: DeviceNetwork + deviceLists: + - 1629 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1228 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 20.5,-10.5 + parent: 2 + - type: DeviceNetwork + deviceLists: + - 1630 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1231 + components: + - type: Transform + pos: 10.5,13.5 + parent: 2 + - type: DeviceNetwork + deviceLists: + - 1620 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1232 + components: + - type: Transform + pos: 2.5,12.5 + parent: 2 + - type: DeviceNetwork + deviceLists: + - 1619 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1233 + components: + - type: Transform + pos: 12.5,1.5 + parent: 2 + - type: DeviceNetwork + deviceLists: + - 1621 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1235 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: -6.5,-16.5 + parent: 2 + - type: DeviceNetwork + deviceLists: + - 1624 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1358 + components: + - type: Transform + pos: -4.5,1.5 + parent: 2 + - type: DeviceNetwork + deviceLists: + - 1622 + - type: AtmosPipeColor + color: '#17E8E2FF' + - uid: 1432 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -12.5,-7.5 + parent: 2 + - type: DeviceNetwork + deviceLists: + - 1623 + - type: AtmosPipeColor + color: '#17E8E2FF' +- proto: GasVentScrubber + entities: + - uid: 1594 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 11.5,1.5 + parent: 2 + - type: DeviceNetwork + deviceLists: + - 1621 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1595 + components: + - type: Transform + pos: 20.5,-4.5 + parent: 2 + - type: DeviceNetwork + deviceLists: + - 1630 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1596 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 2.5,-22.5 + parent: 2 + - type: DeviceNetwork + deviceLists: + - 1607 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1597 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: -3.5,-17.5 + parent: 2 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1598 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -12.5,-6.5 + parent: 2 + - type: DeviceNetwork + deviceLists: + - 1623 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1599 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -5.5,1.5 + parent: 2 + - type: DeviceNetwork + deviceLists: + - 1622 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1600 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 2.5,3.5 + parent: 2 + - type: DeviceNetwork + deviceLists: + - 1619 + - type: AtmosPipeColor + color: '#FF0000FF' + - uid: 1601 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 8.5,11.5 + parent: 2 + - type: DeviceNetwork + deviceLists: + - 1620 + - type: AtmosPipeColor + color: '#FF0000FF' +- proto: GhostBarSpawner + entities: + - uid: 1379 + components: + - type: Transform + pos: 3.5,3.5 + parent: 2 + - uid: 1380 + components: + - type: Transform + pos: 1.5,4.5 + parent: 2 + - uid: 1382 + components: + - type: Transform + pos: 2.5,-7.5 + parent: 2 + - uid: 1384 + components: + - type: Transform + pos: 2.5,-5.5 + parent: 2 +- proto: GravityGeneratorMini + entities: + - uid: 1026 + components: + - type: Transform + pos: -8.5,-22.5 + parent: 2 +- proto: Grille + entities: + - uid: 698 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 14.5,-24.5 + parent: 2 + - uid: 706 + components: + - type: Transform + pos: 14.5,-16.5 + parent: 2 + - uid: 707 + components: + - type: Transform + pos: 14.5,-15.5 + parent: 2 + - uid: 708 + components: + - type: Transform + pos: 14.5,-14.5 + parent: 2 + - uid: 709 + components: + - type: Transform + pos: 14.5,-20.5 + parent: 2 + - uid: 710 + components: + - type: Transform + pos: 14.5,-19.5 + parent: 2 + - uid: 711 + components: + - type: Transform + pos: 14.5,-18.5 + parent: 2 + - uid: 713 + components: + - type: Transform + pos: 19.5,-11.5 + parent: 2 + - uid: 714 + components: + - type: Transform + pos: 20.5,-11.5 + parent: 2 + - uid: 715 + components: + - type: Transform + pos: 21.5,-11.5 + parent: 2 + - uid: 716 + components: + - type: Transform + pos: 11.5,-11.5 + parent: 2 + - uid: 717 + components: + - type: Transform + pos: 11.5,-10.5 + parent: 2 + - uid: 718 + components: + - type: Transform + pos: 12.5,-9.5 + parent: 2 + - uid: 719 + components: + - type: Transform + pos: 13.5,-9.5 + parent: 2 + - uid: 720 + components: + - type: Transform + pos: 14.5,-9.5 + parent: 2 + - uid: 721 + components: + - type: Transform + pos: 15.5,-9.5 + parent: 2 + - uid: 722 + components: + - type: Transform + pos: 12.5,-5.5 + parent: 2 + - uid: 723 + components: + - type: Transform + pos: 13.5,-5.5 + parent: 2 + - uid: 724 + components: + - type: Transform + pos: 14.5,-5.5 + parent: 2 + - uid: 725 + components: + - type: Transform + pos: 15.5,-5.5 + parent: 2 + - uid: 726 + components: + - type: Transform + pos: 11.5,-4.5 + parent: 2 + - uid: 727 + components: + - type: Transform + pos: 11.5,-3.5 + parent: 2 + - uid: 728 + components: + - type: Transform + pos: 10.5,-2.5 + parent: 2 + - uid: 729 + components: + - type: Transform + pos: 10.5,-1.5 + parent: 2 + - uid: 730 + components: + - type: Transform + pos: 9.5,-1.5 + parent: 2 + - uid: 731 + components: + - type: Transform + pos: 9.5,-0.5 + parent: 2 + - uid: 732 + components: + - type: Transform + pos: 20.5,-3.5 + parent: 2 + - uid: 733 + components: + - type: Transform + pos: 21.5,-3.5 + parent: 2 + - uid: 734 + components: + - type: Transform + pos: 19.5,-3.5 + parent: 2 + - uid: 735 + components: + - type: Transform + pos: 24.5,-6.5 + parent: 2 + - uid: 736 + components: + - type: Transform + pos: 24.5,-7.5 + parent: 2 + - uid: 737 + components: + - type: Transform + pos: 24.5,-8.5 + parent: 2 + - uid: 738 + components: + - type: Transform + pos: 14.5,4.5 + parent: 2 + - uid: 739 + components: + - type: Transform + pos: 14.5,5.5 + parent: 2 + - uid: 740 + components: + - type: Transform + pos: 14.5,6.5 + parent: 2 + - uid: 741 + components: + - type: Transform + pos: 0.5,13.5 + parent: 2 + - uid: 742 + components: + - type: Transform + pos: 1.5,13.5 + parent: 2 + - uid: 743 + components: + - type: Transform + pos: 2.5,13.5 + parent: 2 + - uid: 744 + components: + - type: Transform + pos: 3.5,13.5 + parent: 2 + - uid: 745 + components: + - type: Transform + pos: 4.5,13.5 + parent: 2 + - uid: 746 + components: + - type: Transform + pos: -9.5,6.5 + parent: 2 + - uid: 747 + components: + - type: Transform + pos: -9.5,5.5 + parent: 2 + - uid: 748 + components: + - type: Transform + pos: -9.5,4.5 + parent: 2 + - uid: 749 + components: + - type: Transform + pos: -6.5,-4.5 + parent: 2 + - uid: 750 + components: + - type: Transform + pos: -6.5,-3.5 + parent: 2 + - uid: 751 + components: + - type: Transform + pos: -7.5,-5.5 + parent: 2 + - uid: 752 + components: + - type: Transform + pos: -8.5,-5.5 + parent: 2 + - uid: 753 + components: + - type: Transform + pos: -9.5,-5.5 + parent: 2 + - uid: 754 + components: + - type: Transform + pos: -10.5,-5.5 + parent: 2 + - uid: 755 + components: + - type: Transform + pos: -5.5,-2.5 + parent: 2 + - uid: 756 + components: + - type: Transform + pos: -5.5,-1.5 + parent: 2 + - uid: 757 + components: + - type: Transform + pos: -4.5,-1.5 + parent: 2 + - uid: 758 + components: + - type: Transform + pos: -4.5,-0.5 + parent: 2 + - uid: 759 + components: + - type: Transform + pos: -14.5,-3.5 + parent: 2 + - uid: 760 + components: + - type: Transform + pos: -15.5,-3.5 + parent: 2 + - uid: 761 + components: + - type: Transform + pos: -16.5,-3.5 + parent: 2 + - uid: 762 + components: + - type: Transform + pos: -19.5,-6.5 + parent: 2 + - uid: 763 + components: + - type: Transform + pos: -19.5,-7.5 + parent: 2 + - uid: 764 + components: + - type: Transform + pos: -19.5,-8.5 + parent: 2 + - uid: 765 + components: + - type: Transform + pos: -16.5,-11.5 + parent: 2 + - uid: 766 + components: + - type: Transform + pos: -15.5,-11.5 + parent: 2 + - uid: 767 + components: + - type: Transform + pos: -14.5,-11.5 + parent: 2 + - uid: 768 + components: + - type: Transform + pos: -10.5,-9.5 + parent: 2 + - uid: 769 + components: + - type: Transform + pos: -9.5,-9.5 + parent: 2 + - uid: 770 + components: + - type: Transform + pos: -8.5,-9.5 + parent: 2 + - uid: 771 + components: + - type: Transform + pos: -7.5,-9.5 + parent: 2 + - uid: 772 + components: + - type: Transform + pos: -6.5,-10.5 + parent: 2 + - uid: 773 + components: + - type: Transform + pos: -6.5,-11.5 + parent: 2 + - uid: 774 + components: + - type: Transform + pos: -0.5,-22.5 + parent: 2 + - uid: 775 + components: + - type: Transform + pos: -0.5,-23.5 + parent: 2 + - uid: 776 + components: + - type: Transform + pos: 0.5,-23.5 + parent: 2 + - uid: 777 + components: + - type: Transform + pos: 1.5,-23.5 + parent: 2 + - uid: 778 + components: + - type: Transform + pos: 2.5,-23.5 + parent: 2 + - uid: 779 + components: + - type: Transform + pos: 3.5,-23.5 + parent: 2 + - uid: 780 + components: + - type: Transform + pos: 4.5,-23.5 + parent: 2 + - uid: 781 + components: + - type: Transform + pos: 5.5,-23.5 + parent: 2 + - uid: 782 + components: + - type: Transform + pos: 5.5,-22.5 + parent: 2 + - uid: 877 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 14.5,-23.5 + parent: 2 + - uid: 878 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 14.5,-22.5 + parent: 2 +- proto: HarmonicaInstrument + entities: + - uid: 317 + components: + - type: Transform + pos: 0.56536794,12.636257 + parent: 2 +- proto: HarpInstrument + entities: + - uid: 1370 + components: + - type: Transform + pos: -0.5,11.5 + parent: 2 +- proto: HospitalCurtains + entities: + - uid: 1000 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 9.5,10.5 + parent: 2 + - uid: 1001 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 10.5,10.5 + parent: 2 +- proto: hydroponicsTray + entities: + - uid: 271 + components: + - type: Transform + pos: 12.5,-2.5 + parent: 2 + - uid: 272 + components: + - type: Transform + pos: 12.5,-3.5 + parent: 2 + - uid: 273 + components: + - type: Transform + pos: 12.5,-4.5 + parent: 2 + - uid: 274 + components: + - type: Transform + pos: 13.5,-4.5 + parent: 2 + - uid: 275 + components: + - type: Transform + pos: 15.5,-4.5 + parent: 2 + - uid: 276 + components: + - type: Transform + pos: 16.5,-4.5 + parent: 2 + - uid: 277 + components: + - type: Transform + pos: 14.5,-4.5 + parent: 2 + - uid: 278 + components: + - type: Transform + pos: 16.5,-3.5 + parent: 2 + - uid: 279 + components: + - type: Transform + pos: 16.5,-2.5 + parent: 2 + - uid: 280 + components: + - type: Transform + pos: 16.5,-1.5 + parent: 2 + - uid: 281 + components: + - type: Transform + pos: 15.5,-1.5 + parent: 2 +- proto: Jukebox + entities: + - uid: 712 + components: + - type: Transform + pos: 2.5,12.5 + parent: 2 +- proto: KitchenElectricGrill + entities: + - uid: 1041 + components: + - type: Transform + pos: 11.5,5.5 + parent: 2 +- proto: KitchenMicrowave + entities: + - uid: 1040 + components: + - type: Transform + pos: 13.5,4.5 + parent: 2 +- proto: KitchenReagentGrinder + entities: + - uid: 683 + components: + - type: Transform + pos: 13.5,3.5 + parent: 2 +- proto: LockerBoozeFilled + entities: + - uid: 798 + components: + - type: Transform + pos: -4.5,3.5 + parent: 2 +- proto: LockerFreezerBase + entities: + - uid: 1005 + components: + - type: Transform + pos: 9.5,13.5 + parent: 2 +- proto: MarimbaInstrument + entities: + - uid: 1368 + components: + - type: Transform + pos: 5.5,11.5 + parent: 2 +- proto: MaterialWoodPlank + entities: + - uid: 1014 + components: + - type: Transform + pos: -7.4366255,-19.28501 + parent: 2 +- proto: MedicatedSuture + entities: + - uid: 1614 + components: + - type: Transform + pos: 3.0866175,-22.623262 + parent: 2 + - uid: 1615 + components: + - type: Transform + pos: 2.6185322,-22.623262 + parent: 2 + - uid: 1616 + components: + - type: Transform + pos: 2.5972557,-22.325392 + parent: 2 + - uid: 1617 + components: + - type: Transform + pos: 3.0440636,-22.346668 + parent: 2 + - uid: 1618 + components: + - type: Transform + pos: 2.8738508,-22.45305 + parent: 2 +- proto: OxygenCanister + entities: + - uid: 1011 + components: + - type: Transform + pos: -6.5,-19.5 + parent: 2 +- proto: PanFluteInstrument + entities: + - uid: 321 + components: + - type: Transform + pos: 4.3646,12.437675 + parent: 2 +- proto: PlushieHampter + entities: + - uid: 1666 + components: + - type: Transform + pos: -5.189356,14.452841 + parent: 2 +- proto: PlushieMoth + entities: + - uid: 1667 + components: + - type: Transform + pos: -4.9418263,14.504925 + parent: 2 +- proto: PlushieSharkGrey + entities: + - uid: 1665 + components: + - type: Transform + pos: -5.34569,14.765341 + parent: 2 +- proto: PlushieSharkPink + entities: + - uid: 1664 + components: + - type: Transform + pos: -5.593219,14.46586 + parent: 2 +- proto: PlushieXeno + entities: + - uid: 1668 + components: + - type: Transform + pos: -4.79852,14.726278 + parent: 2 +- proto: PosterContrabandBeachStarYamamoto + entities: + - uid: 1695 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: -18.5,-5.5 + parent: 2 +- proto: PosterContrabandBustyBackdoorExoBabes6 + entities: + - uid: 891 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 10.5,-24.5 + parent: 2 +- proto: PosterContrabandGreyTide + entities: + - uid: 252 + components: + - type: Transform + pos: -7.5,2.5 + parent: 2 +- proto: PosterContrabandLustyExomorph + entities: + - uid: 888 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 13.5,-25.5 + parent: 2 +- proto: PosterContrabandSyndicateRecruitment + entities: + - uid: 238 + components: + - type: Transform + pos: -10.5,1.5 + parent: 2 +- proto: PosterLegitCarpMount + entities: + - uid: 1692 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: -6.5,9.5 + parent: 2 +- proto: PosterLegitHighClassMartini + entities: + - uid: 1693 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: -3.5,3.5 + parent: 2 +- proto: PosterLegitNanotrasenLogo + entities: + - uid: 251 + components: + - type: Transform + pos: -12.5,-4.5 + parent: 2 +- proto: PosterLegitRenault + entities: + - uid: 256 + components: + - type: Transform + pos: -12.5,-2.5 + parent: 2 +- proto: PosterLegitSecWatch + entities: + - uid: 253 + components: + - type: Transform + pos: -12.5,-3.5 + parent: 2 +- proto: PosterLegitVacation + entities: + - uid: 1691 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: -13.5,-4.5 + parent: 2 +- proto: PottedPlant10 + entities: + - uid: 1455 + components: + - type: Transform + pos: 4.5,1.5 + parent: 2 +- proto: PottedPlant14 + entities: + - uid: 1456 + components: + - type: Transform + pos: 0.5,1.5 + parent: 2 +- proto: PottedPlant15 + entities: + - uid: 1460 + components: + - type: Transform + pos: 4.5,3.5 + parent: 2 +- proto: PottedPlant22 + entities: + - uid: 1457 + components: + - type: Transform + pos: 15.5,-6.5 + parent: 2 + - uid: 1458 + components: + - type: Transform + pos: 15.5,-8.5 + parent: 2 +- proto: PottedPlantAlt2 + entities: + - uid: 1461 + components: + - type: Transform + pos: 0.5,9.5 + parent: 2 +- proto: PottedPlantAlt3 + entities: + - uid: 1462 + components: + - type: Transform + pos: 4.5,9.5 + parent: 2 +- proto: PottedPlantAlt8 + entities: + - uid: 1459 + components: + - type: Transform + pos: 0.5,3.5 + parent: 2 +- proto: PoweredLEDLightPostSmall + entities: + - uid: 1672 + components: + - type: Transform + pos: -0.5,17.5 + parent: 2 + - uid: 1673 + components: + - type: Transform + pos: 5.5,17.5 + parent: 2 +- proto: Poweredlight + entities: + - uid: 924 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 5.5,3.5 + parent: 2 + - uid: 925 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: -0.5,3.5 + parent: 2 + - uid: 926 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 13.5,7.5 + parent: 2 + - uid: 927 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 14.5,0.5 + parent: 2 + - uid: 928 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 16.5,-4.5 + parent: 2 + - uid: 929 + components: + - type: Transform + pos: 22.5,-5.5 + parent: 2 + - uid: 930 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 18.5,-9.5 + parent: 2 + - uid: 931 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 11.5,-8.5 + parent: 2 + - uid: 932 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 7.5,-12.5 + parent: 2 + - uid: 933 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: -2.5,-12.5 + parent: 2 + - uid: 934 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -1.5,-18.5 + parent: 2 + - uid: 935 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 6.5,-18.5 + parent: 2 + - uid: 936 + components: + - type: Transform + pos: -6.5,-19.5 + parent: 2 + - uid: 938 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: -7.5,-17.5 + parent: 2 + - uid: 939 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -17.5,-9.5 + parent: 2 + - uid: 940 + components: + - type: Transform + pos: -13.5,-5.5 + parent: 2 + - uid: 941 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: -6.5,3.5 + parent: 2 + - uid: 942 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -7.5,12.5 + parent: 2 + - uid: 943 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 8.5,12.5 + parent: 2 + - uid: 944 + components: + - type: Transform + pos: 5.5,-3.5 + parent: 2 + - uid: 945 + components: + - type: Transform + pos: -0.5,-3.5 + parent: 2 + - uid: 946 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: -6.5,-8.5 + parent: 2 + - uid: 1054 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: -3.5,-16.5 + parent: 2 +- proto: PoweredlightLED + entities: + - uid: 1363 + components: + - type: Transform + pos: -4.5,1.5 + parent: 2 + - uid: 1364 + components: + - type: Transform + pos: -10.5,-0.5 + parent: 2 +- proto: PoweredSmallLight + entities: + - uid: 914 + components: + - type: Transform + pos: 12.5,-22.5 + parent: 2 + - uid: 921 + components: + - type: Transform + pos: 3.5,1.5 + parent: 2 + - uid: 922 + components: + - type: Transform + pos: 6.5,8.5 + parent: 2 + - uid: 923 + components: + - type: Transform + pos: -1.5,8.5 + parent: 2 + - uid: 937 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: -3.5,-24.5 + parent: 2 + - uid: 947 + components: + - type: Transform + pos: 12.5,-18.5 + parent: 2 + - uid: 948 + components: + - type: Transform + pos: 12.5,-14.5 + parent: 2 + - uid: 1039 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 8.5,-17.5 + parent: 2 + - uid: 1051 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: -5.5,-24.5 + parent: 2 + - uid: 1052 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: -7.5,-24.5 + parent: 2 + - uid: 1053 + components: + - type: Transform + pos: -7.5,-19.5 + parent: 2 + - uid: 1359 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 5.5,11.5 + parent: 2 + - uid: 1360 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -0.5,11.5 + parent: 2 + - uid: 1361 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: -2.5,12.5 + parent: 2 + - uid: 1362 + components: + - type: Transform + pos: -6.5,8.5 + parent: 2 + - uid: 1375 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 7.5,-0.5 + parent: 2 + - uid: 1376 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -2.5,-0.5 + parent: 2 +- proto: Railing + entities: + - uid: 835 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 4.5,-18.5 + parent: 2 + - uid: 836 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 4.5,-17.5 + parent: 2 + - uid: 837 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 4.5,-16.5 + parent: 2 + - uid: 838 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 1.5,-15.5 + parent: 2 + - uid: 839 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 2.5,-15.5 + parent: 2 + - uid: 840 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 3.5,-15.5 + parent: 2 + - uid: 841 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 0.5,-18.5 + parent: 2 + - uid: 842 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 0.5,-17.5 + parent: 2 + - uid: 843 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 0.5,-16.5 + parent: 2 + - uid: 844 + components: + - type: Transform + pos: 1.5,-19.5 + parent: 2 + - uid: 845 + components: + - type: Transform + pos: 3.5,-19.5 + parent: 2 + - uid: 846 + components: + - type: Transform + pos: 2.5,-19.5 + parent: 2 + - uid: 974 + components: + - type: Transform + pos: 1.5,9.5 + parent: 2 + - uid: 975 + components: + - type: Transform + pos: 2.5,9.5 + parent: 2 + - uid: 976 + components: + - type: Transform + pos: 3.5,9.5 + parent: 2 +- proto: RailingCorner + entities: + - uid: 831 + components: + - type: Transform + pos: 4.5,-19.5 + parent: 2 + - uid: 832 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 0.5,-19.5 + parent: 2 + - uid: 833 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 0.5,-15.5 + parent: 2 + - uid: 834 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 4.5,-15.5 + parent: 2 + - uid: 972 + components: + - type: Transform + pos: 4.5,9.5 + parent: 2 + - uid: 973 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 0.5,9.5 + parent: 2 +- proto: RailingCornerSmall + entities: + - uid: 977 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 4.5,10.5 + parent: 2 + - uid: 978 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 0.5,10.5 + parent: 2 +- proto: RandomPosterLegit + entities: + - uid: 1683 + components: + - type: Transform + pos: 7.5,9.5 + parent: 2 + - uid: 1684 + components: + - type: Transform + pos: -1.5,9.5 + parent: 2 + - uid: 1685 + components: + - type: Transform + pos: -2.5,-13.5 + parent: 2 + - uid: 1686 + components: + - type: Transform + pos: 7.5,-14.5 + parent: 2 + - uid: 1687 + components: + - type: Transform + pos: 10.5,-17.5 + parent: 2 + - uid: 1688 + components: + - type: Transform + pos: 16.5,-6.5 + parent: 2 + - uid: 1689 + components: + - type: Transform + pos: 23.5,-5.5 + parent: 2 +- proto: RandomVendingDrinks + entities: + - uid: 1374 + components: + - type: Transform + pos: 9.5,-21.5 + parent: 2 +- proto: RandomVendingSnacks + entities: + - uid: 1373 + components: + - type: Transform + pos: 8.5,-21.5 + parent: 2 + - uid: 1608 + components: + - type: Transform + pos: -10.5,-6.5 + parent: 2 +- proto: RecorderInstrument + entities: + - uid: 319 + components: + - type: Transform + pos: 4.634104,12.536966 + parent: 2 +- proto: RegenerativeMesh + entities: + - uid: 1609 + components: + - type: Transform + pos: 1.7196245,-22.750923 + parent: 2 + - uid: 1610 + components: + - type: Transform + pos: 1.6557951,-22.304113 + parent: 2 + - uid: 1611 + components: + - type: Transform + pos: 2.0813265,-22.304113 + parent: 2 + - uid: 1612 + components: + - type: Transform + pos: 2.102603,-22.687094 + parent: 2 + - uid: 1613 + components: + - type: Transform + pos: 1.9323893,-22.538157 + parent: 2 +- proto: ReinforcedPlasmaWindow + entities: + - uid: 166 + components: + - type: Transform + pos: 0.5,13.5 + parent: 2 + - uid: 167 + components: + - type: Transform + pos: 2.5,13.5 + parent: 2 + - uid: 168 + components: + - type: Transform + pos: 3.5,13.5 + parent: 2 + - uid: 169 + components: + - type: Transform + pos: 4.5,13.5 + parent: 2 + - uid: 170 + components: + - type: Transform + pos: 1.5,13.5 + parent: 2 + - uid: 494 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 14.5,-24.5 + parent: 2 + - uid: 540 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 14.5,-23.5 + parent: 2 + - uid: 542 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 14.5,-22.5 + parent: 2 +- proto: ReinforcedWindow + entities: + - uid: 79 + components: + - type: Transform + pos: -9.5,5.5 + parent: 2 + - uid: 80 + components: + - type: Transform + pos: -9.5,4.5 + parent: 2 + - uid: 81 + components: + - type: Transform + pos: -9.5,6.5 + parent: 2 + - uid: 84 + components: + - type: Transform + pos: -6.5,-4.5 + parent: 2 + - uid: 171 + components: + - type: Transform + pos: 14.5,4.5 + parent: 2 + - uid: 172 + components: + - type: Transform + pos: 14.5,5.5 + parent: 2 + - uid: 173 + components: + - type: Transform + pos: 14.5,6.5 + parent: 2 + - uid: 174 + components: + - type: Transform + pos: -6.5,-3.5 + parent: 2 + - uid: 175 + components: + - type: Transform + pos: -4.5,-0.5 + parent: 2 + - uid: 176 + components: + - type: Transform + pos: -4.5,-1.5 + parent: 2 + - uid: 177 + components: + - type: Transform + pos: -5.5,-1.5 + parent: 2 + - uid: 178 + components: + - type: Transform + pos: -5.5,-2.5 + parent: 2 + - uid: 179 + components: + - type: Transform + pos: -6.5,-10.5 + parent: 2 + - uid: 180 + components: + - type: Transform + pos: -6.5,-11.5 + parent: 2 + - uid: 181 + components: + - type: Transform + pos: -7.5,-5.5 + parent: 2 + - uid: 182 + components: + - type: Transform + pos: -8.5,-5.5 + parent: 2 + - uid: 183 + components: + - type: Transform + pos: -9.5,-5.5 + parent: 2 + - uid: 184 + components: + - type: Transform + pos: -10.5,-5.5 + parent: 2 + - uid: 185 + components: + - type: Transform + pos: -10.5,-9.5 + parent: 2 + - uid: 186 + components: + - type: Transform + pos: -8.5,-9.5 + parent: 2 + - uid: 187 + components: + - type: Transform + pos: -7.5,-9.5 + parent: 2 + - uid: 188 + components: + - type: Transform + pos: -9.5,-9.5 + parent: 2 + - uid: 189 + components: + - type: Transform + pos: -14.5,-11.5 + parent: 2 + - uid: 190 + components: + - type: Transform + pos: -15.5,-11.5 + parent: 2 + - uid: 191 + components: + - type: Transform + pos: -16.5,-11.5 + parent: 2 + - uid: 192 + components: + - type: Transform + pos: -16.5,-3.5 + parent: 2 + - uid: 193 + components: + - type: Transform + pos: -15.5,-3.5 + parent: 2 + - uid: 194 + components: + - type: Transform + pos: -14.5,-3.5 + parent: 2 + - uid: 195 + components: + - type: Transform + pos: 11.5,-3.5 + parent: 2 + - uid: 196 + components: + - type: Transform + pos: 11.5,-4.5 + parent: 2 + - uid: 197 + components: + - type: Transform + pos: 10.5,-2.5 + parent: 2 + - uid: 198 + components: + - type: Transform + pos: 10.5,-1.5 + parent: 2 + - uid: 199 + components: + - type: Transform + pos: 9.5,-1.5 + parent: 2 + - uid: 200 + components: + - type: Transform + pos: 9.5,-0.5 + parent: 2 + - uid: 201 + components: + - type: Transform + pos: 12.5,-5.5 + parent: 2 + - uid: 202 + components: + - type: Transform + pos: 14.5,-5.5 + parent: 2 + - uid: 203 + components: + - type: Transform + pos: 13.5,-5.5 + parent: 2 + - uid: 204 + components: + - type: Transform + pos: 15.5,-5.5 + parent: 2 + - uid: 205 + components: + - type: Transform + pos: 12.5,-9.5 + parent: 2 + - uid: 206 + components: + - type: Transform + pos: 13.5,-9.5 + parent: 2 + - uid: 207 + components: + - type: Transform + pos: 14.5,-9.5 + parent: 2 + - uid: 208 + components: + - type: Transform + pos: 15.5,-9.5 + parent: 2 + - uid: 209 + components: + - type: Transform + pos: 11.5,-10.5 + parent: 2 + - uid: 210 + components: + - type: Transform + pos: 11.5,-11.5 + parent: 2 + - uid: 211 + components: + - type: Transform + pos: 19.5,-11.5 + parent: 2 + - uid: 212 + components: + - type: Transform + pos: 20.5,-11.5 + parent: 2 + - uid: 213 + components: + - type: Transform + pos: 21.5,-11.5 + parent: 2 + - uid: 214 + components: + - type: Transform + pos: 19.5,-3.5 + parent: 2 + - uid: 215 + components: + - type: Transform + pos: 20.5,-3.5 + parent: 2 + - uid: 216 + components: + - type: Transform + pos: 21.5,-3.5 + parent: 2 + - uid: 217 + components: + - type: Transform + pos: 24.5,-8.5 + parent: 2 + - uid: 218 + components: + - type: Transform + pos: 24.5,-7.5 + parent: 2 + - uid: 219 + components: + - type: Transform + pos: 24.5,-6.5 + parent: 2 + - uid: 220 + components: + - type: Transform + pos: -19.5,-8.5 + parent: 2 + - uid: 221 + components: + - type: Transform + pos: -19.5,-7.5 + parent: 2 + - uid: 222 + components: + - type: Transform + pos: -19.5,-6.5 + parent: 2 + - uid: 521 + components: + - type: Transform + pos: 5.5,-23.5 + parent: 2 + - uid: 522 + components: + - type: Transform + pos: 3.5,-23.5 + parent: 2 + - uid: 526 + components: + - type: Transform + pos: 5.5,-22.5 + parent: 2 + - uid: 528 + components: + - type: Transform + pos: 4.5,-23.5 + parent: 2 + - uid: 586 + components: + - type: Transform + pos: 2.5,-23.5 + parent: 2 + - uid: 587 + components: + - type: Transform + pos: 0.5,-23.5 + parent: 2 + - uid: 588 + components: + - type: Transform + pos: -0.5,-23.5 + parent: 2 + - uid: 589 + components: + - type: Transform + pos: 1.5,-23.5 + parent: 2 + - uid: 590 + components: + - type: Transform + pos: -0.5,-22.5 + parent: 2 + - uid: 667 + components: + - type: Transform + pos: -5.5,-21.5 + parent: 2 + - uid: 670 + components: + - type: Transform + pos: -3.5,-21.5 + parent: 2 + - uid: 700 + components: + - type: Transform + pos: 14.5,-20.5 + parent: 2 + - uid: 701 + components: + - type: Transform + pos: 14.5,-19.5 + parent: 2 + - uid: 702 + components: + - type: Transform + pos: 14.5,-18.5 + parent: 2 + - uid: 703 + components: + - type: Transform + pos: 14.5,-16.5 + parent: 2 + - uid: 704 + components: + - type: Transform + pos: 14.5,-15.5 + parent: 2 + - uid: 705 + components: + - type: Transform + pos: 14.5,-14.5 + parent: 2 + - uid: 979 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 0.5,-2.5 + parent: 2 + - uid: 980 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 1.5,-2.5 + parent: 2 + - uid: 981 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 2.5,-2.5 + parent: 2 + - uid: 982 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 4.5,-2.5 + parent: 2 + - uid: 983 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 3.5,-2.5 + parent: 2 +- proto: RGBStaff + entities: + - uid: 1365 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 12.046281,-23.989346 + parent: 2 +- proto: RockGuitarInstrument + entities: + - uid: 316 + components: + - type: Transform + pos: 0.14132857,12.419422 + parent: 2 +- proto: SeedExtractor + entities: + - uid: 268 + components: + - type: Transform + pos: 14.5,0.5 + parent: 2 +- proto: SheetGlass + entities: + - uid: 1013 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: -7.347678,-19.353334 + parent: 2 +- proto: SheetSteel + entities: + - uid: 1012 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: -7.7306566,-19.459719 + parent: 2 +- proto: SignBar + entities: + - uid: 792 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -3.5,8.5 + parent: 2 +- proto: SignHydro1 + entities: + - uid: 283 + components: + - type: Transform + pos: 8.5,-0.5 + parent: 2 +- proto: SignJanitor + entities: + - uid: 962 + components: + - type: Transform + pos: -5.5,-14.5 + parent: 2 +- proto: SignKitchen + entities: + - uid: 1698 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 8.5,3.5 + parent: 2 +- proto: SignLibrary + entities: + - uid: 1699 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 16.5,-8.5 + parent: 2 +- proto: SodaDispenser + entities: + - uid: 797 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -8.5,6.5 + parent: 2 +- proto: SpaceCash + entities: + - uid: 1338 + components: + - type: Transform + pos: -10.4903965,-0.38488388 + parent: 2 + - type: Stack + count: 1000000 +- proto: SpaceHeaterEnabled + entities: + - uid: 688 + components: + - type: Transform + pos: 11.5,13.5 + parent: 2 + - type: SpaceHeater + powerLevel: High + - type: GasThermoMachine + targetTemperature: 263.15 + heatCapacity: 7000 +- proto: SpaceVillainArcadeFilled + entities: + - uid: 262 + components: + - type: Transform + pos: -3.5,14.5 + parent: 2 + - uid: 263 + components: + - type: Transform + pos: -2.5,14.5 + parent: 2 +- proto: SpawnMobCatKitten + entities: + - uid: 659 + components: + - type: Transform + pos: 1.5,6.5 + parent: 2 +- proto: SpawnMobCow + entities: + - uid: 1077 + components: + - type: Transform + pos: 13.5,-3.5 + parent: 2 +- proto: SpawnMobGoat + entities: + - uid: 1105 + components: + - type: Transform + pos: 15.5,-2.5 + parent: 2 +- proto: SprayBottleSpaceCleaner + entities: + - uid: 1056 + components: + - type: Transform + pos: -8.906613,-15.57811 + parent: 2 + - uid: 1057 + components: + - type: Transform + pos: -8.509451,-15.606478 + parent: 2 + - uid: 1058 + components: + - type: Transform + pos: -8.268316,-15.606478 + parent: 2 +- proto: StairWood + entities: + - uid: 306 + components: + - type: Transform + pos: -0.5,9.5 + parent: 2 + - uid: 307 + components: + - type: Transform + pos: 5.5,9.5 + parent: 2 +- proto: StoolBar + entities: + - uid: 295 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: -2.5,4.5 + parent: 2 + - uid: 296 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: -2.5,6.5 + parent: 2 + - uid: 297 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: -2.5,7.5 + parent: 2 + - uid: 298 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: -2.5,5.5 + parent: 2 +- proto: SuperSynthesizerInstrument + entities: + - uid: 1367 + components: + - type: Transform + pos: 5.7664986,12.363361 + parent: 2 +- proto: SyndieFlag + entities: + - uid: 239 + components: + - type: Transform + pos: -8.5,2.5 + parent: 2 +- proto: SynthesizerInstrument + entities: + - uid: 1366 + components: + - type: Transform + pos: 5.2820907,12.374964 + parent: 2 +- proto: Table + entities: + - uid: 1010 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: -7.5,-19.5 + parent: 2 +- proto: TableCarpet + entities: + - uid: 248 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: -10.5,-0.5 + parent: 2 + - uid: 260 + components: + - type: Transform + pos: -4.5,14.5 + parent: 2 + - uid: 261 + components: + - type: Transform + pos: -5.5,14.5 + parent: 2 + - uid: 308 + components: + - type: Transform + pos: 5.5,12.5 + parent: 2 + - uid: 309 + components: + - type: Transform + pos: -0.5,12.5 + parent: 2 + - uid: 310 + components: + - type: Transform + pos: 0.5,12.5 + parent: 2 + - uid: 311 + components: + - type: Transform + pos: 4.5,12.5 + parent: 2 + - uid: 851 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 19.5,-8.5 + parent: 2 + - uid: 852 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 19.5,-7.5 + parent: 2 + - uid: 853 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 19.5,-6.5 + parent: 2 + - uid: 854 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 20.5,-8.5 + parent: 2 + - uid: 855 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 20.5,-7.5 + parent: 2 + - uid: 856 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 20.5,-6.5 + parent: 2 + - uid: 857 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 21.5,-8.5 + parent: 2 + - uid: 858 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 21.5,-7.5 + parent: 2 + - uid: 859 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 21.5,-6.5 + parent: 2 + - uid: 1713 + components: + - type: Transform + pos: -9.5,-0.5 + parent: 2 +- proto: TableFancyWhite + entities: + - uid: 290 + components: + - type: Transform + pos: 4.5,3.5 + parent: 2 + - uid: 291 + components: + - type: Transform + pos: 0.5,4.5 + parent: 2 + - uid: 292 + components: + - type: Transform + pos: 0.5,3.5 + parent: 2 + - uid: 293 + components: + - type: Transform + pos: 4.5,4.5 + parent: 2 +- proto: TableReinforced + entities: + - uid: 690 + components: + - type: Transform + pos: 11.5,4.5 + parent: 2 + - uid: 691 + components: + - type: Transform + pos: 11.5,6.5 + parent: 2 + - uid: 692 + components: + - type: Transform + pos: 11.5,7.5 + parent: 2 + - uid: 693 + components: + - type: Transform + pos: 11.5,5.5 + parent: 2 + - uid: 694 + components: + - type: Transform + pos: 13.5,3.5 + parent: 2 + - uid: 695 + components: + - type: Transform + pos: 13.5,4.5 + parent: 2 + - uid: 696 + components: + - type: Transform + pos: 13.5,5.5 + parent: 2 + - uid: 783 + components: + - type: Transform + pos: 8.5,6.5 + parent: 2 + - uid: 784 + components: + - type: Transform + pos: 8.5,7.5 + parent: 2 + - uid: 950 + components: + - type: Transform + pos: 4.5,-22.5 + parent: 2 + - uid: 951 + components: + - type: Transform + pos: 3.5,-22.5 + parent: 2 + - uid: 952 + components: + - type: Transform + pos: 1.5,-22.5 + parent: 2 + - uid: 953 + components: + - type: Transform + pos: 0.5,-22.5 + parent: 2 + - uid: 954 + components: + - type: Transform + pos: 2.5,-22.5 + parent: 2 +- proto: TableStone + entities: + - uid: 689 + components: + - type: Transform + pos: 11.5,2.5 + parent: 2 + - uid: 965 + components: + - type: Transform + pos: -7.5,-14.5 + parent: 2 + - uid: 966 + components: + - type: Transform + pos: -8.5,-14.5 + parent: 2 + - uid: 967 + components: + - type: Transform + pos: -8.5,-15.5 + parent: 2 +- proto: TableWood + entities: + - uid: 286 + components: + - type: Transform + pos: -3.5,4.5 + parent: 2 + - uid: 287 + components: + - type: Transform + pos: -3.5,5.5 + parent: 2 + - uid: 288 + components: + - type: Transform + pos: -3.5,7.5 + parent: 2 + - uid: 289 + components: + - type: Transform + pos: -3.5,6.5 + parent: 2 + - uid: 785 + components: + - type: Transform + pos: -8.5,3.5 + parent: 2 + - uid: 786 + components: + - type: Transform + pos: -8.5,4.5 + parent: 2 + - uid: 787 + components: + - type: Transform + pos: -8.5,5.5 + parent: 2 + - uid: 788 + components: + - type: Transform + pos: -8.5,6.5 + parent: 2 + - uid: 1356 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 3.5,-1.5 + parent: 2 + - uid: 1383 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 4.5,-1.5 + parent: 2 + - uid: 1603 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 4.5,-0.5 + parent: 2 +- proto: TelecomServerFilled + entities: + - uid: 1027 + components: + - type: Transform + pos: -8.5,-21.5 + parent: 2 +- proto: TomDrumsInstrument + entities: + - uid: 1371 + components: + - type: Transform + pos: 4.5,11.5 + parent: 2 + - type: Pullable + prevFixedRotation: True +- proto: ToyFigurineClown + entities: + - uid: 1677 + components: + - type: Transform + pos: 19.904709,-8.243494 + parent: 2 +- proto: ToyFigurineGreytider + entities: + - uid: 1675 + components: + - type: Transform + pos: 21.025105,-6.720057 + parent: 2 +- proto: ToyFigurineNukieElite + entities: + - uid: 1682 + components: + - type: Transform + pos: 21.598331,-7.058599 + parent: 2 +- proto: ToyFigurineQueen + entities: + - uid: 1679 + components: + - type: Transform + pos: 20.881798,-7.4622445 + parent: 2 +- proto: ToyFigurineRatKing + entities: + - uid: 1680 + components: + - type: Transform + pos: 20.660324,-7.891932 + parent: 2 +- proto: ToyFigurineSalvage + entities: + - uid: 1681 + components: + - type: Transform + pos: 20.20435,-6.342453 + parent: 2 +- proto: ToyFigurineSpaceDragon + entities: + - uid: 1678 + components: + - type: Transform + pos: 20.217377,-7.592453 + parent: 2 +- proto: ToyFigurineWizard + entities: + - uid: 1674 + components: + - type: Transform + pos: 21.337772,-7.970057 + parent: 2 +- proto: ToyGriffin + entities: + - uid: 1676 + components: + - type: Transform + pos: 19.813515,-7.0716195 + parent: 2 +- proto: ToySword + entities: + - uid: 674 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 1.0552558,-22.466475 + parent: 2 + - uid: 676 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 1.0741682,-22.258438 + parent: 2 +- proto: TromboneInstrument + entities: + - uid: 1369 + components: + - type: Transform + pos: 4.969984,12.560329 + parent: 2 +- proto: TrumpetInstrument + entities: + - uid: 318 + components: + - type: Transform + pos: 4.4213376,12.749733 + parent: 2 +- proto: UprightPianoInstrument + entities: + - uid: 806 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 1.5,12.5 + parent: 2 +- proto: VendingBarDrobe + entities: + - uid: 789 + components: + - type: Transform + pos: -8.5,8.5 + parent: 2 + - type: AccessReader + enabled: False + - type: Emagged +- proto: VendingMachineBooze + entities: + - uid: 795 + components: + - type: Transform + pos: -4.5,8.5 + parent: 2 + - type: AccessReader + enabled: False + - type: Emagged +- proto: VendingMachineCargoDrobe + entities: + - uid: 804 + components: + - type: Transform + pos: -8.5,-4.5 + parent: 2 + - type: AccessReader + enabled: False + - type: Emagged +- proto: VendingMachineCentDrobe + entities: + - uid: 240 + components: + - type: Transform + pos: -11.5,-4.5 + parent: 2 + - type: AccessReader + enabled: False + - type: Emagged +- proto: VendingMachineChang + entities: + - uid: 808 + components: + - type: Transform + pos: -5.5,-12.5 + parent: 2 + - type: Emagged +- proto: VendingMachineChapel + entities: + - uid: 1634 + components: + - type: Transform + pos: -6.5,-1.5 + parent: 2 + - type: AccessReader + enabled: False + - type: Emagged +- proto: VendingMachineChefvend + entities: + - uid: 697 + components: + - type: Transform + pos: 13.5,7.5 + parent: 2 + - type: AccessReader + enabled: False + - type: Emagged +- proto: VendingMachineCigs + entities: + - uid: 249 + components: + - type: Transform + pos: -10.5,-8.5 + parent: 2 + - uid: 1022 + components: + - type: Transform + pos: 7.5,8.5 + parent: 2 +- proto: VendingMachineClothing + entities: + - uid: 244 + components: + - type: Transform + pos: -6.5,1.5 + parent: 2 + - type: Emagged +- proto: VendingMachineCuraDrobe + entities: + - uid: 1700 + components: + - type: Transform + pos: -7.5,-2.5 + parent: 2 + - type: AccessReader + enabled: False + - type: Emagged +- proto: VendingMachineDetDrobe + entities: + - uid: 800 + components: + - type: Transform + pos: -10.5,-4.5 + parent: 2 + - type: AccessReader + enabled: False + - type: Emagged +- proto: VendingMachineDinnerware + entities: + - uid: 699 + components: + - type: Transform + pos: 13.5,8.5 + parent: 2 + - type: AccessReader + enabled: False + - type: Emagged +- proto: VendingMachineDonut + entities: + - uid: 809 + components: + - type: Transform + pos: 10.5,-3.5 + parent: 2 +- proto: VendingMachineEngiDrobe + entities: + - uid: 805 + components: + - type: Transform + pos: -7.5,-3.5 + parent: 2 + - type: AccessReader + enabled: False + - type: Emagged +- proto: VendingMachineGames + entities: + - uid: 870 + components: + - type: Transform + pos: 20.5,-4.5 + parent: 2 +- proto: VendingMachineJaniDrobe + entities: + - uid: 961 + components: + - type: Transform + pos: -6.5,-14.5 + parent: 2 + - type: AccessReader + enabled: False + - type: Emagged +- proto: VendingMachineLawDrobe + entities: + - uid: 1633 + components: + - type: Transform + pos: -9.5,0.5 + parent: 2 + - type: AccessReader + enabled: False + - type: Emagged +- proto: VendingMachineMediDrobe + entities: + - uid: 802 + components: + - type: Transform + pos: -11.5,-2.5 + parent: 2 + - type: AccessReader + enabled: False + - type: Emagged +- proto: VendingMachineNutri + entities: + - uid: 266 + components: + - type: Transform + pos: 14.5,1.5 + parent: 2 + - type: AccessReader + enabled: False + - type: Emagged +- proto: VendingMachineSciDrobe + entities: + - uid: 803 + components: + - type: Transform + pos: -10.5,-1.5 + parent: 2 + - type: AccessReader + enabled: False + - type: Emagged +- proto: VendingMachineSecDrobe + entities: + - uid: 801 + components: + - type: Transform + pos: -11.5,-3.5 + parent: 2 + - type: AccessReader + enabled: False + - type: Emagged +- proto: VendingMachineSeedsUnlocked + entities: + - uid: 267 + components: + - type: Transform + pos: 13.5,1.5 + parent: 2 + - type: Emagged +- proto: VendingMachineShamblersJuice + entities: + - uid: 1059 + components: + - type: Transform + pos: -7.5,10.5 + parent: 2 + - type: Emagged +- proto: VendingMachineSnack + entities: + - uid: 810 + components: + - type: Transform + pos: -4.5,-2.5 + parent: 2 + - type: Emagged + - uid: 1060 + components: + - type: Transform + pos: -6.5,10.5 + parent: 2 + - type: Emagged +- proto: VendingMachineSnackOrange + entities: + - uid: 807 + components: + - type: Transform + pos: 10.5,-12.5 + parent: 2 +- proto: VendingMachineSpaceUp + entities: + - uid: 591 + components: + - type: Transform + pos: -5.5,-3.5 + parent: 2 + - type: Emagged +- proto: VendingMachineStarkist + entities: + - uid: 593 + components: + - type: Transform + pos: 9.5,-2.5 + parent: 2 +- proto: VendingMachineSyndieDrobe + entities: + - uid: 237 + components: + - type: Transform + pos: -9.5,1.5 + parent: 2 + - type: AccessReader + enabled: False + - type: Emagged +- proto: VendingMachineTheater + entities: + - uid: 799 + components: + - type: Transform + pos: -8.5,1.5 + parent: 2 + - type: Emagged +- proto: VendingMachineWinter + entities: + - uid: 245 + components: + - type: Transform + pos: -11.5,-1.5 + parent: 2 + - type: Emagged +- proto: VendingMachineYouTool + entities: + - uid: 592 + components: + - type: Transform + pos: -8.5,-19.5 + parent: 2 + - type: Emagged +- proto: WallmountTelevision + entities: + - uid: 871 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -9.5,7.5 + parent: 2 +- proto: WallReinforced + entities: + - uid: 3 + components: + - type: Transform + pos: 16.5,-0.5 + parent: 2 + - uid: 4 + components: + - type: Transform + pos: -1.5,9.5 + parent: 2 + - uid: 5 + components: + - type: Transform + pos: 6.5,9.5 + parent: 2 + - uid: 6 + components: + - type: Transform + pos: 6.5,10.5 + parent: 2 + - uid: 7 + components: + - type: Transform + pos: 6.5,12.5 + parent: 2 + - uid: 8 + components: + - type: Transform + pos: 6.5,13.5 + parent: 2 + - uid: 9 + components: + - type: Transform + pos: 6.5,11.5 + parent: 2 + - uid: 10 + components: + - type: Transform + pos: 5.5,13.5 + parent: 2 + - uid: 15 + components: + - type: Transform + pos: -0.5,13.5 + parent: 2 + - uid: 16 + components: + - type: Transform + pos: -1.5,13.5 + parent: 2 + - uid: 18 + components: + - type: Transform + pos: -1.5,12.5 + parent: 2 + - uid: 19 + components: + - type: Transform + pos: -1.5,11.5 + parent: 2 + - uid: 20 + components: + - type: Transform + pos: -1.5,10.5 + parent: 2 + - uid: 21 + components: + - type: Transform + pos: 7.5,9.5 + parent: 2 + - uid: 37 + components: + - type: Transform + pos: 6.5,14.5 + parent: 2 + - uid: 38 + components: + - type: Transform + pos: 6.5,15.5 + parent: 2 + - uid: 39 + components: + - type: Transform + pos: 7.5,15.5 + parent: 2 + - uid: 40 + components: + - type: Transform + pos: 8.5,15.5 + parent: 2 + - uid: 41 + components: + - type: Transform + pos: 10.5,15.5 + parent: 2 + - uid: 42 + components: + - type: Transform + pos: 11.5,15.5 + parent: 2 + - uid: 43 + components: + - type: Transform + pos: 12.5,15.5 + parent: 2 + - uid: 44 + components: + - type: Transform + pos: 13.5,15.5 + parent: 2 + - uid: 45 + components: + - type: Transform + pos: 9.5,15.5 + parent: 2 + - uid: 46 + components: + - type: Transform + pos: 13.5,14.5 + parent: 2 + - uid: 47 + components: + - type: Transform + pos: 13.5,12.5 + parent: 2 + - uid: 48 + components: + - type: Transform + pos: 13.5,13.5 + parent: 2 + - uid: 49 + components: + - type: Transform + pos: 13.5,11.5 + parent: 2 + - uid: 50 + components: + - type: Transform + pos: 13.5,10.5 + parent: 2 + - uid: 51 + components: + - type: Transform + pos: 13.5,9.5 + parent: 2 + - uid: 52 + components: + - type: Transform + pos: 14.5,9.5 + parent: 2 + - uid: 53 + components: + - type: Transform + pos: 14.5,8.5 + parent: 2 + - uid: 54 + components: + - type: Transform + pos: 14.5,7.5 + parent: 2 + - uid: 55 + components: + - type: Transform + pos: 14.5,3.5 + parent: 2 + - uid: 56 + components: + - type: Transform + pos: 14.5,2.5 + parent: 2 + - uid: 57 + components: + - type: Transform + pos: 13.5,2.5 + parent: 2 + - uid: 58 + components: + - type: Transform + pos: -1.5,14.5 + parent: 2 + - uid: 59 + components: + - type: Transform + pos: -1.5,15.5 + parent: 2 + - uid: 60 + components: + - type: Transform + pos: -2.5,15.5 + parent: 2 + - uid: 61 + components: + - type: Transform + pos: -3.5,15.5 + parent: 2 + - uid: 62 + components: + - type: Transform + pos: -4.5,15.5 + parent: 2 + - uid: 63 + components: + - type: Transform + pos: -5.5,15.5 + parent: 2 + - uid: 64 + components: + - type: Transform + pos: -7.5,15.5 + parent: 2 + - uid: 65 + components: + - type: Transform + pos: -8.5,15.5 + parent: 2 + - uid: 66 + components: + - type: Transform + pos: -6.5,15.5 + parent: 2 + - uid: 67 + components: + - type: Transform + pos: -8.5,13.5 + parent: 2 + - uid: 68 + components: + - type: Transform + pos: -8.5,14.5 + parent: 2 + - uid: 69 + components: + - type: Transform + pos: -8.5,12.5 + parent: 2 + - uid: 70 + components: + - type: Transform + pos: -8.5,10.5 + parent: 2 + - uid: 71 + components: + - type: Transform + pos: -8.5,11.5 + parent: 2 + - uid: 72 + components: + - type: Transform + pos: -5.5,2.5 + parent: 2 + - uid: 73 + components: + - type: Transform + pos: -6.5,2.5 + parent: 2 + - uid: 74 + components: + - type: Transform + pos: -4.5,2.5 + parent: 2 + - uid: 75 + components: + - type: Transform + pos: -7.5,2.5 + parent: 2 + - uid: 76 + components: + - type: Transform + pos: -8.5,2.5 + parent: 2 + - uid: 77 + components: + - type: Transform + pos: -9.5,2.5 + parent: 2 + - uid: 78 + components: + - type: Transform + pos: -9.5,3.5 + parent: 2 + - uid: 82 + components: + - type: Transform + pos: -9.5,8.5 + parent: 2 + - uid: 83 + components: + - type: Transform + pos: -9.5,9.5 + parent: 2 + - uid: 85 + components: + - type: Transform + pos: -8.5,9.5 + parent: 2 + - uid: 89 + components: + - type: Transform + pos: 8.5,2.5 + parent: 2 + - uid: 90 + components: + - type: Transform + pos: 9.5,2.5 + parent: 2 + - uid: 93 + components: + - type: Transform + pos: 10.5,2.5 + parent: 2 + - uid: 94 + components: + - type: Transform + pos: 17.5,-0.5 + parent: 2 + - uid: 95 + components: + - type: Transform + pos: -11.5,0.5 + parent: 2 + - uid: 96 + components: + - type: Transform + pos: 11.5,-13.5 + parent: 2 + - uid: 98 + components: + - type: Transform + pos: 11.5,-9.5 + parent: 2 + - uid: 99 + components: + - type: Transform + pos: -12.5,-3.5 + parent: 2 + - uid: 102 + components: + - type: Transform + pos: 15.5,0.5 + parent: 2 + - uid: 103 + components: + - type: Transform + pos: 16.5,0.5 + parent: 2 + - uid: 104 + components: + - type: Transform + pos: -3.5,2.5 + parent: 2 + - uid: 105 + components: + - type: Transform + pos: -10.5,0.5 + parent: 2 + - uid: 106 + components: + - type: Transform + pos: -6.5,-9.5 + parent: 2 + - uid: 107 + components: + - type: Transform + pos: -11.5,-0.5 + parent: 2 + - uid: 108 + components: + - type: Transform + pos: -12.5,-0.5 + parent: 2 + - uid: 109 + components: + - type: Transform + pos: -12.5,-1.5 + parent: 2 + - uid: 110 + components: + - type: Transform + pos: -12.5,-2.5 + parent: 2 + - uid: 111 + components: + - type: Transform + pos: -13.5,-3.5 + parent: 2 + - uid: 112 + components: + - type: Transform + pos: -17.5,-3.5 + parent: 2 + - uid: 113 + components: + - type: Transform + pos: -17.5,-4.5 + parent: 2 + - uid: 114 + components: + - type: Transform + pos: -18.5,-4.5 + parent: 2 + - uid: 115 + components: + - type: Transform + pos: -18.5,-5.5 + parent: 2 + - uid: 116 + components: + - type: Transform + pos: -19.5,-5.5 + parent: 2 + - uid: 117 + components: + - type: Transform + pos: -19.5,-9.5 + parent: 2 + - uid: 118 + components: + - type: Transform + pos: -18.5,-9.5 + parent: 2 + - uid: 119 + components: + - type: Transform + pos: -18.5,-10.5 + parent: 2 + - uid: 120 + components: + - type: Transform + pos: -17.5,-10.5 + parent: 2 + - uid: 121 + components: + - type: Transform + pos: -17.5,-11.5 + parent: 2 + - uid: 122 + components: + - type: Transform + pos: -13.5,-11.5 + parent: 2 + - uid: 123 + components: + - type: Transform + pos: -13.5,-10.5 + parent: 2 + - uid: 124 + components: + - type: Transform + pos: -12.5,-10.5 + parent: 2 + - uid: 125 + components: + - type: Transform + pos: -12.5,-9.5 + parent: 2 + - uid: 126 + components: + - type: Transform + pos: -11.5,-9.5 + parent: 2 + - uid: 143 + components: + - type: Transform + pos: 18.5,-11.5 + parent: 2 + - uid: 144 + components: + - type: Transform + pos: 18.5,-10.5 + parent: 2 + - uid: 145 + components: + - type: Transform + pos: 17.5,-10.5 + parent: 2 + - uid: 146 + components: + - type: Transform + pos: 17.5,-9.5 + parent: 2 + - uid: 147 + components: + - type: Transform + pos: 16.5,-9.5 + parent: 2 + - uid: 148 + components: + - type: Transform + pos: 22.5,-11.5 + parent: 2 + - uid: 149 + components: + - type: Transform + pos: 22.5,-10.5 + parent: 2 + - uid: 150 + components: + - type: Transform + pos: 23.5,-10.5 + parent: 2 + - uid: 151 + components: + - type: Transform + pos: 23.5,-9.5 + parent: 2 + - uid: 152 + components: + - type: Transform + pos: 24.5,-9.5 + parent: 2 + - uid: 153 + components: + - type: Transform + pos: 24.5,-5.5 + parent: 2 + - uid: 154 + components: + - type: Transform + pos: 23.5,-5.5 + parent: 2 + - uid: 155 + components: + - type: Transform + pos: 23.5,-4.5 + parent: 2 + - uid: 156 + components: + - type: Transform + pos: 22.5,-4.5 + parent: 2 + - uid: 157 + components: + - type: Transform + pos: 22.5,-3.5 + parent: 2 + - uid: 158 + components: + - type: Transform + pos: 18.5,-3.5 + parent: 2 + - uid: 163 + components: + - type: Transform + pos: 11.5,-12.5 + parent: 2 + - uid: 164 + components: + - type: Transform + pos: -6.5,-12.5 + parent: 2 + - uid: 223 + components: + - type: Transform + pos: 15.5,1.5 + parent: 2 + - uid: 224 + components: + - type: Transform + pos: 15.5,2.5 + parent: 2 + - uid: 225 + components: + - type: Transform + pos: 17.5,-1.5 + parent: 2 + - uid: 226 + components: + - type: Transform + pos: 17.5,-2.5 + parent: 2 + - uid: 227 + components: + - type: Transform + pos: 17.5,-3.5 + parent: 2 + - uid: 228 + components: + - type: Transform + pos: -10.5,2.5 + parent: 2 + - uid: 229 + components: + - type: Transform + pos: -10.5,1.5 + parent: 2 + - uid: 257 + components: + - type: Transform + pos: -9.5,7.5 + parent: 2 + - uid: 491 + components: + - type: Transform + pos: 13.5,-13.5 + parent: 2 + - uid: 492 + components: + - type: Transform + pos: 14.5,-13.5 + parent: 2 + - uid: 493 + components: + - type: Transform + pos: 12.5,-13.5 + parent: 2 + - uid: 504 + components: + - type: Transform + pos: 7.5,-22.5 + parent: 2 + - uid: 518 + components: + - type: Transform + pos: 14.5,-21.5 + parent: 2 + - uid: 519 + components: + - type: Transform + pos: 14.5,-17.5 + parent: 2 + - uid: 520 + components: + - type: Transform + pos: 6.5,-22.5 + parent: 2 + - uid: 523 + components: + - type: Transform + pos: -7.5,-13.5 + parent: 2 + - uid: 524 + components: + - type: Transform + pos: -6.5,-13.5 + parent: 2 + - uid: 525 + components: + - type: Transform + pos: -8.5,-13.5 + parent: 2 + - uid: 527 + components: + - type: Transform + pos: -1.5,-22.5 + parent: 2 + - uid: 529 + components: + - type: Transform + pos: -2.5,-22.5 + parent: 2 + - uid: 530 + components: + - type: Transform + pos: -9.5,-13.5 + parent: 2 + - uid: 531 + components: + - type: Transform + pos: -9.5,-14.5 + parent: 2 + - uid: 532 + components: + - type: Transform + pos: -9.5,-15.5 + parent: 2 + - uid: 533 + components: + - type: Transform + pos: -9.5,-16.5 + parent: 2 + - uid: 534 + components: + - type: Transform + pos: -9.5,-18.5 + parent: 2 + - uid: 535 + components: + - type: Transform + pos: -9.5,-19.5 + parent: 2 + - uid: 536 + components: + - type: Transform + pos: -9.5,-20.5 + parent: 2 + - uid: 537 + components: + - type: Transform + pos: -9.5,-22.5 + parent: 2 + - uid: 538 + components: + - type: Transform + pos: -9.5,-21.5 + parent: 2 + - uid: 539 + components: + - type: Transform + pos: -9.5,-17.5 + parent: 2 + - uid: 541 + components: + - type: Transform + pos: 14.5,-25.5 + parent: 2 + - uid: 543 + components: + - type: Transform + pos: 13.5,-25.5 + parent: 2 + - uid: 544 + components: + - type: Transform + pos: 12.5,-25.5 + parent: 2 + - uid: 545 + components: + - type: Transform + pos: 11.5,-25.5 + parent: 2 + - uid: 546 + components: + - type: Transform + pos: 9.5,-25.5 + parent: 2 + - uid: 547 + components: + - type: Transform + pos: 8.5,-25.5 + parent: 2 + - uid: 548 + components: + - type: Transform + pos: 10.5,-25.5 + parent: 2 + - uid: 549 + components: + - type: Transform + pos: -2.5,-23.5 + parent: 2 + - uid: 550 + components: + - type: Transform + pos: -2.5,-24.5 + parent: 2 + - uid: 551 + components: + - type: Transform + pos: -2.5,-25.5 + parent: 2 + - uid: 552 + components: + - type: Transform + pos: -3.5,-25.5 + parent: 2 + - uid: 553 + components: + - type: Transform + pos: -5.5,-25.5 + parent: 2 + - uid: 554 + components: + - type: Transform + pos: -6.5,-25.5 + parent: 2 + - uid: 555 + components: + - type: Transform + pos: -7.5,-25.5 + parent: 2 + - uid: 556 + components: + - type: Transform + pos: -4.5,-25.5 + parent: 2 + - uid: 557 + components: + - type: Transform + pos: -8.5,-25.5 + parent: 2 + - uid: 558 + components: + - type: Transform + pos: -9.5,-25.5 + parent: 2 + - uid: 559 + components: + - type: Transform + pos: -9.5,-24.5 + parent: 2 + - uid: 560 + components: + - type: Transform + pos: -9.5,-23.5 + parent: 2 + - uid: 579 + components: + - type: Transform + pos: 7.5,-25.5 + parent: 2 + - uid: 580 + components: + - type: Transform + pos: 7.5,-23.5 + parent: 2 + - uid: 581 + components: + - type: Transform + pos: 7.5,-24.5 + parent: 2 + - uid: 876 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -8.5,9.5 + parent: 2 + - uid: 1043 + components: + - type: Transform + pos: -6.5,-24.5 + parent: 2 + - uid: 1044 + components: + - type: Transform + pos: -6.5,-23.5 + parent: 2 + - uid: 1045 + components: + - type: Transform + pos: -6.5,-22.5 + parent: 2 + - uid: 1046 + components: + - type: Transform + pos: -6.5,-21.5 + parent: 2 + - uid: 1047 + components: + - type: Transform + pos: -4.5,-21.5 + parent: 2 + - uid: 1048 + components: + - type: Transform + pos: -4.5,-22.5 + parent: 2 + - uid: 1049 + components: + - type: Transform + pos: -4.5,-23.5 + parent: 2 + - uid: 1050 + components: + - type: Transform + pos: -4.5,-24.5 + parent: 2 +- proto: WallSilver + entities: + - uid: 11 + components: + - type: Transform + pos: 7.5,11.5 + parent: 2 + - uid: 12 + components: + - type: Transform + pos: 8.5,10.5 + parent: 2 + - uid: 13 + components: + - type: Transform + pos: 7.5,14.5 + parent: 2 + - uid: 14 + components: + - type: Transform + pos: 7.5,12.5 + parent: 2 + - uid: 17 + components: + - type: Transform + pos: 7.5,10.5 + parent: 2 + - uid: 23 + components: + - type: Transform + pos: 7.5,13.5 + parent: 2 + - uid: 24 + components: + - type: Transform + pos: 8.5,14.5 + parent: 2 + - uid: 25 + components: + - type: Transform + pos: 9.5,14.5 + parent: 2 + - uid: 26 + components: + - type: Transform + pos: 10.5,14.5 + parent: 2 + - uid: 27 + components: + - type: Transform + pos: 11.5,14.5 + parent: 2 + - uid: 28 + components: + - type: Transform + pos: 12.5,14.5 + parent: 2 + - uid: 29 + components: + - type: Transform + pos: 12.5,13.5 + parent: 2 + - uid: 30 + components: + - type: Transform + pos: 12.5,12.5 + parent: 2 + - uid: 31 + components: + - type: Transform + pos: 12.5,11.5 + parent: 2 + - uid: 32 + components: + - type: Transform + pos: 12.5,10.5 + parent: 2 + - uid: 33 + components: + - type: Transform + pos: 11.5,10.5 + parent: 2 +- proto: WallSolid + entities: + - uid: 22 + components: + - type: Transform + pos: -3.5,9.5 + parent: 2 + - uid: 34 + components: + - type: Transform + pos: 8.5,9.5 + parent: 2 + - uid: 35 + components: + - type: Transform + pos: 11.5,9.5 + parent: 2 + - uid: 36 + components: + - type: Transform + pos: 12.5,9.5 + parent: 2 + - uid: 86 + components: + - type: Transform + pos: 8.5,8.5 + parent: 2 + - uid: 87 + components: + - type: Transform + pos: 8.5,5.5 + parent: 2 + - uid: 88 + components: + - type: Transform + pos: 8.5,3.5 + parent: 2 + - uid: 97 + components: + - type: Transform + pos: 11.5,-5.5 + parent: 2 + - uid: 100 + components: + - type: Transform + pos: 8.5,-0.5 + parent: 2 + - uid: 101 + components: + - type: Transform + pos: 11.5,-2.5 + parent: 2 + - uid: 159 + components: + - type: Transform + pos: 18.5,-4.5 + parent: 2 + - uid: 160 + components: + - type: Transform + pos: 17.5,-4.5 + parent: 2 + - uid: 161 + components: + - type: Transform + pos: 17.5,-5.5 + parent: 2 + - uid: 162 + components: + - type: Transform + pos: 16.5,-5.5 + parent: 2 + - uid: 230 + components: + - type: Transform + pos: -11.5,-5.5 + parent: 2 + - uid: 231 + components: + - type: Transform + pos: -12.5,-5.5 + parent: 2 + - uid: 232 + components: + - type: Transform + pos: -12.5,-4.5 + parent: 2 + - uid: 233 + components: + - type: Transform + pos: -13.5,-4.5 + parent: 2 + - uid: 234 + components: + - type: Transform + pos: -6.5,-5.5 + parent: 2 + - uid: 235 + components: + - type: Transform + pos: -6.5,-2.5 + parent: 2 + - uid: 236 + components: + - type: Transform + pos: -3.5,-0.5 + parent: 2 + - uid: 258 + components: + - type: Transform + pos: -3.5,8.5 + parent: 2 + - uid: 259 + components: + - type: Transform + pos: -3.5,3.5 + parent: 2 + - uid: 495 + components: + - type: Transform + pos: 10.5,-13.5 + parent: 2 + - uid: 496 + components: + - type: Transform + pos: 7.5,-13.5 + parent: 2 + - uid: 497 + components: + - type: Transform + pos: 7.5,-14.5 + parent: 2 + - uid: 498 + components: + - type: Transform + pos: 7.5,-15.5 + parent: 2 + - uid: 499 + components: + - type: Transform + pos: 7.5,-17.5 + parent: 2 + - uid: 500 + components: + - type: Transform + pos: 7.5,-18.5 + parent: 2 + - uid: 501 + components: + - type: Transform + pos: 7.5,-19.5 + parent: 2 + - uid: 502 + components: + - type: Transform + pos: 7.5,-20.5 + parent: 2 + - uid: 503 + components: + - type: Transform + pos: 7.5,-21.5 + parent: 2 + - uid: 505 + components: + - type: Transform + pos: 7.5,-16.5 + parent: 2 + - uid: 506 + components: + - type: Transform + pos: 10.5,-14.5 + parent: 2 + - uid: 507 + components: + - type: Transform + pos: 10.5,-16.5 + parent: 2 + - uid: 508 + components: + - type: Transform + pos: 10.5,-17.5 + parent: 2 + - uid: 509 + components: + - type: Transform + pos: 11.5,-17.5 + parent: 2 + - uid: 510 + components: + - type: Transform + pos: 13.5,-17.5 + parent: 2 + - uid: 511 + components: + - type: Transform + pos: 12.5,-17.5 + parent: 2 + - uid: 512 + components: + - type: Transform + pos: 10.5,-18.5 + parent: 2 + - uid: 513 + components: + - type: Transform + pos: 10.5,-20.5 + parent: 2 + - uid: 514 + components: + - type: Transform + pos: 10.5,-21.5 + parent: 2 + - uid: 515 + components: + - type: Transform + pos: 11.5,-21.5 + parent: 2 + - uid: 516 + components: + - type: Transform + pos: 13.5,-21.5 + parent: 2 + - uid: 517 + components: + - type: Transform + pos: 12.5,-21.5 + parent: 2 + - uid: 562 + components: + - type: Transform + pos: -2.5,-21.5 + parent: 2 + - uid: 563 + components: + - type: Transform + pos: -2.5,-20.5 + parent: 2 + - uid: 564 + components: + - type: Transform + pos: -2.5,-19.5 + parent: 2 + - uid: 565 + components: + - type: Transform + pos: -2.5,-18.5 + parent: 2 + - uid: 566 + components: + - type: Transform + pos: -5.5,-13.5 + parent: 2 + - uid: 567 + components: + - type: Transform + pos: -5.5,-14.5 + parent: 2 + - uid: 568 + components: + - type: Transform + pos: -2.5,-17.5 + parent: 2 + - uid: 569 + components: + - type: Transform + pos: -2.5,-16.5 + parent: 2 + - uid: 570 + components: + - type: Transform + pos: -2.5,-14.5 + parent: 2 + - uid: 571 + components: + - type: Transform + pos: -2.5,-13.5 + parent: 2 + - uid: 572 + components: + - type: Transform + pos: -2.5,-15.5 + parent: 2 + - uid: 573 + components: + - type: Transform + pos: -5.5,-16.5 + parent: 2 + - uid: 574 + components: + - type: Transform + pos: -5.5,-17.5 + parent: 2 + - uid: 575 + components: + - type: Transform + pos: -5.5,-18.5 + parent: 2 + - uid: 576 + components: + - type: Transform + pos: -6.5,-18.5 + parent: 2 + - uid: 577 + components: + - type: Transform + pos: -7.5,-18.5 + parent: 2 + - uid: 578 + components: + - type: Transform + pos: -8.5,-18.5 + parent: 2 + - uid: 582 + components: + - type: Transform + pos: 10.5,-24.5 + parent: 2 + - uid: 583 + components: + - type: Transform + pos: 10.5,-22.5 + parent: 2 + - uid: 847 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: -11.5,-8.5 + parent: 2 + - uid: 848 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 16.5,-8.5 + parent: 2 + - uid: 849 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: -11.5,-6.5 + parent: 2 + - uid: 850 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 16.5,-6.5 + parent: 2 + - uid: 872 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -4.5,9.5 + parent: 2 + - uid: 873 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -6.5,9.5 + parent: 2 + - uid: 874 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -8.5,9.5 + parent: 2 + - uid: 875 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -7.5,9.5 + parent: 2 +- proto: WallWood + entities: + - uid: 127 + components: + - type: Transform + pos: 5.5,-2.5 + parent: 2 + - uid: 128 + components: + - type: Transform + pos: -0.5,-2.5 + parent: 2 + - uid: 129 + components: + - type: Transform + pos: -0.5,2.5 + parent: 2 + - uid: 130 + components: + - type: Transform + pos: 5.5,2.5 + parent: 2 + - uid: 131 + components: + - type: Transform + pos: 5.5,-0.5 + parent: 2 + - uid: 132 + components: + - type: Transform + pos: 5.5,0.5 + parent: 2 + - uid: 133 + components: + - type: Transform + pos: 5.5,1.5 + parent: 2 + - uid: 134 + components: + - type: Transform + pos: 5.5,-1.5 + parent: 2 + - uid: 135 + components: + - type: Transform + pos: -0.5,-1.5 + parent: 2 + - uid: 136 + components: + - type: Transform + pos: -0.5,-0.5 + parent: 2 + - uid: 137 + components: + - type: Transform + pos: -0.5,0.5 + parent: 2 + - uid: 138 + components: + - type: Transform + pos: -0.5,1.5 + parent: 2 + - uid: 139 + components: + - type: Transform + pos: 0.5,2.5 + parent: 2 + - uid: 140 + components: + - type: Transform + pos: 1.5,2.5 + parent: 2 + - uid: 141 + components: + - type: Transform + pos: 3.5,2.5 + parent: 2 + - uid: 142 + components: + - type: Transform + pos: 4.5,2.5 + parent: 2 +- proto: WarpPoint + entities: + - uid: 1042 + components: + - type: MetaData + name: Ghost bar + - type: Transform + rot: -1.5707963267948966 rad + pos: 2.5,6.5 + parent: 2 +- proto: WaterTankHighCapacity + entities: + - uid: 964 + components: + - type: Transform + pos: -8.5,-17.5 + parent: 2 +- proto: WaterVaporCanister + entities: + - uid: 918 + components: + - type: Transform + pos: 1.5,1.5 + parent: 2 +- proto: WeaponDisablerPractice + entities: + - uid: 1017 + components: + - type: Transform + pos: 3.6438046,-22.323229 + parent: 2 + - uid: 1018 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 3.7927408,-22.408337 + parent: 2 + - uid: 1019 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 3.707634,-22.642378 + parent: 2 + - uid: 1020 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 3.4948683,-22.557272 + parent: 2 +- proto: WeaponLaserCarbinePractice + entities: + - uid: 1015 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 4.676496,-22.514719 + parent: 2 + - uid: 1016 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 4.3360705,-22.514719 + parent: 2 +- proto: WindoorServiceLocked + entities: + - uid: 1625 + components: + - type: Transform + pos: 11.5,2.5 + parent: 2 + - uid: 1631 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 11.5,2.5 + parent: 2 +- proto: WoodDoor + entities: + - uid: 165 + components: + - type: Transform + pos: 2.5,2.5 + parent: 2 + - type: Door + secondsUntilStateChange: -25241.162 + state: Opening +- proto: WoodenBench + entities: + - uid: 790 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 0.5,-0.5 + parent: 2 + - uid: 917 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 0.5,0.5 + parent: 2 + - uid: 919 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 0.5,-1.5 + parent: 2 + - uid: 1006 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 3.5,-6.5 + parent: 2 + - uid: 1007 + components: + - type: Transform + pos: 2.5,-5.5 + parent: 2 + - uid: 1008 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 1.5,-6.5 + parent: 2 + - uid: 1009 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 2.5,-7.5 + parent: 2 +... diff --git a/Resources/Prototypes/ADT/Catalog/Fills/Backpacks/duffelbag.yml b/Resources/Prototypes/ADT/Catalog/Fills/Backpacks/duffelbag.yml index e4f495860a4..3994d3e71d5 100644 --- a/Resources/Prototypes/ADT/Catalog/Fills/Backpacks/duffelbag.yml +++ b/Resources/Prototypes/ADT/Catalog/Fills/Backpacks/duffelbag.yml @@ -181,3 +181,44 @@ - id: ADTClothingShoesBootsMagAdvSynd - id: EnergyShield - id: EnergySword + +- type: entity + parent: ClothingBackpackDuffelSyndicateBundle + id: ADTClothingBackpackDuffelSyndicateFilledChinaLikeGrenadeLauncher + name: China-Lake bundle + description: "An old China-Lake grenade launcher bundled with 11 rounds of various destruction capability." + components: + - type: StorageFill + contents: + - id: ADTWeaponLauncherChinaLake + - id: ADT40mmGrenadeBlast + amount: 4 + - id: ADT40mmGrenadeHEAT + amount: 8 + - id: ADT40mmGrenadeSmoke + amount: 4 + +- type: entity + parent: ClothingBackpackDuffelSyndicateBundle + id: ADTClothingBackpackDuffelSyndicateFilledGrenadeLauncher + name: Rocket Launcher bundle + components: + - type: StorageFill + contents: + - id: ADTWeaponLauncherRocket + - id: ADTCartridgeFragRocket + amount: 4 + - id: ADTCartridgeBlastRocket + amount: 4 + +- type: entity + parent: ClothingBackpackDuffelSyndicateBundle + id: ADTClothingBackpackDuffelSyndicateFilledWeaponAttachments + name: weapon attachments bundle + components: + - type: StorageFill + contents: + - id: ADTAttachmentVerticalGrip + - id: ADTAttachmentLaserSight + - id: ADTAttachmentReflexSight + - id: ADTAttachmentT2Miniscope diff --git a/Resources/Prototypes/ADT/Catalog/Fills/Items/weaponcase.yml b/Resources/Prototypes/ADT/Catalog/Fills/Items/weaponcase.yml index a2e3d1881fd..7178552c22f 100644 --- a/Resources/Prototypes/ADT/Catalog/Fills/Items/weaponcase.yml +++ b/Resources/Prototypes/ADT/Catalog/Fills/Items/weaponcase.yml @@ -10,10 +10,61 @@ - id: WeaponRifleM90GrenadeLauncher - id: MagazineRifle amount: 5 - - id: GrenadeFrag - amount: 2 - - id: GrenadeBlast + +- type: entity + id: WeaponCaseNTM90GrenadeLauncherAttachment + name: weapon Case + suffix: M-90gl + description: Case with weapons. + parent: WeaponCaseNT + components: + - type: StorageFill + contents: + - id: ADTAttachmentM90GrenadeLauncher + - id: ADT40mmGrenadeBlast + amount: 6 + - id: ADT40mmGrenadeHEAT + amount: 4 + - id: ADT40mmGrenadeBaton + amount: 4 + - id: ADT40mmGrenadeEMP + amount: 4 + - id: ADT40mmGrenadeFlash + amount: 4 + - id: ADT40mmGrenadeSmoke + amount: 4 + +- type: entity + id: WeaponCaseNTM90UnderBarrelShotGunAttachment + name: weapon Case + suffix: M-90gl + description: Case with weapons. + parent: WeaponCaseNT + components: + - type: StorageFill + contents: + - id: ADTAttachmentM90UnderbarrelShotgun + - id: MagazineShotgun amount: 3 + - id: MagazineShotgunBeanbag + amount: 2 + - id: MagazineShotgunIncendiary + amount: 2 + - id: MagazineShotgunSlug + +- type: entity + id: WeaponCaseNTGunsModules + name: weapon Case + suffix: Weapon Attacments + description: Case with weapons. + parent: WeaponCaseNT + components: + - type: StorageFill + contents: + - id: ADTAttachmentVerticalGrip + - id: ADTAttachmentLaserSight + - id: ADTAttachmentReflexSight + - id: ADTAttachmentT2Miniscope - type: entity id: WeaponCaseNTLecter diff --git a/Resources/Prototypes/ADT/Catalog/boobr_catalog.yml b/Resources/Prototypes/ADT/Catalog/boobr_catalog.yml index 382ecae2bdd..e8a3db6e241 100644 --- a/Resources/Prototypes/ADT/Catalog/boobr_catalog.yml +++ b/Resources/Prototypes/ADT/Catalog/boobr_catalog.yml @@ -5,10 +5,76 @@ icon: { sprite: /Textures/Objects/Weapons/Guns/Rifles/carbine.rsi, state: base } productEntity: WeaponCaseNTM90 cost: - Productunit: 30 + Productunit: 18 categories: - ADTUplinkERTWeapon +- type: listing + id: ADTBoberM90GrenadeLauncher + name: boobr-m90-grenadelauncher-name + description: boobr-m90-grenadelauncher-desc + icon: { sprite: /Textures/Objects/Weapons/Guns/Rifles/carbine.rsi, state: base } + productEntity: WeaponCaseNTM90GrenadeLauncherAttachment + cost: + Productunit: 5 + categories: + - ADTUplinkERTAttachments + +- type: listing + id: ADTBoberM90UnderbarrelShotgun + name: boobr-m90-shotgun-name + description: boobr-m90-shotgun-desc + icon: { sprite: /Textures/Objects/Weapons/Guns/Rifles/carbine.rsi, state: base } + productEntity: WeaponCaseNTM90UnderBarrelShotGunAttachment + cost: + Productunit: 5 + categories: + - ADTUplinkERTAttachments + +- type: listing + id: ADTBoberWeaponAttachments + name: boobr-weapon-attachments-name + description: boobr-weapon-attachments-desc + icon: { sprite: /Textures/ADT/Objects/Weapons/Guns/Attachments/under.rsi, state: tech_basic } + productEntity: WeaponCaseNTGunsModules + cost: + Productunit: 3 + categories: + - ADTUplinkERTAttachments + +- type: listing + id: ADTBoberAntilyingAttachment + name: boobr-weapon-attachments-antilying-name + description: boobr-weapon-attachments-antilying-desc + icon: { sprite: /Textures/ADT/Objects/Weapons/Guns/Attachments/barrel.rsi, state: antilying } + productEntity: ADTAttachmentAntiLyingWarrior + cost: + Productunit: 4 + categories: + - ADTUplinkERTAttachments + +- type: listing + id: ADTBoberSuppressorAttachment + name: boobr-weapon-attachments-suppressor-name + description: boobr-weapon-attachments-suppressor-desc + icon: { sprite: /Textures/ADT/Objects/Weapons/Guns/Attachments/barrel.rsi, state: suppressor } + productEntity: ADTAttachmentSuppressor + cost: + Productunit: 3 + categories: + - ADTUplinkERTAttachments + +- type: listing + id: ADTBoberMagneticHarnessAttachment + name: boobr-weapon-attachments-magneticharness-name + description: boobr-weapon-attachments-magneticharness-description + icon: { sprite: /Textures/ADT/Objects/Weapons/Guns/Attachments/rail.rsi, state: magnetic } + productEntity: ADTAttachmentMagneticHarness + cost: + Productunit: 4 + categories: + - ADTUplinkERTAttachments + - type: listing id: ADTBoberLecter name: boobr-lecter-name @@ -16,7 +82,7 @@ icon: { sprite: /Textures/Objects/Weapons/Guns/Rifles/lecter.rsi, state: icon } productEntity: WeaponCaseNTLecter cost: - Productunit: 22 + Productunit: 18 categories: - ADTUplinkERTWeapon @@ -27,7 +93,7 @@ icon: { sprite: /Textures/Objects/Weapons/Guns/Battery/pulse_carbine.rsi, state: icon } productEntity: WeaponCaseNTnPulseCarbine cost: - Productunit: 27 + Productunit: 24 categories: - ADTUplinkERTWeapon @@ -38,7 +104,7 @@ icon: { sprite: /Textures/ADT/Objects/Weapons/Guns/Revolvers/mateba.rsi, state: icon } productEntity: WeaponCaseNTMateba cost: - Productunit: 10 + Productunit: 8 categories: - ADTUplinkERTWeapon @@ -49,7 +115,7 @@ description: boobr-ap-desc productEntity: WeaponCaseNTAPAmmo cost: - Productunit: 10 + Productunit: 8 categories: - ADTUplinkERTWeapon @@ -82,7 +148,7 @@ icon: { sprite: ADT/Objects/Weapons/Guns/Battery/ion_rifle.rsi, state: base } productEntity: WeaponCaseNTIonRifle cost: - Productunit: 10 + Productunit: 8 categories: - ADTUplinkERTWeapon @@ -93,7 +159,7 @@ icon: { sprite: Objects/Weapons/Guns/SMGs/drozd.rsi, state: base } productEntity: WeaponCaseNTDrozd cost: - Productunit: 15 + Productunit: 14 categories: - ADTUplinkERTWeapon @@ -104,7 +170,7 @@ icon: { sprite: Objects/Weapons/Guns/Shotguns/bulldog.rsi, state: base } productEntity: WeaponCaseBulldog cost: - Productunit: 25 + Productunit: 20 categories: - ADTUplinkERTWeapon @@ -115,7 +181,7 @@ icon: { sprite: ADT/Objects/Weapons/Guns/Rifles/ar12.rsi, state: icon } productEntity: ADTWeaponCaseAR12 cost: - Productunit: 27 + Productunit: 24 categories: - ADTUplinkERTWeapon @@ -127,7 +193,7 @@ description: boobr-riot-shield-desc productEntity: RiotShield cost: - Productunit: 10 + Productunit: 4 categories: - ADTUplinkERTMisc @@ -137,7 +203,7 @@ description: boobr-bullet-shield-desc productEntity: RiotBulletShield cost: - Productunit: 15 + Productunit: 6 categories: - ADTUplinkERTMisc @@ -147,7 +213,7 @@ description: boobr-mag-boots-desc productEntity: ADTClothingShoesBootsMagERT cost: - Productunit: 3 + Productunit: 2 categories: - ADTUplinkERTMisc @@ -167,7 +233,7 @@ description: boobr-grenade-desc productEntity: GrenadeShrapnel cost: - Productunit: 3 + Productunit: 2 categories: - ADTUplinkERTMisc @@ -217,7 +283,7 @@ description: boobr-portable-recharger-desc productEntity: PortableRecharger cost: - Productunit: 5 + Productunit: 4 categories: - ADTUplinkERTMisc @@ -227,6 +293,6 @@ description: boobr-holo-projector-desc productEntity: ADTAdvancedHoloprojectorField cost: - Productunit: 5 + Productunit: 4 categories: - ADTUplinkERTMisc diff --git a/Resources/Prototypes/ADT/Catalog/uplink_catalog.yml b/Resources/Prototypes/ADT/Catalog/uplink_catalog.yml index 319ee8a6caf..92f87a30486 100644 --- a/Resources/Prototypes/ADT/Catalog/uplink_catalog.yml +++ b/Resources/Prototypes/ADT/Catalog/uplink_catalog.yml @@ -42,6 +42,9 @@ description: uplink-xc67-description icon: { sprite: /Textures/ADT/Objects/Weapons/Guns/Rifles/xc67.rsi, state: icon} productEntity: ADTClothingBackpackDuffelSyndicateFilledXC67 + discountCategory: usualDiscounts + discountDownTo: + Telecrystal: 12 cost: Telecrystal: 18 categories: @@ -52,6 +55,81 @@ tags: - NukeOpsUplink +#UplinkAttachments +- type: listing + id: ADTUplinkWeaponAttachmentsBundle + name: uplink-attachmentsbundle-name + description: uplink-attachmentsbundle-description + icon: { sprite: /Textures/ADT/Objects/Weapons/Guns/Attachments/under.rsi, state: uplink_modules } + productEntity: ADTClothingBackpackDuffelSyndicateFilledWeaponAttachments + discountCategory: usualDiscounts + discountDownTo: + Telecrystal: 2 + cost: + Telecrystal: 4 + categories: + - UplinkAttachments #ADT_Tweak + +- type: listing + id: ADTUplinkLaserSightAttachment + name: uplink-lasersight-name + description: uplink-lasersight-description + icon: { sprite: /Textures/ADT/Objects/Weapons/Guns/Attachments/under.rsi, state: lasersight} + productEntity: ADTAttachmentLaserSight + cost: + Telecrystal: 1 + categories: + - UplinkAttachments #ADT_Tweak + +- type: listing + id: ADTUplinkSuppressorAttachment + name: uplink-suppressor-name + description: uplink-suppressor-description + icon: { sprite: /Textures/ADT/Objects/Weapons/Guns/Attachments/barrel.rsi, state: suppressor} + productEntity: ADTAttachmentSuppressor + cost: + Telecrystal: 2 + categories: + - UplinkAttachments #ADT_Tweak + +- type: listing + id: ADTUplinkAntilyingAttachment + name: uplink-attachments-antilying-name + description: uplink-attachments-antilying-description + icon: { sprite: /Textures/ADT/Objects/Weapons/Guns/Attachments/barrel.rsi, state: antilying } + productEntity: ADTAttachmentAntiLyingWarrior + discountCategory: usualDiscounts + discountDownTo: + Telecrystal: 5 + cost: + Telecrystal: 8 + categories: + - UplinkAttachments #ADT_Tweak + conditions: + - !type:StoreWhitelistCondition + whitelist: + tags: + - NukeOpsUplink + +- type: listing + id: ADTUplinkMagneticHarnessAttachment + name: uplink-attachments-magneticharness-name + description: uplink-attachments-magneticharness-description + icon: { sprite: /Textures/ADT/Objects/Weapons/Guns/Attachments/rail.rsi, state: magnetic } + productEntity: ADTAttachmentMagneticHarness + discountCategory: usualDiscounts + discountDownTo: + Telecrystal: 4 + cost: + Telecrystal: 6 + categories: + - UplinkAttachments #ADT_Tweak + conditions: + - !type:StoreWhitelistCondition + whitelist: + tags: + - NukeOpsUplink + #UplinkAmmo - type: listing @@ -483,3 +561,28 @@ Telecrystal: 2 categories: - UplinkWearables + +- type: listing + id: ADTUplinkGrenadeLauncherBundle + name: ADTuplink-grenade-launcher-bundle-name + description: ADTuplink-grenade-launcher-bundle-desc + icon: { sprite: /Textures/Objects/Weapons/Guns/Launchers/rocket.rsi, state: base } + productEntity: ADTClothingBackpackDuffelSyndicateFilledGrenadeLauncher + discountCategory: veryRareDiscounts + discountDownTo: + Telecrystal: 20 + cost: + Telecrystal: 25 + categories: + - UplinkWeaponry + +- type: listing + id: ADTUplinkMask + name: uplink-mask-name + description: uplink-mask-desc + productEntity: ADTMaskCoif + categories: + - UplinkPointless + conditions: + - !type:ListingLimitedStockCondition + stock: 3 diff --git a/Resources/Prototypes/ADT/Entities/Clothing/Masks/mask.yml b/Resources/Prototypes/ADT/Entities/Clothing/Masks/mask.yml index e3d79a0adb8..ae1eb9f5f80 100644 --- a/Resources/Prototypes/ADT/Entities/Clothing/Masks/mask.yml +++ b/Resources/Prototypes/ADT/Entities/Clothing/Masks/mask.yml @@ -439,3 +439,24 @@ - type: Clothing sprite: ADT/Clothing/Mask/payday_wolf.rsi - type: BreathMask + +- type: entity + id: ADTMaskCoif + parent: BaseItem + name: heat absorbent coif + description: A close-fitting cap that covers the top, back, and sides of the head. Can also be adjusted to cover the lower part of the face so it keeps the user warm in harsh conditions. + components: + - type: Sprite + sprite: ADT/Clothing/Mask/coif.rsi + state: icon + - type: Clothing + slots: [mask] + sprite: ADT/Clothing/Mask/coif.rsi + - type: StaticPrice + price: 25 + - type: IdentityBlocker + coverage: MOUTH + - type: Item + storedRotation: -90 + size: Small + - type: Mask diff --git a/Resources/Prototypes/ADT/Entities/Mobs/NPCs/creature.yml b/Resources/Prototypes/ADT/Entities/Mobs/NPCs/creatures.yml similarity index 82% rename from Resources/Prototypes/ADT/Entities/Mobs/NPCs/creature.yml rename to Resources/Prototypes/ADT/Entities/Mobs/NPCs/creatures.yml index 93a74bc71b1..a8fd3e60260 100644 --- a/Resources/Prototypes/ADT/Entities/Mobs/NPCs/creature.yml +++ b/Resources/Prototypes/ADT/Entities/Mobs/NPCs/creatures.yml @@ -250,3 +250,61 @@ - GalacticCommon understands: - GalacticCommon + +- type: entity + parent: [BaseMob, MobCombat] + id: ADTMobAngelCrying + name: crying angel + description: crying angel + components: + - type: TimeDespawnDamage + - type: NoSlip + - type: MeleeWeapon + hidden: true + soundHit: + collection: MetalThud + damage: + types: + Blunt: 30 + - type: Sprite + sprite: ADT/Mobs/Demons/angel_crying.rsi + layers: + - map: [ "enum.DamageStateVisualLayers.Base" ] + state: angel + - map: ["enum.HumanoidVisualLayers.LHand"] + - map: ["enum.HumanoidVisualLayers.RHand"] + - type: Body + prototype: Human + - type: Hands + - type: MindContainer + - type: NpcFactionMember + factions: + - SimpleNeutral + - type: MobThresholds + thresholds: + 0: Alive + 100: Dead + - type: Clickable + - type: MobState + allowedStates: + - Alive + - Dead + - type: LanguageSpeaker + speaks: + - GalacticCommon + understands: + - GalacticCommon + - type: ComplexInteraction + - type: Strippable + - type: UserInterface + interfaces: + enum.StrippingUiKey.Key: + type: StrippableBoundUserInterface + - type: Prying + pryPowered: true + force: true + speedModifier: 1.5 + useSound: + path: /Audio/Machines/airlock_creaking.ogg + - type: MovementAlwaysTouching + - type: LagCompensation diff --git a/Resources/Prototypes/ADT/Entities/Objects/Devices/binoculars.yml b/Resources/Prototypes/ADT/Entities/Objects/Devices/binoculars.yml new file mode 100644 index 00000000000..9d4d726449a --- /dev/null +++ b/Resources/Prototypes/ADT/Entities/Objects/Devices/binoculars.yml @@ -0,0 +1,18 @@ +- type: entity + name: binoculars + parent: BaseItem + id: ADTBinoculars + description: A military-issued pair of binoculars. + components: + - type: Item + size: Small + - type: Sprite + sprite: ADT/Objects/Devices/binoculars.rsi + state: binoculars + - type: Scope + useInHand: true + zoomLevels: + - zoom: 1.6 + offset: 14 + allowMovement: true + doAfter: 0 diff --git a/Resources/Prototypes/ADT/Entities/Objects/Specific/Mech/mech_gun.yml b/Resources/Prototypes/ADT/Entities/Objects/Specific/Mech/mech_gun.yml index 34c4a330ec8..2ce0d2e2356 100644 --- a/Resources/Prototypes/ADT/Entities/Objects/Specific/Mech/mech_gun.yml +++ b/Resources/Prototypes/ADT/Entities/Objects/Specific/Mech/mech_gun.yml @@ -317,9 +317,9 @@ soundEmpty: path: /Audio/Weapons/Guns/Empty/empty.ogg - type: BallisticMechAmmoProvider - proto: GrenadeFlash - shots: 3 - capacity: 3 + proto: ADT40mmGrenadeFlash + shots: 6 + capacity: 6 ammoType: granade reloadTime: 5 - type: UIFragment @@ -340,13 +340,13 @@ availableModes: - FullAuto soundGunshot: - path: /Audio/Weapons/Guns/Gunshots/rpgfire.ogg + path: /Audio/Weapons/Guns/Gunshots/grenade_launcher.ogg soundEmpty: path: /Audio/Weapons/Guns/Empty/empty.ogg - type: BallisticMechAmmoProvider - proto: BulletRocket - shots: 2 - capacity: 2 + proto: ADT40mmGrenadeHEAT + shots: 9 + capacity: 9 ammoType: granade reloadTime: 5 - type: UIFragment @@ -367,13 +367,13 @@ availableModes: - FullAuto soundGunshot: - path: /Audio/Weapons/Guns/Gunshots/rpgfire.ogg + path: /Audio/Weapons/Guns/Gunshots/grenade_launcher.ogg soundEmpty: path: /Audio/Weapons/Guns/Empty/empty.ogg - type: BallisticMechAmmoProvider - proto: GrenadeBaton - shots: 3 - capacity: 3 + proto: ADT40mmGrenadeBaton + shots: 6 + capacity: 6 ammoType: granade reloadTime: 5 - type: UIFragment diff --git a/Resources/Prototypes/ADT/Entities/Objects/Specific/uplink_ERT.yml b/Resources/Prototypes/ADT/Entities/Objects/Specific/uplink_ERT.yml index ff49502dbec..4436c9764a3 100644 --- a/Resources/Prototypes/ADT/Entities/Objects/Specific/uplink_ERT.yml +++ b/Resources/Prototypes/ADT/Entities/Objects/Specific/uplink_ERT.yml @@ -7,6 +7,7 @@ categories: - ADTUplinkERTWeapon - ADTUplinkERTMisc + - ADTUplinkERTAttachments currencyWhitelist: - Productunit @@ -15,7 +16,7 @@ id: ADTBaseUplinkBOBERT name: Б.О.О.Б.Р. description: Блюспейс оружейная отряда быстрого реагирования. - suffix: 35 PU + suffix: 35 ЕТ components: - type: Sprite sprite: ADT/Objects/Specific/bobert.rsi diff --git a/Resources/Prototypes/ADT/Entities/Objects/Weapons/Guns/Ammunition/Projectiles/projectiles.yml b/Resources/Prototypes/ADT/Entities/Objects/Weapons/Guns/Ammunition/Projectiles/projectiles.yml new file mode 100644 index 00000000000..55d12000dd8 --- /dev/null +++ b/Resources/Prototypes/ADT/Entities/Objects/Weapons/Guns/Ammunition/Projectiles/projectiles.yml @@ -0,0 +1,160 @@ +- type: entity + id: ADTBullet40mmGrenadeBaton + name: baton grenade + parent: BaseBullet + categories: [ HideSpawnMenu ] + components: + - type: Sprite + sprite: Objects/Weapons/Guns/Projectiles/projectiles2.rsi + layers: + - state: grenade + - type: Projectile + deleteOnCollide: true + damage: + types: + Blunt: 25 + soundHit: + path: /Audio/Effects/gen_hit.ogg + - type: StaminaDamageOnCollide + damage: 160 + +- type: entity + id: ADTBullet40mmGrenadeBlast + name: blast grenade + parent: BaseBulletTrigger + categories: [ HideSpawnMenu ] + components: + - type: Sprite + sprite: Objects/Weapons/Guns/Projectiles/projectiles2.rsi + layers: + - state: grenade + - type: ExplodeOnTrigger + - type: Explosive + explosionType: Default + maxIntensity: 10 + intensitySlope: 3 + totalIntensity: 120 # about a ~4 tile radius + canCreateVacuum: false + +- type: entity + id: ADTBullet40mmGrenadeFlash + name: flash grenade + parent: BaseBulletTrigger + categories: [ HideSpawnMenu ] + components: + - type: Sprite + sprite: Objects/Weapons/Guns/Projectiles/projectiles2.rsi + layers: + - state: grenade + - type: FlashOnTrigger + range: 5 + - type: SpawnOnTrigger + proto: GrenadeFlashEffect + - type: ActiveTimerTrigger + timeRemaining: 0.3 + - type: DeleteOnTrigger + +- type: entity + id: ADTBullet40mmGrenadeHEAT + name: heat grenade + parent: BaseBulletTrigger + categories: [ HideSpawnMenu ] + components: + - type: Sprite + sprite: Objects/Weapons/Guns/Projectiles/projectiles2.rsi + layers: + - state: grenade + - type: ExplodeOnTrigger + - type: Explosive # Powerful explosion in a very small radius. Doesn't break underplating. + explosionType: DemolitionCharge + totalIntensity: 150 + intensitySlope: 25 + maxIntensity: 50 + canCreateVacuum: false + - type: Projectile + deleteOnCollide: true + damage: + types: + Structural: 1000 + Piercing: 75 + soundHit: + path: /Audio/Effects/gen_hit.ogg + +- type: entity + id: ADTBullet40mmGrenadeEMP + name: EMP grenade + parent: BaseBulletTrigger + categories: [ HideSpawnMenu ] + components: + - type: Sprite + sprite: Objects/Weapons/Guns/Projectiles/projectiles2.rsi + layers: + - state: frag + - type: EmpOnTrigger + range: 4 + energyConsumption: 50000 + disableDuration: 10 + - type: Ammo + muzzleFlash: null + - type: PointLight + radius: 3.5 + color: blue + energy: 0.5 + +- type: entity + id: ADTBullet40mmGrenadeSmoke + name: smoke grenade + parent: BaseBulletTrigger + categories: [ HideSpawnMenu ] + components: + - type: Sprite + sprite: Objects/Weapons/Guns/Projectiles/projectiles2.rsi + layers: + - state: grenade + - type: SmokeOnTrigger + duration: 30 + spreadAmount: 40 + - type: SoundOnTrigger + sound: /Audio/Items/smoke_grenade_smoke.ogg + +- type: entity + id: ADTBulletFragRocket + name: frag rocket + parent: BaseBulletTrigger + categories: [ HideSpawnMenu ] + components: + - type: Sprite + sprite: Objects/Weapons/Guns/Projectiles/projectiles2.rsi + layers: + - state: frag + - type: ExplodeOnTrigger + - type: Explosive + explosionType: Default + totalIntensity: 175 # about a ~6 tile radius + intensitySlope: 1 + maxIntensity: 10 + - type: PointLight + radius: 3.5 + color: orange + energy: 0.5 + +- type: entity + id: ADTBulletBlastRocket + name: blast rocket + parent: BaseBulletTrigger + categories: [ HideSpawnMenu ] + components: + - type: Sprite + sprite: Objects/Weapons/Guns/Projectiles/projectiles2.rsi + layers: + - state: frag + - type: ExplodeOnTrigger + - type: Explosive + explosionType: Default + totalIntensity: 150 # a ~2 tile radius + intensitySlope: 5 + maxIntensity: 10 + - type: PointLight + radius: 3.5 + color: orange + energy: 0.5 diff --git a/Resources/Prototypes/ADT/Entities/Objects/Weapons/Guns/Ammunition/explosives.yml b/Resources/Prototypes/ADT/Entities/Objects/Weapons/Guns/Ammunition/explosives.yml new file mode 100644 index 00000000000..0258be6d508 --- /dev/null +++ b/Resources/Prototypes/ADT/Entities/Objects/Weapons/Guns/Ammunition/explosives.yml @@ -0,0 +1,144 @@ +- type: entity + id: ADTBase40mmGrenade + name: base 40 mm grenade + parent: [BaseItem, BaseMajorContraband] + abstract: true + components: + - type: Tag + tags: + - ADT40mmGrenade + - type: Item + size: Tiny + - type: Sprite + - type: CartridgeAmmo + deleteOnSpawn: true + +- type: entity + id: ADT40mmGrenadeBaton + name: 40 mm baton grenade + parent: ADTBase40mmGrenade + components: + - type: CartridgeAmmo + proto: ADTBullet40mmGrenadeBaton + - type: Sprite + sprite: ADT/Objects/Weapons/Guns/Ammunition/Explosives/40mm_grenade.rsi + layers: + - state: stun + map: ["enum.AmmoVisualLayers.Base"] + - type: Appearance + - type: SpentAmmoVisuals + +- type: entity + id: ADT40mmGrenadeBlast + name: 40 mm blast grenade + parent: ADTBase40mmGrenade + components: + - type: CartridgeAmmo + proto: ADTBullet40mmGrenadeBlast + - type: Sprite + sprite: ADT/Objects/Weapons/Guns/Ammunition/Explosives/40mm_grenade.rsi + layers: + - state: he + map: ["enum.AmmoVisualLayers.Base"] + - type: Appearance + - type: SpentAmmoVisuals + +- type: entity + id: ADT40mmGrenadeHEAT + name: 40 mm HEAT grenade + parent: ADTBase40mmGrenade + components: + - type: CartridgeAmmo + proto: ADTBullet40mmGrenadeHEAT + - type: Sprite + sprite: ADT/Objects/Weapons/Guns/Ammunition/Explosives/40mm_grenade.rsi + layers: + - state: heat + map: ["enum.AmmoVisualLayers.Base"] + - type: Appearance + - type: SpentAmmoVisuals + +- type: entity + id: ADT40mmGrenadeEMP + name: 40 mm EMP grenade + parent: ADTBase40mmGrenade + components: + - type: CartridgeAmmo + proto: ADTBullet40mmGrenadeEMP + - type: Sprite + sprite: ADT/Objects/Weapons/Guns/Ammunition/Explosives/40mm_grenade.rsi + layers: + - state: emp + map: ["enum.AmmoVisualLayers.Base"] + - type: Appearance + - type: SpentAmmoVisuals + +- type: entity + id: ADT40mmGrenadeFlash + name: 40 mm flash grenade + parent: ADTBase40mmGrenade + components: + - type: CartridgeAmmo + proto: ADTBullet40mmGrenadeFlash + - type: Sprite + sprite: ADT/Objects/Weapons/Guns/Ammunition/Explosives/40mm_grenade.rsi + layers: + - state: flash + map: ["enum.AmmoVisualLayers.Base"] + - type: Appearance + - type: SpentAmmoVisuals + +- type: entity + id: ADT40mmGrenadeSmoke + name: 40 mm smoke grenade + parent: ADTBase40mmGrenade + components: + - type: CartridgeAmmo + proto: ADTBullet40mmGrenadeSmoke + - type: Sprite + sprite: ADT/Objects/Weapons/Guns/Ammunition/Explosives/40mm_grenade.rsi + layers: + - state: smoke + map: ["enum.AmmoVisualLayers.Base"] + - type: Appearance + - type: SpentAmmoVisuals + +- type: entity + id: ADTCartridgeFragRocket + name: PG-7VL frag grenade + parent: [BaseItem, BaseMajorContraband] + description: A 1.5 warhead designed for the RPG-7 launcher. Has tubular shape. + components: + - type: Tag + tags: + - CartridgeRocket + - type: Item + size: Small + - type: CartridgeAmmo + proto: ADTBulletFragRocket + deleteOnSpawn: true + - type: Sprite + sprite: Objects/Weapons/Guns/Ammunition/Explosives/explosives.rsi + state: rpg + - type: StaticPrice + price: 20 + +- type: entity + id: ADTCartridgeBlastRocket + name: PG-7VL blast grenade + parent: [BaseItem, BaseMajorContraband] + description: A 1.5 warhead designed for the RPG-7 launcher. Has tubular shape. + components: + - type: Tag + tags: + - CartridgeRocket + - type: Item + size: Small + - type: CartridgeAmmo + proto: ADTBulletBlastRocket + deleteOnSpawn: true + - type: Sprite + sprite: Objects/Weapons/Guns/Ammunition/Explosives/explosives.rsi + state: rpg + - type: StaticPrice + price: 20 diff --git a/Resources/Prototypes/ADT/Entities/Objects/Weapons/Guns/Attachments/Actions/actions.yml b/Resources/Prototypes/ADT/Entities/Objects/Weapons/Guns/Attachments/Actions/actions.yml new file mode 100644 index 00000000000..964582d707d --- /dev/null +++ b/Resources/Prototypes/ADT/Entities/Objects/Weapons/Guns/Attachments/Actions/actions.yml @@ -0,0 +1,48 @@ +- type: entity + id: ADTActionBase + categories: + - HideSpawnMenu + +- type: entity + parent: ADTActionBase + id: ADTActionToggleScope + name: Toggle Optics + description: Scope + components: + - type: InstantAction + icon: + sprite: ADT/Objects/Weapons/Guns/Attachments/scope_actions.rsi + state: sniperscope + event: !type:ToggleActionEvent + useDelay: 0.25 + +- type: entity + parent: ADTActionBase + id: ADTActionCycleZoomLevel + name: Cycle Zoom Level + description: Scope + components: + - type: InstantAction + icon: + sprite: ADT/Objects/Weapons/Guns/Attachments/scope_actions.rsi + state: sniperscope + event: !type:ScopeCycleZoomLevelEvent + useDelay: 0.25 + - type: Tag + tags: + - ADTActionCycleZoomLevel + +- type: entity + parent: ADTActionBase + id: ADTActionToggleAttachable + name: Toggle Attachable + description: Toggle an attachable. + components: + - type: InstantAction + icon: + sprite: ADT/Objects/Weapons/Guns/Attachments/scope_actions.rsi + state: sniperscope + event: !type:AttachableToggleActionEvent + +- type: Tag + id: ADTActionCycleZoomLevel diff --git a/Resources/Prototypes/ADT/Entities/Objects/Weapons/Guns/Attachments/Attachments/barrel_attachment.yml b/Resources/Prototypes/ADT/Entities/Objects/Weapons/Guns/Attachments/Attachments/barrel_attachment.yml new file mode 100644 index 00000000000..310b29db812 --- /dev/null +++ b/Resources/Prototypes/ADT/Entities/Objects/Weapons/Guns/Attachments/Attachments/barrel_attachment.yml @@ -0,0 +1,54 @@ +## BASE +- type: entity + abstract: true + parent: ADTAttachableBase + id: ADTBarrelAttachmentBase + components: + - type: Sprite + sprite: ADT/Objects/Weapons/Guns/Attachments/barrel.rsi + - type: Tag + tags: + - ADTAttachmentBarrel +## + +- type: entity + parent: ADTBarrelAttachmentBase + id: ADTAttachmentSuppressor + name: suppressor + description: "A small tube with exhaust ports to expel noise and gas. + Does not completely silence a weapon, but does make it much quieter at the cost of slightly reduced damage." + # categories: + # - HideSpawnMenu + components: + - type: Sprite + state: suppressor + - type: Tag + tags: + - ADTAttachmentBarrel + - ADTAttachmentSuppressor + - type: AttachableVisuals + prefix: suppressor + - type: AttachableSilencer + sound: + collection: ADTSilencedShoot + params: + maxDistance: 6 + # - type: AttachableWeaponRangedMods Пока не работает + # modifiers: + # - damageFalloffAddMult: 0.1 + +- type: entity + parent: ADTBarrelAttachmentBase + id: ADTAttachmentAntiLyingWarrior + name: Anti Lying Warrior + description: AntiLyingWarrior + components: + - type: Sprite + state: antilying + - type: Tag + tags: + - ADTAttachmentBarrel + - ADTAttachmentAntiLyingWarrior + - type: AttachableVisuals + prefix: antilying + - type: AttachableAntiLyingWarrior diff --git a/Resources/Prototypes/ADT/Entities/Objects/Weapons/Guns/Attachments/Attachments/rail_attachment.yml b/Resources/Prototypes/ADT/Entities/Objects/Weapons/Guns/Attachments/Attachments/rail_attachment.yml new file mode 100644 index 00000000000..2c7a781f3bd --- /dev/null +++ b/Resources/Prototypes/ADT/Entities/Objects/Weapons/Guns/Attachments/Attachments/rail_attachment.yml @@ -0,0 +1,185 @@ +## BASE +- type: entity + abstract: true + parent: ADTAttachableBase + id: ADTRailAttachmentBase + components: + - type: Sprite + sprite: ADT/Objects/Weapons/Guns/Attachments/rail.rsi + - type: Tag + tags: + - ADTAttachmentRail +## BASE + +- type: entity + parent: ADTRailAttachmentBase + id: ADTAttachmentMagneticHarness + name: magnetic harness + description: A magnetically attached harness kit that attaches to the rail mount of a weapon. When dropped, the weapon will sling to any set of Marine armor. + components: + - type: Sprite + state: magnetic + - type: Tag + tags: + - ADTAttachmentRail + - ADTAttachmentMagneticHarness + - type: AttachableMagnetic + - type: AttachableWeaponRangedMods + modifiers: + - accuracyAddMult: -0.05 + +- type: entity + abstract: true + parent: [ ADTRailAttachmentBase, ADTAttachableToggleableBase ] + id: ADTAttachmentScopeBase + components: + - type: AttachableToggleable + needHand: true + heldOnlyActivate: true + userOnly: true + doInterrupt: true + attachedOnly: true + breakOnMove: true + breakOnRotate: true + wieldedOnly: true + useDelay: 0.5 + showTogglePopup: false + icon: + sprite: ADT/Objects/Weapons/Guns/Attachments/scope_actions.rsi + state: sniperscope + actionName: action-name-basescope + actionDesc: action-description-basescope + - type: AttachableToggleableSimpleActivate + - type: Scope + requireWielding: true + attachment: true + useInHand: true + zoomLevels: + - zoom: 1 + offset: 15 + allowMovement: false + doAfter: 0 + +- type: entity + parent: ADTAttachmentScopeBase + id: ADTAttachmentHristovScope + name: Hristov x6 scope + description: Hristov x6 scope + components: + - type: Sprite + sprite: ADT/Objects/Weapons/Guns/Attachments/scope_actions.rsi + state: sniperscope + - type: Tag + tags: + - ADTAttachmentRail + - ADTAttachmentHristovScope + - type: AttachableVisuals + - type: AttachableToggleable + actionName: action-name-hristovscope + actionDesc: action-description-hristovscope + - type: AttachableToggleableSimpleActivate + - type: Scope + zoomLevels: + - zoom: 1.8 + offset: 0 + allowMovement: false + doAfter: 0 + - type: AttachableSpeedMods + modifiers: + - conditions: + wieldedOnly: true + walk: -0.23 + sprint: -0.35 + - type: AttachableWieldDelayMods + modifiers: + - delay: 0.4 + - type: AttachableWeaponRangedMods + modifiers: + - fireDelayFlat: 0.1 + - conditions: + activeOnly: true + fireDelayFlat: 0.25 + accuracyAddMult: 0.35 + # damageFalloffAddMult: -0.4 + # - conditions: + # wieldedOnly: true + # inactiveOnly: true + # accuracyAddMult: -0.05 + +- type: entity + parent: ADTAttachmentScopeBase + id: ADTAttachmentT2Miniscope + name: T2 scope + description: T2 scope + components: + - type: Sprite + sprite: ADT/Objects/Weapons/Guns/Attachments/rail.rsi + state: miniscope + - type: Tag + tags: + - ADTAttachmentRail + - ADTAttachmentT2Miniscope + - type: AttachableVisuals + - type: AttachableToggleable + breakOnMove: false + actionName: action-name-t2scope + actionDesc: action-description-t2scope + wieldedOnly: false + breakOnRotate: false + icon: + sprite: ADT/Objects/Weapons/Guns/Attachments/rail.rsi + state: miniscope + - type: AttachableToggleableSimpleActivate + - type: Scope + zoomLevels: + - zoom: 1.4 + offset: 0 + allowMovement: true + doAfter: 0 + requireWielding: false + - type: AttachableSpeedMods + modifiers: + - conditions: + activeOnly: true + walk: -0.31 + sprint: -0.448 + - type: AttachableWieldDelayMods + modifiers: + - delay: 0.2 + - type: AttachableWeaponRangedMods + modifiers: + - conditions: + activeOnly: true + fireDelayFlat: 0.15 + accuracyAddMult: 0.35 + # damageFalloffAddMult: -0.2 + # - conditions: + # wieldedOnly: true + # inactiveOnly: true + # accuracyAddMult: -0.05 #TODO: Add flare gun modifiers when it's implemented. + +- type: entity + parent: ADTRailAttachmentBase + id: ADTAttachmentReflexSight + name: reflex sight + description: Areflex sight + components: + - type: Sprite + sprite: ADT/Objects/Weapons/Guns/Attachments/rail.rsi + state: reflex + - type: Tag + tags: + - ADTAttachmentRail + - ADTAttachmentReflexSight + - type: AttachableVisuals + - type: AttachableWeaponRangedMods + modifiers: + - conditions: + wieldedOnly: true + accuracyAddMult: 0.20 + scatterFlat: -4 + burstScatterAddMult: -2 + - conditions: + unwieldedOnly: true + accuracyAddMult: 0.4 + scatterFlat: -8 diff --git a/Resources/Prototypes/ADT/Entities/Objects/Weapons/Guns/Attachments/Attachments/stock_attachment.yml b/Resources/Prototypes/ADT/Entities/Objects/Weapons/Guns/Attachments/Attachments/stock_attachment.yml new file mode 100644 index 00000000000..e69de29bb2d diff --git a/Resources/Prototypes/ADT/Entities/Objects/Weapons/Guns/Attachments/Attachments/under_attachment.yml b/Resources/Prototypes/ADT/Entities/Objects/Weapons/Guns/Attachments/Attachments/under_attachment.yml new file mode 100644 index 00000000000..85136e47496 --- /dev/null +++ b/Resources/Prototypes/ADT/Entities/Objects/Weapons/Guns/Attachments/Attachments/under_attachment.yml @@ -0,0 +1,188 @@ +## BASE +- type: entity + abstract: true + parent: ADTAttachableBase + id: ADTUnderAttachmentBase + components: + - type: Sprite + sprite: ADT/Objects/Weapons/Guns/Attachments/under.rsi + - type: Tag + tags: + - ADTAttachmentUnderbarrel +## BASE + +- type: entity + parent: [ ADTUnderAttachmentBase, ADTAttachableToggleableBase ] + id: ADTAttachmentM90GrenadeLauncher + name: M90 Grenade Launcher + description: A weapon-mounted, reloadable grenade launcher. + components: + - type: Sprite + layers: + - state: grenade + map: [ "enum.BreechVisuals.Open" ] + - type: ContainerContainer + containers: + ballistic-ammo: !type:Container + ents: [] + - type: RMCAmmoEject + containerID: ballistic-ammo + ejectSound: + path: /Audio/_RMC14/Weapons/Guns/Reload/grenade_insert.ogg + - type: AmmoCounter + - type: Gun + projectileSpeed: 20 + soundGunshot: + path: /Audio/_RMC14/Weapons/Guns/Gunshots/gun_ugl.ogg + resetOnHandSelected: false + - type: RMCSelectiveFire + baseFireRate: 0.417 + - type: BallisticAmmoProvider + whitelist: + tags: + - ADT40mmGrenade + proto: null + capacity: 1 + soundInsert: + path: /Audio/_RMC14/Weapons/Guns/Reload/grenade_insert.ogg + params: + volume: -2 + - type: ShootAtFixedPoint + maxFixedRange: 10 + - type: Appearance + - type: GenericVisualizer + visuals: + enum.BreechVisuals.Open: + enum.BreechVisuals.Open: + True: { state: grenade-open } + False: { state: grenade } + - type: AttachableToggleable + userOnly: true + attachedOnly: true + supercedeHolder: true + wieldedUseOnly: true + activatePopupText: attachable-popup-switch-to-generic + deactivatePopupText: attachable-popup-switch-from-generic + actionName: Switch to the M90 Grenade Launcher + actionDesc: Switch to using the underbarrel grenade launcher. + icon: + sprite: ADT/Objects/Weapons/Guns/Attachments/under.rsi + state: grenade + iconActive: + sprite: ADT/Objects/Weapons/Guns/Attachments/under.rsi + state: grenade-on + - type: AttachableVisuals + redrawOnAppearanceChange: true + - type: Tag + tags: + - ADTAttachmentUnderbarrel + - ADTAttachmentM90GrenadeLauncher + - type: Item + sprite: ADT/Objects/Weapons/Guns/Attachments/under.rsi + storedRotation: -90 + +- type: entity + parent: [ ADTUnderAttachmentBase, ADTAttachableToggleableBase ] + id: ADTAttachmentM90UnderbarrelShotgun + name: M90 underbarrel shotgun + description: MEOW + components: + - type: Sprite + state: masterkey + - type: Tag + tags: + - ADTAttachmentUnderbarrel + - ADTAttachmentM90UnderbarrelShotgun + - type: Gun + soundGunshot: + path: /Audio/Corvax/Weapons/Guns/Gunshots/shotgun_alt.ogg + params: + volume: -2 + - type: RMCSelectiveFire + baseFireRate: 0.476 + - type: ContainerContainer + containers: + ballistic-ammo: !type:Container + - type: RMCAmmoEject + containerID: ballistic-ammo + ejectSound: /Audio/Weapons/Guns/MagIn/shotgun_insert.ogg + - type: BallisticAmmoProvider + cycleable: false + whitelist: + tags: + - ShellShotgun + capacity: 3 + proto: null + soundInsert: + path: /Audio/Weapons/Guns/MagIn/shotgun_insert.ogg + - type: UseDelay + - type: AttachableToggleable + userOnly: true + attachedOnly: true + supercedeHolder: true + wieldedUseOnly: true + activatePopupText: attachable-popup-switch-to-generic + deactivatePopupText: attachable-popup-switch-from-generic + actionName: Switch to the M90 underbarrel shotgun + actionDesc: Switch to using the underbarrel shotgun. + icon: + sprite: ADT/Objects/Weapons/Guns/Attachments/under.rsi + state: masterkey + iconActive: + sprite: ADT/Objects/Weapons/Guns/Attachments/under.rsi + state: masterkey-on + - type: AttachableVisuals + - type: UniqueAction + - type: PumpAction + - type: Item + sprite: ADT/Objects/Weapons/Guns/Attachments/under.rsi + storedRotation: -90 + +- type: entity + parent: ADTUnderAttachmentBase + id: ADTAttachmentVerticalGrip + name: vertical grip + description: "A vertical foregrip that offers better accuracy, less recoil, and less scatter, especially during burst fire. + However, it also increases weapon size." + components: + - type: Sprite + state: verticalgrip + - type: AttachableVisuals + - type: Tag + tags: + - ADTAttachmentUnderbarrel + - ADTAttachmentVerticalGrip + - type: AttachableWeaponRangedMods + modifiers: + - conditions: + wieldedOnly: true + accuracyAddMult: 0.3 + recoilFlat: -2 + scatterFlat: -4 + burstScatterAddMult: -4 + +- type: entity + parent: ADTUnderAttachmentBase + id: ADTAttachmentLaserSight + name: laser sight + description: A laser sight that attaches to the underside of most weapons. Increases accuracy and decreases scatter, especially while one-handed. + components: + - type: Sprite + state: lasersight + - type: AttachableVisuals + - type: Tag + tags: + - ADTAttachmentUnderbarrel + - ADTAttachmentLaserSight + - type: AttachableWeaponRangedMods + modifiers: + - conditions: + wieldedOnly: true + accuracyAddMult: 0.15 + scatterFlat: -2 + recoilFlat: -2 + - conditions: + unwieldedOnly: true + accuracyAddMult: 0.3 + scatterFlat: -6 + recoilFlat: -4 diff --git a/Resources/Prototypes/ADT/Entities/Objects/Weapons/Guns/Attachments/attachable_base.yml b/Resources/Prototypes/ADT/Entities/Objects/Weapons/Guns/Attachments/attachable_base.yml new file mode 100644 index 00000000000..e0f23c9e5ae --- /dev/null +++ b/Resources/Prototypes/ADT/Entities/Objects/Weapons/Guns/Attachments/attachable_base.yml @@ -0,0 +1,35 @@ +- type: entity + parent: BaseItem + abstract: true + id: ADTAttachableBase + components: + - type: Item + size: Small + - type: Attachable + +- type: entity + parent: ADTAttachableBase + abstract: true + id: ADTAttachableToggleableBase + components: + - type: AttachableToggleable + - type: UseDelay + delay: 0 + +- type: entity + abstract: true + id: ADTBaseAttachableHolder + components: + - type: AttachableHolder + - type: ItemSizeChange + - type: ActivatableUI + verbText: rmc-verb-strip-attachables + verbOnly: true + key: + enum.AttachmentUI.StripKey + - type: UserInterface + interfaces: + enum.AttachmentUI.StripKey: + type: AttachmentStripBui + enum.AttachmentUI.ChooseSlotKey: + type: AttachmentChooseSlotBui diff --git a/Resources/Prototypes/ADT/Entities/Objects/Weapons/Guns/Attachments/guns_base.yml b/Resources/Prototypes/ADT/Entities/Objects/Weapons/Guns/Attachments/guns_base.yml new file mode 100644 index 00000000000..3b4a398001d --- /dev/null +++ b/Resources/Prototypes/ADT/Entities/Objects/Weapons/Guns/Attachments/guns_base.yml @@ -0,0 +1,28 @@ +- type: entity + id: ADTBasePumpingGun + categories: + - HideSpawnMenu + components: + - type: UniqueAction + - type: PumpAction + - type: Appearance + - type: BallisticAmmoProvider + cycleable: true + - type: ContainerContainer + containers: + ballistic-ammo: !type:Container + ents: [] + +- type: entity + parent: ADTBaseAttachableHolder + id: ADTBaseMagneticGun + categories: + - HideSpawnMenu + components: + - type: AttachableHolder + slots: + rmc-aslot-rail: + whitelist: + tags: + - ADTAttachmentMagneticHarness + - type: Appearance diff --git a/Resources/Prototypes/ADT/Entities/Objects/Weapons/Guns/Attachments/tags.yml b/Resources/Prototypes/ADT/Entities/Objects/Weapons/Guns/Attachments/tags.yml new file mode 100644 index 00000000000..fb6066b6344 --- /dev/null +++ b/Resources/Prototypes/ADT/Entities/Objects/Weapons/Guns/Attachments/tags.yml @@ -0,0 +1,44 @@ +- type: Tag + id: ADTAttachmentUnderbarrel + +- type: Tag + id: ADTAttachmentM90GrenadeLauncher + +- type: Tag + id: ADTAttachmentM90UnderbarrelShotgun + +- type: Tag + id: ADTAttachmentBarrel + +- type: Tag + id: SurvivalKnifeAttachment + +- type: Tag + id: ADTAttachmentRail + +- type: Tag + id: ADTAttachmentMagneticHarness + +- type: Tag + id: ADTAttachmentHristovScope + +- type: Tag + id: ADTMosinBayonetAttachment + +- type: Tag + id: ADTAttachmentT2Miniscope + +- type: Tag + id: ADTAttachmentVerticalGrip + +- type: Tag + id: ADTAttachmentReflexSight + +- type: Tag + id: ADTAttachmentLaserSight + +- type: Tag + id: ADTAttachmentSuppressor + +- type: Tag + id: ADTAttachmentAntiLyingWarrior diff --git a/Resources/Prototypes/ADT/Entities/Objects/Weapons/Guns/Battery/battery_gun.yml b/Resources/Prototypes/ADT/Entities/Objects/Weapons/Guns/Battery/battery_gun.yml index 7edff5be225..d0d91d0f87c 100644 --- a/Resources/Prototypes/ADT/Entities/Objects/Weapons/Guns/Battery/battery_gun.yml +++ b/Resources/Prototypes/ADT/Entities/Objects/Weapons/Guns/Battery/battery_gun.yml @@ -1,6 +1,6 @@ - type: entity name: ion rifle - parent: BaseWeaponBattery + parent: [BaseWeaponBattery, ADTBaseMagneticGun] id: ADTWeaponIonRifle description: An ion-electronic disruptor rifle specifically designed to fight cyborgs and mechs. components: diff --git a/Resources/Prototypes/ADT/Entities/Objects/Weapons/Guns/Launchers/fill.txt b/Resources/Prototypes/ADT/Entities/Objects/Weapons/Guns/Launchers/fill.txt deleted file mode 100644 index b4954caf47d..00000000000 --- a/Resources/Prototypes/ADT/Entities/Objects/Weapons/Guns/Launchers/fill.txt +++ /dev/null @@ -1 +0,0 @@ -# Данный файл существует по причине того что Githab плохо дружит с пустыми папками, при работе с этой папкой этот файл можно спокойно удалить \ No newline at end of file diff --git a/Resources/Prototypes/ADT/Entities/Objects/Weapons/Guns/Launchers/launchers.yml b/Resources/Prototypes/ADT/Entities/Objects/Weapons/Guns/Launchers/launchers.yml new file mode 100644 index 00000000000..b07c58bafbb --- /dev/null +++ b/Resources/Prototypes/ADT/Entities/Objects/Weapons/Guns/Launchers/launchers.yml @@ -0,0 +1,74 @@ +- type: entity + name: china lake + parent: [BaseWeaponLauncher, BaseGunWieldable, BaseSyndicateContraband, ADTBaseMagneticGun, ADTBasePumpingGun] + id: ADTWeaponLauncherChinaLake + description: PLOOP. + components: + - type: Sprite + sprite: Objects/Weapons/Guns/Launchers/china_lake.rsi + layers: + - state: icon + map: ["enum.GunVisualLayers.Base"] + - type: Clothing + sprite: Objects/Weapons/Guns/Launchers/china_lake.rsi + slots: + - Back + - suitStorage + - type: AmmoCounter + - type: Gun + fireRate: 1 + selectedMode: SemiAuto + availableModes: + - SemiAuto + soundGunshot: + path: /Audio/Weapons/Guns/Gunshots/grenade_launcher.ogg + - type: BallisticAmmoProvider + whitelist: + tags: + - ADT40mmGrenade + capacity: 4 + proto: ADT40mmGrenadeBlast + soundInsert: + path: /Audio/Weapons/Guns/MagIn/batrifle_magin.ogg + +- type: entity + name: RPG-7 + parent: [BaseWeaponLauncher, BaseMajorContraband, ADTBaseMagneticGun, BaseGunWieldable] + id: ADTWeaponLauncherRocket + description: A modified ancient rocket-propelled grenade launcher. + components: + - type: Sprite + sprite: Objects/Weapons/Guns/Launchers/rocket.rsi + layers: + - state: base + map: ["enum.GunVisualLayers.Base"] + - state: mag-0 + map: ["enum.GunVisualLayers.Mag"] + - type: Clothing + sprite: Objects/Weapons/Guns/Launchers/rocket.rsi + - type: Gun + fireRate: 0.5 + soundGunshot: + path: /Audio/Weapons/Guns/Gunshots/rpgfire.ogg + - type: BallisticAmmoProvider + whitelist: + tags: + - CartridgeRocket + proto: ADTCartridgeBlastRocket + capacity: 1 + soundInsert: + path: /Audio/Weapons/Guns/MagIn/batrifle_magin.ogg + - type: MagazineVisuals + magState: mag + steps: 2 + zeroVisible: false + - type: Appearance + - type: Scope + zoomLevels: + - zoom: 1.2 + offset: 12 + allowMovement: true + doAfter: 0 + requireWielding: false + attachment: false + - type: GunRequiresWield diff --git a/Resources/Prototypes/ADT/Entities/Objects/Weapons/Guns/Revolvers/saber_revolvers.yml b/Resources/Prototypes/ADT/Entities/Objects/Weapons/Guns/Revolvers/saber_revolvers.yml index fcb3575f23c..6fda62a9cc8 100644 --- a/Resources/Prototypes/ADT/Entities/Objects/Weapons/Guns/Revolvers/saber_revolvers.yml +++ b/Resources/Prototypes/ADT/Entities/Objects/Weapons/Guns/Revolvers/saber_revolvers.yml @@ -39,7 +39,7 @@ projectileSpeed: 30 soundGunshot: path: /Audio/Weapons/Guns/Gunshots/laser_cannon.ogg - useKey: false + useKey: true - type: MeleeWeapon wideAnimationRotation: -135 attackRate: 1 @@ -103,3 +103,5 @@ whitelist: tags: - ADTLasgunRevolverCell + - type: AltFireMelee + attackType: Heavy diff --git a/Resources/Prototypes/ADT/Entities/Objects/Weapons/Guns/Rifles/rifles.yml b/Resources/Prototypes/ADT/Entities/Objects/Weapons/Guns/Rifles/rifles.yml index fd8b1982ac4..85a3c4279ad 100644 --- a/Resources/Prototypes/ADT/Entities/Objects/Weapons/Guns/Rifles/rifles.yml +++ b/Resources/Prototypes/ADT/Entities/Objects/Weapons/Guns/Rifles/rifles.yml @@ -100,7 +100,7 @@ - type: entity name: AR-12 - parent: WeaponRifleLecter + parent: [WeaponRifleLecter, ADTBaseMagneticGun] id: ADTWeaponRifleAR12 description: AR-12 components: @@ -155,7 +155,7 @@ - type: entity name: xC67 - parent: BaseWeaponRifle + parent: [BaseWeaponRifle, ADTBaseAttachableHolder] id: ADTWeaponRifleXC67 description: A high end prototipe assault rifle. Uses .20 rifle ammo. components: @@ -169,8 +169,8 @@ - type: Clothing sprite: ADT/Objects/Weapons/Guns/Rifles/xc67.rsi - type: Gun - #minAngle: 2 - #maxAngle: 8 + minAngle: 20.5 + maxAngle: 31 fireRate: 6 #angleIncrease: 1 #angleDecay: 12 @@ -208,3 +208,38 @@ steps: 1 zeroVisible: true - type: Appearance + - type: AttachableHolder + slots: + rmc-aslot-underbarrel: + startingAttachable: ADTAttachmentVerticalGrip + whitelist: + tags: + - ADTAttachmentM90GrenadeLauncher + - ADTAttachmentM90UnderbarrelShotgun + - ADTAttachmentVerticalGrip + - ADTAttachmentLaserSight + - SurvivalKnifeAttachment + rmc-aslot-rail: + startingAttachable: ADTAttachmentT2Miniscope + whitelist: + tags: + - ADTAttachmentMagneticHarness + - ADTAttachmentReflexSight + - ADTAttachmentT2Miniscope + rmc-aslot-barrel: + whitelist: + tags: + - ADTAttachmentSuppressor + - ADTAttachmentAntiLyingWarrior + - type: AttachableHolderVisuals + offsets: + rmc-aslot-underbarrel: 0.3125, -0.03125 + rmc-aslot-rail: -0.0940, -0.0325 + rmc-aslot-barrel: 0.96875, 0.03125 + - type: ItemSizeChange + - type: UserInterface + interfaces: + enum.AttachmentUI.StripKey: + type: AttachmentStripBui + enum.AttachmentUI.ChooseSlotKey: + type: AttachmentChooseSlotBui diff --git a/Resources/Prototypes/ADT/Entities/Objects/Weapons/Guns/Snipers/snipers.yml b/Resources/Prototypes/ADT/Entities/Objects/Weapons/Guns/Snipers/snipers.yml index 7e03dbeacc3..32bac904254 100644 --- a/Resources/Prototypes/ADT/Entities/Objects/Weapons/Guns/Snipers/snipers.yml +++ b/Resources/Prototypes/ADT/Entities/Objects/Weapons/Guns/Snipers/snipers.yml @@ -54,3 +54,24 @@ - type: Appearance - type: StaticPrice price: 5000 + - type: AttachableHolder + slots: + rmc-aslot-rail: + locked: true + startingAttachable: ADTAttachmentHristovScope + whitelist: + tags: + - ADTAttachmentMagneticHarness + - ADTAttachmentHristovScope + - type: ItemSizeChange + - type: ActivatableUI + verbText: rmc-verb-strip-attachables + verbOnly: true + key: + enum.AttachmentUI.StripKey + - type: UserInterface + interfaces: + enum.AttachmentUI.StripKey: + type: AttachmentStripBui + enum.AttachmentUI.ChooseSlotKey: + type: AttachmentChooseSlotBui diff --git a/Resources/Prototypes/ADT/Entities/Objects/Weapons/Melee/knife.yml b/Resources/Prototypes/ADT/Entities/Objects/Weapons/Melee/knife.yml new file mode 100644 index 00000000000..86bea65efa3 --- /dev/null +++ b/Resources/Prototypes/ADT/Entities/Objects/Weapons/Melee/knife.yml @@ -0,0 +1,29 @@ +- type: entity + name: Mosin`s rifle bayonet + parent: [CombatKnife, BaseSecurityCargoContraband, ADTBarrelAttachmentBase] + id: ADTMosinBayonet + description: Triangular bayonet wounds are impossible to stitch up. + components: + - type: Sprite + sprite: ADT/Objects/Weapons/Melee/mosin_bayonet.rsi + state: icon + - type: Item + sprite: ADT/Objects/Weapons/Melee/mosin_bayonet.rsi + - type: Tag + tags: + - ADTMosinBayonetAttachment + - type: AttachableWeaponMeleeMods + modifiers: + - bonusDamage: + types: + Piercing: 20 + - decreaseDamage: + types: + Blunt: 5 + - type: AttachableWeaponRangedMods + modifiers: + - accuracyAddMult: -0.05 + - type: AttachablePrying + - type: AttachableVisuals + rsi: ADT/Objects/Weapons/Guns/Attachments/under.rsi + prefix: mosinbayonet diff --git a/Resources/Prototypes/ADT/Entities/Structures/Decorations/statues.yml b/Resources/Prototypes/ADT/Entities/Structures/Decorations/statues.yml index 9fb121d3f59..667eb927868 100644 --- a/Resources/Prototypes/ADT/Entities/Structures/Decorations/statues.yml +++ b/Resources/Prototypes/ADT/Entities/Structures/Decorations/statues.yml @@ -25,3 +25,41 @@ state: beer_messiah_right drawdepth: Mobs offset: "0.0,0.5" + +- type: entity + id: ADTStatueCryingAngel + parent: BaseStructureDynamic + name: crying angel + description: crying angel + suffix: Statue + components: + - type: Sprite + noRot: true + sprite: ADT/Mobs/Demons/angel_crying.rsi + state: angel + drawdepth: Mobs + - type: InteractionOutline + - type: Fixtures + fixtures: + fix1: + shape: + !type:PhysShapeAabb + bounds: "-0.3,-0.4,0.3,0.4" + density: 500 + mask: + - MachineMask + layer: + - MidImpassable + - LowImpassable + - type: Rotatable + - type: Damageable + damageContainer: StructuralInorganic + damageModifierSet: Metallic + - type: Destructible + thresholds: + - trigger: + !type:DamageTrigger + damage: 150 + behaviors: + - !type:DoActsBehavior + acts: [ "Destruction" ] diff --git a/Resources/Prototypes/ADT/Recipes/Lathes/armory.yml b/Resources/Prototypes/ADT/Recipes/Lathes/armory.yml index 8e27d4722ff..36d921d1dae 100644 --- a/Resources/Prototypes/ADT/Recipes/Lathes/armory.yml +++ b/Resources/Prototypes/ADT/Recipes/Lathes/armory.yml @@ -17,4 +17,102 @@ Glass: 200 Gold: 300 Plasma: 900 - Diamond: 200 \ No newline at end of file + Diamond: 200 + +- type: latheRecipe + id: ADTAttachmentVerticalGripRecipe + result: ADTAttachmentVerticalGrip + completetime: 5 + materials: + Steel: 100 + Plastic: 500 + +- type: latheRecipe + id: ADTAttachmentLaserSightRecipe + result: ADTAttachmentLaserSight + completetime: 8 + materials: + Steel: 500 + Plastic: 500 + Gold: 100 + Glass: 200 + +- type: latheRecipe + id: ADTAttachmentReflexSightRecipe + result: ADTAttachmentReflexSight + completetime: 8 + materials: + Steel: 300 + Plastic: 300 + Gold: 100 + Glass: 500 + +- type: latheRecipe + id: ADTAttachmentT2MiniscopeRecipe + result: ADTAttachmentT2Miniscope + completetime: 10 + materials: + Steel: 500 + Plastic: 300 + Gold: 200 + Glass: 500 + +- type: latheRecipe + id: ADTAttachmentM90UnderbarrelShotgunRecipe + result: ADTAttachmentM90UnderbarrelShotgun + completetime: 10 + materials: + Steel: 1000 + Plastic: 500 + Plasma: 100 + +- type: latheRecipe + id: ADTAttachmentM90GrenadeLauncherRecipe + result: ADTAttachmentM90GrenadeLauncher + completetime: 10 + materials: + Steel: 1500 + Plastic: 500 + Plasma: 500 + +- type: latheRecipe + id: ADT40mmGrenadeHEATRecipe + result: ADT40mmGrenadeHEAT + completetime: 5 + materials: + Steel: 300 + Plastic: 100 + Plasma: 100 + +- type: latheRecipe + id: ADT40mmGrenadeBatonRecipe + result: ADT40mmGrenadeBaton + completetime: 5 + materials: + Steel: 300 + Plastic: 300 + +- type: latheRecipe + id: ADT40mmGrenadeEMPRecipe + result: ADT40mmGrenadeEMP + completetime: 5 + materials: + Steel: 300 + Plastic: 100 + Gold: 100 + +- type: latheRecipe + id: ADT40mmGrenadeFlashRecipe + result: ADT40mmGrenadeFlash + completetime: 5 + materials: + Steel: 300 + Plastic: 200 + +- type: latheRecipe + id: ADT40mmGrenadeSmokeRecipe + result: ADT40mmGrenadeSmoke + completetime: 5 + materials: + Steel: 300 + Plastic: 200 diff --git a/Resources/Prototypes/ADT/Research/arsenal.yml b/Resources/Prototypes/ADT/Research/arsenal.yml index df4e6fad0da..d906ba7cac7 100644 --- a/Resources/Prototypes/ADT/Research/arsenal.yml +++ b/Resources/Prototypes/ADT/Research/arsenal.yml @@ -10,4 +10,42 @@ recipeUnlocks: - ADTWeaponCutterAdv technologyPrerequisites: - - SalvageWeapons \ No newline at end of file + - SalvageWeapons + +#Технологии модулей +- type: technology + id: ADTArsenalBasicModules + name: research-technology-modules-based + icon: + sprite: ADT/Objects/Weapons/Guns/Attachments/under.rsi + state: tech_basic + discipline: Arsenal + tier: 1 + cost: 5000 + recipeUnlocks: + - ADTAttachmentVerticalGripRecipe + - ADTAttachmentLaserSightRecipe + - ADTAttachmentReflexSightRecipe + # technologyPrerequisites: + # - SalvageWeapons + +- type: technology + id: ADTArsenalExtendedModules + name: research-technology-modules-extended + icon: + sprite: ADT/Objects/Weapons/Guns/Attachments/under.rsi + state: tech_extented + discipline: Arsenal + tier: 2 + cost: 10000 + recipeUnlocks: + - ADTAttachmentT2MiniscopeRecipe + - ADTAttachmentM90UnderbarrelShotgunRecipe + - ADTAttachmentM90GrenadeLauncherRecipe + - ADT40mmGrenadeHEATRecipe + - ADT40mmGrenadeBatonRecipe + - ADT40mmGrenadeEMPRecipe + - ADT40mmGrenadeFlashRecipe + - ADT40mmGrenadeSmokeRecipe + technologyPrerequisites: + - ADTArsenalBasicModules diff --git a/Resources/Prototypes/ADT/Research/mech_tecnology.yml b/Resources/Prototypes/ADT/Research/mech_tecnology.yml index 0be8078bb30..8ea031c2974 100644 --- a/Resources/Prototypes/ADT/Research/mech_tecnology.yml +++ b/Resources/Prototypes/ADT/Research/mech_tecnology.yml @@ -76,7 +76,7 @@ state: durand discipline: Arsenal tier: 2 - cost: 20000 + cost: 12500 recipeUnlocks: - ADTDurandHarness - ADTDurandLArm @@ -96,7 +96,7 @@ state: phazon discipline: Arsenal tier: 3 - cost: 30000 + cost: 25000 recipeUnlocks: - ADTPhazonHarness - ADTPhazonLArm @@ -222,31 +222,31 @@ #Технологии оружия -- type: technology - id: ADTMechEnergyGunSmallTechnology - name: research-technology-mech-energy-gun-small - icon: - sprite: Objects/Specific/Mech/mecha_equipment.rsi - state: mecha_laser - discipline: Arsenal - tier: 2 - cost: 15000 - recipeUnlocks: - - ADTMechGunImmolatorLaser - - ADTMechGunPeacemakerDisabler +# - type: technology +# id: ADTMechEnergyGunSmallTechnology +# name: research-technology-mech-energy-gun-small +# icon: +# sprite: Objects/Specific/Mech/mecha_equipment.rsi +# state: mecha_laser +# discipline: Arsenal +# tier: 2 +# cost: 15000 +# recipeUnlocks: +# - ADTMechGunImmolatorLaser +# - ADTMechGunPeacemakerDisabler -- type: technology - id: ADTMechEnergyGunHeavyTechnology - name: research-technology-mech-energy-gun-heavy - icon: - sprite: Objects/Specific/Mech/mecha_equipment.rsi - state: mecha_pulse - discipline: Arsenal - tier: 2 - cost: 20000 - recipeUnlocks: - - ADTMechGunSolarisLaserCannon - - ADTMechGunTeslaCannon +# - type: technology +# id: ADTMechEnergyGunHeavyTechnology +# name: research-technology-mech-energy-gun-heavy +# icon: +# sprite: Objects/Specific/Mech/mecha_equipment.rsi +# state: mecha_pulse +# discipline: Arsenal +# tier: 2 +# cost: 20000 +# recipeUnlocks: +# - ADTMechGunSolarisLaserCannon +# - ADTMechGunTeslaCannon - type: technology id: ADTMechGunSmallTechnology @@ -280,4 +280,4 @@ - ADTMechGunSRM8 - ADTMechGunBRM6 - ADTBoxAmmoSniper - - ADTBoxAmmoGranade \ No newline at end of file + - ADTBoxAmmoGranade diff --git a/Resources/Prototypes/ADT/SoundCollections/attachments.yml b/Resources/Prototypes/ADT/SoundCollections/attachments.yml new file mode 100644 index 00000000000..9735d8f9795 --- /dev/null +++ b/Resources/Prototypes/ADT/SoundCollections/attachments.yml @@ -0,0 +1,5 @@ +- type: soundCollection + id: ADTSilencedShoot + files: + - /Audio/_RMC14/Weapons/Guns/Gunshots/gun_silenced_shot1.ogg + - /Audio/_RMC14/Weapons/Guns/Gunshots/gun_silenced_shot2.ogg diff --git a/Resources/Prototypes/ADT/Store/categories.yml b/Resources/Prototypes/ADT/Store/categories.yml index 386af6a6f07..0702f2fc443 100644 --- a/Resources/Prototypes/ADT/Store/categories.yml +++ b/Resources/Prototypes/ADT/Store/categories.yml @@ -1,14 +1,18 @@ - type: storeCategory id: ADTUplinkERTWeapon - name: вооружение + name: Оружие priority: 1 - type: storeCategory id: ADTUplinkERTMisc - name: прочее + name: Прочее priority: 2 -#ling +- type: storeCategory + id: ADTUplinkERTAttachments + name: Оруж. обвесы + priority: 3 + - type: storeCategory id: ChangelingAbilities name: store-category-abilities diff --git a/Resources/Prototypes/ADT/ghostbar.yml b/Resources/Prototypes/ADT/ghostbar.yml index ef3349868ca..382ad3b3013 100644 --- a/Resources/Prototypes/ADT/ghostbar.yml +++ b/Resources/Prototypes/ADT/ghostbar.yml @@ -5,3 +5,8 @@ - type: ghostbarMap id: GhostbarMapRatbar path: "Maps/ADTMaps/Ghostbars/ratbar.yml" + +# Гост бар от maksim21612 +- type: ghostbarMap + id: GhostbarMapCalm + path: "Maps/ADTMaps/Ghostbars/calm_ghostly_bar.yml" \ No newline at end of file diff --git a/Resources/Prototypes/ADT/tags.yml b/Resources/Prototypes/ADT/tags.yml index 448071b494c..15c4ebe8691 100644 --- a/Resources/Prototypes/ADT/tags.yml +++ b/Resources/Prototypes/ADT/tags.yml @@ -403,6 +403,9 @@ - type: Tag id: ADTDogEmotes +- type: Tag + id: ADT40mmGrenade + #sponsor_items - type: Tag id: ADTWeaponPistolPrazatHawk diff --git a/Resources/Prototypes/Catalog/uplink_catalog.yml b/Resources/Prototypes/Catalog/uplink_catalog.yml index 56262428ac7..baa4ac0e441 100644 --- a/Resources/Prototypes/Catalog/uplink_catalog.yml +++ b/Resources/Prototypes/Catalog/uplink_catalog.yml @@ -198,7 +198,7 @@ name: uplink-grenade-launcher-bundle-name description: uplink-grenade-launcher-bundle-desc icon: { sprite: /Textures/Objects/Weapons/Guns/Launchers/china_lake.rsi, state: icon } - productEntity: ClothingBackpackDuffelSyndicateFilledGrenadeLauncher + productEntity: ADTClothingBackpackDuffelSyndicateFilledChinaLikeGrenadeLauncher # adt tweak discountCategory: veryRareDiscounts discountDownTo: Telecrystal: 20 diff --git a/Resources/Prototypes/Entities/Objects/Specific/syndicate.yml b/Resources/Prototypes/Entities/Objects/Specific/syndicate.yml index ac02eeef9bc..f7cd0fdff1f 100644 --- a/Resources/Prototypes/Entities/Objects/Specific/syndicate.yml +++ b/Resources/Prototypes/Entities/Objects/Specific/syndicate.yml @@ -132,6 +132,7 @@ categories: - UplinkWeaponry - UplinkAmmo + - UplinkAttachments #ADT_Tweak - UplinkExplosives - UplinkChemicals - UplinkDeception diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Basic/base_pka.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Basic/base_pka.yml index f85e93b893f..9fc5e6bc427 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Basic/base_pka.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Basic/base_pka.yml @@ -1,7 +1,7 @@ - type: entity id: WeaponProtoKineticAcceleratorBase abstract: true - parent: BaseItem + parent: [BaseItem, ADTBaseAttachableHolder] # ADT TWEAK components: - type: Sprite sprite: Objects/Weapons/Guns/Basic/kinetic_accelerator.rsi @@ -47,3 +47,28 @@ - Belt - type: UseDelay delay: 1 + - type: AttachableHolder #ADT_Tweak + slots: + rmc-aslot-underbarrel: + whitelist: + tags: + - SurvivalKnifeAttachment + # rmc-aslot-stock: + # whitelist: + # tags: + # rmc-aslot-rail: + # whitelist: + # tags: + - type: AttachableHolderVisuals #ADT_Tweak + offsets: + rmc-aslot-underbarrel: 0.315, -0.209 + - type: MeleeWeapon #ADT_Tweak + resetOnHandSelected: false + attackRate: 1 + damage: + types: + Blunt: 5 + soundHit: + collection: GenericHit + - type: AltFireMelee #ADT_Tweak + diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Battery/battery_guns.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Battery/battery_guns.yml index ad5c1b82e83..4403c22710c 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Battery/battery_guns.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Battery/battery_guns.yml @@ -226,7 +226,7 @@ - type: entity name: laser rifle - parent: [WeaponLaserCarbinePractice, BaseGunWieldable, BaseRestrictedContraband] + parent: [WeaponLaserCarbinePractice, BaseGunWieldable, BaseRestrictedContraband, ADTBaseAttachableHolder] # ADT TWEAK id: WeaponLaserCarbine description: Favoured by Nanotrasen Security for being cheap and easy to use. components: @@ -235,6 +235,34 @@ - type: HitscanBatteryAmmoProvider proto: RedLaser fireCost: 62.5 + - type: MeleeWeapon #ADT_Tweak + resetOnHandSelected: false + attackRate: 1 + damage: + types: + Blunt: 5 + soundHit: + collection: GenericHit + - type: AltFireMelee #ADT_Tweak +# ADT TWEAK START + - type: AttachableHolder + slots: + rmc-aslot-underbarrel: + whitelist: + tags: + - ADTAttachmentLaserSight + - SurvivalKnifeAttachment + rmc-aslot-rail: + whitelist: + tags: + - ADTAttachmentMagneticHarness + - ADTAttachmentReflexSight + - ADTAttachmentT2Miniscope + - type: AttachableHolderVisuals + offsets: + rmc-aslot-underbarrel: 0.345, -0.125 + rmc-aslot-rail: -0.1185, -0.0325 +# ADT TWEAK END - type: entity name: pulse pistol @@ -720,7 +748,7 @@ - type: entity name: energy shotgun - parent: [BaseWeaponBattery, BaseGunWieldable, BaseGrandTheftContraband] + parent: [BaseWeaponBattery, BaseGunWieldable, BaseGrandTheftContraband, ADTBaseMagneticGun] # ADT TWEAK id: WeaponEnergyShotgun description: A one-of-a-kind prototype energy weapon that uses various shotgun configurations. It offers the possibility of both lethal and non-lethal shots, making it a versatile weapon. components: diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/LMGs/lmgs.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/LMGs/lmgs.yml index a415927cc56..e0a1b5cab6f 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/LMGs/lmgs.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/LMGs/lmgs.yml @@ -68,7 +68,7 @@ - type: entity name: L6 SAW id: WeaponLightMachineGunL6 - parent: [BaseWeaponLightMachineGun, BaseSyndicateContraband] + parent: [BaseWeaponLightMachineGun, BaseSyndicateContraband, ADTBaseAttachableHolder] # adt tweak description: A rather traditionally made LMG with a pleasantly lacquered wooden pistol grip. Uses .30 rifle ammo. components: - type: Sprite @@ -83,6 +83,19 @@ steps: 4 zeroVisible: true - type: Appearance +# ADT TWEAK START + - type: AttachableHolder + slots: + rmc-aslot-rail: + whitelist: + tags: + - ADTAttachmentMagneticHarness + - ADTAttachmentReflexSight + - ADTAttachmentT2Miniscope + - type: AttachableHolderVisuals + offsets: + rmc-aslot-rail: -0.2275, -0.1575 +# ADT TWEAK END - type: entity name: L6C ROW diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Launchers/launchers.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Launchers/launchers.yml index 725254d8782..62a0a278ad2 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Launchers/launchers.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Launchers/launchers.yml @@ -22,7 +22,7 @@ - type: entity name: china lake - parent: [BaseWeaponLauncher, BaseGunWieldable, BaseSyndicateContraband] + parent: [BaseWeaponLauncher, BaseGunWieldable, BaseSyndicateContraband, ADTBaseMagneticGun] # ADT TWEAK id: WeaponLauncherChinaLake description: PLOOP. components: diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Pistols/pistols.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Pistols/pistols.yml index fbc1f9e8426..396268bbba5 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Pistols/pistols.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Pistols/pistols.yml @@ -70,7 +70,7 @@ - type: entity name: viper - parent: [BaseWeaponPistol, BaseSyndicateContraband] + parent: [BaseWeaponPistol, BaseSyndicateContraband, ADTBaseAttachableHolder] # adt tweak id: WeaponPistolViper description: A small, easily concealable, but somewhat underpowered gun. Retrofitted with a fully automatic receiver. Uses .35 auto ammo. components: @@ -100,6 +100,23 @@ containers: gun_magazine: !type:ContainerSlot gun_chamber: !type:ContainerSlot +# ADT TWEAK START + - type: AttachableHolder + slots: + rmc-aslot-underbarrel: + whitelist: + tags: + - ADTAttachmentLaserSight + rmc-aslot-barrel: + whitelist: + tags: + - ADTAttachmentSuppressor + - ADTAttachmentAntiLyingWarrior + - type: AttachableHolderVisuals + offsets: + rmc-aslot-underbarrel: 0.235, -0.00875 + rmc-aslot-barrel: 0.84375, 0.09735 +# ADT TWEAK END - type: entity name: echis @@ -138,7 +155,7 @@ - type: entity name: cobra - parent: [ BaseWeaponPistol, BaseSyndicateContraband ] + parent: [ BaseWeaponPistol, BaseSyndicateContraband, ADTBaseAttachableHolder] # adt tweak id: WeaponPistolCobra description: A rugged, robust operator handgun with inbuilt silencer. Uses .25 caseless ammo. components: @@ -184,10 +201,21 @@ containers: gun_magazine: !type:ContainerSlot gun_chamber: !type:ContainerSlot +# ADT TWEAK START + - type: AttachableHolder + slots: + rmc-aslot-underbarrel: + whitelist: + tags: + - ADTAttachmentLaserSight + - type: AttachableHolderVisuals + offsets: + rmc-aslot-underbarrel: 0.16, 0.035 +# ADT TWEAK END - type: entity name: mk 58 - parent: [BaseWeaponPistol, BaseRestrictedContraband] + parent: [BaseWeaponPistol, BaseRestrictedContraband, ADTBaseAttachableHolder] # adt tweak id: WeaponPistolMk58 description: A cheap, ubiquitous sidearm, produced by a NanoTrasen subsidiary. Uses .35 auto ammo. components: @@ -210,6 +238,23 @@ - Burst soundGunshot: path: /Audio/Weapons/Guns/Gunshots/mk58.ogg +# ADT TWEAK START + - type: AttachableHolder + slots: + rmc-aslot-underbarrel: + whitelist: + tags: + - ADTAttachmentLaserSight + rmc-aslot-barrel: + whitelist: + tags: + - ADTAttachmentSuppressor + - ADTAttachmentAntiLyingWarrior + - type: AttachableHolderVisuals + offsets: + rmc-aslot-underbarrel: 0.17, -0.014 + rmc-aslot-barrel: 0.84375, 0.125 +# ADT TWEAK END - type: entity name: N1984 diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Projectiles/projectiles.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Projectiles/projectiles.yml index ccca1079be2..f4043820d0c 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Projectiles/projectiles.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Projectiles/projectiles.yml @@ -407,7 +407,7 @@ Structural: 30 # Short lifespan - type: TimedDespawn - lifetime: 0.4 + lifetime: 0.1 - type: GatheringProjectile - type: entity diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Revolvers/revolvers.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Revolvers/revolvers.yml index 97c8f893c3d..fbd4fa2e045 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Revolvers/revolvers.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Revolvers/revolvers.yml @@ -49,6 +49,7 @@ path: /Audio/Weapons/Guns/MagIn/revolver_magin.ogg - type: StaticPrice price: 500 + - type: UniqueAction # ADT TWEAK - type: entity name: Deckard diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Rifles/rifles.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Rifles/rifles.yml index 242f43b702f..40b4a16fd4a 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Rifles/rifles.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Rifles/rifles.yml @@ -50,10 +50,19 @@ gun_chamber: !type:ContainerSlot - type: StaticPrice price: 500 + - type: MeleeWeapon #ADT_Tweak. Для ШТЫКОВОЙ + resetOnHandSelected: false + attackRate: 1 + damage: + types: + Blunt: 5 + soundHit: + collection: GenericHit + - type: AltFireMelee #ADT_Tweak - type: entity name: AKMS - parent: [BaseWeaponRifle, BaseRestrictedContraband] + parent: [BaseWeaponRifle, BaseRestrictedContraband, ADTBaseMagneticGun] # adt tweak id: WeaponRifleAk description: An iconic weapon of war. Uses .30 rifle ammo. components: @@ -102,7 +111,7 @@ - type: entity name: M-90gl - parent: [BaseWeaponRifle, BaseSyndicateContraband] + parent: [BaseWeaponRifle, ADTBaseAttachableHolder] # ADT TWEAK М90 ОБР ЯВЛЯЕТСЯ КОНТРАБАНДОЙ СИНДИКАТА XDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD id: WeaponRifleM90GrenadeLauncher description: An older bullpup carbine model, with an attached underbarrel grenade launcher. Uses .20 rifle ammo. components: @@ -134,7 +143,34 @@ whitelist: tags: - CartridgeRifle - - Grenade +# ADT TWEAK START + - type: AttachableHolder + slots: + rmc-aslot-underbarrel: + whitelist: + tags: + - ADTAttachmentM90GrenadeLauncher + - ADTAttachmentM90UnderbarrelShotgun + - ADTAttachmentVerticalGrip + - ADTAttachmentLaserSight + - SurvivalKnifeAttachment + rmc-aslot-rail: + whitelist: + tags: + - ADTAttachmentMagneticHarness + - ADTAttachmentReflexSight + - ADTAttachmentT2Miniscope + rmc-aslot-barrel: + whitelist: + tags: + - ADTAttachmentSuppressor + - ADTAttachmentAntiLyingWarrior + - type: AttachableHolderVisuals + offsets: + rmc-aslot-underbarrel: 0.3125, -0.0625 + rmc-aslot-rail: 0.0, -0.0325 + rmc-aslot-barrel: 0.96875, 0 +# ADT TWEAK END - type: ContainerContainer containers: gun_magazine: !type:ContainerSlot @@ -147,7 +183,7 @@ - type: entity name: Lecter - parent: [BaseWeaponRifle, BaseRestrictedContraband] + parent: [BaseWeaponRifle, BaseRestrictedContraband, ADTBaseAttachableHolder] # ADT TWEAK id: WeaponRifleLecter description: A high end military grade assault rifle. Uses .20 rifle ammo. components: @@ -191,6 +227,34 @@ steps: 1 zeroVisible: true - type: Appearance +# ADT TWEAK START + - type: AttachableHolder + slots: + rmc-aslot-underbarrel: + whitelist: + tags: + - ADTAttachmentM90GrenadeLauncher + - ADTAttachmentM90UnderbarrelShotgun + - ADTAttachmentVerticalGrip + - ADTAttachmentLaserSight + - SurvivalKnifeAttachment + rmc-aslot-rail: + whitelist: + tags: + - ADTAttachmentMagneticHarness + - ADTAttachmentReflexSight + - ADTAttachmentT2Miniscope + rmc-aslot-barrel: + whitelist: + tags: + - ADTAttachmentSuppressor + - ADTAttachmentAntiLyingWarrior + - type: AttachableHolderVisuals + offsets: + rmc-aslot-underbarrel: 0.3125, -0.0625 + rmc-aslot-rail: 0, 0 + rmc-aslot-barrel: 0.96875, 0 +# ADT TWEAK END - type: entity name: Foam Force Astro Ace diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/SMGs/smgs.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/SMGs/smgs.yml index 5140a358e10..8f380d0202d 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/SMGs/smgs.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/SMGs/smgs.yml @@ -60,7 +60,7 @@ - type: entity name: Atreides - parent: [BaseWeaponSubMachineGun, BaseMajorContraband] + parent: [BaseWeaponSubMachineGun, BaseMajorContraband, ADTBaseMagneticGun] # ADT TWEAK id: WeaponSubMachineGunAtreides description: Pla-ket-ket-ket-ket! Uses .35 auto ammo. components: @@ -83,7 +83,7 @@ - type: entity name: C-20r sub machine gun - parent: [BaseWeaponSubMachineGun, BaseSyndicateContraband] + parent: [BaseWeaponSubMachineGun, BaseSyndicateContraband, ADTBaseAttachableHolder] # ADT TWEAK id: WeaponSubMachineGunC20r description: A firearm that is often used by the infamous nuclear operatives. Uses .35 auto ammo. components: @@ -118,10 +118,29 @@ steps: 6 zeroVisible: true - type: Appearance +# ADT TWEAK START + - type: AttachableHolder + slots: + rmc-aslot-rail: + whitelist: + tags: + - ADTAttachmentMagneticHarness + - ADTAttachmentReflexSight + - ADTAttachmentT2Miniscope + rmc-aslot-barrel: + whitelist: + tags: + - ADTAttachmentSuppressor + - ADTAttachmentAntiLyingWarrior + - type: AttachableHolderVisuals + offsets: + rmc-aslot-rail: -0.0325, -0.0325 + rmc-aslot-barrel: 0.75, 0 +# ADT TWEAK END - type: entity name: Drozd - parent: [BaseWeaponSubMachineGun, BaseRestrictedContraband] + parent: [BaseWeaponSubMachineGun, BaseRestrictedContraband, ADTBaseAttachableHolder] # ADT TWEAK id: WeaponSubMachineGunDrozd description: An excellent fully automatic Heavy SMG. components: @@ -144,11 +163,12 @@ maxAngle: 32 fireRate: 12 burstFireRate: 12 - selectedMode: Burst + selectedMode: FullAuto soundGunshot: path: /Audio/Weapons/Guns/Gunshots/atreides.ogg availableModes: - Burst + - FullAuto shotsPerBurst: 3 burstCooldown: 0.25 - type: ItemSlots @@ -175,10 +195,35 @@ steps: 1 zeroVisible: true - type: Appearance + # ADT TWEAK START + - type: AttachableHolder + slots: + rmc-aslot-underbarrel: + whitelist: + tags: + - ADTAttachmentVerticalGrip + - ADTAttachmentLaserSight + rmc-aslot-rail: + whitelist: + tags: + - ADTAttachmentMagneticHarness + - ADTAttachmentReflexSight + - ADTAttachmentT2Miniscope + rmc-aslot-barrel: + whitelist: + tags: + - ADTAttachmentSuppressor + - ADTAttachmentAntiLyingWarrior + - type: AttachableHolderVisuals + offsets: + rmc-aslot-underbarrel: 0.28, -0.1250 + rmc-aslot-rail: -0.0325, -0.0625 + rmc-aslot-barrel: 0.90625, 0 + # ADT TWEAK END - type: entity name: Vector - parent: BaseWeaponSubMachineGun + parent: [BaseWeaponSubMachineGun, ADTBaseMagneticGun] # ADT TWEAK id: WeaponSubMachineGunVector suffix: Deprecated use Drozd description: An excellent fully automatic Heavy SMG. Uses .45 magnum ammo. @@ -226,7 +271,7 @@ - type: entity name: WT550 - parent: [ BaseWeaponSubMachineGun, BaseRestrictedContraband ] + parent: [ BaseWeaponSubMachineGun, BaseRestrictedContraband, ADTBaseMagneticGun] # ADT TWEAK id: WeaponSubMachineGunWt550 description: An excellent SMG, produced by NanoTrasen's Small Arms Division. Uses .35 auto ammo. components: diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Shotguns/shotguns.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Shotguns/shotguns.yml index 473ba3f3983..6b5f1387c8e 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Shotguns/shotguns.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Shotguns/shotguns.yml @@ -46,7 +46,7 @@ - type: entity name: Bulldog # Don't parent to BaseWeaponShotgun because it differs significantly - parent: [BaseItem, BaseGunWieldable, BaseSyndicateContraband] + parent: [BaseItem, BaseGunWieldable, BaseSyndicateContraband, ADTBaseAttachableHolder] # adt tweak id: WeaponShotgunBulldog description: It's a magazine-fed shotgun designed for close quarters combat. Uses .50 shotgun shells. components: @@ -100,6 +100,37 @@ - type: Appearance - type: StaticPrice price: 500 + - type: MeleeWeapon #ADT_Tweak. Для ШТЫКОВОЙ + resetOnHandSelected: false + attackRate: 1 + damage: + types: + Blunt: 5 + soundHit: + collection: GenericHit + - type: AltFireMelee #ADT_Tweak +# ADT TWEAK START + - type: AttachableHolder + slots: + rmc-aslot-underbarrel: + whitelist: + tags: + - ADTAttachmentM90GrenadeLauncher + - ADTAttachmentM90UnderbarrelShotgun + - ADTAttachmentVerticalGrip + - ADTAttachmentLaserSight + - SurvivalKnifeAttachment + rmc-aslot-rail: + whitelist: + tags: + - ADTAttachmentMagneticHarness + - ADTAttachmentReflexSight + - ADTAttachmentT2Miniscope + - type: AttachableHolderVisuals + offsets: + rmc-aslot-underbarrel: 0.365, -0.1075 + rmc-aslot-rail: -0.02375, -0.0325 +# ADT TWEAK END - type: entity name: double-barreled shotgun @@ -138,7 +169,7 @@ - type: entity name: Enforcer - parent: [BaseWeaponShotgun, BaseGunWieldable, BaseRestrictedContraband] + parent: [BaseWeaponShotgun, BaseGunWieldable, BaseRestrictedContraband, ADTBaseAttachableHolder] # adt tweak id: WeaponShotgunEnforcer description: A premium combat shotgun based on the Kammerer design, featuring an upgraded clip capacity. .50 shotgun shells. components: @@ -153,6 +184,35 @@ - type: Gun # Corvax-Guns soundGunshot: path: /Audio/Corvax/Weapons/Guns/Gunshots/shotgun_metal.ogg + - type: MeleeWeapon #ADT_Tweak. Для ШТЫКОВОЙ + resetOnHandSelected: false + attackRate: 1 + damage: + types: + Blunt: 5 + soundHit: + collection: GenericHit + - type: AltFireMelee #ADT_Tweak +# ADT TWEAK START + - type: AttachableHolder + slots: + rmc-aslot-underbarrel: + whitelist: + tags: + - ADTAttachmentVerticalGrip + - ADTAttachmentLaserSight + - SurvivalKnifeAttachment + rmc-aslot-rail: + whitelist: + tags: + - ADTAttachmentMagneticHarness + - ADTAttachmentReflexSight + - ADTAttachmentT2Miniscope + - type: AttachableHolderVisuals + offsets: + rmc-aslot-underbarrel: 0.2875, -0.125 + rmc-aslot-rail: -0.0375, -0.1575 +# ADT TWEAK END - type: entity parent: WeaponShotgunEnforcer @@ -167,7 +227,7 @@ - type: entity name: Kammerer - parent: [BaseWeaponShotgun, BaseGunWieldable, BaseRestrictedContraband] + parent: [BaseWeaponShotgun, BaseGunWieldable, BaseRestrictedContraband, ADTBasePumpingGun, ADTBaseMagneticGun] # adt tweak id: WeaponShotgunKammerer description: When an old Remington design meets modern materials, this is the result. A favourite weapon of militia forces throughout many worlds. Uses .50 shotgun shells. components: diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Snipers/snipers.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Snipers/snipers.yml index 4ea0061c961..8bf9c580094 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Snipers/snipers.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Snipers/snipers.yml @@ -40,16 +40,38 @@ - type: entity name: Kardashev-Mosin - parent: [BaseWeaponSniper, BaseGunWieldable, BaseSyndicateContraband] + parent: [BaseWeaponSniper, BaseGunWieldable, BaseSyndicateContraband, ADTBaseAttachableHolder] #ADT_Tweak id: WeaponSniperMosin description: A weapon for hunting, or endless trench warfare. Uses .30 rifle ammo. components: - type: Sprite - sprite: Objects/Weapons/Guns/Snipers/bolt_gun_wood.rsi + sprite: ADT/ADTGlobalEvents/WorldWar1/Objects/Weapons/Guns/Rifles/mosin.rsi #ADT_Tweak +#ADT_Tweak START + - type: AttachableHolder #ADT_Tweak + slots: + rmc-aslot-barrel: + startingAttachable: ADTMosinBayonet + whitelist: + tags: + - ADTMosinBayonetAttachment + - type: AttachableHolderVisuals #ADT_Tweak + offsets: + rmc-aslot-barrel: 0.59375, 0 + # rmc-aslot-barrel: 0.59375, -0.15625 + - type: MeleeWeapon #ADT_Tweak + resetOnHandSelected: false + attackRate: 1 + damage: + types: + Blunt: 5 + soundHit: + collection: GenericHit + - type: AltFireMelee +#ADT_Tweak END - type: entity name: Hristov - parent: [BaseWeaponSniper, BaseGunWieldable, BaseSyndicateContraband] + parent: [BaseWeaponSniper, BaseGunWieldable, BaseSyndicateContraband, ADTBaseMagneticGun] # ADT TWEAK id: WeaponSniperHristov description: A portable anti-materiel rifle. Fires armor piercing 14.5mm shells. Uses .60 anti-materiel ammo. components: @@ -63,6 +85,15 @@ - CartridgeAntiMateriel capacity: 5 proto: CartridgeAntiMateriel + - type: AttachableHolder + slots: + rmc-aslot-rail: + locked: true + startingAttachable: ADTAttachmentHristovScope + whitelist: + tags: + - ADTAttachmentMagneticHarness + - ADTAttachmentHristovScope - type: entity name: musket diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Melee/knife.yml b/Resources/Prototypes/Entities/Objects/Weapons/Melee/knife.yml index 464dc58b3f6..26b6f876f51 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Melee/knife.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Melee/knife.yml @@ -89,14 +89,14 @@ - type: entity name: combat knife - parent: [BaseKnife, BaseRestrictedContraband] + parent: [BaseKnife, BaseRestrictedContraband, ADTUnderAttachmentBase] # ADT TWEAK id: CombatKnife description: A deadly knife intended for melee confrontations. components: - - type: Tag - tags: - - CombatKnife - - Knife + # - type: Tag + # tags: + # - CombatKnife + # - Knife - type: Sprite sprite: Objects/Weapons/Melee/combat_knife.rsi state: icon @@ -120,14 +120,35 @@ sprite: Objects/Weapons/Melee/combat_knife.rsi - type: DisarmMalus malus: 0.225 - #ADT add start +# ADT TWEAK START - type: ThrowingAngle angle: 225 - #ADT add end + - type: Tag + tags: + - SurvivalKnifeAttachment + - CombatKnife + - Knife + - type: AttachableWeaponMeleeMods + modifiers: + - bonusDamage: + types: + Slash: 5 + Piercing: 12 + - decreaseDamage: + types: + Blunt: 5 + - type: AttachableWeaponRangedMods + modifiers: + - accuracyAddMult: -0.05 + - type: AttachablePrying + - type: AttachableVisuals + rsi: ADT/Objects/Weapons/Guns/Attachments/under.rsi + prefix: combatknife +# ADT TWEAK END - type: entity name: survival knife - parent: [CombatKnife, BaseSecurityCargoContraband] + parent: [CombatKnife, BaseSecurityCargoContraband, ADTUnderAttachmentBase] # ADT TWEAK id: SurvivalKnife description: Weapon of first and last resort for combatting space carp. components: @@ -139,6 +160,27 @@ storedSprite: state: storage sprite: Objects/Weapons/Melee/survival_knife.rsi +# ADT TWEAK START + - type: Tag + tags: + - SurvivalKnifeAttachment + - Knife + - type: AttachableWeaponMeleeMods + modifiers: + - bonusDamage: + types: + Slash: 15 + - decreaseDamage: + types: + Blunt: 5 + - type: AttachableWeaponRangedMods + modifiers: + - accuracyAddMult: -0.05 + - type: AttachablePrying + - type: AttachableVisuals + rsi: Objects/Weapons/Melee/survival_knife.rsi + prefix: icon +# ADT TWEAK END - type: entity name: kukri knife diff --git a/Resources/Prototypes/Entities/Structures/Machines/lathe.yml b/Resources/Prototypes/Entities/Structures/Machines/lathe.yml index 03b262e4b00..04bdbd50f40 100644 --- a/Resources/Prototypes/Entities/Structures/Machines/lathe.yml +++ b/Resources/Prototypes/Entities/Structures/Machines/lathe.yml @@ -918,6 +918,17 @@ # Start ADT tweak - ADTMagazineMagnumIncendiary - ADTMagazineMagnumUranium + - ADTAttachmentVerticalGripRecipe + - ADTAttachmentLaserSightRecipe + - ADTAttachmentReflexSightRecipe + - ADTAttachmentT2MiniscopeRecipe + - ADTAttachmentM90UnderbarrelShotgunRecipe + - ADTAttachmentM90GrenadeLauncherRecipe + - ADT40mmGrenadeHEATRecipe + - ADT40mmGrenadeBatonRecipe + - ADT40mmGrenadeEMPRecipe + - ADT40mmGrenadeFlashRecipe + - ADT40mmGrenadeSmokeRecipe # Start ADT tweak - MagazineRifleIncendiary - MagazineRifleUranium diff --git a/Resources/Prototypes/Research/arsenal.yml b/Resources/Prototypes/Research/arsenal.yml index dc2fdc92561..13ec745fd70 100644 --- a/Resources/Prototypes/Research/arsenal.yml +++ b/Resources/Prototypes/Research/arsenal.yml @@ -50,7 +50,10 @@ cost: 7500 recipeUnlocks: - WeaponLaserCarbine + # Start ADT tweak - ADTBorgModuleHarm #ADT secborg + - ADTMechGunImmolatorLaser + # End ADT tweak - type: technology id: NonlethalAmmunition @@ -83,7 +86,7 @@ - MagazinePistolUranium # Start ADT tweak - ADTMagazineMagnumUranium - # Start ADT tweak + # End ADT tweak - MagazineLightRifleUranium - SpeedLoaderMagnumUranium - MagazineBoxPistolUranium @@ -106,6 +109,10 @@ - TelescopicShield - HoloprojectorSecurity - WeaponDisablerSMG + # Start ADT tweak - часть технологий подходящих по стилю переношу сюда + - ClothingBackpackElectropack + - ADTMechGunPeacemakerDisabler + # End ADT tweak - type: technology id: ExplosiveTechnology @@ -125,17 +132,17 @@ - ExplosivePayload - ChemicalPayload -- type: technology - id: SpecialMeans - name: research-technology-special-means - icon: - sprite: Clothing/Back/Backpacks/electropack.rsi - state: icon - discipline: Arsenal - tier: 1 - cost: 5000 - recipeUnlocks: - - ClothingBackpackElectropack +# - type: technology #ADT_Tweak - электрорюкзак перенесен в технологию контроля беспорядков +# id: SpecialMeans +# name: research-technology-special-means +# icon: +# sprite: Clothing/Back/Backpacks/electropack.rsi +# state: icon +# discipline: Arsenal +# tier: 1 +# cost: 5000 +# recipeUnlocks: +# - ClothingBackpackElectropack # Tier 2 @@ -150,6 +157,7 @@ cost: 10000 recipeUnlocks: - WeaponLaserCannon + - ADTMechGunSolarisLaserCannon #ADT_Tweak - type: technology id: WaveParticleHarnessing @@ -162,6 +170,7 @@ cost: 10000 recipeUnlocks: - WeaponXrayCannon + - ADTMechGunTeslaCannon #ADT_Tweak - type: technology id: BasicShuttleArmament diff --git a/Resources/Prototypes/Store/categories.yml b/Resources/Prototypes/Store/categories.yml index 53457b252ad..37b3d0f58b6 100644 --- a/Resources/Prototypes/Store/categories.yml +++ b/Resources/Prototypes/Store/categories.yml @@ -44,50 +44,57 @@ name: store-category-ammo priority: 1 +#ADT_Tweak-Start +- type: storeCategory + id: UplinkAttachments #ADT_Tweak + name: store-category-attachments + priority: 2 +#ADT_Tweak-END + - type: storeCategory id: UplinkExplosives name: store-category-explosives - priority: 2 + priority: 3 #ADT_Tweak - type: storeCategory id: UplinkWearables name: store-category-wearables - priority: 3 + priority: 4 #ADT_Tweak - type: storeCategory id: UplinkChemicals name: store-category-chemicals - priority: 4 + priority: 5 #ADT_Tweak - type: storeCategory id: UplinkDeception name: store-category-deception - priority: 5 + priority: 6 #ADT_Tweak - type: storeCategory id: UplinkDisruption name: store-category-disruption - priority: 6 + priority: 7 #ADT_Tweak - type: storeCategory id: UplinkImplants name: store-category-implants - priority: 7 + priority: 8 #ADT_Tweak - type: storeCategory id: UplinkAllies name: store-category-allies - priority: 8 + priority: 9 #ADT_Tweak - type: storeCategory id: UplinkJob name: store-category-job - priority: 9 + priority: 10 #ADT_Tweak - type: storeCategory id: UplinkPointless name: store-category-pointless - priority: 10 + priority: 11 #ADT_Tweak #revenant - type: storeCategory diff --git a/Resources/Prototypes/Store/presets.yml b/Resources/Prototypes/Store/presets.yml index 762ed68921a..810a52808ef 100644 --- a/Resources/Prototypes/Store/presets.yml +++ b/Resources/Prototypes/Store/presets.yml @@ -7,6 +7,7 @@ categories: - UplinkWeaponry - UplinkAmmo + - UplinkAttachments #ADT_Tweak - UplinkExplosives - UplinkChemicals - UplinkDeception diff --git a/Resources/Textures/ADT/ADTGlobalEvents/WorldWar1/Objects/Weapons/Guns/Rifles/mosin.rsi/base.png b/Resources/Textures/ADT/ADTGlobalEvents/WorldWar1/Objects/Weapons/Guns/Rifles/mosin.rsi/base.png new file mode 100644 index 00000000000..ceee92fa80e Binary files /dev/null and b/Resources/Textures/ADT/ADTGlobalEvents/WorldWar1/Objects/Weapons/Guns/Rifles/mosin.rsi/base.png differ diff --git a/Resources/Textures/ADT/ADTGlobalEvents/WorldWar1/Objects/Weapons/Guns/Rifles/mosin.rsi/bolt-open.png b/Resources/Textures/ADT/ADTGlobalEvents/WorldWar1/Objects/Weapons/Guns/Rifles/mosin.rsi/bolt-open.png new file mode 100644 index 00000000000..4ea7189d646 Binary files /dev/null and b/Resources/Textures/ADT/ADTGlobalEvents/WorldWar1/Objects/Weapons/Guns/Rifles/mosin.rsi/bolt-open.png differ diff --git a/Resources/Textures/ADT/ADTGlobalEvents/WorldWar1/Objects/Weapons/Guns/Rifles/mosin.rsi/equipped-BACKPACK.png b/Resources/Textures/ADT/ADTGlobalEvents/WorldWar1/Objects/Weapons/Guns/Rifles/mosin.rsi/equipped-BACKPACK.png new file mode 100644 index 00000000000..d5bca755fb3 Binary files /dev/null and b/Resources/Textures/ADT/ADTGlobalEvents/WorldWar1/Objects/Weapons/Guns/Rifles/mosin.rsi/equipped-BACKPACK.png differ diff --git a/Resources/Textures/ADT/ADTGlobalEvents/WorldWar1/Objects/Weapons/Guns/Rifles/mosin.rsi/equipped-SUITSTORAGE.png b/Resources/Textures/ADT/ADTGlobalEvents/WorldWar1/Objects/Weapons/Guns/Rifles/mosin.rsi/equipped-SUITSTORAGE.png new file mode 100644 index 00000000000..d5bca755fb3 Binary files /dev/null and b/Resources/Textures/ADT/ADTGlobalEvents/WorldWar1/Objects/Weapons/Guns/Rifles/mosin.rsi/equipped-SUITSTORAGE.png differ diff --git a/Resources/Textures/ADT/ADTGlobalEvents/WorldWar1/Objects/Weapons/Guns/Rifles/mosin.rsi/inhand-left.png b/Resources/Textures/ADT/ADTGlobalEvents/WorldWar1/Objects/Weapons/Guns/Rifles/mosin.rsi/inhand-left.png new file mode 100644 index 00000000000..e8c6db08d32 Binary files /dev/null and b/Resources/Textures/ADT/ADTGlobalEvents/WorldWar1/Objects/Weapons/Guns/Rifles/mosin.rsi/inhand-left.png differ diff --git a/Resources/Textures/ADT/ADTGlobalEvents/WorldWar1/Objects/Weapons/Guns/Rifles/mosin.rsi/inhand-right.png b/Resources/Textures/ADT/ADTGlobalEvents/WorldWar1/Objects/Weapons/Guns/Rifles/mosin.rsi/inhand-right.png new file mode 100644 index 00000000000..05f0c69ee13 Binary files /dev/null and b/Resources/Textures/ADT/ADTGlobalEvents/WorldWar1/Objects/Weapons/Guns/Rifles/mosin.rsi/inhand-right.png differ diff --git a/Resources/Textures/ADT/ADTGlobalEvents/WorldWar1/Objects/Weapons/Guns/Rifles/mosin.rsi/meta.json b/Resources/Textures/ADT/ADTGlobalEvents/WorldWar1/Objects/Weapons/Guns/Rifles/mosin.rsi/meta.json new file mode 100644 index 00000000000..7db8a827350 --- /dev/null +++ b/Resources/Textures/ADT/ADTGlobalEvents/WorldWar1/Objects/Weapons/Guns/Rifles/mosin.rsi/meta.json @@ -0,0 +1,41 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Created by discord:prazat911", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "base" + }, + { + "name": "bolt-open" + }, + { + "name": "inhand-left", + "directions": 4 + }, + { + "name": "inhand-right", + "directions": 4 + }, + { + "name": "wielded-inhand-left", + "directions": 4 + }, + { + "name": "wielded-inhand-right", + "directions": 4 + }, + { + "name": "equipped-BACKPACK", + "directions": 4 + }, + { + "name": "equipped-SUITSTORAGE", + "directions": 4 + } + ] +} diff --git a/Resources/Textures/ADT/ADTGlobalEvents/WorldWar1/Objects/Weapons/Guns/Rifles/mosin.rsi/wielded-inhand-left.png b/Resources/Textures/ADT/ADTGlobalEvents/WorldWar1/Objects/Weapons/Guns/Rifles/mosin.rsi/wielded-inhand-left.png new file mode 100644 index 00000000000..2c3de531eaa Binary files /dev/null and b/Resources/Textures/ADT/ADTGlobalEvents/WorldWar1/Objects/Weapons/Guns/Rifles/mosin.rsi/wielded-inhand-left.png differ diff --git a/Resources/Textures/ADT/ADTGlobalEvents/WorldWar1/Objects/Weapons/Guns/Rifles/mosin.rsi/wielded-inhand-right.png b/Resources/Textures/ADT/ADTGlobalEvents/WorldWar1/Objects/Weapons/Guns/Rifles/mosin.rsi/wielded-inhand-right.png new file mode 100644 index 00000000000..08cd5ccccc2 Binary files /dev/null and b/Resources/Textures/ADT/ADTGlobalEvents/WorldWar1/Objects/Weapons/Guns/Rifles/mosin.rsi/wielded-inhand-right.png differ diff --git a/Resources/Textures/ADT/Changeling/Objects/bone_shard.rsi/meta.json b/Resources/Textures/ADT/Changeling/Objects/bone_shard.rsi/meta.json index 84f7f10e4dc..eb20d7f644d 100644 --- a/Resources/Textures/ADT/Changeling/Objects/bone_shard.rsi/meta.json +++ b/Resources/Textures/ADT/Changeling/Objects/bone_shard.rsi/meta.json @@ -7,11 +7,11 @@ "y": 32 }, "states": [ - { - "name": "icon" - }, - { - "name": "festive" - } + { + "name": "icon" + }, + { + "name": "festive" + } ] } diff --git a/Resources/Textures/ADT/Clothing/Mask/coif.rsi/equipped-MASK.png b/Resources/Textures/ADT/Clothing/Mask/coif.rsi/equipped-MASK.png new file mode 100644 index 00000000000..1bffbcba02b Binary files /dev/null and b/Resources/Textures/ADT/Clothing/Mask/coif.rsi/equipped-MASK.png differ diff --git a/Resources/Textures/ADT/Clothing/Mask/coif.rsi/icon.png b/Resources/Textures/ADT/Clothing/Mask/coif.rsi/icon.png new file mode 100644 index 00000000000..0c5c4851be4 Binary files /dev/null and b/Resources/Textures/ADT/Clothing/Mask/coif.rsi/icon.png differ diff --git a/Resources/Textures/ADT/Clothing/Mask/coif.rsi/meta.json b/Resources/Textures/ADT/Clothing/Mask/coif.rsi/meta.json new file mode 100644 index 00000000000..531ac2cc08b --- /dev/null +++ b/Resources/Textures/ADT/Clothing/Mask/coif.rsi/meta.json @@ -0,0 +1,22 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from CM-SS13 at https://github.com/cmss13-devs/cmss13/blob/master/icons/mob/humans/onmob/mask.dmi, equipped-MASK-reptilian modified by DangerRevolution on github, equipped-MASK-avali modified by DasIrrlicht, equipped-MASK-vulpkanin modified by PolarTundraa on github.", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "icon" + }, + { + "name": "equipped-MASK", + "directions": 4 + }, + { + "name": "up-equipped-MASK", + "directions": 4 + } + ] +} diff --git a/Resources/Textures/ADT/Clothing/Mask/coif.rsi/up-equipped-MASK.png b/Resources/Textures/ADT/Clothing/Mask/coif.rsi/up-equipped-MASK.png new file mode 100644 index 00000000000..8763782fc9c Binary files /dev/null and b/Resources/Textures/ADT/Clothing/Mask/coif.rsi/up-equipped-MASK.png differ diff --git a/Resources/Textures/ADT/Mobs/Demons/angel_crying.rsi/angel.png b/Resources/Textures/ADT/Mobs/Demons/angel_crying.rsi/angel.png new file mode 100644 index 00000000000..6956a245da2 Binary files /dev/null and b/Resources/Textures/ADT/Mobs/Demons/angel_crying.rsi/angel.png differ diff --git a/Resources/Textures/ADT/Mobs/Demons/angel_crying.rsi/meta.json b/Resources/Textures/ADT/Mobs/Demons/angel_crying.rsi/meta.json new file mode 100644 index 00000000000..e563c9ece6c --- /dev/null +++ b/Resources/Textures/ADT/Mobs/Demons/angel_crying.rsi/meta.json @@ -0,0 +1,16 @@ +{ + "version": 1, + "size": { + "x": 32, + "y": 32 + }, + "license": "CC-BY-SA-3.0", + "copyright": "Sprite by discord:anvel", + "states": + [ + { + "name": "angel", + "directions": 4 + } + ] + } diff --git a/Resources/Textures/ADT/Objects/Devices/binoculars.rsi/binoculars.png b/Resources/Textures/ADT/Objects/Devices/binoculars.rsi/binoculars.png new file mode 100644 index 00000000000..7fc7f7f9c80 Binary files /dev/null and b/Resources/Textures/ADT/Objects/Devices/binoculars.rsi/binoculars.png differ diff --git a/Resources/Textures/ADT/Objects/Devices/binoculars.rsi/binoculars_civ.png b/Resources/Textures/ADT/Objects/Devices/binoculars.rsi/binoculars_civ.png new file mode 100644 index 00000000000..f6ecab07fef Binary files /dev/null and b/Resources/Textures/ADT/Objects/Devices/binoculars.rsi/binoculars_civ.png differ diff --git a/Resources/Textures/ADT/Objects/Devices/binoculars.rsi/binoculars_laser_civ.png b/Resources/Textures/ADT/Objects/Devices/binoculars.rsi/binoculars_laser_civ.png new file mode 100644 index 00000000000..569325e4ab0 Binary files /dev/null and b/Resources/Textures/ADT/Objects/Devices/binoculars.rsi/binoculars_laser_civ.png differ diff --git a/Resources/Textures/ADT/Objects/Devices/binoculars.rsi/binoculars_range_civ.png b/Resources/Textures/ADT/Objects/Devices/binoculars.rsi/binoculars_range_civ.png new file mode 100644 index 00000000000..fc03bc8070e Binary files /dev/null and b/Resources/Textures/ADT/Objects/Devices/binoculars.rsi/binoculars_range_civ.png differ diff --git a/Resources/Textures/ADT/Objects/Devices/binoculars.rsi/c_binoculars.png b/Resources/Textures/ADT/Objects/Devices/binoculars.rsi/c_binoculars.png new file mode 100644 index 00000000000..16b9d712165 Binary files /dev/null and b/Resources/Textures/ADT/Objects/Devices/binoculars.rsi/c_binoculars.png differ diff --git a/Resources/Textures/ADT/Objects/Devices/binoculars.rsi/c_rangefinder.png b/Resources/Textures/ADT/Objects/Devices/binoculars.rsi/c_rangefinder.png new file mode 100644 index 00000000000..d915a653e1e Binary files /dev/null and b/Resources/Textures/ADT/Objects/Devices/binoculars.rsi/c_rangefinder.png differ diff --git a/Resources/Textures/ADT/Objects/Devices/binoculars.rsi/d_binoculars.png b/Resources/Textures/ADT/Objects/Devices/binoculars.rsi/d_binoculars.png new file mode 100644 index 00000000000..203735f581e Binary files /dev/null and b/Resources/Textures/ADT/Objects/Devices/binoculars.rsi/d_binoculars.png differ diff --git a/Resources/Textures/ADT/Objects/Devices/binoculars.rsi/d_designator_b.png b/Resources/Textures/ADT/Objects/Devices/binoculars.rsi/d_designator_b.png new file mode 100644 index 00000000000..1ff805589e2 Binary files /dev/null and b/Resources/Textures/ADT/Objects/Devices/binoculars.rsi/d_designator_b.png differ diff --git a/Resources/Textures/ADT/Objects/Devices/binoculars.rsi/d_designator_e.png b/Resources/Textures/ADT/Objects/Devices/binoculars.rsi/d_designator_e.png new file mode 100644 index 00000000000..6cd311bc6af Binary files /dev/null and b/Resources/Textures/ADT/Objects/Devices/binoculars.rsi/d_designator_e.png differ diff --git a/Resources/Textures/ADT/Objects/Devices/binoculars.rsi/d_designator_r.png b/Resources/Textures/ADT/Objects/Devices/binoculars.rsi/d_designator_r.png new file mode 100644 index 00000000000..db4be711ba8 Binary files /dev/null and b/Resources/Textures/ADT/Objects/Devices/binoculars.rsi/d_designator_r.png differ diff --git a/Resources/Textures/ADT/Objects/Devices/binoculars.rsi/d_rangefinder.png b/Resources/Textures/ADT/Objects/Devices/binoculars.rsi/d_rangefinder.png new file mode 100644 index 00000000000..2ffe3abe1c4 Binary files /dev/null and b/Resources/Textures/ADT/Objects/Devices/binoculars.rsi/d_rangefinder.png differ diff --git a/Resources/Textures/ADT/Objects/Devices/binoculars.rsi/designator_b.png b/Resources/Textures/ADT/Objects/Devices/binoculars.rsi/designator_b.png new file mode 100644 index 00000000000..1ff805589e2 Binary files /dev/null and b/Resources/Textures/ADT/Objects/Devices/binoculars.rsi/designator_b.png differ diff --git a/Resources/Textures/ADT/Objects/Devices/binoculars.rsi/designator_e.png b/Resources/Textures/ADT/Objects/Devices/binoculars.rsi/designator_e.png new file mode 100644 index 00000000000..6cd311bc6af Binary files /dev/null and b/Resources/Textures/ADT/Objects/Devices/binoculars.rsi/designator_e.png differ diff --git a/Resources/Textures/ADT/Objects/Devices/binoculars.rsi/designator_r.png b/Resources/Textures/ADT/Objects/Devices/binoculars.rsi/designator_r.png new file mode 100644 index 00000000000..db4be711ba8 Binary files /dev/null and b/Resources/Textures/ADT/Objects/Devices/binoculars.rsi/designator_r.png differ diff --git a/Resources/Textures/ADT/Objects/Devices/binoculars.rsi/las_b.png b/Resources/Textures/ADT/Objects/Devices/binoculars.rsi/las_b.png new file mode 100644 index 00000000000..749a47c1bde Binary files /dev/null and b/Resources/Textures/ADT/Objects/Devices/binoculars.rsi/las_b.png differ diff --git a/Resources/Textures/ADT/Objects/Devices/binoculars.rsi/las_r.png b/Resources/Textures/ADT/Objects/Devices/binoculars.rsi/las_r.png new file mode 100644 index 00000000000..8e93d3cd1e8 Binary files /dev/null and b/Resources/Textures/ADT/Objects/Devices/binoculars.rsi/las_r.png differ diff --git a/Resources/Textures/ADT/Objects/Devices/binoculars.rsi/laser_cas.png b/Resources/Textures/ADT/Objects/Devices/binoculars.rsi/laser_cas.png new file mode 100644 index 00000000000..cfe7dcd96e8 Binary files /dev/null and b/Resources/Textures/ADT/Objects/Devices/binoculars.rsi/laser_cas.png differ diff --git a/Resources/Textures/ADT/Objects/Devices/binoculars.rsi/laser_range.png b/Resources/Textures/ADT/Objects/Devices/binoculars.rsi/laser_range.png new file mode 100644 index 00000000000..b902edac185 Binary files /dev/null and b/Resources/Textures/ADT/Objects/Devices/binoculars.rsi/laser_range.png differ diff --git a/Resources/Textures/ADT/Objects/Devices/binoculars.rsi/laser_spotter.png b/Resources/Textures/ADT/Objects/Devices/binoculars.rsi/laser_spotter.png new file mode 100644 index 00000000000..ce2fd93faa6 Binary files /dev/null and b/Resources/Textures/ADT/Objects/Devices/binoculars.rsi/laser_spotter.png differ diff --git a/Resources/Textures/ADT/Objects/Devices/binoculars.rsi/laslock_b.png b/Resources/Textures/ADT/Objects/Devices/binoculars.rsi/laslock_b.png new file mode 100644 index 00000000000..f048ac71074 Binary files /dev/null and b/Resources/Textures/ADT/Objects/Devices/binoculars.rsi/laslock_b.png differ diff --git a/Resources/Textures/ADT/Objects/Devices/binoculars.rsi/laslock_r.png b/Resources/Textures/ADT/Objects/Devices/binoculars.rsi/laslock_r.png new file mode 100644 index 00000000000..55853498f28 Binary files /dev/null and b/Resources/Textures/ADT/Objects/Devices/binoculars.rsi/laslock_r.png differ diff --git a/Resources/Textures/ADT/Objects/Devices/binoculars.rsi/meta.json b/Resources/Textures/ADT/Objects/Devices/binoculars.rsi/meta.json new file mode 100644 index 00000000000..b27d1219afa --- /dev/null +++ b/Resources/Textures/ADT/Objects/Devices/binoculars.rsi/meta.json @@ -0,0 +1,124 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from cmss13 at https://github.com/cmss13-devs/cmss13/blob/c67c5213507a19e10e252ef2898d94354c0709bf/icons/obj/items/binoculars.dmi", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "binoculars_civ" + }, + { + "name": "binoculars_laser_civ" + }, + { + "name": "binoculars_range_civ" + }, + { + "name": "designator_b" + }, + { + "name": "designator_r" + }, + { + "name": "designator_e" + }, + { + "name": "d_designator_b" + }, + { + "name": "d_designator_r" + }, + { + "name": "d_designator_e" + }, + { + "name": "las_r", + "delays": [ + [ + 0.2, + 0.2, + 0.2, + 0.2 + ] + ] + }, + { + "name": "las_b", + "delays": [ + [ + 0.2, + 0.2, + 0.2, + 0.2 + ] + ] + }, + { + "name": "laslock_r", + "delays": [ + [ + 0.1, + 0.1, + 0.1, + 0.1 + ] + ] + }, + { + "name": "laslock_b", + "delays": [ + [ + 0.1, + 0.1, + 0.1, + 0.1 + ] + ] + }, + { + "name": "binoculars" + }, + { + "name": "s_binoculars" + }, + { + "name": "d_binoculars" + }, + { + "name": "u_binoculars" + }, + { + "name": "c_binoculars" + }, + { + "name": "rangefinder" + }, + { + "name": "s_rangefinder" + }, + { + "name": "d_rangefinder" + }, + { + "name": "u_rangefinder" + }, + { + "name": "c_rangefinder" + }, + { + "name": "laser_cas" + }, + { + "name": "laser_range" + }, + { + "name": "laser_spotter" + }, + { + "name": "spotter_overlay" + } + ] +} \ No newline at end of file diff --git a/Resources/Textures/ADT/Objects/Devices/binoculars.rsi/rangefinder.png b/Resources/Textures/ADT/Objects/Devices/binoculars.rsi/rangefinder.png new file mode 100644 index 00000000000..f15d1d8820c Binary files /dev/null and b/Resources/Textures/ADT/Objects/Devices/binoculars.rsi/rangefinder.png differ diff --git a/Resources/Textures/ADT/Objects/Devices/binoculars.rsi/s_binoculars.png b/Resources/Textures/ADT/Objects/Devices/binoculars.rsi/s_binoculars.png new file mode 100644 index 00000000000..f2ada91f709 Binary files /dev/null and b/Resources/Textures/ADT/Objects/Devices/binoculars.rsi/s_binoculars.png differ diff --git a/Resources/Textures/ADT/Objects/Devices/binoculars.rsi/s_rangefinder.png b/Resources/Textures/ADT/Objects/Devices/binoculars.rsi/s_rangefinder.png new file mode 100644 index 00000000000..5593796c1c2 Binary files /dev/null and b/Resources/Textures/ADT/Objects/Devices/binoculars.rsi/s_rangefinder.png differ diff --git a/Resources/Textures/ADT/Objects/Devices/binoculars.rsi/spotter_overlay.png b/Resources/Textures/ADT/Objects/Devices/binoculars.rsi/spotter_overlay.png new file mode 100644 index 00000000000..748fdd65eaa Binary files /dev/null and b/Resources/Textures/ADT/Objects/Devices/binoculars.rsi/spotter_overlay.png differ diff --git a/Resources/Textures/ADT/Objects/Devices/binoculars.rsi/u_binoculars.png b/Resources/Textures/ADT/Objects/Devices/binoculars.rsi/u_binoculars.png new file mode 100644 index 00000000000..cf5561ef5c5 Binary files /dev/null and b/Resources/Textures/ADT/Objects/Devices/binoculars.rsi/u_binoculars.png differ diff --git a/Resources/Textures/ADT/Objects/Devices/binoculars.rsi/u_rangefinder.png b/Resources/Textures/ADT/Objects/Devices/binoculars.rsi/u_rangefinder.png new file mode 100644 index 00000000000..d632e837fff Binary files /dev/null and b/Resources/Textures/ADT/Objects/Devices/binoculars.rsi/u_rangefinder.png differ diff --git a/Resources/Textures/ADT/Objects/Fun/sharkplushie.rsi/meta.json b/Resources/Textures/ADT/Objects/Fun/sharkplushie.rsi/meta.json index 71392398528..9cdd05f97d1 100644 --- a/Resources/Textures/ADT/Objects/Fun/sharkplushie.rsi/meta.json +++ b/Resources/Textures/ADT/Objects/Fun/sharkplushie.rsi/meta.json @@ -17,6 +17,9 @@ { "name": "black-inhand-right", "directions": 4 + }, + { + "name": "mopbucket_shark_black" } ] } diff --git a/Resources/Textures/ADT/Objects/Fun/sharkplushie.rsi/mopbucket_shark_black.png b/Resources/Textures/ADT/Objects/Fun/sharkplushie.rsi/mopbucket_shark_black.png new file mode 100644 index 00000000000..06ee27944b1 Binary files /dev/null and b/Resources/Textures/ADT/Objects/Fun/sharkplushie.rsi/mopbucket_shark_black.png differ diff --git a/Resources/Textures/ADT/Objects/Weapons/Guns/Ammunition/Explosives/40mm_grenade.rsi/base-spent.png b/Resources/Textures/ADT/Objects/Weapons/Guns/Ammunition/Explosives/40mm_grenade.rsi/base-spent.png new file mode 100644 index 00000000000..2e79a9fc148 Binary files /dev/null and b/Resources/Textures/ADT/Objects/Weapons/Guns/Ammunition/Explosives/40mm_grenade.rsi/base-spent.png differ diff --git a/Resources/Textures/ADT/Objects/Weapons/Guns/Ammunition/Explosives/40mm_grenade.rsi/emp.png b/Resources/Textures/ADT/Objects/Weapons/Guns/Ammunition/Explosives/40mm_grenade.rsi/emp.png new file mode 100644 index 00000000000..ac609ea0fff Binary files /dev/null and b/Resources/Textures/ADT/Objects/Weapons/Guns/Ammunition/Explosives/40mm_grenade.rsi/emp.png differ diff --git a/Resources/Textures/ADT/Objects/Weapons/Guns/Ammunition/Explosives/40mm_grenade.rsi/flash.png b/Resources/Textures/ADT/Objects/Weapons/Guns/Ammunition/Explosives/40mm_grenade.rsi/flash.png new file mode 100644 index 00000000000..b75f9b9c112 Binary files /dev/null and b/Resources/Textures/ADT/Objects/Weapons/Guns/Ammunition/Explosives/40mm_grenade.rsi/flash.png differ diff --git a/Resources/Textures/ADT/Objects/Weapons/Guns/Ammunition/Explosives/40mm_grenade.rsi/he.png b/Resources/Textures/ADT/Objects/Weapons/Guns/Ammunition/Explosives/40mm_grenade.rsi/he.png new file mode 100644 index 00000000000..01fe138002a Binary files /dev/null and b/Resources/Textures/ADT/Objects/Weapons/Guns/Ammunition/Explosives/40mm_grenade.rsi/he.png differ diff --git a/Resources/Textures/ADT/Objects/Weapons/Guns/Ammunition/Explosives/40mm_grenade.rsi/heat.png b/Resources/Textures/ADT/Objects/Weapons/Guns/Ammunition/Explosives/40mm_grenade.rsi/heat.png new file mode 100644 index 00000000000..2ee5f0e2ef5 Binary files /dev/null and b/Resources/Textures/ADT/Objects/Weapons/Guns/Ammunition/Explosives/40mm_grenade.rsi/heat.png differ diff --git a/Resources/Textures/ADT/Objects/Weapons/Guns/Ammunition/Explosives/40mm_grenade.rsi/meta.json b/Resources/Textures/ADT/Objects/Weapons/Guns/Ammunition/Explosives/40mm_grenade.rsi/meta.json new file mode 100644 index 00000000000..3e6e9c35270 --- /dev/null +++ b/Resources/Textures/ADT/Objects/Weapons/Guns/Ammunition/Explosives/40mm_grenade.rsi/meta.json @@ -0,0 +1,35 @@ +{ + "version": 1, + "size": { + "x": 32, + "y": 32 + }, + "license": "CC-BY-SA-3.0", + "copyright": "Make by not_so_big_chungus", + "states": [ + { + "name": "emp" + }, + { + "name": "flash" + }, + { + "name": "he" + }, + { + "name": "heat" + }, + { + "name": "smoke" + }, + { + "name": "stinger" + }, + { + "name": "stun" + }, + { + "name": "base-spent" + } + ] +} diff --git a/Resources/Textures/ADT/Objects/Weapons/Guns/Ammunition/Explosives/40mm_grenade.rsi/smoke.png b/Resources/Textures/ADT/Objects/Weapons/Guns/Ammunition/Explosives/40mm_grenade.rsi/smoke.png new file mode 100644 index 00000000000..40df04afdb2 Binary files /dev/null and b/Resources/Textures/ADT/Objects/Weapons/Guns/Ammunition/Explosives/40mm_grenade.rsi/smoke.png differ diff --git a/Resources/Textures/ADT/Objects/Weapons/Guns/Ammunition/Explosives/40mm_grenade.rsi/stinger.png b/Resources/Textures/ADT/Objects/Weapons/Guns/Ammunition/Explosives/40mm_grenade.rsi/stinger.png new file mode 100644 index 00000000000..5bc491f000a Binary files /dev/null and b/Resources/Textures/ADT/Objects/Weapons/Guns/Ammunition/Explosives/40mm_grenade.rsi/stinger.png differ diff --git a/Resources/Textures/ADT/Objects/Weapons/Guns/Ammunition/Explosives/40mm_grenade.rsi/stun.png b/Resources/Textures/ADT/Objects/Weapons/Guns/Ammunition/Explosives/40mm_grenade.rsi/stun.png new file mode 100644 index 00000000000..46539d089df Binary files /dev/null and b/Resources/Textures/ADT/Objects/Weapons/Guns/Ammunition/Explosives/40mm_grenade.rsi/stun.png differ diff --git a/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/barrel.rsi/antilying.png b/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/barrel.rsi/antilying.png new file mode 100644 index 00000000000..0bc188086fc Binary files /dev/null and b/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/barrel.rsi/antilying.png differ diff --git a/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/barrel.rsi/antilying_a.png b/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/barrel.rsi/antilying_a.png new file mode 100644 index 00000000000..f89641b8c5b Binary files /dev/null and b/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/barrel.rsi/antilying_a.png differ diff --git a/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/barrel.rsi/meta.json b/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/barrel.rsi/meta.json new file mode 100644 index 00000000000..064fa3a1bf6 --- /dev/null +++ b/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/barrel.rsi/meta.json @@ -0,0 +1,23 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "taken from cmss13 at https://github.com/cmss13-devs/cmss13/blob/7e38a6a747b200b3854888a3eacd18b47992d066/icons/obj/items/weapons/guns/attachments", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "suppressor" + }, + { + "name": "suppressor_a" + }, + { + "name": "antilying" + }, + { + "name": "antilying_a" + } + ] +} diff --git a/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/barrel.rsi/suppressor.png b/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/barrel.rsi/suppressor.png new file mode 100644 index 00000000000..de1d235845d Binary files /dev/null and b/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/barrel.rsi/suppressor.png differ diff --git a/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/barrel.rsi/suppressor_a.png b/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/barrel.rsi/suppressor_a.png new file mode 100644 index 00000000000..aa07789eef6 Binary files /dev/null and b/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/barrel.rsi/suppressor_a.png differ diff --git a/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/rail.rsi/magnetic.png b/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/rail.rsi/magnetic.png new file mode 100644 index 00000000000..f52e9133eb9 Binary files /dev/null and b/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/rail.rsi/magnetic.png differ diff --git a/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/rail.rsi/meta.json b/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/rail.rsi/meta.json new file mode 100644 index 00000000000..1cd81382e43 --- /dev/null +++ b/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/rail.rsi/meta.json @@ -0,0 +1,26 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "magnetic taken from cmss13 at https://github.com/cmss13-devs/cmss13/blob/7e38a6a747b200b3854888a3eacd18b47992d066/icons/obj/items/weapons/guns/attachments/rail.dmi", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "magnetic" + }, + { + "name": "miniscope" + }, + { + "name": "miniscope_a" + }, + { + "name": "reflex" + }, + { + "name": "reflex_a" + } + ] +} diff --git a/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/rail.rsi/miniscope.png b/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/rail.rsi/miniscope.png new file mode 100644 index 00000000000..b186d9d4da7 Binary files /dev/null and b/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/rail.rsi/miniscope.png differ diff --git a/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/rail.rsi/miniscope_a.png b/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/rail.rsi/miniscope_a.png new file mode 100644 index 00000000000..f5272bb5a62 Binary files /dev/null and b/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/rail.rsi/miniscope_a.png differ diff --git a/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/rail.rsi/reflex.png b/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/rail.rsi/reflex.png new file mode 100644 index 00000000000..4f478522a2d Binary files /dev/null and b/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/rail.rsi/reflex.png differ diff --git a/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/rail.rsi/reflex_a.png b/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/rail.rsi/reflex_a.png new file mode 100644 index 00000000000..e4be6eb721d Binary files /dev/null and b/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/rail.rsi/reflex_a.png differ diff --git a/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/scope_actions.rsi/meta.json b/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/scope_actions.rsi/meta.json new file mode 100644 index 00000000000..13673645db9 --- /dev/null +++ b/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/scope_actions.rsi/meta.json @@ -0,0 +1,14 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from cmss13 at https://github.com/cmss13-devs/cmss13/blob/7cb618c69b75873f3ce893022fe08d1233b3152d/icons/obj/items/weapons/guns/attachments/rail.dmi", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "sniperscope" + } + ] +} \ No newline at end of file diff --git a/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/scope_actions.rsi/sniperscope.png b/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/scope_actions.rsi/sniperscope.png new file mode 100644 index 00000000000..d408b671953 Binary files /dev/null and b/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/scope_actions.rsi/sniperscope.png differ diff --git a/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/under.rsi/combatknife_a.png b/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/under.rsi/combatknife_a.png new file mode 100644 index 00000000000..4c92b4dc266 Binary files /dev/null and b/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/under.rsi/combatknife_a.png differ diff --git a/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/under.rsi/grenade-on.png b/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/under.rsi/grenade-on.png new file mode 100644 index 00000000000..101a03e8f13 Binary files /dev/null and b/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/under.rsi/grenade-on.png differ diff --git a/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/under.rsi/grenade-open.png b/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/under.rsi/grenade-open.png new file mode 100644 index 00000000000..1e847846603 Binary files /dev/null and b/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/under.rsi/grenade-open.png differ diff --git a/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/under.rsi/grenade-open_a.png b/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/under.rsi/grenade-open_a.png new file mode 100644 index 00000000000..1e847846603 Binary files /dev/null and b/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/under.rsi/grenade-open_a.png differ diff --git a/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/under.rsi/grenade.png b/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/under.rsi/grenade.png new file mode 100644 index 00000000000..d59ff4624c2 Binary files /dev/null and b/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/under.rsi/grenade.png differ diff --git a/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/under.rsi/grenade_a.png b/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/under.rsi/grenade_a.png new file mode 100644 index 00000000000..d59ff4624c2 Binary files /dev/null and b/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/under.rsi/grenade_a.png differ diff --git a/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/under.rsi/lasersight.png b/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/under.rsi/lasersight.png new file mode 100644 index 00000000000..ecff28b5465 Binary files /dev/null and b/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/under.rsi/lasersight.png differ diff --git a/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/under.rsi/lasersight_a.png b/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/under.rsi/lasersight_a.png new file mode 100644 index 00000000000..a916d13483e Binary files /dev/null and b/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/under.rsi/lasersight_a.png differ diff --git a/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/under.rsi/masterkey-on.png b/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/under.rsi/masterkey-on.png new file mode 100644 index 00000000000..222ad13c746 Binary files /dev/null and b/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/under.rsi/masterkey-on.png differ diff --git a/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/under.rsi/masterkey.png b/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/under.rsi/masterkey.png new file mode 100644 index 00000000000..4f47df56ede Binary files /dev/null and b/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/under.rsi/masterkey.png differ diff --git a/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/under.rsi/masterkey_a.png b/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/under.rsi/masterkey_a.png new file mode 100644 index 00000000000..f3b01148921 Binary files /dev/null and b/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/under.rsi/masterkey_a.png differ diff --git a/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/under.rsi/meta.json b/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/under.rsi/meta.json new file mode 100644 index 00000000000..f7b7c80f7c3 --- /dev/null +++ b/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/under.rsi/meta.json @@ -0,0 +1,66 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Created by discord: inconnu1337 and taken from RMC-14", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + + { + "name": "grenade" + }, + { + "name": "grenade-open" + }, + { + "name": "grenade-on" + }, + { + "name": "grenade_a" + }, + { + "name": "grenade-open_a" + }, + { + "name": "mosinbayonet" + }, + { + "name": "mosinbayonet_a" + }, + { + "name": "masterkey" + }, + { + "name": "masterkey-on" + }, + { + "name": "masterkey_a" + }, + { + "name": "verticalgrip" + }, + { + "name": "verticalgrip_a" + }, + { + "name": "lasersight" + }, + { + "name": "lasersight_a" + }, + { + "name": "combatknife_a" + }, + { + "name": "tech_basic" + }, + { + "name": "tech_extented" + }, + { + "name": "uplink_modules" + } + ] +} diff --git a/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/under.rsi/mosinbayonet.png b/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/under.rsi/mosinbayonet.png new file mode 100644 index 00000000000..51e6ddb8056 Binary files /dev/null and b/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/under.rsi/mosinbayonet.png differ diff --git a/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/under.rsi/mosinbayonet_a.png b/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/under.rsi/mosinbayonet_a.png new file mode 100644 index 00000000000..428cec765c3 Binary files /dev/null and b/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/under.rsi/mosinbayonet_a.png differ diff --git a/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/under.rsi/tech_basic.png b/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/under.rsi/tech_basic.png new file mode 100644 index 00000000000..a8221b729cb Binary files /dev/null and b/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/under.rsi/tech_basic.png differ diff --git a/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/under.rsi/tech_extented.png b/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/under.rsi/tech_extented.png new file mode 100644 index 00000000000..7320d637cb6 Binary files /dev/null and b/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/under.rsi/tech_extented.png differ diff --git a/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/under.rsi/uplink_modules.png b/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/under.rsi/uplink_modules.png new file mode 100644 index 00000000000..e6db6fe903d Binary files /dev/null and b/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/under.rsi/uplink_modules.png differ diff --git a/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/under.rsi/verticalgrip.png b/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/under.rsi/verticalgrip.png new file mode 100644 index 00000000000..2eb28365708 Binary files /dev/null and b/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/under.rsi/verticalgrip.png differ diff --git a/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/under.rsi/verticalgrip_a.png b/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/under.rsi/verticalgrip_a.png new file mode 100644 index 00000000000..1ad553627cc Binary files /dev/null and b/Resources/Textures/ADT/Objects/Weapons/Guns/Attachments/under.rsi/verticalgrip_a.png differ diff --git a/Resources/Textures/ADT/Objects/Weapons/Guns/Rifles/xc67.rsi/base.png b/Resources/Textures/ADT/Objects/Weapons/Guns/Rifles/xc67.rsi/base.png index f1353406806..02236c1be59 100644 Binary files a/Resources/Textures/ADT/Objects/Weapons/Guns/Rifles/xc67.rsi/base.png and b/Resources/Textures/ADT/Objects/Weapons/Guns/Rifles/xc67.rsi/base.png differ diff --git a/Resources/Textures/ADT/Objects/Weapons/Guns/Rifles/xc67.rsi/bolt-open.png b/Resources/Textures/ADT/Objects/Weapons/Guns/Rifles/xc67.rsi/bolt-open.png index 828d1aad6fe..3d86739abc6 100644 Binary files a/Resources/Textures/ADT/Objects/Weapons/Guns/Rifles/xc67.rsi/bolt-open.png and b/Resources/Textures/ADT/Objects/Weapons/Guns/Rifles/xc67.rsi/bolt-open.png differ diff --git a/Resources/Textures/ADT/Objects/Weapons/Guns/Rifles/xc67.rsi/icon.png b/Resources/Textures/ADT/Objects/Weapons/Guns/Rifles/xc67.rsi/icon.png index 6435fdf3af2..fd23a96f46b 100644 Binary files a/Resources/Textures/ADT/Objects/Weapons/Guns/Rifles/xc67.rsi/icon.png and b/Resources/Textures/ADT/Objects/Weapons/Guns/Rifles/xc67.rsi/icon.png differ diff --git a/Resources/Textures/ADT/Objects/Weapons/Guns/Rifles/xc67.rsi/wielded-inhand-left.png b/Resources/Textures/ADT/Objects/Weapons/Guns/Rifles/xc67.rsi/wielded-inhand-left.png index 28796011f65..5c24ca5f496 100644 Binary files a/Resources/Textures/ADT/Objects/Weapons/Guns/Rifles/xc67.rsi/wielded-inhand-left.png and b/Resources/Textures/ADT/Objects/Weapons/Guns/Rifles/xc67.rsi/wielded-inhand-left.png differ diff --git a/Resources/Textures/ADT/Objects/Weapons/Guns/Rifles/xc67.rsi/wielded-inhand-right.png b/Resources/Textures/ADT/Objects/Weapons/Guns/Rifles/xc67.rsi/wielded-inhand-right.png index c6eee6cb664..6ebb3b09fb5 100644 Binary files a/Resources/Textures/ADT/Objects/Weapons/Guns/Rifles/xc67.rsi/wielded-inhand-right.png and b/Resources/Textures/ADT/Objects/Weapons/Guns/Rifles/xc67.rsi/wielded-inhand-right.png differ diff --git a/Resources/Textures/ADT/Objects/Weapons/Melee/mosin_bayonet.rsi/equipped-BELT.png b/Resources/Textures/ADT/Objects/Weapons/Melee/mosin_bayonet.rsi/equipped-BELT.png new file mode 100644 index 00000000000..4f24bae15a0 Binary files /dev/null and b/Resources/Textures/ADT/Objects/Weapons/Melee/mosin_bayonet.rsi/equipped-BELT.png differ diff --git a/Resources/Textures/ADT/Objects/Weapons/Melee/mosin_bayonet.rsi/icon.png b/Resources/Textures/ADT/Objects/Weapons/Melee/mosin_bayonet.rsi/icon.png new file mode 100644 index 00000000000..51e6ddb8056 Binary files /dev/null and b/Resources/Textures/ADT/Objects/Weapons/Melee/mosin_bayonet.rsi/icon.png differ diff --git a/Resources/Textures/ADT/Objects/Weapons/Melee/mosin_bayonet.rsi/inhand-left.png b/Resources/Textures/ADT/Objects/Weapons/Melee/mosin_bayonet.rsi/inhand-left.png new file mode 100644 index 00000000000..b2fd137cf79 Binary files /dev/null and b/Resources/Textures/ADT/Objects/Weapons/Melee/mosin_bayonet.rsi/inhand-left.png differ diff --git a/Resources/Textures/ADT/Objects/Weapons/Melee/mosin_bayonet.rsi/inhand-right.png b/Resources/Textures/ADT/Objects/Weapons/Melee/mosin_bayonet.rsi/inhand-right.png new file mode 100644 index 00000000000..6adba6750c8 Binary files /dev/null and b/Resources/Textures/ADT/Objects/Weapons/Melee/mosin_bayonet.rsi/inhand-right.png differ diff --git a/Resources/Textures/ADT/Objects/Weapons/Melee/mosin_bayonet.rsi/meta.json b/Resources/Textures/ADT/Objects/Weapons/Melee/mosin_bayonet.rsi/meta.json new file mode 100644 index 00000000000..01a363305a1 --- /dev/null +++ b/Resources/Textures/ADT/Objects/Weapons/Melee/mosin_bayonet.rsi/meta.json @@ -0,0 +1,26 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Created by discord:not_so_big_chungus", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "icon" + }, + { + "name": "inhand-left", + "directions": 4 + }, + { + "name": "inhand-right", + "directions": 4 + }, + { + "name": "equipped-BELT", + "directions": 4 + } + ] +} diff --git a/Resources/Textures/Objects/Fun/sharkplush.rsi/meta.json b/Resources/Textures/Objects/Fun/sharkplush.rsi/meta.json index 33604c15fd1..a4b904e0a60 100644 --- a/Resources/Textures/Objects/Fun/sharkplush.rsi/meta.json +++ b/Resources/Textures/Objects/Fun/sharkplush.rsi/meta.json @@ -39,6 +39,9 @@ { "name": "grey-inhand-right", "directions": 4 + }, + { + "name": "mopbucket_shark_black" } ] } diff --git a/Resources/Textures/Objects/Weapons/Guns/Basic/kinetic_accelerator.rsi/icon_a.png b/Resources/Textures/Objects/Weapons/Guns/Basic/kinetic_accelerator.rsi/icon_a.png new file mode 100644 index 00000000000..28f96dcc283 Binary files /dev/null and b/Resources/Textures/Objects/Weapons/Guns/Basic/kinetic_accelerator.rsi/icon_a.png differ diff --git a/Resources/Textures/Objects/Weapons/Guns/Basic/kinetic_accelerator.rsi/meta.json b/Resources/Textures/Objects/Weapons/Guns/Basic/kinetic_accelerator.rsi/meta.json index 3aac7e37881..7a3f3af51da 100644 --- a/Resources/Textures/Objects/Weapons/Guns/Basic/kinetic_accelerator.rsi/meta.json +++ b/Resources/Textures/Objects/Weapons/Guns/Basic/kinetic_accelerator.rsi/meta.json @@ -10,6 +10,9 @@ { "name": "icon" }, + { + "name": "icon_a" + }, { "name": "animation-icon", "delays": [ diff --git a/Resources/Textures/Objects/Weapons/Guns/Rifles/carbine.rsi/base.png b/Resources/Textures/Objects/Weapons/Guns/Rifles/carbine.rsi/base.png index c9f1ce49e37..4cb8b48b7de 100644 Binary files a/Resources/Textures/Objects/Weapons/Guns/Rifles/carbine.rsi/base.png and b/Resources/Textures/Objects/Weapons/Guns/Rifles/carbine.rsi/base.png differ diff --git a/Resources/Textures/Objects/Weapons/Guns/Rifles/carbine.rsi/bolt-open.png b/Resources/Textures/Objects/Weapons/Guns/Rifles/carbine.rsi/bolt-open.png index 477b65066e2..4cb8b48b7de 100644 Binary files a/Resources/Textures/Objects/Weapons/Guns/Rifles/carbine.rsi/bolt-open.png and b/Resources/Textures/Objects/Weapons/Guns/Rifles/carbine.rsi/bolt-open.png differ diff --git a/Resources/Textures/Objects/Weapons/Guns/Rifles/carbine.rsi/icon.png b/Resources/Textures/Objects/Weapons/Guns/Rifles/carbine.rsi/icon.png index 34f9741a5f5..4cb8b48b7de 100644 Binary files a/Resources/Textures/Objects/Weapons/Guns/Rifles/carbine.rsi/icon.png and b/Resources/Textures/Objects/Weapons/Guns/Rifles/carbine.rsi/icon.png differ diff --git a/Resources/Textures/Objects/Weapons/Guns/Rifles/carbine.rsi/meta.json b/Resources/Textures/Objects/Weapons/Guns/Rifles/carbine.rsi/meta.json index cac6899c489..caaf002eb6b 100644 --- a/Resources/Textures/Objects/Weapons/Guns/Rifles/carbine.rsi/meta.json +++ b/Resources/Textures/Objects/Weapons/Guns/Rifles/carbine.rsi/meta.json @@ -1,7 +1,7 @@ { "version": 1, "license": "CC-BY-SA-3.0", - "copyright": "Taken from Polaris at https://github.com/PolarisSS13/Polaris/commit/ff87150c3dfc387c46db7d1c956abf19ddff7819, backpack sprite by Peptide, backpack sling sprite edited by Boaz1111", + "copyright": "Taken from Polaris at https://github.com/PolarisSS13/Polaris/commit/ff87150c3dfc387c46db7d1c956abf19ddff7819, backpack sprite by Peptide, backpack sling sprite edited by Boaz1111, M90GL resprited by Inconnu(discord)", "size": { "x": 32, "y": 32 diff --git a/Resources/Textures/Objects/Weapons/Melee/survival_knife.rsi/icon_a.png b/Resources/Textures/Objects/Weapons/Melee/survival_knife.rsi/icon_a.png new file mode 100644 index 00000000000..f02f0a4b567 Binary files /dev/null and b/Resources/Textures/Objects/Weapons/Melee/survival_knife.rsi/icon_a.png differ diff --git a/Resources/Textures/Objects/Weapons/Melee/survival_knife.rsi/meta.json b/Resources/Textures/Objects/Weapons/Melee/survival_knife.rsi/meta.json index ba497ca7861..ab9214718ec 100644 --- a/Resources/Textures/Objects/Weapons/Melee/survival_knife.rsi/meta.json +++ b/Resources/Textures/Objects/Weapons/Melee/survival_knife.rsi/meta.json @@ -10,6 +10,9 @@ { "name": "icon" }, + { + "name": "icon_a" + }, { "name": "inhand-left", "directions": 4 diff --git a/runclient.bat b/runclient.bat index 96237c34411..b961c9b3d70 100644 --- a/runclient.bat +++ b/runclient.bat @@ -1,2 +1,3 @@ @echo off dotnet run --project Content.Client +pause \ No newline at end of file