diff --git a/Content.Server/Xenoarchaeology/Equipment/Components/BiasedArtifactComponent.cs b/Content.Server/Xenoarchaeology/Equipment/Components/BiasedArtifactComponent.cs new file mode 100644 index 0000000000..9b42e96ffb --- /dev/null +++ b/Content.Server/Xenoarchaeology/Equipment/Components/BiasedArtifactComponent.cs @@ -0,0 +1,12 @@ +namespace Content.Server.Xenoarchaeology.Equipment.Components; + +/// +/// This is used for artifacts that are biased to move +/// in a particular direction via the +/// +[RegisterComponent] +public sealed class BiasedArtifactComponent : Component +{ + [ViewVariables] + public EntityUid Provider; +} diff --git a/Content.Server/Xenoarchaeology/Equipment/Components/TraversalDistorterComponent.cs b/Content.Server/Xenoarchaeology/Equipment/Components/TraversalDistorterComponent.cs new file mode 100644 index 0000000000..3530b6af15 --- /dev/null +++ b/Content.Server/Xenoarchaeology/Equipment/Components/TraversalDistorterComponent.cs @@ -0,0 +1,36 @@ +using Content.Shared.Construction.Prototypes; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; + +namespace Content.Server.Xenoarchaeology.Equipment.Components; + +/// +/// This is used for a machine that biases +/// an artifact placed on it to move up/down +/// +[RegisterComponent] +public sealed class TraversalDistorterComponent : Component +{ + [ViewVariables(VVAccess.ReadWrite)] + public float BiasChance; + + [DataField("baseBiasChance")] + public float BaseBiasChance = 0.7f; + + [DataField("machinePartBiasChance", customTypeSerializer: typeof(PrototypeIdSerializer))] + public string MachinePartBiasChance = "ScanningModule"; + + [DataField("partRatingBiasChance")] + public float PartRatingBiasChance = 1.1f; + + [ViewVariables(VVAccess.ReadWrite)] + public BiasDirection BiasDirection = BiasDirection.In; + + public TimeSpan NextActivation = default!; + public TimeSpan ActivationDelay = TimeSpan.FromSeconds(1); +} + +public enum BiasDirection : byte +{ + In, //down the tree, towards depth 0 + Out //up the tree, away from depth 0 +} diff --git a/Content.Server/Xenoarchaeology/Equipment/Systems/TraversalDistorterSystem.cs b/Content.Server/Xenoarchaeology/Equipment/Systems/TraversalDistorterSystem.cs new file mode 100644 index 0000000000..f1dacaabca --- /dev/null +++ b/Content.Server/Xenoarchaeology/Equipment/Systems/TraversalDistorterSystem.cs @@ -0,0 +1,112 @@ +using Content.Server.Construction; +using Content.Server.Popups; +using Content.Server.Power.EntitySystems; +using Content.Server.Xenoarchaeology.Equipment.Components; +using Content.Server.Xenoarchaeology.XenoArtifacts; +using Content.Shared.Examine; +using Content.Shared.Interaction; +using Robust.Shared.Physics.Events; +using Robust.Shared.Player; +using Robust.Shared.Timing; + +namespace Content.Server.Xenoarchaeology.Equipment.Systems; + +public sealed class TraversalDistorterSystem : EntitySystem +{ + [Dependency] private readonly PopupSystem _popup = default!; + [Dependency] private readonly IGameTiming _timing = default!; + + /// + public override void Initialize() + { + SubscribeLocalEvent(OnInit); + + SubscribeLocalEvent(OnInteract); + SubscribeLocalEvent(OnExamine); + SubscribeLocalEvent(OnRefreshParts); + SubscribeLocalEvent(OnUpgradeExamine); + + SubscribeLocalEvent(OnCollide); + SubscribeLocalEvent(OnEndCollide); + } + + private void OnInit(EntityUid uid, TraversalDistorterComponent component, MapInitEvent args) + { + component.NextActivation = _timing.CurTime; + } + + private void OnInteract(EntityUid uid, TraversalDistorterComponent component, ActivateInWorldEvent args) + { + if (args.Handled || !this.IsPowered(uid, EntityManager)) + return; + if (_timing.CurTime < component.NextActivation) + return; + args.Handled = true; + component.NextActivation = _timing.CurTime + component.ActivationDelay; + + component.BiasDirection = component.BiasDirection == BiasDirection.In + ? BiasDirection.Out + : BiasDirection.In; + + var toPopup = string.Empty; + switch (component.BiasDirection) + { + case BiasDirection.In: + toPopup = Loc.GetString("traversal-distorter-set-in"); + break; + case BiasDirection.Out: + toPopup = Loc.GetString("traversal-distorter-set-out"); + break; + } + _popup.PopupEntity(toPopup, uid, Filter.Pvs(uid)); + } + + private void OnExamine(EntityUid uid, TraversalDistorterComponent component, ExaminedEvent args) + { + string examine = string.Empty; + switch (component.BiasDirection) + { + case BiasDirection.In: + examine = Loc.GetString("traversal-distorter-desc-in"); + break; + case BiasDirection.Out: + examine = Loc.GetString("traversal-distorter-desc-out"); + break; + } + args.Message.AddMarkup(examine); + } + + private void OnRefreshParts(EntityUid uid, TraversalDistorterComponent component, RefreshPartsEvent args) + { + var biasRating = args.PartRatings[component.MachinePartBiasChance]; + + component.BiasChance = component.BaseBiasChance * MathF.Pow(component.PartRatingBiasChance, biasRating - 1); + } + + private void OnUpgradeExamine(EntityUid uid, TraversalDistorterComponent component, UpgradeExamineEvent args) + { + args.AddPercentageUpgrade("traversal-distorter-upgrade-bias", component.BiasChance / component.BaseBiasChance); + } + + private void OnCollide(EntityUid uid, TraversalDistorterComponent component, ref StartCollideEvent args) + { + var otherEnt = args.OtherFixture.Body.Owner; + + if (!HasComp(otherEnt)) + return; + + var bias = EnsureComp(otherEnt); + bias.Provider = uid; + } + + private void OnEndCollide(EntityUid uid, TraversalDistorterComponent component, ref EndCollideEvent args) + { + var otherEnt = args.OtherFixture.Body.Owner; + + if (!HasComp(otherEnt)) + return; + + if (TryComp(otherEnt, out var bias) && bias.Provider == uid) + RemComp(otherEnt, bias); + } +} diff --git a/Content.Server/Xenoarchaeology/XenoArtifacts/ArtifactSystem.cs b/Content.Server/Xenoarchaeology/XenoArtifacts/ArtifactSystem.cs index 7b535e5b30..a84ad96deb 100644 --- a/Content.Server/Xenoarchaeology/XenoArtifacts/ArtifactSystem.cs +++ b/Content.Server/Xenoarchaeology/XenoArtifacts/ArtifactSystem.cs @@ -1,6 +1,8 @@ using System.Diagnostics.CodeAnalysis; using System.Linq; using Content.Server.Cargo.Systems; +using Content.Server.Power.EntitySystems; +using Content.Server.Xenoarchaeology.Equipment.Components; using Content.Server.Xenoarchaeology.XenoArtifacts.Events; using JetBrains.Annotations; using Robust.Shared.Random; @@ -160,17 +162,50 @@ public sealed partial class ArtifactSystem : EntitySystem component.CurrentNode.Triggered = true; if (component.CurrentNode.Edges.Any()) { - var undiscoveredNodes = component.CurrentNode.Edges.Where(x => !x.Discovered).ToList(); - - var newNode = _random.Pick(component.CurrentNode.Edges); - if (undiscoveredNodes.Any() && _random.Prob(0.75f)) - { - newNode = _random.Pick(undiscoveredNodes); - } + var newNode = GetNewNode(component); + if (newNode == null) + return; EnterNode(uid, ref newNode, component); } } + private ArtifactNode? GetNewNode(ArtifactComponent component) + { + if (component.CurrentNode == null) + return null; + + var allNodes = component.CurrentNode.Edges; + + if (TryComp(component.Owner, out var bias) && + TryComp(bias.Provider, out var trav) && + _random.Prob(trav.BiasChance) && + this.IsPowered(bias.Provider, EntityManager)) + { + switch (trav.BiasDirection) + { + case BiasDirection.In: + var foo = allNodes.Where(x => x.Depth < component.CurrentNode.Depth).ToList(); + if (foo.Any()) + allNodes = foo; + break; + case BiasDirection.Out: + var bar = allNodes.Where(x => x.Depth > component.CurrentNode.Depth).ToList(); + if (bar.Any()) + allNodes = bar; + break; + } + } + + var undiscoveredNodes = allNodes.Where(x => !x.Discovered).ToList(); + var newNode = _random.Pick(allNodes); + if (undiscoveredNodes.Any() && _random.Prob(0.75f)) + { + newNode = _random.Pick(undiscoveredNodes); + } + + return newNode; + } + /// /// Try and get a data object from a node /// diff --git a/Resources/Locale/en-US/xenoarchaeology/traversal-distorter.ftl b/Resources/Locale/en-US/xenoarchaeology/traversal-distorter.ftl new file mode 100644 index 0000000000..af3039e864 --- /dev/null +++ b/Resources/Locale/en-US/xenoarchaeology/traversal-distorter.ftl @@ -0,0 +1,7 @@ +traversal-distorter-set-in = Traversal bias set to "in" +traversal-distorter-set-out = Traversal bias set to "out" + +traversal-distorter-desc-in = The affected artifact's traversal now favors moving inwards to the beginning. +traversal-distorter-desc-out = The affected artifact's traversal now favors moving outwards towards more dangerous nodes. + +traversal-distorter-upgrade-bias = Bias effectiveness diff --git a/Resources/Prototypes/Catalog/Research/technologies.yml b/Resources/Prototypes/Catalog/Research/technologies.yml index bd59ea06f7..4da5fbc1b9 100644 --- a/Resources/Prototypes/Catalog/Research/technologies.yml +++ b/Resources/Prototypes/Catalog/Research/technologies.yml @@ -446,6 +446,7 @@ - HighPowerMicroLaserStockPart - NanoManipulatorStockPart - AdvancedScanningModuleStockPart + - TraversalDistorterMachineCircuitboard #sigh # Bluespace Theory Technology Tree diff --git a/Resources/Prototypes/Entities/Objects/Devices/Circuitboards/Machine/production.yml b/Resources/Prototypes/Entities/Objects/Devices/Circuitboards/Machine/production.yml index 0a93fb97ed..7a9a712d96 100644 --- a/Resources/Prototypes/Entities/Objects/Devices/Circuitboards/Machine/production.yml +++ b/Resources/Prototypes/Entities/Objects/Devices/Circuitboards/Machine/production.yml @@ -147,6 +147,23 @@ materialRequirements: Glass: 5 +- type: entity + id: TraversalDistorterMachineCircuitboard + parent: BaseMachineCircuitboard + name: traversal distorter machine board + description: A machine printed circuit board for a traversal distorter + components: + - type: Sprite + state: science + - type: MachineBoard + prototype: MachineTraversalDistorter + requirements: + ScanningModule: 1 + Capacitor: 2 + materialRequirements: + Steel: 5 + Cable: 1 + - type: entity id: ThermomachineFreezerMachineCircuitBoard parent: BaseMachineCircuitboard diff --git a/Resources/Prototypes/Entities/Structures/Machines/artifact_analyzer.yml b/Resources/Prototypes/Entities/Structures/Machines/artifact_analyzer.yml index f65025c522..fbff9dec4c 100644 --- a/Resources/Prototypes/Entities/Structures/Machines/artifact_analyzer.yml +++ b/Resources/Prototypes/Entities/Structures/Machines/artifact_analyzer.yml @@ -66,3 +66,50 @@ enum.PowerDeviceVisualLayers.Powered: True: { visible: true } False: { visible: false } + +- type: entity + id: MachineTraversalDistorter + parent: [ BaseMachinePowered, ConstructibleMachine ] + name: traversal distorter + description: A machine capable of distorting the traversal of artifact nodes. + components: + - type: Sprite + noRot: true + sprite: Structures/Machines/traversal_distorter.rsi + drawdepth: FloorObjects + layers: + - state: icon + - state: unshaded + shader: unshaded + map: ["enum.PowerDeviceVisualLayers.Powered"] + - type: Physics + bodyType: Static + canCollide: true + - type: Fixtures + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.35,-0.35,0.35,0.35" + density: 190 + mask: + - MachineMask + layer: + - Impassable + - MidImpassable + - LowImpassable + hard: False + - type: Transform + noRot: false + - type: UpgradePowerDraw + powerDrawMultiplier: 0.80 + scaling: Exponential + - type: TraversalDistorter + - type: Machine + board: TraversalDistorterMachineCircuitboard + - type: Appearance + - type: GenericVisualizer + visuals: + enum.PowerDeviceVisuals.Powered: + enum.PowerDeviceVisualLayers.Powered: + True: { visible: true } + False: { visible: false } \ No newline at end of file diff --git a/Resources/Prototypes/Entities/Structures/Machines/lathe.yml b/Resources/Prototypes/Entities/Structures/Machines/lathe.yml index 387070a95b..286c538c48 100644 --- a/Resources/Prototypes/Entities/Structures/Machines/lathe.yml +++ b/Resources/Prototypes/Entities/Structures/Machines/lathe.yml @@ -300,6 +300,7 @@ - SeedExtractorMachineCircuitboard - AnalysisComputerCircuitboard - ArtifactAnalyzerMachineCircuitboard + - TraversalDistorterMachineCircuitboard - type: MaterialStorage whitelist: tags: diff --git a/Resources/Prototypes/Recipes/Lathes/electronics.yml b/Resources/Prototypes/Recipes/Lathes/electronics.yml index f49ca51063..61f82c7993 100644 --- a/Resources/Prototypes/Recipes/Lathes/electronics.yml +++ b/Resources/Prototypes/Recipes/Lathes/electronics.yml @@ -186,6 +186,16 @@ Glass: 900 Gold: 100 +- type: latheRecipe + id: TraversalDistorterMachineCircuitboard + icon: Objects/Misc/module.rsi/science.png + result: TraversalDistorterMachineCircuitboard + completetime: 4 + materials: + Steel: 100 + Glass: 900 + Gold: 100 + - type: latheRecipe id: ReagentGrinderMachineCircuitboard icon: Objects/Misc/module.rsi/id_mod.png diff --git a/Resources/Textures/Structures/Machines/traversal_distorter.rsi/icon.png b/Resources/Textures/Structures/Machines/traversal_distorter.rsi/icon.png new file mode 100644 index 0000000000..53f921e615 Binary files /dev/null and b/Resources/Textures/Structures/Machines/traversal_distorter.rsi/icon.png differ diff --git a/Resources/Textures/Structures/Machines/traversal_distorter.rsi/meta.json b/Resources/Textures/Structures/Machines/traversal_distorter.rsi/meta.json new file mode 100644 index 0000000000..413b7c38ed --- /dev/null +++ b/Resources/Textures/Structures/Machines/traversal_distorter.rsi/meta.json @@ -0,0 +1,17 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Created by EmoGarbage404", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "icon" + }, + { + "name": "unshaded" + } + ] +} diff --git a/Resources/Textures/Structures/Machines/traversal_distorter.rsi/unshaded.png b/Resources/Textures/Structures/Machines/traversal_distorter.rsi/unshaded.png new file mode 100644 index 0000000000..0d57a2d8c4 Binary files /dev/null and b/Resources/Textures/Structures/Machines/traversal_distorter.rsi/unshaded.png differ