SS14-26480 Roll Traversal Distorter into regular Artifact Analyzers (#26545)

* SS14-26480 Roll Traversal Distorter into regular Artifact Analyzers

Bit of a grab-bag of cleanup of Xenoarchaeology prompted by #26480.

1. Traversal distortion biases are now "up" and "down" instead of "in" and "out".
2. Node generation has been tidied up to make it a little clearer how it works.
3. Traversal Distorters have been removed from the game along with their board.
4. Traversal distortion is now done by the artifact analyzers by default.
5. Some loc strings have been made clearer.
6. The Abnormal Artifact Manipulation tech has been made slightly cheaper.
7. The aformentioned tech is now localized as Artifact Recycling, given all it does is unlock the crusher.
8. The Xenoarchaeology guidebook entry has been given a bit of a rewrite, putting all information into
one page and making sure to cover the basics that otherwise would require someone typing "Liltenhead
artifact tutorial" into Youtube.

* Fix references to deleted guidebook entry

* Add fancy button to console because @EmoGarbage404 asked me to

* migration comprete

* Fixed a goober comment

* maint fails to resolve conflicts: more at 11

* Resolve PR comments

* Make UI nice

---------

Co-authored-by: Nemanja <98561806+EmoGarbage404@users.noreply.github.com>
This commit is contained in:
Hannah Giovanna Dawson
2024-04-21 17:09:26 +01:00
committed by GitHub
parent e009a80a8c
commit f059714a75
25 changed files with 252 additions and 311 deletions

View File

@@ -39,6 +39,14 @@ public sealed class AnalysisConsoleBoundUserInterface : BoundUserInterface
{
SendMessage(new AnalysisConsoleExtractButtonPressedMessage());
};
_consoleMenu.OnUpBiasButtonPressed += () =>
{
SendMessage(new AnalysisConsoleBiasButtonPressedMessage(false));
};
_consoleMenu.OnDownBiasButtonPressed += () =>
{
SendMessage(new AnalysisConsoleBiasButtonPressedMessage(true));
};
}
protected override void UpdateState(BoundUserInterfaceState state)
@@ -47,7 +55,7 @@ public sealed class AnalysisConsoleBoundUserInterface : BoundUserInterface
switch (state)
{
case AnalysisConsoleScanUpdateState msg:
case AnalysisConsoleUpdateState msg:
_consoleMenu?.SetButtonsDisabled(msg);
_consoleMenu?.UpdateInformationDisplay(msg);
_consoleMenu?.UpdateProgressBar(msg);

View File

@@ -1,30 +1,46 @@
<controls:FancyWindow xmlns="https://spacestation14.io"
xmlns:gfx="clr-namespace:Robust.Client.Graphics;assembly=Robust.Client"
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
xmlns:customControls="clr-namespace:Content.Client.Administration.UI.CustomControls"
Title="{Loc 'analysis-console-menu-title'}"
MinSize="620 280"
SetSize="620 280">
xmlns:gfx="clr-namespace:Robust.Client.Graphics;assembly=Robust.Client"
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
xmlns:customControls="clr-namespace:Content.Client.Administration.UI.CustomControls"
Title="{Loc 'analysis-console-menu-title'}"
MinSize="620 280"
SetSize="620 280">
<BoxContainer Orientation="Horizontal" HorizontalExpand="True" VerticalExpand="True">
<BoxContainer Margin="10 10 10 10" MinWidth="150" Orientation="Vertical" VerticalExpand="True" SizeFlagsStretchRatio="1">
<BoxContainer Margin="10 10 10 10" MinWidth="150" Orientation="Vertical"
VerticalExpand="True" SizeFlagsStretchRatio="1">
<BoxContainer Orientation="Vertical" VerticalExpand="True">
<Button Name="ServerSelectionButton"
Text="{Loc 'analysis-console-server-list-button'}"></Button>
Text="{Loc 'analysis-console-server-list-button'}"></Button>
<BoxContainer MinHeight="5"></BoxContainer>
<Button Name="ScanButton"
Text="{Loc 'analysis-console-scan-button'}"
ToolTip="{Loc 'analysis-console-scan-tooltip-info'}">
Text="{Loc 'analysis-console-scan-button'}"
ToolTip="{Loc 'analysis-console-scan-tooltip-info'}">
</Button>
<BoxContainer MinHeight="5"></BoxContainer>
<Button Name="PrintButton"
Text="{Loc 'analysis-console-print-button'}"
ToolTip="{Loc 'analysis-console-print-tooltip-info'}">
Text="{Loc 'analysis-console-print-button'}"
ToolTip="{Loc 'analysis-console-print-tooltip-info'}">
</Button>
<BoxContainer MinHeight="5"></BoxContainer>
<Button Name="ExtractButton"
Text="{Loc 'analysis-console-extract-button'}"
ToolTip="{Loc 'analysis-console-extract-button-info'}">
Text="{Loc 'analysis-console-extract-button'}"
ToolTip="{Loc 'analysis-console-extract-button-info'}">
</Button>
<BoxContainer MinHeight="5"></BoxContainer>
<BoxContainer Orientation="Horizontal">
<Button Name="UpBiasButton"
Text="{Loc 'analysis-console-bias-up'}"
ToolTip="{Loc 'analysis-console-bias-button-info-up'}"
HorizontalExpand="True"
StyleClasses="OpenRight">
</Button>
<Button Name="DownBiasButton"
Text="{Loc 'analysis-console-bias-down'}"
ToolTip="{Loc 'analysis-console-bias-button-info-down'}"
HorizontalExpand="True"
StyleClasses="OpenLeft">
</Button>
</BoxContainer>
</BoxContainer>
<BoxContainer Orientation="Vertical">
<Label Name="ProgressLabel"></Label>
@@ -36,13 +52,13 @@
</ProgressBar>
</BoxContainer>
</BoxContainer>
<customControls:VSeparator StyleClasses="LowDivider"/>
<customControls:VSeparator StyleClasses="LowDivider" />
<PanelContainer Margin="10 10 10 10" HorizontalExpand="True" SizeFlagsStretchRatio="3">
<PanelContainer.PanelOverride>
<gfx:StyleBoxFlat BackgroundColor="#000000FF" />
</PanelContainer.PanelOverride>
<BoxContainer Margin="10 10 10 10" Orientation="Horizontal">
<BoxContainer Orientation="Vertical" HorizontalExpand="True" >
<BoxContainer Orientation="Vertical" HorizontalExpand="True">
<BoxContainer VerticalExpand="True">
<RichTextLabel Name="Information"> </RichTextLabel>
</BoxContainer>

View File

@@ -3,6 +3,7 @@ using Content.Client.UserInterface.Controls;
using Content.Shared.Xenoarchaeology.Equipment;
using Robust.Client.AutoGenerated;
using Robust.Client.GameObjects;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.Timing;
using Robust.Shared.Utility;
@@ -19,6 +20,8 @@ public sealed partial class AnalysisConsoleMenu : FancyWindow
public event Action? OnScanButtonPressed;
public event Action? OnPrintButtonPressed;
public event Action? OnExtractButtonPressed;
public event Action? OnUpBiasButtonPressed;
public event Action? OnDownBiasButtonPressed;
// For rendering the progress bar, updated from BUI state
private TimeSpan? _startTime;
@@ -36,6 +39,12 @@ public sealed partial class AnalysisConsoleMenu : FancyWindow
ScanButton.OnPressed += _ => OnScanButtonPressed?.Invoke();
PrintButton.OnPressed += _ => OnPrintButtonPressed?.Invoke();
ExtractButton.OnPressed += _ => OnExtractButtonPressed?.Invoke();
UpBiasButton.OnPressed += _ => OnUpBiasButtonPressed?.Invoke();
DownBiasButton.OnPressed += _ => OnDownBiasButtonPressed?.Invoke();
var buttonGroup = new ButtonGroup(false);
UpBiasButton.Group = buttonGroup;
DownBiasButton.Group = buttonGroup;
}
protected override void FrameUpdate(FrameEventArgs args)
@@ -60,7 +69,7 @@ public sealed partial class AnalysisConsoleMenu : FancyWindow
ProgressBar.Value = Math.Clamp(1.0f - (float) remaining.Divide(total), 0.0f, 1.0f);
}
public void SetButtonsDisabled(AnalysisConsoleScanUpdateState state)
public void SetButtonsDisabled(AnalysisConsoleUpdateState state)
{
ScanButton.Disabled = !state.CanScan;
PrintButton.Disabled = !state.CanPrint;
@@ -78,7 +87,6 @@ public sealed partial class AnalysisConsoleMenu : FancyWindow
ExtractButton.AddStyleClass("ButtonColorGreen");
}
}
private void UpdateArtifactIcon(EntityUid? uid)
{
if (uid == null)
@@ -91,7 +99,7 @@ public sealed partial class AnalysisConsoleMenu : FancyWindow
ArtifactDisplay.SetEntity(uid);
}
public void UpdateInformationDisplay(AnalysisConsoleScanUpdateState state)
public void UpdateInformationDisplay(AnalysisConsoleUpdateState state)
{
var message = new FormattedMessage();
@@ -129,7 +137,7 @@ public sealed partial class AnalysisConsoleMenu : FancyWindow
Information.SetMessage(message);
}
public void UpdateProgressBar(AnalysisConsoleScanUpdateState state)
public void UpdateProgressBar(AnalysisConsoleUpdateState state)
{
ProgressBar.Visible = state.Scanning;
ProgressLabel.Visible = state.Scanning;

View File

@@ -8,7 +8,7 @@
public sealed partial class TraversalDistorterComponent : Component
{
[ViewVariables(VVAccess.ReadWrite)]
public BiasDirection BiasDirection = BiasDirection.In;
public BiasDirection BiasDirection = BiasDirection.Up;
public TimeSpan NextActivation = default!;
public TimeSpan ActivationDelay = TimeSpan.FromSeconds(1);
@@ -16,6 +16,6 @@ public sealed partial class TraversalDistorterComponent : Component
public enum BiasDirection : byte
{
In, //down the tree, towards depth 0
Out //up the tree, away from depth 0
Up, //Towards depth 0
Down, //Away from depth 0
}

View File

@@ -40,6 +40,7 @@ public sealed class ArtifactAnalyzerSystem : EntitySystem
[Dependency] private readonly PaperSystem _paper = default!;
[Dependency] private readonly ResearchSystem _research = default!;
[Dependency] private readonly MetaDataSystem _metaSystem = default!;
[Dependency] private readonly TraversalDistorterSystem _traversalDistorter = default!;
/// <inheritdoc/>
public override void Initialize()
@@ -61,6 +62,7 @@ public sealed class ArtifactAnalyzerSystem : EntitySystem
SubscribeLocalEvent<AnalysisConsoleComponent, AnalysisConsoleScanButtonPressedMessage>(OnScanButton);
SubscribeLocalEvent<AnalysisConsoleComponent, AnalysisConsolePrintButtonPressedMessage>(OnPrintButton);
SubscribeLocalEvent<AnalysisConsoleComponent, AnalysisConsoleExtractButtonPressedMessage>(OnExtractButton);
SubscribeLocalEvent<AnalysisConsoleComponent, AnalysisConsoleBiasButtonPressedMessage>(OnBiasButton);
SubscribeLocalEvent<AnalysisConsoleComponent, ResearchClientServerSelectedMessage>((e, c, _) => UpdateUserInterface(e, c),
after: new[] { typeof(ResearchSystem) });
@@ -192,6 +194,7 @@ public sealed class ArtifactAnalyzerSystem : EntitySystem
var canScan = false;
var canPrint = false;
var points = 0;
if (TryComp<ArtifactAnalyzerComponent>(component.AnalyzerEntity, out var analyzer))
{
artifact = analyzer.LastAnalyzedArtifact;
@@ -205,15 +208,20 @@ public sealed class ArtifactAnalyzerSystem : EntitySystem
if (GetArtifactForAnalysis(component.AnalyzerEntity, placer) is { } current)
points = _artifact.GetResearchPointValue(current);
}
var analyzerConnected = component.AnalyzerEntity != null;
var serverConnected = TryComp<ResearchClientComponent>(uid, out var client) && client.ConnectedToServer;
var scanning = TryComp<ActiveArtifactAnalyzerComponent>(component.AnalyzerEntity, out var active);
var paused = active != null ? active.AnalysisPaused : false;
var biasDirection = BiasDirection.Up;
var state = new AnalysisConsoleScanUpdateState(GetNetEntity(artifact), analyzerConnected, serverConnected,
canScan, canPrint, msg, scanning, paused, active?.StartTime, active?.AccumulatedRunTime, totalTime, points);
if (TryComp<TraversalDistorterComponent>(component.AnalyzerEntity, out var trav))
biasDirection = trav.BiasDirection;
var state = new AnalysisConsoleUpdateState(GetNetEntity(artifact), analyzerConnected, serverConnected,
canScan, canPrint, msg, scanning, paused, active?.StartTime, active?.AccumulatedRunTime, totalTime, points, biasDirection == BiasDirection.Down);
var bui = _ui.GetUi(uid, ArtifactAnalzyerUiKey.Key);
_ui.SetUiState(bui, state);
@@ -372,6 +380,20 @@ public sealed class ArtifactAnalyzerSystem : EntitySystem
UpdateUserInterface(uid, component);
}
private void OnBiasButton(EntityUid uid, AnalysisConsoleComponent component, AnalysisConsoleBiasButtonPressedMessage args)
{
if (component.AnalyzerEntity == null)
return;
if (!TryComp<TraversalDistorterComponent>(component.AnalyzerEntity, out var trav))
return;
if (!_traversalDistorter.SetState(component.AnalyzerEntity.Value, trav, args.IsDown))
return;
UpdateUserInterface(uid, component);
}
/// <summary>
/// Cancels scans if the artifact changes nodes (is activated) during the scan.
/// </summary>

View File

@@ -17,8 +17,6 @@ public sealed class TraversalDistorterSystem : EntitySystem
public override void Initialize()
{
SubscribeLocalEvent<TraversalDistorterComponent, MapInitEvent>(OnInit);
SubscribeLocalEvent<TraversalDistorterComponent, ActivateInWorldEvent>(OnInteract);
SubscribeLocalEvent<TraversalDistorterComponent, ExaminedEvent>(OnExamine);
SubscribeLocalEvent<TraversalDistorterComponent, ItemPlacedEvent>(OnItemPlaced);
@@ -30,30 +28,25 @@ public sealed class TraversalDistorterSystem : EntitySystem
component.NextActivation = _timing.CurTime;
}
private void OnInteract(EntityUid uid, TraversalDistorterComponent component, ActivateInWorldEvent args)
/// <summary>
/// Switches the state of the traversal distorter between up and down.
/// </summary>
/// <param name="uid">The distorter's entity</param>
/// <param name="component">The component on the entity</param>
/// <returns>If the distorter changed state</returns>
public bool SetState(EntityUid uid, TraversalDistorterComponent component, bool isDown)
{
if (args.Handled || !this.IsPowered(uid, EntityManager))
return;
if (!this.IsPowered(uid, EntityManager))
return false;
if (_timing.CurTime < component.NextActivation)
return;
args.Handled = true;
return false;
component.NextActivation = _timing.CurTime + component.ActivationDelay;
component.BiasDirection = component.BiasDirection == BiasDirection.In
? BiasDirection.Out
: BiasDirection.In;
component.BiasDirection = isDown ? BiasDirection.Down : BiasDirection.Up;
var toPopup = string.Empty;
switch (component.BiasDirection)
{
case BiasDirection.In:
toPopup = Loc.GetString("traversal-distorter-set-in");
break;
case BiasDirection.Out:
toPopup = Loc.GetString("traversal-distorter-set-out");
break;
}
_popup.PopupEntity(toPopup, uid);
return true;
}
private void OnExamine(EntityUid uid, TraversalDistorterComponent component, ExaminedEvent args)
@@ -61,11 +54,11 @@ public sealed class TraversalDistorterSystem : EntitySystem
string examine = string.Empty;
switch (component.BiasDirection)
{
case BiasDirection.In:
examine = Loc.GetString("traversal-distorter-desc-in");
case BiasDirection.Up:
examine = Loc.GetString("traversal-distorter-desc-up");
break;
case BiasDirection.Out:
examine = Loc.GetString("traversal-distorter-desc-out");
case BiasDirection.Down:
examine = Loc.GetString("traversal-distorter-desc-down");
break;
}

View File

@@ -19,26 +19,46 @@ public sealed partial class ArtifactSystem
/// </summary>
/// <param name="artifact"></param>
/// <param name="allNodes"></param>
/// <param name="nodeAmount">The amount of nodes it has.</param>
private void GenerateArtifactNodeTree(EntityUid artifact, ref List<ArtifactNode> allNodes, int nodeAmount)
/// <param name="nodesToCreate">The amount of nodes it has.</param>
private void GenerateArtifactNodeTree(EntityUid artifact, List<ArtifactNode> allNodes, int nodesToCreate)
{
if (nodeAmount < 1)
if (nodesToCreate < 1)
{
Log.Error($"nodeAmount {nodeAmount} is less than 1. Aborting artifact tree generation.");
Log.Error($"nodesToCreate {nodesToCreate} is less than 1. Aborting artifact tree generation.");
return;
}
_usedNodeIds.Clear();
var uninitializedNodes = new List<ArtifactNode> { new(){ Id = GetValidNodeId() } };
var createdNodes = 1;
var rootNode = new ArtifactNode
while (uninitializedNodes.Count > 0)
{
Id = GetValidNodeId()
};
var uninitializedNodes = new List<ArtifactNode> { rootNode };
while (uninitializedNodes.Any())
{
GenerateNode(artifact, ref uninitializedNodes, ref allNodes, nodeAmount);
var node = uninitializedNodes[0];
uninitializedNodes.Remove(node);
node.Trigger = GetRandomTrigger(artifact, ref node);
node.Effect = GetRandomEffect(artifact, ref node);
var maxChildren = _random.Next(1, MaxEdgesPerNode - 1);
for (var i = 0; i < maxChildren; i++)
{
if (nodesToCreate <= createdNodes)
{
break;
}
var child = new ArtifactNode {Id = GetValidNodeId(), Depth = node.Depth + 1};
node.Edges.Add(child.Id);
child.Edges.Add(node.Id);
uninitializedNodes.Add(child);
createdNodes++;
}
allNodes.Add(node);
}
}
@@ -51,46 +71,10 @@ public sealed partial class ArtifactSystem
}
_usedNodeIds.Add(id);
return id;
}
/// <summary>
/// Generate an individual node on the tree.
/// </summary>
private void GenerateNode(EntityUid artifact, ref List<ArtifactNode> uninitializedNodes, ref List<ArtifactNode> allNodes, int targetNodeAmount)
{
if (!uninitializedNodes.Any())
return;
var node = uninitializedNodes.First();
uninitializedNodes.Remove(node);
//Generate the connected nodes
var maxEdges = Math.Max(1, targetNodeAmount - allNodes.Count - uninitializedNodes.Count - 1);
maxEdges = Math.Min(maxEdges, MaxEdgesPerNode);
var minEdges = Math.Clamp(targetNodeAmount - allNodes.Count - uninitializedNodes.Count - 1, 0, 1);
var edgeAmount = _random.Next(minEdges, maxEdges);
for (var i = 0; i < edgeAmount; i++)
{
var neighbor = new ArtifactNode
{
Depth = node.Depth + 1,
Id = GetValidNodeId()
};
node.Edges.Add(neighbor.Id);
neighbor.Edges.Add(node.Id);
uninitializedNodes.Add(neighbor);
}
node.Trigger = GetRandomTrigger(artifact, ref node);
node.Effect = GetRandomEffect(artifact, ref node);
allNodes.Add(node);
}
//yeah these two functions are near duplicates but i don't
//want to implement an interface or abstract parent
@@ -159,6 +143,7 @@ public sealed partial class ArtifactSystem
return key;
}
}
return _random.Pick(weights.Keys); //shouldn't happen
}

