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

Hotfixmod #601

Draft
wants to merge 12 commits into
base: master
Choose a base branch
from
  •  
  •  
  •  
39 changes: 39 additions & 0 deletions Content.Client/ADT/Modsuits/UI/ModSuitBoundUserInterface.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using Content.Shared.ADT.ModSuits;
using Robust.Client.Graphics;
using Robust.Client.Input;
using Robust.Client.UserInterface;

namespace Content.Client.ADT.Modsuits.UI;

public sealed class ModSuitBoundUserInterface : BoundUserInterface
{
[Dependency] private readonly IClyde _displayManager = default!;
[Dependency] private readonly IInputManager _inputManager = default!;

private IEntityManager _entityManager;
private ModSuitRadialMenu? _menu;

public ModSuitBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey)
{
IoCManager.InjectDependencies(this);
_entityManager = IoCManager.Resolve<IEntityManager>();
}

protected override void Open()
{
base.Open();

_menu = this.CreateWindow<ModSuitRadialMenu>();
_menu.SetEntity(Owner);
_menu.SendToggleClothingMessageAction += SendModSuitMessage;

var vpSize = _displayManager.ScreenSize;
_menu.OpenCentered();
}

private void SendModSuitMessage(EntityUid uid)
{
var message = new ModSuitUiMessage(_entityManager.GetNetEntity(uid));
SendPredictedMessage(message);
}
}
13 changes: 13 additions & 0 deletions Content.Client/ADT/Modsuits/UI/ModSuitRadialMenu.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<ui:RadialMenu xmlns="https://spacestation14.io"
xmlns:ui="clr-namespace:Content.Client.UserInterface.Controls"
BackButtonStyleClass="RadialMenuBackButton"
CloseButtonStyleClass="RadialMenuCloseButton"
VerticalExpand="True"
HorizontalExpand="True"
MinSize="450 450">

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

</ui:RadialMenu>
102 changes: 102 additions & 0 deletions Content.Client/ADT/Modsuits/UI/ModSuitRadialMenu.xaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
using Content.Client.UserInterface.Controls;
using Content.Shared.ADT.ModSuits;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML;
using System.Numerics;

namespace Content.Client.ADT.Modsuits.UI;

public sealed partial class ModSuitRadialMenu : RadialMenu
{
[Dependency] private readonly EntityManager _entityManager = default!;

public event Action<EntityUid>? SendToggleClothingMessageAction;

public EntityUid Entity { get; set; }

public ModSuitRadialMenu()
{
IoCManager.InjectDependencies(this);
RobustXamlLoader.Load(this);
}

public void SetEntity(EntityUid uid)
{
Entity = uid;
RefreshUI();
}

public void RefreshUI()
{
var main = FindControl<RadialContainer>("Main");

if (!_entityManager.TryGetComponent<ModSuitComponent>(Entity, out var clothing))
return;

var clothingContainer = clothing.Container;

if (clothingContainer == null)
return;

foreach(var attached in clothing.ClothingUids)
{
// Change tooltip text if attached clothing is toggle/untoggled
var tooltipText = Loc.GetString("modsuit-clothing-unattach-tooltip");

if (clothingContainer.Contains(attached.Key))
tooltipText = Loc.GetString("modsuit-clothing-attach-tooltip");

var button = new ModSuitRadialMenuButton()
{
StyleClasses = { "RadialMenuButton" },
SetSize = new Vector2(64, 64),
ToolTip = tooltipText,
AttachedClothingId = attached.Key
};

var entProtoView = new EntityPrototypeView()
{
SetSize = new Vector2(48, 48),
VerticalAlignment = VAlignment.Center,
HorizontalAlignment = HAlignment.Center,
Stretch = SpriteView.StretchMode.Fill
};

entProtoView.SetEntity(attached.Key);

button.AddChild(entProtoView);
main.AddChild(button);
}

AddModSuitMenuButtonOnClickAction(main);
}

private void AddModSuitMenuButtonOnClickAction(Control control)
{
var mainControl = control as RadialContainer;

if (mainControl == null)
return;

foreach (var child in mainControl.Children)
{
var castChild = child as ModSuitRadialMenuButton;

if (castChild == null)
return;

castChild.OnButtonDown += _ =>
{
SendToggleClothingMessageAction?.Invoke(castChild.AttachedClothingId);
mainControl.DisposeAllChildren();
RefreshUI();
};
}
}
}

public sealed class ModSuitRadialMenuButton : RadialMenuTextureButton
{
public EntityUid AttachedClothingId { get; set; }
}
97 changes: 97 additions & 0 deletions Content.Shared/ADT/Modsuit/Components/ModSuitComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
using Content.Shared.Inventory;
using Robust.Shared.Containers;
using Robust.Shared.GameStates;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;

namespace Content.Shared.ADT.ModSuits;

