forked from space-wizards/space-station-14
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Borg type switching. (space-wizards#32586)
* Borg type switching. This allows borgs (new spawn or constructed) to select their chassis type on creation, like in SS13. This removes the need for the many different chassis types, and means round-start borgs can actually play the game immediately instead of waiting for science to unlock everything. New borgs have an additional action that allows them to select their type. This opens a nice window with basic information about the borgs and a select button. Once a type has been selected it is permanent for that borg chassis. These borg types also immediately start the borg with specific modules, so they do not need to be printed. Additional modules can still be inserted for upgrades, though this is now less critical. The built-in modules cannot be removed, but are shown in the UI. The modules that each borg type starts with: * Generic: tools * Engineering: advanced tools, construction, RCD, cable * Salvage: Grappling gun, appraisal, mining * Janitor: cleaning, light replacer * Medical: treatment * Service: music, service, clowning Specialized borgs have 3 additional module slots available on top of the ones listed above, generic borgs have 5. Borg types are specified in a new BorgTypePrototype. These prototypes specify all information about the borg type. It is assigned to the borg entity through a mix of client side, server, and shared code. Some of the involved components were made networked, others are just ensured they're set on both sides of the wire. The most gnarly change is the inventory template prototype, which needs to change purely to modify the borg hat offset. I managed to bodge this in with an API that *probably* won't explode for specifically for this use case, but it's still not the most clean of API designs. Parts for specific borg chassis have been removed (so much deleted YAML) and specialized borg modules that are in the base set of a type have been removed from the exosuit fab as there's no point to printing those. The ability to "downgrade" a borg so it can select a new chassis, like in SS13, is something that would be nice, but was not high enough priority for me to block the feature on. I did keep it in mind with some of the code, so it may be possible in the future. There is no fancy animation when selecting borg types like in SS13, because I didn't think it was high priority, and it would add a lot of complex code. * Fix sandbox failure due to collection expression. * Module tweak Fix salvage borg modules still having research/lathe recipes Engie borg has regular tool module, not advanced. * Fix inventory system breakage * Fix migrations Some things were missing * Guidebook rewordings & review * MinWidth on confirm selection button
- Loading branch information
Showing
49 changed files
with
1,336 additions
and
1,533 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
<controls:FancyWindow xmlns="https://spacestation14.io" | ||
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls" | ||
xmlns:customControls="clr-namespace:Content.Client.Administration.UI.CustomControls" | ||
Title="{Loc 'borg-select-type-menu-title'}" | ||
SetSize="550 300"> | ||
<BoxContainer Orientation="Vertical"> | ||
<BoxContainer Orientation="Horizontal" VerticalExpand="True"> | ||
<!-- Left pane: selection of borg type --> | ||
<BoxContainer Orientation="Vertical" MinWidth="200" Margin="2 0"> | ||
<Label Text="{Loc 'borg-select-type-menu-available'}" StyleClasses="LabelHeading" /> | ||
<ScrollContainer HScrollEnabled="False" VerticalExpand="True"> | ||
<BoxContainer Name="SelectionsContainer" Orientation="Vertical" /> | ||
</ScrollContainer> | ||
</BoxContainer> | ||
|
||
<customControls:VSeparator /> | ||
|
||
<!-- Right pane: information about selected borg module, confirm button. --> | ||
<BoxContainer Orientation="Vertical" HorizontalExpand="True" Margin="2 0"> | ||
<Label Text="{Loc 'borg-select-type-menu-information'}" StyleClasses="LabelHeading" /> | ||
<Control VerticalExpand="True"> | ||
<controls:Placeholder Name="InfoPlaceholder" PlaceholderText="{Loc 'borg-select-type-menu-select-type'}" /> | ||
<BoxContainer Name="InfoContents" Orientation="Vertical" Visible="False"> | ||
<BoxContainer Orientation="Horizontal" Margin="0 0 0 4"> | ||
<EntityPrototypeView Name="ChassisView" Scale="2,2" /> | ||
<Label Name="NameLabel" HorizontalExpand="True" /> | ||
</BoxContainer> | ||
|
||
<RichTextLabel Name="DescriptionLabel" VerticalExpand="True" VerticalAlignment="Top" /> | ||
</BoxContainer> | ||
</Control> | ||
<controls:ConfirmButton Name="ConfirmTypeButton" Text="{Loc 'borg-select-type-menu-confirm'}" | ||
Disabled="True" HorizontalAlignment="Right" | ||
MinWidth="200" /> | ||
</BoxContainer> | ||
</BoxContainer> | ||
|
||
<controls:StripeBack Margin="0 0 0 4"> | ||
<Label Text="{Loc 'borg-select-type-menu-bottom-text'}" HorizontalAlignment="Center" StyleClasses="LabelSubText" Margin="4 4 0 4"/> | ||
</controls:StripeBack> | ||
</BoxContainer> | ||
|
||
</controls:FancyWindow> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
using System.Linq; | ||
using Content.Client.UserInterface.Controls; | ||
using Content.Client.UserInterface.Systems.Guidebook; | ||
using Content.Shared.Guidebook; | ||
using Content.Shared.Silicons.Borgs; | ||
using Content.Shared.Silicons.Borgs.Components; | ||
using Robust.Client.AutoGenerated; | ||
using Robust.Client.UserInterface.Controls; | ||
using Robust.Client.UserInterface.XAML; | ||
using Robust.Shared.Prototypes; | ||
|
||
namespace Content.Client.Silicons.Borgs; | ||
|
||
/// <summary> | ||
/// Menu used by borgs to select their type. | ||
/// </summary> | ||
/// <seealso cref="BorgSelectTypeUserInterface"/> | ||
/// <seealso cref="BorgSwitchableTypeComponent"/> | ||
[GenerateTypedNameReferences] | ||
public sealed partial class BorgSelectTypeMenu : FancyWindow | ||
{ | ||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!; | ||
|
||
private BorgTypePrototype? _selectedBorgType; | ||
|
||
public event Action<ProtoId<BorgTypePrototype>>? ConfirmedBorgType; | ||
|
||
[ValidatePrototypeId<GuideEntryPrototype>] | ||
private static readonly List<ProtoId<GuideEntryPrototype>> GuidebookEntries = new() { "Cyborgs", "Robotics" }; | ||
|
||
public BorgSelectTypeMenu() | ||
{ | ||
RobustXamlLoader.Load(this); | ||
IoCManager.InjectDependencies(this); | ||
|
||
var group = new ButtonGroup(); | ||
foreach (var borgType in _prototypeManager.EnumeratePrototypes<BorgTypePrototype>().OrderBy(PrototypeName)) | ||
{ | ||
var button = new Button | ||
{ | ||
Text = PrototypeName(borgType), | ||
Group = group, | ||
}; | ||
button.OnPressed += _ => | ||
{ | ||
_selectedBorgType = borgType; | ||
UpdateInformation(borgType); | ||
}; | ||
SelectionsContainer.AddChild(button); | ||
} | ||
|
||
ConfirmTypeButton.OnPressed += ConfirmButtonPressed; | ||
HelpGuidebookIds = GuidebookEntries; | ||
} | ||
|
||
private void UpdateInformation(BorgTypePrototype prototype) | ||
{ | ||
_selectedBorgType = prototype; | ||
|
||
InfoContents.Visible = true; | ||
InfoPlaceholder.Visible = false; | ||
ConfirmTypeButton.Disabled = false; | ||
|
||
NameLabel.Text = PrototypeName(prototype); | ||
DescriptionLabel.Text = Loc.GetString($"borg-type-{prototype.ID}-desc"); | ||
ChassisView.SetPrototype(prototype.DummyPrototype); | ||
} | ||
|
||
private void ConfirmButtonPressed(BaseButton.ButtonEventArgs obj) | ||
{ | ||
if (_selectedBorgType == null) | ||
return; | ||
|
||
ConfirmedBorgType?.Invoke(_selectedBorgType); | ||
} | ||
|
||
private static string PrototypeName(BorgTypePrototype prototype) | ||
{ | ||
return Loc.GetString($"borg-type-{prototype.ID}-name"); | ||
} | ||
} |
30 changes: 30 additions & 0 deletions
30
Content.Client/Silicons/Borgs/BorgSelectTypeUserInterface.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
using Content.Shared.Silicons.Borgs.Components; | ||
using JetBrains.Annotations; | ||
using Robust.Client.UserInterface; | ||
|
||
namespace Content.Client.Silicons.Borgs; | ||
|
||
/// <summary> | ||
/// User interface used by borgs to select their type. | ||
/// </summary> | ||
/// <seealso cref="BorgSelectTypeMenu"/> | ||
/// <seealso cref="BorgSwitchableTypeComponent"/> | ||
/// <seealso cref="BorgSwitchableTypeUiKey"/> | ||
[UsedImplicitly] | ||
public sealed class BorgSelectTypeUserInterface : BoundUserInterface | ||
{ | ||
[ViewVariables] | ||
private BorgSelectTypeMenu? _menu; | ||
|
||
public BorgSelectTypeUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey) | ||
{ | ||
} | ||
|
||
protected override void Open() | ||
{ | ||
base.Open(); | ||
|
||
_menu = this.CreateWindow<BorgSelectTypeMenu>(); | ||
_menu.ConfirmedBorgType += prototype => SendMessage(new BorgSelectTypeMessage(prototype)); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; | ||
|
||
/// <summary> | ||
/// Client side logic for borg type switching. Sets up primarily client-side visual information. | ||
/// </summary> | ||
/// <seealso cref="SharedBorgSwitchableTypeSystem"/> | ||
/// <seealso cref="BorgSwitchableTypeComponent"/> | ||
public sealed class BorgSwitchableTypeSystem : SharedBorgSwitchableTypeSystem | ||
{ | ||
[Dependency] private readonly BorgSystem _borgSystem = default!; | ||
[Dependency] private readonly AppearanceSystem _appearance = default!; | ||
|
||
public override void Initialize() | ||
{ | ||
base.Initialize(); | ||
|
||
SubscribeLocalEvent<BorgSwitchableTypeComponent, AfterAutoHandleStateEvent>(AfterStateHandler); | ||
SubscribeLocalEvent<BorgSwitchableTypeComponent, ComponentStartup>(OnComponentStartup); | ||
} | ||
|
||
private void OnComponentStartup(Entity<BorgSwitchableTypeComponent> ent, ref ComponentStartup args) | ||
{ | ||
UpdateEntityAppearance(ent); | ||
} | ||
|
||
private void AfterStateHandler(Entity<BorgSwitchableTypeComponent> ent, ref AfterAutoHandleStateEvent args) | ||
{ | ||
UpdateEntityAppearance(ent); | ||
} | ||
|
||
protected override void UpdateEntityAppearance( | ||
Entity<BorgSwitchableTypeComponent> 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<SpriteMovementComponent>(entity); | ||
spriteMovement.NoMovementLayers.Clear(); | ||
spriteMovement.NoMovementLayers["movement"] = new PrototypeLayerData | ||
{ | ||
State = prototype.SpriteBodyState, | ||
}; | ||
spriteMovement.MovementLayers.Clear(); | ||
spriteMovement.MovementLayers["movement"] = new PrototypeLayerData | ||
{ | ||
State = movementState, | ||
}; | ||
} | ||
else | ||
{ | ||
RemComp<SpriteMovementComponent>(entity); | ||
} | ||
|
||
base.UpdateEntityAppearance(entity, prototype); | ||
} | ||
} |
Oops, something went wrong.