using Content.Client.Construction; using Content.Client.UserInterface.Controls; using Content.Shared.Construction.Prototypes; using Robust.Client.AutoGenerated; using Robust.Client.GameObjects; using Robust.Client.Graphics; using Robust.Client.UserInterface.Controls; using Robust.Client.UserInterface.XAML; using Robust.Client.UserInterface; using Robust.Shared.Prototypes; namespace Content.Client._Offbrand.Surgery; public record SurgeryListData(ConstructionPrototype Construction) : ListData; [GenerateTypedNameReferences] public sealed partial class SurgeryGuideMenu : FancyWindow { [Dependency] private readonly IEntityManager _entityManager = default!; [Dependency] private readonly IPrototypeManager _prototypeManager = default!; private readonly ConstructionSystem _construction = default!; private readonly SpriteSystem _sprite = default!; public event Action>? OnSurgerySelected; public event Action? OnCleanUp; private ConstructionPrototype? _selectedSurgery; public string Category = string.Empty; public SurgeryGuideMenu() { RobustXamlLoader.Load(this); IoCManager.InjectDependencies(this); _sprite = _entityManager.System(); _construction = _entityManager.System(); _construction.ConstructionGuideAvailable += GuideAvailable; BackButton.OnPressed += _ => { SurgeriesContainer.Visible = true; StepsContainer.Visible = false; }; PerformButton.OnPressed += _ => { if (_selectedSurgery is not { } surgery) return; OnSurgerySelected?.Invoke(surgery.ID); }; CleanUp.OnPressed += _ => OnCleanUp?.Invoke(); PossibleSurgeries.GenerateItem += GenerateButton; PossibleSurgeries.ItemKeyBindDown += OnSelectSurgery; } protected override void ExitedTree() { _construction.ConstructionGuideAvailable -= GuideAvailable; } private void GuideAvailable(object? sender, string id) { if (_selectedSurgery?.ID != id) return; RefreshSteps(); } private void OnSelectSurgery(GUIBoundKeyEventArgs args, ListData data) { if (data is not SurgeryListData entry) return; SurgeriesContainer.Visible = false; StepsContainer.Visible = true; _selectedSurgery = entry.Construction; SurgeryName.Text = Loc.GetString(entry.Construction.SetName!.Value); SurgeryDescription.Text = Loc.GetString(entry.Construction.SetDescription!.Value); RefreshSteps(); } private void RefreshSteps() { StepsList.Clear(); if (_selectedSurgery is null || _construction.GetGuide(_selectedSurgery) is not { } guide) return; foreach (var entry in guide.Entries) { var text = entry.Arguments != null ? Loc.GetString(entry.Localization, entry.Arguments) : Loc.GetString(entry.Localization); if (entry.EntryNumber is { } number) { text = Loc.GetString("construction-presenter-step-wrapper", ("step-number", number), ("text", text)); } text = text.PadLeft(text.Length + entry.Padding); var icon = entry.Icon != null ? _sprite.Frame0(entry.Icon) : Texture.Transparent; StepsList.AddItem(text, icon, false); } } private void GenerateButton(ListData data, ListContainerButton button) { if (data is not SurgeryListData entry) return; button.AddChild(new Label() { Text = Loc.GetString(entry.Construction.SetName!.Value) }); button.ToolTip = Loc.GetString(entry.Construction.SetDescription!.Value); button.AddStyleClass("ButtonSquare"); } public void Populate() { var listData = new List(); foreach (var proto in _prototypeManager.EnumeratePrototypes()) { if (proto.Category != Category) continue; listData.Add(new SurgeryListData(proto)); } listData.Sort((a, b) => { if (a.Construction.SetName is not { } aName) throw new InvalidOperationException($"Construction {a.Construction.ID} does not have a name"); if (b.Construction.SetName is not { } bName) throw new InvalidOperationException($"Construction {b.Construction.ID} does not have a name"); return string.Compare(Loc.GetString(aName), Loc.GetString(bName), StringComparison.InvariantCulture); }); PossibleSurgeries.PopulateList(listData); } }