/// <summary>
/// This component gives an item an action that will equip or un-equip some clothing e.g.
/// </summary>
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
public sealed partial class ModSuitComponent : Component
{
public const string DefaultClothingContainerId = "modsuit-part";

/// <summary>
/// Action used to toggle the clothing on or off.
/// </summary>
[DataField, AutoNetworkedField]
public EntProtoId Action = "ActionToggleSuitPiece";

[DataField, AutoNetworkedField]
public EntityUid? ActionEntity;

/// <summary>
/// Dictionary of inventory slots and entity prototypes to spawn into the clothing container.
/// </summary>
[DataField(required: true), AutoNetworkedField]
public Dictionary<string, EntProtoId> ClothingPrototypes = default!;

/// <summary>
/// Dictionary of clothing uids and slots
/// </summary>
[DataField, AutoNetworkedField]
public Dictionary<EntityUid, string> ClothingUids = new();

/// <summary>
/// The inventory slot flags required for this component to function.
/// </summary>
[DataField("requiredSlot"), AutoNetworkedField]
public SlotFlags RequiredFlags = SlotFlags.OUTERCLOTHING;

/// <summary>
/// The container that the clothing is stored in when not equipped.
/// </summary>
[DataField, AutoNetworkedField]
public string ContainerId = DefaultClothingContainerId;

[ViewVariables]
public Container? Container;

/// <summary>
/// Time it takes for this clothing to be toggled via the stripping menu verbs. Null prevents the verb from even showing up.
/// </summary>
[DataField, AutoNetworkedField]
public TimeSpan? StripDelay = TimeSpan.FromSeconds(3);

/// <summary>
/// Text shown in the toggle-clothing verb. Defaults to using the name of the <see cref="ActionEntity"/> action.
/// </summary>
[DataField, AutoNetworkedField]
public string? VerbText;

/// <summary>
/// If true it will block unequip of this entity until all attached clothing are removed
/// </summary>
[DataField, AutoNetworkedField]
public bool BlockUnequipWhenAttached = true;

/// <summary>
/// If true all attached will replace already equipped clothing on equip attempt
/// </summary>
[DataField, AutoNetworkedField]
public bool ReplaceCurrentClothing = true;

[DataField]
[ViewVariables(VVAccess.ReadWrite)]
public int ToggleClothingDoAfter = 7;
}

[Serializable, NetSerializable]
public enum ToggleModSuitUiKey : byte
{
Key
}

[Serializable, NetSerializable]
public sealed class ModSuitUiMessage : BoundUserInterfaceMessage
{
public NetEntity AttachedClothingUid;

public ModSuitUiMessage(NetEntity attachedClothingUid)
{
AttachedClothingUid = attachedClothingUid;
}
}
38 changes: 38 additions & 0 deletions Content.Shared/ADT/Modsuit/Components/ModSuitModComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
using Robust.Shared.GameStates;
using Robust.Shared.Serialization;
using Content.Shared.Item.ItemToggle;
using Robust.Shared.GameStates;
using Robust.Shared.Prototypes;

namespace Content.Shared.ADT.ModSuits;

[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
public sealed partial class ModSuitModComponent : Component
{
/// <summary>
/// The container that the clothing is stored in when not equipped.
/// </summary>
[DataField, AutoNetworkedField]
public string Slot = "head";

/// <summary>
/// The components to add when activated.
/// </summary>
[DataField(required: true)]
public ComponentRegistry Components = new();

/// <summary>
/// The components to remove when deactivated.
/// If this is null <see cref="Components"/> is reused.
/// </summary>
[DataField]
public ComponentRegistry? RemoveComponents;

/// <summary>
/// The container that the clothing is stored in when not equipped.
/// </summary>
[DataField, AutoNetworkedField]
public float SpeedMod = -0.01f;

public bool Inserted = false;
}
32 changes: 32 additions & 0 deletions Content.Shared/ADT/Modsuit/Components/ModSuitPartComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using Robust.Shared.Containers;
using Robust.Shared.GameStates;

namespace Content.Shared.ADT.ModSuits;

/// <summary>
/// This component indicates that this clothing is attached to some other entity with a <see
/// cref="MODSuitComponent"/>. When unequipped, this entity should be returned to the entity that it is
/// attached to, rather than being dumped on the floor or something like that. Intended for use with hardsuits and
/// hardsuit helmets.
/// </summary>
[Access(typeof(ModSuitSystem))]
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
public sealed partial class ModPartComponent : Component
{
public const string DefaultClothingContainerId = "replaced-clothing";

/// <summary>
/// The Id of the piece of clothing that this entity belongs to.
/// </summary>
[DataField, AutoNetworkedField]
public EntityUid AttachedUid;

/// <summary>
/// Container ID for clothing that will be replaced with this one
/// </summary>
[DataField, AutoNetworkedField]
public string ClothingContainerId = DefaultClothingContainerId;

[ViewVariables, NonSerialized]
public ContainerSlot? ClothingContainer;
}
Loading
Loading