View File

@@ -129,7 +129,7 @@ public sealed partial class ArtifactSystem : EntitySystem
{
var nodeAmount = _random.Next(component.NodesMin, component.NodesMax);
GenerateArtifactNodeTree(uid, ref component.NodeTree, nodeAmount);
GenerateArtifactNodeTree(uid, component.NodeTree, nodeAmount);
var firstNode = GetRootNode(component.NodeTree);
EnterNode(uid, ref firstNode, component);
}
@@ -184,13 +184,14 @@ public sealed partial class ArtifactSystem : EntitySystem
var currentNode = GetNodeFromId(component.CurrentNodeId.Value, component);
currentNode.Triggered = true;
if (currentNode.Edges.Any())
{
var newNode = GetNewNode(uid, component);
if (newNode == null)
return;
EnterNode(uid, ref newNode, component);
}
if (currentNode.Edges.Count == 0)
return;
var newNode = GetNewNode(uid, component);
if (newNode == null)
return;
EnterNode(uid, ref newNode, component);
}
private ArtifactNode? GetNewNode(EntityUid uid, ArtifactComponent component)
@@ -210,15 +211,15 @@ public sealed partial class ArtifactSystem : EntitySystem
{
switch (trav.BiasDirection)
{
case BiasDirection.In:
var foo = allNodes.Where(x => GetNodeFromId(x, component).Depth < currentNode.Depth).ToHashSet();
if (foo.Any())
allNodes = foo;
case BiasDirection.Up:
var upNodes = allNodes.Where(x => GetNodeFromId(x, component).Depth < currentNode.Depth).ToHashSet();
if (upNodes.Count != 0)
allNodes = upNodes;
break;
case BiasDirection.Out:
var bar = allNodes.Where(x => GetNodeFromId(x, component).Depth > currentNode.Depth).ToHashSet();
if (bar.Any())
allNodes = bar;
case BiasDirection.Down:
var downNodes = allNodes.Where(x => GetNodeFromId(x, component).Depth > currentNode.Depth).ToHashSet();
if (downNodes.Count != 0)
allNodes = downNodes;
break;
}
}
@@ -226,12 +227,14 @@ public sealed partial class ArtifactSystem : EntitySystem
var undiscoveredNodes = allNodes.Where(x => !GetNodeFromId(x, component).Discovered).ToList();
Log.Debug($"Undiscovered nodes: {string.Join(", ", undiscoveredNodes)}");
var newNode = _random.Pick(allNodes);
if (undiscoveredNodes.Any() && _random.Prob(0.75f))
if (undiscoveredNodes.Count != 0 && _random.Prob(0.75f))
{
newNode = _random.Pick(undiscoveredNodes);
}
Log.Debug($"Going to node {newNode}");
return GetNodeFromId(newNode, component);
}

View File

@@ -30,50 +30,40 @@ public sealed class AnalysisConsoleExtractButtonPressedMessage : BoundUserInterf
}
[Serializable, NetSerializable]
public sealed class AnalysisConsoleScanUpdateState : BoundUserInterfaceState
public sealed class AnalysisConsoleBiasButtonPressedMessage(bool isDown) : BoundUserInterfaceMessage
{
public NetEntity? Artifact;
public bool AnalyzerConnected;
public bool ServerConnected;
public bool CanScan;
public bool CanPrint;
public FormattedMessage? ScanReport;
public bool Scanning;
public bool Paused;
public TimeSpan? StartTime;
public TimeSpan? AccumulatedRunTime;
public TimeSpan? TotalTime;
public int PointAmount;
public AnalysisConsoleScanUpdateState(NetEntity? artifact, bool analyzerConnected, bool serverConnected, bool canScan, bool canPrint,
FormattedMessage? scanReport, bool scanning, bool paused, TimeSpan? startTime, TimeSpan? accumulatedRunTime, TimeSpan? totalTime, int pointAmount)
{
Artifact = artifact;
AnalyzerConnected = analyzerConnected;
ServerConnected = serverConnected;
CanScan = canScan;
CanPrint = canPrint;
ScanReport = scanReport;
Scanning = scanning;
Paused = paused;
StartTime = startTime;
AccumulatedRunTime = accumulatedRunTime;
TotalTime = totalTime;
PointAmount = pointAmount;
}
public bool IsDown = isDown;
}
[Serializable, NetSerializable]
public sealed class AnalysisConsoleUpdateState(
NetEntity? artifact,
bool analyzerConnected,
bool serverConnected,
bool canScan,
bool canPrint,
FormattedMessage? scanReport,
bool scanning,
bool paused,
TimeSpan? startTime,
TimeSpan? accumulatedRunTime,
TimeSpan? totalTime,
int pointAmount,
bool isTraversalDown
)
: BoundUserInterfaceState
{
public NetEntity? Artifact = artifact;
public bool AnalyzerConnected = analyzerConnected;
public bool ServerConnected = serverConnected;
public bool CanScan = canScan;
public bool CanPrint = canPrint;
public FormattedMessage? ScanReport = scanReport;
public bool Scanning = scanning;
public bool Paused = paused;
public TimeSpan? StartTime = startTime;
public TimeSpan? AccumulatedRunTime = accumulatedRunTime;
public TimeSpan? TotalTime = totalTime;
public int PointAmount = pointAmount;
public bool IsTraversalDown = isTraversalDown;
}

View File

@@ -44,7 +44,7 @@ research-technology-magnets-tech = Localized Magnetism
research-technology-advanced-parts = Advanced Parts
research-technology-anomaly-harnessing = Anomaly Core Harnessing
research-technology-grappling = Grappling
research-technology-abnormal-artifact-manipulation = Abnormal Artifact Manipulation
research-technology-abnormal-artifact-manipulation = Artifact Recycling
research-technology-gravity-manipulation = Gravity Manipulation
research-technology-quantum-leaping = Quantum Leaping
research-technology-advanced-anomaly-research = Advanced Anomaly Research

View File

@@ -6,6 +6,10 @@ analysis-console-print-button = Print
analysis-console-print-tooltip-info = Print out the current information about the artifact.
analysis-console-extract-button = Extract
analysis-console-extract-button-info = Extract points from an artifact based on the newly explored nodes.
analysis-console-bias-up = Up
analysis-console-bias-down = Down
analysis-console-bias-button-info-up = Toggles the bias an artifact has in moving between its nodes. Up heads toward zero depth.
analysis-console-bias-button-info-down = Toggles the bias an artifact has in moving between its nodes. Down heads toward ever-higher depths.
analysis-console-info-no-scanner = No analyzer connected! Please connect one using a multitool.
analysis-console-info-no-artifact = No artifact present! Place one on the pad then scan for information.

View File

@@ -1,5 +1,5 @@
traversal-distorter-set-in = Traversal bias set to "in"
traversal-distorter-set-out = Traversal bias set to "out"
traversal-distorter-set-up = Traversal bias set to up, toward safer nodes
traversal-distorter-set-down = Traversal bias set to down, toward more dangerous nodes
traversal-distorter-desc-in = The affected artifact's traversal now favors moving inwards to the beginning.
traversal-distorter-desc-out = The affected artifact's traversal now favors moving outwards towards more dangerous nodes.
traversal-distorter-desc-up = The affected artifact's traversal now favors moving up the node tree toward safer nodes.
traversal-distorter-desc-down = The affected artifact's traversal now favors moving down the node tree towards more dangerous nodes.

View File

@@ -7444,13 +7444,6 @@ entities:
- type: Transform
pos: 32.5,14.5
parent: 1653
- proto: MachineTraversalDistorter
entities:
- uid: 1058
components:
- type: Transform
pos: 34.5,22.5
parent: 1653
- proto: MaintenanceFluffSpawner
entities:
- uid: 867

View File

@@ -253,23 +253,6 @@
materialRequirements:
Glass: 5
- type: entity
id: TraversalDistorterMachineCircuitboard
parent: BaseMachineCircuitboard
name: traversal distorter machine board
description: A machine printed circuit board for a traversal distorter.
components:
- type: Sprite
state: science
- type: MachineBoard
prototype: MachineTraversalDistorter
requirements:
Manipulator: 1
Capacitor: 2
materialRequirements:
Steel: 5
Cable: 1
- type: entity
id: ArtifactCrusherMachineCircuitboard
parent: BaseMachineCircuitboard

View File

@@ -43,6 +43,7 @@
powerLoad: 12000
needsPower: false #only turns on when scanning
- type: ArtifactAnalyzer
- type: TraversalDistorter
- type: ItemPlacer
whitelist:
components:
@@ -72,62 +73,6 @@
True: { visible: true }
False: { visible: false }
- type: entity
id: MachineTraversalDistorter
parent: [ BaseMachinePowered, ConstructibleMachine ]
name: traversal distorter
description: A machine capable of distorting the traversal of artifact nodes.
components:
- type: Sprite
noRot: true
sprite: Structures/Machines/traversal_distorter.rsi
drawdepth: FloorObjects
layers:
- state: icon
- state: unshaded
shader: unshaded
map: ["enum.PowerDeviceVisualLayers.Powered"]
- type: Physics
bodyType: Static
canCollide: true
- type: Fixtures
fixtures:
fix1:
shape:
!type:PhysShapeAabb
bounds: "-0.35,-0.35,0.35,0.35"
density: 190
mask:
- MachineMask
layer:
- Impassable
- MidImpassable
- LowImpassable
hard: False
- type: Transform
noRot: false
- type: TraversalDistorter
- type: ItemPlacer
# don't limit the number of artifacts that can be biased
maxEntities: 0
whitelist:
components:
- Artifact
- type: PlaceableSurface
placeCentered: true
- type: Machine
board: TraversalDistorterMachineCircuitboard
- type: Appearance
- type: GuideHelp
guides:
- TraversalDistorter
- type: GenericVisualizer
visuals:
enum.PowerDeviceVisuals.Powered:
enum.PowerDeviceVisualLayers.Powered:
True: { visible: true }
False: { visible: false }
- type: entity
id: MachineArtifactCrusher
parent: [ ConstructibleMachine, BaseMachinePowered ]

View File

@@ -443,7 +443,6 @@
- AnomalySynchronizerCircuitboard
- APECircuitboard
- ArtifactAnalyzerMachineCircuitboard
- TraversalDistorterMachineCircuitboard
- ArtifactCrusherMachineCircuitboard
- TelecomServerCircuitboard
- MassMediaCircuitboard

View File

@@ -38,7 +38,6 @@
text: "/ServerInfo/Guidebook/Science/Xenoarchaeology.xml"
children:
- ArtifactReports
- TraversalDistorter
- type: guideEntry
id: Robotics
@@ -52,11 +51,6 @@
name: guide-entry-artifact-reports
text: "/ServerInfo/Guidebook/Science/ArtifactReports.xml"
- type: guideEntry
id: TraversalDistorter
name: guide-entry-traversal-distorter
text: "/ServerInfo/Guidebook/Science/TraversalDistorter.xml"
- type: guideEntry
id: Cyborgs
name: guide-entry-cyborgs

View File

@@ -328,16 +328,6 @@
Glass: 900
Gold: 100
- type: latheRecipe
id: TraversalDistorterMachineCircuitboard
result: TraversalDistorterMachineCircuitboard
category: Circuitry
completetime: 4
materials:
Steel: 100
Glass: 900
Gold: 100
- type: latheRecipe
id: ArtifactCrusherMachineCircuitboard
result: ArtifactCrusherMachineCircuitboard
@@ -921,7 +911,7 @@
materials:
Steel: 100
Glass: 900
- type: latheRecipe
id: ShuttleGunPerforatorCircuitboard
result: ShuttleGunPerforatorCircuitboard
@@ -930,7 +920,7 @@
Steel: 100
Glass: 900
Gold: 100
- type: latheRecipe
id: ShuttleGunKineticCircuitboard
result: ShuttleGunKineticCircuitboard
@@ -938,7 +928,7 @@
materials:
Steel: 100
Glass: 900
- type: latheRecipe
id: ShuttleGunFriendshipCircuitboard
result: ShuttleGunFriendshipCircuitboard
@@ -947,7 +937,7 @@
Steel: 100
Glass: 900
Gold: 50
- type: latheRecipe
id: ShuttleGunDusterCircuitboard
result: ShuttleGunDusterCircuitboard

View File

@@ -87,13 +87,12 @@
id: AbnormalArtifactManipulation
name: research-technology-abnormal-artifact-manipulation
icon:
sprite: Structures/Machines/traversal_distorter.rsi
state: display
sprite: Structures/Machines/artifact_crusher.rsi
state: icon
discipline: Experimental
tier: 2
cost: 5000
recipeUnlocks:
- TraversalDistorterMachineCircuitboard
- ArtifactCrusherMachineCircuitboard
- type: technology

View File

@@ -1,25 +1,24 @@
<Document>
# Artifact Reports
A large portion of Xenoarchaeology gameplay revolves around the interpretation of artifact reports, which are created at the [color=#a4885c]analysis console[/color] after an artifact is scanned. Reports contain the following information:
# Artifact Reports
A large portion of Xenoarchaeology gameplay revolves around the interpretation of artifact reports, which are created at the [color=#a4885c]analysis console[/color] after an artifact is scanned. Reports contain the following information:
- [color=#a4885c]Node ID:[/color] a unique numeric ID corresponding to this artifact's node. Useful in conjunction with a [color=#a4885c]node scanner[/color] for quickly identifying recurring nodes.
- [color=#a4885c]Node ID:[/color] a unique numeric ID corresponding to this artifact's node. Useful in conjunction with a [color=#a4885c]node scanner[/color] for quickly identifying recurring nodes.
- [color=#a4885c]Depth:[/color] a distance from the starting node (depth 0). This is a good shorthand for the value and danger of a node.
- [color=#a4885c]Depth:[/color] a distance from the starting node (depth 0). This is a good shorthand for the value and danger of a node.
- [color=#a4885c]Activation status:[/color] whether or not a node has been activated in the past.
- [color=#a4885c]Activation status:[/color] whether or not a node has been activated in the past.
- [color=#a4885c]Stimulus:[/color] the stimulus for that particular node.
- [color=#a4885c]Stimulus:[/color] the stimulus for that particular node.
- [color=#a4885c]Reaction:[/color] the reaction the stimulus induces. This is often vague, so caution is advised.
- [color=#a4885c]Reaction:[/color] the reaction the stimulus induces. This is often vague, so caution is advised.
- [color=#a4885c]Edges:[/color] the amount of nodes that are connected to the current node. Using this, you can calculate the total number of nodes as well as organize a map of their connections.
- [color=#a4885c]Edges:[/color] the amount of nodes that are connected to the current node. Using this, you can calculate the total number of nodes as well as organize a map of their connections.
- [color=#a4885c]Unextracted value:[/color] the amount of research points an artifact will give when extracted. Extracting sets this to zero and traversing new nodes increases it.
Reports are a helpful tool in manipulating an artifact, especially in the later stages where you are traversing nodes that have already been activated.
<Box>
<GuideEntityEmbed Entity="PaperArtifactAnalyzer"/>
</Box>
To help with this process, consider printing out reports, writing down details uncovered during activation, or storing them in a folder nearby.
- [color=#a4885c]Unextracted value:[/color] the amount of research points an artifact will give when extracted. Extracting sets this to zero and traversing new nodes increases it.
Reports are a helpful tool in manipulating an artifact, especially in the later stages where you are traversing nodes that have already been activated.
<Box>
<GuideEntityEmbed Entity="PaperArtifactAnalyzer"/>
</Box>
To help with this process, consider printing out reports, writing down details uncovered during activation, or storing them in a folder nearby.
</Document>

View File

@@ -1,18 +0,0 @@
<Document>
# Traversal Distorter
The traversal distorter is a late-game artifact machine that can aid in moving through the nodes of an artifact.
<Box>
<GuideEntityEmbed Entity="MachineTraversalDistorter"/>
</Box>
Artifacts placed on top of a powered traversal distorter are subjected to a bias which affects which node they will move to after being activated. The bias can be set by clicking on the distorter.
There are two types of biases:
- [color=#a4885c]In:[/color] favors nodes closer to the origin. Results in a decrease of depth.
- [color=#a4885c]Out:[/color] favors nodes farther away from the origin. Results in an increase of depth.
Setting it to bias inwards allows you to return to the beginning of an artifact graph, if you've reached a dead end.
Likewise, if you find yourself stuck at low depths, setting it to bias outward will help you find new nodes. In certain circumstances, toggling between the two allows you to repeatedly activate the same node.
</Document>

View File

@@ -2,18 +2,28 @@
# Xenoarchaeology
Xenoarchaeology is a science subdepartment focused on researching and experimenting on alien artifacts.
## Artifacts
At the start of each shift, the Science department will usually have access to at least two artifacts to experiment on. You can buy more by talking to the Cargo department.
By researching the unique things each artifact can do, you gain Research Points, increase the artifact's sale value, and potentially discover a useful ability or two that can help your department or the whole station!
## Artifact Nodes
<Box>
<GuideEntityEmbed Entity="ComplexXenoArtifact" Caption=""/>
<GuideEntityEmbed Entity="SimpleXenoArtifactItem" Caption=""/>
</Box>
Artifacts consist of a randomly-generated graph structure. They consist of nodes connected to each other by edges, the traversal of which is the main goal of the scientists working on them.
Artifacts consist of a randomly-generated tree of nodes. These nodes have a "[color=#a4885c]depth[/color]", representing how dangerous the node is, and the number of other nodes connected to it, called "[color=#a4885c]edges[/color]",
Each node has two main components: a [color=#a4885c]stimulus[/color] and a [color=#a4885c]reaction[/color]. A stimulus is the external behavior that triggers the reaction. Some reactions are instantaneous effects while others are permanent changes. Triggering the reaction causes the artifact to move to one of the node's edges.
Artifacts always start at depth zero, the root of the tree. Travelling the tree to find as many nodes as possible is the main goal of the scientists working on them. Knowledge is extracted from nodes to gain Research Points and increase the artifact's sale value.
With these basic principles, you can begin to grasp how the different nodes of an artifact are interconnected, and how one can move between them by repeatedly activating nodes.
Each node has two components: its [color=#a4885c]stimulus[/color] and a [color=#a4885c]reaction[/color].
While it might seem random to an untrained eye, a skilled scientist can learn to understand the internal structure of any artifact.
A stimulus is the external behavior that triggers the reaction. There's a variety of these, and higher depth nodes have more difficult to accomplish stimuli. Some stimuli will need improvisation to trigger, and you may need to talk to other departments to get everything you need.
Some reactions are instantaneous effects while others are permanent changes. Once an artifact is triggered, the reaction causes the artifact to randomly move to another node it is linked to.
With some experimental science, you can begin to grasp how the different nodes of an artifact are connected, and how to move between them by repeatedly activating nodes.
All non-zero-depth nodes will have exactly one edge that leads up to its parent node. All other edges a node has lead down to the next depth.
## Artifact Analyzer and Analysis Console
<Box>
@@ -22,13 +32,26 @@ While it might seem random to an untrained eye, a skilled scientist can learn to
</Box>
The main equipment that you'll be using for Xenoarchaeology is the [color=#a4885c]artifact analyzer[/color] and the [color=#a4885c]analysis console[/color]. You can use these to create reports that contain valuable information about an artifact.
To set them up, simply link them with a network configurator, set an artifact on top of the analyzer, and press the [color=#a4885c]Scan[/color] button.
To set them up, simply link them with a network configurator and set an artifact on top of the analyzer. Every station has at least one of these machines already set up.
Using the console, you can extract points from the artifact using the [color=#a4885c]Extract[/color] button. The amount of points you extract is based on how many new nodes have been activated, since last extracting. You can extract multiple times, there is no reason not to!!!
Use the console's [color=#a4885c]scan[/color] button to discover what stimulus the artifact needs and what its reaction will do. Scanning takes thirty seconds.
Use the [color=#a4885c]print[/color] button to save the scan result, so you can refer to it later.
Once you've discovered a new node, you can extract points from the artifact using the [color=#a4885c]Extract[/color] button.
## Assembling Artifacts
<GuideEntityEmbed Entity="ArtifactFragment" Caption="Artifact Fragment"/>
It is possible to gather multiple artifact fragments and assemble them into a working artifact. You can ask for these from Salvage, they usually find these while mining asteroids or on Expeditions.
It is possible to gather multiple artifact fragments and assemble them into a working artifact. You can ask for these from Salvage, who usually find these while mining asteroids or on Expeditions.
## Traversal Bias
<Box>
<GuideEntityEmbed Entity="MachineArtifactAnalyzer"/>
</Box>
Artifacts placed on top of a powered artifact analyzer are subjected to a bias which affects which node they will move to after being activated. The bias can be set in the artifact console.
There are two types of biases:
- [color=#a4885c]Up:[/color] favors nodes closer to the origin. Results in a decrease of depth.
- [color=#a4885c]Down:[/color] favors nodes farther away from the origin. Results in an increase of depth.
</Document>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@@ -7,6 +7,9 @@
"y": 64
},
"states": [
{
"name": "icon"
},
{
"name": "glass"
},

View File

@@ -269,6 +269,8 @@ ClothingHeadHatHairflower: FoodPoppy
RPED: null
# 2024-03-30
TraversalDistorterMachineCircuitboard: null
MachineTraversalDistorter: null
# These are technically not equivalent, but it probably makes more sense to replace any existing SCAF stuff with SOME kind of armor, instead of just deleting it outright.
ClothingHeadHelmetScaf: ClothingHeadHelmetBasic
ClothingOuterArmorScaf: ClothingOuterArmorBasic