using Content.Shared.Actions; using Content.Shared.Actions.Components; using Content.Shared.Destructible.Thresholds; using Content.Shared.EntityTable.EntitySelectors; using Content.Shared.Xenoarchaeology.Artifact.Prototypes; using Robust.Shared.Audio; using Robust.Shared.Containers; using Robust.Shared.GameStates; using Robust.Shared.Prototypes; using Robust.Shared.Utility; namespace Content.Shared.Xenoarchaeology.Artifact.Components; /// /// This is used for handling interactions with artifacts as well as /// storing data about artifact node graphs. /// [RegisterComponent, NetworkedComponent, Access(typeof(SharedXenoArtifactSystem)), AutoGenerateComponentState, AutoGenerateComponentPause] public sealed partial class XenoArtifactComponent : Component { public static string NodeContainerId = "node-container"; /// /// Marker, if nodes graph should be generated for artifact. /// [DataField] public bool IsGenerationRequired = true; /// /// Container for artifact graph node entities. /// [ViewVariables] public Container NodeContainer = default!; /// /// The nodes in this artifact that are currently "active." /// This is cached and updated when nodes are removed, added, or unlocked. /// [DataField, AutoNetworkedField] public List CachedActiveNodes = new(); /// /// Cache of interconnected node chunks - segments. /// This is cached and updated when nodes are removed, added, or unlocked. /// [DataField, AutoNetworkedField] public List> CachedSegments = new(); /// /// Marker, if true - node activations should not happen. /// [DataField, AutoNetworkedField] public bool Suppressed; /// /// A multiplier applied to the calculated point value /// to determine the monetary value of the artifact. /// [DataField] public float PriceMultiplier = 0.10f; #region Unlocking /// /// How long does the unlocking state last by default. /// [DataField] public TimeSpan UnlockStateDuration = TimeSpan.FromSeconds(6); /// /// By how much unlocking state should be prolonged for each node that was unlocked. /// [DataField] public TimeSpan UnlockStateIncrementPerNode = TimeSpan.FromSeconds(10); /// /// Minimum waiting time between unlock states. /// [DataField] public TimeSpan UnlockStateRefractory = TimeSpan.FromSeconds(5); /// /// When next unlock session can be triggered. /// [DataField, AutoPausedField] public TimeSpan NextUnlockTime; #endregion // NOTE: you should not be accessing any of these values directly. Use the methods in SharedXenoArtifactSystem.Graph #region Graph /// /// List of all nodes currently on this artifact. /// Indexes are used as a lookup table for . /// [DataField, AutoNetworkedField] public NetEntity?[] NodeVertices = []; /// /// Adjacency matrix that stores connections between this artifact's nodes. /// A value of "true" denotes an directed edge from node1 to node2, where the location of the vertex is (node1, node2) /// A value of "false" denotes no edge. /// [DataField, AutoNetworkedField] public List> NodeAdjacencyMatrix = new(); public int NodeAdjacencyMatrixRows => NodeAdjacencyMatrix.Count; public int NodeAdjacencyMatrixColumns => NodeAdjacencyMatrix.TryGetValue(0, out var value) ? value.Count : 0; #endregion #region GenerationInfo /// /// The total number of nodes that make up this artifact. /// [DataField] public MinMax NodeCount = new(10, 16); /// /// The amount of nodes that go in each segment. /// A segment is an interconnected series of nodes. /// [DataField] public MinMax SegmentSize = new(5, 8); /// /// For each "layer" in a segment (set of nodes with equal depth), how many will we generate? /// [DataField] public MinMax NodesPerSegmentLayer = new(1, 3); /// /// How man nodes can be randomly added on top of usual distribution (per layer). /// [DataField] public MinMax ScatterPerLayer = new(0, 2); /// /// Effects that can be used during this artifact generation. /// [DataField] public EntityTableSelector EffectsTable = new NestedSelector { TableId = "XenoArtifactEffectsDefaultTable" }; /// /// Triggers that can be used during this artefact generation. /// [DataField] public ProtoId TriggerWeights = "DefaultTriggers"; #endregion /// /// Sound effect to be played when artifact node is force-activated. /// [DataField] public SoundSpecifier? ForceActivationSoundSpecifier = new SoundCollectionSpecifier("ArtifactForceActivation") { Params = new() { Variation = 0.1f } }; /// /// Action that allows the artifact to self activate. /// [DataField] public EntProtoId SelfActivateAction = "ActionArtifactActivate"; } /// /// Event raised by sentient artifact to activate itself at no durability cost. /// public sealed partial class ArtifactSelfActivateEvent : InstantActionEvent;