From 75ec5465509edcb1f4b3b9c43f44e0f123a6f5c1 Mon Sep 17 00:00:00 2001 From: SlamBamActionman <83650252+SlamBamActionman@users.noreply.github.com> Date: Thu, 14 Nov 2024 14:57:05 +0100 Subject: [PATCH 1/6] Update Label workflows to use new labels (#33310) * Update labeler.yml * Update labeler-needsreview.yml * Update labeler-staging.yml * Update labeler-stable.yml * Update labeler-untriaged.yml * Create labeler-size.yml * Update labeler-size.yml * Update labeler-size.yml * Update conflict-labeler.yml * Rename conflict-labeler.yml to labeler-conflict.yml --- .github/labeler.yml | 2 +- ...flict-labeler.yml => labeler-conflict.yml} | 2 +- .github/workflows/labeler-needsreview.yml | 4 ++-- .github/workflows/labeler-size.yml | 20 +++++++++++++++++++ .github/workflows/labeler-stable.yml | 2 +- .github/workflows/labeler-staging.yml | 2 +- .github/workflows/labeler-untriaged.yml | 4 +++- 7 files changed, 29 insertions(+), 7 deletions(-) rename .github/workflows/{conflict-labeler.yml => labeler-conflict.yml} (93%) create mode 100644 .github/workflows/labeler-size.yml diff --git a/.github/labeler.yml b/.github/labeler.yml index 97b402eda9ff..69b2ca87749c 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -16,7 +16,7 @@ - changed-files: - any-glob-to-any-file: '**/*.swsl' -"No C#": +"Changes: No C#": - changed-files: # Equiv to any-glob-to-all as long as this has one matcher. If ALL changed files are not C# files, then apply label. - all-globs-to-all-files: "!**/*.cs" diff --git a/.github/workflows/conflict-labeler.yml b/.github/workflows/labeler-conflict.yml similarity index 93% rename from .github/workflows/conflict-labeler.yml rename to .github/workflows/labeler-conflict.yml index 1e2125c30a23..ebcc54d4604d 100644 --- a/.github/workflows/conflict-labeler.yml +++ b/.github/workflows/labeler-conflict.yml @@ -16,6 +16,6 @@ jobs: - name: Check for Merge Conflicts uses: eps1lon/actions-label-merge-conflict@v3.0.0 with: - dirtyLabel: "Merge Conflict" + dirtyLabel: "S: Merge Conflict" repoToken: "${{ secrets.GITHUB_TOKEN }}" commentOnDirty: "This pull request has conflicts, please resolve those before we can evaluate the pull request." diff --git a/.github/workflows/labeler-needsreview.yml b/.github/workflows/labeler-needsreview.yml index 311048acb0f3..819b34b7bbd3 100644 --- a/.github/workflows/labeler-needsreview.yml +++ b/.github/workflows/labeler-needsreview.yml @@ -10,7 +10,7 @@ jobs: steps: - uses: actions-ecosystem/action-add-labels@v1 with: - labels: "Status: Needs Review" + labels: "S: Needs Review" - uses: actions-ecosystem/action-remove-labels@v1 with: - labels: "Status: Awaiting Changes" + labels: "S: Awaiting Changes" diff --git a/.github/workflows/labeler-size.yml b/.github/workflows/labeler-size.yml new file mode 100644 index 000000000000..ad6e35c82929 --- /dev/null +++ b/.github/workflows/labeler-size.yml @@ -0,0 +1,20 @@ +name: "Labels: Size" +on: pull_request_target +jobs: + size-label: + runs-on: ubuntu-latest + steps: + - name: size-label + uses: "pascalgn/size-label-action@v0.5.5" + env: + GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" + with: + # Custom size configuration + sizes: > + { + "0": "XS", + "10": "S", + "30": "M", + "100": "L", + "1000": "XL" + } diff --git a/.github/workflows/labeler-stable.yml b/.github/workflows/labeler-stable.yml index 491d6a76fad5..f6fd2033a11b 100644 --- a/.github/workflows/labeler-stable.yml +++ b/.github/workflows/labeler-stable.yml @@ -13,4 +13,4 @@ jobs: steps: - uses: actions-ecosystem/action-add-labels@v1 with: - labels: "Branch: stable" + labels: "Branch: Stable" diff --git a/.github/workflows/labeler-staging.yml b/.github/workflows/labeler-staging.yml index e31a5a482f2d..b46a198aefb5 100644 --- a/.github/workflows/labeler-staging.yml +++ b/.github/workflows/labeler-staging.yml @@ -13,4 +13,4 @@ jobs: steps: - uses: actions-ecosystem/action-add-labels@v1 with: - labels: "Branch: staging" + labels: "Branch: Staging" diff --git a/.github/workflows/labeler-untriaged.yml b/.github/workflows/labeler-untriaged.yml index 775aab265468..ec1d194851c5 100644 --- a/.github/workflows/labeler-untriaged.yml +++ b/.github/workflows/labeler-untriaged.yml @@ -3,6 +3,8 @@ on: issues: types: [opened] + pull_request_target: + types: [opened] jobs: add_label: @@ -11,4 +13,4 @@ jobs: - uses: actions-ecosystem/action-add-labels@v1 if: join(github.event.issue.labels) == '' with: - labels: "Status: Untriaged" + labels: "S: Untriaged" From 815e37e512ce7d1df152bac1642b769cf3e9bb32 Mon Sep 17 00:00:00 2001 From: CheddaCheez Date: Thu, 14 Nov 2024 10:56:21 -0600 Subject: [PATCH 2/6] Fix mime broken vow alert (#33303) Swap VowAlert and VowBrokenAlert on lines 149 and 150 so that the proper alerts are cleared and shown --- Content.Server/Abilities/Mime/MimePowersSystem.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Content.Server/Abilities/Mime/MimePowersSystem.cs b/Content.Server/Abilities/Mime/MimePowersSystem.cs index 20889f293c3b..bd8cf7c17661 100644 --- a/Content.Server/Abilities/Mime/MimePowersSystem.cs +++ b/Content.Server/Abilities/Mime/MimePowersSystem.cs @@ -146,8 +146,8 @@ public void RetakeVow(EntityUid uid, MimePowersComponent? mimePowers = null) mimePowers.ReadyToRepent = false; mimePowers.VowBroken = false; AddComp(uid); - _alertsSystem.ClearAlert(uid, mimePowers.VowAlert); - _alertsSystem.ShowAlert(uid, mimePowers.VowBrokenAlert); + _alertsSystem.ClearAlert(uid, mimePowers.VowBrokenAlert); + _alertsSystem.ShowAlert(uid, mimePowers.VowAlert); _actionsSystem.AddAction(uid, ref mimePowers.InvisibleWallActionEntity, mimePowers.InvisibleWallAction, uid); } } From 669bc148f91980f983b691d1e516b1b8d627a315 Mon Sep 17 00:00:00 2001 From: PJBot Date: Thu, 14 Nov 2024 16:57:29 +0000 Subject: [PATCH 3/6] Automatic changelog update --- Resources/Changelog/Changelog.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 9cc788c96f74..eb3f72680084 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,11 +1,4 @@ Entries: -- author: Blackern5000 - changes: - - message: Combat medical kits now contain saline syringes. - type: Add - id: 7108 - time: '2024-08-14T06:25:54.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/29954 - author: TheShuEd changes: - message: added morbilliard variants of procedural tacos and kebabs @@ -3941,3 +3934,10 @@ id: 7607 time: '2024-11-13T23:36:37.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/33201 +- author: CheddaCheez + changes: + - message: Fixed mimes being unable to break their vow more than once. Despicable! + type: Fix + id: 7608 + time: '2024-11-14T16:56:22.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/33303 From 1bebb3390ccedfdae173f0f681be6578146057ca Mon Sep 17 00:00:00 2001 From: Pieter-Jan Briers Date: Thu, 14 Nov 2024 18:08:35 +0100 Subject: [PATCH 4/6] Borg type switching. (#32586) * Borg type switching. This allows borgs (new spawn or constructed) to select their chassis type on creation, like in SS13. This removes the need for the many different chassis types, and means round-start borgs can actually play the game immediately instead of waiting for science to unlock everything. New borgs have an additional action that allows them to select their type. This opens a nice window with basic information about the borgs and a select button. Once a type has been selected it is permanent for that borg chassis. These borg types also immediately start the borg with specific modules, so they do not need to be printed. Additional modules can still be inserted for upgrades, though this is now less critical. The built-in modules cannot be removed, but are shown in the UI. The modules that each borg type starts with: * Generic: tools * Engineering: advanced tools, construction, RCD, cable * Salvage: Grappling gun, appraisal, mining * Janitor: cleaning, light replacer * Medical: treatment * Service: music, service, clowning Specialized borgs have 3 additional module slots available on top of the ones listed above, generic borgs have 5. Borg types are specified in a new BorgTypePrototype. These prototypes specify all information about the borg type. It is assigned to the borg entity through a mix of client side, server, and shared code. Some of the involved components were made networked, others are just ensured they're set on both sides of the wire. The most gnarly change is the inventory template prototype, which needs to change purely to modify the borg hat offset. I managed to bodge this in with an API that *probably* won't explode for specifically for this use case, but it's still not the most clean of API designs. Parts for specific borg chassis have been removed (so much deleted YAML) and specialized borg modules that are in the base set of a type have been removed from the exosuit fab as there's no point to printing those. The ability to "downgrade" a borg so it can select a new chassis, like in SS13, is something that would be nice, but was not high enough priority for me to block the feature on. I did keep it in mind with some of the code, so it may be possible in the future. There is no fancy animation when selecting borg types like in SS13, because I didn't think it was high priority, and it would add a lot of complex code. * Fix sandbox failure due to collection expression. * Module tweak Fix salvage borg modules still having research/lathe recipes Engie borg has regular tool module, not advanced. * Fix inventory system breakage * Fix migrations Some things were missing * Guidebook rewordings & review * MinWidth on confirm selection button --- .../Clothing/ClientClothingSystem.cs | 24 +- .../Inventory/ClientInventorySystem.cs | 16 +- Content.Client/Overlays/EquipmentHudSystem.cs | 3 +- .../Overlays/ShowHealthBarsSystem.cs | 7 + .../Overlays/ShowHealthIconsSystem.cs | 7 + .../Silicons/Borgs/BorgMenu.xaml.cs | 3 +- .../Silicons/Borgs/BorgModuleControl.xaml.cs | 3 +- .../Silicons/Borgs/BorgSelectTypeMenu.xaml | 43 ++ .../Silicons/Borgs/BorgSelectTypeMenu.xaml.cs | 81 +++ .../Borgs/BorgSelectTypeUserInterface.cs | 30 ++ .../Borgs/BorgSwitchableTypeSystem.cs | 81 +++ Content.Client/Silicons/Borgs/BorgSystem.cs | 14 + .../Borgs/BorgSwitchableTypeSystem.cs | 82 +++ .../Silicons/Borgs/BorgSystem.Modules.cs | 39 ++ .../Silicons/Borgs/BorgSystem.Transponder.cs | 17 + .../Silicons/Borgs/BorgSystem.Ui.cs | 3 + Content.Server/Silicons/Borgs/BorgSystem.cs | 15 +- .../Interaction/InteractionPopupSystem.cs | 22 + .../Inventory/InventoryComponent.cs | 10 +- .../Inventory/InventorySystem.Slots.cs | 49 ++ .../Overlays/ShowHealthBarsComponent.cs | 2 + .../Overlays/ShowHealthIconsComponent.cs | 2 + .../Silicons/Borgs/BorgTypePrototype.cs | 155 ++++++ .../Borgs/Components/BorgChassisComponent.cs | 15 +- .../Borgs/Components/BorgModuleComponent.cs | 8 + .../Components/BorgSwitchableTypeComponent.cs | 72 +++ .../Borgs/SharedBorgSwitchableTypeSystem.cs | 125 +++++ .../Silicons/Borgs/SharedBorgSystem.cs | 9 + Resources/Locale/en-US/borg/borg.ftl | 37 ++ Resources/Prototypes/Actions/borgs.yml | 12 + Resources/Prototypes/Body/Parts/silicon.yml | 47 +- .../Mobs/Cyborgs/base_borg_chassis.yml | 7 + .../Entities/Mobs/Cyborgs/borg_chassis.yml | 319 ++--------- .../Entities/Mobs/Player/silicon.yml | 21 +- .../Objects/Specific/Robotics/borg_parts.yml | 503 ------------------ .../Specific/Robotics/endoskeleton.yml | 169 +----- .../Entities/Structures/Machines/lathe.yml | 40 -- .../Prototypes/InventoryTemplates/borg.yml | 3 +- .../Construction/Graphs/machines/cyborg.yml | 173 +----- .../Prototypes/Recipes/Lathes/robotics.yml | 220 -------- .../Prototypes/Research/civilianservices.yml | 3 - Resources/Prototypes/Research/industrial.yml | 3 - .../Prototypes/Roles/Jobs/Science/borg.yml | 2 +- Resources/Prototypes/borg_types.yml | 218 ++++++++ Resources/Prototypes/tags.yml | 99 +--- .../ServerInfo/Guidebook/Science/Cyborgs.xml | 16 +- .../Actions/actions_borg.rsi/meta.json | 5 +- .../Actions/actions_borg.rsi/select-type.png | Bin 0 -> 408 bytes Resources/migration.yml | 35 ++ 49 files changed, 1336 insertions(+), 1533 deletions(-) create mode 100644 Content.Client/Silicons/Borgs/BorgSelectTypeMenu.xaml create mode 100644 Content.Client/Silicons/Borgs/BorgSelectTypeMenu.xaml.cs create mode 100644 Content.Client/Silicons/Borgs/BorgSelectTypeUserInterface.cs create mode 100644 Content.Client/Silicons/Borgs/BorgSwitchableTypeSystem.cs create mode 100644 Content.Server/Silicons/Borgs/BorgSwitchableTypeSystem.cs create mode 100644 Content.Shared/Silicons/Borgs/BorgTypePrototype.cs create mode 100644 Content.Shared/Silicons/Borgs/Components/BorgSwitchableTypeComponent.cs create mode 100644 Content.Shared/Silicons/Borgs/SharedBorgSwitchableTypeSystem.cs delete mode 100644 Resources/Prototypes/Entities/Objects/Specific/Robotics/borg_parts.yml create mode 100644 Resources/Prototypes/borg_types.yml create mode 100644 Resources/Textures/Interface/Actions/actions_borg.rsi/select-type.png diff --git a/Content.Client/Clothing/ClientClothingSystem.cs b/Content.Client/Clothing/ClientClothingSystem.cs index 3462fc923603..46f879e81560 100644 --- a/Content.Client/Clothing/ClientClothingSystem.cs +++ b/Content.Client/Clothing/ClientClothingSystem.cs @@ -58,6 +58,7 @@ public override void Initialize() base.Initialize(); SubscribeLocalEvent(OnGetVisuals); + SubscribeLocalEvent(OnInventoryTemplateUpdated); SubscribeLocalEvent(OnVisualsChanged); SubscribeLocalEvent(OnDidUnequip); @@ -70,11 +71,7 @@ private void OnAppearanceUpdate(EntityUid uid, InventoryComponent component, ref if (args.Sprite == null) return; - var enumerator = _inventorySystem.GetSlotEnumerator((uid, component)); - while (enumerator.NextItem(out var item, out var slot)) - { - RenderEquipment(uid, item, slot.Name, component); - } + UpdateAllSlots(uid, component); // No clothing equipped -> make sure the layer is hidden, though this should already be handled by on-unequip. if (args.Sprite.LayerMapTryGet(HumanoidVisualLayers.StencilMask, out var layer)) @@ -84,6 +81,23 @@ private void OnAppearanceUpdate(EntityUid uid, InventoryComponent component, ref } } + private void OnInventoryTemplateUpdated(Entity ent, ref InventoryTemplateUpdated args) + { + UpdateAllSlots(ent.Owner, clothing: ent.Comp); + } + + private void UpdateAllSlots( + EntityUid uid, + InventoryComponent? inventoryComponent = null, + ClothingComponent? clothing = null) + { + var enumerator = _inventorySystem.GetSlotEnumerator((uid, inventoryComponent)); + while (enumerator.NextItem(out var item, out var slot)) + { + RenderEquipment(uid, item, slot.Name, inventoryComponent, clothingComponent: clothing); + } + } + private void OnGetVisuals(EntityUid uid, ClothingComponent item, GetEquipmentVisualsEvent args) { if (!TryComp(args.Equipee, out InventoryComponent? inventory)) diff --git a/Content.Client/Inventory/ClientInventorySystem.cs b/Content.Client/Inventory/ClientInventorySystem.cs index 87cea4e3d2fc..dce401eefda5 100644 --- a/Content.Client/Inventory/ClientInventorySystem.cs +++ b/Content.Client/Inventory/ClientInventorySystem.cs @@ -235,9 +235,23 @@ public void UIInventoryAltActivateItem(string slot, EntityUid uid) EntityManager.RaisePredictiveEvent(new InteractInventorySlotEvent(GetNetEntity(item.Value), altInteract: true)); } + protected override void UpdateInventoryTemplate(Entity ent) + { + base.UpdateInventoryTemplate(ent); + + if (TryComp(ent, out InventorySlotsComponent? inventorySlots)) + { + foreach (var slot in ent.Comp.Slots) + { + if (inventorySlots.SlotData.TryGetValue(slot.Name, out var slotData)) + slotData.SlotDef = slot; + } + } + } + public sealed class SlotData { - public readonly SlotDefinition SlotDef; + public SlotDefinition SlotDef; public EntityUid? HeldEntity => Container?.ContainedEntity; public bool Blocked; public bool Highlighted; diff --git a/Content.Client/Overlays/EquipmentHudSystem.cs b/Content.Client/Overlays/EquipmentHudSystem.cs index c7578b6793f5..502a1f36274b 100644 --- a/Content.Client/Overlays/EquipmentHudSystem.cs +++ b/Content.Client/Overlays/EquipmentHudSystem.cs @@ -14,6 +14,7 @@ public abstract class EquipmentHudSystem : EntitySystem where T : IComponent { [Dependency] private readonly IPlayerManager _player = default!; + [ViewVariables] protected bool IsActive; protected virtual SlotFlags TargetSlots => ~SlotFlags.POCKET; @@ -102,7 +103,7 @@ protected virtual void OnRefreshComponentHud(EntityUid uid, T component, Refresh args.Components.Add(component); } - private void RefreshOverlay(EntityUid uid) + protected void RefreshOverlay(EntityUid uid) { if (uid != _player.LocalSession?.AttachedEntity) return; diff --git a/Content.Client/Overlays/ShowHealthBarsSystem.cs b/Content.Client/Overlays/ShowHealthBarsSystem.cs index 1eb712a8988f..b23209ff202b 100644 --- a/Content.Client/Overlays/ShowHealthBarsSystem.cs +++ b/Content.Client/Overlays/ShowHealthBarsSystem.cs @@ -21,9 +21,16 @@ public override void Initialize() { base.Initialize(); + SubscribeLocalEvent(OnHandleState); + _overlay = new(EntityManager, _prototype); } + private void OnHandleState(Entity ent, ref AfterAutoHandleStateEvent args) + { + RefreshOverlay(ent); + } + protected override void UpdateInternal(RefreshEquipmentHudEvent component) { base.UpdateInternal(component); diff --git a/Content.Client/Overlays/ShowHealthIconsSystem.cs b/Content.Client/Overlays/ShowHealthIconsSystem.cs index 8c22c78f17cd..b4d845e4217a 100644 --- a/Content.Client/Overlays/ShowHealthIconsSystem.cs +++ b/Content.Client/Overlays/ShowHealthIconsSystem.cs @@ -17,6 +17,7 @@ public sealed class ShowHealthIconsSystem : EquipmentHudSystem DamageContainers = new(); public override void Initialize() @@ -24,6 +25,7 @@ public override void Initialize() base.Initialize(); SubscribeLocalEvent(OnGetStatusIconsEvent); + SubscribeLocalEvent(OnHandleState); } protected override void UpdateInternal(RefreshEquipmentHudEvent component) @@ -43,6 +45,11 @@ protected override void DeactivateInternal() DamageContainers.Clear(); } + private void OnHandleState(Entity ent, ref AfterAutoHandleStateEvent args) + { + RefreshOverlay(ent); + } + private void OnGetStatusIconsEvent(Entity entity, ref GetStatusIconsEvent args) { if (!IsActive) diff --git a/Content.Client/Silicons/Borgs/BorgMenu.xaml.cs b/Content.Client/Silicons/Borgs/BorgMenu.xaml.cs index f6a861aa057b..b8f0e69c022f 100644 --- a/Content.Client/Silicons/Borgs/BorgMenu.xaml.cs +++ b/Content.Client/Silicons/Borgs/BorgMenu.xaml.cs @@ -131,7 +131,8 @@ private void UpdateModulePanel() _modules.Clear(); foreach (var module in chassis.ModuleContainer.ContainedEntities) { - var control = new BorgModuleControl(module, _entity); + var moduleComponent = _entity.GetComponent(module); + var control = new BorgModuleControl(module, _entity, !moduleComponent.DefaultModule); control.RemoveButtonPressed += () => { RemoveModuleButtonPressed?.Invoke(module); diff --git a/Content.Client/Silicons/Borgs/BorgModuleControl.xaml.cs b/Content.Client/Silicons/Borgs/BorgModuleControl.xaml.cs index d5cf05ba63ed..245425524ca0 100644 --- a/Content.Client/Silicons/Borgs/BorgModuleControl.xaml.cs +++ b/Content.Client/Silicons/Borgs/BorgModuleControl.xaml.cs @@ -9,7 +9,7 @@ public sealed partial class BorgModuleControl : PanelContainer { public Action? RemoveButtonPressed; - public BorgModuleControl(EntityUid entity, IEntityManager entityManager) + public BorgModuleControl(EntityUid entity, IEntityManager entityManager, bool canRemove) { RobustXamlLoader.Load(this); @@ -20,6 +20,7 @@ public BorgModuleControl(EntityUid entity, IEntityManager entityManager) { RemoveButtonPressed?.Invoke(); }; + RemoveButton.Visible = canRemove; } } diff --git a/Content.Client/Silicons/Borgs/BorgSelectTypeMenu.xaml b/Content.Client/Silicons/Borgs/BorgSelectTypeMenu.xaml new file mode 100644 index 000000000000..f51c2f53fd0d --- /dev/null +++ b/Content.Client/Silicons/Borgs/BorgSelectTypeMenu.xaml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + diff --git a/Content.Client/Silicons/Borgs/BorgSelectTypeMenu.xaml.cs b/Content.Client/Silicons/Borgs/BorgSelectTypeMenu.xaml.cs new file mode 100644 index 000000000000..e1fbd376b54e --- /dev/null +++ b/Content.Client/Silicons/Borgs/BorgSelectTypeMenu.xaml.cs @@ -0,0 +1,81 @@ +using System.Linq; +using Content.Client.UserInterface.Controls; +using Content.Client.UserInterface.Systems.Guidebook; +using Content.Shared.Guidebook; +using Content.Shared.Silicons.Borgs; +using Content.Shared.Silicons.Borgs.Components; +using Robust.Client.AutoGenerated; +using Robust.Client.UserInterface.Controls; +using Robust.Client.UserInterface.XAML; +using Robust.Shared.Prototypes; + +namespace Content.Client.Silicons.Borgs; + +/// +/// Menu used by borgs to select their type. +/// +/// +/// +[GenerateTypedNameReferences] +public sealed partial class BorgSelectTypeMenu : FancyWindow +{ + [Dependency] private readonly IPrototypeManager _prototypeManager = default!; + + private BorgTypePrototype? _selectedBorgType; + + public event Action>? ConfirmedBorgType; + + [ValidatePrototypeId] + private static readonly List> GuidebookEntries = new() { "Cyborgs", "Robotics" }; + + public BorgSelectTypeMenu() + { + RobustXamlLoader.Load(this); + IoCManager.InjectDependencies(this); + + var group = new ButtonGroup(); + foreach (var borgType in _prototypeManager.EnumeratePrototypes().OrderBy(PrototypeName)) + { + var button = new Button + { + Text = PrototypeName(borgType), + Group = group, + }; + button.OnPressed += _ => + { + _selectedBorgType = borgType; + UpdateInformation(borgType); + }; + SelectionsContainer.AddChild(button); + } + + ConfirmTypeButton.OnPressed += ConfirmButtonPressed; + HelpGuidebookIds = GuidebookEntries; + } + + private void UpdateInformation(BorgTypePrototype prototype) + { + _selectedBorgType = prototype; + + InfoContents.Visible = true; + InfoPlaceholder.Visible = false; + ConfirmTypeButton.Disabled = false; + + NameLabel.Text = PrototypeName(prototype); + DescriptionLabel.Text = Loc.GetString($"borg-type-{prototype.ID}-desc"); + ChassisView.SetPrototype(prototype.DummyPrototype); + } + + private void ConfirmButtonPressed(BaseButton.ButtonEventArgs obj) + { + if (_selectedBorgType == null) + return; + + ConfirmedBorgType?.Invoke(_selectedBorgType); + } + + private static string PrototypeName(BorgTypePrototype prototype) + { + return Loc.GetString($"borg-type-{prototype.ID}-name"); + } +} diff --git a/Content.Client/Silicons/Borgs/BorgSelectTypeUserInterface.cs b/Content.Client/Silicons/Borgs/BorgSelectTypeUserInterface.cs new file mode 100644 index 000000000000..8c76fade8c95 --- /dev/null +++ b/Content.Client/Silicons/Borgs/BorgSelectTypeUserInterface.cs @@ -0,0 +1,30 @@ +using Content.Shared.Silicons.Borgs.Components; +using JetBrains.Annotations; +using Robust.Client.UserInterface; + +namespace Content.Client.Silicons.Borgs; + +/// +/// User interface used by borgs to select their type. +/// +/// +/// +/// +[UsedImplicitly] +public sealed class BorgSelectTypeUserInterface : BoundUserInterface +{ + [ViewVariables] + private BorgSelectTypeMenu? _menu; + + public BorgSelectTypeUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey) + { + } + + protected override void Open() + { + base.Open(); + + _menu = this.CreateWindow(); + _menu.ConfirmedBorgType += prototype => SendMessage(new BorgSelectTypeMessage(prototype)); + } +} diff --git a/Content.Client/Silicons/Borgs/BorgSwitchableTypeSystem.cs b/Content.Client/Silicons/Borgs/BorgSwitchableTypeSystem.cs new file mode 100644 index 000000000000..346dc5c276ee --- /dev/null +++ b/Content.Client/Silicons/Borgs/BorgSwitchableTypeSystem.cs @@ -0,0 +1,81 @@ +using Content.Shared.Movement.Components; +using Content.Shared.Silicons.Borgs; +using Content.Shared.Silicons.Borgs.Components; +using Robust.Client.GameObjects; + +namespace Content.Client.Silicons.Borgs; + +/// +/// Client side logic for borg type switching. Sets up primarily client-side visual information. +/// +/// +/// +public sealed class BorgSwitchableTypeSystem : SharedBorgSwitchableTypeSystem +{ + [Dependency] private readonly BorgSystem _borgSystem = default!; + [Dependency] private readonly AppearanceSystem _appearance = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(AfterStateHandler); + SubscribeLocalEvent(OnComponentStartup); + } + + private void OnComponentStartup(Entity ent, ref ComponentStartup args) + { + UpdateEntityAppearance(ent); + } + + private void AfterStateHandler(Entity ent, ref AfterAutoHandleStateEvent args) + { + UpdateEntityAppearance(ent); + } + + protected override void UpdateEntityAppearance( + Entity entity, + BorgTypePrototype prototype) + { + if (TryComp(entity, out SpriteComponent? sprite)) + { + sprite.LayerSetState(BorgVisualLayers.Body, prototype.SpriteBodyState); + sprite.LayerSetState(BorgVisualLayers.LightStatus, prototype.SpriteToggleLightState); + } + + if (TryComp(entity, out BorgChassisComponent? chassis)) + { + _borgSystem.SetMindStates( + (entity.Owner, chassis), + prototype.SpriteHasMindState, + prototype.SpriteNoMindState); + + if (TryComp(entity, out AppearanceComponent? appearance)) + { + // Queue update so state changes apply. + _appearance.QueueUpdate(entity, appearance); + } + } + + if (prototype.SpriteBodyMovementState is { } movementState) + { + var spriteMovement = EnsureComp(entity); + spriteMovement.NoMovementLayers.Clear(); + spriteMovement.NoMovementLayers["movement"] = new PrototypeLayerData + { + State = prototype.SpriteBodyState, + }; + spriteMovement.MovementLayers.Clear(); + spriteMovement.MovementLayers["movement"] = new PrototypeLayerData + { + State = movementState, + }; + } + else + { + RemComp(entity); + } + + base.UpdateEntityAppearance(entity, prototype); + } +} diff --git a/Content.Client/Silicons/Borgs/BorgSystem.cs b/Content.Client/Silicons/Borgs/BorgSystem.cs index e92ce5cc7774..387a56384e9a 100644 --- a/Content.Client/Silicons/Borgs/BorgSystem.cs +++ b/Content.Client/Silicons/Borgs/BorgSystem.cs @@ -92,4 +92,18 @@ private void OnMMIAppearanceChanged(EntityUid uid, MMIComponent component, ref A sprite.LayerSetState(MMIVisualLayers.Base, state); } } + + /// + /// Sets the sprite states used for the borg "is there a mind or not" indication. + /// + /// The entity and component to modify. + /// The state to use if the borg has a mind. + /// The state to use if the borg has no mind. + /// + /// + public void SetMindStates(Entity borg, string hasMindState, string noMindState) + { + borg.Comp.HasMindState = hasMindState; + borg.Comp.NoMindState = noMindState; + } } diff --git a/Content.Server/Silicons/Borgs/BorgSwitchableTypeSystem.cs b/Content.Server/Silicons/Borgs/BorgSwitchableTypeSystem.cs new file mode 100644 index 000000000000..d1a32a6a5ba0 --- /dev/null +++ b/Content.Server/Silicons/Borgs/BorgSwitchableTypeSystem.cs @@ -0,0 +1,82 @@ +using Content.Server.Inventory; +using Content.Server.Radio.Components; +using Content.Shared.Inventory; +using Content.Shared.Silicons.Borgs; +using Content.Shared.Silicons.Borgs.Components; +using Robust.Shared.Prototypes; +using Robust.Shared.Utility; + +namespace Content.Server.Silicons.Borgs; + +/// +/// Server-side logic for borg type switching. Handles more heavyweight and server-specific switching logic. +/// +public sealed class BorgSwitchableTypeSystem : SharedBorgSwitchableTypeSystem +{ + [Dependency] private readonly BorgSystem _borgSystem = default!; + [Dependency] private readonly ServerInventorySystem _inventorySystem = default!; + + protected override void SelectBorgModule(Entity ent, ProtoId borgType) + { + var prototype = Prototypes.Index(borgType); + + // Assign radio channels + string[] radioChannels = [.. ent.Comp.InherentRadioChannels, .. prototype.RadioChannels]; + if (TryComp(ent, out IntrinsicRadioTransmitterComponent? transmitter)) + transmitter.Channels = [.. radioChannels]; + + if (TryComp(ent, out ActiveRadioComponent? activeRadio)) + activeRadio.Channels = [.. radioChannels]; + + // Borg transponder for the robotics console + if (TryComp(ent, out BorgTransponderComponent? transponder)) + { + _borgSystem.SetTransponderSprite( + (ent.Owner, transponder), + new SpriteSpecifier.Rsi(new ResPath("Mobs/Silicon/chassis.rsi"), prototype.SpriteBodyState)); + + _borgSystem.SetTransponderName( + (ent.Owner, transponder), + Loc.GetString($"borg-type-{borgType}-transponder")); + } + + // Configure modules + if (TryComp(ent, out BorgChassisComponent? chassis)) + { + var chassisEnt = (ent.Owner, chassis); + _borgSystem.SetMaxModules( + chassisEnt, + prototype.ExtraModuleCount + prototype.DefaultModules.Length); + + _borgSystem.SetModuleWhitelist(chassisEnt, prototype.ModuleWhitelist); + + foreach (var module in prototype.DefaultModules) + { + var moduleEntity = Spawn(module); + var borgModule = Comp(moduleEntity); + _borgSystem.SetBorgModuleDefault((moduleEntity, borgModule), true); + _borgSystem.InsertModule(chassisEnt, moduleEntity); + } + } + + // Configure special components + if (Prototypes.TryIndex(ent.Comp.SelectedBorgType, out var previousPrototype)) + { + if (previousPrototype.AddComponents is { } removeComponents) + EntityManager.RemoveComponents(ent, removeComponents); + } + + if (prototype.AddComponents is { } addComponents) + { + EntityManager.AddComponents(ent, addComponents); + } + + // Configure inventory template (used for hat spacing) + if (TryComp(ent, out InventoryComponent? inventory)) + { + _inventorySystem.SetTemplateId((ent.Owner, inventory), prototype.InventoryTemplateId); + } + + base.SelectBorgModule(ent, borgType); + } +} diff --git a/Content.Server/Silicons/Borgs/BorgSystem.Modules.cs b/Content.Server/Silicons/Borgs/BorgSystem.Modules.cs index d5a429db0309..f95a5807360c 100644 --- a/Content.Server/Silicons/Borgs/BorgSystem.Modules.cs +++ b/Content.Server/Silicons/Borgs/BorgSystem.Modules.cs @@ -2,6 +2,7 @@ using Content.Shared.Hands.Components; using Content.Shared.Interaction.Components; using Content.Shared.Silicons.Borgs.Components; +using Content.Shared.Whitelist; using Robust.Shared.Containers; namespace Content.Server.Silicons.Borgs; @@ -300,6 +301,24 @@ public bool CanInsertModule(EntityUid uid, EntityUid module, BorgChassisComponen return true; } + /// + /// Check if a module can be removed from a borg. + /// + /// The borg that the module is being removed from. + /// The module to remove from the borg. + /// The user attempting to remove the module. + /// True if the module can be removed. + public bool CanRemoveModule( + Entity borg, + Entity module, + EntityUid? user = null) + { + if (module.Comp.DefaultModule) + return false; + + return true; + } + /// /// Installs and activates all modules currently inside the borg's module container /// @@ -369,4 +388,24 @@ public void UninstallModule(EntityUid uid, EntityUid module, BorgChassisComponen var ev = new BorgModuleUninstalledEvent(uid); RaiseLocalEvent(module, ref ev); } + + /// + /// Sets . + /// + /// The borg to modify. + /// The new max module count. + public void SetMaxModules(Entity ent, int maxModules) + { + ent.Comp.MaxModules = maxModules; + } + + /// + /// Sets . + /// + /// The borg to modify. + /// The new module whitelist. + public void SetModuleWhitelist(Entity ent, EntityWhitelist? whitelist) + { + ent.Comp.ModuleWhitelist = whitelist; + } } diff --git a/Content.Server/Silicons/Borgs/BorgSystem.Transponder.cs b/Content.Server/Silicons/Borgs/BorgSystem.Transponder.cs index 781f847be35e..b4ba14004415 100644 --- a/Content.Server/Silicons/Borgs/BorgSystem.Transponder.cs +++ b/Content.Server/Silicons/Borgs/BorgSystem.Transponder.cs @@ -8,6 +8,7 @@ using Content.Server.DeviceNetwork.Components; using Content.Server.DeviceNetwork.Systems; using Content.Server.Explosion.Components; +using Robust.Shared.Utility; namespace Content.Server.Silicons.Borgs; @@ -134,4 +135,20 @@ private bool CheckEmagged(EntityUid uid, string name) return false; } + + /// + /// Sets . + /// + public void SetTransponderSprite(Entity ent, SpriteSpecifier sprite) + { + ent.Comp.Sprite = sprite; + } + + /// + /// Sets . + /// + public void SetTransponderName(Entity ent, string name) + { + ent.Comp.Name = name; + } } diff --git a/Content.Server/Silicons/Borgs/BorgSystem.Ui.cs b/Content.Server/Silicons/Borgs/BorgSystem.Ui.cs index d0e9f80e3645..40c2c3bf3324 100644 --- a/Content.Server/Silicons/Borgs/BorgSystem.Ui.cs +++ b/Content.Server/Silicons/Borgs/BorgSystem.Ui.cs @@ -82,6 +82,9 @@ private void OnRemoveModuleBuiMessage(EntityUid uid, BorgChassisComponent compon if (!component.ModuleContainer.Contains(module)) return; + if (!CanRemoveModule((uid, component), (module, Comp(module)), args.Actor)) + return; + _adminLog.Add(LogType.Action, LogImpact.Medium, $"{ToPrettyString(args.Actor):player} removed module {ToPrettyString(module)} from borg {ToPrettyString(uid)}"); _container.Remove(module, component.ModuleContainer); diff --git a/Content.Server/Silicons/Borgs/BorgSystem.cs b/Content.Server/Silicons/Borgs/BorgSystem.cs index bd85282a0f5e..ff204bfa8ceb 100644 --- a/Content.Server/Silicons/Borgs/BorgSystem.cs +++ b/Content.Server/Silicons/Borgs/BorgSystem.cs @@ -129,7 +129,7 @@ private void OnChassisInteractUsing(EntityUid uid, BorgChassisComponent componen if (module != null && CanInsertModule(uid, used, component, module, args.User)) { - _container.Insert(used, component.ModuleContainer); + InsertModule((uid, component), used); _adminLog.Add(LogType.Action, LogImpact.Low, $"{ToPrettyString(args.User):player} installed module {ToPrettyString(used)} into borg {ToPrettyString(uid)}"); args.Handled = true; @@ -137,6 +137,19 @@ private void OnChassisInteractUsing(EntityUid uid, BorgChassisComponent componen } } + /// + /// Inserts a new module into a borg, the same as if a player inserted it manually. + /// + /// + /// This does not run checks to see if the borg is actually allowed to be inserted, such as whitelists. + /// + /// The borg to insert into. + /// The module to insert. + public void InsertModule(Entity ent, EntityUid module) + { + _container.Insert(module, ent.Comp.ModuleContainer); + } + // todo: consider transferring over the ghost role? managing that might suck. protected override void OnInserted(EntityUid uid, BorgChassisComponent component, EntInsertedIntoContainerMessage args) { diff --git a/Content.Shared/Interaction/InteractionPopupSystem.cs b/Content.Shared/Interaction/InteractionPopupSystem.cs index 20c079dfd8c8..8df0035fc982 100644 --- a/Content.Shared/Interaction/InteractionPopupSystem.cs +++ b/Content.Shared/Interaction/InteractionPopupSystem.cs @@ -159,4 +159,26 @@ private void SharedInteract( _audio.PlayEntity(sfx, Filter.Empty().FromEntities(target), target, false); } } + + /// + /// Sets . + /// + /// + /// This field is not networked automatically, so this method must be called on both sides of the network. + /// + public void SetInteractSuccessString(Entity ent, string str) + { + ent.Comp.InteractSuccessString = str; + } + + /// + /// Sets . + /// + /// + /// This field is not networked automatically, so this method must be called on both sides of the network. + /// + public void SetInteractFailureString(Entity ent, string str) + { + ent.Comp.InteractFailureString = str; + } } diff --git a/Content.Shared/Inventory/InventoryComponent.cs b/Content.Shared/Inventory/InventoryComponent.cs index 629cf1169c45..61e0114ff24b 100644 --- a/Content.Shared/Inventory/InventoryComponent.cs +++ b/Content.Shared/Inventory/InventoryComponent.cs @@ -7,10 +7,12 @@ namespace Content.Shared.Inventory; [RegisterComponent, NetworkedComponent] [Access(typeof(InventorySystem))] +[AutoGenerateComponentState(true)] public sealed partial class InventoryComponent : Component { [DataField("templateId", customTypeSerializer: typeof(PrototypeIdSerializer))] - public string TemplateId { get; private set; } = "human"; + [AutoNetworkedField] + public string TemplateId { get; set; } = "human"; [DataField("speciesId")] public string? SpeciesId { get; set; } @@ -32,3 +34,9 @@ public sealed partial class InventoryComponent : Component [DataField] public Dictionary MaleDisplacements = new(); } + +/// +/// Raised if the of an inventory changed. +/// +[ByRefEvent] +public struct InventoryTemplateUpdated; diff --git a/Content.Shared/Inventory/InventorySystem.Slots.cs b/Content.Shared/Inventory/InventorySystem.Slots.cs index 2522dd5d0a33..04d58c1cd52d 100644 --- a/Content.Shared/Inventory/InventorySystem.Slots.cs +++ b/Content.Shared/Inventory/InventorySystem.Slots.cs @@ -1,4 +1,5 @@ using System.Diagnostics.CodeAnalysis; +using System.Linq; using Content.Shared.Inventory.Events; using Content.Shared.Storage; using Robust.Shared.Containers; @@ -19,6 +20,8 @@ private void InitializeSlots() _vvm.GetTypeHandler() .AddHandler(HandleViewVariablesSlots, ListViewVariablesSlots); + + SubscribeLocalEvent(AfterAutoState); } private void ShutdownSlots() @@ -68,6 +71,27 @@ protected virtual void OnInit(EntityUid uid, InventoryComponent component, Compo } } + private void AfterAutoState(Entity ent, ref AfterAutoHandleStateEvent args) + { + UpdateInventoryTemplate(ent); + } + + protected virtual void UpdateInventoryTemplate(Entity ent) + { + if (ent.Comp.LifeStage < ComponentLifeStage.Initialized) + return; + + if (!_prototypeManager.TryIndex(ent.Comp.TemplateId, out InventoryTemplatePrototype? invTemplate)) + return; + + DebugTools.Assert(ent.Comp.Slots.Length == invTemplate.Slots.Length); + + ent.Comp.Slots = invTemplate.Slots; + + var ev = new InventoryTemplateUpdated(); + RaiseLocalEvent(ent, ref ev); + } + private void OnOpenSlotStorage(OpenSlotStorageNetworkMessage ev, EntitySessionEventArgs args) { if (args.SenderSession.AttachedEntity is not { Valid: true } uid) @@ -170,6 +194,31 @@ private IEnumerable ListViewVariablesSlots(EntityUid uid, InventoryCompo } } + /// + /// Change the inventory template ID an entity is using. The new template must be compatible. + /// + /// + /// + /// For an inventory template to be compatible with another, it must have exactly the same slot names. + /// All other changes are rejected. + /// + /// + /// The entity to update. + /// The ID of the new inventory template prototype. + /// + /// Thrown if the new template is not compatible with the existing one. + /// + public void SetTemplateId(Entity ent, ProtoId newTemplate) + { + var newPrototype = _prototypeManager.Index(newTemplate); + + if (!newPrototype.Slots.Select(x => x.Name).SequenceEqual(ent.Comp.Slots.Select(x => x.Name))) + throw new ArgumentException("Incompatible inventory template!"); + + ent.Comp.TemplateId = newTemplate; + Dirty(ent); + } + /// /// Enumerator for iterating over an inventory's slot containers. Also has methods that skip empty containers. /// It should be safe to add or remove items while enumerating. diff --git a/Content.Shared/Overlays/ShowHealthBarsComponent.cs b/Content.Shared/Overlays/ShowHealthBarsComponent.cs index cb4f0fe7dd49..3f27885db18c 100644 --- a/Content.Shared/Overlays/ShowHealthBarsComponent.cs +++ b/Content.Shared/Overlays/ShowHealthBarsComponent.cs @@ -9,12 +9,14 @@ namespace Content.Shared.Overlays; /// This component allows you to see health bars above damageable mobs. /// [RegisterComponent, NetworkedComponent] +[AutoGenerateComponentState(true)] public sealed partial class ShowHealthBarsComponent : Component { /// /// Displays health bars of the damage containers. /// [DataField] + [AutoNetworkedField] public List> DamageContainers = new() { "Biological" diff --git a/Content.Shared/Overlays/ShowHealthIconsComponent.cs b/Content.Shared/Overlays/ShowHealthIconsComponent.cs index aa12c9887a8e..bc8b5419d2a1 100644 --- a/Content.Shared/Overlays/ShowHealthIconsComponent.cs +++ b/Content.Shared/Overlays/ShowHealthIconsComponent.cs @@ -8,12 +8,14 @@ namespace Content.Shared.Overlays; /// This component allows you to see health status icons above damageable mobs. /// [RegisterComponent, NetworkedComponent] +[AutoGenerateComponentState(true)] public sealed partial class ShowHealthIconsComponent : Component { /// /// Displays health status icons of the damage containers. /// [DataField] + [AutoNetworkedField] public List> DamageContainers = new() { "Biological" diff --git a/Content.Shared/Silicons/Borgs/BorgTypePrototype.cs b/Content.Shared/Silicons/Borgs/BorgTypePrototype.cs new file mode 100644 index 000000000000..6154c1275774 --- /dev/null +++ b/Content.Shared/Silicons/Borgs/BorgTypePrototype.cs @@ -0,0 +1,155 @@ +using Content.Shared.Interaction.Components; +using Content.Shared.Inventory; +using Content.Shared.Radio; +using Content.Shared.Silicons.Borgs.Components; +using Content.Shared.Whitelist; +using Robust.Shared.Audio; +using Robust.Shared.Prototypes; + +namespace Content.Shared.Silicons.Borgs; + +/// +/// Information for a borg type that can be selected by . +/// +/// +[Prototype] +public sealed partial class BorgTypePrototype : IPrototype +{ + [ValidatePrototypeId] + private static readonly ProtoId DefaultFootsteps = new("FootstepBorg"); + + [IdDataField] + public required string ID { get; init; } + + // + // Description info (name/desc) is configured via localization strings directly. + // + + /// + /// The prototype displayed in the selection menu for this type. + /// + [DataField] + public required EntProtoId DummyPrototype { get; init; } + + // + // Functional information + // + + /// + /// The amount of free module slots this borg type has. + /// + /// + /// This count is on top of the modules specified in . + /// + /// + [DataField] + public int ExtraModuleCount { get; set; } = 0; + + /// + /// The whitelist for borg modules that can be inserted into this borg type. + /// + /// + [DataField] + public EntityWhitelist? ModuleWhitelist { get; set; } + + /// + /// Inventory template used by this borg. + /// + /// + /// This template must be compatible with the normal borg templates, + /// so in practice it can only be used to differentiate the visual position of the slots on the character sprites. + /// + /// + [DataField] + public ProtoId InventoryTemplateId { get; set; } = "borgShort"; + + /// + /// Radio channels that this borg will gain access to from this module. + /// + /// + /// These channels are provided on top of the ones specified in + /// . + /// + [DataField] + public ProtoId[] RadioChannels = []; + + /// + /// Borg module types that are always available to borgs of this type. + /// + /// + /// These modules still work like modules, although they cannot be removed from the borg. + /// + /// + [DataField] + public EntProtoId[] DefaultModules = []; + + /// + /// Additional components to add to the borg entity when this type is selected. + /// + [DataField] + public ComponentRegistry? AddComponents { get; set; } + + // + // Visual information + // + + /// + /// The sprite state for the main borg body. + /// + [DataField] + public string SpriteBodyState { get; set; } = "robot"; + + /// + /// An optional movement sprite state for the main borg body. + /// + [DataField] + public string? SpriteBodyMovementState { get; set; } + + /// + /// Sprite state used to indicate that the borg has a mind in it. + /// + /// + [DataField] + public string SpriteHasMindState { get; set; } = "robot_e"; + + /// + /// Sprite state used to indicate that the borg has no mind in it. + /// + /// + [DataField] + public string SpriteNoMindState { get; set; } = "robot_e_r"; + + /// + /// Sprite state used when the borg's flashlight is on. + /// + [DataField] + public string SpriteToggleLightState { get; set; } = "robot_l"; + + // + // Minor information + // + + /// + /// String to use on petting success. + /// + /// + [DataField] + public string PetSuccessString { get; set; } = "petting-success-generic-cyborg"; + + /// + /// String to use on petting failure. + /// + /// + [DataField] + public string PetFailureString { get; set; } = "petting-failure-generic-cyborg"; + + // + // Sounds + // + + /// + /// Sound specifier for footstep sounds created by this borg. + /// + [DataField] + public SoundSpecifier FootstepCollection { get; set; } = new SoundCollectionSpecifier(DefaultFootsteps); +} diff --git a/Content.Shared/Silicons/Borgs/Components/BorgChassisComponent.cs b/Content.Shared/Silicons/Borgs/Components/BorgChassisComponent.cs index de0fe0bce381..c2bf2b2801b1 100644 --- a/Content.Shared/Silicons/Borgs/Components/BorgChassisComponent.cs +++ b/Content.Shared/Silicons/Borgs/Components/BorgChassisComponent.cs @@ -89,5 +89,18 @@ public enum BorgVisuals : byte [Serializable, NetSerializable] public enum BorgVisualLayers : byte { - Light + /// + /// Main borg body layer. + /// + Body, + + /// + /// Layer for the borg's mind state. + /// + Light, + + /// + /// Layer for the borg flashlight status. + /// + LightStatus, } diff --git a/Content.Shared/Silicons/Borgs/Components/BorgModuleComponent.cs b/Content.Shared/Silicons/Borgs/Components/BorgModuleComponent.cs index a7523c1ce702..e542a1e3e3e8 100644 --- a/Content.Shared/Silicons/Borgs/Components/BorgModuleComponent.cs +++ b/Content.Shared/Silicons/Borgs/Components/BorgModuleComponent.cs @@ -7,6 +7,7 @@ namespace Content.Shared.Silicons.Borgs.Components; /// to give them unique abilities and attributes. /// [RegisterComponent, NetworkedComponent, Access(typeof(SharedBorgSystem))] +[AutoGenerateComponentState] public sealed partial class BorgModuleComponent : Component { /// @@ -16,6 +17,13 @@ public sealed partial class BorgModuleComponent : Component public EntityUid? InstalledEntity; public bool Installed => InstalledEntity != null; + + /// + /// If true, this is a "default" module that cannot be removed from a borg. + /// + [DataField] + [AutoNetworkedField] + public bool DefaultModule; } /// diff --git a/Content.Shared/Silicons/Borgs/Components/BorgSwitchableTypeComponent.cs b/Content.Shared/Silicons/Borgs/Components/BorgSwitchableTypeComponent.cs new file mode 100644 index 000000000000..9a783d19aa7d --- /dev/null +++ b/Content.Shared/Silicons/Borgs/Components/BorgSwitchableTypeComponent.cs @@ -0,0 +1,72 @@ +using Content.Shared.Actions; +using Content.Shared.Radio; +using Robust.Shared.GameStates; +using Robust.Shared.Prototypes; +using Robust.Shared.Serialization; + +namespace Content.Shared.Silicons.Borgs.Components; + +/// +/// Component for borgs that can switch their "type" after being created. +/// +/// +/// +/// This is used by all NT borgs, on construction and round-start spawn. +/// Borgs are effectively useless until they have made their choice of type. +/// Borg type selections are currently irreversible. +/// +/// +/// Available types are specified in s. +/// +/// +/// +[RegisterComponent, NetworkedComponent] +[AutoGenerateComponentState(raiseAfterAutoHandleState: true)] +[Access(typeof(SharedBorgSwitchableTypeSystem))] +public sealed partial class BorgSwitchableTypeComponent : Component +{ + /// + /// Action entity used by players to select their type. + /// + [DataField, AutoNetworkedField] + public EntityUid? SelectTypeAction; + + /// + /// The currently selected borg type, if any. + /// + /// + /// This can be set in a prototype to immediately apply a borg type, and not have switching support. + /// + [DataField, AutoNetworkedField] + public ProtoId? SelectedBorgType; + + /// + /// Radio channels that the borg will always have. These are added on top of the selected type's radio channels. + /// + [DataField] + public ProtoId[] InherentRadioChannels = []; +} + +/// +/// Action event used to open the selection menu of a . +/// +public sealed partial class BorgToggleSelectTypeEvent : InstantActionEvent; + +/// +/// UI message used by a borg to select their type with . +/// +/// The borg type prototype that the user selected. +[Serializable, NetSerializable] +public sealed class BorgSelectTypeMessage(ProtoId prototype) : BoundUserInterfaceMessage +{ + public ProtoId Prototype = prototype; +} + +/// +/// UI key used by the selection menu for . +/// +[NetSerializable, Serializable] +public enum BorgSwitchableTypeUiKey : byte +{ + SelectBorgType, +} diff --git a/Content.Shared/Silicons/Borgs/SharedBorgSwitchableTypeSystem.cs b/Content.Shared/Silicons/Borgs/SharedBorgSwitchableTypeSystem.cs new file mode 100644 index 000000000000..d9abeb2d3266 --- /dev/null +++ b/Content.Shared/Silicons/Borgs/SharedBorgSwitchableTypeSystem.cs @@ -0,0 +1,125 @@ +using Content.Shared.Actions; +using Content.Shared.Interaction; +using Content.Shared.Interaction.Components; +using Content.Shared.Movement.Components; +using Content.Shared.Silicons.Borgs.Components; +using Robust.Shared.Player; +using Robust.Shared.Prototypes; + +namespace Content.Shared.Silicons.Borgs; + +/// +/// Implements borg type switching. +/// +/// +public abstract class SharedBorgSwitchableTypeSystem : EntitySystem +{ + // TODO: Allow borgs to be reset to default configuration. + + [Dependency] private readonly SharedActionsSystem _actionsSystem = default!; + [Dependency] private readonly SharedUserInterfaceSystem _userInterface = default!; + [Dependency] protected readonly IPrototypeManager Prototypes = default!; + [Dependency] private readonly InteractionPopupSystem _interactionPopup = default!; + + [ValidatePrototypeId] + public const string ActionId = "ActionSelectBorgType"; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnMapInit); + SubscribeLocalEvent(OnShutdown); + SubscribeLocalEvent(OnSelectBorgTypeAction); + + Subs.BuiEvents(BorgSwitchableTypeUiKey.SelectBorgType, + sub => + { + sub.Event(SelectTypeMessageHandler); + }); + } + + // + // UI-adjacent code + // + + private void OnMapInit(Entity ent, ref MapInitEvent args) + { + _actionsSystem.AddAction(ent, ref ent.Comp.SelectTypeAction, ActionId); + Dirty(ent); + + if (ent.Comp.SelectedBorgType != null) + { + SelectBorgModule(ent, ent.Comp.SelectedBorgType.Value); + } + } + + private void OnShutdown(Entity ent, ref ComponentShutdown args) + { + _actionsSystem.RemoveAction(ent, ent.Comp.SelectTypeAction); + } + + private void OnSelectBorgTypeAction(Entity ent, ref BorgToggleSelectTypeEvent args) + { + if (args.Handled || !TryComp(ent, out var actor)) + return; + + args.Handled = true; + + _userInterface.TryToggleUi((ent.Owner, null), BorgSwitchableTypeUiKey.SelectBorgType, actor.PlayerSession); + } + + private void SelectTypeMessageHandler(Entity ent, ref BorgSelectTypeMessage args) + { + if (ent.Comp.SelectedBorgType != null) + return; + + if (!Prototypes.HasIndex(args.Prototype)) + return; + + SelectBorgModule(ent, args.Prototype); + } + + // + // Implementation + // + + protected virtual void SelectBorgModule( + Entity ent, + ProtoId borgType) + { + ent.Comp.SelectedBorgType = borgType; + + _actionsSystem.RemoveAction(ent, ent.Comp.SelectTypeAction); + ent.Comp.SelectTypeAction = null; + Dirty(ent); + + _userInterface.CloseUi((ent.Owner, null), BorgSwitchableTypeUiKey.SelectBorgType); + + UpdateEntityAppearance(ent); + } + + protected void UpdateEntityAppearance(Entity entity) + { + if (!Prototypes.TryIndex(entity.Comp.SelectedBorgType, out var proto)) + return; + + UpdateEntityAppearance(entity, proto); + } + + protected virtual void UpdateEntityAppearance( + Entity entity, + BorgTypePrototype prototype) + { + if (TryComp(entity, out InteractionPopupComponent? popup)) + { + _interactionPopup.SetInteractSuccessString((entity.Owner, popup), prototype.PetSuccessString); + _interactionPopup.SetInteractFailureString((entity.Owner, popup), prototype.PetFailureString); + } + + if (TryComp(entity, out FootstepModifierComponent? footstepModifier)) + { + footstepModifier.FootstepSoundCollection = prototype.FootstepCollection; + } + } +} diff --git a/Content.Shared/Silicons/Borgs/SharedBorgSystem.cs b/Content.Shared/Silicons/Borgs/SharedBorgSystem.cs index c62e63481d62..827bb351b078 100644 --- a/Content.Shared/Silicons/Borgs/SharedBorgSystem.cs +++ b/Content.Shared/Silicons/Borgs/SharedBorgSystem.cs @@ -124,4 +124,13 @@ private void OnRefreshMovementSpeedModifiers(EntityUid uid, BorgChassisComponent var sprintDif = movement.BaseWalkSpeed / movement.BaseSprintSpeed; args.ModifySpeed(1f, sprintDif); } + + /// + /// Sets . + /// + public void SetBorgModuleDefault(Entity ent, bool newDefault) + { + ent.Comp.DefaultModule = newDefault; + Dirty(ent); + } } diff --git a/Resources/Locale/en-US/borg/borg.ftl b/Resources/Locale/en-US/borg/borg.ftl index 6c495510b05a..9c9dc71069a6 100644 --- a/Resources/Locale/en-US/borg/borg.ftl +++ b/Resources/Locale/en-US/borg/borg.ftl @@ -25,3 +25,40 @@ borg-transponder-disabling-popup = Your transponder begins to lock you out of th borg-transponder-destroying-popup = The self destruct of {$name} starts beeping! borg-transponder-emagged-disabled-popup = Your transponder's lights go out! borg-transponder-emagged-destroyed-popup = Your transponder's fuse blows! + +## Borg type selection UI. +borg-select-type-menu-title = Select Chassis Type +borg-select-type-menu-bottom-text = Chassis selection is irreversible +borg-select-type-menu-available = Available types +borg-select-type-menu-information = Information +borg-select-type-menu-select-type = Select type to view information +borg-select-type-menu-confirm = Confirm selection +borg-select-type-menu-guidebook = Guidebook + +## Borg type information + +borg-type-generic-name = Generic +borg-type-generic-desc = Jack of all trades, master of none. Do various random station tasks, or maybe help out the science department that built you. +borg-type-generic-transponder = generic cyborg + +borg-type-engineering-name = Engineering +borg-type-engineering-desc = Assist the engineering team in station construction, repairing damage, or fixing electrical and atmospheric issues. +borg-type-engineering-transponder = engineering cyborg + +borg-type-mining-name = Salvage +borg-type-mining-desc = Join salvage and help them mine for materials, scavenge wrecks, and fight off hostile wildlife. +borg-type-mining-transponder = salvage cyborg + +borg-type-janitor-name = Janitor +borg-type-janitor-desc = Keep the station nice and tidy, clean up spills, collect and properly dispose of trash left around by lazy crewmembers. +borg-type-janitor-transponder = janitor cyborg + +borg-type-medical-name = Medical +borg-type-medical-desc = Provide medical attention to crew who need it, either in medbay or in hazardous areas conventional paramedics cannot reach. +borg-type-medical-transponder = medical cyborg + +borg-type-service-name = Service +borg-type-service-desc = Help out with a wide range of crew services, ranging from serving snacks and drinks to botany to entertainment. +borg-type-service-transponder = service cyborg + + diff --git a/Resources/Prototypes/Actions/borgs.yml b/Resources/Prototypes/Actions/borgs.yml index a0168ef00fc4..0f635ba3ec67 100644 --- a/Resources/Prototypes/Actions/borgs.yml +++ b/Resources/Prototypes/Actions/borgs.yml @@ -10,3 +10,15 @@ state: state-laws event: !type:ToggleLawsScreenEvent useDelay: 0.5 + +- type: entity + id: ActionSelectBorgType + name: Select Cyborg Type + components: + - type: InstantAction + itemIconStyle: NoItem + icon: + sprite: Interface/Actions/actions_borg.rsi + state: select-type + event: !type:BorgToggleSelectTypeEvent + useDelay: 0.5 diff --git a/Resources/Prototypes/Body/Parts/silicon.yml b/Resources/Prototypes/Body/Parts/silicon.yml index 6b2b3f57d264..3b0f2540963d 100644 --- a/Resources/Prototypes/Body/Parts/silicon.yml +++ b/Resources/Prototypes/Body/Parts/silicon.yml @@ -28,82 +28,105 @@ - Robotics - type: entity - id: BaseBorgArmLeft + id: LeftArmBorg parent: PartSilicon name: cyborg left arm - abstract: true components: - type: BodyPart partType: Hand symmetry: Left + - type: Sprite + state: borg_l_arm + - type: Icon + state: borg_l_arm - type: Tag tags: - Trash - BorgArm + - BorgLArm - type: entity - id: BaseBorgArmRight + id: RightArmBorg parent: PartSilicon name: cyborg right arm - abstract: true components: - type: BodyPart partType: Hand symmetry: Right + - type: Sprite + state: borg_r_arm + - type: Icon + state: borg_r_arm - type: Tag tags: - Trash - BorgArm + - BorgRArm - type: entity - id: BaseBorgLegLeft + id: LeftLegBorg parent: PartSilicon name: cyborg left leg - abstract: true components: - type: BodyPart partType: Leg symmetry: Left + - type: Sprite + state: borg_l_leg + - type: Icon + state: borg_l_leg - type: Tag tags: - Trash - BorgLeg + - BorgLLeg - type: entity - id: BaseBorgLegRight + id: RightLegBorg parent: PartSilicon name: cyborg right leg - abstract: true components: - type: BodyPart partType: Leg symmetry: Right + - type: Sprite + state: borg_r_leg + - type: Icon + state: borg_r_leg - type: Tag tags: - Trash - BorgLeg + - BorgRLeg - type: entity - id: BaseBorgHead + id: LightHeadBorg parent: PartSilicon name: cyborg head - abstract: true components: - type: BodyPart partType: Head + - type: Sprite + state: borg_head + - type: Icon + state: borg_head - type: Tag tags: - Trash - BorgHead - type: entity - id: BaseBorgTorso + id: TorsoBorg parent: PartSilicon name: cyborg torso - abstract: true components: - type: BodyPart partType: Torso + - type: Sprite + state: borg_chest + - type: Icon + state: borg_chest - type: Tag tags: - Trash + - BorgTorso diff --git a/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml b/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml index 0db92ac941d4..9303bd42dd55 100644 --- a/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml +++ b/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml @@ -69,6 +69,9 @@ type: BorgBoundUserInterface enum.StrippingUiKey.Key: type: StrippableBoundUserInterface + # Only used for NT borgs that can switch type, defined here to avoid copy-pasting the rest of this component. + enum.BorgSwitchableTypeUiKey.SelectBorgType: + type: BorgSelectTypeUserInterface - type: ActivatableUI key: enum.BorgUiKey.Key - type: SiliconLawBound @@ -157,6 +160,7 @@ collection: FootstepBorg - type: Construction graph: Cyborg + node: cyborg containers: - part-container - cell_slot @@ -285,6 +289,9 @@ - type: AccessReader access: [["Command"], ["Research"]] - type: ShowJobIcons + - type: InteractionPopup + interactSuccessSound: + path: /Audio/Ambience/Objects/periodic_beep.ogg - type: entity id: BaseBorgChassisSyndicate diff --git a/Resources/Prototypes/Entities/Mobs/Cyborgs/borg_chassis.yml b/Resources/Prototypes/Entities/Mobs/Cyborgs/borg_chassis.yml index 6a8f1e5abb08..fa324c0124fd 100644 --- a/Resources/Prototypes/Entities/Mobs/Cyborgs/borg_chassis.yml +++ b/Resources/Prototypes/Entities/Mobs/Cyborgs/borg_chassis.yml @@ -1,23 +1,22 @@ - type: entity - id: BorgChassisGeneric + id: BorgChassisSelectable parent: BaseBorgChassisNT components: - type: Sprite layers: - state: robot + map: ["enum.BorgVisualLayers.Body", "movement"] - state: robot_e_r map: ["enum.BorgVisualLayers.Light"] shader: unshaded visible: false - state: robot_l shader: unshaded - map: ["light"] + map: ["light","enum.BorgVisualLayers.LightStatus"] visible: false - type: BorgChassis - maxModules: 6 - moduleWhitelist: - tags: - - BorgModuleGeneric + # Default borg can take no modules until selected type. + maxModules: 0 hasMindState: robot_e noMindState: robot_e_r - type: BorgTransponder @@ -25,308 +24,62 @@ sprite: Mobs/Silicon/chassis.rsi state: robot name: cyborg - - type: Construction - node: cyborg - - type: Speech - speechVerb: Robotic - type: InteractionPopup interactSuccessString: petting-success-generic-cyborg interactFailureString: petting-failure-generic-cyborg - interactSuccessSound: - path: /Audio/Ambience/Objects/periodic_beep.ogg + - type: BorgSwitchableType + inherentRadioChannels: + - Common + - Binary + +- type: entity + id: BorgChassisGeneric + parent: BorgChassisSelectable + name: generic cyborg + suffix: type picked + components: + - type: BorgSwitchableType + selectedBorgType: generic - type: entity id: BorgChassisMining - parent: BaseBorgChassisNT + parent: BorgChassisSelectable name: salvage cyborg components: - - type: Sprite - layers: - - state: miner - map: ["movement"] - - state: miner_e_r - map: ["enum.BorgVisualLayers.Light"] - shader: unshaded - visible: false - - state: miner_l - shader: unshaded - map: ["light"] - visible: false - - type: SpriteMovement - movementLayers: - movement: - state: miner_moving - noMovementLayers: - movement: - state: miner - - type: BorgChassis - maxModules: 4 - moduleWhitelist: - tags: - - BorgModuleGeneric - - BorgModuleCargo - hasMindState: miner_e - noMindState: miner_e_r - - type: BorgTransponder - sprite: - sprite: Mobs/Silicon/chassis.rsi - state: miner - name: salvage cyborg - - type: Construction - node: mining - - type: IntrinsicRadioTransmitter - channels: - - Supply - - Binary - - Common - - Science - - type: ActiveRadio - channels: - - Supply - - Binary - - Common - - Science - - type: AccessReader - access: [["Cargo"], ["Salvage"], ["Command"], ["Research"]] - - type: Inventory - templateId: borgTall - - type: InteractionPopup - interactSuccessString: petting-success-salvage-cyborg - interactFailureString: petting-failure-salvage-cyborg - interactSuccessSound: - path: /Audio/Ambience/Objects/periodic_beep.ogg + - type: BorgSwitchableType + selectedBorgType: mining - type: entity id: BorgChassisEngineer - parent: BaseBorgChassisNT + parent: BorgChassisSelectable name: engineer cyborg components: - - type: Sprite - layers: - - state: engineer - - state: engineer_e_r - map: ["enum.BorgVisualLayers.Light"] - shader: unshaded - visible: false - - state: engineer_l - shader: unshaded - map: ["light"] - visible: false - - type: BorgChassis - maxModules: 4 - moduleWhitelist: - tags: - - BorgModuleGeneric - - BorgModuleEngineering - hasMindState: engineer_e - noMindState: engineer_e_r - - type: BorgTransponder - sprite: - sprite: Mobs/Silicon/chassis.rsi - state: engineer - name: engineer cyborg - - type: Construction - node: engineer - - type: IntrinsicRadioTransmitter - channels: - - Engineering - - Binary - - Common - - Science - - type: ActiveRadio - channels: - - Engineering - - Binary - - Common - - Science - - type: AccessReader - access: [["Engineering"], ["Command"], ["Research"]] - - type: Inventory - templateId: borgShort - - type: InteractionPopup - interactSuccessString: petting-success-engineer-cyborg - interactFailureString: petting-failure-engineer-cyborg - interactSuccessSound: - path: /Audio/Ambience/Objects/periodic_beep.ogg + - type: BorgSwitchableType + selectedBorgType: engineering - type: entity id: BorgChassisJanitor - parent: BaseBorgChassisNT + parent: BorgChassisSelectable name: janitor cyborg components: - - type: Sprite - layers: - - state: janitor - map: ["movement"] - - state: janitor_e_r - map: ["enum.BorgVisualLayers.Light"] - shader: unshaded - visible: false - - state: janitor_l - shader: unshaded - map: ["light"] - visible: false - - type: SpriteMovement - movementLayers: - movement: - state: janitor_moving - noMovementLayers: - movement: - state: janitor - - type: BorgChassis - maxModules: 4 - moduleWhitelist: - tags: - - BorgModuleGeneric - - BorgModuleJanitor - hasMindState: janitor_e - noMindState: janitor_e_r - - type: BorgTransponder - sprite: - sprite: Mobs/Silicon/chassis.rsi - state: janitor - name: janitor cyborg - - type: Construction - node: janitor - - type: IntrinsicRadioTransmitter - channels: - - Service - - Binary - - Common - - Science - - type: ActiveRadio - channels: - - Service - - Binary - - Common - - Science - - type: AccessReader - access: [["Service"], ["Command"], ["Research"]] - - type: Inventory - templateId: borgShort - - type: InteractionPopup - interactSuccessString: petting-success-janitor-cyborg - interactFailureString: petting-failure-janitor-cyborg - interactSuccessSound: - path: /Audio/Ambience/Objects/periodic_beep.ogg + - type: BorgSwitchableType + selectedBorgType: janitor - type: entity id: BorgChassisMedical - parent: [BaseBorgChassisNT, ShowMedicalIcons] + parent: BorgChassisSelectable name: medical cyborg components: - - type: Sprite - layers: - - state: medical - map: ["movement"] - - state: medical_e_r - map: ["enum.BorgVisualLayers.Light"] - shader: unshaded - visible: false - - state: medical_l - shader: unshaded - map: ["light"] - visible: false - - type: SpriteMovement - movementLayers: - movement: - state: medical_moving - noMovementLayers: - movement: - state: medical - - type: BorgChassis - maxModules: 4 - moduleWhitelist: - tags: - - BorgModuleGeneric - - BorgModuleMedical - hasMindState: medical_e - noMindState: medical_e_r - - type: BorgTransponder - sprite: - sprite: Mobs/Silicon/chassis.rsi - state: medical - name: medical cyborg - - type: Construction - node: medical - - type: IntrinsicRadioTransmitter - channels: - - Medical - - Binary - - Common - - Science - - type: ActiveRadio - channels: - - Medical - - Binary - - Common - - Science - - type: AccessReader - access: [["Medical"], ["Command"], ["Research"]] - - type: Inventory - templateId: borgDutch - - type: FootstepModifier - footstepSoundCollection: - collection: FootstepHoverBorg - - type: SolutionScanner - - type: InteractionPopup - interactSuccessString: petting-success-medical-cyborg - interactFailureString: petting-failure-medical-cyborg - interactSuccessSound: - path: /Audio/Ambience/Objects/periodic_beep.ogg + - type: BorgSwitchableType + selectedBorgType: medical - type: entity id: BorgChassisService - parent: BaseBorgChassisNT + parent: BorgChassisSelectable name: service cyborg components: - - type: Sprite - layers: - - state: service - - state: service_e_r - map: ["enum.BorgVisualLayers.Light"] - shader: unshaded - visible: false - - state: service_l - shader: unshaded - map: ["light"] - visible: false - - type: BorgChassis - maxModules: 4 - moduleWhitelist: - tags: - - BorgModuleGeneric - - BorgModuleService - hasMindState: service_e - noMindState: service_e_r - - type: BorgTransponder - sprite: - sprite: Mobs/Silicon/chassis.rsi - state: service - name: service cyborg - - type: Construction - node: service - - type: IntrinsicRadioTransmitter - channels: - - Service - - Binary - - Common - - Science - - type: ActiveRadio - channels: - - Service - - Binary - - Common - - Science - - type: AccessReader - access: [["Service"], ["Command"], ["Research"]] - - type: Inventory - templateId: borgTall - - type: InteractionPopup - interactSuccessString: petting-success-service-cyborg - interactFailureString: petting-failure-service-cyborg - interactSuccessSound: - path: /Audio/Ambience/Objects/periodic_beep.ogg + - type: BorgSwitchableType + selectedBorgType: service - type: entity id: BorgChassisSyndicateAssault @@ -354,8 +107,6 @@ - BorgModuleSyndicateAssault hasMindState: synd_sec_e noMindState: synd_sec - - type: Construction - node: syndicateassault - type: InteractionPopup interactSuccessString: petting-success-syndicate-cyborg interactFailureString: petting-failure-syndicate-cyborg @@ -388,8 +139,6 @@ - BorgModuleSyndicate hasMindState: synd_medical_e noMindState: synd_medical - - type: Construction - node: syndicatemedical - type: ShowHealthBars - type: InteractionPopup interactSuccessString: petting-success-syndicate-cyborg @@ -429,8 +178,6 @@ - BorgModuleSyndicate hasMindState: synd_engi_e noMindState: synd_engi - - type: Construction - node: syndicatesaboteur - type: ShowHealthBars damageContainers: - Inorganic diff --git a/Resources/Prototypes/Entities/Mobs/Player/silicon.yml b/Resources/Prototypes/Entities/Mobs/Player/silicon.yml index e787ef59f00a..bcac46ed842a 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/silicon.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/silicon.yml @@ -429,28 +429,9 @@ map: ["base"] # Borgs -- type: entity - id: PlayerBorgGeneric - parent: BorgChassisGeneric - suffix: Battery, Tools - components: - - type: ContainerFill - containers: - borg_brain: - - PositronicBrain - borg_module: - - BorgModuleTool - - type: ItemSlots - slots: - cell_slot: - name: power-cell-slot-component-slot-name-default - startingItem: PowerCellMedium - - type: RandomMetadata - nameSegments: [names_borg] - - type: entity id: PlayerBorgBattery - parent: BorgChassisGeneric + parent: BorgChassisSelectable suffix: Battery components: - type: ContainerFill diff --git a/Resources/Prototypes/Entities/Objects/Specific/Robotics/borg_parts.yml b/Resources/Prototypes/Entities/Objects/Specific/Robotics/borg_parts.yml deleted file mode 100644 index 6df0488e28fe..000000000000 --- a/Resources/Prototypes/Entities/Objects/Specific/Robotics/borg_parts.yml +++ /dev/null @@ -1,503 +0,0 @@ -# generic parts -- type: entity - id: LeftArmBorg - parent: BaseBorgArmLeft - components: - - type: Sprite - state: borg_l_arm - - type: Icon - state: borg_l_arm - - type: Tag - tags: - - Trash - - BorgArm - - BorgGenericLArm - -- type: entity - id: RightArmBorg - parent: BaseBorgArmRight - components: - - type: Sprite - state: borg_r_arm - - type: Icon - state: borg_r_arm - - type: Tag - tags: - - Trash - - BorgArm - - BorgGenericRArm - -- type: entity - id: LeftLegBorg - parent: BaseBorgLegLeft - components: - - type: Sprite - state: borg_l_leg - - type: Icon - state: borg_l_leg - - type: Tag - tags: - - Trash - - BorgLeg - - BorgGenericLLeg - -- type: entity - id: RightLegBorg - parent: BaseBorgLegRight - components: - - type: Sprite - state: borg_r_leg - - type: Icon - state: borg_r_leg - - type: Tag - tags: - - Trash - - BorgLeg - - BorgGenericRLeg - -- type: entity - id: LightHeadBorg - parent: BaseBorgHead - components: - - type: Sprite - state: borg_head - - type: Icon - state: borg_head - - type: Tag - tags: - - Trash - - BorgHead - - BorgGenericHead - -- type: entity - id: TorsoBorg - parent: BaseBorgTorso - components: - - type: Sprite - state: borg_chest - - type: Icon - state: borg_chest - - type: Tag - tags: - - Trash - - BorgGenericTorso - -# engineer parts -- type: entity - id: LeftArmBorgEngineer - parent: BaseBorgArmLeft - name: engineer cyborg left arm - components: - - type: Sprite - state: engineer_l_arm - - type: Icon - state: engineer_l_arm - - type: Tag - tags: - - Trash - - BorgArm - - BorgEngineerLArm - -- type: entity - id: RightArmBorgEngineer - parent: BaseBorgArmRight - name: engineer cyborg right arm - components: - - type: Sprite - state: engineer_r_arm - - type: Icon - state: engineer_r_arm - - type: Tag - tags: - - Trash - - BorgArm - - BorgEngineerRArm - -- type: entity - id: LeftLegBorgEngineer - parent: BaseBorgLegLeft - name: engineer cyborg left leg - components: - - type: Sprite - state: engineer_l_leg - - type: Icon - state: engineer_l_leg - - type: Tag - tags: - - Trash - - BorgLeg - - BorgEngineerLLeg - -- type: entity - id: RightLegBorgEngineer - parent: BaseBorgLegRight - name: engineer cyborg right leg - components: - - type: Sprite - state: engineer_r_leg - - type: Icon - state: engineer_r_leg - - type: Tag - tags: - - Trash - - BorgLeg - - BorgEngineerRLeg - -- type: entity - id: HeadBorgEngineer - parent: BaseBorgHead - name: engineer cyborg head - components: - - type: Sprite - state: engineer_head - - type: Icon - state: engineer_head - - type: Tag - tags: - - Trash - - BorgHead - - BorgEngineerHead - -- type: entity - id: TorsoBorgEngineer - parent: BaseBorgTorso - name: engineer cyborg torso - components: - - type: Sprite - state: engineer_chest - - type: Icon - state: engineer_chest - - type: Tag - tags: - - Trash - - BorgEngineerTorso - -# janitor parts -- type: entity - id: LeftLegBorgJanitor - parent: BaseBorgLegLeft - name: janitor cyborg left leg - components: - - type: Sprite - state: janitor_l_leg - - type: Icon - state: janitor_l_leg - - type: Tag - tags: - - Trash - - BorgLeg - - BorgJanitorLLeg - -- type: entity - id: RightLegBorgJanitor - parent: BaseBorgLegRight - name: janitor cyborg right leg - components: - - type: Sprite - state: janitor_r_leg - - type: Icon - state: janitor_r_leg - - type: Tag - tags: - - Trash - - BorgLeg - - BorgJanitorRLeg - -- type: entity - id: HeadBorgJanitor - parent: BaseBorgHead - name: janitor cyborg head - components: - - type: Sprite - state: janitor_head - - type: Icon - state: janitor_head - - type: Tag - tags: - - Trash - - BorgHead - - BorgJanitorHead - -- type: entity - id: TorsoBorgJanitor - parent: BaseBorgTorso - name: janitor cyborg torso - components: - - type: Sprite - state: janitor_chest - - type: Icon - state: janitor_chest - - type: Tag - tags: - - Trash - - BorgJanitorTorso - -# medical parts -- type: entity - id: LeftArmBorgMedical - parent: BaseBorgArmLeft - name: medical cyborg left arm - components: - - type: Sprite - state: medical_l_arm - - type: Icon - state: medical_l_arm - - type: Tag - tags: - - Trash - - BorgArm - - BorgMedicalLArm - -- type: entity - id: RightArmBorgMedical - parent: BaseBorgArmRight - name: medical cyborg right arm - components: - - type: Sprite - state: medical_r_arm - - type: Icon - state: medical_r_arm - - type: Tag - tags: - - Trash - - BorgArm - - BorgMedicalRArm - -- type: entity - id: LeftLegBorgMedical - parent: BaseBorgLegLeft - name: medical cyborg left leg - components: - - type: Sprite - state: medical_l_leg - - type: Icon - state: medical_l_leg - - type: Tag - tags: - - Trash - - BorgLeg - - BorgMedicalLLeg - -- type: entity - id: RightLegBorgMedical - parent: BaseBorgLegRight - name: medical cyborg right leg - components: - - type: Sprite - state: medical_r_leg - - type: Icon - state: medical_r_leg - - type: Tag - tags: - - Trash - - BorgLeg - - BorgMedicalRLeg - -- type: entity - id: HeadBorgMedical - parent: BaseBorgHead - name: medical cyborg head - components: - - type: Sprite - state: medical_head - - type: Icon - state: medical_head - - type: Tag - tags: - - Trash - - BorgHead - - BorgMedicalHead - -- type: entity - id: TorsoBorgMedical - parent: BaseBorgTorso - name: medical cyborg torso - components: - - type: Sprite - state: medical_chest - - type: Icon - state: medical_chest - - type: Tag - tags: - - Trash - - BorgMedicalTorso - -# mining parts -- type: entity - id: LeftArmBorgMining - parent: BaseBorgArmLeft - name: mining cyborg left arm - components: - - type: Sprite - state: mining_l_arm - - type: Icon - state: mining_l_arm - - type: Tag - tags: - - Trash - - BorgArm - - BorgMiningLArm - -- type: entity - id: RightArmBorgMining - parent: BaseBorgArmRight - name: mining cyborg right arm - components: - - type: Sprite - state: mining_r_arm - - type: Icon - state: mining_r_arm - - type: Tag - tags: - - Trash - - BorgArm - - BorgMiningRArm - -- type: entity - id: LeftLegBorgMining - parent: BaseBorgLegLeft - name: mining cyborg left leg - components: - - type: Sprite - state: mining_l_leg - - type: Icon - state: mining_l_leg - - type: Tag - tags: - - Trash - - BorgLeg - - BorgMiningLLeg - -- type: entity - id: RightLegBorgMining - parent: BaseBorgLegRight - name: mining cyborg right leg - components: - - type: Sprite - state: mining_r_leg - - type: Icon - state: mining_r_leg - - type: Tag - tags: - - Trash - - BorgLeg - - BorgMiningRLeg - -- type: entity - id: HeadBorgMining - parent: BaseBorgHead - name: mining cyborg head - components: - - type: Sprite - state: mining_head - - type: Icon - state: mining_head - - type: Tag - tags: - - Trash - - BorgHead - - BorgMiningHead - -- type: entity - id: TorsoBorgMining - parent: BaseBorgTorso - name: mining cyborg torso - components: - - type: Sprite - state: mining_chest - - type: Icon - state: mining_chest - - type: Tag - tags: - - Trash - - BorgMiningTorso - -# service parts -- type: entity - id: LeftArmBorgService - parent: BaseBorgArmLeft - name: service cyborg left arm - components: - - type: Sprite - state: service_l_arm - - type: Icon - state: service_l_arm - - type: Tag - tags: - - Trash - - BorgArm - - BorgServiceLArm - -- type: entity - id: RightArmBorgService - parent: BaseBorgArmRight - name: service cyborg right arm - components: - - type: Sprite - state: service_r_arm - - type: Icon - state: service_r_arm - - type: Tag - tags: - - Trash - - BorgArm - - BorgServiceRArm - -- type: entity - id: LeftLegBorgService - parent: BaseBorgLegLeft - name: service cyborg left leg - components: - - type: Sprite - state: service_l_leg - - type: Icon - state: service_l_leg - - type: Tag - tags: - - Trash - - BorgLeg - - BorgServiceLLeg - -- type: entity - id: RightLegBorgService - parent: BaseBorgLegRight - name: service cyborg right leg - components: - - type: Sprite - state: service_r_leg - - type: Icon - state: service_r_leg - - type: Tag - tags: - - Trash - - BorgLeg - - BorgServiceRLeg - -- type: entity - id: HeadBorgService - parent: BaseBorgHead - name: service cyborg head - components: - - type: Sprite - state: service_head - - type: Icon - state: service_head - - type: Tag - tags: - - Trash - - BorgHead - - BorgServiceHead - -- type: entity - id: TorsoBorgService - parent: BaseBorgTorso - name: service cyborg torso - components: - - type: Sprite - state: service_chest - - type: Icon - state: service_chest - - type: Tag - tags: - - Trash - - BorgServiceTorso diff --git a/Resources/Prototypes/Entities/Objects/Specific/Robotics/endoskeleton.yml b/Resources/Prototypes/Entities/Objects/Specific/Robotics/endoskeleton.yml index 9261e06ea2a7..6afc06a79675 100644 --- a/Resources/Prototypes/Entities/Objects/Specific/Robotics/endoskeleton.yml +++ b/Resources/Prototypes/Entities/Objects/Specific/Robotics/endoskeleton.yml @@ -33,139 +33,27 @@ borg_l_arm+o: whitelist: tags: - - BorgGenericLArm + - BorgLArm borg_r_arm+o: whitelist: tags: - - BorgGenericRArm + - BorgRArm borg_l_leg+o: whitelist: tags: - - BorgGenericLLeg + - BorgLLeg borg_r_leg+o: whitelist: tags: - - BorgGenericRLeg + - BorgRLeg borg_head+o: whitelist: tags: - - BorgGenericHead + - BorgHead borg_chest+o: whitelist: tags: - - BorgGenericTorso - service_l_arm+o: - whitelist: - tags: - - BorgServiceLArm - service_r_arm+o: - whitelist: - tags: - - BorgServiceRArm - service_l_leg+o: - whitelist: - tags: - - BorgServiceLLeg - service_r_leg+o: - whitelist: - tags: - - BorgServiceRLeg - service_head+o: - whitelist: - tags: - - BorgServiceHead - service_chest+o: - whitelist: - tags: - - BorgServiceTorso - engineer_l_arm+o: - whitelist: - tags: - - BorgEngineerLArm - engineer_r_arm+o: - whitelist: - tags: - - BorgEngineerRArm - engineer_l_leg+o: - whitelist: - tags: - - BorgEngineerLLeg - engineer_r_leg+o: - whitelist: - tags: - - BorgEngineerRLeg - engineer_head+o: - whitelist: - tags: - - BorgEngineerHead - engineer_chest+o: - whitelist: - tags: - - BorgEngineerTorso - mining_l_arm+o: - whitelist: - tags: - - BorgMiningLArm - mining_r_arm+o: - whitelist: - tags: - - BorgMiningRArm - mining_l_leg+o: - whitelist: - tags: - - BorgMiningLLeg - mining_r_leg+o: - whitelist: - tags: - - BorgMiningRLeg - mining_head+o: - whitelist: - tags: - - BorgMiningHead - mining_chest+o: - whitelist: - tags: - - BorgMiningTorso - medical_l_arm+o: - whitelist: - tags: - - BorgMedicalLArm - medical_r_arm+o: - whitelist: - tags: - - BorgMedicalRArm - medical_l_leg+o: - whitelist: - tags: - - BorgMedicalLLeg - medical_r_leg+o: - whitelist: - tags: - - BorgMedicalRLeg - medical_head+o: - whitelist: - tags: - - BorgMedicalHead - medical_chest+o: - whitelist: - tags: - - BorgMedicalTorso - janitor_l_leg+o: - whitelist: - tags: - - BorgJanitorLLeg - janitor_r_leg+o: - whitelist: - tags: - - BorgJanitorRLeg - janitor_head+o: - whitelist: - tags: - - BorgJanitorHead - janitor_chest+o: - whitelist: - tags: - - BorgJanitorTorso + - BorgTorso - type: ContainerContainer containers: part-container: !type:Container @@ -173,45 +61,12 @@ - type: PartAssembly parts: generic: - - BorgGenericLArm - - BorgGenericRArm - - BorgGenericLLeg - - BorgGenericRLeg - - BorgGenericHead - - BorgGenericTorso - service: - - BorgServiceLArm - - BorgServiceRArm - - BorgServiceLLeg - - BorgServiceRLeg - - BorgServiceHead - - BorgServiceTorso - engineer: - - BorgEngineerLArm - - BorgEngineerRArm - - BorgEngineerLLeg - - BorgEngineerRLeg - - BorgEngineerHead - - BorgEngineerTorso - medical: - - BorgMedicalLArm - - BorgMedicalRArm - - BorgMedicalLLeg - - BorgMedicalRLeg - - BorgMedicalHead - - BorgMedicalTorso - janitor: - - BorgJanitorLLeg - - BorgJanitorRLeg - - BorgJanitorHead - - BorgJanitorTorso - mining: - - BorgMiningLArm - - BorgMiningRArm - - BorgMiningLLeg - - BorgMiningRLeg - - BorgMiningHead - - BorgMiningTorso + - BorgLArm + - BorgRArm + - BorgLLeg + - BorgRLeg + - BorgHead + - BorgTorso - type: Construction graph: Cyborg node: start diff --git a/Resources/Prototypes/Entities/Structures/Machines/lathe.yml b/Resources/Prototypes/Entities/Structures/Machines/lathe.yml index 020566ad1a73..6a94891d127b 100644 --- a/Resources/Prototypes/Entities/Structures/Machines/lathe.yml +++ b/Resources/Prototypes/Entities/Structures/Machines/lathe.yml @@ -572,11 +572,6 @@ - BorgModuleFireExtinguisher - BorgModuleRadiationDetection - BorgModuleTool - - BorgModuleAppraisal - - BorgModuleConstruction - - BorgModuleService - - BorgModuleTreatment - - BorgModuleCleaning - CyborgEndoskeleton - LeftArmBorg - RightArmBorg @@ -584,50 +579,15 @@ - RightLegBorg - LightHeadBorg - TorsoBorg - - LeftArmBorgEngineer - - RightArmBorgEngineer - - LeftLegBorgEngineer - - RightLegBorgEngineer - - HeadBorgEngineer - - TorsoBorgEngineer - - LeftLegBorgJanitor - - RightLegBorgJanitor - - HeadBorgJanitor - - TorsoBorgJanitor - - LeftArmBorgMedical - - RightArmBorgMedical - - LeftLegBorgMedical - - RightLegBorgMedical - - HeadBorgMedical - - TorsoBorgMedical - - LeftArmBorgMining - - RightArmBorgMining - - LeftLegBorgMining - - RightLegBorgMining - - HeadBorgMining - - TorsoBorgMining - - LeftArmBorgService - - RightArmBorgService - - LeftLegBorgService - - RightLegBorgService - - HeadBorgService - - TorsoBorgService dynamicRecipes: - ProximitySensor - - BorgModuleLightReplacer - BorgModuleAdvancedCleaning - - BorgModuleMining - - BorgModuleGrapplingGun - BorgModuleAdvancedTool - BorgModuleGPS - - BorgModuleRCD - BorgModuleArtifact - BorgModuleAnomaly - BorgModuleGardening - BorgModuleHarvesting - - BorgModuleMusique - - BorgModuleClowning - - BorgModuleDiagnosis - BorgModuleDefibrillator - BorgModuleAdvancedTreatment - RipleyHarness diff --git a/Resources/Prototypes/InventoryTemplates/borg.yml b/Resources/Prototypes/InventoryTemplates/borg.yml index d43519f61cf4..3d3ef29eb037 100644 --- a/Resources/Prototypes/InventoryTemplates/borg.yml +++ b/Resources/Prototypes/InventoryTemplates/borg.yml @@ -26,8 +26,7 @@ - name: head slotTexture: head slotFlags: HEAD - slotGroup: MainHotbar - uiWindowPos: 0,0 + uiWindowPos: 1,0 strippingWindowPos: 0,0 displayName: Head offset: 0.015625, 0 diff --git a/Resources/Prototypes/Recipes/Construction/Graphs/machines/cyborg.yml b/Resources/Prototypes/Recipes/Construction/Graphs/machines/cyborg.yml index 0f012cefc98e..4ebc43667c5e 100644 --- a/Resources/Prototypes/Recipes/Construction/Graphs/machines/cyborg.yml +++ b/Resources/Prototypes/Recipes/Construction/Graphs/machines/cyborg.yml @@ -5,18 +5,6 @@ - node: start entity: CyborgEndoskeleton edges: - - # empty the parts via prying - - to: start - conditions: - - !type:ContainerNotEmpty - container: part-container - steps: - - tool: Prying - doAfter: 0.5 - completed: - - !type:EmptyAllContainers - - to: cyborg steps: - assemblyId: generic @@ -43,165 +31,6 @@ - tool: Screwing doAfter: 0.5 - - - to: engineer - steps: - - assemblyId: engineer - guideString: borg-construction-guide-string - - - material: Cable - amount: 1 - doAfter: 1 - store: part-container - - - component: Flash - name: flash - store: part-container - icon: - sprite: Objects/Weapons/Melee/flash.rsi - state: flash - - - component: Flash - name: second flash - store: part-container - icon: - sprite: Objects/Weapons/Melee/flash.rsi - state: flash - - - tool: Screwing - doAfter: 0.5 - - - to: janitor - steps: - - assemblyId: janitor - guideString: borg-construction-guide-string - - - material: Cable - amount: 1 - doAfter: 1 - store: part-container - - - component: Flash - name: flash - store: part-container - icon: - sprite: Objects/Weapons/Melee/flash.rsi - state: flash - - - component: Flash - name: second flash - store: part-container - icon: - sprite: Objects/Weapons/Melee/flash.rsi - state: flash - - - tool: Screwing - doAfter: 0.5 - - - to: medical - steps: - - assemblyId: medical - guideString: borg-construction-guide-string - - - material: Cable - amount: 1 - doAfter: 1 - store: part-container - - - component: Flash - name: flash - store: part-container - icon: - sprite: Objects/Weapons/Melee/flash.rsi - state: flash - - - component: Flash - name: second flash - store: part-container - icon: - sprite: Objects/Weapons/Melee/flash.rsi - state: flash - - - tool: Screwing - doAfter: 0.5 - - - to: mining - steps: - - assemblyId: mining - guideString: borg-construction-guide-string - - - material: Cable - amount: 1 - doAfter: 1 - store: part-container - - - component: Flash - name: flash - store: part-container - icon: - sprite: Objects/Weapons/Melee/flash.rsi - state: flash - - - component: Flash - name: second flash - store: part-container - icon: - sprite: Objects/Weapons/Melee/flash.rsi - state: flash - - - tool: Screwing - doAfter: 0.5 - - - to: service - steps: - - assemblyId: service - guideString: borg-construction-guide-string - - - material: Cable - amount: 1 - doAfter: 1 - store: part-container - - - component: Flash - name: flash - store: part-container - icon: - sprite: Objects/Weapons/Melee/flash.rsi - state: flash - - - component: Flash - name: second flash - store: part-container - icon: - sprite: Objects/Weapons/Melee/flash.rsi - state: flash - - - tool: Screwing - doAfter: 0.5 - node: cyborg - entity: BorgChassisGeneric - - - node: engineer - entity: BorgChassisEngineer - - - node: janitor - entity: BorgChassisJanitor - - - node: mining - entity: BorgChassisMining - - - node: medical - entity: BorgChassisMedical - - - node: service - entity: BorgChassisService - - - node: syndicateassault - entity: BorgChassisSyndicateAssault - - - node: syndicatemedical - entity: BorgChassisSyndicateMedical - - - node: syndicatesaboteur - entity: BorgChassisSyndicateSaboteur + entity: BorgChassisSelectable diff --git a/Resources/Prototypes/Recipes/Lathes/robotics.yml b/Resources/Prototypes/Recipes/Lathes/robotics.yml index bf8deba9840e..a4413e01ebee 100644 --- a/Resources/Prototypes/Recipes/Lathes/robotics.yml +++ b/Resources/Prototypes/Recipes/Lathes/robotics.yml @@ -61,8 +61,6 @@ materials: Steel: 1500 -# Generic - - type: latheRecipe parent: BaseBorgLimbRecipe id: LeftArmBorg @@ -93,162 +91,6 @@ id: TorsoBorg result: TorsoBorg -# Engineer - -- type: latheRecipe - parent: BaseBorgLimbRecipe - id: LeftArmBorgEngineer - result: LeftArmBorgEngineer - -- type: latheRecipe - parent: BaseBorgLimbRecipe - id: RightArmBorgEngineer - result: RightArmBorgEngineer - -- type: latheRecipe - parent: BaseBorgLimbRecipe - id: LeftLegBorgEngineer - result: LeftLegBorgEngineer - -- type: latheRecipe - parent: BaseBorgLimbRecipe - id: RightLegBorgEngineer - result: RightLegBorgEngineer - -- type: latheRecipe - parent: BaseBorgLimbRecipe - id: HeadBorgEngineer - result: HeadBorgEngineer - -- type: latheRecipe - parent: BaseBorgLimbRecipe - id: TorsoBorgEngineer - result: TorsoBorgEngineer - -# Medical - -- type: latheRecipe - parent: BaseBorgLimbRecipe - id: LeftArmBorgMedical - result: LeftArmBorgMedical - -- type: latheRecipe - parent: BaseBorgLimbRecipe - id: RightArmBorgMedical - result: RightArmBorgMedical - -- type: latheRecipe - parent: BaseBorgLimbRecipe - id: LeftLegBorgMedical - result: LeftLegBorgMedical - -- type: latheRecipe - parent: BaseBorgLimbRecipe - id: RightLegBorgMedical - result: RightLegBorgMedical - -- type: latheRecipe - parent: BaseBorgLimbRecipe - id: HeadBorgMedical - result: HeadBorgMedical - -- type: latheRecipe - parent: BaseBorgLimbRecipe - id: TorsoBorgMedical - result: TorsoBorgMedical - -# Mining - -- type: latheRecipe - parent: BaseBorgLimbRecipe - id: LeftArmBorgMining - result: LeftArmBorgMining - -- type: latheRecipe - parent: BaseBorgLimbRecipe - id: RightArmBorgMining - result: RightArmBorgMining - -- type: latheRecipe - parent: BaseBorgLimbRecipe - id: LeftLegBorgMining - result: LeftLegBorgMining - -- type: latheRecipe - parent: BaseBorgLimbRecipe - id: RightLegBorgMining - result: RightLegBorgMining - -- type: latheRecipe - parent: BaseBorgLimbRecipe - id: HeadBorgMining - result: HeadBorgMining - -- type: latheRecipe - parent: BaseBorgLimbRecipe - id: TorsoBorgMining - result: TorsoBorgMining - -# Service - -- type: latheRecipe - parent: BaseBorgLimbRecipe - id: LeftArmBorgService - result: LeftArmBorgService - -- type: latheRecipe - parent: BaseBorgLimbRecipe - id: RightArmBorgService - result: RightArmBorgService - -- type: latheRecipe - parent: BaseBorgLimbRecipe - id: LeftLegBorgService - result: LeftLegBorgService - -- type: latheRecipe - parent: BaseBorgLimbRecipe - id: RightLegBorgService - result: RightLegBorgService - -- type: latheRecipe - parent: BaseBorgLimbRecipe - id: HeadBorgService - result: HeadBorgService - -- type: latheRecipe - parent: BaseBorgLimbRecipe - id: TorsoBorgService - result: TorsoBorgService - -# Janitor - -- type: latheRecipe - parent: BaseBorgLimbRecipe - id: LeftLegBorgJanitor - result: LeftLegBorgJanitor - -- type: latheRecipe - parent: BaseBorgLimbRecipe - id: RightLegBorgJanitor - result: RightLegBorgJanitor - -- type: latheRecipe - parent: BaseBorgLimbRecipe - id: HeadBorgJanitor - result: HeadBorgJanitor - materials: - Steel: 500 - Glass: 200 - -- type: latheRecipe - parent: BaseBorgLimbRecipe - id: TorsoBorgJanitor - result: TorsoBorgJanitor - materials: - Steel: 500 - Glass: 200 - # Parts - type: latheRecipe @@ -304,23 +146,6 @@ id: BorgModuleTool result: BorgModuleTool -# Mining Modules - -- type: latheRecipe - parent: BaseBorgModuleRecipe - id: BorgModuleAppraisal - result: BorgModuleAppraisal - -- type: latheRecipe - parent: BaseBorgModuleRecipe - id: BorgModuleMining - result: BorgModuleMining - -- type: latheRecipe - parent: BaseGoldBorgModuleRecipe - id: BorgModuleGrapplingGun - result: BorgModuleGrapplingGun - # Engineering Modules - type: latheRecipe @@ -328,28 +153,8 @@ id: BorgModuleAdvancedTool result: BorgModuleAdvancedTool -- type: latheRecipe - parent: BaseBorgModuleRecipe - id: BorgModuleConstruction - result: BorgModuleConstruction - -- type: latheRecipe - parent: BaseGoldBorgModuleRecipe - id: BorgModuleRCD - result: BorgModuleRCD - # Janitor Modules -- type: latheRecipe - parent: BaseBorgModuleRecipe - id: BorgModuleLightReplacer - result: BorgModuleLightReplacer - -- type: latheRecipe - parent: BaseBorgModuleRecipe - id: BorgModuleCleaning - result: BorgModuleCleaning - - type: latheRecipe parent: BaseGoldBorgModuleRecipe id: BorgModuleAdvancedCleaning @@ -357,16 +162,6 @@ # Medical Modules -- type: latheRecipe - parent: BaseBorgModuleRecipe - id: BorgModuleDiagnosis - result: BorgModuleDiagnosis - -- type: latheRecipe - parent: BaseBorgModuleRecipe - id: BorgModuleTreatment - result: BorgModuleTreatment - - type: latheRecipe parent: BaseGoldBorgModuleRecipe id: BorgModuleAdvancedTreatment @@ -391,16 +186,6 @@ # Service Modules -- type: latheRecipe - parent: BaseBorgModuleRecipe - id: BorgModuleService - result: BorgModuleService - -- type: latheRecipe - parent: BaseBorgModuleRecipe - id: BorgModuleMusique - result: BorgModuleMusique - - type: latheRecipe parent: BaseBorgModuleRecipe id: BorgModuleGardening @@ -410,8 +195,3 @@ parent: BaseBorgModuleRecipe id: BorgModuleHarvesting result: BorgModuleHarvesting - -- type: latheRecipe - parent: BaseBorgModuleRecipe - id: BorgModuleClowning - result: BorgModuleClowning diff --git a/Resources/Prototypes/Research/civilianservices.yml b/Resources/Prototypes/Research/civilianservices.yml index b990eb6ae40c..9430c391a992 100644 --- a/Resources/Prototypes/Research/civilianservices.yml +++ b/Resources/Prototypes/Research/civilianservices.yml @@ -66,8 +66,6 @@ recipeUnlocks: - ComputerTelevisionCircuitboard - SynthesizerInstrument - - BorgModuleMusique - - BorgModuleClowning - DawInstrumentMachineCircuitboard - MassMediaCircuitboard - JukeboxCircuitBoard @@ -82,7 +80,6 @@ tier: 1 cost: 5000 recipeUnlocks: - - BorgModuleLightReplacer - BorgModuleAdvancedCleaning - type: technology diff --git a/Resources/Prototypes/Research/industrial.yml b/Resources/Prototypes/Research/industrial.yml index e65c734ffdab..817e50834b70 100644 --- a/Resources/Prototypes/Research/industrial.yml +++ b/Resources/Prototypes/Research/industrial.yml @@ -12,8 +12,6 @@ recipeUnlocks: - MiningDrill - MineralScannerEmpty - - BorgModuleMining - - BorgModuleGrapplingGun - OreProcessorIndustrialMachineCircuitboard - ClothingMaskWeldingGas @@ -168,7 +166,6 @@ - PowerDrill - JawsOfLife - BorgModuleAdvancedTool - - BorgModuleRCD - type: technology id: MassExcavation diff --git a/Resources/Prototypes/Roles/Jobs/Science/borg.yml b/Resources/Prototypes/Roles/Jobs/Science/borg.yml index 4cbede17ca2d..c62482d286ee 100644 --- a/Resources/Prototypes/Roles/Jobs/Science/borg.yml +++ b/Resources/Prototypes/Roles/Jobs/Science/borg.yml @@ -25,5 +25,5 @@ canBeAntag: false icon: JobIconBorg supervisors: job-supervisors-rd - jobEntity: PlayerBorgGeneric + jobEntity: PlayerBorgBattery applyTraits: false diff --git a/Resources/Prototypes/borg_types.yml b/Resources/Prototypes/borg_types.yml new file mode 100644 index 000000000000..f6294be68e35 --- /dev/null +++ b/Resources/Prototypes/borg_types.yml @@ -0,0 +1,218 @@ +# Generic borg +- type: borgType + id: generic + + # Description + dummyPrototype: BorgChassisGeneric + + # Functional + extraModuleCount: 5 + moduleWhitelist: + tags: + - BorgModuleGeneric + + defaultModules: + - BorgModuleTool + + radioChannels: + - Science + + # Visual + inventoryTemplateId: borgShort + spriteBodyState: robot + spriteHasMindState: robot_e + spriteNoMindState: robot_e_r + spriteToggleLightState: robot_l + + # Pet + petSuccessString: petting-success-generic-cyborg + petFailureString: petting-failure-generic-cyborg + + +# Engineering borg +- type: borgType + id: engineering + + # Description + dummyPrototype: BorgChassisEngineer + + # Functional + extraModuleCount: 3 + moduleWhitelist: + tags: + - BorgModuleGeneric + - BorgModuleEngineering + + defaultModules: + - BorgModuleTool + - BorgModuleConstruction + - BorgModuleRCD + - BorgModuleCable + + radioChannels: + - Engineering + - Science + + # Visual + inventoryTemplateId: borgShort + spriteBodyState: engineer + spriteHasMindState: engineer_e + spriteNoMindState: engineer_e_r + spriteToggleLightState: engineer_l + + # Pet + petSuccessString: petting-success-engineer-cyborg + petFailureString: petting-failure-engineer-cyborg + + +# Salvage borg +- type: borgType + id: mining + + # Description + dummyPrototype: BorgChassisMining + + # Functional + extraModuleCount: 3 + moduleWhitelist: + tags: + - BorgModuleGeneric + - BorgModuleCargo + + defaultModules: + - BorgModuleGrapplingGun + - BorgModuleMining + - BorgModuleAppraisal + + radioChannels: + - Supply + - Science + + # Visual + inventoryTemplateId: borgTall + spriteBodyState: miner + spriteBodyMovementState: miner_moving + spriteHasMindState: miner_e + spriteNoMindState: miner_e_r + spriteToggleLightState: miner_l + + # Pet + petSuccessString: petting-success-salvage-cyborg + petFailureString: petting-failure-salvage-cyborg + + +# Janitor borg +- type: borgType + id: janitor + + # Description + dummyPrototype: BorgChassisJanitor + + # Functional + extraModuleCount: 3 + moduleWhitelist: + tags: + - BorgModuleGeneric + - BorgModuleJanitor + + defaultModules: + - BorgModuleLightReplacer + - BorgModuleCleaning + + radioChannels: + - Science + - Service + + # Visual + inventoryTemplateId: borgShort + spriteBodyState: janitor + spriteBodyMovementState: janitor_moving + spriteHasMindState: janitor_e + spriteNoMindState: janitor_e_r + spriteToggleLightState: janitor_l + + # Pet + petSuccessString: petting-success-janitor-cyborg + petFailureString: petting-failure-janitor-cyborg + + +# Medical borg +- type: borgType + id: medical + + # Description + dummyPrototype: BorgChassisMedical + + # Functional + extraModuleCount: 3 + moduleWhitelist: + tags: + - BorgModuleGeneric + - BorgModuleMedical + + defaultModules: + - BorgModuleTreatment + + radioChannels: + - Science + - Medical + + addComponents: + - type: SolutionScanner + - type: ShowHealthBars + damageContainers: + - Biological + - type: ShowHealthIcons + damageContainers: + - Biological + + # Visual + inventoryTemplateId: borgDutch + spriteBodyState: medical + spriteBodyMovementState: medical_moving + spriteHasMindState: medical_e + spriteNoMindState: medical_e_r + spriteToggleLightState: medical_l + + # Pet + petSuccessString: petting-success-medical-cyborg + petFailureString: petting-failure-medical-cyborg + + # Sounds + footstepCollection: + collection: FootstepHoverBorg + + +# Service borg +- type: borgType + id: service + + # Description + dummyPrototype: BorgChassisService + + # Functional + extraModuleCount: 3 + moduleWhitelist: + tags: + - BorgModuleGeneric + - BorgModuleService + + defaultModules: + - BorgModuleMusique + - BorgModuleService + - BorgModuleClowning + + radioChannels: + - Science + - Service + + # Visual + inventoryTemplateId: borgTall + spriteBodyState: service + spriteHasMindState: service_e + spriteNoMindState: service_e_r + spriteToggleLightState: service_l + + # Pet + petSuccessString: petting-success-service-cyborg + petFailureString: petting-failure-service-cyborg diff --git a/Resources/Prototypes/tags.yml b/Resources/Prototypes/tags.yml index be9c90ce93d8..6112f93c1648 100644 --- a/Resources/Prototypes/tags.yml +++ b/Resources/Prototypes/tags.yml @@ -75,95 +75,26 @@ - type: Tag id: BorgArm -- type: Tag - id: BorgEngineerHead - -- type: Tag - id: BorgEngineerLArm - -- type: Tag - id: BorgEngineerLLeg - -- type: Tag - id: BorgEngineerRArm - -- type: Tag - id: BorgEngineerRLeg - -- type: Tag - id: BorgEngineerTorso - -- type: Tag - id: BorgGenericHead - -- type: Tag - id: BorgGenericLArm - -- type: Tag - id: BorgGenericLLeg - -- type: Tag - id: BorgGenericRArm - -- type: Tag - id: BorgGenericRLeg - -- type: Tag - id: BorgGenericTorso - - type: Tag id: BorgHead - type: Tag - id: BorgJanitorHead - -- type: Tag - id: BorgJanitorLLeg - -- type: Tag - id: BorgJanitorRLeg - -- type: Tag - id: BorgJanitorTorso + id: BorgLArm - type: Tag - id: BorgLeg - -- type: Tag - id: BorgMedicalHead - -- type: Tag - id: BorgMedicalLArm - -- type: Tag - id: BorgMedicalLLeg - -- type: Tag - id: BorgMedicalRArm - -- type: Tag - id: BorgMedicalRLeg - -- type: Tag - id: BorgMedicalTorso - -- type: Tag - id: BorgMiningHead + id: BorgLLeg - type: Tag - id: BorgMiningLArm + id: BorgRArm - type: Tag - id: BorgMiningLLeg + id: BorgRLeg - type: Tag - id: BorgMiningRArm + id: BorgTorso - type: Tag - id: BorgMiningRLeg - -- type: Tag - id: BorgMiningTorso + id: BorgLeg - type: Tag id: BorgModuleCargo @@ -189,24 +120,6 @@ - type: Tag id: BorgModuleSyndicateAssault -- type: Tag - id: BorgServiceHead - -- type: Tag - id: BorgServiceLArm - -- type: Tag - id: BorgServiceLLeg - -- type: Tag - id: BorgServiceRArm - -- type: Tag - id: BorgServiceRLeg - -- type: Tag - id: BorgServiceTorso - - type: Tag id: Bot diff --git a/Resources/ServerInfo/Guidebook/Science/Cyborgs.xml b/Resources/ServerInfo/Guidebook/Science/Cyborgs.xml index 2b8defb07058..c1507ca53960 100644 --- a/Resources/ServerInfo/Guidebook/Science/Cyborgs.xml +++ b/Resources/ServerInfo/Guidebook/Science/Cyborgs.xml @@ -18,28 +18,28 @@ Both brains can be fabricated without requiring any additional research. - ## Chassis - While all cyborgs share the same endoskeleton, not all share the same chassis. The chassis determines what modules the cyborg can have, along with the [color=#a4885c]departmental radio channel[/color] they correspond to. By default, they will always have access to [color=#D381C9]Science[/color] and [color=green]station-wide[/color] frequencies, along with having [color=#a4885c]all-access[/color]. + ## Cyborg types + Once created, a cyborg needs to specialize its chassis to a duty on the station. This determines what modules it starts with, which additional modules can be installed, and what [color=#a4885c]departmental radio channel[/color] it has access to. All cyborgs have access to the [color=#D381C9]Science[/color] and [color=green]station-wide[/color] radio channels. All cyborg types have [color=#a4885c]all-access[/color]. - + - [italic]Examples of various cyborg chassis[/italic] + [italic]Examples of various cyborg types[/italic] - If you wish to change the chassis of an already existing cyborg, you have to construct a whole new one, limbs and frame included. The brain, power cell and modules [italic](if it can fit in the new chassis,)[/italic] can be carried over from the old chassis, if desired. + Once a cyborg chassis has been specialized, it cannot be changed. To change types, a new chassis must be constructed. The brain, power cell, and any modules [italic](if they are compatible with the new chassis)[/italic] can be carried over from the old chassis if desired. ## Modules - A cyborg isn't able to do much without [color=#a4885c]modules[/color]. These printed circuit boards are specific to cyborgs and grant additional functionality to them. They are printed at the [color=#a4885c]Exosuit Fabricator[/color]. + Cyborgs do not have hands, and therefore cannot pick things up like most other players. Instead, their equipment is provided by various [color=#a4885c]modules[/color]. Every cyborg type starts with its own specific set of modules, but additional modules can be inserted as upgrades. These additional modules can be printed at the [color=#a4885c]Exosuit Fabricator[/color]. - [color=#a4885c]Generic[/color] modules add versatility. They can be fitted into any chassis, granting useful tools such as crowbars, GPS, and the ability to interact with cables. [bold]The generic borg chassis can fit up to 6 modules in total.[/bold] + [color=#a4885c]Generic[/color] modules add versatility. They can be fitted into any chassis, granting useful tools such as crowbars, GPS, and the ability to interact with cables. [bold]The generic cyborg chassis can fit up to five additional modules.[/bold] @@ -49,7 +49,7 @@ [italic]Examples of generic modules[/italic] - For more specific needs, [color=#a4885c]specialized[/color] modules are available, granting capabilities like scanning anomalies, constructing walls, reviving crew mates, or cleaning a space lube spill. These modules are typically colored with the same palette as the department [italic](or occupation)[/italic] they relate to. These modules [italic](with exception to [color=#D381C9]science[/color] modules, which can fit any chassis,)[/italic] can only be fitted in their associated borg chassis. [bold]The specialized borg chassis, being the engineering, janitorial, service, medical, and mining chassis, can fit up to 4 modules.[/bold] + For more specific needs, [color=#a4885c]specialized[/color] modules are available, granting capabilities like scanning anomalies, constructing walls, reviving crew mates, or cleaning a space lube spill. These modules are typically colored with the same palette as the department [italic](or occupation)[/italic] they relate to. These modules [italic](with exception to [color=#D381C9]science[/color] modules, which can fit any chassis,)[/italic] can only be fitted in their associated borg chassis. [bold]The specialized borg chassis, being the engineering, janitorial, service, medical, and mining chassis, can fit up to three additional modules.[/bold] diff --git a/Resources/Textures/Interface/Actions/actions_borg.rsi/meta.json b/Resources/Textures/Interface/Actions/actions_borg.rsi/meta.json index dc8a6fcf9c6e..2ebb6eddcf50 100644 --- a/Resources/Textures/Interface/Actions/actions_borg.rsi/meta.json +++ b/Resources/Textures/Interface/Actions/actions_borg.rsi/meta.json @@ -48,7 +48,7 @@ }, { "name":"light-replacer-module" - }, + }, { "name":"cleaning-module" }, @@ -102,6 +102,9 @@ }, { "name":"syndicate-martyr-module" + }, + { + "name": "select-type" } ] } diff --git a/Resources/Textures/Interface/Actions/actions_borg.rsi/select-type.png b/Resources/Textures/Interface/Actions/actions_borg.rsi/select-type.png new file mode 100644 index 0000000000000000000000000000000000000000..766fd71abd0d865e7e4fe89a8137ebafc0c7e5ee GIT binary patch literal 408 zcmV;J0cZY+P)Px$Qb|NXR9J=WS22%+AQXO(nnJGeEyctxoo?;a|Nlpt4qeVfbRe<8$=rm82<>^1 z)4^}zJ%sP$6VOKh0J7}Vzyc`Cufs0OPK^-x68r!F&CZUbEZBdr3X!*_-3ySiU}>7d z@tC##VL#})ZV*#Se@$LhC6lsXM#R8@B-yu0sS&|kpp-(A>{|fnogN54#AxKUh`N@2 zJP;6b^|k;Tn*-}~;PJS9#2`PPKc9;_fQZZP0j1Pv4-6ti1Vrp(t#xoRt##jT+IH-N zJ3qi12RP@TwFb`lh}_M&u@93Sutm6VbG8E^Om@Ib99pg2_g4pAo&q1a$-AU(&iBmZ zQxIC!yZ0X&H`#%?vC4bE>%ir5eZ~^8eGNAU*6#qo_`iQ{@}L9v`;CPPlPRKJ6)II# zGD65$fDm~rWx?uNMlH_>A^y_Lh=@t<6$G$sdHxMyApx5dNM}g^0000bR8v literal 0 HcmV?d00001 diff --git a/Resources/migration.yml b/Resources/migration.yml index 3ed618dcfd70..8940df2b65e1 100644 --- a/Resources/migration.yml +++ b/Resources/migration.yml @@ -440,3 +440,38 @@ BlueprintFlare: null # 2024-10-04 BaseAdvancedPen: Pen + +# 2024-10-09 +# Removal of separate borg chassis parts, replace them with generic borg parts. +LeftArmBorgEngineer: LeftArmBorg +RightArmBorgEngineer: RightArmBorg +LeftLegBorgEngineer: LeftLegBorg +RightLegBorgEngineer: RightLegBorg +HeadBorgEngineer: LightHeadBorg +TorsoBorgEngineer: TorsoBorg + +LeftArmBorgMedical: LeftArmBorg +RightArmBorgMedical: RightArmBorg +LeftLegBorgMedical: LeftLegBorg +RightLegBorgMedical: RightLegBorg +HeadBorgMedical: LightHeadBorg +TorsoBorgMedical: TorsoBorg + +LeftArmBorgMining: LeftArmBorg +RightArmBorgMining: RightArmBorg +LeftLegBorgMining: LeftLegBorg +RightLegBorgMining: RightLegBorg +HeadBorgMining: LightHeadBorg +TorsoBorgMining: TorsoBorg + +LeftArmBorgService: LeftArmBorg +RightArmBorgService: RightArmBorg +LeftLegBorgService: LeftLegBorg +RightLegBorgService: RightLegBorg +HeadBorgService: LightHeadBorg +TorsoBorgService: TorsoBorg + +LeftLegBorgJanitor: LeftLegBorg +RightLegBorgJanitor: RightLegBorg +HeadBorgJanitor: LightHeadBorg +TorsoBorgJanitor: TorsoBorg From 0437ec6d56e764458ff0c9a74fbe4ed3e7280007 Mon Sep 17 00:00:00 2001 From: PJBot Date: Thu, 14 Nov 2024 17:09:42 +0000 Subject: [PATCH 5/6] Automatic changelog update --- Resources/Changelog/Changelog.yml | 32 +++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index eb3f72680084..ce0be691a4a4 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,18 +1,4 @@ Entries: -- author: TheShuEd - changes: - - message: added morbilliard variants of procedural tacos and kebabs - type: Add - - message: removed all microwave taco and kebabs recipes (except for the taco shell - itself) - type: Remove - - message: you can fight with a skewer (even if it has food on it) - type: Tweak - - message: now you can't put more than 10 layers on a burger. (20 before) - type: Tweak - id: 7109 - time: '2024-08-14T13:04:00.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/30905 - author: themias changes: - message: Fixed lizards being unable to eat custom burgers @@ -3941,3 +3927,21 @@ id: 7608 time: '2024-11-14T16:56:22.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/33303 +- author: PJB3005 + changes: + - message: Borgs can now select their chassis type upon creation (construction or + job spawn), immediately giving borgs access to all chassis types. + type: Add + - message: Borg chassis types now come with built-in modules depending on the type, + so you can immediately do your job without help from science. Some upgrade modules + must still be installed later however. + type: Add + - message: Specialized chassis types have been removed from construction, as they + are no longer necessary. + type: Remove + - message: Borg unlock access is no longer determined by their chassis, it's always + science or command. This means the janitor can't unlock jani borgs anymore. + type: Remove + id: 7609 + time: '2024-11-14T17:08:35.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/32586 From 9b8d845293fbcb054d7c1a6d5d235edf842e249d Mon Sep 17 00:00:00 2001 From: MilenVolf Date: Fri, 15 Nov 2024 00:10:58 +0300 Subject: [PATCH 6/6] Update locale files & Localization --- .../ss14-ru/prototypes/actions/borgs.ftl | 2 ++ .../ss14-ru/prototypes/body/parts/silicon.ftl | 12 ++++----- .../entities/mobs/cyborgs/borg_chassis.ftl | 15 ++++++----- .../entities/mobs/player/silicon.ftl | 7 ++---- Resources/Locale/ru-RU/borg/borg.ftl | 25 +++++++++++++++++++ .../ss14-ru/prototypes/actions/borgs.ftl | 2 ++ .../ss14-ru/prototypes/body/parts/silicon.ftl | 12 ++++----- .../entities/mobs/cyborgs/borg_chassis.ftl | 7 ++++-- .../entities/mobs/player/silicon.ftl | 3 --- 9 files changed, 57 insertions(+), 28 deletions(-) diff --git a/Resources/Locale/en-US/ss14-ru/prototypes/actions/borgs.ftl b/Resources/Locale/en-US/ss14-ru/prototypes/actions/borgs.ftl index 8e102f58df5d..be6b7a6eff87 100644 --- a/Resources/Locale/en-US/ss14-ru/prototypes/actions/borgs.ftl +++ b/Resources/Locale/en-US/ss14-ru/prototypes/actions/borgs.ftl @@ -1,2 +1,4 @@ ent-ActionViewLaws = View Laws .desc = View the laws that you must follow. +ent-ActionSelectBorgType = Select Cyborg Type + .desc = { "" } diff --git a/Resources/Locale/en-US/ss14-ru/prototypes/body/parts/silicon.ftl b/Resources/Locale/en-US/ss14-ru/prototypes/body/parts/silicon.ftl index d992d96d4976..ce8727565a8d 100644 --- a/Resources/Locale/en-US/ss14-ru/prototypes/body/parts/silicon.ftl +++ b/Resources/Locale/en-US/ss14-ru/prototypes/body/parts/silicon.ftl @@ -1,14 +1,14 @@ ent-PartSilicon = { ent-BaseItem } .desc = { ent-BaseItem.desc } -ent-BaseBorgArmLeft = cyborg left arm +ent-LeftArmBorg = cyborg left arm .desc = { ent-PartSilicon.desc } -ent-BaseBorgArmRight = cyborg right arm +ent-RightArmBorg = cyborg right arm .desc = { ent-PartSilicon.desc } -ent-BaseBorgLegLeft = cyborg left leg +ent-LeftLegBorg = cyborg left leg .desc = { ent-PartSilicon.desc } -ent-BaseBorgLegRight = cyborg right leg +ent-RightLegBorg = cyborg right leg .desc = { ent-PartSilicon.desc } -ent-BaseBorgHead = cyborg head +ent-LightHeadBorg = cyborg head .desc = { ent-PartSilicon.desc } -ent-BaseBorgTorso = cyborg torso +ent-TorsoBorg = cyborg torso .desc = { ent-PartSilicon.desc } diff --git a/Resources/Locale/en-US/ss14-ru/prototypes/entities/mobs/cyborgs/borg_chassis.ftl b/Resources/Locale/en-US/ss14-ru/prototypes/entities/mobs/cyborgs/borg_chassis.ftl index b0f641ca70e1..df9537e9cee1 100644 --- a/Resources/Locale/en-US/ss14-ru/prototypes/entities/mobs/cyborgs/borg_chassis.ftl +++ b/Resources/Locale/en-US/ss14-ru/prototypes/entities/mobs/cyborgs/borg_chassis.ftl @@ -1,15 +1,18 @@ -ent-BorgChassisGeneric = { ent-BaseBorgChassisNT } +ent-BorgChassisSelectable = { ent-BaseBorgChassisNT } .desc = { ent-BaseBorgChassisNT.desc } +ent-BorgChassisGeneric = generic cyborg + .suffix = type picked + .desc = { ent-BorgChassisSelectable.desc } ent-BorgChassisMining = salvage cyborg - .desc = { ent-BaseBorgChassisNT.desc } + .desc = { ent-BorgChassisSelectable.desc } ent-BorgChassisEngineer = engineer cyborg - .desc = { ent-BaseBorgChassisNT.desc } + .desc = { ent-BorgChassisSelectable.desc } ent-BorgChassisJanitor = janitor cyborg - .desc = { ent-BaseBorgChassisNT.desc } + .desc = { ent-BorgChassisSelectable.desc } ent-BorgChassisMedical = medical cyborg - .desc = { ent-BaseBorgChassisNT.desc } + .desc = { ent-BorgChassisSelectable.desc } ent-BorgChassisService = service cyborg - .desc = { ent-BaseBorgChassisNT.desc } + .desc = { ent-BorgChassisSelectable.desc } ent-BorgChassisSyndicateAssault = syndicate assault cyborg .desc = A lean, mean killing machine with access to a variety of deadly modules. ent-BorgChassisSyndicateMedical = syndicate medical cyborg diff --git a/Resources/Locale/en-US/ss14-ru/prototypes/entities/mobs/player/silicon.ftl b/Resources/Locale/en-US/ss14-ru/prototypes/entities/mobs/player/silicon.ftl index ce4d0e09a32a..72200f5b94e1 100644 --- a/Resources/Locale/en-US/ss14-ru/prototypes/entities/mobs/player/silicon.ftl +++ b/Resources/Locale/en-US/ss14-ru/prototypes/entities/mobs/player/silicon.ftl @@ -45,12 +45,9 @@ ent-StationAiBrain = { ent-PositronicBrain } ent-StationAiHolo = AI eye .desc = The AI's viewer. .suffix = DO NOT MAP -ent-PlayerBorgGeneric = { ent-BorgChassisGeneric } - .suffix = Battery, Tools - .desc = { ent-BorgChassisGeneric.desc } -ent-PlayerBorgBattery = { ent-BorgChassisGeneric } +ent-PlayerBorgBattery = { ent-BorgChassisSelectable } .suffix = Battery - .desc = { ent-BorgChassisGeneric.desc } + .desc = { ent-BorgChassisSelectable.desc } ent-PlayerBorgSyndicateAssaultBattery = { ent-BorgChassisSyndicateAssault } .suffix = Battery, Module, Operative .desc = { ent-BorgChassisSyndicateAssault.desc } diff --git a/Resources/Locale/ru-RU/borg/borg.ftl b/Resources/Locale/ru-RU/borg/borg.ftl index 5dbbb3f1ff98..c69f3815bbe5 100644 --- a/Resources/Locale/ru-RU/borg/borg.ftl +++ b/Resources/Locale/ru-RU/borg/borg.ftl @@ -19,3 +19,28 @@ borg-transponder-disabling-popup = Ваш транспондер начинае borg-transponder-destroying-popup = Механизм самоуничтожения { $name } начинает пищать! borg-transponder-emagged-disabled-popup = Огни вашего транспондера погасли! borg-transponder-emagged-destroyed-popup = Предохранитель вашего транспондера перегорел! +borg-select-type-menu-title = Выберите тип оболочки +borg-select-type-menu-bottom-text = Выбор оболочки необратим +borg-select-type-menu-available = Доступные типы +borg-select-type-menu-information = Информация +borg-select-type-menu-select-type = Выберите тип для просмотра информации +borg-select-type-menu-confirm = Подтвердить выбор +borg-select-type-menu-guidebook = Руководство +borg-type-generic-name = Универсальный +borg-type-generic-desc = Мастер на все руки, мастер ни в чем. Выполняйте различные случайные поручения на станции или помогайте научному отделу, который вас создал. +borg-type-generic-transponder = универсальный киборг +borg-type-engineering-name = Инженерный +borg-type-engineering-desc = Помогайте команде инженеров в строительстве станции, устранении повреждений или устранении электрических и атмосферных неполадок. +borg-type-engineering-transponder = инженерный киборг +borg-type-mining-name = Утилизаторский +borg-type-mining-desc = Присоединяйтесь к утилизаторам и помогайте им добывать материалы, собирать обломки и бороться с враждебной дикой природой. +borg-type-mining-transponder = утилизаторский киборг +borg-type-janitor-name = Уборочный +borg-type-janitor-desc = Поддерживайте чистоту на станции, убирайте лужи, собирайте и надлежащим образом утилизируйте мусор, оставленный ленивыми членами экипажа. +borg-type-janitor-transponder = уборочный киборг +borg-type-medical-name = Медицинский +borg-type-medical-desc = Оказывайте медицинскую помощь экипажу, который в ней нуждается, либо в медицинском отсеке, либо в опасных зонах, куда обычные парамедики не могут добраться. +borg-type-medical-transponder = медицинский киборг +borg-type-service-name = Сервисный +borg-type-service-desc = Помогите экипажу с широким спектром услуг, начиная от подачи закусок и напитков, заканчивая ботаникой и развлечениями. +borg-type-service-transponder = сервисный киборг diff --git a/Resources/Locale/ru-RU/ss14-ru/prototypes/actions/borgs.ftl b/Resources/Locale/ru-RU/ss14-ru/prototypes/actions/borgs.ftl index b94c8ed0c566..c68402701e26 100644 --- a/Resources/Locale/ru-RU/ss14-ru/prototypes/actions/borgs.ftl +++ b/Resources/Locale/ru-RU/ss14-ru/prototypes/actions/borgs.ftl @@ -1,2 +1,4 @@ ent-ActionViewLaws = Просмотреть Законы .desc = Просмотреть законы, которые Вы обязаны соблюдать. +ent-ActionSelectBorgType = Выберите тип киборга + .desc = { "" } diff --git a/Resources/Locale/ru-RU/ss14-ru/prototypes/body/parts/silicon.ftl b/Resources/Locale/ru-RU/ss14-ru/prototypes/body/parts/silicon.ftl index 5b9b6791f611..77edcda3ffc8 100644 --- a/Resources/Locale/ru-RU/ss14-ru/prototypes/body/parts/silicon.ftl +++ b/Resources/Locale/ru-RU/ss14-ru/prototypes/body/parts/silicon.ftl @@ -1,14 +1,14 @@ ent-PartSilicon = { ent-BaseItem } .desc = { ent-BaseItem.desc } -ent-BaseBorgArmLeft = левая рука киборга +ent-LeftArmBorg = левая рука киборга .desc = { ent-PartSilicon.desc } -ent-BaseBorgArmRight = правая рука киборга +ent-RightArmBorg = правая рука киборга .desc = { ent-PartSilicon.desc } -ent-BaseBorgLegLeft = левая нога киборга +ent-LeftLegBorg = левая нога киборга .desc = { ent-PartSilicon.desc } -ent-BaseBorgLegRight = правая нога киборга +ent-RightLegBorg = правая нога киборга .desc = { ent-PartSilicon.desc } -ent-BaseBorgHead = голова киборга +ent-LightHeadBorg = голова киборга .desc = { ent-PartSilicon.desc } -ent-BaseBorgTorso = туловище киборга +ent-TorsoBorg = туловище киборга .desc = { ent-PartSilicon.desc } diff --git a/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/mobs/cyborgs/borg_chassis.ftl b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/mobs/cyborgs/borg_chassis.ftl index 4adea48ead06..73aa157911d7 100644 --- a/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/mobs/cyborgs/borg_chassis.ftl +++ b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/mobs/cyborgs/borg_chassis.ftl @@ -1,7 +1,10 @@ -ent-BorgChassisGeneric = { ent-BaseBorgChassisNT } +ent-BorgChassisSelectable = { ent-BaseBorgChassisNT } .desc = { ent-BaseBorgChassisNT.desc } +ent-BorgChassisGeneric = универсальный киборг + .desc = { ent-BorgChassisSelectable.desc } + .suffix = Выбранный тип ent-BorgChassisMining = шахтёрский киборг - .desc = { ent-BaseBorgChassisNT.desc } + .desc = { ent-BorgChassisSelectable.desc } ent-BorgChassisEngineer = инженерный киборг .desc = { ent-BaseBorgChassisNT.desc } ent-BorgChassisJanitor = уборочный киборг diff --git a/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/mobs/player/silicon.ftl b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/mobs/player/silicon.ftl index 3a6d84564dad..67b79ea4ae9c 100644 --- a/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/mobs/player/silicon.ftl +++ b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/mobs/player/silicon.ftl @@ -45,9 +45,6 @@ ent-StationAiBrain = { ent-PositronicBrain } ent-StationAiHolo = око ИИ .desc = Обозреватель ИИ. .suffix = НЕ МАППИТЬ -ent-PlayerBorgGeneric = { ent-BorgChassisGeneric } - .desc = { ent-BorgChassisGeneric.desc } - .suffix = Батарея, Инструменты ent-PlayerBorgBattery = { ent-BorgChassisGeneric } .suffix = Батарея .desc = { ent-BorgChassisGeneric.desc }