From 8b7c5169283890bcbb1318416971e68e440b32d1 Mon Sep 17 00:00:00 2001 From: pofitlo Date: Fri, 19 Jul 2024 23:10:43 +0400 Subject: [PATCH 01/11] Add teleporter --- .../SyndicateTeleporterComponent.cs | 27 +++++ .../SyndicateTeleporterSystem.cs | 108 ++++++++++++++++++ Resources/Audio/Effects/beeps.ogg | Bin 0 -> 12995 bytes .../Effects/electrical_short_circuit2.ogg | Bin 0 -> 11291 bytes .../Audio/Items/electrical_short_circuit.ogg | Bin 0 -> 12518 bytes .../Locale/en-US/store/uplink-catalog.ftl | 3 + .../Prototypes/Catalog/uplink_catalog.yml | 11 ++ .../Entities/Effects/teleport_effect.yml | 22 ++++ .../syndicate_teleporter.yml | 26 +++++ .../SoundCollections/broken device.yml | 15 +++ .../Effects/teleport_sparks.rsi/meta.json | 22 ++++ .../Effects/teleport_sparks.rsi/sparks.png | Bin 0 -> 870 bytes .../Devices/syndicate_teleporter.rsi/icon.png | Bin 0 -> 600 bytes .../syndicate_teleporter.rsi/meta.json | 15 +++ 14 files changed, 249 insertions(+) create mode 100644 Content.Server/SyndicateTeleporter/SyndicateTeleporterComponent.cs create mode 100644 Content.Server/SyndicateTeleporter/SyndicateTeleporterSystem.cs create mode 100644 Resources/Audio/Effects/beeps.ogg create mode 100644 Resources/Audio/Effects/electrical_short_circuit2.ogg create mode 100644 Resources/Audio/Items/electrical_short_circuit.ogg create mode 100644 Resources/Prototypes/Entities/Effects/teleport_effect.yml create mode 100644 Resources/Prototypes/Entities/Objects/Devices/Syndicate_Gadgets/syndicate_teleporter.yml create mode 100644 Resources/Prototypes/SoundCollections/broken device.yml create mode 100644 Resources/Textures/Effects/teleport_sparks.rsi/meta.json create mode 100644 Resources/Textures/Effects/teleport_sparks.rsi/sparks.png create mode 100644 Resources/Textures/Objects/Devices/syndicate_teleporter.rsi/icon.png create mode 100644 Resources/Textures/Objects/Devices/syndicate_teleporter.rsi/meta.json diff --git a/Content.Server/SyndicateTeleporter/SyndicateTeleporterComponent.cs b/Content.Server/SyndicateTeleporter/SyndicateTeleporterComponent.cs new file mode 100644 index 00000000000..384e048d201 --- /dev/null +++ b/Content.Server/SyndicateTeleporter/SyndicateTeleporterComponent.cs @@ -0,0 +1,27 @@ +using Robust.Shared.Audio; + +namespace Content.Server.SyndicateTeleporter; + +[RegisterComponent] +public sealed partial class SyndicateTeleporterComponent : Component +{ + [DataField("RandomValue")] + [ViewVariables(VVAccess.ReadWrite)] + public int RandomValue = 4; + + [DataField("TeleportationValue")] + [ViewVariables(VVAccess.ReadWrite)] + public float TeleportationValue = 4f; + + [DataField("SaveAttempts")] + [ViewVariables(VVAccess.ReadWrite)] + public int SaveAttempts = 1; + + [DataField("SaveDistance")] + [ViewVariables(VVAccess.ReadWrite)] + public int SaveDistance = 3; + + [ViewVariables(VVAccess.ReadWrite), DataField("alarm"), AutoNetworkedField] + public SoundSpecifier? AlarmSound = new SoundPathSpecifier("/Audio/Effects/beeps.ogg"); + +} diff --git a/Content.Server/SyndicateTeleporter/SyndicateTeleporterSystem.cs b/Content.Server/SyndicateTeleporter/SyndicateTeleporterSystem.cs new file mode 100644 index 00000000000..5222918672a --- /dev/null +++ b/Content.Server/SyndicateTeleporter/SyndicateTeleporterSystem.cs @@ -0,0 +1,108 @@ +using Content.Shared.Interaction.Events; +using Robust.Shared.Map; +using Content.Shared.Charges.Components; +using Content.Shared.Charges.Systems; +using System.Numerics; +using Content.Shared.Maps; +using Content.Shared.Physics; +using Content.Shared.Body.Components; +using Content.Shared.Body.Systems; +using Robust.Shared.Audio.Systems; +using System.Threading.Tasks; + +namespace Content.Server.SyndicateTeleporter; + +public sealed class SyndicateTeleporterSystem : EntitySystem +{ + [Dependency] private readonly SharedTransformSystem _transformSystem = default!; + [Dependency] private readonly SharedChargesSystem _charges = default!; + [Dependency] private readonly TurfSystem _turf = default!; + [Dependency] private readonly IMapManager _mapMan = default!; + [Dependency] private readonly SharedBodySystem _body = default!; + [Dependency] protected readonly SharedAudioSystem _audio = default!; + + + public const string TeleportEffectPrototype = "TeleportEffect"; + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnUse); + } + + private void OnUse(EntityUid uid, SyndicateTeleporterComponent component, UseInHandEvent args) + { + TryComp(uid, out var charges); + + if (args.Handled) + return; + + if (_charges.IsEmpty(uid, charges)) + return; + + _charges.UseCharge(uid, charges); + + Teleportation(uid, args.User, component); + } + + private async Task Teleportation(EntityUid uid, EntityUid user, SyndicateTeleporterComponent comp) + { + Random rnd = new Random(); + float random = rnd.Next(0, comp.RandomValue); + var multiplaer = new Vector2(comp.TeleportationValue + random, comp.TeleportationValue + random); //make random for teleport distance value + + EntityUid? tuser = null; + + var transform = Transform(user); + var offsetValue = transform.LocalRotation.ToWorldVec().Normalized() * multiplaer; + var coords = transform.Coordinates.Offset(offsetValue); //set coordinates where we move on + + Spawn(TeleportEffectPrototype, Transform(user).Coordinates); + + if (transform.MapID != coords.GetMapId(EntityManager)) + return; + + _transformSystem.SetCoordinates(user, coords); // teleport + + Spawn(TeleportEffectPrototype, Transform(user).Coordinates); + + var tile = coords.GetTileRef(EntityManager, _mapMan); // get info about place where we just teleported. theare a walls? + if (tile == null) + return; + + var saveattempts = comp.SaveAttempts; + var savedistance = comp.SaveDistance; + + while (_turf.IsTileBlocked(tile.Value, CollisionGroup.Impassable)) + { + if (!TryComp(user, out var body)) + return; + + + if (saveattempts > 0) // if we have chnce to survive then teleport in random side away + { + await Task.Delay(400); + double side = rnd.Next(-180, 180); + offsetValue = Angle.FromDegrees(side).ToWorldVec() * savedistance; //averages the resulting direction, turning it into one of 8 directions, (N, NE, E...) + coords = transform.Coordinates.Offset(offsetValue); + _transformSystem.SetCoordinates(user, coords); + + Spawn(TeleportEffectPrototype, coords); + _audio.PlayPredicted(comp.AlarmSound, uid, tuser); + + saveattempts--; + } + else + { + _body.GibBody(user, true, body); + break; + } + + + tile = coords.GetTileRef(EntityManager, _mapMan); + if (tile == null) + return; + + } + } +} diff --git a/Resources/Audio/Effects/beeps.ogg b/Resources/Audio/Effects/beeps.ogg new file mode 100644 index 0000000000000000000000000000000000000000..455bac2ef4182d8787f50218e4af2393c5a6e398 GIT binary patch literal 12995 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 bRx{FU$}dOOo9A#2A0{i&bGL}$S_A$cCUq2w literal 0 HcmV?d00001 diff --git a/Resources/Audio/Items/electrical_short_circuit.ogg b/Resources/Audio/Items/electrical_short_circuit.ogg new file mode 100644 index 0000000000000000000000000000000000000000..af495a37f617e221cae28ae297d26cbed25a2a2a GIT binary patch literal 12518 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 literal 0 HcmV?d00001 diff --git a/Resources/Locale/en-US/store/uplink-catalog.ftl b/Resources/Locale/en-US/store/uplink-catalog.ftl index 8edbde9bdc9..52a850b27a7 100644 --- a/Resources/Locale/en-US/store/uplink-catalog.ftl +++ b/Resources/Locale/en-US/store/uplink-catalog.ftl @@ -436,3 +436,6 @@ uplink-barber-scissors-desc = A good tool to give your fellow agent a nice hairc uplink-backpack-syndicate-name = Syndicate backpack uplink-backpack-syndicate-desc = Lightweight explosion-proof а backpack for holding various traitor goods + +uplink-syndicate-teleporter-name = Hand syndicate teleporter +uplink-syndicate-teleporter-desc = An experimental hand teleporting device. Teleports its owner forward in a small area. Be careful not to end up in the wall. diff --git a/Resources/Prototypes/Catalog/uplink_catalog.yml b/Resources/Prototypes/Catalog/uplink_catalog.yml index 420982dcaec..3cb53d8bdc4 100644 --- a/Resources/Prototypes/Catalog/uplink_catalog.yml +++ b/Resources/Prototypes/Catalog/uplink_catalog.yml @@ -1743,3 +1743,14 @@ blacklist: components: - SurplusBundle + +- type: listing + id: UplinkTeleporter + name: uplink-syndicate-teleporter-name + description: uplink-syndicate-teleporter-desc + icon: { sprite: Objects/Devices/syndicate_teleporter.rsi, state: icon} + productEntity: SyndicateTeleporter + cost: + Telecrystal: 12 + categories: + - UplinkDisruption diff --git a/Resources/Prototypes/Entities/Effects/teleport_effect.yml b/Resources/Prototypes/Entities/Effects/teleport_effect.yml new file mode 100644 index 00000000000..1f1f9000120 --- /dev/null +++ b/Resources/Prototypes/Entities/Effects/teleport_effect.yml @@ -0,0 +1,22 @@ +- type: entity + id: TeleportEffect + noSpawn: true + components: + - type: TimedDespawn + lifetime: 0.4 + - type: Sprite + drawdepth: Effects + noRot: true + layers: + - shader: unshaded + map: ["enum.EffectLayers.Unshaded"] + sprite: Effects/teleport_sparks.rsi + state: sparks + - type: EffectVisuals + - type: Tag + tags: + - HideContextMenu + - type: EmitSoundOnSpawn + sound: + path: /Audio/Effects/electrical_short_circuit2.ogg + - type: AnimationPlayer diff --git a/Resources/Prototypes/Entities/Objects/Devices/Syndicate_Gadgets/syndicate_teleporter.yml b/Resources/Prototypes/Entities/Objects/Devices/Syndicate_Gadgets/syndicate_teleporter.yml new file mode 100644 index 00000000000..181cf35a99a --- /dev/null +++ b/Resources/Prototypes/Entities/Objects/Devices/Syndicate_Gadgets/syndicate_teleporter.yml @@ -0,0 +1,26 @@ +- type: entity + parent: BaseItem + id: SyndicateTeleporter + name: syndicate teleporter + description: Personal syndicate teleporter + components: + - type: Sprite + sprite: Objects/Devices/syndicate_teleporter.rsi + state: icon + - type: Item + sprite: Objects/Devices/syndicate_teleporter.rsi + - type: SyndicateTeleporter + RandomValue: 4 + TeleportationValue: 4 + - type: UseDelay + delay: 0.5 + - type: LimitedCharges + charges: 411 + maxcharges: 411 + - type: AutoRecharge + rechargeDuration: 10 + - type: EmitSoundOnUse + sound: + collection: BrokenDevice + params: + variation: 0.125 \ No newline at end of file diff --git a/Resources/Prototypes/SoundCollections/broken device.yml b/Resources/Prototypes/SoundCollections/broken device.yml new file mode 100644 index 00000000000..17d755cbb6e --- /dev/null +++ b/Resources/Prototypes/SoundCollections/broken device.yml @@ -0,0 +1,15 @@ +- type: soundCollection + id: BrokenDevice + files: + - /Audio/Items/electrical_short_circuit.ogg + +- type: soundCollection + id: ShortCircuit + files: + - /Audio/Items/electrical_short_circuit2.ogg + +- type: soundCollection + id: Alarm + files: + - /Audio/Items/bibs.ogg + diff --git a/Resources/Textures/Effects/teleport_sparks.rsi/meta.json b/Resources/Textures/Effects/teleport_sparks.rsi/meta.json new file mode 100644 index 00000000000..44a5e6b62b7 --- /dev/null +++ b/Resources/Textures/Effects/teleport_sparks.rsi/meta.json @@ -0,0 +1,22 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "created by pofitlo", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "sparks", + "delays": [ + [ + 0.1, + 0.1, + 0.1, + 0.1 + ] + ] + } + ] +} diff --git a/Resources/Textures/Effects/teleport_sparks.rsi/sparks.png b/Resources/Textures/Effects/teleport_sparks.rsi/sparks.png new file mode 100644 index 0000000000000000000000000000000000000000..a852aec09fc1483eac6063b3484e6b138157b4ae GIT binary patch literal 870 zcmV-s1DX7ZP)Px&AW1|)RCr$PTftEzF$|o2lE8)l+3+PszGMR-kO0r6OqI8ck*ro*nlUWA4n`xj zS}j?gsyl5r{&TwV{I_3E!0Yq*a{u_go$k0?rU{q@z$mcBEbqR(oVQ&GI3nSer0Dpt z0+7In4O4N105&#EfCZcdVEL`jNB(DGPZKZ`98EscZkm8haFXvz`0VhjzFh=F2ltS7 zNDD9tN4JE>pU0L`fK@RDfaSA)-o}vr?QIQL3wXiK+Itkpk{?0<8{A8f6i17VVxkB@ zoqH1;$=&m;*rFI!0(u9iLod+LQCBWFTF=jtn=%BWK(T%pvZxlY0J3V){969{VOjj3 z*W(ZZEPxha%*N+AAx8113CKu(1lSV~u@woBda0Kc;+&~`eW&^_zt`mkU2;6wrWMd8 z=?OeT4yq6Y&olvTrS?{dq!!Nr{IX>#fiTPX^}J(kfG80V0i!BQEr14R622}l-lG+=G5i??lxi{sF$u7SO_dw7hokL+Vqi!x30Uo%FL*8= z+ePYgW)8RrKr2=NMo;VNv)u-zZL!@Pk<(~MK!5zz;C+zx?^%hrki)UP%+^aK zVCCU=y|(Xp5m}LtR0Tx!X{Mhr0#>XpLR=UDeK0Q}S;ue1WnP9_09jzXq#zYUZM4{F z3Xp(VcLFq-NV{|bj;uODluAI<=cuS}07x>7&6R+tn;!!rd)piN|3*MD%=~^gYKN@B zTa(xRV^#VLXce*IJfI2a&(#%^L)wuhpg+>uVV8M(Lz42?qPx%5=lfsR9Hvtl|M*AQ542M9a0Gq2TKa#(O}e2O^Hh`;aDvV6*L7AC=IRA)D{g{ zOG9HNxb#N|q{SAosTvv{1QJxQ9ONOQ7HFIc_wkA>@2zmiv%CkFd%xfP&N=s3(B!Z* zSsyKcmIEyZq#fu4YP^M?Am2^G08+H2b~^F!^1{ICMZGi$ z0VsYyvY8A>P^nf8t*q5*0F6WnxXbLL$3Mf?>7PQoSiolx4FmXmzM9+ZhRfx`RWgaK z_I3jxQY>O96oRhn43J`NFU`K&o7V_04Ps?BAP+$H?etbqO9{Um?pU*>ARge=r z$b}y{zyavMXf%qkbeg5$XmS!0hlijPoCN~R0S>?&;4b_M06B0SUSvf`f*y|txm=C` zQ4ywxhgk}|BRi}Hc>d}CV#_I?0=k8{3rL7+fdkOZ1DBTuz-OKC<1R2mP&ZHz1c_7d z;uC!p8}0&rE9wTj-43tUYdD~38p`D|R8~qB zL8Ar+QYkiwXiAEvK_~?u2h!E}IEIdo-wmQa1u(ZFA4ujwBq}adgk}iygCip@4N!OJ mODqW0fW-OVZfOBD-GMhR`U)_1r^L$u0000 Date: Sat, 20 Jul 2024 00:46:00 +0400 Subject: [PATCH 02/11] Oops --- .../SyndicateTeleporter/SyndicateTeleporterComponent.cs | 8 ++++---- .../Devices/Syndicate_Gadgets/syndicate_teleporter.yml | 6 ++---- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/Content.Server/SyndicateTeleporter/SyndicateTeleporterComponent.cs b/Content.Server/SyndicateTeleporter/SyndicateTeleporterComponent.cs index 384e048d201..0ca0db0543f 100644 --- a/Content.Server/SyndicateTeleporter/SyndicateTeleporterComponent.cs +++ b/Content.Server/SyndicateTeleporter/SyndicateTeleporterComponent.cs @@ -5,19 +5,19 @@ namespace Content.Server.SyndicateTeleporter; [RegisterComponent] public sealed partial class SyndicateTeleporterComponent : Component { - [DataField("RandomValue")] + [DataField("randomValue")] [ViewVariables(VVAccess.ReadWrite)] public int RandomValue = 4; - [DataField("TeleportationValue")] + [DataField("teleportationValue")] [ViewVariables(VVAccess.ReadWrite)] public float TeleportationValue = 4f; - [DataField("SaveAttempts")] + [DataField("saveAttempts")] [ViewVariables(VVAccess.ReadWrite)] public int SaveAttempts = 1; - [DataField("SaveDistance")] + [DataField("saveDistance")] [ViewVariables(VVAccess.ReadWrite)] public int SaveDistance = 3; diff --git a/Resources/Prototypes/Entities/Objects/Devices/Syndicate_Gadgets/syndicate_teleporter.yml b/Resources/Prototypes/Entities/Objects/Devices/Syndicate_Gadgets/syndicate_teleporter.yml index 181cf35a99a..8b7ed314c4c 100644 --- a/Resources/Prototypes/Entities/Objects/Devices/Syndicate_Gadgets/syndicate_teleporter.yml +++ b/Resources/Prototypes/Entities/Objects/Devices/Syndicate_Gadgets/syndicate_teleporter.yml @@ -10,13 +10,11 @@ - type: Item sprite: Objects/Devices/syndicate_teleporter.rsi - type: SyndicateTeleporter - RandomValue: 4 - TeleportationValue: 4 - type: UseDelay delay: 0.5 - type: LimitedCharges - charges: 411 - maxcharges: 411 + charges: 4 + maxCharges: 4 - type: AutoRecharge rechargeDuration: 10 - type: EmitSoundOnUse From d79015fa2fe31cb1407786225b23ecb96419044c Mon Sep 17 00:00:00 2001 From: pofitlo Date: Sat, 20 Jul 2024 03:24:41 +0400 Subject: [PATCH 03/11] fix --- .../SoundCollections/{broken device.yml => broken_device.yml} | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename Resources/Prototypes/SoundCollections/{broken device.yml => broken_device.yml} (72%) diff --git a/Resources/Prototypes/SoundCollections/broken device.yml b/Resources/Prototypes/SoundCollections/broken_device.yml similarity index 72% rename from Resources/Prototypes/SoundCollections/broken device.yml rename to Resources/Prototypes/SoundCollections/broken_device.yml index 17d755cbb6e..1036d535b3e 100644 --- a/Resources/Prototypes/SoundCollections/broken device.yml +++ b/Resources/Prototypes/SoundCollections/broken_device.yml @@ -6,10 +6,10 @@ - type: soundCollection id: ShortCircuit files: - - /Audio/Items/electrical_short_circuit2.ogg + - /Audio/Effects/electrical_short_circuit2.ogg - type: soundCollection id: Alarm files: - - /Audio/Items/bibs.ogg + - /Audio/Effects/beeps.ogg From 59489ee6ad59cbf0157f065a1b8bf1b12b78f8e7 Mon Sep 17 00:00:00 2001 From: pofitlo Date: Sat, 20 Jul 2024 04:29:56 +0400 Subject: [PATCH 04/11] changes changes on demand of slarticodefast --- .../SyndicateTeleporterComponent.cs | 29 ++++++++++-------- Resources/Audio/Effects/attributions.yml | 5 +++ .../electrical_short_circuit.ogg | Bin .../SoundCollections/broken_device.yml | 2 +- 4 files changed, 23 insertions(+), 13 deletions(-) rename Resources/Audio/{Items => Effects}/electrical_short_circuit.ogg (100%) diff --git a/Content.Server/SyndicateTeleporter/SyndicateTeleporterComponent.cs b/Content.Server/SyndicateTeleporter/SyndicateTeleporterComponent.cs index 0ca0db0543f..d2c3df382b4 100644 --- a/Content.Server/SyndicateTeleporter/SyndicateTeleporterComponent.cs +++ b/Content.Server/SyndicateTeleporter/SyndicateTeleporterComponent.cs @@ -5,23 +5,28 @@ namespace Content.Server.SyndicateTeleporter; [RegisterComponent] public sealed partial class SyndicateTeleporterComponent : Component { - [DataField("randomValue")] - [ViewVariables(VVAccess.ReadWrite)] + /// + /// adds a random value to which you teleport, which is added to the guaranteed teleport value. from 0 to the set number. set 0 if you don't need randomness when teleporting + /// + [DataField] public int RandomValue = 4; - - [DataField("teleportationValue")] - [ViewVariables(VVAccess.ReadWrite)] + /// + /// this is the guaranteed number of tiles that you teleport to. + /// + [DataField] public float TeleportationValue = 4f; - - [DataField("saveAttempts")] - [ViewVariables(VVAccess.ReadWrite)] + /// + /// how many attempts do you have to teleport into the wall without a fatal outcome + /// + [DataField] public int SaveAttempts = 1; - - [DataField("saveDistance")] - [ViewVariables(VVAccess.ReadWrite)] + /// + /// the distance to which you will be teleported when you teleport into a wall + /// + [DataField] public int SaveDistance = 3; - [ViewVariables(VVAccess.ReadWrite), DataField("alarm"), AutoNetworkedField] + [DataField("alarm"), AutoNetworkedField] public SoundSpecifier? AlarmSound = new SoundPathSpecifier("/Audio/Effects/beeps.ogg"); } diff --git a/Resources/Audio/Effects/attributions.yml b/Resources/Audio/Effects/attributions.yml index 6f18510d17b..a6c362261d4 100644 --- a/Resources/Audio/Effects/attributions.yml +++ b/Resources/Audio/Effects/attributions.yml @@ -231,3 +231,8 @@ copyright: '"beep_landmine.ogg" by kaktuscsc of Discord for SS14' license: "CC-BY-SA-3.0" source: https://github.com/YuriyKiss/space-station-14/commit/971a135a9c83aed46e967aac9302ab5b35562b5f + +- files: [beeps.ogg, electrical_short_circuit.ogg, electrical_short_circuit2.ogg, ] + copyright: '"taken from zvukipro.com' + license: "CC-BY-SA-3.0" + source: https://zvukipro.com/predmet/158-zvuk-elektrichestva.html diff --git a/Resources/Audio/Items/electrical_short_circuit.ogg b/Resources/Audio/Effects/electrical_short_circuit.ogg similarity index 100% rename from Resources/Audio/Items/electrical_short_circuit.ogg rename to Resources/Audio/Effects/electrical_short_circuit.ogg diff --git a/Resources/Prototypes/SoundCollections/broken_device.yml b/Resources/Prototypes/SoundCollections/broken_device.yml index 1036d535b3e..813a318063c 100644 --- a/Resources/Prototypes/SoundCollections/broken_device.yml +++ b/Resources/Prototypes/SoundCollections/broken_device.yml @@ -1,7 +1,7 @@ - type: soundCollection id: BrokenDevice files: - - /Audio/Items/electrical_short_circuit.ogg + - /Audio/Effects/electrical_short_circuit.ogg - type: soundCollection id: ShortCircuit From f09c914e22dfe9de8e74e221542fbfa83923382d Mon Sep 17 00:00:00 2001 From: pofitlo Date: Sat, 20 Jul 2024 05:18:02 +0400 Subject: [PATCH 05/11] random --- .../SyndicateTeleporter/SyndicateTeleporterComponent.cs | 2 +- .../SyndicateTeleporter/SyndicateTeleporterSystem.cs | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/Content.Server/SyndicateTeleporter/SyndicateTeleporterComponent.cs b/Content.Server/SyndicateTeleporter/SyndicateTeleporterComponent.cs index d2c3df382b4..6354cab9dd4 100644 --- a/Content.Server/SyndicateTeleporter/SyndicateTeleporterComponent.cs +++ b/Content.Server/SyndicateTeleporter/SyndicateTeleporterComponent.cs @@ -9,7 +9,7 @@ public sealed partial class SyndicateTeleporterComponent : Component /// adds a random value to which you teleport, which is added to the guaranteed teleport value. from 0 to the set number. set 0 if you don't need randomness when teleporting /// [DataField] - public int RandomValue = 4; + public int RandomDistanceValue = 4; /// /// this is the guaranteed number of tiles that you teleport to. /// diff --git a/Content.Server/SyndicateTeleporter/SyndicateTeleporterSystem.cs b/Content.Server/SyndicateTeleporter/SyndicateTeleporterSystem.cs index 5222918672a..5c33a13f3a8 100644 --- a/Content.Server/SyndicateTeleporter/SyndicateTeleporterSystem.cs +++ b/Content.Server/SyndicateTeleporter/SyndicateTeleporterSystem.cs @@ -9,6 +9,7 @@ using Content.Shared.Body.Systems; using Robust.Shared.Audio.Systems; using System.Threading.Tasks; +using Robust.Shared.Random; namespace Content.Server.SyndicateTeleporter; @@ -20,6 +21,7 @@ public sealed class SyndicateTeleporterSystem : EntitySystem [Dependency] private readonly IMapManager _mapMan = default!; [Dependency] private readonly SharedBodySystem _body = default!; [Dependency] protected readonly SharedAudioSystem _audio = default!; + [Dependency] private readonly IRobustRandom _random = default!; public const string TeleportEffectPrototype = "TeleportEffect"; @@ -47,8 +49,7 @@ private void OnUse(EntityUid uid, SyndicateTeleporterComponent component, UseInH private async Task Teleportation(EntityUid uid, EntityUid user, SyndicateTeleporterComponent comp) { - Random rnd = new Random(); - float random = rnd.Next(0, comp.RandomValue); + float random = _random.Next(0, comp.RandomDistanceValue); var multiplaer = new Vector2(comp.TeleportationValue + random, comp.TeleportationValue + random); //make random for teleport distance value EntityUid? tuser = null; @@ -79,10 +80,10 @@ private async Task Teleportation(EntityUid uid, EntityUid user, SyndicateTelepor return; - if (saveattempts > 0) // if we have chnce to survive then teleport in random side away + if (saveattempts > 0) // if we have chance to survive then teleport in random side away { await Task.Delay(400); - double side = rnd.Next(-180, 180); + double side = _random.Next(-180, 180); offsetValue = Angle.FromDegrees(side).ToWorldVec() * savedistance; //averages the resulting direction, turning it into one of 8 directions, (N, NE, E...) coords = transform.Coordinates.Offset(offsetValue); _transformSystem.SetCoordinates(user, coords); From 41bdb3439c1f31e1a01ba1c4659d884ae76e5ef7 Mon Sep 17 00:00:00 2001 From: pofitlo Date: Sat, 27 Jul 2024 01:15:57 +0400 Subject: [PATCH 06/11] Apply suggestions from code review Co-authored-by: faint <46868845+ficcialfaint@users.noreply.github.com> --- .../SyndicateTeleporter/SyndicateTeleporterSystem.cs | 6 ++++-- Resources/Prototypes/Catalog/uplink_catalog.yml | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/Content.Server/SyndicateTeleporter/SyndicateTeleporterSystem.cs b/Content.Server/SyndicateTeleporter/SyndicateTeleporterSystem.cs index 5c33a13f3a8..8b9c6068b17 100644 --- a/Content.Server/SyndicateTeleporter/SyndicateTeleporterSystem.cs +++ b/Content.Server/SyndicateTeleporter/SyndicateTeleporterSystem.cs @@ -24,7 +24,8 @@ public sealed class SyndicateTeleporterSystem : EntitySystem [Dependency] private readonly IRobustRandom _random = default!; - public const string TeleportEffectPrototype = "TeleportEffect"; + [ValidatePrototypeId] + private const string TeleportEffectPrototype = "TeleportEffect"; public override void Initialize() { base.Initialize(); @@ -34,7 +35,8 @@ public override void Initialize() private void OnUse(EntityUid uid, SyndicateTeleporterComponent component, UseInHandEvent args) { - TryComp(uid, out var charges); + if (!TryComp(uid, out var charges)) + return; if (args.Handled) return; diff --git a/Resources/Prototypes/Catalog/uplink_catalog.yml b/Resources/Prototypes/Catalog/uplink_catalog.yml index 3cb53d8bdc4..09e166c03a3 100644 --- a/Resources/Prototypes/Catalog/uplink_catalog.yml +++ b/Resources/Prototypes/Catalog/uplink_catalog.yml @@ -1748,7 +1748,7 @@ id: UplinkTeleporter name: uplink-syndicate-teleporter-name description: uplink-syndicate-teleporter-desc - icon: { sprite: Objects/Devices/syndicate_teleporter.rsi, state: icon} + icon: { sprite: Objects/Devices/syndicate_teleporter.rsi, state: icon} productEntity: SyndicateTeleporter cost: Telecrystal: 12 From 8a3812adb3576d323fc9d4b5b78e3451633a818a Mon Sep 17 00:00:00 2001 From: pofitlo Date: Sat, 27 Jul 2024 13:57:20 +0400 Subject: [PATCH 07/11] Correct licensing --- Resources/Audio/Effects/attributions.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Resources/Audio/Effects/attributions.yml b/Resources/Audio/Effects/attributions.yml index a6c362261d4..07755d6afdc 100644 --- a/Resources/Audio/Effects/attributions.yml +++ b/Resources/Audio/Effects/attributions.yml @@ -234,5 +234,5 @@ - files: [beeps.ogg, electrical_short_circuit.ogg, electrical_short_circuit2.ogg, ] copyright: '"taken from zvukipro.com' - license: "CC-BY-SA-3.0" + license: "CC-BY-NC" source: https://zvukipro.com/predmet/158-zvuk-elektrichestva.html From 0b33cfdd3bd240ba43de6cad33379829d6b29c86 Mon Sep 17 00:00:00 2001 From: pofitlo Date: Sat, 17 Aug 2024 22:30:24 +0400 Subject: [PATCH 08/11] got rid of the Task.Await --- .../SyndicateTeleporterComponent.cs | 12 ++++ .../SyndicateTeleporterSystem.cs | 71 +++++++++++++++---- 2 files changed, 70 insertions(+), 13 deletions(-) diff --git a/Content.Server/SyndicateTeleporter/SyndicateTeleporterComponent.cs b/Content.Server/SyndicateTeleporter/SyndicateTeleporterComponent.cs index 6354cab9dd4..442ecf25933 100644 --- a/Content.Server/SyndicateTeleporter/SyndicateTeleporterComponent.cs +++ b/Content.Server/SyndicateTeleporter/SyndicateTeleporterComponent.cs @@ -29,4 +29,16 @@ public sealed partial class SyndicateTeleporterComponent : Component [DataField("alarm"), AutoNetworkedField] public SoundSpecifier? AlarmSound = new SoundPathSpecifier("/Audio/Effects/beeps.ogg"); + + public EntityUid UserComp; + /// + /// the number of seconds the player stays in the wall. (just so that he would realize that he almost died) + /// + [DataField] + public float CorrectTime = 0.5f; + public float Timer = 0; + + public bool InWall = false; + + } diff --git a/Content.Server/SyndicateTeleporter/SyndicateTeleporterSystem.cs b/Content.Server/SyndicateTeleporter/SyndicateTeleporterSystem.cs index 8b9c6068b17..a4cd93df123 100644 --- a/Content.Server/SyndicateTeleporter/SyndicateTeleporterSystem.cs +++ b/Content.Server/SyndicateTeleporter/SyndicateTeleporterSystem.cs @@ -10,6 +10,8 @@ using Robust.Shared.Audio.Systems; using System.Threading.Tasks; using Robust.Shared.Random; +using Content.Server.Popups; +using Content.Shared.Popups; namespace Content.Server.SyndicateTeleporter; @@ -22,9 +24,8 @@ public sealed class SyndicateTeleporterSystem : EntitySystem [Dependency] private readonly SharedBodySystem _body = default!; [Dependency] protected readonly SharedAudioSystem _audio = default!; [Dependency] private readonly IRobustRandom _random = default!; + [Dependency] private readonly PopupSystem _popups = default!; - - [ValidatePrototypeId] private const string TeleportEffectPrototype = "TeleportEffect"; public override void Initialize() { @@ -33,8 +34,29 @@ public override void Initialize() SubscribeLocalEvent(OnUse); } + public override void Update(float frameTime) + { + base.Update(frameTime); + + var query = EntityQueryEnumerator(); + while (query.MoveNext(out var uid, out var comp)) + { + if (comp.InWall == true) + { + comp.Timer += frameTime; + if (comp.Timer >= comp.CorrectTime) //I'm not sure I should do it this way... + { + SaveTeleport(uid, comp); + comp.Timer = 0; + } + } + } + } + private void OnUse(EntityUid uid, SyndicateTeleporterComponent component, UseInHandEvent args) { + component.UserComp = args.User; // well, i need this for SaveTeleport... + if (!TryComp(uid, out var charges)) return; @@ -49,12 +71,10 @@ private void OnUse(EntityUid uid, SyndicateTeleporterComponent component, UseInH Teleportation(uid, args.User, component); } - private async Task Teleportation(EntityUid uid, EntityUid user, SyndicateTeleporterComponent comp) + private void Teleportation(EntityUid uid, EntityUid user, SyndicateTeleporterComponent comp) { float random = _random.Next(0, comp.RandomDistanceValue); - var multiplaer = new Vector2(comp.TeleportationValue + random, comp.TeleportationValue + random); //make random for teleport distance value - - EntityUid? tuser = null; + var multiplaer = new Vector2(comp.TeleportationValue + random, comp.TeleportationValue + random); //make random for teleport distance valu var transform = Transform(user); var offsetValue = transform.LocalRotation.ToWorldVec().Normalized() * multiplaer; @@ -73,22 +93,41 @@ private async Task Teleportation(EntityUid uid, EntityUid user, SyndicateTelepor if (tile == null) return; + if (_turf.IsTileBlocked(tile.Value, CollisionGroup.Impassable)) + { + comp.InWall = true; // if yes then starting the timer countdown in update + + } + + } + + private void SaveTeleport(EntityUid uid, SyndicateTeleporterComponent comp) + { + var transform = Transform(comp.UserComp); + var offsetValue = Transform(comp.UserComp).LocalPosition; + var coords = transform.Coordinates.WithPosition(offsetValue); + + var tile = coords.GetTileRef(EntityManager, _mapMan); + if (tile == null) + return; + var saveattempts = comp.SaveAttempts; var savedistance = comp.SaveDistance; while (_turf.IsTileBlocked(tile.Value, CollisionGroup.Impassable)) { - if (!TryComp(user, out var body)) + if (!TryComp(comp.UserComp, out var body)) return; + EntityUid? tuser = null; + if (saveattempts > 0) // if we have chance to survive then teleport in random side away { - await Task.Delay(400); double side = _random.Next(-180, 180); offsetValue = Angle.FromDegrees(side).ToWorldVec() * savedistance; //averages the resulting direction, turning it into one of 8 directions, (N, NE, E...) coords = transform.Coordinates.Offset(offsetValue); - _transformSystem.SetCoordinates(user, coords); + _transformSystem.SetCoordinates(comp.UserComp, coords); Spawn(TeleportEffectPrototype, coords); _audio.PlayPredicted(comp.AlarmSound, uid, tuser); @@ -97,15 +136,21 @@ private async Task Teleportation(EntityUid uid, EntityUid user, SyndicateTelepor } else { - _body.GibBody(user, true, body); + _body.GibBody(comp.UserComp, true, body); + comp.InWall = false; // closing the countdown in update break; } - tile = coords.GetTileRef(EntityManager, _mapMan); - if (tile == null) + if(tile == null) + { return; - + } + if (!_turf.IsTileBlocked(tile.Value, CollisionGroup.Impassable)) + { + comp.InWall = false; + return; + } } } } From 41b3e846f1ac564209580cd5da38002af18f83fe Mon Sep 17 00:00:00 2001 From: pofitlo Date: Sat, 17 Aug 2024 22:41:45 +0400 Subject: [PATCH 09/11] license --- Resources/Audio/Effects/attributions.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Resources/Audio/Effects/attributions.yml b/Resources/Audio/Effects/attributions.yml index 07755d6afdc..7b22f4e79d8 100644 --- a/Resources/Audio/Effects/attributions.yml +++ b/Resources/Audio/Effects/attributions.yml @@ -234,5 +234,5 @@ - files: [beeps.ogg, electrical_short_circuit.ogg, electrical_short_circuit2.ogg, ] copyright: '"taken from zvukipro.com' - license: "CC-BY-NC" + license: "CC-BY-NC-3.0" source: https://zvukipro.com/predmet/158-zvuk-elektrichestva.html From c47fb5f9164dd14dcb697c573f14e98ee4423f1b Mon Sep 17 00:00:00 2001 From: FN Date: Sun, 10 Nov 2024 17:17:03 +0700 Subject: [PATCH 10/11] Ready --- .../SyndicateTeleporterComponent.cs | 11 +++ .../Teleporter/SyndicateTeleporterSystem.cs | 73 +++++++++++++++++++ .../Prototypes/Catalog/uplink_catalog.yml | 2 +- .../Entities/Effects/teleport_effect.yml | 6 +- .../syndicate_teleporter.yml | 10 +-- 5 files changed, 90 insertions(+), 12 deletions(-) create mode 100644 Content.Server/_CorvaxNext/Teleporter/SyndicateTeleporterComponent.cs create mode 100644 Content.Server/_CorvaxNext/Teleporter/SyndicateTeleporterSystem.cs diff --git a/Content.Server/_CorvaxNext/Teleporter/SyndicateTeleporterComponent.cs b/Content.Server/_CorvaxNext/Teleporter/SyndicateTeleporterComponent.cs new file mode 100644 index 00000000000..bcd7a31b650 --- /dev/null +++ b/Content.Server/_CorvaxNext/Teleporter/SyndicateTeleporterComponent.cs @@ -0,0 +1,11 @@ +namespace Content.Server._CorvaxNext.Teleporter; + +[RegisterComponent] +public sealed partial class SyndicateTeleporterComponent : Component +{ + [DataField] + public float TeleportationRangeStart = 4; + + [DataField] + public int TeleportationRangeLength = 4; +} diff --git a/Content.Server/_CorvaxNext/Teleporter/SyndicateTeleporterSystem.cs b/Content.Server/_CorvaxNext/Teleporter/SyndicateTeleporterSystem.cs new file mode 100644 index 00000000000..6870cd1131f --- /dev/null +++ b/Content.Server/_CorvaxNext/Teleporter/SyndicateTeleporterSystem.cs @@ -0,0 +1,73 @@ +using Content.Shared.Body.Systems; +using Content.Shared.Coordinates.Helpers; +using Content.Shared.Interaction.Events; +using Content.Shared.Maps; +using Content.Shared.Physics; +using Content.Shared.Random.Helpers; +using Robust.Shared.Map; +using Robust.Shared.Prototypes; +using Robust.Shared.Random; + +namespace Content.Server._CorvaxNext.Teleporter; + +public sealed class SyndicateTeleporterSystem : EntitySystem +{ + [Dependency] private readonly SharedTransformSystem _transform = default!; + [Dependency] private readonly IMapManager _map = default!; + [Dependency] private readonly TurfSystem _turf = default!; + [Dependency] private readonly SharedBodySystem _body = default!; + [Dependency] private readonly IRobustRandom _random = default!; + + [ValidatePrototypeId] + private const string TeleportEffectPrototype = "TeleportEffect"; + + public override void Initialize() + { + SubscribeLocalEvent(OnUseInHand); + } + + private void OnUseInHand(EntityUid entity, SyndicateTeleporterComponent teleproter, UseInHandEvent e) + { + if (e.Handled) + return; + + var transform = Transform(e.User); + + var direction = transform.LocalRotation.ToWorldVec().Normalized(); + + List safeCoordinates = []; + + for (var i = 0; i <= teleproter.TeleportationRangeLength; i++) + { + var offset = (teleproter.TeleportationRangeStart + i) * direction; + + var coordinates = transform.Coordinates.Offset(offset).SnapToGrid(EntityManager, _map); + + var tile = coordinates.GetTileRef(EntityManager, _map); + + if (tile is not null && _turf.IsTileBlocked(tile.Value, CollisionGroup.MobMask)) + continue; + + safeCoordinates.Add(coordinates); + } + + EntityCoordinates resultCoordinates; + + if (safeCoordinates.Count < 1) + { + var offset = (teleproter.TeleportationRangeStart + _random.NextFloat(teleproter.TeleportationRangeLength)) * direction; + + resultCoordinates = transform.Coordinates.Offset(offset); + } + else + resultCoordinates = _random.Pick(safeCoordinates); + + Spawn(TeleportEffectPrototype, transform.Coordinates); + Spawn(TeleportEffectPrototype, resultCoordinates); + + _transform.SetCoordinates(e.User, resultCoordinates); + + if (safeCoordinates.Count < 1) + _body.GibBody(e.User, true); + } +} diff --git a/Resources/Prototypes/Catalog/uplink_catalog.yml b/Resources/Prototypes/Catalog/uplink_catalog.yml index bf91afd1a70..f88ee8e4623 100644 --- a/Resources/Prototypes/Catalog/uplink_catalog.yml +++ b/Resources/Prototypes/Catalog/uplink_catalog.yml @@ -2110,7 +2110,7 @@ id: UplinkTeleporter name: uplink-syndicate-teleporter-name description: uplink-syndicate-teleporter-desc - icon: { sprite: Objects/Devices/syndicate_teleporter.rsi, state: icon} + icon: { sprite: _CorvaxNext/Objects/Devices/syndicate_teleporter.rsi, state: icon } productEntity: SyndicateTeleporter cost: Telecrystal: 12 diff --git a/Resources/Prototypes/_CorvaxNext/Entities/Effects/teleport_effect.yml b/Resources/Prototypes/_CorvaxNext/Entities/Effects/teleport_effect.yml index 1f1f9000120..70ccd8ff92a 100644 --- a/Resources/Prototypes/_CorvaxNext/Entities/Effects/teleport_effect.yml +++ b/Resources/Prototypes/_CorvaxNext/Entities/Effects/teleport_effect.yml @@ -1,6 +1,6 @@ - type: entity id: TeleportEffect - noSpawn: true + categories: [ HideSpawnMenu ] components: - type: TimedDespawn lifetime: 0.4 @@ -10,7 +10,7 @@ layers: - shader: unshaded map: ["enum.EffectLayers.Unshaded"] - sprite: Effects/teleport_sparks.rsi + sprite: _CorvaxNext/Effects/teleport_sparks.rsi state: sparks - type: EffectVisuals - type: Tag @@ -18,5 +18,5 @@ - HideContextMenu - type: EmitSoundOnSpawn sound: - path: /Audio/Effects/electrical_short_circuit2.ogg + collection: ShortCircuit - type: AnimationPlayer diff --git a/Resources/Prototypes/_CorvaxNext/Entities/Objects/Devices/Syndicate_Gadgets/syndicate_teleporter.yml b/Resources/Prototypes/_CorvaxNext/Entities/Objects/Devices/Syndicate_Gadgets/syndicate_teleporter.yml index 027e38c6241..dcb2555589e 100644 --- a/Resources/Prototypes/_CorvaxNext/Entities/Objects/Devices/Syndicate_Gadgets/syndicate_teleporter.yml +++ b/Resources/Prototypes/_CorvaxNext/Entities/Objects/Devices/Syndicate_Gadgets/syndicate_teleporter.yml @@ -5,18 +5,12 @@ description: Personal syndicate teleporter. components: - type: Sprite - sprite: Objects/Devices/syndicate_teleporter.rsi + sprite: _CorvaxNext/Objects/Devices/syndicate_teleporter.rsi state: icon - type: Item - sprite: Objects/Devices/syndicate_teleporter.rsi - type: SyndicateTeleporter - type: UseDelay - delay: 0.5 - - type: LimitedCharges - charges: 4 - maxCharges: 4 - - type: AutoRecharge - rechargeDuration: 10 + delay: 60 - type: EmitSoundOnUse sound: collection: BrokenDevice From 3e9c1c1b0f6d1a2ec7cb2e52b5507075ee6941b6 Mon Sep 17 00:00:00 2001 From: FN Date: Tue, 12 Nov 2024 06:46:30 +0700 Subject: [PATCH 11/11] Requests --- .../Teleporter/SyndicateTeleporterComponent.cs | 5 +++++ .../Teleporter/SyndicateTeleporterSystem.cs | 13 ++++++------- Resources/Prototypes/Catalog/uplink_catalog.yml | 13 ------------- .../_CorvaxNext/Catalog/uplink_catalog.yml | 10 ++++++++++ 4 files changed, 21 insertions(+), 20 deletions(-) create mode 100644 Resources/Prototypes/_CorvaxNext/Catalog/uplink_catalog.yml diff --git a/Content.Server/_CorvaxNext/Teleporter/SyndicateTeleporterComponent.cs b/Content.Server/_CorvaxNext/Teleporter/SyndicateTeleporterComponent.cs index bcd7a31b650..55d66351bfd 100644 --- a/Content.Server/_CorvaxNext/Teleporter/SyndicateTeleporterComponent.cs +++ b/Content.Server/_CorvaxNext/Teleporter/SyndicateTeleporterComponent.cs @@ -1,3 +1,5 @@ +using Content.Shared.Physics; + namespace Content.Server._CorvaxNext.Teleporter; [RegisterComponent] @@ -8,4 +10,7 @@ public sealed partial class SyndicateTeleporterComponent : Component [DataField] public int TeleportationRangeLength = 4; + + [DataField] + public CollisionGroup CollisionGroup = CollisionGroup.MobMask; } diff --git a/Content.Server/_CorvaxNext/Teleporter/SyndicateTeleporterSystem.cs b/Content.Server/_CorvaxNext/Teleporter/SyndicateTeleporterSystem.cs index 6870cd1131f..40a40e4696e 100644 --- a/Content.Server/_CorvaxNext/Teleporter/SyndicateTeleporterSystem.cs +++ b/Content.Server/_CorvaxNext/Teleporter/SyndicateTeleporterSystem.cs @@ -18,15 +18,14 @@ public sealed class SyndicateTeleporterSystem : EntitySystem [Dependency] private readonly SharedBodySystem _body = default!; [Dependency] private readonly IRobustRandom _random = default!; - [ValidatePrototypeId] - private const string TeleportEffectPrototype = "TeleportEffect"; + private static readonly EntProtoId TeleportEffectPrototype = "TeleportEffect"; public override void Initialize() { SubscribeLocalEvent(OnUseInHand); } - private void OnUseInHand(EntityUid entity, SyndicateTeleporterComponent teleproter, UseInHandEvent e) + private void OnUseInHand(Entity teleproter, ref UseInHandEvent e) { if (e.Handled) return; @@ -37,15 +36,15 @@ private void OnUseInHand(EntityUid entity, SyndicateTeleporterComponent teleprot List safeCoordinates = []; - for (var i = 0; i <= teleproter.TeleportationRangeLength; i++) + for (var i = 0; i <= teleproter.Comp.TeleportationRangeLength; i++) { - var offset = (teleproter.TeleportationRangeStart + i) * direction; + var offset = (teleproter.Comp.TeleportationRangeStart + i) * direction; var coordinates = transform.Coordinates.Offset(offset).SnapToGrid(EntityManager, _map); var tile = coordinates.GetTileRef(EntityManager, _map); - if (tile is not null && _turf.IsTileBlocked(tile.Value, CollisionGroup.MobMask)) + if (tile is not null && _turf.IsTileBlocked(tile.Value, teleproter.Comp.CollisionGroup)) continue; safeCoordinates.Add(coordinates); @@ -55,7 +54,7 @@ private void OnUseInHand(EntityUid entity, SyndicateTeleporterComponent teleprot if (safeCoordinates.Count < 1) { - var offset = (teleproter.TeleportationRangeStart + _random.NextFloat(teleproter.TeleportationRangeLength)) * direction; + var offset = (teleproter.Comp.TeleportationRangeStart + _random.NextFloat(teleproter.Comp.TeleportationRangeLength)) * direction; resultCoordinates = transform.Coordinates.Offset(offset); } diff --git a/Resources/Prototypes/Catalog/uplink_catalog.yml b/Resources/Prototypes/Catalog/uplink_catalog.yml index f88ee8e4623..f31d85414d4 100644 --- a/Resources/Prototypes/Catalog/uplink_catalog.yml +++ b/Resources/Prototypes/Catalog/uplink_catalog.yml @@ -2104,16 +2104,3 @@ whitelist: - Chef - Mime - -# Corvax-Next-Teleporter-Start -- type: listing - id: UplinkTeleporter - name: uplink-syndicate-teleporter-name - description: uplink-syndicate-teleporter-desc - icon: { sprite: _CorvaxNext/Objects/Devices/syndicate_teleporter.rsi, state: icon } - productEntity: SyndicateTeleporter - cost: - Telecrystal: 12 - categories: - - UplinkDisruption -# Corvax-Next-Teleporter-End diff --git a/Resources/Prototypes/_CorvaxNext/Catalog/uplink_catalog.yml b/Resources/Prototypes/_CorvaxNext/Catalog/uplink_catalog.yml new file mode 100644 index 00000000000..fae7a0b49d1 --- /dev/null +++ b/Resources/Prototypes/_CorvaxNext/Catalog/uplink_catalog.yml @@ -0,0 +1,10 @@ +- type: listing + id: UplinkTeleporter + name: uplink-syndicate-teleporter-name + description: uplink-syndicate-teleporter-desc + icon: { sprite: _CorvaxNext/Objects/Devices/syndicate_teleporter.rsi, state: icon } + productEntity: SyndicateTeleporter + cost: + Telecrystal: 12 + categories: + - UplinkDisruption