Files
crystall-punk-14/Content.Shared/Xenoarchaeology/Equipment/SharedNodeScannerSystem.cs
Fildrance d38042a0c0 3mo xeno archeology (first phase) (#33370)
* DAG Adjacency Matrix & Tests

* Fix sandbox type errors

* First pass on procgen

* Procgen adjustments

* Networking

* Cruft and god and beauty and analysis console

* convert to data types that dont make me want to kill myself

* starting work on console UI

* drawing nodes n shit

* damn that ui FUCKS

* XAT

* Add a bunch of basic triggers

* Fix trigger gen

* Add node info into the analysis console UI

* Add node unlocking

* more trigger cuz thats pretty cool

* final triggers + incorporate gnostic faith

* some ui changes, mostly

* Fix orphaned procgen segments

* its not random dipshit

* yeah... this one will make pjb happy....

* we call it a day for the UI

* imagine... shared power code...

* extraction WIP but we gotta sidequest momentarily

* oh hey would you look at that its the actual functionality

* distrotrased

* Small departure for randomness.

* ok yep yep indeed that is an effect very cool.

* thanos snap oldcode

* fuck it we ball

* feat: node scanner now displays triggered nodes. Removed unused old artifact systems and related code (most of it). xml-doc and minor fixups.

* refactor: most of preparations, cleanup and groundwork. also segment-related tests

* feature: all basic effects returning

* feat: finished effects lits, created weight lists for struct and handheld artifacts, fixed throw trigger and music ApplyComponent artifact effects not working

* feat: prevent non-first-time-predicted calls in shared artifact effect systems

* fix: remove gun effect from artifact effects - as it interferes with 'activate artefact' action

* fix: foam reagent selection, neat ApplyComponents art effect scenarios, handheld art is RadiationReceiver again

* fix: moved spawn/ pry&throw effect systems back to server part of code - entity duplication bugs were not quite fun

* refactor: fix protos

* refactor: fix linter

* fix: fix old artifact component names in yml

* fix: no more throwing error on artifact spawn with empty XAEFoamComponent.Reagents

* fix: removed old component usage in maps

* fix: remove more deleted components from map

* fix: ContainerContainer is now part of initial artifact entity, it won't be affecting UninitializedSaveTest

* refactor: fix tests, add loc description to toolshed commands

* Changed node scanner to tell the whole story about current artifact state

* refactor: remove excessive get of EntityCoordinates in XAE systems, removed Value access in NodeScannerDisplay

* fix: turned off TriggerInteraction, removed XAESpawn usage and system, EmpSystem now can use EntityCoordinates,

* fix: moved SharedXenoArtifactSystem.CancelUnlockingOnGraphStructureChange into RebuildXenoArtifactMetaData to lessen code coupling

* fix: XenoArtifactEffectJunkSpawn moved invalid rolls declaration

* refactor: set default value for XenoArtifactComponent.EffectsTable for tests

* fix: now explosions XAE can be activated for effect

* refactor: added some usedelay so artifactuse would'nt be spammed

* refactor: artifact-related hints improvements

* fix: artifact no longer spawns fauna into itself

* refactor: xml-doc and minor refactoring

* refactor: xml-doc for Xeno Artifact systems, renaming of questionable XAT systems

* map for playtest, TODO REVERT THIS

* fix: magboots trigger art from a mile

* refactor: bind artifact animation to unlocking state

* feat: radiation dmg now have reference to source (and artifacts won't irradiate themselves)

* fix: random artifact node durability now is rolled for max and not current value

* refactor: gas effects are more rare, hand-held artifact effects are filtered properly now, rad dmg trigger now requires only 20 dmg for activation

* feat: animations and sound effects for artifact force-use and failed finish of unlocking phase

* use only 1 file with art use animation

* refactor: minor artifact dmg triggers tuning

* feat: now nodes that CAN be unlocked are displayed with specific color in console.

* feat: now unlocking stage time is dynamic and it depends on amount of triggers player activated correctly. Failed one stops incrementing

* feat: now non-active unlocked nodes return more points if durability was not wasted

* feat: now puddle/foam effects change description of node

* fix: fix test failure

* refactor: renamed phasing effect, fixed failing test for elkridge

* minor balance changes

* refactor: split rare materials into separate effects

* feat: unlocked nodes without successor wont listen to unlocks, node unlock is not activating node

* fix: removed OnIrradiatedEvent duplicate c-tor

* revert changes of reach for playtest

* revert last row empty line removal on reach.yml

* fix: fix PVS bug, born from attempt to relay event to art nodes that were not synced yet to the client

* fix: fix elkridge for tests (again)

* refactor: xml-doc, more stuff predicted, allocation optimization in XAE/XAT systems

* refactor: naming

* refactor: extract variable refactor for XAEApplyComponentsSystem.OnActivated insides

* fix: duplicate xeno artifact unlocking sound fixed

* feat: CreatePuddle xeno artifact effect now can have min and max borders for chamicals to be drafted, minor XAECreatePuddleSystem refactor

* feat: networking for shared XAE components + xml-doc leftovers

* refactor: more xml-doc, fix XAEApplyComponentsComponent.Components not being serializable but trying to be

* refactor: xml-docs and XAEThrowThingsAroundSystem now uses circle and not box for prying tiles

* refactor: xml-docs, minor refactors

* revert XenoArtifactCommand.ArtifactPrototype being PrototId

* refactor: simplify the way ExtractionResearchLabel works

---------

Co-authored-by: EmoGarbage404 <retron404@gmail.com>
Co-authored-by: pa.pecherskij <pa.pecherskij@interfax.ru>
2025-04-15 10:34:53 +10:00

121 lines
4.2 KiB
C#

using Content.Shared.Interaction;
using Content.Shared.NameIdentifier;
using Content.Shared.Timing;
using Content.Shared.Verbs;
using Content.Shared.Xenoarchaeology.Artifact;
using Content.Shared.Xenoarchaeology.Artifact.Components;
using Content.Shared.Xenoarchaeology.Equipment.Components;
using Robust.Shared.Timing;
namespace Content.Shared.Xenoarchaeology.Equipment;
/// <summary> Controls behaviour of artifact node scanner device. </summary>
public abstract class SharedNodeScannerSystem : EntitySystem
{
[Dependency] private readonly UseDelaySystem _useDelay = default!;
[Dependency] private readonly SharedXenoArtifactSystem _artifact = default!;
[Dependency] private readonly IGameTiming _timing = default!;
/// <inheritdoc/>
public override void Initialize()
{
SubscribeLocalEvent<NodeScannerComponent, BeforeRangedInteractEvent>(OnBeforeRangedInteract);
SubscribeLocalEvent<NodeScannerComponent, GetVerbsEvent<UtilityVerb>>(AddScanVerb);
}
private void OnBeforeRangedInteract(EntityUid uid, NodeScannerComponent component, BeforeRangedInteractEvent args)
{
if (args.Handled || !args.CanReach || args.Target is not { } target)
return;
Entity<XenoArtifactUnlockingComponent?> unlockingEnt = TryComp<XenoArtifactUnlockingComponent>(target, out var unlockingComponent)
? (target, unlockingComponent)
: (target, null);
TryMakeActiveNodesSnapshot((uid, component), unlockingEnt, args.User);
args.Handled = true;
}
private void AddScanVerb(EntityUid uid, NodeScannerComponent component, GetVerbsEvent<UtilityVerb> args)
{
if (!args.CanAccess)
return;
if (!TryComp<XenoArtifactUnlockingComponent>(args.Target, out var unlockingComponent))
return;
var verb = new UtilityVerb
{
Act = () =>
{
TryMakeActiveNodesSnapshot((uid, component), (args.Target, unlockingComponent), args.User);
},
Text = Loc.GetString("node-scan-tooltip")
};
args.Verbs.Add(verb);
}
private void TryMakeActiveNodesSnapshot(
Entity<NodeScannerComponent> device,
Entity<XenoArtifactUnlockingComponent?> unlockingEnt,
EntityUid actor
)
{
if (!_timing.IsFirstTimePredicted)
return;
if (TryComp(device, out UseDelayComponent? useDelay)
&& !_useDelay.TryResetDelay((device, useDelay), true))
return;
if (!TryComp<XenoArtifactComponent>(unlockingEnt.Owner, out var artifactComponent))
return;
TryOpenUi(device, actor);
TimeSpan? waitTime = null;
HashSet<string> triggeredNodeNames;
ArtifactState artifactState;
if (unlockingEnt.Comp == null)
{
triggeredNodeNames = new HashSet<string>();
var timeToUnlockAvailable = artifactComponent.NextUnlockTime - _timing.CurTime;
if (timeToUnlockAvailable > TimeSpan.Zero)
{
artifactState = ArtifactState.Cooldown;
waitTime = timeToUnlockAvailable;
}
else
{
artifactState = ArtifactState.Ready;
}
}
else
{
var triggeredIndexes = unlockingEnt.Comp.TriggeredNodeIndexes;
triggeredNodeNames = new HashSet<string>(triggeredIndexes.Count);
foreach (var triggeredIndex in triggeredIndexes)
{
var node = _artifact.GetNode((unlockingEnt.Owner, artifactComponent), triggeredIndex);
var triggeredNodeName = (CompOrNull<NameIdentifierComponent>(node)?.Identifier ?? 0).ToString("D3");
triggeredNodeNames.Add(triggeredNodeName);
}
artifactState = ArtifactState.Unlocking;
waitTime = _timing.CurTime - unlockingEnt.Comp.EndTime;
}
device.Comp.ArtifactState = artifactState;
device.Comp.WaitTime = waitTime;
device.Comp.TriggeredNodesSnapshot = triggeredNodeNames;
device.Comp.ScannedAt = _timing.CurTime;
Dirty(device);
}
protected abstract void TryOpenUi(Entity<NodeScannerComponent> device, EntityUid actor);
}