Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improved RCDs #22799

Merged
merged 92 commits into from
Mar 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
92 commits
Select commit Hold shift + click to select a range
61a30ce
Initial radial menu prototyping for the RCD
chromiumboy Dec 19, 2023
184a27a
Merge branch 'master' of https://github.com/space-wizards/space-stati…
chromiumboy Dec 19, 2023
9bfbc77
Radial UI buttons can send messages to the server
chromiumboy Dec 19, 2023
ac6a813
Beginning to update RCDSystem
chromiumboy Dec 19, 2023
eeefbee
RCD building system in progress
chromiumboy Dec 20, 2023
4328312
Further updates
chromiumboy Dec 21, 2023
eaaeeda
Added extra effects, RCDSystem now reads RCD prototype data
chromiumboy Dec 22, 2023
2887e48
Merge branch 'master' of https://github.com/space-wizards/space-stati…
chromiumboy Dec 22, 2023
20b4e34
Replacing tiles is instant, multiple constructions are allowed, decon…
chromiumboy Dec 22, 2023
b3f7b8a
Added extra functionality to RadialContainers plus documentation
chromiumboy Dec 23, 2023
1cf7410
Fixed localization of RCD UI strings
chromiumboy Dec 23, 2023
bba6432
Menu opens near cursor, added basic RCD
chromiumboy Dec 23, 2023
a061668
Merge branch 'master' of https://github.com/space-wizards/space-stati…
chromiumboy Dec 23, 2023
26f7895
Avoiding merge conflict
chromiumboy Jan 13, 2024
ceeb4e9
Merge branch 'master' of https://github.com/space-wizards/space-stati…
chromiumboy Jan 13, 2024
8254b03
Implemented atomized construction / deconstruction rules
chromiumboy Jan 15, 2024
3e74624
Increased RCD ammo base charges
chromiumboy Jan 15, 2024
03faad5
Moved input context definition to content
chromiumboy Jan 15, 2024
013c0bb
Removed obsoleted code
chromiumboy Jan 15, 2024
029b822
Updates to system
chromiumboy Jan 17, 2024
e8882b4
Switch machine and computer frames for electrical cabling
chromiumboy Jan 17, 2024
98d3b8f
Added construction ghosts
chromiumboy Jan 17, 2024
ed33882
Fixed issue with keybind detection code
chromiumboy Jan 17, 2024
5bcdd9f
Fixed RCD construction ghost mispredications
chromiumboy Jan 17, 2024
ecba541
Code clean up
chromiumboy Jan 17, 2024
e0d9d38
Updated deconstruction effects
chromiumboy Jan 17, 2024
52c40eb
RCDs effects don't rotate
chromiumboy Jan 17, 2024
b7f63f7
Code clean up
chromiumboy Jan 18, 2024
0746c90
Balancing for ammo counts
chromiumboy Jan 18, 2024
dcf4d18
Code clean up
chromiumboy Jan 18, 2024
e33ee9b
Added missing localized strings
chromiumboy Jan 18, 2024
6538cf4
More clean up
chromiumboy Jan 18, 2024
9bd7809
Made directional window handling more robust
chromiumboy Jan 18, 2024
c751359
Added documentation to radial menus and made them no longer dependent…
chromiumboy Jan 18, 2024
f3e5ac5
Made radial containers more robust
chromiumboy Jan 18, 2024
6fd8795
Further robustness to the radial menu
chromiumboy Jan 18, 2024
e9b0400
The RCD submenu buttons are only shown when the destination layer has…
chromiumboy Jan 19, 2024
f50ae7b
Expanded upon deconstructing plus construction balance
chromiumboy Jan 21, 2024
78115de
Fixed line endings
chromiumboy Jan 21, 2024
40207df
Merge branch 'master' of https://github.com/space-wizards/space-stati…
chromiumboy Jan 21, 2024
7be36ed
Updated list of RCD deconstructable entities. Now needs a component t…
chromiumboy Jan 22, 2024
95ccbd0
Bug fixes
chromiumboy Jan 23, 2024
94bb344
Merge branch 'master' of https://github.com/space-wizards/space-stati…
chromiumboy Jan 23, 2024
1e19778
Revert unnecessary change
chromiumboy Jan 23, 2024
dcfd690
Updated RCD strings
chromiumboy Jan 23, 2024
9d3c2d0
Fixed bug
chromiumboy Jan 23, 2024
4fd9666
More fixes
chromiumboy Jan 23, 2024
6d763e2
Deconstructed tiles/subflooring convert to lattice instead
chromiumboy Jan 25, 2024
05ef687
Fixed failed tests (Linux doesn't like invalid spritespecifer paths)
chromiumboy Jan 25, 2024
d92f806
Merge branch 'master' of https://github.com/space-wizards/space-stati…
chromiumboy Jan 25, 2024
f266e1b
Fixing merge conflict
chromiumboy Feb 1, 2024
15a4df1
Merge branch 'master' of https://github.com/space-wizards/space-stati…
chromiumboy Feb 1, 2024
37163f7
Updated airlock assembly
chromiumboy Feb 1, 2024
db24e32
Fixing merge conflict
chromiumboy Feb 2, 2024
21d81ae
Fixing merge conflict
chromiumboy Feb 2, 2024
20418bf
Merge conflict resolution?
chromiumboy Feb 2, 2024
1ccdfd6
More fixing...
chromiumboy Feb 2, 2024
257eb89
Removed erroneous project file change
chromiumboy Feb 6, 2024
476113a
Merge branch 'master' of https://github.com/space-wizards/space-stati…
chromiumboy Feb 6, 2024
5e2c2c6
Fixed string handling issue
chromiumboy Feb 6, 2024
f0f08d1
Trying to fix merge conflict
chromiumboy Feb 15, 2024
d88db8a
Merge branch 'master' of https://github.com/space-wizards/space-stati…
chromiumboy Feb 15, 2024
1746286
Still fixing merge conflicts
chromiumboy Feb 15, 2024
6238048
Balancing
chromiumboy Feb 15, 2024
0c9e93a
Hidden RCD construction ghosts when in 'build' mode
chromiumboy Feb 17, 2024
dabc9b0
Merge branch 'master' of https://github.com/space-wizards/space-stati…
chromiumboy Feb 23, 2024
c39cbf4
Fixing merge conflict
chromiumboy Mar 14, 2024
0b9eb69
Merge branch 'master' of https://github.com/space-wizards/space-stati…
chromiumboy Mar 14, 2024
ef68a7b
Implemented requested changes (Part 1)
chromiumboy Mar 14, 2024
f888d92
Added more requested changes
chromiumboy Mar 15, 2024
ac4154a
Fix for failed test. Removed sussy null suppression
chromiumboy Mar 15, 2024
903c0c2
Made requested changes - custom construction ghost system was replaced
chromiumboy Mar 18, 2024
1eebc28
Fixing merge conflict
chromiumboy Mar 18, 2024
a8e641a
Merge branch 'master' of https://github.com/space-wizards/space-stati…
chromiumboy Mar 18, 2024
d7d1b7d
Fixed merge conflict
chromiumboy Mar 18, 2024
8249007
Fixed bug in RCD construction ghost validation
chromiumboy Mar 18, 2024
f53054f
Fixing merge conflict
chromiumboy Mar 25, 2024
24f4ace
Merge branch 'master' of https://github.com/space-wizards/space-stati…
chromiumboy Mar 25, 2024
d73f485
Merge conflict fixed
chromiumboy Mar 25, 2024
9ca0ee9
Made required update
chromiumboy Mar 25, 2024
697ac74
Merge branch 'master' of https://github.com/space-wizards/space-stati…
chromiumboy Mar 26, 2024
76ac10c
Merge branch 'space-wizards:master' into rcd-with-radial-menu
chromiumboy Mar 26, 2024
e925a7c
Removed lingering RCD deconstruct tag
chromiumboy Mar 26, 2024
c6d36a8
Merge branch 'rcd-with-radial-menu' of https://github.com/chromiumboy…
chromiumboy Mar 26, 2024
0b964de
Fixing merge conflict
chromiumboy Mar 30, 2024
c59f860
Merge branch 'master' of https://github.com/space-wizards/space-stati…
chromiumboy Mar 30, 2024
688d6b6
Merge conflict fixed
chromiumboy Mar 30, 2024
2f476da
Merge branch 'master' of https://github.com/space-wizards/space-stati…
chromiumboy Mar 30, 2024
2f0ede9
Made requested changes
chromiumboy Mar 30, 2024
55545fd
Bug fixes and balancing
chromiumboy Mar 30, 2024
c7cd310
Made string names more consistent
chromiumboy Mar 31, 2024
b937d38
Can no longer stack catwalks
chromiumboy Mar 31, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Content.Client/Input/ContentContexts.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ public static void SetupContexts(IInputContextContainer contexts)
// Not in engine because the engine doesn't understand what a flipped object is
common.AddFunction(ContentKeyFunctions.EditorFlipObject);

// Not in engine so that the RCD can rotate objects
common.AddFunction(EngineKeyFunctions.EditorRotateObject);

var human = contexts.GetContext("human");
human.AddFunction(EngineKeyFunctions.MoveUp);
human.AddFunction(EngineKeyFunctions.MoveDown);
Expand Down
122 changes: 122 additions & 0 deletions Content.Client/RCD/AlignRCDConstruction.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
using System.Numerics;
using Content.Client.Gameplay;
using Content.Shared.Hands.Components;
using Content.Shared.Interaction;
using Content.Shared.RCD.Components;
using Content.Shared.RCD.Systems;
using Robust.Client.Placement;
using Robust.Client.Player;
using Robust.Client.State;
using Robust.Shared.Map;
using Robust.Shared.Map.Components;

namespace Content.Client.RCD;

public sealed class AlignRCDConstruction : PlacementMode
{
[Dependency] private readonly IEntityManager _entityManager = default!;
[Dependency] private readonly IMapManager _mapManager = default!;
[Dependency] private readonly SharedMapSystem _mapSystem = default!;
[Dependency] private readonly RCDSystem _rcdSystem = default!;
[Dependency] private readonly SharedTransformSystem _transformSystem = default!;
[Dependency] private readonly IPlayerManager _playerManager = default!;
[Dependency] private readonly IStateManager _stateManager = default!;

private const float SearchBoxSize = 2f;
private const float PlaceColorBaseAlpha = 0.5f;

private EntityCoordinates _unalignedMouseCoords = default;

/// <summary>
/// This placement mode is not on the engine because it is content specific (i.e., for the RCD)
/// </summary>
public AlignRCDConstruction(PlacementManager pMan) : base(pMan)
{
var dependencies = IoCManager.Instance!;
_entityManager = dependencies.Resolve<IEntityManager>();
_mapManager = dependencies.Resolve<IMapManager>();
_playerManager = dependencies.Resolve<IPlayerManager>();
_stateManager = dependencies.Resolve<IStateManager>();

_mapSystem = _entityManager.System<SharedMapSystem>();
_rcdSystem = _entityManager.System<RCDSystem>();
_transformSystem = _entityManager.System<SharedTransformSystem>();

ValidPlaceColor = ValidPlaceColor.WithAlpha(PlaceColorBaseAlpha);
}

public override void AlignPlacementMode(ScreenCoordinates mouseScreen)
{
_unalignedMouseCoords = ScreenToCursorGrid(mouseScreen);
MouseCoords = _unalignedMouseCoords.AlignWithClosestGridTile(SearchBoxSize, _entityManager, _mapManager);

var gridId = MouseCoords.GetGridUid(_entityManager);

if (!_entityManager.TryGetComponent<MapGridComponent>(gridId, out var mapGrid))
return;

CurrentTile = _mapSystem.GetTileRef(gridId.Value, mapGrid, MouseCoords);

float tileSize = mapGrid.TileSize;
GridDistancing = tileSize;

if (pManager.CurrentPermission!.IsTile)
{
MouseCoords = new EntityCoordinates(MouseCoords.EntityId, new Vector2(CurrentTile.X + tileSize / 2,
CurrentTile.Y + tileSize / 2));
}
else
{
MouseCoords = new EntityCoordinates(MouseCoords.EntityId, new Vector2(CurrentTile.X + tileSize / 2 + pManager.PlacementOffset.X,
CurrentTile.Y + tileSize / 2 + pManager.PlacementOffset.Y));
}
}

public override bool IsValidPosition(EntityCoordinates position)
{
var player = _playerManager.LocalSession?.AttachedEntity;

// If the destination is out of interaction range, set the placer alpha to zero
if (!_entityManager.TryGetComponent<TransformComponent>(player, out var xform))
return false;

if (!xform.Coordinates.InRange(_entityManager, _transformSystem, position, SharedInteractionSystem.InteractionRange))
{
InvalidPlaceColor = InvalidPlaceColor.WithAlpha(0);
return false;
}

// Otherwise restore the alpha value
else
{
InvalidPlaceColor = InvalidPlaceColor.WithAlpha(PlaceColorBaseAlpha);
}

// Determine if player is carrying an RCD in their active hand
if (!_entityManager.TryGetComponent<HandsComponent>(player, out var hands))
return false;

var heldEntity = hands.ActiveHand?.HeldEntity;

if (!_entityManager.TryGetComponent<RCDComponent>(heldEntity, out var rcd))
return false;

// Retrieve the map grid data for the position
if (!_rcdSystem.TryGetMapGridData(position, out var mapGridData))
return false;

// Determine if the user is hovering over a target
var currentState = _stateManager.CurrentState;

if (currentState is not GameplayStateBase screen)
return false;

var target = screen.GetClickedEntity(_unalignedMouseCoords.ToMap(_entityManager, _transformSystem));

// Determine if the RCD operation is valid or not
if (!_rcdSystem.IsRCDOperationStillValid(heldEntity.Value, rcd, mapGridData.Value, target, player.Value, false))
return false;

return true;
}
}
78 changes: 78 additions & 0 deletions Content.Client/RCD/RCDConstructionGhostSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
using Content.Shared.Hands.Components;
using Content.Shared.Interaction;
using Content.Shared.RCD;
using Content.Shared.RCD.Components;
using Content.Shared.RCD.Systems;
using Robust.Client.Placement;
using Robust.Client.Player;
using Robust.Shared.Enums;

namespace Content.Client.RCD;

public sealed class RCDConstructionGhostSystem : EntitySystem
{
[Dependency] private readonly IPlayerManager _playerManager = default!;
[Dependency] private readonly RCDSystem _rcdSystem = default!;
[Dependency] private readonly IPlacementManager _placementManager = default!;

private string _placementMode = typeof(AlignRCDConstruction).Name;
private Direction _placementDirection = default;

public override void Update(float frameTime)
{
base.Update(frameTime);

// Get current placer data
var placerEntity = _placementManager.CurrentPermission?.MobUid;
var placerProto = _placementManager.CurrentPermission?.EntityType;
var placerIsRCD = HasComp<RCDComponent>(placerEntity);

// Exit if erasing or the current placer is not an RCD (build mode is active)
if (_placementManager.Eraser || (placerEntity != null && !placerIsRCD))
return;

// Determine if player is carrying an RCD in their active hand
var player = _playerManager.LocalSession?.AttachedEntity;

if (!TryComp<HandsComponent>(player, out var hands))
return;

var heldEntity = hands.ActiveHand?.HeldEntity;

if (!TryComp<RCDComponent>(heldEntity, out var rcd))
{
// If the player was holding an RCD, but is no longer, cancel placement
if (placerIsRCD)
_placementManager.Clear();

return;
}

// Update the direction the RCD prototype based on the placer direction
if (_placementDirection != _placementManager.Direction)
{
_placementDirection = _placementManager.Direction;
RaiseNetworkEvent(new RCDConstructionGhostRotationEvent(GetNetEntity(heldEntity.Value), _placementDirection));
}

// If the placer has not changed, exit
_rcdSystem.UpdateCachedPrototype(heldEntity.Value, rcd);

if (heldEntity == placerEntity && rcd.CachedPrototype.Prototype == placerProto)
return;

// Create a new placer
var newObjInfo = new PlacementInformation
{
MobUid = heldEntity.Value,
PlacementOption = _placementMode,
EntityType = rcd.CachedPrototype.Prototype,
Range = (int) Math.Ceiling(SharedInteractionSystem.InteractionRange),
IsTile = (rcd.CachedPrototype.Mode == RcdMode.ConstructTile),
UseEditorContext = false,
};

_placementManager.Clear();
_placementManager.BeginPlacing(newObjInfo);
}
}
47 changes: 47 additions & 0 deletions Content.Client/RCD/RCDMenu.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<ui:RadialMenu xmlns="https://spacestation14.io"
xmlns:ui="clr-namespace:Content.Client.UserInterface.Controls"
xmlns:rcd="clr-namespace:Content.Client.RCD"
BackButtonStyleClass="RadialMenuBackButton"
CloseButtonStyleClass="RadialMenuCloseButton"
VerticalExpand="True"
HorizontalExpand="True"
MinSize="450 450">

<!-- Note: The min size of the window just determine how close to the edge of the screen the center of the radial menu can be placed -->
<!-- The radial menu will try to open so that its center is located where the player's cursor is currently -->

<!-- Entry layer (shows main categories) -->
<ui:RadialContainer Name="Main" VerticalExpand="True" HorizontalExpand="True" Radius="64" ReserveSpaceForHiddenChildren="False">
<ui:RadialMenuTextureButton StyleClasses="RadialMenuButton" SetSize="64 64" ToolTip="{Loc 'rcd-component-walls-and-flooring'}" TargetLayer="WallsAndFlooring" Visible="False">
<TextureRect VerticalAlignment="Center" HorizontalAlignment="Center" TextureScale="2 2" TexturePath="/Textures/Interface/Radial/RCD/walls_and_flooring.png"/>
</ui:RadialMenuTextureButton>
<ui:RadialMenuTextureButton StyleClasses="RadialMenuButton" SetSize="64 64" ToolTip="{Loc 'rcd-component-windows-and-grilles'}" TargetLayer="WindowsAndGrilles" Visible="False">
<TextureRect VerticalAlignment="Center" HorizontalAlignment="Center" TextureScale="2 2" TexturePath="/Textures/Interface/Radial/RCD/windows_and_grilles.png"/>
</ui:RadialMenuTextureButton>
<ui:RadialMenuTextureButton StyleClasses="RadialMenuButton" SetSize="64 64" ToolTip="{Loc 'rcd-component-airlocks'}" TargetLayer="Airlocks" Visible="False">
<TextureRect VerticalAlignment="Center" HorizontalAlignment="Center" TextureScale="2 2" TexturePath="/Textures/Interface/Radial/RCD/airlocks.png"/>
</ui:RadialMenuTextureButton>
<ui:RadialMenuTextureButton StyleClasses="RadialMenuButton" SetSize="64 64" ToolTip="{Loc 'rcd-component-electrical'}" TargetLayer="Electrical" Visible="False">
<TextureRect VerticalAlignment="Center" HorizontalAlignment="Center" TextureScale="2 2" TexturePath="/Textures/Interface/Radial/RCD/multicoil.png"/>
</ui:RadialMenuTextureButton>
<ui:RadialMenuTextureButton StyleClasses="RadialMenuButton" SetSize="64 64" ToolTip="{Loc 'rcd-component-lighting'}" TargetLayer="Lighting" Visible="False">
<TextureRect VerticalAlignment="Center" HorizontalAlignment="Center" TextureScale="2 2" TexturePath="/Textures/Interface/Radial/RCD/lighting.png"/>
</ui:RadialMenuTextureButton>
</ui:RadialContainer>

<!-- Walls and flooring -->
<ui:RadialContainer Name="WallsAndFlooring" VerticalExpand="True" HorizontalExpand="True" Radius="64"/>

<!-- Windows and grilles -->
<ui:RadialContainer Name="WindowsAndGrilles" VerticalExpand="True" HorizontalExpand="True" Radius="64"/>

<!-- Airlocks -->
<ui:RadialContainer Name="Airlocks" VerticalExpand="True" HorizontalExpand="True" Radius="64"/>

<!-- Computer and machine frames -->
<ui:RadialContainer Name="Electrical" VerticalExpand="True" HorizontalExpand="True" Radius="64"/>

<!-- Lighting -->
<ui:RadialContainer Name="Lighting" VerticalExpand="True" HorizontalExpand="True" Radius="64"/>

</ui:RadialMenu>
137 changes: 137 additions & 0 deletions Content.Client/RCD/RCDMenu.xaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
using Content.Client.UserInterface.Controls;
using Content.Shared.RCD;
using Content.Shared.RCD.Components;
using Robust.Client.AutoGenerated;
using Robust.Client.GameObjects;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.Prototypes;
using System.Numerics;

namespace Content.Client.RCD;

[GenerateTypedNameReferences]
public sealed partial class RCDMenu : RadialMenu
{
[Dependency] private readonly EntityManager _entManager = default!;
[Dependency] private readonly IPrototypeManager _protoManager = default!;

private readonly SpriteSystem _spriteSystem;

public event Action<ProtoId<RCDPrototype>>? SendRCDSystemMessageAction;

public RCDMenu(EntityUid owner, RCDMenuBoundUserInterface bui)
{
IoCManager.InjectDependencies(this);
RobustXamlLoader.Load(this);

_spriteSystem = _entManager.System<SpriteSystem>();

// Find the main radial container
var main = FindControl<RadialContainer>("Main");

if (main == null)
return;

// Populate secondary radial containers
if (!_entManager.TryGetComponent<RCDComponent>(owner, out var rcd))
return;

foreach (var protoId in rcd.AvailablePrototypes)
{
if (!_protoManager.TryIndex(protoId, out var proto))
continue;

if (proto.Mode == RcdMode.Invalid)
continue;

var parent = FindControl<RadialContainer>(proto.Category);

if (parent == null)
continue;

var name = Loc.GetString(proto.SetName);
name = char.ToUpper(name[0]) + name.Remove(0, 1);

var button = new RCDMenuButton()
{
StyleClasses = { "RadialMenuButton" },
SetSize = new Vector2(64f, 64f),
ToolTip = name,
ProtoId = protoId,
};

if (proto.Sprite != null)
{
var tex = new TextureRect()
{
VerticalAlignment = VAlignment.Center,
HorizontalAlignment = HAlignment.Center,
Texture = _spriteSystem.Frame0(proto.Sprite),
TextureScale = new Vector2(2f, 2f),
};

button.AddChild(tex);
}

parent.AddChild(button);

// Ensure that the button that transitions the menu to the associated category layer
// is visible in the main radial container (as these all start with Visible = false)
foreach (var child in main.Children)
{
var castChild = child as RadialMenuTextureButton;

if (castChild is not RadialMenuTextureButton)
continue;

if (castChild.TargetLayer == proto.Category)
{
castChild.Visible = true;
break;
}
}
}

// Set up menu actions
foreach (var child in Children)
AddRCDMenuButtonOnClickActions(child);

OnChildAdded += AddRCDMenuButtonOnClickActions;

SendRCDSystemMessageAction += bui.SendRCDSystemMessage;
}

private void AddRCDMenuButtonOnClickActions(Control control)
{
var radialContainer = control as RadialContainer;

if (radialContainer == null)
return;

foreach (var child in radialContainer.Children)
{
var castChild = child as RCDMenuButton;

if (castChild == null)
continue;

castChild.OnButtonUp += _ =>
{
SendRCDSystemMessageAction?.Invoke(castChild.ProtoId);
Close();
};
}
}
}

public sealed class RCDMenuButton : RadialMenuTextureButton
{
public ProtoId<RCDPrototype> ProtoId { get; set; }

public RCDMenuButton()
{

}
}
Loading
Loading