diff --git a/Content.Client/Xenoarchaeology/Ui/AnalysisConsoleMenu.xaml.cs b/Content.Client/Xenoarchaeology/Ui/AnalysisConsoleMenu.xaml.cs index 9f9637f58a..e77e43b2e7 100644 --- a/Content.Client/Xenoarchaeology/Ui/AnalysisConsoleMenu.xaml.cs +++ b/Content.Client/Xenoarchaeology/Ui/AnalysisConsoleMenu.xaml.cs @@ -1,12 +1,10 @@ using Content.Client.Stylesheets; using Content.Client.UserInterface.Controls; using Content.Shared.Xenoarchaeology.Equipment; -using Content.Shared.Xenoarchaeology.XenoArtifacts; 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.Utility; namespace Content.Client.Xenoarchaeology.Ui; @@ -15,7 +13,6 @@ namespace Content.Client.Xenoarchaeology.Ui; public sealed partial class AnalysisConsoleMenu : FancyWindow { [Dependency] private readonly IEntityManager _ent = default!; - [Dependency] private readonly IPrototypeManager _proto = default!; public AnalysisDestroyWindow? AnalysisDestroyWindow; @@ -73,7 +70,7 @@ public sealed partial class AnalysisConsoleMenu : FancyWindow } } - public void UpdateArtifactIcon(EntityUid? uid) + private void UpdateArtifactIcon(EntityUid? uid) { if (uid == null) { @@ -100,75 +97,18 @@ public sealed partial class AnalysisConsoleMenu : FancyWindow return; } - //do this here + if (!state.AnalyzerConnected) //no analyzer connected + message.AddMarkup(Loc.GetString("analysis-console-info-no-scanner")); + else if (!state.CanScan) //no artifact + message.AddMarkup(Loc.GetString("analysis-console-info-no-artifact")); + else if (state.Artifact == null) //ready to go + message.AddMarkup(Loc.GetString("analysis-console-info-ready")); + UpdateArtifactIcon(state.Artifact); - if (state.Artifact == null)//no scan present - { - if (!state.AnalyzerConnected) //no analyzer connected - message.AddMarkup(Loc.GetString("analysis-console-info-no-scanner")); - else if (!state.CanScan) //no artifact - message.AddMarkup(Loc.GetString("analysis-console-info-no-artifact")); - else if (state.Artifact == null) //ready to go - message.AddMarkup(Loc.GetString("analysis-console-info-ready")); - } + if (state.ScanReport != null) + message.AddMessage(state.ScanReport); - if (state.Id != null) //node id - { - message.AddMarkup(Loc.GetString("analysis-console-info-id", ("id", state.Id))); - message.PushNewline(); - } - if (state.Depth != null) //node depth - { - message.AddMarkup(Loc.GetString("analysis-console-info-depth", ("depth", state.Depth))); - message.PushNewline(); - } - - if (state.Triggered != null) //whether it has been triggered - { - var activated = state.Triggered.Value - ? "analysis-console-info-triggered-true" - : "analysis-console-info-triggered-false"; - message.AddMarkup(Loc.GetString(activated)); - message.PushNewline(); - } - - message.PushNewline(); - var needSecondNewline = false; - - if (state.TriggerProto != null && //possible triggers - _proto.TryIndex(state.TriggerProto, out var trigger) && - trigger.TriggerHint != null) - { - message.AddMarkup(Loc.GetString("analysis-console-info-trigger", - ("trigger", Loc.GetString(trigger.TriggerHint)))); - message.PushNewline(); - needSecondNewline = true; - } - - if (state.EffectProto != null && //possible effects - _proto.TryIndex(state.EffectProto, out var effect) && - effect.EffectHint != null) - { - message.AddMarkup(Loc.GetString("analysis-console-info-effect", - ("effect", Loc.GetString(effect.EffectHint)))); - message.PushNewline(); - needSecondNewline = true; - } - - if (needSecondNewline) - message.PushNewline(); - - if (state.Edges != null) //number of edges - { - message.AddMarkup(Loc.GetString("analysis-console-info-edges", ("edges", state.Edges))); - message.PushNewline(); - } - if (state.PointValue != null) //completion percentage - { - message.AddMarkup(Loc.GetString("analysis-console-info-value", ("value", state.PointValue))); - message.PushNewline(); - } Information.SetMessage(message); } diff --git a/Content.Server/Xenoarchaeology/Equipment/Systems/ArtifactAnalyzerSystem.cs b/Content.Server/Xenoarchaeology/Equipment/Systems/ArtifactAnalyzerSystem.cs index 804a221bbf..0697aaf44e 100644 --- a/Content.Server/Xenoarchaeology/Equipment/Systems/ArtifactAnalyzerSystem.cs +++ b/Content.Server/Xenoarchaeology/Equipment/Systems/ArtifactAnalyzerSystem.cs @@ -172,30 +172,26 @@ public sealed class ArtifactAnalyzerSystem : EntitySystem return; EntityUid? artifact = null; - ArtifactNode? node = null; - int? pointValue = null; + FormattedMessage? msg = null; var totalTime = TimeSpan.Zero; var canScan = false; var canPrint = false; if (component.AnalyzerEntity != null && TryComp(component.AnalyzerEntity, out var analyzer)) { artifact = analyzer.LastAnalyzedArtifact; - node = analyzer.LastAnalyzedNode; - pointValue = analyzer.LastAnalyzerPointValue; + msg = GetArtifactScanMessage(analyzer); totalTime = analyzer.AnalysisDuration * analyzer.AnalysisDurationMulitplier; canScan = analyzer.Contacts.Any(); canPrint = analyzer.ReadyToPrint; } - var analyzerConnected = component.AnalyzerEntity != null; var serverConnected = TryComp(uid, out var client) && client.ConnectedToServer; var scanning = TryComp(component.AnalyzerEntity, out var active); var remaining = active != null ? _timing.CurTime - active.StartTime : TimeSpan.Zero; - var state = new AnalysisConsoleScanUpdateState(artifact, analyzerConnected, serverConnected, canScan, canPrint, - node?.Id, node?.Depth, node?.Edges.Count, node?.Triggered, node?.Effect.ID, node?.Trigger.ID, pointValue, - scanning, remaining, totalTime); + var state = new AnalysisConsoleScanUpdateState(artifact, analyzerConnected, serverConnected, + canScan, canPrint, msg, scanning, remaining, totalTime); var bui = _ui.GetUi(uid, ArtifactAnalzyerUiKey.Key); _ui.SetUiState(bui, state); @@ -250,14 +246,27 @@ public sealed class ArtifactAnalyzerSystem : EntitySystem { return; } - analyzer.ReadyToPrint = false; - var n = analyzer.LastAnalyzedNode; var report = Spawn(component.ReportEntityId, Transform(uid).Coordinates); - MetaData(report).EntityName = Loc.GetString("analysis-report-title", ("id", n.Id)); + MetaData(report).EntityName = Loc.GetString("analysis-report-title", ("id", analyzer.LastAnalyzedNode.Id)); + var msg = GetArtifactScanMessage(analyzer); + if (msg == null) + return; + + _popup.PopupEntity(Loc.GetString("analysis-console-print-popup"), uid, Filter.Pvs(uid)); + _paper.SetContent(report, msg.ToMarkup()); + UpdateUserInterface(uid, component); + } + + private FormattedMessage? GetArtifactScanMessage(ArtifactAnalyzerComponent component) + { var msg = new FormattedMessage(); + if (component.LastAnalyzedNode == null) + return null; + + var n = component.LastAnalyzedNode; msg.AddMarkup(Loc.GetString("analysis-console-info-id", ("id", n.Id))); msg.PushNewline(); @@ -292,11 +301,10 @@ public sealed class ArtifactAnalyzerSystem : EntitySystem msg.AddMarkup(Loc.GetString("analysis-console-info-edges", ("edges", n.Edges.Count))); msg.PushNewline(); - msg.AddMarkup(Loc.GetString("analysis-console-info-value", ("value", analyzer.LastAnalyzerPointValue))); + if (component.LastAnalyzerPointValue != null) + msg.AddMarkup(Loc.GetString("analysis-console-info-value", ("value", component.LastAnalyzerPointValue))); - _popup.PopupEntity(Loc.GetString("analysis-console-print-popup"), uid, Filter.Pvs(uid)); - _paper.SetContent(report, msg.ToMarkup()); - UpdateUserInterface(uid, component); + return msg; } /// diff --git a/Content.Server/Xenoarchaeology/XenoArtifacts/ArtifactSystem.Nodes.cs b/Content.Server/Xenoarchaeology/XenoArtifacts/ArtifactSystem.Nodes.cs index 0125fc6fa5..52c2bcd9a9 100644 --- a/Content.Server/Xenoarchaeology/XenoArtifacts/ArtifactSystem.Nodes.cs +++ b/Content.Server/Xenoarchaeology/XenoArtifacts/ArtifactSystem.Nodes.cs @@ -1,6 +1,5 @@ using System.Linq; using Content.Server.Xenoarchaeology.XenoArtifacts.Events; -using Content.Shared.Item; using Content.Shared.Xenoarchaeology.XenoArtifacts; using Robust.Shared.Prototypes; using Robust.Shared.Random; @@ -14,7 +13,7 @@ public sealed partial class ArtifactSystem [Dependency] private readonly IComponentFactory _componentFactory = default!; [Dependency] private readonly ISerializationManager _serialization = default!; - private const int MaxEdgesPerNode = 3; + private const int MaxEdgesPerNode = 4; /// /// Generate an Artifact tree with fully developed nodes. @@ -162,16 +161,15 @@ public sealed partial class ArtifactSystem } component.CurrentNode = node; - node.Discovered = true; var allComponents = node.Effect.Components.Concat(node.Effect.PermanentComponents).Concat(node.Trigger.Components); foreach (var (name, entry) in allComponents) { var reg = _componentFactory.GetRegistration(name); - if (EntityManager.HasComponent(uid, reg.Type)) + if (node.Discovered && EntityManager.HasComponent(uid, reg.Type)) { - // Don't re-add permanent components + // Don't re-add permanent components unless this is the first time you've entered this node if (node.Effect.PermanentComponents.ContainsKey(name)) continue; @@ -187,6 +185,7 @@ public sealed partial class ArtifactSystem EntityManager.AddComponent(uid, (Component) temp!, true); } + node.Discovered = true; RaiseLocalEvent(uid, new ArtifactNodeEnteredEvent(component.CurrentNode.Id)); } diff --git a/Content.Server/Xenoarchaeology/XenoArtifacts/Triggers/Components/ArtifactMagnetTriggerComponent.cs b/Content.Server/Xenoarchaeology/XenoArtifacts/Triggers/Components/ArtifactMagnetTriggerComponent.cs index d19880e73d..f29f057687 100644 --- a/Content.Server/Xenoarchaeology/XenoArtifacts/Triggers/Components/ArtifactMagnetTriggerComponent.cs +++ b/Content.Server/Xenoarchaeology/XenoArtifacts/Triggers/Components/ArtifactMagnetTriggerComponent.cs @@ -11,4 +11,11 @@ public sealed class ArtifactMagnetTriggerComponent : Component /// [DataField("range")] public float Range = 40f; + + /// + /// How close do active magboots have to be? + /// This is smaller because they are weaker magnets + /// + [DataField("magbootRange")] + public float MagbootRange = 2f; } diff --git a/Content.Server/Xenoarchaeology/XenoArtifacts/Triggers/Systems/ArtifactMagnetTriggerSystem.cs b/Content.Server/Xenoarchaeology/XenoArtifacts/Triggers/Systems/ArtifactMagnetTriggerSystem.cs index e23cb2cdbd..1960982841 100644 --- a/Content.Server/Xenoarchaeology/XenoArtifacts/Triggers/Systems/ArtifactMagnetTriggerSystem.cs +++ b/Content.Server/Xenoarchaeology/XenoArtifacts/Triggers/Systems/ArtifactMagnetTriggerSystem.cs @@ -1,5 +1,7 @@ -using Content.Server.Salvage; +using System.Linq; +using Content.Server.Salvage; using Content.Server.Xenoarchaeology.XenoArtifacts.Triggers.Components; +using Content.Shared.Clothing; namespace Content.Server.Xenoarchaeology.XenoArtifacts.Triggers.Systems; @@ -16,6 +18,42 @@ public sealed class ArtifactMagnetTriggerSystem : EntitySystem SubscribeLocalEvent(OnMagnetActivated); } + public override void Update(float frameTime) + { + base.Update(frameTime); + + var artifactQuery = EntityQuery().ToHashSet(); + if (!artifactQuery.Any()) + return; + + List toActivate = new(); + + //assume that there's more instruments than artifacts + foreach (var magboot in EntityQuery()) + { + if (!magboot.On) + continue; + + var magXform = Transform(magboot.Owner); + + foreach (var (trigger, xform) in artifactQuery) + { + if (!magXform.Coordinates.TryDistance(EntityManager, xform.Coordinates, out var distance)) + continue; + + if (distance > trigger.Range) + continue; + + toActivate.Add(trigger.Owner); + } + } + + foreach (var a in toActivate) + { + _artifact.TryActivateArtifact(a); + } + } + private void OnMagnetActivated(SalvageMagnetActivatedEvent ev) { var magXform = Transform(ev.Magnet); diff --git a/Content.Shared/Xenoarchaeology/Equipment/SharedArtifactAnalyzer.cs b/Content.Shared/Xenoarchaeology/Equipment/SharedArtifactAnalyzer.cs index 0f8841487b..2d6a3950b6 100644 --- a/Content.Shared/Xenoarchaeology/Equipment/SharedArtifactAnalyzer.cs +++ b/Content.Shared/Xenoarchaeology/Equipment/SharedArtifactAnalyzer.cs @@ -1,4 +1,5 @@ using Robust.Shared.Serialization; +using Robust.Shared.Utility; namespace Content.Shared.Xenoarchaeology.Equipment; @@ -41,19 +42,7 @@ public sealed class AnalysisConsoleScanUpdateState : BoundUserInterfaceState public bool CanPrint; - public int? Id; - - public int? Depth; - - public int? Edges; - - public bool? Triggered; - - public string? EffectProto; - - public string? TriggerProto; - - public int? PointValue; + public FormattedMessage? ScanReport; public bool Scanning; @@ -62,8 +51,7 @@ public sealed class AnalysisConsoleScanUpdateState : BoundUserInterfaceState public TimeSpan TotalTime; public AnalysisConsoleScanUpdateState(EntityUid? artifact, bool analyzerConnected, bool serverConnected, bool canScan, bool canPrint, - int? id, int? depth, int? edges, bool? triggered, string? effectProto, string? triggerProto, int? pointValue, - bool scanning, TimeSpan timeRemaining, TimeSpan totalTime) + FormattedMessage? scanReport, bool scanning, TimeSpan timeRemaining, TimeSpan totalTime) { Artifact = artifact; AnalyzerConnected = analyzerConnected; @@ -71,13 +59,7 @@ public sealed class AnalysisConsoleScanUpdateState : BoundUserInterfaceState CanScan = canScan; CanPrint = canPrint; - Id = id; - Depth = depth; - Edges = edges; - Triggered = triggered; - EffectProto = effectProto; - TriggerProto = triggerProto; - PointValue = pointValue; + ScanReport = scanReport; Scanning = scanning; TimeRemaining = timeRemaining; diff --git a/Resources/Prototypes/Entities/Objects/Specific/Xenoarchaeology/item_artifacts.yml b/Resources/Prototypes/Entities/Objects/Specific/Xenoarchaeology/item_artifacts.yml index a53c145a9d..6eaa140fb2 100644 --- a/Resources/Prototypes/Entities/Objects/Specific/Xenoarchaeology/item_artifacts.yml +++ b/Resources/Prototypes/Entities/Objects/Specific/Xenoarchaeology/item_artifacts.yml @@ -28,6 +28,12 @@ available: - enum.ArtifactsVisualLayers.Effect: ano01_on: Rainbow + - type: UserInterface #needs to be here for certain effects + interfaces: + - key: enum.StorageUiKey.Key + type: StorageBoundUserInterface + - key: enum.TransferAmountUiKey.Key + type: TransferAmountBoundUserInterface - type: Appearance - type: StaticPrice price: 500 diff --git a/Resources/Prototypes/Entities/Structures/Machines/artifact_analyzer.yml b/Resources/Prototypes/Entities/Structures/Machines/artifact_analyzer.yml index fbff9dec4c..d6a5f1dafd 100644 --- a/Resources/Prototypes/Entities/Structures/Machines/artifact_analyzer.yml +++ b/Resources/Prototypes/Entities/Structures/Machines/artifact_analyzer.yml @@ -40,11 +40,7 @@ anchored: true noRot: false - type: ApcPowerReceiver - powerLoad: 15000 #really freaking high - needsPower: false #only turns on when scanning - - type: UpgradePowerDraw - powerDrawMultiplier: 0.80 - scaling: Exponential + powerLoad: 15000 - type: ArtifactAnalyzer - type: DeviceNetwork deviceNetId: Wired @@ -112,4 +108,4 @@ enum.PowerDeviceVisuals.Powered: enum.PowerDeviceVisualLayers.Powered: True: { visible: true } - False: { visible: false } \ No newline at end of file + False: { visible: false } diff --git a/Resources/Prototypes/XenoArch/Effects/utility_effects.yml b/Resources/Prototypes/XenoArch/Effects/utility_effects.yml index 376533f0b2..ea9c72ec2b 100644 --- a/Resources/Prototypes/XenoArch/Effects/utility_effects.yml +++ b/Resources/Prototypes/XenoArch/Effects/utility_effects.yml @@ -17,21 +17,6 @@ type: InstrumentBoundUserInterface - type: RandomInstrumentArtifact -- type: artifactEffect - id: EffectSlippy - targetDepth: 2 - effectHint: artifact-effect-hint-soap - whitelist: - components: - - Item - permanentComponents: - - type: Slippery - paralyzeTime: 7 - launchForwardsMultiplier: 9.0 - - type: StepTrigger - - type: CollisionWake - enabled: false - - type: artifactEffect id: EffectStorage targetDepth: 2 @@ -40,10 +25,6 @@ components: - Item # it doesnt necessarily have to be restricted from structures, but i think it'll be better that way permanentComponents: - - type: UserInterface - interfaces: - - key: enum.StorageUiKey.Key - type: StorageBoundUserInterface - type: ContainerContainer containers: storagebase: !type:Container @@ -59,10 +40,6 @@ components: - Item permanentComponents: - - type: UserInterface - interfaces: - - key: enum.TransferAmountUiKey.Key - type: TransferAmountBoundUserInterface - type: SolutionContainerManager solutions: beaker: