From 7b52ecd62ac62b1b852a5f132a50edfed8966618 Mon Sep 17 00:00:00 2001 From: Spatison <137375981+Spatison@users.noreply.github.com> Date: Sat, 21 Sep 2024 13:05:07 +0300 Subject: [PATCH] add: experimentel teleport --- .../ExperimentalTeleporterComponent.cs | 28 ++++ .../ExperimentalTeleporterSystem.cs | 111 ++++++++++++++++ .../_White/Object/Devices/attributions.yml | 4 + .../Devices/experimentalsyndicateteleport.ogg | Bin 0 -> 11769 bytes .../en-US/_white/store/uplink-catalog.ftl | 5 +- .../experimental-teleporter.ftl | 2 + .../ru-RU/_white/store/uplink-catalog.ftl | 5 +- .../_White/Catalog/uplink_catalog.yml | 10 ++ .../_White/Entities/Effects/effects.yml | 39 ++++++ .../experimental_teleporter.yml | 16 +++ .../icon.png | Bin 0 -> 409 bytes .../in.png | Bin 0 -> 5476 bytes .../inhand-left.png | Bin 0 -> 248 bytes .../inhand-right.png | Bin 0 -> 247 bytes .../meta.json | 122 ++++++++++++++++++ .../out.png | Bin 0 -> 4370 bytes 16 files changed, 340 insertions(+), 2 deletions(-) create mode 100644 Content.Server/_White/Teleporter/ExperimentalTeleporterComponent.cs create mode 100644 Content.Server/_White/Teleporter/ExperimentalTeleporterSystem.cs create mode 100644 Resources/Audio/_White/Object/Devices/attributions.yml create mode 100644 Resources/Audio/_White/Object/Devices/experimentalsyndicateteleport.ogg create mode 100644 Resources/Locale/ru-RU/_white/prototypes/entities/objects/device/syndicate_gadgets/experimental-teleporter.ftl create mode 100644 Resources/Prototypes/_White/Entities/Effects/effects.yml create mode 100644 Resources/Prototypes/_White/Entities/Objects/Devices/Syndicate_Gadgets/experimental_teleporter.yml create mode 100644 Resources/Textures/_White/Objects/Devices/experimentalsyndicateteleporter.rsi/icon.png create mode 100644 Resources/Textures/_White/Objects/Devices/experimentalsyndicateteleporter.rsi/in.png create mode 100644 Resources/Textures/_White/Objects/Devices/experimentalsyndicateteleporter.rsi/inhand-left.png create mode 100644 Resources/Textures/_White/Objects/Devices/experimentalsyndicateteleporter.rsi/inhand-right.png create mode 100644 Resources/Textures/_White/Objects/Devices/experimentalsyndicateteleporter.rsi/meta.json create mode 100644 Resources/Textures/_White/Objects/Devices/experimentalsyndicateteleporter.rsi/out.png diff --git a/Content.Server/_White/Teleporter/ExperimentalTeleporterComponent.cs b/Content.Server/_White/Teleporter/ExperimentalTeleporterComponent.cs new file mode 100644 index 0000000000..c9a773e531 --- /dev/null +++ b/Content.Server/_White/Teleporter/ExperimentalTeleporterComponent.cs @@ -0,0 +1,28 @@ +using Robust.Shared.Audio; + +namespace Content.Server._White.Teleporter; + +[RegisterComponent] +public sealed partial class ExperimentalTeleporterComponent : Component +{ + [DataField] + public int MinTeleportRange = 3; + + [DataField] + public int MaxTeleportRange = 8; + + [DataField] + public int EmergencyLength = 4; + + [DataField] + public List RandomRotations = new() {90, -90}; + + [DataField] + public string? TeleportInEffect = "ExperimentalTeleporterInEffect"; + + [DataField] + public string? TeleportOutEffect = "ExperimentalTeleporterOutEffect"; + + [DataField] + public SoundSpecifier TeleportSound = new SoundPathSpecifier("/Audio/_White/Object/Devices/experimentalsyndicateteleport.ogg"); +} diff --git a/Content.Server/_White/Teleporter/ExperimentalTeleporterSystem.cs b/Content.Server/_White/Teleporter/ExperimentalTeleporterSystem.cs new file mode 100644 index 0000000000..7bc70b6bfd --- /dev/null +++ b/Content.Server/_White/Teleporter/ExperimentalTeleporterSystem.cs @@ -0,0 +1,111 @@ +using System.Linq; +using System.Numerics; +using Content.Server.Body.Systems; +using Content.Server.Standing; +using Content.Shared.Charges.Systems; +using Content.Shared.Coordinates.Helpers; +using Content.Shared.Interaction.Events; +using Content.Shared.Maps; +using Content.Shared.Tag; +using Robust.Server.Audio; +using Robust.Server.Containers; +using Robust.Server.GameObjects; +using Robust.Shared.Map; +using Robust.Shared.Map.Components; +using Robust.Shared.Random; + +namespace Content.Server._White.Teleporter; + +public sealed class ExperimentalTeleporterSystem : EntitySystem +{ + [Dependency] private readonly TransformSystem _transform = default!; + [Dependency] private readonly BodySystem _bodySystem = default!; + [Dependency] private readonly MapSystem _mapSystem = default!; + [Dependency] private readonly IEntityManager _entManager = default!; + [Dependency] private readonly AudioSystem _audio = default!; + [Dependency] private readonly ContainerSystem _containerSystem = default!; + [Dependency] private readonly IRobustRandom _random = default!; + [Dependency] private readonly LayingDownSystem _layingDown = default!; + [Dependency] private readonly SharedChargesSystem _charges = default!; + [Dependency] private readonly TagSystem _tag = default!; + + public override void Initialize() + { + base.Initialize(); + SubscribeLocalEvent(OnUse); + } + + private void OnUse(EntityUid uid, ExperimentalTeleporterComponent component, UseInHandEvent args) + { + if (_charges.IsEmpty(uid) + || !TryComp(args.User, out var xform) + || _containerSystem.IsEntityInContainer(args.User) + && !_containerSystem.TryRemoveFromContainer(args.User)) + return; + + var oldCoords = xform.Coordinates; + var random = _random.Next(component.MinTeleportRange, component.MaxTeleportRange); + var offset = xform.LocalRotation.ToWorldVec().Normalized(); + var direction = xform.LocalRotation.GetDir().ToVec(); + var newOffset = offset + direction * random; + + var coords = xform.Coordinates.Offset(newOffset).SnapToGrid(EntityManager); + + Teleport(args.User, uid, component, coords, oldCoords); + + if (!TryCheckWall(coords) + || EmergencyTeleportation(args.User, uid, component, xform, oldCoords, newOffset)) + return; + + _bodySystem.GibBody(args.User, true, splatModifier: 3F); + } + + private bool EmergencyTeleportation(EntityUid uid, EntityUid teleporterUid, ExperimentalTeleporterComponent component, TransformComponent xform, EntityCoordinates oldCoords, Vector2 offset) + { + var newOffset = offset + VectorRandomDirection(component, offset, component.EmergencyLength); + var coords = xform.Coordinates.Offset(newOffset).SnapToGrid(EntityManager); + + if (_charges.IsEmpty(teleporterUid)) + return false; + + Teleport(uid, teleporterUid, component, coords, oldCoords); + + return !TryCheckWall(coords); + } + + private void Teleport(EntityUid uid, EntityUid teleporterUid, ExperimentalTeleporterComponent component, EntityCoordinates coords, EntityCoordinates oldCoords) + { + SoundAndEffects(component, coords, oldCoords); + + _layingDown.LieDownInRange(uid, coords); + _transform.SetCoordinates(uid, coords); + + _charges.UseCharge(teleporterUid); + } + + private void SoundAndEffects(ExperimentalTeleporterComponent component, EntityCoordinates coords, EntityCoordinates oldCoords) + { + _audio.PlayPvs(component.TeleportSound, coords); + _audio.PlayPvs(component.TeleportSound, oldCoords); + + _entManager.SpawnEntity(component.TeleportInEffect, coords); + _entManager.SpawnEntity(component.TeleportOutEffect, oldCoords); + } + + private bool TryCheckWall(EntityCoordinates coords) + { + if (!coords.TryGetTileRef(out var tile) + || !TryComp(tile.Value.GridUid, out var mapGridComponent)) + return false; + + var anchoredEntities = _mapSystem.GetAnchoredEntities(tile.Value.GridUid, mapGridComponent, coords); + + return anchoredEntities.Any(x => _tag.HasTag(x, "Wall")); + } + + private Vector2 VectorRandomDirection(ExperimentalTeleporterComponent component, Vector2 offset, int length) + { + var randomRotation = _random.Next(0, component.RandomRotations.Count); + return Angle.FromDegrees(component.RandomRotations[randomRotation]).RotateVec(offset.Normalized() * length); + } +} diff --git a/Resources/Audio/_White/Object/Devices/attributions.yml b/Resources/Audio/_White/Object/Devices/attributions.yml new file mode 100644 index 0000000000..a8950150f7 --- /dev/null +++ b/Resources/Audio/_White/Object/Devices/attributions.yml @@ -0,0 +1,4 @@ +- files: ["experimentalsyndicateteleport.ogg"] + license: "CC-BY-NC-SA-4.0" + copyright: "Taken from White Dream" + source: "https://github.com/frosty-dev/ss14-core/blob/master/Resources/Audio/White/Devices/expsyndicateteleport.ogg" \ No newline at end of file diff --git a/Resources/Audio/_White/Object/Devices/experimentalsyndicateteleport.ogg b/Resources/Audio/_White/Object/Devices/experimentalsyndicateteleport.ogg new file mode 100644 index 0000000000000000000000000000000000000000..37a5b3839c3152fba758da1df4cd760d7356aa88 GIT binary patch literal 11769 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 literal 0 HcmV?d00001 diff --git a/Resources/Locale/en-US/_white/store/uplink-catalog.ftl b/Resources/Locale/en-US/_white/store/uplink-catalog.ftl index 44ce8ca0fa..5a8d9288ca 100644 --- a/Resources/Locale/en-US/_white/store/uplink-catalog.ftl +++ b/Resources/Locale/en-US/_white/store/uplink-catalog.ftl @@ -2,4 +2,7 @@ uplink-emp-flashlight-desc = A rechargeable device disguised as a flashlight designed to disrupt electronic systems. Useful for disrupting communications, security's energy weapons, and APCs when you're in a tight spot. uplink-betrayal-knife-name = Betrayal dagger -uplink-betrayal-knife-desc = The betrayal dagger allows the user to teleport a short distance, and also causes significant damage when stabbed in the back. \ No newline at end of file +uplink-betrayal-knife-desc = The betrayal dagger allows the user to teleport a short distance, and also causes significant damage when stabbed in the back. + +uplink-betrayal-knife-name = Experimental syndicate teleporter +uplink-betrayal-knife-desc = Syndicate teleporter, when used, moves 3-8 meters forward. In case of teleportation into a wall, uses emergency teleportation. Has 4 charge. \ No newline at end of file diff --git a/Resources/Locale/ru-RU/_white/prototypes/entities/objects/device/syndicate_gadgets/experimental-teleporter.ftl b/Resources/Locale/ru-RU/_white/prototypes/entities/objects/device/syndicate_gadgets/experimental-teleporter.ftl new file mode 100644 index 0000000000..f9359375ac --- /dev/null +++ b/Resources/Locale/ru-RU/_white/prototypes/entities/objects/device/syndicate_gadgets/experimental-teleporter.ftl @@ -0,0 +1,2 @@ +ent-ExperimentalSyndicateTeleporter = экспериментальный телепортер синдиката + .desc = Телепортер синдиката, при использовании перемещает на 3-8 метров вперед. В случае телепортации в стену, использует экстренную телепортацию. Имеет 4 заряда и автоматически заряжается. \ No newline at end of file diff --git a/Resources/Locale/ru-RU/_white/store/uplink-catalog.ftl b/Resources/Locale/ru-RU/_white/store/uplink-catalog.ftl index 5953a18549..9d757b318a 100644 --- a/Resources/Locale/ru-RU/_white/store/uplink-catalog.ftl +++ b/Resources/Locale/ru-RU/_white/store/uplink-catalog.ftl @@ -2,4 +2,7 @@ uplink-emp-flashlight-desc = Замаскированное под фонарик устройство. При ударе выпускает ЭМИ, поражающий электрические устройства. uplink-betrayal-knife-name = Предательский кинжал -uplink-betrayal-knife-desc = Предательский кинжал позволяет пользователю телепортироваться на короткое расстояние, а также наносит значительные повреждения при ударе в спину. \ No newline at end of file +uplink-betrayal-knife-desc = Предательский кинжал позволяет пользователю телепортироваться на короткое расстояние, а также наносит значительные повреждения при ударе в спину. + +uplink-experimental-syndicate-teleporter-name = Экспериментальный телепортер синдиката +uplink-experimental-syndicate-teleporter-desc = Телепортер синдиката, при использовании перемещает на 3-8 метров вперед. В случае телепортации в стену, использует экстренную телепортацию. Имеет 4 заряда и автоматически заряжается. \ No newline at end of file diff --git a/Resources/Prototypes/_White/Catalog/uplink_catalog.yml b/Resources/Prototypes/_White/Catalog/uplink_catalog.yml index 4c1e4b0a60..960188ea00 100644 --- a/Resources/Prototypes/_White/Catalog/uplink_catalog.yml +++ b/Resources/Prototypes/_White/Catalog/uplink_catalog.yml @@ -8,6 +8,16 @@ categories: - UplinkUtility +- type: listing + id: UplinkExperimentalSyndicateTeleporter + name: uplink-experimental-syndicate-teleporter-name + description: uplink-experimental-syndicate-teleporter-desc + productEntity: ExperimentalSyndicateTeleporter + cost: + Telecrystal: 10 + categories: + - UplinkUtility + - type: listing id: UplinkBetrayalKnife name: uplink-betrayal-knife-name diff --git a/Resources/Prototypes/_White/Entities/Effects/effects.yml b/Resources/Prototypes/_White/Entities/Effects/effects.yml new file mode 100644 index 0000000000..2c20be01c5 --- /dev/null +++ b/Resources/Prototypes/_White/Entities/Effects/effects.yml @@ -0,0 +1,39 @@ +- type: entity + id: ExperimentalTeleporterInEffect + name: experimental syndicate teleporter in effect + components: + - type: TimedDespawn + lifetime: 0.6 + - type: EvaporationSparkle + - type: Transform + noRot: true + anchored: true + - type: Sprite + layers: + - sprite: /Textures/_White/Objects/Devices/experimentalsyndicateteleporter.rsi + state: in + shader: unshaded + netsync: false + drawdepth: Effects + - type: PointLight + color: "#008DFE" + +- type: entity + id: ExperimentalTeleporterOutEffect + name: experimental syndicate teleporter out effect + components: + - type: TimedDespawn + lifetime: 0.6 + - type: EvaporationSparkle + - type: Transform + noRot: true + anchored: true + - type: Sprite + layers: + - sprite: /Textures/_White/Objects/Devices/experimentalsyndicateteleporter.rsi + state: out + shader: unshaded + netsync: false + drawdepth: Effects + - type: PointLight + color: "#008DFE" \ No newline at end of file diff --git a/Resources/Prototypes/_White/Entities/Objects/Devices/Syndicate_Gadgets/experimental_teleporter.yml b/Resources/Prototypes/_White/Entities/Objects/Devices/Syndicate_Gadgets/experimental_teleporter.yml new file mode 100644 index 0000000000..9bade18288 --- /dev/null +++ b/Resources/Prototypes/_White/Entities/Objects/Devices/Syndicate_Gadgets/experimental_teleporter.yml @@ -0,0 +1,16 @@ +- type: entity + id: ExperimentalSyndicateTeleporter + parent: BaseItem + name: experimental syndicate teleporter + description: Syndicate teleporter, when used, moves 3-8 meters forward. In case of teleportation into a wall, uses emergency teleportation. Has 4 charge. + components: + - type: Sprite + sprite: /Textures/_White/Objects/Devices/experimentalsyndicateteleporter.rsi + layers: + - state: icon + - type: ExperimentalTeleporter + - type: LimitedCharges + maxCharges: 4 + charges: 4 + - type: AutoRecharge + rechargeDuration: 10 \ No newline at end of file diff --git a/Resources/Textures/_White/Objects/Devices/experimentalsyndicateteleporter.rsi/icon.png b/Resources/Textures/_White/Objects/Devices/experimentalsyndicateteleporter.rsi/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..106f3f415c8b82bf3a934a7ccf22d97bab6320d9 GIT binary patch literal 409 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I3?%1nZ+ru!7>k44ofy`glX(f`#0L0;xU$M= z@ONBcw~pb?Tw-itBO$989Ua}%(-SmxR>8W>o?%H^ffhMC>WUAwq^&J0KiRo=@4hn( z3^N%RywdV{_ylai;=S6sfrb?@Ff3qU*~P%{pMjx^fk9v2Ku%8XfQXn4P)@!i$S?Rm zcEA7?J{B;)8mM%?r;B4qMC;pW2f3OJ1YDRUKZt2^@T&ayKmVqL?yNNTtX#!ua})G7 z|2AT|X!?D!5m$y_!5nKTW b!WsBI8e_yXpS`LAdWFH$)z4*}Q$iB}Um2xI literal 0 HcmV?d00001 diff --git a/Resources/Textures/_White/Objects/Devices/experimentalsyndicateteleporter.rsi/in.png b/Resources/Textures/_White/Objects/Devices/experimentalsyndicateteleporter.rsi/in.png new file mode 100644 index 0000000000000000000000000000000000000000..456e592a332082ac7d6437666ad9dcabe3519ada GIT binary patch literal 5476 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