6
StarHorizon_Public/Content.Client/Xenoarchaeology/Ui/AnalysisConsoleMenu.xaml.cs
2026-01-24 12:49:55 +03:00

250 lines
8.8 KiB
C#

using System.Text;
using Content.Client.Message;
using Content.Client.Resources;
using Content.Client.UserInterface.Controls;
using Content.Client.Xenoarchaeology.Artifact;
using Content.Client.Xenoarchaeology.Equipment;
using Content.Shared.Xenoarchaeology.Artifact.Components;
using Content.Shared.Xenoarchaeology.Equipment.Components;
using Robust.Client.Audio;
using Robust.Client.AutoGenerated;
using Robust.Client.Graphics;
using Robust.Client.ResourceManagement;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.Audio;
using Robust.Shared.Configuration;
using Robust.Shared.Timing;
using Robust.Shared.Utility;
namespace Content.Client.Xenoarchaeology.Ui;
[GenerateTypedNameReferences]
public sealed partial class AnalysisConsoleMenu : FancyWindow
{
private static readonly TimeSpan ExtractInfoDisplayForDuration = TimeSpan.FromSeconds(3);
[Dependency] private readonly IEntityManager _ent = default!;
[Dependency] private readonly IResourceCache _resCache = default!;
[Dependency] private readonly IGameTiming _timing = default!;
private readonly ArtifactAnalyzerSystem _artifactAnalyzer;
private readonly XenoArtifactSystem _xenoArtifact;
private readonly AudioSystem _audio;
private readonly MetaDataSystem _meta = default!;
private Entity<AnalysisConsoleComponent> _owner;
private Entity<XenoArtifactNodeComponent>? _currentNode;
private TimeSpan? _hideExtractInfoIn;
private int _extractionSum;
public event Action? OnServerSelectionButtonPressed;
public event Action? OnExtractButtonPressed;
public AnalysisConsoleMenu()
{
RobustXamlLoader.Load(this);
IoCManager.InjectDependencies(this);
_xenoArtifact = _ent.System<XenoArtifactSystem>();
_artifactAnalyzer = _ent.System<ArtifactAnalyzerSystem>();
_audio = _ent.System<AudioSystem>();
_meta = _ent.System<MetaDataSystem>();
if (BackPanel.PanelOverride is StyleBoxTexture tex)
tex.Texture = _resCache.GetTexture("/Textures/Interface/Nano/button.svg.96dpi.png");
GraphControl.OnNodeSelected += node =>
{
_currentNode = node;
SetSelectedNode(node);
};
ServerButton.OnPressed += _ =>
{
OnServerSelectionButtonPressed?.Invoke();
};
ExtractButton.OnPressed += StartExtract;
}
/// <summary>
/// Set entity that corresponds analysis console, for which window is opened.
/// Closes window if <see cref="AnalysisConsoleComponent"/> is not present on entity.
/// </summary>
public void SetOwner(EntityUid owner)
{
if (!_ent.TryGetComponent<AnalysisConsoleComponent>(owner, out var comp))
{
Close();
return;
}
_owner = (owner, comp);
Update(_owner);
}
private void StartExtract(BaseButton.ButtonEventArgs obj)
{
if (!_artifactAnalyzer.TryGetArtifactFromConsole(_owner, out var artifact))
return;
ExtractContainer.Visible = true;
NodeViewContainer.Visible = false;
_extractionSum = 0;
var extractionMessage = new FormattedMessage();
var nodes = _xenoArtifact.GetAllNodes(artifact.Value);
var count = 0;
foreach (var node in nodes)
{
var pointValue = _xenoArtifact.GetResearchValue(node);
if (pointValue <= 0)
continue;
count++;
var nodeId = _xenoArtifact.GetNodeId(node);
var text = Loc.GetString("analysis-console-extract-value", ("id", nodeId), ("value", pointValue));
extractionMessage.AddMarkupOrThrow(text);
extractionMessage.PushNewline();
}
if (count == 0)
extractionMessage.AddMarkupOrThrow(Loc.GetString("analysis-console-extract-none"));
_hideExtractInfoIn = _timing.CurTime + ExtractInfoDisplayForDuration;
ExtractionResearchLabel.SetMessage(extractionMessage);
ExtractionSumLabel.SetMarkup(Loc.GetString("analysis-console-extract-sum", ("value", _extractionSum)));
_audio.PlayGlobal(_owner.Comp.ScanFinishedSound, _owner, AudioParams.Default.WithVolume(1f));
OnExtractButtonPressed?.Invoke();
}
protected override void FrameUpdate(FrameEventArgs args)
{
base.FrameUpdate(args);
if (_hideExtractInfoIn == null || _timing.CurTime + _meta.GetPauseTime(_owner) < _hideExtractInfoIn)
return;
ExtractContainer.Visible = false;
NodeViewContainer.Visible = true;
_hideExtractInfoIn = null;
}
public void Update(Entity<AnalysisConsoleComponent> ent)
{
_artifactAnalyzer.TryGetArtifactFromConsole(ent, out var arti);
ArtifactView.SetEntity(arti);
GraphControl.SetArtifact(arti);
ExtractButton.Disabled = arti == null;
if (arti == null)
NoneSelectedLabel.Visible = false;
NoArtiLabel.Visible = true;
if (!_artifactAnalyzer.TryGetAnalyzer(ent, out _))
NoArtiLabel.Text = Loc.GetString("analysis-console-info-no-scanner");
else if (arti == null)
NoArtiLabel.Text = Loc.GetString("analysis-console-info-no-artifact");
else
NoArtiLabel.Visible = false;
if (_currentNode == null
|| arti == null
|| !_xenoArtifact.TryGetIndex((arti.Value, arti.Value), _currentNode.Value, out _))
{
SetSelectedNode(null);
}
}
public void SetSelectedNode(Entity<XenoArtifactNodeComponent>? node)
{
InfoContainer.Visible = node != null;
if (!_artifactAnalyzer.TryGetArtifactFromConsole(_owner, out var artifact))
return;
NoneSelectedLabel.Visible = node == null;
if (node == null)
return;
var nodeId = _xenoArtifact.GetNodeId(node.Value);
IDValueLabel.SetMarkup(Loc.GetString("analysis-console-info-id-value", ("id", nodeId)));
// If active, state is 2. else, it is 0 or 1 based on whether it is unlocked, or not.
int lockedState;
if (_xenoArtifact.IsNodeActive(artifact.Value, node.Value))
lockedState = 2;
else
lockedState = node.Value.Comp.Locked ? 0 : 1;
LockedValueLabel.SetMarkup(Loc.GetString("analysis-console-info-locked-value", ("state", lockedState)));
// Frontier: handle zero max durability
if (node.Value.Comp.MaxDurability <= 1)
{
DurabilityValueLabel.SetMarkup(Loc.GetString("analysis-console-info-durability-triggered",
("current", node.Value.Comp.Durability)));
}
else
{
var percent = node.Value.Comp.MaxDurability <= 0 ? 0f : (float)node.Value.Comp.Durability / node.Value.Comp.MaxDurability;
var color = percent switch
{
>= 0.75f => Color.Lime,
>= 0.50f => Color.Yellow,
_ => Color.Red
};
DurabilityValueLabel.SetMarkup(Loc.GetString("analysis-console-info-durability-value",
("color", color),
("current", node.Value.Comp.Durability),
("max", node.Value.Comp.MaxDurability)));
}
// End Frontier
var hasInfo = _xenoArtifact.HasUnlockedPredecessor(artifact.Value, node.Value);
// Frontier: hide xenoarch effects
var description = (lockedState == 0) ?
Loc.GetString("analysis-console-info-effect-unknown") :
_ent.GetComponentOrNull<MetaDataComponent>(node.Value)?.EntityDescription ?? string.Empty;
EffectValueLabel.SetMarkup(Loc.GetString("analysis-console-info-effect-value",
("state", hasInfo),
("info", description)));
// End Frontier: hide xenoarch effects
var predecessorNodes = _xenoArtifact.GetPredecessorNodes(artifact.Value.Owner, node.Value);
if (!hasInfo)
{
TriggerValueLabel.SetMarkup(Loc.GetString("analysis-console-info-effect-value", ("state", false)));
}
else
{
var triggerStr = new StringBuilder();
triggerStr.Append("- ");
triggerStr.Append(Loc.GetString(node.Value.Comp.TriggerTip!));
foreach (var predecessor in predecessorNodes)
{
triggerStr.AppendLine();
triggerStr.Append("- ");
triggerStr.Append(Loc.GetString(predecessor.Comp.TriggerTip!));
}
TriggerValueLabel.SetMarkup(Loc.GetString("analysis-console-info-triggered-value", ("triggers", triggerStr.ToString())));
}
ClassValueLabel.SetMarkup(Loc.GetString("analysis-console-info-class-value",
("class", Loc.GetString($"artifact-node-nf-class-{Math.Min(8, predecessorNodes.Count + 1)}")))); // Frontier: add nf-, 6<8
}
}