* Initial radial menu prototyping for the RCD * Radial UI buttons can send messages to the server * Beginning to update RCDSystem * RCD building system in progress * Further updates * Added extra effects, RCDSystem now reads RCD prototype data * Replacing tiles is instant, multiple constructions are allowed, deconstruction is broken * Added extra functionality to RadialContainers plus documentation * Fixed localization of RCD UI strings * Menu opens near cursor, added basic RCD * Avoiding merge conflict * Implemented atomized construction / deconstruction rules * Increased RCD ammo base charges * Moved input context definition to content * Removed obsoleted code * Updates to system * Switch machine and computer frames for electrical cabling * Added construction ghosts * Fixed issue with keybind detection code * Fixed RCD construction ghost mispredications * Code clean up * Updated deconstruction effects * RCDs effects don't rotate * Code clean up * Balancing for ammo counts * Code clean up * Added missing localized strings * More clean up * Made directional window handling more robust * Added documentation to radial menus and made them no longer dependent on Content * Made radial containers more robust * Further robustness to the radial menu * The RCD submenu buttons are only shown when the destination layer has at least one children * Expanded upon deconstructing plus construction balance * Fixed line endings * Updated list of RCD deconstructable entities. Now needs a component to deconstruct instead of a tag * Bug fixes * Revert unnecessary change * Updated RCD strings * Fixed bug * More fixes * Deconstructed tiles/subflooring convert to lattice instead * Fixed failed tests (Linux doesn't like invalid spritespecifer paths) * Fixing merge conflict * Updated airlock assembly * Fixing merge conflict * Fixing merge conflict * More fixing... * Removed erroneous project file change * Fixed string handling issue * Trying to fix merge conflict * Still fixing merge conflicts * Balancing * Hidden RCD construction ghosts when in 'build' mode * Fixing merge conflict * Implemented requested changes (Part 1) * Added more requested changes * Fix for failed test. Removed sussy null suppression * Made requested changes - custom construction ghost system was replaced * Fixing merge conflict * Fixed merge conflict * Fixed bug in RCD construction ghost validation * Fixing merge conflict * Merge conflict fixed * Made required update * Removed lingering RCD deconstruct tag * Fixing merge conflict * Merge conflict fixed * Made requested changes * Bug fixes and balancing * Made string names more consistent * Can no longer stack catwalks
123 lines
4.7 KiB
C#
123 lines
4.7 KiB
C#
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;
|
|
}
|
|
}
|