diff --git a/Content.Server/EntityEffects/Effects/ArtifactUnlock.cs b/Content.Server/EntityEffects/Effects/ArtifactUnlock.cs
new file mode 100644
index 0000000000..21454ff7a7
--- /dev/null
+++ b/Content.Server/EntityEffects/Effects/ArtifactUnlock.cs
@@ -0,0 +1,47 @@
+using Content.Server.Popups;
+using Content.Server.Xenoarchaeology.Artifact;
+using Content.Shared.EntityEffects;
+using Content.Shared.Popups;
+using Content.Shared.Xenoarchaeology.Artifact.Components;
+using JetBrains.Annotations;
+using Robust.Shared.Prototypes;
+
+namespace Content.Server.EntityEffects.Effects;
+
+///
+/// Sets an artifact into the unlocking state and marks the artifexium effect as true.
+/// This is a very specific behavior intended for a specific chem.
+///
+[UsedImplicitly]
+public sealed partial class ArtifactUnlock : EntityEffect
+{
+ public override void Effect(EntityEffectBaseArgs args)
+ {
+ var entMan = args.EntityManager;
+ var xenoArtifactSys = entMan.System();
+ var popupSys = entMan.System();
+
+ if (!entMan.TryGetComponent(args.TargetEntity, out var xenoArtifact))
+ return;
+
+ if (!entMan.TryGetComponent(args.TargetEntity, out var unlocking))
+ {
+ xenoArtifactSys.TriggerXenoArtifact((args.TargetEntity, xenoArtifact), null, force: true);
+ unlocking = entMan.EnsureComponent(args.TargetEntity);
+ }
+ else if (!unlocking.ArtifexiumApplied)
+ {
+ popupSys.PopupEntity(Loc.GetString("artifact-activation-artifexium"), args.TargetEntity, PopupType.Medium);
+ }
+
+ if (unlocking.ArtifexiumApplied)
+ return;
+
+ xenoArtifactSys.SetArtifexiumApplied((args.TargetEntity, unlocking), true);
+ }
+
+ protected override string ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys)
+ {
+ return Loc.GetString("reagent-effect-guidebook-artifact-unlock", ("chance", Probability));
+ }
+}
diff --git a/Content.Shared/Xenoarchaeology/Artifact/Components/XenoArtifactUnlockingComponent.cs b/Content.Shared/Xenoarchaeology/Artifact/Components/XenoArtifactUnlockingComponent.cs
index 13b07f4474..6b2351cc2f 100644
--- a/Content.Shared/Xenoarchaeology/Artifact/Components/XenoArtifactUnlockingComponent.cs
+++ b/Content.Shared/Xenoarchaeology/Artifact/Components/XenoArtifactUnlockingComponent.cs
@@ -21,6 +21,12 @@ public sealed partial class XenoArtifactUnlockingComponent : Component
[DataField, AutoNetworkedField, AutoPausedField]
public TimeSpan EndTime;
+ ///
+ /// Tracks if artifexium has been applied, which changes the unlock behavior slightly.
+ ///
+ [DataField, AutoNetworkedField]
+ public bool ArtifexiumApplied;
+
///
/// The sound that plays when an artifact finishes unlocking successfully (with node unlocked).
///
diff --git a/Content.Shared/Xenoarchaeology/Artifact/SharedXenoArtifactSystem.Unlock.cs b/Content.Shared/Xenoarchaeology/Artifact/SharedXenoArtifactSystem.Unlock.cs
index 9786e65478..57d6502bfb 100644
--- a/Content.Shared/Xenoarchaeology/Artifact/SharedXenoArtifactSystem.Unlock.cs
+++ b/Content.Shared/Xenoarchaeology/Artifact/SharedXenoArtifactSystem.Unlock.cs
@@ -3,6 +3,8 @@ using System.Linq;
using Content.Shared.Xenoarchaeology.Artifact.Components;
using Robust.Shared.Audio;
using Robust.Shared.Audio.Systems;
+using Robust.Shared.Collections;
+using Robust.Shared.Random;
namespace Content.Shared.Xenoarchaeology.Artifact;
@@ -94,14 +96,14 @@ public abstract partial class SharedXenoArtifactSystem
}
RemComp(ent, unlockingComponent);
- RiseUnlockingFinished(ent, node);
+ RaiseUnlockingFinished(ent, node);
artifactComponent.NextUnlockTime = _timing.CurTime + artifactComponent.UnlockStateRefractory;
}
public void CancelUnlockingState(Entity ent)
{
RemComp(ent, ent.Comp1);
- RiseUnlockingFinished(ent, null);
+ RaiseUnlockingFinished(ent, null);
}
///
@@ -113,9 +115,10 @@ public abstract partial class SharedXenoArtifactSystem
)
{
node = null;
+ var potentialNodes = new ValueList>();
var artifactUnlockingComponent = ent.Comp1;
- foreach (var nodeIndex in artifactUnlockingComponent.TriggeredNodeIndexes)
+ foreach (var nodeIndex in GetAllNodeIndices((ent, ent)))
{
var artifactComponent = ent.Comp2;
var curNode = GetNode((ent, artifactComponent), nodeIndex);
@@ -125,15 +128,29 @@ public abstract partial class SharedXenoArtifactSystem
var requiredIndices = GetPredecessorNodes((ent, artifactComponent), nodeIndex);
requiredIndices.Add(nodeIndex);
- // Make sure the two sets are identical
- if (requiredIndices.Count != artifactUnlockingComponent.TriggeredNodeIndexes.Count
- || !artifactUnlockingComponent.TriggeredNodeIndexes.All(requiredIndices.Contains))
+ if (!ent.Comp1.ArtifexiumApplied)
+ {
+ // Make sure the two sets are identical
+ if (requiredIndices.Count != artifactUnlockingComponent.TriggeredNodeIndexes.Count
+ || !artifactUnlockingComponent.TriggeredNodeIndexes.All(requiredIndices.Contains))
+ continue;
+
+ node = curNode;
+ return true; // exit early
+ }
+
+ // If we apply artifexium, check that the sets are identical EXCEPT for one extra node.
+ // This node is a "wildcard" and we'll make a pool so we can pick one to actually unlock.
+ if (!artifactUnlockingComponent.TriggeredNodeIndexes.All(requiredIndices.Contains) ||
+ requiredIndices.Count - 1 != artifactUnlockingComponent.TriggeredNodeIndexes.Count)
continue;
- node = curNode;
- return true;
+ potentialNodes.Add(curNode);
}
+ if (potentialNodes.Count != 0)
+ node = RobustRandom.Pick(potentialNodes);
+
return node != null;
}
@@ -143,7 +160,7 @@ public abstract partial class SharedXenoArtifactSystem
RaiseLocalEvent(ent.Owner, ref unlockingStartedEvent);
}
- private void RiseUnlockingFinished(
+ private void RaiseUnlockingFinished(
Entity ent,
Entity? node
)
diff --git a/Content.Shared/Xenoarchaeology/Artifact/SharedXenoArtifactSystem.XAT.cs b/Content.Shared/Xenoarchaeology/Artifact/SharedXenoArtifactSystem.XAT.cs
index 863f56134b..1ef85db27f 100644
--- a/Content.Shared/Xenoarchaeology/Artifact/SharedXenoArtifactSystem.XAT.cs
+++ b/Content.Shared/Xenoarchaeology/Artifact/SharedXenoArtifactSystem.XAT.cs
@@ -56,15 +56,13 @@ public abstract partial class SharedXenoArtifactSystem
///
/// Attempts to shift artifact into unlocking state, in which it is going to listen to interactions, that could trigger nodes.
///
- public void TriggerXenoArtifact(Entity ent, Entity node)
+ public void TriggerXenoArtifact(Entity ent, Entity? node, bool force = false)
{
// limits spontaneous chain activations, also prevents spamming every triggering tool to activate nodes
// without real knowledge about triggers
- if (_timing.CurTime < ent.Comp.NextUnlockTime)
+ if (!force && _timing.CurTime < ent.Comp.NextUnlockTime)
return;
- var index = GetIndex(ent, node);
-
if (!_unlockingQuery.TryGetComponent(ent, out var unlockingComp))
{
unlockingComp = EnsureComp(ent);
@@ -73,25 +71,34 @@ public abstract partial class SharedXenoArtifactSystem
if (_net.IsServer)
_popup.PopupEntity(Loc.GetString("artifact-unlock-state-begin"), ent);
+ Dirty(ent);
}
- else
+ else if (node != null)
{
+ var index = GetIndex(ent, node.Value);
+
var predecessorNodeIndices = GetPredecessorNodes((ent, ent), index);
var successorNodeIndices = GetSuccessorNodes((ent, ent), index);
- if(unlockingComp.TriggeredNodeIndexes.Count == 0
- || unlockingComp.TriggeredNodeIndexes.All(
- x => predecessorNodeIndices.Contains(x) || successorNodeIndices.Contains(x)
+ if (unlockingComp.TriggeredNodeIndexes.Count == 0
+ || unlockingComp.TriggeredNodeIndexes.All(
+ x => predecessorNodeIndices.Contains(x) || successorNodeIndices.Contains(x)
)
)
// we add time on each new trigger, if it is not going to fail us
unlockingComp.EndTime += ent.Comp.UnlockStateIncrementPerNode;
}
- if (unlockingComp.TriggeredNodeIndexes.Add(index))
+ if (node != null && unlockingComp.TriggeredNodeIndexes.Add(GetIndex(ent, node.Value)))
{
Dirty(ent, unlockingComp);
}
}
+
+ public void SetArtifexiumApplied(Entity ent, bool val)
+ {
+ ent.Comp.ArtifexiumApplied = val;
+ Dirty(ent);
+ }
}
///
diff --git a/Resources/Locale/en-US/guidebook/chemistry/effects.ftl b/Resources/Locale/en-US/guidebook/chemistry/effects.ftl
index 098403c84c..2a40d00f72 100644
--- a/Resources/Locale/en-US/guidebook/chemistry/effects.ftl
+++ b/Resources/Locale/en-US/guidebook/chemistry/effects.ftl
@@ -357,6 +357,12 @@ reagent-effect-guidebook-add-to-solution-reaction =
*[other] cause
} chemicals applied to an object to be added to its internal solution container
+reagent-effect-guidebook-artifact-unlock =
+ { $chance ->
+ [1] Helps
+ *[other] help
+ } unlock an alien artifact.
+
reagent-effect-guidebook-plant-attribute =
{ $chance ->
[1] Adjusts
diff --git a/Resources/Locale/en-US/xenoarchaeology/artifact-component.ftl b/Resources/Locale/en-US/xenoarchaeology/artifact-component.ftl
index b083d33f35..50fa136928 100644
--- a/Resources/Locale/en-US/xenoarchaeology/artifact-component.ftl
+++ b/Resources/Locale/en-US/xenoarchaeology/artifact-component.ftl
@@ -15,6 +15,7 @@ artifact-unlock-state-end-failure = It slows down before uneventfully stopping.
### Activation
artifact-activation-fail = Nothing happens...
+artifact-activation-artifexium = The liquid seeps into the pores of the artifact...
### Misc.
artifact-examine-trigger-desc = [color=gray][italic]Am I on your mind?[/italic][/color]
diff --git a/Resources/Prototypes/Entities/Objects/Specific/Xenoarchaeology/xenoartifacts.yml b/Resources/Prototypes/Entities/Objects/Specific/Xenoarchaeology/xenoartifacts.yml
index 74a78cee59..6fa30b7265 100644
--- a/Resources/Prototypes/Entities/Objects/Specific/Xenoarchaeology/xenoartifacts.yml
+++ b/Resources/Prototypes/Entities/Objects/Specific/Xenoarchaeology/xenoartifacts.yml
@@ -45,6 +45,10 @@
# These components are needed for certain triggers to work.
- type: RadiationReceiver
- type: Reactive
+ groups:
+ Flammable: [Touch]
+ Extinguish: [Touch]
+ Acidic: [Touch]
- type: entity
id: ActionArtifactActivate
diff --git a/Resources/Prototypes/Reagents/chemicals.yml b/Resources/Prototypes/Reagents/chemicals.yml
index be5473fb8c..85f518bf5e 100644
--- a/Resources/Prototypes/Reagents/chemicals.yml
+++ b/Resources/Prototypes/Reagents/chemicals.yml
@@ -72,6 +72,14 @@
damage:
types:
Caustic: 2
+ reactiveEffects:
+ Acidic:
+ methods: [ Touch ]
+ effects:
+ - !type:ArtifactUnlock
+ conditions:
+ - !type:ReagentThreshold
+ min: 5
- type: reagent
id: Benzene