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; /// Controls behaviour of artifact node scanner device. public abstract class SharedNodeScannerSystem : EntitySystem { [Dependency] private readonly UseDelaySystem _useDelay = default!; [Dependency] private readonly SharedXenoArtifactSystem _artifact = default!; [Dependency] private readonly IGameTiming _timing = default!; /// public override void Initialize() { SubscribeLocalEvent(OnBeforeRangedInteract); SubscribeLocalEvent>(AddScanVerb); } private void OnBeforeRangedInteract(EntityUid uid, NodeScannerComponent component, BeforeRangedInteractEvent args) { if (args.Handled || !args.CanReach || args.Target is not { } target) return; Entity unlockingEnt = TryComp(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 args) { if (!args.CanAccess) return; if (!TryComp(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 device, Entity unlockingEnt, EntityUid actor ) { if (!_timing.IsFirstTimePredicted) return; if (TryComp(device, out UseDelayComponent? useDelay) && !_useDelay.TryResetDelay((device, useDelay), true)) return; if (!TryComp(unlockingEnt.Owner, out var artifactComponent)) return; TryOpenUi(device, actor); TimeSpan? waitTime = null; HashSet triggeredNodeNames; ArtifactState artifactState; if (unlockingEnt.Comp == null) { triggeredNodeNames = new HashSet(); 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(triggeredIndexes.Count); foreach (var triggeredIndex in triggeredIndexes) { var node = _artifact.GetNode((unlockingEnt.Owner, artifactComponent), triggeredIndex); var triggeredNodeName = (CompOrNull(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 device, EntityUid actor); }