using Content.Shared.Administration.Logs; using Content.Shared.Database; using Content.Shared.Interaction; using Content.Shared.Interaction.Events; using Content.Shared.Timing; using Content.Shared.Xenoarchaeology.Artifact.Components; using Robust.Shared.Map; namespace Content.Shared.Xenoarchaeology.Artifact; public abstract partial class SharedXenoArtifactSystem { [Dependency] private readonly UseDelaySystem _useDelay = default!; [Dependency] private readonly ISharedAdminLogManager _adminLogger = default!; private void InitializeXAE() { SubscribeLocalEvent(OnUseInHand); SubscribeLocalEvent(OnAfterInteract); SubscribeLocalEvent(OnActivateInWorld); } private void OnUseInHand(Entity ent, ref UseInHandEvent args) { if (args.Handled) return; args.Handled = TryActivateXenoArtifact(ent, args.User, args.User, Transform(args.User).Coordinates); } private void OnAfterInteract(Entity ent, ref AfterInteractEvent args) { if (args.Handled || !args.CanReach) return; args.Handled = TryActivateXenoArtifact(ent, args.User, args.Target, args.ClickLocation); } private void OnActivateInWorld(Entity ent, ref ActivateInWorldEvent args) { if (args.Handled || !args.Complex) return; args.Handled = TryActivateXenoArtifact(ent, args.User, args.Target, Transform(args.Target).Coordinates); } /// /// Attempts to activate artifact nodes. 'active' are nodes that are marked as 'unlocked' and have no other successors, marked as 'unlocked'. /// /// Artifact entity, for which attempt to activate was made. /// Character that attempted to activate artifact. /// Target, on which artifact activation attempt was used (for hand-held artifact - it can be 'clicked' over someone). /// Coordinates of entity. /// Whether this activation will deplete durability on the activated nodes. /// True, if activation was successful, false otherwise. public bool TryActivateXenoArtifact( Entity artifact, EntityUid? user, EntityUid? target, EntityCoordinates coordinates, bool consumeDurability = true ) { XenoArtifactComponent xenoArtifactComponent = artifact; if (xenoArtifactComponent.Suppressed) return false; if (TryComp(artifact, out var delay) && !_useDelay.TryResetDelay((artifact, delay), true)) return false; var success = false; foreach (var node in GetActiveNodes(artifact)) { success |= ActivateNode(artifact, node, user, target, coordinates, consumeDurability: consumeDurability); } if (!success) { _popup.PopupClient(Loc.GetString("artifact-activation-fail"), artifact, user); return false; } // we raised event for each node activation, // now we raise event for artifact itself. For animations and stuff. var ev = new XenoArtifactActivatedEvent( artifact, user, target, coordinates ); RaiseLocalEvent(artifact, ref ev); if (user.HasValue) _audio.PlayPredicted(xenoArtifactComponent.ForceActivationSoundSpecifier, artifact, user); else _audio.PlayPvs(xenoArtifactComponent.ForceActivationSoundSpecifier, artifact); return true; } /// /// Pushes node activation event and updates durability for activated node. /// /// Artifact entity, for which attempt to activate was made. /// Node entity, effect of which should be activated. /// Character that attempted to activate artifact. /// Target, on which artifact activation attempt was used (for hand-held artifact - it can be 'clicked' over someone). /// Coordinates of entity. /// Marker, if node durability should be adjusted as a result of activation. /// True, if activation was successful, false otherwise. public bool ActivateNode( Entity artifact, Entity node, EntityUid? user, EntityUid? target, EntityCoordinates coordinates, bool consumeDurability = true ) { if (node.Comp.Degraded) return false; _adminLogger.Add( LogType.ArtifactNode, LogImpact.Low, $"{ToPrettyString(artifact.Owner)} node {ToPrettyString(node)} got activated at {coordinates}" ); if (consumeDurability) { AdjustNodeDurability((node, node.Comp), -1); } var ev = new XenoArtifactNodeActivatedEvent(artifact, node, user, target, coordinates); RaiseLocalEvent(node, ref ev); return true; } } /// /// Event of node activation. Should lead to node effect being activated. /// /// Artifact entity, for which attempt to activate was made. /// Node entity, effect of which should be activated. /// Character that attempted to activate artifact. /// Target, on which artifact activation attempt was used (for hand-held artifact - it can be 'clicked' over someone). /// Coordinates of entity. [ByRefEvent] public readonly record struct XenoArtifactNodeActivatedEvent( Entity Artifact, Entity Node, EntityUid? User, EntityUid? Target, EntityCoordinates Coordinates ); [ByRefEvent] public readonly record struct XenoArtifactActivatedEvent( Entity Artifact, EntityUid? User, EntityUid? Target, EntityCoordinates Coordinates );