Restore Artifexium Effect (#36595)

* Restore Artifexium

* popup

* small tweaks
This commit is contained in:
Nemanja
2025-04-15 18:49:58 -04:00
committed by GitHub
parent a3b68f7181
commit 83c2fdb619
8 changed files with 114 additions and 18 deletions

View File

@@ -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;
/// <summary>
/// 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.
/// </summary>
[UsedImplicitly]
public sealed partial class ArtifactUnlock : EntityEffect
{
public override void Effect(EntityEffectBaseArgs args)
{
var entMan = args.EntityManager;
var xenoArtifactSys = entMan.System<XenoArtifactSystem>();
var popupSys = entMan.System<PopupSystem>();
if (!entMan.TryGetComponent<XenoArtifactComponent>(args.TargetEntity, out var xenoArtifact))
return;
if (!entMan.TryGetComponent<XenoArtifactUnlockingComponent>(args.TargetEntity, out var unlocking))
{
xenoArtifactSys.TriggerXenoArtifact((args.TargetEntity, xenoArtifact), null, force: true);
unlocking = entMan.EnsureComponent<XenoArtifactUnlockingComponent>(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));
}
}

View File

@@ -21,6 +21,12 @@ public sealed partial class XenoArtifactUnlockingComponent : Component
[DataField, AutoNetworkedField, AutoPausedField]
public TimeSpan EndTime;
/// <summary>
/// Tracks if artifexium has been applied, which changes the unlock behavior slightly.
/// </summary>
[DataField, AutoNetworkedField]
public bool ArtifexiumApplied;
/// <summary>
/// The sound that plays when an artifact finishes unlocking successfully (with node unlocked).
/// </summary>

View File

@@ -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<XenoArtifactUnlockingComponent, XenoArtifactComponent> ent)
{
RemComp(ent, ent.Comp1);
RiseUnlockingFinished(ent, null);
RaiseUnlockingFinished(ent, null);
}
/// <summary>
@@ -113,9 +115,10 @@ public abstract partial class SharedXenoArtifactSystem
)
{
node = null;
var potentialNodes = new ValueList<Entity<XenoArtifactNodeComponent>>();
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<XenoArtifactUnlockingComponent, XenoArtifactComponent> ent,
Entity<XenoArtifactNodeComponent>? node
)

View File

@@ -56,15 +56,13 @@ public abstract partial class SharedXenoArtifactSystem
/// <summary>
/// Attempts to shift artifact into unlocking state, in which it is going to listen to interactions, that could trigger nodes.
/// </summary>
public void TriggerXenoArtifact(Entity<XenoArtifactComponent> ent, Entity<XenoArtifactNodeComponent> node)
public void TriggerXenoArtifact(Entity<XenoArtifactComponent> ent, Entity<XenoArtifactNodeComponent>? 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<XenoArtifactUnlockingComponent>(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<XenoArtifactUnlockingComponent> ent, bool val)
{
ent.Comp.ArtifexiumApplied = val;
Dirty(ent);
}
}
/// <summary>

View File

@@ -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

View File

@@ -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]

View File

@@ -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

View File

@@ -72,6 +72,14 @@
damage:
types:
Caustic: 2
reactiveEffects:
Acidic:
methods: [ Touch ]
effects:
- !type:ArtifactUnlock
conditions:
- !type:ReagentThreshold
min: 5
- type: reagent
id: Benzene