mirror of
https://github.com/WWhiteDreamProject/wwdpublic.git
synced 2026-04-28 19:17:53 +03:00
# Description This PR removes label duplicates from item names in order to make actual labels work properly and make them visible in vending machines' menus as well as loadout preferences. As we can see in Fig 1, the aluminium jug is not only labelled as "aluminium 10u" but contains "(aluminium 10u)" in the item name, which drives chemists homicidal when it comes to labelling the jugs. This issue also appears with other labelled items such as pill canisters in item preferences (see Fig 2), which led to a row of nameless pill canisters being present in our server's menu. My solution is to fetch the item's LabelComponent in the menu so this redundancy is no more needed. See Fig 3 for an example. The VendingMachineMenu.xaml.cs code fetches and localizes the text from the LabelComponent from the prototype the same way it fetches sprites, and in the LoadoutPreferenceSelector.xaml.cs the task is pretty straightforward since the item is spawned in the Nullspace anyway. --- - [x] Added label rendering for VendingMachineMenu.xaml.cs - [x] Stripped reagent jugs' names off their fake labels - [x] Added label rendering for LoadoutPreferenceSelector.xaml.cs - [x] Stripped pill canisters' names off their fake labels - [x] Reformatted pills *that do not have explicit descriptions* to match "pill (label)" format --- <!-- This is default collapsed, readers click to expand it and see all your media The PR media section can get very large at times, so this is a good way to keep it clean The title is written using HTML tags The title must be within the <summary> tags or you won't see it --> <details><summary><h1>Media</h1></summary> <p> Fig 1, the issue with ChemVend's reagent jugs:  Fig 2, the issue with pill canisters:  Fig 3, demonstration of the solution:  </p> </details> --- # Changelog 🆑 NeLepus - add: Added label rendering for vending machines & item preferences - tweak: Formatted pill without descriptions to follow "pill (label)" - remove: Fake label duplicates in reagent jugs and pill canisters (cherry picked from commit f0f9512b491fefa2416f661e8f6b20fab215fa2f)
302 lines
11 KiB
C#
302 lines
11 KiB
C#
using System.Linq;
|
|
using System.Numerics;
|
|
using System.Text;
|
|
using Content.Client.Guidebook;
|
|
using Content.Client.Paint;
|
|
using Content.Client.Players.PlayTimeTracking;
|
|
using Content.Client.Stylesheets;
|
|
using Content.Client.UserInterface.Systems.Guidebook;
|
|
using Content.Shared.Clothing.Loadouts.Prototypes;
|
|
using Content.Shared.Clothing.Loadouts.Systems;
|
|
using Content.Shared.Customization.Systems;
|
|
using Content.Shared.Labels.Components;
|
|
using Content.Shared.Paint;
|
|
using Content.Shared.Preferences;
|
|
using Content.Shared.Roles;
|
|
using Robust.Client.AutoGenerated;
|
|
using Robust.Client.Graphics;
|
|
using Robust.Client.UserInterface;
|
|
using Robust.Client.UserInterface.Controls;
|
|
using Robust.Client.UserInterface.CustomControls;
|
|
using Robust.Client.UserInterface.XAML;
|
|
using Robust.Shared.Configuration;
|
|
using Robust.Shared.Map;
|
|
using Robust.Shared.Prototypes;
|
|
using Robust.Shared.Timing;
|
|
using Robust.Shared.Utility;
|
|
|
|
namespace Content.Client.Lobby.UI;
|
|
|
|
|
|
[GenerateTypedNameReferences]
|
|
public sealed partial class LoadoutPreferenceSelector : Control
|
|
{
|
|
public const string DefaultLoadoutInfoGuidebook = "LoadoutInfo";
|
|
|
|
public EntityUid DummyEntityUid;
|
|
private readonly IEntityManager _entityManager;
|
|
|
|
public LoadoutPrototype Loadout { get; }
|
|
|
|
private LoadoutPreference _preference = null!;
|
|
public LoadoutPreference Preference
|
|
{
|
|
get => _preference;
|
|
set
|
|
{
|
|
_preference = value;
|
|
NameEdit.Text = value.CustomName ?? "";
|
|
DescriptionEdit.TextRope = new Rope.Leaf(value.CustomDescription ?? "");
|
|
ColorEdit.Color = Color.FromHex(value.CustomColorTint, Color.White);
|
|
if (value.CustomColorTint != null)
|
|
UpdatePaint(new(DummyEntityUid, _entityManager.GetComponent<PaintedComponent>(DummyEntityUid)), _entityManager);
|
|
HeirloomButton.Pressed = value.CustomHeirloom ?? false;
|
|
PreferenceButton.Pressed = value.Selected;
|
|
}
|
|
}
|
|
|
|
public bool Valid;
|
|
private bool _showUnusable;
|
|
public bool ShowUnusable
|
|
{
|
|
get => _showUnusable;
|
|
set
|
|
{
|
|
_showUnusable = value;
|
|
Visible = Valid && _wearable || _showUnusable;
|
|
PreferenceButton.RemoveStyleClass(StyleBase.ButtonDanger);
|
|
PreferenceButton.AddStyleClass(Valid ? "" : StyleBase.ButtonDanger);
|
|
}
|
|
}
|
|
|
|
private bool _wearable;
|
|
public bool Wearable
|
|
{
|
|
get => _wearable;
|
|
set
|
|
{
|
|
_wearable = value;
|
|
Visible = Valid && _wearable || _showUnusable;
|
|
PreferenceButton.RemoveStyleClass(StyleBase.ButtonCaution);
|
|
PreferenceButton.AddStyleClass(_wearable ? "" : StyleBase.ButtonCaution);
|
|
}
|
|
}
|
|
|
|
public event Action<LoadoutPreference>? PreferenceChanged;
|
|
|
|
|
|
public LoadoutPreferenceSelector(LoadoutPrototype loadout, JobPrototype highJob,
|
|
HumanoidCharacterProfile profile, ref Dictionary<string, EntityUid> entities,
|
|
IEntityManager entityManager, IPrototypeManager prototypeManager, IConfigurationManager configManager,
|
|
CharacterRequirementsSystem characterRequirementsSystem, JobRequirementsManager jobRequirementsManager)
|
|
{
|
|
RobustXamlLoader.Load(this);
|
|
|
|
_entityManager = entityManager;
|
|
Loadout = loadout;
|
|
|
|
// Show/hide the special menu and items depending on what's allowed
|
|
HeirloomButton.Visible = loadout.CanBeHeirloom;
|
|
SpecialMenu.Visible = Loadout.CustomName || Loadout.CustomDescription || Loadout.CustomColorTint;
|
|
SpecialName.Visible = Loadout.CustomName;
|
|
SpecialDescription.Visible = Loadout.CustomDescription;
|
|
SpecialColorTintToggle.Visible = Loadout.CustomColorTint;
|
|
|
|
|
|
SpriteView previewLoadout;
|
|
if (!entities.TryGetValue(loadout.ID + 0, out var dummyLoadoutItem))
|
|
{
|
|
// Get the first item in the loadout to be the preview
|
|
dummyLoadoutItem = entityManager.SpawnEntity(loadout.Items.First(), MapCoordinates.Nullspace);
|
|
entities.Add(loadout.ID + 0, dummyLoadoutItem);
|
|
|
|
// Create a sprite preview of the loadout item
|
|
previewLoadout = new SpriteView
|
|
{
|
|
Scale = new Vector2(1, 1),
|
|
OverrideDirection = Direction.South,
|
|
VerticalAlignment = VAlignment.Center,
|
|
SizeFlagsStretchRatio = 1,
|
|
};
|
|
previewLoadout.SetEntity(dummyLoadoutItem);
|
|
}
|
|
else
|
|
{
|
|
// Create a sprite preview of the loadout item
|
|
previewLoadout = new SpriteView
|
|
{
|
|
Scale = new Vector2(1, 1),
|
|
OverrideDirection = Direction.South,
|
|
VerticalAlignment = VAlignment.Center,
|
|
SizeFlagsStretchRatio = 1,
|
|
};
|
|
previewLoadout.SetEntity(dummyLoadoutItem);
|
|
}
|
|
DummyEntityUid = dummyLoadoutItem;
|
|
|
|
entityManager.EnsureComponent<AppearanceComponent>(dummyLoadoutItem);
|
|
entityManager.EnsureComponent<PaintedComponent>(dummyLoadoutItem, out var paint);
|
|
|
|
var loadoutName =
|
|
Loc.GetString($"loadout-name-{loadout.ID}") == $"loadout-name-{loadout.ID}"
|
|
? entityManager.GetComponent<MetaDataComponent>(dummyLoadoutItem).EntityName
|
|
: Loc.GetString($"loadout-name-{loadout.ID}");
|
|
|
|
// Display the item's label if it's present
|
|
if (entityManager.TryGetComponent(dummyLoadoutItem, out LabelComponent? labelComponent))
|
|
{
|
|
var itemLabel = labelComponent.CurrentLabel;
|
|
if (!string.IsNullOrEmpty(itemLabel))
|
|
loadoutName += $" ({Loc.GetString(itemLabel)})";
|
|
}
|
|
|
|
var loadoutDesc =
|
|
!Loc.TryGetString($"loadout-description-{loadout.ID}", out var description)
|
|
? entityManager.GetComponent<MetaDataComponent>(dummyLoadoutItem).EntityDescription
|
|
: description;
|
|
|
|
|
|
// Manage the info button
|
|
void UpdateGuidebook() => GuidebookButton.Visible =
|
|
prototypeManager.HasIndex<GuideEntryPrototype>(loadout.GuideEntry);
|
|
UpdateGuidebook();
|
|
prototypeManager.PrototypesReloaded += _ => UpdateGuidebook();
|
|
|
|
GuidebookButton.OnPressed += _ =>
|
|
{
|
|
if (!prototypeManager.TryIndex<GuideEntryPrototype>(loadout.GuideEntry, out var guideRoot))
|
|
return;
|
|
|
|
var guidebookController = UserInterfaceManager.GetUIController<GuidebookUIController>();
|
|
//TODO: Don't close the guidebook if its already open, just go to the correct page
|
|
guidebookController.ToggleGuidebook(
|
|
new Dictionary<string, GuideEntry> { { loadout.GuideEntry, guideRoot } },
|
|
includeChildren: true,
|
|
selected: loadout.GuideEntry);
|
|
};
|
|
|
|
// Create a checkbox to get the loadout
|
|
PreferenceButton.AddChild(new BoxContainer
|
|
{
|
|
Children =
|
|
{
|
|
new Label
|
|
{
|
|
Text = loadout.Cost.ToString(),
|
|
StyleClasses = { StyleBase.StyleClassLabelHeading },
|
|
MinWidth = 32,
|
|
MaxWidth = 32,
|
|
ClipText = true,
|
|
Margin = new Thickness(0, 0, 8, 0),
|
|
},
|
|
new PanelContainer
|
|
{
|
|
PanelOverride = new StyleBoxFlat { BackgroundColor = Color.FromHex("#2f2f2f") },
|
|
Children =
|
|
{
|
|
previewLoadout,
|
|
},
|
|
},
|
|
new Label
|
|
{
|
|
Text = loadoutName,
|
|
Margin = new Thickness(8, 0, 0, 0),
|
|
},
|
|
},
|
|
});
|
|
PreferenceButton.OnToggled += args =>
|
|
{
|
|
_preference.Selected = args.Pressed;
|
|
PreferenceChanged?.Invoke(Preference);
|
|
};
|
|
HeirloomButton.OnToggled += args =>
|
|
{
|
|
_preference.CustomHeirloom = args.Pressed ? true : null;
|
|
PreferenceChanged?.Invoke(Preference);
|
|
};
|
|
SaveButton.OnPressed += _ =>
|
|
{
|
|
_preference.CustomColorTint = SpecialColorTintToggle.Pressed ? ColorEdit.Color.ToHex() : null;
|
|
_preference.Selected = PreferenceButton.Pressed;
|
|
PreferenceChanged?.Invoke(Preference);
|
|
};
|
|
|
|
// Update prefs cache when something changes
|
|
NameEdit.OnTextChanged += _ =>
|
|
_preference.CustomName = string.IsNullOrEmpty(NameEdit.Text) ? null : NameEdit.Text;
|
|
DescriptionEdit.OnTextChanged += _ =>
|
|
_preference.CustomDescription = string.IsNullOrEmpty(Rope.Collapse(DescriptionEdit.TextRope)) ? null : Rope.Collapse(DescriptionEdit.TextRope);
|
|
SpecialColorTintToggle.OnToggled += args =>
|
|
ColorEdit.Visible = args.Pressed;
|
|
ColorEdit.OnColorChanged += _ =>
|
|
{
|
|
_preference.CustomColorTint = SpecialColorTintToggle.Pressed ? ColorEdit.Color.ToHex() : null;
|
|
UpdatePaint(new Entity<PaintedComponent>(dummyLoadoutItem, paint), entityManager);
|
|
};
|
|
|
|
NameEdit.PlaceHolder = loadoutName;
|
|
DescriptionEdit.Placeholder = new Rope.Leaf(Loc.GetString(loadoutDesc));
|
|
|
|
|
|
var tooltip = new StringBuilder();
|
|
// Add the loadout description to the tooltip if there is one
|
|
if (!string.IsNullOrEmpty(loadoutDesc))
|
|
tooltip.Append($"{Loc.GetString(loadoutDesc)}");
|
|
|
|
// Get requirement reasons
|
|
characterRequirementsSystem.CheckRequirementsValid(
|
|
loadout.Requirements, highJob, profile, new Dictionary<string, TimeSpan>(),
|
|
jobRequirementsManager.IsWhitelisted(), loadout,
|
|
entityManager, prototypeManager, configManager,
|
|
out var reasons);
|
|
|
|
// Add requirement reasons to the tooltip
|
|
foreach (var reason in reasons)
|
|
tooltip.Append($"\n{reason}");
|
|
|
|
// Combine the tooltip and format it in the checkbox supplier
|
|
if (tooltip.Length > 0)
|
|
{
|
|
var formattedTooltip = new Tooltip();
|
|
formattedTooltip.SetMessage(FormattedMessage.FromMarkupPermissive(tooltip.ToString()));
|
|
PreferenceButton.TooltipSupplier = _ => formattedTooltip;
|
|
}
|
|
}
|
|
|
|
private bool _initialized;
|
|
protected override void FrameUpdate(FrameEventArgs args)
|
|
{
|
|
if (_initialized || SpecialMenu.Heading == null)
|
|
return;
|
|
|
|
// Move the special editor
|
|
var heading = SpecialMenu.Heading;
|
|
heading.Orphan();
|
|
ButtonGroup.AddChild(heading);
|
|
GuidebookButton.Orphan();
|
|
ButtonGroup.AddChild(GuidebookButton);
|
|
|
|
// These guys are here too for reasons
|
|
HeadingButton.SetHeight = HeirloomButton.SetHeight = GuidebookButton.SetHeight = PreferenceButton.Size.Y;
|
|
SpecialColorTintToggle.Pressed = ColorEdit.Visible = _preference.CustomColorTint != null;
|
|
|
|
_initialized = true;
|
|
}
|
|
|
|
|
|
private void UpdatePaint(Entity<PaintedComponent> entity, IEntityManager entityManager)
|
|
{
|
|
if (_preference.CustomColorTint != null)
|
|
{
|
|
entity.Comp.Color = Color.FromHex(_preference.CustomColorTint);
|
|
entity.Comp.Enabled = true;
|
|
}
|
|
else
|
|
entity.Comp.Enabled = false;
|
|
|
|
var app = entityManager.System<SharedAppearanceSystem>();
|
|
app.TryGetData(entity, PaintVisuals.Painted, out bool value);
|
|
app.SetData(entity, PaintVisuals.Painted, !value);
|
|
}
|
|
}
|