From ef328177508a89b4eeb0447dca63b92e4dd67417 Mon Sep 17 00:00:00 2001 From: FoxxoTrystan Date: Mon, 6 Jan 2025 03:44:22 +0100 Subject: [PATCH 1/5] Start --- .../Clothing/ClientClothingSystem.cs | 24 +- .../Inventory/ClientInventorySystem.cs | 15 +- Content.Client/Overlays/EquipmentHudSystem.cs | 3 +- .../Overlays/ShowHealthBarsSystem.cs | 7 + .../Overlays/ShowHealthIconsSystem.cs | 8 +- .../Silicons/Borgs/BorgMenu.xaml.cs | 3 +- .../Silicons/Borgs/BorgModuleControl.xaml.cs | 3 +- .../Silicons/Borgs/BorgSelectTypeMenu.xaml | 43 ++ .../Silicons/Borgs/BorgSelectTypeMenu.xaml.cs | 80 +++ .../Borgs/BorgSelectTypeUserInterface.cs | 29 + .../Borgs/BorgSwitchableTypeSystem.cs | 81 +++ Content.Client/Silicons/Borgs/BorgSystem.cs | 15 + .../Borgs/BorgSwitchableTypeSystem.cs | 82 +++ .../Silicons/Borgs/BorgSystem.Modules.cs | 40 ++ .../Silicons/Borgs/BorgSystem.Transponder.cs | 18 + .../Silicons/Borgs/BorgSystem.Ui.cs | 3 + Content.Server/Silicons/Borgs/BorgSystem.cs | 15 +- .../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 | 118 ++++ .../Silicons/Borgs/SharedBorgSystem.cs | 9 + Resources/Locale/en-US/borg/borg.ftl | 29 + Resources/Migrations/migration.yml | 35 ++ Resources/Prototypes/Actions/borgs.yml | 12 + Resources/Prototypes/Body/Parts/silicon.yml | 58 +- .../Mobs/Cyborgs/base_borg_chassis.yml | 4 + .../Entities/Mobs/Cyborgs/borg_chassis.yml | 294 ++-------- .../Entities/Mobs/Player/silicon.yml | 21 +- .../Objects/Specific/Robotics/borg_parts.yml | 503 ------------------ .../Specific/Robotics/endoskeleton.yml | 169 +----- .../Entities/Structures/Machines/lathe.yml | 40 -- .../Construction/Graphs/machines/cyborg.yml | 149 +----- .../Prototypes/Recipes/Lathes/robotics.yml | 374 ------------- Resources/Prototypes/Research/industrial.yml | 3 - .../Prototypes/Roles/Jobs/Science/borg.yml | 2 +- Resources/Prototypes/borg_types.yml | 194 +++++++ Resources/Prototypes/tags.yml | 98 +--- .../ServerInfo/Guidebook/Science/Cyborgs.xml | 17 +- .../Actions/actions_borg.rsi/meta.json | 3 + .../Actions/actions_borg.rsi/select-type.png | Bin 0 -> 408 bytes 46 files changed, 1275 insertions(+), 1639 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 878d71cac18..e59ff52f5bc 100644 --- a/Content.Client/Clothing/ClientClothingSystem.cs +++ b/Content.Client/Clothing/ClientClothingSystem.cs @@ -59,6 +59,7 @@ public override void Initialize() base.Initialize(); SubscribeLocalEvent(OnGetVisuals); + SubscribeLocalEvent(OnInventoryTemplateUpdated); SubscribeLocalEvent(OnVisualsChanged); SubscribeLocalEvent(OnDidUnequip); @@ -71,11 +72,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)) @@ -85,6 +82,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 87cea4e3d2f..edd7c252c01 100644 --- a/Content.Client/Inventory/ClientInventorySystem.cs +++ b/Content.Client/Inventory/ClientInventorySystem.cs @@ -235,9 +235,22 @@ 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 c7578b6793f..502a1f36274 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 170f552cf3f..3dda480b439 100644 --- a/Content.Client/Overlays/ShowHealthBarsSystem.cs +++ b/Content.Client/Overlays/ShowHealthBarsSystem.cs @@ -18,9 +18,16 @@ public override void Initialize() { base.Initialize(); + SubscribeLocalEvent(OnHandleState); + _overlay = new(EntityManager); } + 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 a546cf4d828..342433eac78 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,7 +25,7 @@ public override void Initialize() base.Initialize(); SubscribeLocalEvent(OnGetStatusIconsEvent); - + SubscribeLocalEvent(OnHandleState); } protected override void UpdateInternal(RefreshEquipmentHudEvent component) @@ -44,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 || args.InContainer) diff --git a/Content.Client/Silicons/Borgs/BorgMenu.xaml.cs b/Content.Client/Silicons/Borgs/BorgMenu.xaml.cs index 046d8e299fe..a91f38041bc 100644 --- a/Content.Client/Silicons/Borgs/BorgMenu.xaml.cs +++ b/Content.Client/Silicons/Borgs/BorgMenu.xaml.cs @@ -117,7 +117,8 @@ private void UpdateModulePanel() ModuleContainer.Children.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 d5cf05ba63e..245425524ca 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 00000000000..169d8a79704 --- /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 00000000000..7dc02df3a66 --- /dev/null +++ b/Content.Client/Silicons/Borgs/BorgSelectTypeMenu.xaml.cs @@ -0,0 +1,80 @@ +using System.Linq; +using Content.Client.UserInterface.Controls; +using Content.Client.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(BorgSelectTypeUserInterface owner) + { + 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.SetMessage(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 00000000000..356a49674b8 --- /dev/null +++ b/Content.Client/Silicons/Borgs/BorgSelectTypeUserInterface.cs @@ -0,0 +1,29 @@ +using Content.Shared.Silicons.Borgs.Components; +using JetBrains.Annotations; + +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 = new BorgSelectTypeMenu(this); + _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 00000000000..346dc5c276e --- /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 e92ce5cc777..055ae7deee3 100644 --- a/Content.Client/Silicons/Borgs/BorgSystem.cs +++ b/Content.Client/Silicons/Borgs/BorgSystem.cs @@ -92,4 +92,19 @@ 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 00000000000..d1a32a6a5ba --- /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 7ede2342428..4e28adcef06 100644 --- a/Content.Server/Silicons/Borgs/BorgSystem.Modules.cs +++ b/Content.Server/Silicons/Borgs/BorgSystem.Modules.cs @@ -3,6 +3,7 @@ using Content.Shared.Interaction.Components; using Content.Shared.Silicons.Borgs.Components; using Content.Server.Silicons.Borgs.Components; +using Content.Shared.Whitelist; using Robust.Shared.Containers; namespace Content.Server.Silicons.Borgs; @@ -300,6 +301,25 @@ public void InstallAllModules(EntityUid uid, BorgChassisComponent? component = n } } + /// + /// 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; + } + + /// /// Deactivates all modules currently inside the borg's module container /// @@ -351,4 +371,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 1c10cbe667e..ec42f0a8c3c 100644 --- a/Content.Server/Silicons/Borgs/BorgSystem.Transponder.cs +++ b/Content.Server/Silicons/Borgs/BorgSystem.Transponder.cs @@ -7,6 +7,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; @@ -104,4 +105,21 @@ 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 d0e9f80e364..40c2c3bf332 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 75f25a3a922..57f9d12c56c 100644 --- a/Content.Server/Silicons/Borgs/BorgSystem.cs +++ b/Content.Server/Silicons/Borgs/BorgSystem.cs @@ -128,7 +128,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; @@ -136,6 +136,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/Inventory/InventoryComponent.cs b/Content.Shared/Inventory/InventoryComponent.cs index b7a42fec53c..8e43232eeda 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 e0f2a695576..25f87ed2e2a 100644 --- a/Content.Shared/Inventory/InventorySystem.Slots.cs +++ b/Content.Shared/Inventory/InventorySystem.Slots.cs @@ -4,6 +4,7 @@ using Robust.Shared.Containers; using Robust.Shared.Prototypes; using Robust.Shared.Utility; +using System.Linq; namespace Content.Shared.Inventory; @@ -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 48e3162269a..1ce14590966 100644 --- a/Content.Shared/Overlays/ShowHealthBarsComponent.cs +++ b/Content.Shared/Overlays/ShowHealthBarsComponent.cs @@ -8,11 +8,13 @@ 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("damageContainers", customTypeSerializer: typeof(PrototypeIdListSerializer))] + [AutoNetworkedField] public List DamageContainers = new(); } diff --git a/Content.Shared/Overlays/ShowHealthIconsComponent.cs b/Content.Shared/Overlays/ShowHealthIconsComponent.cs index c2526c2f401..05d5fbc1335 100644 --- a/Content.Shared/Overlays/ShowHealthIconsComponent.cs +++ b/Content.Shared/Overlays/ShowHealthIconsComponent.cs @@ -8,11 +8,13 @@ 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("damageContainers", customTypeSerializer: typeof(PrototypeIdListSerializer))] + [AutoNetworkedField] public List DamageContainers = new(); } diff --git a/Content.Shared/Silicons/Borgs/BorgTypePrototype.cs b/Content.Shared/Silicons/Borgs/BorgTypePrototype.cs new file mode 100644 index 00000000000..6154c127577 --- /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 71d3a7bd166..0e480c7ddb8 100644 --- a/Content.Shared/Silicons/Borgs/Components/BorgChassisComponent.cs +++ b/Content.Shared/Silicons/Borgs/Components/BorgChassisComponent.cs @@ -87,5 +87,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 a7523c1ce70..e542a1e3e3e 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 00000000000..9a783d19aa7 --- /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 00000000000..e75177a4d6d --- /dev/null +++ b/Content.Shared/Silicons/Borgs/SharedBorgSwitchableTypeSystem.cs @@ -0,0 +1,118 @@ +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!; + + [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 FootstepModifierComponent? footstepModifier)) + { + footstepModifier.FootstepSoundCollection = prototype.FootstepCollection; + } + } +} diff --git a/Content.Shared/Silicons/Borgs/SharedBorgSystem.cs b/Content.Shared/Silicons/Borgs/SharedBorgSystem.cs index 0431d95a42f..8fd9cfb2905 100644 --- a/Content.Shared/Silicons/Borgs/SharedBorgSystem.cs +++ b/Content.Shared/Silicons/Borgs/SharedBorgSystem.cs @@ -96,4 +96,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 c9005eb7961..60056b4919c 100644 --- a/Resources/Locale/en-US/borg/borg.ftl +++ b/Resources/Locale/en-US/borg/borg.ftl @@ -22,3 +22,32 @@ borg-ui-module-counter = {$actual}/{$max} borg-transponder-disabled-popup = A brain shoots out the top of {$name}! 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/Migrations/migration.yml b/Resources/Migrations/migration.yml index 3ac6b353a9b..4846ce4323c 100644 --- a/Resources/Migrations/migration.yml +++ b/Resources/Migrations/migration.yml @@ -244,3 +244,38 @@ ReinforcementRadioSyndicateMonkeyNukeops: ReinforcementRadioSyndicateAncestorNuk # 2024-05-01 DrinkBottleGoldschlager: DrinkBottleGildlager + +# 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 diff --git a/Resources/Prototypes/Actions/borgs.yml b/Resources/Prototypes/Actions/borgs.yml index 6d35c69cf6a..2e884f9cc56 100644 --- a/Resources/Prototypes/Actions/borgs.yml +++ b/Resources/Prototypes/Actions/borgs.yml @@ -11,3 +11,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 24d88276ccb..3b0f2540963 100644 --- a/Resources/Prototypes/Body/Parts/silicon.yml +++ b/Resources/Prototypes/Body/Parts/silicon.yml @@ -24,85 +24,109 @@ Steel: 25 - type: GuideHelp guides: - - Cyborgs + - Cyborgs + - Robotics - type: entity - id: BaseBorgArmLeft + id: LeftArmBorg parent: PartSilicon - name: left cyborg arm - abstract: true + name: cyborg left arm 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: right cyborg arm - abstract: true + name: cyborg right arm 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: left cyborg leg - abstract: true + name: cyborg left leg 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: right cyborg leg - abstract: true + name: cyborg right leg 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 b44dd1a52d8..03585b0b8ab 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 @@ -139,6 +142,7 @@ collection: FootstepBorg - type: Construction graph: Cyborg + node: cyborg containers: - part-container - cell_slot diff --git a/Resources/Prototypes/Entities/Mobs/Cyborgs/borg_chassis.yml b/Resources/Prototypes/Entities/Mobs/Cyborgs/borg_chassis.yml index e0dc4a0ad43..c61371cf820 100644 --- a/Resources/Prototypes/Entities/Mobs/Cyborgs/borg_chassis.yml +++ b/Resources/Prototypes/Entities/Mobs/Cyborgs/borg_chassis.yml @@ -1,23 +1,21 @@ - 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 + maxModules: 0 hasMindState: robot_e noMindState: robot_e_r - type: BorgTransponder @@ -25,287 +23,59 @@ sprite: Mobs/Silicon/chassis.rsi state: robot name: cyborg - - type: Construction - node: cyborg - - type: Speech - speechVerb: Robotic + - 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: 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: SiliconLawProvider # Delta-V - Adds custom lawset for Engineering Cyborg - laws: Engineer + - 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: SiliconLawProvider # Delta-V Adds custom lawset for Janitor Cyborg - laws: Janitor + - type: BorgSwitchableType + selectedBorgType: janitor - type: entity id: BorgChassisMedical - parent: BaseBorgChassisNT + 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: FabricateActions - actions: - - ActionFabricateLollipop - - ActionFabricateGumball - - type: SiliconLawProvider - laws: Medical + - 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: BorgSwitchableType + selectedBorgType: service - type: entity id: BorgChassisSyndicateAssault diff --git a/Resources/Prototypes/Entities/Mobs/Player/silicon.yml b/Resources/Prototypes/Entities/Mobs/Player/silicon.yml index 0f8998bdec8..ea8afb7c4b7 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/silicon.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/silicon.yml @@ -1,25 +1,6 @@ -- 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 6df0488e28f..00000000000 --- 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 98f953f6824..cc253b0c612 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 c74a4303b21..2e6a47fd8ff 100644 --- a/Resources/Prototypes/Entities/Structures/Machines/lathe.yml +++ b/Resources/Prototypes/Entities/Structures/Machines/lathe.yml @@ -605,11 +605,6 @@ - BorgModuleFireExtinguisher - BorgModuleRadiationDetection - BorgModuleTool - - BorgModuleAppraisal - - BorgModuleConstruction - - BorgModuleService - - BorgModuleTreatment - - BorgModuleCleaning - CyborgEndoskeleton - LeftArmBorg - RightArmBorg @@ -617,52 +612,17 @@ - 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 - BorgModuleJetpack - BorgModulePka - BorgModuleArtifact - BorgModuleAnomaly - BorgModuleGardening - BorgModuleHarvesting - - BorgModuleMusique - - BorgModuleClowning - - BorgModuleDiagnosis - BorgModuleDefibrillator - BorgModuleAdvancedTreatment - RipleyHarness diff --git a/Resources/Prototypes/Recipes/Construction/Graphs/machines/cyborg.yml b/Resources/Prototypes/Recipes/Construction/Graphs/machines/cyborg.yml index 0f012cefc98..7c7dfb6a5ee 100644 --- a/Resources/Prototypes/Recipes/Construction/Graphs/machines/cyborg.yml +++ b/Resources/Prototypes/Recipes/Construction/Graphs/machines/cyborg.yml @@ -6,17 +6,6 @@ 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,118 +32,10 @@ - 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 + - to: quadborg 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 + - assemblyId: quadborg guideString: borg-construction-guide-string - material: Cable @@ -180,28 +61,4 @@ 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 2dc0a65748e..b1d6e114b87 100644 --- a/Resources/Prototypes/Recipes/Lathes/robotics.yml +++ b/Resources/Prototypes/Recipes/Lathes/robotics.yml @@ -79,258 +79,6 @@ Steel: 250 Glass: 100 -- type: latheRecipe - id: LeftArmBorgEngineer - result: LeftArmBorgEngineer - category: Robotics - completetime: 2 - materials: - Steel: 250 - Glass: 100 - -- type: latheRecipe - id: RightArmBorgEngineer - result: RightArmBorgEngineer - category: Robotics - completetime: 2 - materials: - Steel: 250 - Glass: 100 - -- type: latheRecipe - id: LeftLegBorgEngineer - result: LeftLegBorgEngineer - category: Robotics - completetime: 2 - materials: - Steel: 250 - Glass: 100 - -- type: latheRecipe - id: RightLegBorgEngineer - result: RightLegBorgEngineer - category: Robotics - completetime: 2 - materials: - Steel: 250 - Glass: 100 - -- type: latheRecipe - id: HeadBorgEngineer - result: HeadBorgEngineer - category: Robotics - completetime: 2 - materials: - Steel: 250 - Glass: 100 - -- type: latheRecipe - id: TorsoBorgEngineer - result: TorsoBorgEngineer - category: Robotics - completetime: 2 - materials: - Steel: 250 - Glass: 100 - -- type: latheRecipe - id: LeftArmBorgMedical - result: LeftArmBorgMedical - category: Robotics - completetime: 2 - materials: - Steel: 250 - Glass: 100 - -- type: latheRecipe - id: RightArmBorgMedical - result: RightArmBorgMedical - category: Robotics - completetime: 2 - materials: - Steel: 250 - Glass: 100 - -- type: latheRecipe - id: LeftLegBorgMedical - result: LeftLegBorgMedical - category: Robotics - completetime: 2 - materials: - Steel: 250 - Glass: 100 - -- type: latheRecipe - id: RightLegBorgMedical - result: RightLegBorgMedical - category: Robotics - completetime: 2 - materials: - Steel: 250 - Glass: 100 - -- type: latheRecipe - id: HeadBorgMedical - result: HeadBorgMedical - category: Robotics - completetime: 2 - materials: - Steel: 250 - Glass: 100 - -- type: latheRecipe - id: TorsoBorgMedical - result: TorsoBorgMedical - category: Robotics - completetime: 2 - materials: - Steel: 250 - Glass: 100 - -- type: latheRecipe - id: LeftArmBorgMining - result: LeftArmBorgMining - category: Robotics - completetime: 2 - materials: - Steel: 250 - Glass: 100 - -- type: latheRecipe - id: RightArmBorgMining - result: RightArmBorgMining - category: Robotics - completetime: 2 - materials: - Steel: 250 - Glass: 100 - -- type: latheRecipe - id: LeftLegBorgMining - result: LeftLegBorgMining - category: Robotics - completetime: 2 - materials: - Steel: 250 - Glass: 100 - -- type: latheRecipe - id: RightLegBorgMining - result: RightLegBorgMining - category: Robotics - completetime: 2 - materials: - Steel: 250 - Glass: 100 - -- type: latheRecipe - id: HeadBorgMining - result: HeadBorgMining - category: Robotics - completetime: 2 - materials: - Steel: 250 - Glass: 100 - -- type: latheRecipe - id: TorsoBorgMining - result: TorsoBorgMining - category: Robotics - completetime: 2 - materials: - Steel: 250 - Glass: 100 - -- type: latheRecipe - id: LeftArmBorgService - result: LeftArmBorgService - category: Robotics - completetime: 2 - materials: - Steel: 250 - Glass: 100 - -- type: latheRecipe - id: RightArmBorgService - result: RightArmBorgService - category: Robotics - completetime: 2 - materials: - Steel: 250 - Glass: 100 - -- type: latheRecipe - id: LeftLegBorgService - result: LeftLegBorgService - category: Robotics - completetime: 2 - materials: - Steel: 250 - Glass: 100 - -- type: latheRecipe - id: RightLegBorgService - result: RightLegBorgService - category: Robotics - completetime: 2 - materials: - Steel: 250 - Glass: 100 - -- type: latheRecipe - id: HeadBorgService - result: HeadBorgService - category: Robotics - completetime: 2 - materials: - Steel: 250 - Glass: 100 - -- type: latheRecipe - id: TorsoBorgService - result: TorsoBorgService - category: Robotics - completetime: 2 - materials: - Steel: 250 - Glass: 100 - -- type: latheRecipe - id: LeftLegBorgJanitor - result: LeftLegBorgJanitor - category: Robotics - completetime: 2 - materials: - Steel: 250 - Glass: 100 - -- type: latheRecipe - id: RightLegBorgJanitor - result: RightLegBorgJanitor - category: Robotics - completetime: 2 - materials: - Steel: 250 - Glass: 100 - -- type: latheRecipe - id: HeadBorgJanitor - result: HeadBorgJanitor - category: Robotics - completetime: 4 - materials: - Steel: 500 - Glass: 200 - -- type: latheRecipe - id: TorsoBorgJanitor - result: TorsoBorgJanitor - category: Robotics - completetime: 4 - materials: - Steel: 500 - Glass: 200 - - type: latheRecipe id: MMI result: MMI @@ -407,37 +155,6 @@ Glass: 250 Plastic: 250 -- type: latheRecipe - id: BorgModuleAppraisal - result: BorgModuleAppraisal - category: Robotics - completetime: 3 - materials: - Steel: 250 - Glass: 250 - Plastic: 250 - -- type: latheRecipe - id: BorgModuleMining - result: BorgModuleMining - category: Robotics - completetime: 3 - materials: - Steel: 250 - Glass: 250 - Plastic: 250 - -- type: latheRecipe - id: BorgModuleGrapplingGun - result: BorgModuleGrapplingGun - category: Robotics - completetime: 3 - materials: - Steel: 500 - Glass: 500 - Plastic: 250 - Gold: 50 - - type: latheRecipe id: BorgModuleAdvancedTool result: BorgModuleAdvancedTool @@ -449,47 +166,6 @@ Plastic: 250 Gold: 50 -- type: latheRecipe - id: BorgModuleConstruction - result: BorgModuleConstruction - category: Robotics - completetime: 3 - materials: - Steel: 500 - Glass: 500 - Plastic: 250 - -- type: latheRecipe - id: BorgModuleRCD - result: BorgModuleRCD - category: Robotics - completetime: 3 - materials: - Steel: 500 - Glass: 500 - Plastic: 250 - Gold: 50 - -- type: latheRecipe - id: BorgModuleLightReplacer - result: BorgModuleLightReplacer - category: Robotics - completetime: 3 - materials: - Steel: 250 - Glass: 250 - Plastic: 250 - -- type: latheRecipe - id: BorgModuleCleaning - result: BorgModuleCleaning - category: Robotics - completetime: 3 - materials: - Steel: 250 - Glass: 250 - Plastic: 250 - - type: latheRecipe id: BorgModuleAdvancedCleaning result: BorgModuleAdvancedCleaning @@ -501,26 +177,6 @@ Plastic: 250 Gold: 50 -- type: latheRecipe - id: BorgModuleDiagnosis - result: BorgModuleDiagnosis - category: Robotics - completetime: 3 - materials: - Steel: 250 - Glass: 250 - Plastic: 250 - -- type: latheRecipe - id: BorgModuleTreatment - result: BorgModuleTreatment - category: Robotics - completetime: 3 - materials: - Steel: 250 - Glass: 250 - Plastic: 250 - - type: latheRecipe id: BorgModuleAdvancedTreatment result: BorgModuleAdvancedTreatment @@ -563,26 +219,6 @@ Glass: 250 Plastic: 250 -- type: latheRecipe - id: BorgModuleService - result: BorgModuleService - category: Robotics - completetime: 3 - materials: - Steel: 250 - Glass: 250 - Plastic: 250 - -- type: latheRecipe - id: BorgModuleMusique - result: BorgModuleMusique - category: Robotics - completetime: 3 - materials: - Steel: 250 - Glass: 250 - Plastic: 250 - - type: latheRecipe id: BorgModuleGardening result: BorgModuleGardening @@ -603,16 +239,6 @@ Glass: 250 Plastic: 250 -- type: latheRecipe - id: BorgModuleClowning - result: BorgModuleClowning - category: Robotics - completetime: 3 - materials: - Steel: 250 - Glass: 250 - Plastic: 250 - - type: latheRecipe id: BorgModulePka result: BorgModulePka diff --git a/Resources/Prototypes/Research/industrial.yml b/Resources/Prototypes/Research/industrial.yml index e48dd97662e..b50f747618b 100644 --- a/Resources/Prototypes/Research/industrial.yml +++ b/Resources/Prototypes/Research/industrial.yml @@ -11,7 +11,6 @@ cost: 7500 recipeUnlocks: - MiningDrill - - BorgModuleMining - OreProcessorIndustrialMachineCircuitboard - OreBagOfHolding - ClothingMaskWeldingGas @@ -119,7 +118,6 @@ cost: 5000 recipeUnlocks: - WeaponGrapplingGun - - BorgModuleGrapplingGun # Tier 2 @@ -180,7 +178,6 @@ - PowerDrill - JawsOfLife - BorgModuleAdvancedTool - - BorgModuleRCD - type: technology id: MechanizedSalvaging diff --git a/Resources/Prototypes/Roles/Jobs/Science/borg.yml b/Resources/Prototypes/Roles/Jobs/Science/borg.yml index e62be04beec..fea9afa0b59 100644 --- a/Resources/Prototypes/Roles/Jobs/Science/borg.yml +++ b/Resources/Prototypes/Roles/Jobs/Science/borg.yml @@ -9,4 +9,4 @@ canBeAntag: false icon: JobIconBorg supervisors: job-supervisors-rd - jobEntity: PlayerBorgGeneric + jobEntity: PlayerBorgBattery diff --git a/Resources/Prototypes/borg_types.yml b/Resources/Prototypes/borg_types.yml new file mode 100644 index 00000000000..3cfb3210b19 --- /dev/null +++ b/Resources/Prototypes/borg_types.yml @@ -0,0 +1,194 @@ +# 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 + + +# 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 + + +# 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 + + +# 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 + + +# 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 + + # 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 diff --git a/Resources/Prototypes/tags.yml b/Resources/Prototypes/tags.yml index c0ed329c039..15d6a8c9fc1 100644 --- a/Resources/Prototypes/tags.yml +++ b/Resources/Prototypes/tags.yml @@ -76,96 +76,24 @@ - 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 + id: BorgLArm - type: Tag - id: BorgJanitorLLeg + id: BorgRArm - type: Tag - id: BorgJanitorRLeg + id: BorgTorso - type: Tag - id: BorgJanitorTorso + id: BorgRLeg - 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 - -- type: Tag - id: BorgMiningLArm - -- type: Tag - id: BorgMiningLLeg - -- type: Tag - id: BorgMiningRArm - -- type: Tag - id: BorgMiningRLeg - -- type: Tag - id: BorgMiningTorso - - type: Tag id: BorgModuleCargo @@ -190,24 +118,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: BotanyHatchet diff --git a/Resources/ServerInfo/Guidebook/Science/Cyborgs.xml b/Resources/ServerInfo/Guidebook/Science/Cyborgs.xml index 2b8defb0705..92a350478cb 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] @@ -63,4 +63,3 @@ Additional modules with advanced or novel capabilities can be acquired through new [textlink="technologies" link="Technologies"] researched by scientists. - diff --git a/Resources/Textures/Interface/Actions/actions_borg.rsi/meta.json b/Resources/Textures/Interface/Actions/actions_borg.rsi/meta.json index f63bacd07a9..03f6758dfd2 100644 --- a/Resources/Textures/Interface/Actions/actions_borg.rsi/meta.json +++ b/Resources/Textures/Interface/Actions/actions_borg.rsi/meta.json @@ -9,6 +9,9 @@ "states": [ { "name": "state-laws" + }, + { + "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 From 4e58b471278d2d7f32a800de6f7fdfde653424e9 Mon Sep 17 00:00:00 2001 From: FoxxoTrystan Date: Tue, 7 Jan 2025 12:35:52 +0100 Subject: [PATCH 2/5] Bunch of fixes --- Resources/Prototypes/Research/civilianservices.yml | 3 --- Resources/Prototypes/tags.yml | 3 +++ 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Resources/Prototypes/Research/civilianservices.yml b/Resources/Prototypes/Research/civilianservices.yml index a92f72f797d..889dcd9d113 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/tags.yml b/Resources/Prototypes/tags.yml index 15d6a8c9fc1..f19792ab9ab 100644 --- a/Resources/Prototypes/tags.yml +++ b/Resources/Prototypes/tags.yml @@ -85,6 +85,9 @@ - type: Tag id: BorgRArm +- type: Tag + id: BorgLLeg + - type: Tag id: BorgTorso From 0a361d8c30be72c32af4f69a8a0eae9c14c4cda8 Mon Sep 17 00:00:00 2001 From: FoxxoTrystan Date: Tue, 7 Jan 2025 12:43:41 +0100 Subject: [PATCH 3/5] addtional fixes --- .../Construction/Graphs/machines/cyborg.yml | 27 ------------------- 1 file changed, 27 deletions(-) diff --git a/Resources/Prototypes/Recipes/Construction/Graphs/machines/cyborg.yml b/Resources/Prototypes/Recipes/Construction/Graphs/machines/cyborg.yml index 7c7dfb6a5ee..b557df8abb9 100644 --- a/Resources/Prototypes/Recipes/Construction/Graphs/machines/cyborg.yml +++ b/Resources/Prototypes/Recipes/Construction/Graphs/machines/cyborg.yml @@ -33,32 +33,5 @@ - tool: Screwing doAfter: 0.5 - - to: quadborg - steps: - - assemblyId: quadborg - 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: BorgChassisSelectable From 54495ece1655dc015733ccaa69db6c2f49d51eb5 Mon Sep 17 00:00:00 2001 From: FoxxoTrystan Date: Tue, 7 Jan 2025 13:00:06 +0100 Subject: [PATCH 4/5] more! --- Resources/Prototypes/Entities/Mobs/Cyborgs/borg_chassis.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/Resources/Prototypes/Entities/Mobs/Cyborgs/borg_chassis.yml b/Resources/Prototypes/Entities/Mobs/Cyborgs/borg_chassis.yml index c61371cf820..c07afae8df1 100644 --- a/Resources/Prototypes/Entities/Mobs/Cyborgs/borg_chassis.yml +++ b/Resources/Prototypes/Entities/Mobs/Cyborgs/borg_chassis.yml @@ -163,5 +163,3 @@ - BorgModuleSyndicate hasMindState: synd_engi_e noMindState: synd_engi - - type: Construction - node: syndicatesaboteur From 80868f5e81765e02ec3d22dc6227ee54ec9c23f3 Mon Sep 17 00:00:00 2001 From: FoxxoTrystan Date: Tue, 7 Jan 2025 13:08:19 +0100 Subject: [PATCH 5/5] fixes! --- Resources/Prototypes/Entities/Mobs/Cyborgs/borg_chassis.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Resources/Prototypes/Entities/Mobs/Cyborgs/borg_chassis.yml b/Resources/Prototypes/Entities/Mobs/Cyborgs/borg_chassis.yml index c07afae8df1..a681d931903 100644 --- a/Resources/Prototypes/Entities/Mobs/Cyborgs/borg_chassis.yml +++ b/Resources/Prototypes/Entities/Mobs/Cyborgs/borg_chassis.yml @@ -105,8 +105,6 @@ - BorgModuleSyndicateAssault hasMindState: synd_sec_e noMindState: synd_sec - - type: Construction - node: syndicateassault - type: entity id: BorgChassisSyndicateMedical @@ -134,8 +132,6 @@ - BorgModuleSyndicate hasMindState: synd_medical_e noMindState: synd_medical - - type: Construction - node: syndicatemedical - type: entity id: BorgChassisSyndicateSaboteur