* Add the chameleon controller implant * address the issues (Git please dont kill me) * Address the review and fix some merge conflicts! * Cleanup * Add use delay * Silly mistakes * Making a PR at 2 am: Gone wrong * Predict use delay and disable the buttons until you can choose another * First phase custom clothing * Better system, now relays to agent id and mindshield. Chameleon loadouts are a lot better to work with as well * Address the review! No more evil goto * Slams way is better I should have read more closely xD * Some of the jobs * Add to Cargo, CentComm, Service, Passenger, Ninja, Cluwne, Wizard + Minor changes to existing; Add chameleon to bandanas, medals, jugsuits and HUDs * Add everything else * Fix test * Job name * This looks better * Add department organization * Minor cleanup * Added some mindshields * Remove redudent comment and change funcion name to be clearer * Fix cluwne outfit * fix merge conflicts --------- Co-authored-by: SlamBamActionman <slambamactionman@gmail.com>
158 lines
5.2 KiB
C#
158 lines
5.2 KiB
C#
using System.Linq;
|
|
using System.Numerics;
|
|
using Content.Client.Roles;
|
|
using Content.Client.Stylesheets;
|
|
using Content.Client.UserInterface.Controls;
|
|
using Content.Shared.Implants;
|
|
using Content.Shared.StatusIcon;
|
|
using Robust.Client.AutoGenerated;
|
|
using Robust.Client.GameObjects;
|
|
using Robust.Client.UserInterface.Controls;
|
|
using Robust.Client.UserInterface.XAML;
|
|
using Robust.Shared.Prototypes;
|
|
using Robust.Shared.Timing;
|
|
|
|
namespace Content.Client.Implants.UI;
|
|
|
|
[GenerateTypedNameReferences]
|
|
public sealed partial class ChameleonControllerMenu : FancyWindow
|
|
{
|
|
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
|
[Dependency] private readonly IEntityManager _entityManager = default!;
|
|
private readonly SpriteSystem _sprite;
|
|
private readonly JobSystem _job;
|
|
|
|
// List of all the job protos that you can select!
|
|
private IEnumerable<ChameleonOutfitPrototype> _outfits;
|
|
|
|
// Lock the UI until this time
|
|
public DateTime? _lockedUntil;
|
|
|
|
private static readonly ProtoId<JobIconPrototype> UnknownIcon = "JobIconUnknown";
|
|
private static readonly LocId UnknownDepartment = "department-Unknown";
|
|
|
|
public event Action<ProtoId<ChameleonOutfitPrototype>>? OnJobSelected;
|
|
|
|
public ChameleonControllerMenu()
|
|
{
|
|
RobustXamlLoader.Load(this);
|
|
IoCManager.InjectDependencies(this);
|
|
_sprite = _entityManager.System<SpriteSystem>();
|
|
_job = _entityManager.System<JobSystem>();
|
|
|
|
_outfits = _prototypeManager.EnumeratePrototypes<ChameleonOutfitPrototype>();
|
|
|
|
UpdateGrid();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Fill the grid with the correct job icons and buttons.
|
|
/// </summary>
|
|
/// <param name="disabled">Set to true to disable all the buttons.</param>
|
|
public void UpdateGrid(bool disabled = false)
|
|
{
|
|
Grid.RemoveAllChildren();
|
|
|
|
// Dictionary to easily put outfits in departments.
|
|
// Department name -> UI element holding that department.
|
|
var departments = new Dictionary<string, BoxContainer>();
|
|
|
|
departments.Add(UnknownDepartment, CreateDepartment(UnknownDepartment));
|
|
|
|
// Go through every outfit and add them to the correct department.
|
|
foreach (var outfit in _outfits)
|
|
{
|
|
_prototypeManager.TryIndex(outfit.Job, out var jobProto);
|
|
|
|
var name = outfit.LoadoutName ?? outfit.Name ?? jobProto?.Name ?? "Prototype has no name or job.";
|
|
|
|
var jobIconId = outfit.Icon ?? jobProto?.Icon ?? UnknownIcon;
|
|
var jobIconProto = _prototypeManager.Index(jobIconId);
|
|
|
|
var outfitButton = CreateOutfitButton(disabled, name, jobIconProto, outfit.ID);
|
|
|
|
if (outfit.Job != null && _job.TryGetLowestWeightDepartment(outfit.Job, out var departmentPrototype))
|
|
{
|
|
if (!departments.ContainsKey(departmentPrototype.Name))
|
|
departments.Add(departmentPrototype.Name, CreateDepartment(departmentPrototype.Name));
|
|
|
|
departments[departmentPrototype.Name].AddChild(outfitButton);
|
|
}
|
|
else
|
|
{
|
|
departments[UnknownDepartment].AddChild(outfitButton);
|
|
}
|
|
}
|
|
|
|
// Sort the departments by their weight.
|
|
var departmentList = departments.ToList();
|
|
departmentList.Sort((a, b) => a.Value.ChildCount.CompareTo(b.Value.ChildCount));
|
|
|
|
// Actually add the departments to the window.
|
|
foreach (var department in departmentList)
|
|
{
|
|
Grid.AddChild(department.Value);
|
|
}
|
|
}
|
|
|
|
private BoxContainer CreateDepartment(string name)
|
|
{
|
|
var departmentContainer = new BoxContainer
|
|
{
|
|
Orientation = BoxContainer.LayoutOrientation.Vertical,
|
|
};
|
|
departmentContainer.AddChild(new Label
|
|
{
|
|
Text = Loc.GetString(name),
|
|
});
|
|
|
|
return departmentContainer;
|
|
}
|
|
|
|
private BoxContainer CreateOutfitButton(bool disabled, string name, JobIconPrototype jobIconProto, ProtoId<ChameleonOutfitPrototype> outfitProto)
|
|
{
|
|
var outfitButton = new BoxContainer();
|
|
|
|
var button = new Button
|
|
{
|
|
HorizontalExpand = true,
|
|
StyleClasses = {StyleBase.ButtonSquare},
|
|
ToolTip = Loc.GetString(name),
|
|
Text = Loc.GetString(name),
|
|
Margin = new Thickness(0, 0, 15, 0),
|
|
Disabled = disabled,
|
|
};
|
|
|
|
var jobIconTexture = new TextureRect
|
|
{
|
|
Texture = _sprite.Frame0(jobIconProto.Icon),
|
|
TextureScale = new Vector2(2.5f, 2.5f),
|
|
Stretch = TextureRect.StretchMode.KeepCentered,
|
|
Margin = new Thickness(0, 0, 5, 0),
|
|
};
|
|
|
|
outfitButton.AddChild(jobIconTexture);
|
|
outfitButton.AddChild(button);
|
|
|
|
button.OnPressed += _ => JobButtonPressed(outfitProto);
|
|
|
|
return outfitButton;
|
|
}
|
|
|
|
private void JobButtonPressed(ProtoId<ChameleonOutfitPrototype> outfit)
|
|
{
|
|
OnJobSelected?.Invoke(outfit);
|
|
}
|
|
|
|
protected override void FrameUpdate(FrameEventArgs args)
|
|
{
|
|
base.FrameUpdate(args);
|
|
|
|
if (_lockedUntil == null || DateTime.Now < _lockedUntil)
|
|
return;
|
|
|
|
_lockedUntil = null;
|
|
UpdateGrid();
|
|
}
|
|
}
|