using System.Linq; using Content.Server.Construction.Components; using Content.Shared.Construction.Components; using Content.Shared.Construction.Prototypes; using Content.Shared.Examine; using Content.Shared.Stacks; using Content.Shared.Verbs; using Robust.Shared.Utility; namespace Content.Server.Construction; //Uses base namespace to extend ConstructionSystem behaviour // Adopted from Wizard's Den's abandoned ConstructionSystem machine part system. public struct MachinePartState { public MachinePartComponent Part; public StackComponent? Stack; // If item is a stack, return the count in the stack, otherwise it's a singular, non-stackable part public int Quantity() { return Stack?.Count ?? 1; } } public sealed partial class ConstructionSystem { [Dependency] ExamineSystemShared _examineSystem = default!; private void InitializeMachineUpgrades() { SubscribeLocalEvent>(OnMachineExaminableVerb); } private void OnMachineExaminableVerb(EntityUid uid, MachineComponent component, GetVerbsEvent args) { if (!args.CanInteract || !args.CanAccess) return; var markup = new FormattedMessage(); RaiseLocalEvent(uid, new UpgradeExamineEvent(ref markup)); if (markup.IsEmpty) return; // Not upgradable. if(!FormattedMessage.TryFromMarkup(markup.ToMarkup().TrimEnd('\n'), out markup)) // Cursed workaround to https://github.com/space-wizards/RobustToolbox/issues/3371 { markup = FormattedMessage.Empty; // Frontier: attempt sane error handling } var verb = new ExamineVerb() { Act = () => { _examineSystem.SendExamineTooltip(args.User, uid, markup, getVerbs: false, centerAtCursor: false); }, Text = Loc.GetString("machine-upgrade-examinable-verb-text"), Message = Loc.GetString("machine-upgrade-examinable-verb-message"), Category = VerbCategory.Examine, Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/VerbIcons/pickup.svg.192dpi.png")) }; args.Verbs.Add(verb); } // Frontier: return type changed to include stack info public List GetAllParts(EntityUid uid, MachineComponent? component = null) { if (!Resolve(uid, ref component)) return new List(); return GetAllParts(component); } // Frontier: return type changed to include stack info public List GetAllParts(MachineComponent component) { var parts = new List(); foreach (var entity in component.PartContainer.ContainedEntities) { if (GetMachinePartState(entity, out var partState)) parts.Add(partState); } return parts; } public bool GetMachinePartState(EntityUid uid, out MachinePartState state) { state = new MachinePartState(); MachinePartComponent? part; if (TryComp(uid, out part) && part is not null) state.Part = part; else return false; TryComp(uid, out state.Stack); return true; } public Dictionary GetPartsRatings(List partStates) { var output = new Dictionary(); foreach (var type in _prototypeManager.EnumeratePrototypes()) { var amount = 0f; var sumRating = 0f; foreach (var state in partStates.Where(part => part.Part.PartType == type.ID)) { amount += state.Quantity(); sumRating += state.Part.Rating * state.Quantity(); } var rating = amount != 0 ? sumRating / amount : 1.0f; output.Add(type.ID, rating); } return output; } public void RefreshParts(EntityUid uid, MachineComponent component) { var parts = GetAllParts(component); EntityManager.EventBus.RaiseLocalEvent(uid, new RefreshPartsEvent { Parts = parts, PartRatings = GetPartsRatings(parts), }, true); } } public sealed class RefreshPartsEvent : EntityEventArgs { public IReadOnlyList Parts = new List(); // Frontier: MachinePartComponent PartRatings = new Dictionary(); } public sealed class UpgradeExamineEvent : EntityEventArgs { private FormattedMessage _message; public UpgradeExamineEvent(ref FormattedMessage message) { _message = message; } /// /// Add a line to the upgrade examine tooltip with a percentage-based increase or decrease. /// public void AddPercentageUpgrade(string upgradedLocId, float multiplier) { var percent = Math.Round(100 * MathF.Abs(multiplier - 1), 2); var locId = multiplier switch { < 1 => "machine-upgrade-decreased-by-percentage", 1 or float.NaN => "machine-upgrade-not-upgraded", > 1 => "machine-upgrade-increased-by-percentage", }; var upgraded = Loc.GetString(upgradedLocId); this._message.TryAddMarkup(Loc.GetString(locId, ("upgraded", upgraded), ("percent", percent)) + '\n', out _); // Frontier: AddMarkup /// Add a line to the upgrade examine tooltip with a numeric increase or decrease. /// public void AddNumberUpgrade(string upgradedLocId, int number) { var difference = Math.Abs(number); var locId = number switch { < 0 => "machine-upgrade-decreased-by-amount", 0 => "machine-upgrade-not-upgraded", > 0 => "machine-upgrade-increased-by-amount", }; var upgraded = Loc.GetString(upgradedLocId); this._message.TryAddMarkup(Loc.GetString(locId, ("upgraded", upgraded), ("difference", difference)) + '\n', out _); // Frontier: AddMarkup