diff --git a/Content.Server/_Impstation/Xenoarchaeology/XenoArtifacts/Effects/Components/ScrambleDNAArtifactComponent.cs b/Content.Server/_Impstation/Xenoarchaeology/XenoArtifacts/Effects/Components/ScrambleDNAArtifactComponent.cs new file mode 100644 index 00000000000000..114810bf57de86 --- /dev/null +++ b/Content.Server/_Impstation/Xenoarchaeology/XenoArtifacts/Effects/Components/ScrambleDNAArtifactComponent.cs @@ -0,0 +1,34 @@ +namespace Content.Server.Xenoarchaeology.XenoArtifacts.Effects.Components; + +/// +/// Scrambles DNA of some number of people within some range, possibly outside of their species +/// +[RegisterComponent] +public sealed partial class ScrambleDNAArtifactComponent : Component +{ + /// + /// Distance from the artifact find people to scramble DNA + /// + [DataField("range"), ViewVariables(VVAccess.ReadWrite)] + public float Range = 6f; + + /// + /// Number of people to DNA scramble + /// + [DataField("count"), ViewVariables(VVAccess.ReadWrite)] + public int Count = 1; + + /// + /// Force scrambling to respect initial species + /// + [DataField("withinSpecies"), ViewVariables(VVAccess.ReadWrite)] + public bool WithinSpecies = true; + + /// + /// if WithinSpecies is false, what species cannot be rolled + /// + [DataField("excludedSpecies"), ViewVariables(VVAccess.ReadWrite)] + public HashSet? ExcludedSpecies = null; + + +} diff --git a/Content.Server/_Impstation/Xenoarchaeology/XenoArtifacts/Effects/Systems/KnockdownArtifactSystem.cs b/Content.Server/_Impstation/Xenoarchaeology/XenoArtifacts/Effects/Systems/KnockdownArtifactSystem.cs index eba2ef50dff49c..0c7061455df6c8 100644 --- a/Content.Server/_Impstation/Xenoarchaeology/XenoArtifacts/Effects/Systems/KnockdownArtifactSystem.cs +++ b/Content.Server/_Impstation/Xenoarchaeology/XenoArtifacts/Effects/Systems/KnockdownArtifactSystem.cs @@ -44,8 +44,6 @@ private void OnActivated(EntityUid uid, KnockdownArtifactComponent component, Ar _stuns.TryParalyze(child, TimeSpan.FromSeconds(component.KnockdownTime), true, status); } - - } else // knock over only people in range { diff --git a/Content.Server/_Impstation/Xenoarchaeology/XenoArtifacts/Effects/Systems/ScrambleDNAArtifactSystem.cs b/Content.Server/_Impstation/Xenoarchaeology/XenoArtifacts/Effects/Systems/ScrambleDNAArtifactSystem.cs new file mode 100644 index 00000000000000..7ceee0f6303945 --- /dev/null +++ b/Content.Server/_Impstation/Xenoarchaeology/XenoArtifacts/Effects/Systems/ScrambleDNAArtifactSystem.cs @@ -0,0 +1,79 @@ +using Content.Server.Xenoarchaeology.XenoArtifacts.Effects.Components; +using Content.Server.Xenoarchaeology.XenoArtifacts.Events; +using Content.Shared.Preferences; +using Content.Server.Humanoid; +using System.Linq; +using Robust.Shared.Random; +using Content.Shared.Humanoid; +using Content.Shared.Forensics; +using Content.Server.Forensics; + + + +namespace Content.Server.Xenoarchaeology.XenoArtifacts.Effects.Systems; + +public sealed class ScrambleDNAArtifactSystem : EntitySystem +{ + [Dependency] private readonly EntityLookupSystem _lookup = default!; + [Dependency] private readonly IRobustRandom _random = default!; + [Dependency] private readonly HumanoidAppearanceSystem _humanoidAppearance = default!; + [Dependency] private readonly MetaDataSystem _metaData = default!; + [Dependency] private readonly ForensicsSystem _forensicsSystem = default!; + + + + /// + public override void Initialize() + { + SubscribeLocalEvent(OnActivated); + } + + private void OnActivated(EntityUid uid, ScrambleDNAArtifactComponent component, ArtifactActivatedEvent args) + { + // Get all entities in range, and the person who activated the artifact even if they are not within range + var ents = _lookup.GetEntitiesInRange(uid, component.Range); + if (args.Activator != null) + ents.Add(args.Activator.Value); + + //Extract the people who can be scrambled + var possibleVictims = new List(); + foreach (var ent in ents) + { + if (HasComp(ent)) + possibleVictims.Add(ent); + } + + //Select random targets to scramble DNA + var numScrambled = 0; + while (numScrambled < component.Count){ + var targetIndex = _random.Next(0, possibleVictims.Count); + var target = possibleVictims.ElementAt(targetIndex); + possibleVictims.Remove(target); + + ScrambleTargetDNA(target, component); + numScrambled ++; + } + } + + private void ScrambleTargetDNA(EntityUid target, ScrambleDNAArtifactComponent component) + { + if (TryComp(target, out var humanoid)) + { + var newProfile = (component.WithinSpecies ? HumanoidCharacterProfile.RandomWithSpecies(humanoid.Species) : HumanoidCharacterProfile.Random(component.ExcludedSpecies)); + _humanoidAppearance.LoadProfile(target, newProfile, humanoid); + _metaData.SetEntityName(target, newProfile.Name); + if (TryComp(target, out var dna)) + { + dna.DNA = _forensicsSystem.GenerateDNA(); + + var ev = new GenerateDnaEvent { Owner = target, DNA = dna.DNA }; + RaiseLocalEvent(target, ref ev); + } + if (TryComp(target, out var fingerprint)) + { + fingerprint.Fingerprint = _forensicsSystem.GenerateFingerprint(); + } + } + } + +} diff --git a/Resources/Prototypes/XenoArch/Effects/normal_effects.yml b/Resources/Prototypes/XenoArch/Effects/normal_effects.yml index 87ded0225ce13e..60f7e32dfdd5ab 100644 --- a/Resources/Prototypes/XenoArch/Effects/normal_effects.yml +++ b/Resources/Prototypes/XenoArch/Effects/normal_effects.yml @@ -1081,6 +1081,17 @@ duration: 10 count: 1 +- type: artifactEffect + id: EffectScrambleSingleRare + targetDepth: 4 + effectHint: artifact-effect-hint-polymorph + effectProb: 0.01 + components: + - type: ScrambleDNAArtifact + range: 4 + withinSpecies: true + count: 1 + - type: artifactEffect id: EffectSingulo targetDepth: 10