From 2b6c352afffbd90f56c4300eed1011f6e948a4c9 Mon Sep 17 00:00:00 2001 From: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com> Date: Fri, 24 Jun 2022 17:44:30 +1000 Subject: [PATCH] Jetpacks (#9023) * Movement acceleration * tweaks * Weightless refactor coz fuck it * CCVars * weightless movement tweaks * Some cleanup while I'm here * dorkpacks * thanks fork * fixes * zoomies * toggles * hmm * yamls * b * so true * Effects refactor * namespace * review --- Content.Client/Clothing/MagbootsSystem.cs | 1 - .../Movement/Components/ClimbableComponent.cs | 1 + .../Movement/Components/ClimbingComponent.cs | 3 +- .../Movement/{ => Systems}/ClimbSystem.cs | 4 +- .../Movement/Systems/JetpackSystem.cs | 80 ++++++ .../Nutrition/Components/HungerComponent.cs | 2 +- .../Physics/Controllers/MoverController.cs | 1 + Content.Client/Spawners/TimedDespawnSystem.cs | 11 + .../Atmos/Components/GasTankComponent.cs | 5 + Content.Server/Body/Systems/BodySystem.cs | 2 +- .../ReagentEffects/MovespeedModifier.cs | 2 +- .../Disposal/Tube/DisposalTubeSystem.cs | 1 + .../Unit/EntitySystems/DisposalUnitSystem.cs | 1 + Content.Server/Ghost/GhostSystem.cs | 2 +- Content.Server/Magic/MagicSystem.cs | 1 + .../Medical/MedicalScannerSystem.cs | 1 + .../Movement/Systems/JetpackSystem.cs | 48 ++++ .../Nutrition/Components/HungerComponent.cs | 2 +- .../Nutrition/EntitySystems/ThirstSystem.cs | 2 +- .../Physics/Controllers/MoverController.cs | 1 + .../Resist/EscapeInventorySystem.cs | 2 +- Content.Server/Resist/ResistLockerSystem.cs | 1 + .../EntitySystems/TimedDespawnSystem.cs | 16 +- .../Storage/EntitySystems/StorageSystem.cs | 1 + .../ActionBlocker/ActionBlockerSystem.cs | 1 + .../Administration/AdminFrozenSystem.cs | 1 + Content.Shared/Buckle/SharedBuckleSystem.cs | 1 + .../MetabolismMovespeedModifierSystem.cs | 2 +- Content.Shared/Climbing/SharedClimbSystem.cs | 1 + .../Clothing/ClothingSpeedModifierSystem.cs | 2 +- Content.Shared/Cuffs/SharedCuffableSystem.cs | 1 + .../Damage/Systems/SlowOnDamageSystem.cs | 2 +- Content.Shared/Follower/FollowerSystem.cs | 2 +- .../Friction/SharedTileFrictionController.cs | 1 + .../Inventory/InventorySystem.Equip.cs | 2 +- .../Inventory/InventorySystem.Relay.cs | 2 +- .../MobState/EntitySystems/MobStateSystem.cs | 1 + .../Components/ActiveJetpackComponent.cs | 13 + .../Movement/Components/JetpackComponent.cs | 24 ++ .../Components/JetpackUserComponent.cs | 14 ++ .../MovementSpeedModifierComponent.cs | 2 +- .../EntitySystems/SharedMobMoverSystem.cs | 48 ---- .../Movement/Events/RelayMoveInputEvent.cs | 13 + .../{ => Events}/RelayMovementEntityEvent.cs | 2 +- .../Movement/Events/ToggleJetpackEvent.cs | 8 + .../{ => Events}/UpdateCanMoveEvent.cs | 2 +- .../Movement/Events/WeightlessMoveEvent.cs | 14 ++ .../Movement/MobMovementProfileEvent.cs | 35 +++ .../MovementIgnoreGravitySystem.cs | 5 +- .../MovementSpeedModifierSystem.cs | 26 +- .../Movement/Systems/SharedJetpackSystem.cs | 124 +++++++++ .../SharedMoverController.Input.cs} | 88 +++---- .../Systems/SharedMoverController.Pushing.cs | 56 +++++ .../{ => Systems}/SharedMoverController.cs | 82 ++++-- .../SlowContactsSystem.cs | 8 +- .../EntitySystems/SharedHungerSystem.cs | 2 +- Content.Shared/PAI/SharedPAISystem.cs | 1 + .../Pulling/Systems/SharedPullableSystem.cs | 2 +- .../Pulling/Systems/SharedPullerSystem.cs | 2 +- .../Systems/SharedShuttleConsoleSystem.cs | 1 + .../Components/TimedDespawnComponent.cs | 2 +- .../EntitySystems/SharedTimedDespawnSystem.cs | 28 +++ Content.Shared/Stunnable/SharedStunSystem.cs | 7 +- .../Weapons/Ranged/Systems/SharedGunSystem.cs | 8 +- .../Entities/Objects/Tools/jetpacks.yml | 235 ++++++++++++++++++ .../Jetpacks/black.rsi/equipped-BACKPACK.png | Bin 0 -> 810 bytes .../Tanks/Jetpacks/black.rsi/icon-on.png | Bin 0 -> 580 bytes .../Objects/Tanks/Jetpacks/black.rsi/icon.png | Bin 0 -> 461 bytes .../Tanks/Jetpacks/black.rsi/inhand-left.png | Bin 0 -> 516 bytes .../Tanks/Jetpacks/black.rsi/inhand-right.png | Bin 0 -> 529 bytes .../Tanks/Jetpacks/black.rsi/meta.json | 59 +++++ .../black.rsi/on-equipped-BACKPACK.png | Bin 0 -> 1089 bytes .../Jetpacks/blue.rsi/equipped-BACKPACK.png | Bin 0 -> 835 bytes .../Tanks/Jetpacks/blue.rsi/icon-on.png | Bin 0 -> 592 bytes .../Objects/Tanks/Jetpacks/blue.rsi/icon.png | Bin 0 -> 476 bytes .../Tanks/Jetpacks/blue.rsi/inhand-left.png | Bin 0 -> 534 bytes .../Tanks/Jetpacks/blue.rsi/inhand-right.png | Bin 0 -> 555 bytes .../Objects/Tanks/Jetpacks/blue.rsi/meta.json | 59 +++++ .../blue.rsi/on-equipped-BACKPACK.png | Bin 0 -> 1073 bytes .../captain.rsi/equipped-BACKPACK.png | Bin 0 -> 838 bytes .../Tanks/Jetpacks/captain.rsi/icon-on.png | Bin 0 -> 599 bytes .../Tanks/Jetpacks/captain.rsi/icon.png | Bin 0 -> 508 bytes .../Jetpacks/captain.rsi/inhand-left.png | Bin 0 -> 530 bytes .../Jetpacks/captain.rsi/inhand-right.png | Bin 0 -> 551 bytes .../Tanks/Jetpacks/captain.rsi/meta.json | 59 +++++ .../captain.rsi/on-equipped-BACKPACK.png | Bin 0 -> 1099 bytes .../Jetpacks/mini.rsi/equipped-BACKPACK.png | Bin 0 -> 1021 bytes .../Tanks/Jetpacks/mini.rsi/icon-on.png | Bin 0 -> 1457 bytes .../Objects/Tanks/Jetpacks/mini.rsi/icon.png | Bin 0 -> 616 bytes .../Tanks/Jetpacks/mini.rsi/inhand-left.png | Bin 0 -> 516 bytes .../Tanks/Jetpacks/mini.rsi/inhand-right.png | Bin 0 -> 529 bytes .../Objects/Tanks/Jetpacks/mini.rsi/meta.json | 64 +++++ .../mini.rsi/on-equipped-BACKPACK.png | Bin 0 -> 2190 bytes .../security.rsi/equipped-BACKPACK.png | Bin 0 -> 839 bytes .../Tanks/Jetpacks/security.rsi/icon-on.png | Bin 0 -> 574 bytes .../Tanks/Jetpacks/security.rsi/icon.png | Bin 0 -> 479 bytes .../Jetpacks/security.rsi/inhand-left.png | Bin 0 -> 563 bytes .../Jetpacks/security.rsi/inhand-right.png | Bin 0 -> 564 bytes .../Tanks/Jetpacks/security.rsi/meta.json | 59 +++++ .../security.rsi/on-equipped-BACKPACK.png | Bin 0 -> 1145 bytes .../Jetpacks/void.rsi/equipped-BACKPACK.png | Bin 0 -> 892 bytes .../Tanks/Jetpacks/void.rsi/icon-on.png | Bin 0 -> 434 bytes .../Objects/Tanks/Jetpacks/void.rsi/icon.png | Bin 0 -> 379 bytes .../Tanks/Jetpacks/void.rsi/inhand-left.png | Bin 0 -> 579 bytes .../Tanks/Jetpacks/void.rsi/inhand-right.png | Bin 0 -> 596 bytes .../Objects/Tanks/Jetpacks/void.rsi/meta.json | 41 +++ .../void.rsi/on-equipped-BACKPACK.png | Bin 0 -> 892 bytes 107 files changed, 1197 insertions(+), 206 deletions(-) rename Content.Client/Movement/{ => Systems}/ClimbSystem.cs (97%) create mode 100644 Content.Client/Movement/Systems/JetpackSystem.cs create mode 100644 Content.Client/Spawners/TimedDespawnSystem.cs create mode 100644 Content.Server/Movement/Systems/JetpackSystem.cs create mode 100644 Content.Shared/Movement/Components/ActiveJetpackComponent.cs create mode 100644 Content.Shared/Movement/Components/JetpackComponent.cs create mode 100644 Content.Shared/Movement/Components/JetpackUserComponent.cs delete mode 100644 Content.Shared/Movement/EntitySystems/SharedMobMoverSystem.cs create mode 100644 Content.Shared/Movement/Events/RelayMoveInputEvent.cs rename Content.Shared/Movement/{ => Events}/RelayMovementEntityEvent.cs (84%) create mode 100644 Content.Shared/Movement/Events/ToggleJetpackEvent.cs rename Content.Shared/Movement/{ => Events}/UpdateCanMoveEvent.cs (90%) create mode 100644 Content.Shared/Movement/Events/WeightlessMoveEvent.cs create mode 100644 Content.Shared/Movement/MobMovementProfileEvent.cs rename Content.Shared/Movement/{EntitySystems => Systems}/MovementIgnoreGravitySystem.cs (86%) rename Content.Shared/Movement/{EntitySystems => Systems}/MovementSpeedModifierSystem.cs (80%) create mode 100644 Content.Shared/Movement/Systems/SharedJetpackSystem.cs rename Content.Shared/Movement/{EntitySystems/SharedMoverSystem.cs => Systems/SharedMoverController.Input.cs} (59%) create mode 100644 Content.Shared/Movement/Systems/SharedMoverController.Pushing.cs rename Content.Shared/Movement/{ => Systems}/SharedMoverController.cs (82%) rename Content.Shared/Movement/{EntitySystems => Systems}/SlowContactsSystem.cs (91%) rename {Content.Server => Content.Shared}/Spawners/Components/TimedDespawnComponent.cs (88%) create mode 100644 Content.Shared/Spawners/EntitySystems/SharedTimedDespawnSystem.cs create mode 100644 Resources/Prototypes/Entities/Objects/Tools/jetpacks.yml create mode 100644 Resources/Textures/Objects/Tanks/Jetpacks/black.rsi/equipped-BACKPACK.png create mode 100644 Resources/Textures/Objects/Tanks/Jetpacks/black.rsi/icon-on.png create mode 100644 Resources/Textures/Objects/Tanks/Jetpacks/black.rsi/icon.png create mode 100644 Resources/Textures/Objects/Tanks/Jetpacks/black.rsi/inhand-left.png create mode 100644 Resources/Textures/Objects/Tanks/Jetpacks/black.rsi/inhand-right.png create mode 100644 Resources/Textures/Objects/Tanks/Jetpacks/black.rsi/meta.json create mode 100644 Resources/Textures/Objects/Tanks/Jetpacks/black.rsi/on-equipped-BACKPACK.png create mode 100644 Resources/Textures/Objects/Tanks/Jetpacks/blue.rsi/equipped-BACKPACK.png create mode 100644 Resources/Textures/Objects/Tanks/Jetpacks/blue.rsi/icon-on.png create mode 100644 Resources/Textures/Objects/Tanks/Jetpacks/blue.rsi/icon.png create mode 100644 Resources/Textures/Objects/Tanks/Jetpacks/blue.rsi/inhand-left.png create mode 100644 Resources/Textures/Objects/Tanks/Jetpacks/blue.rsi/inhand-right.png create mode 100644 Resources/Textures/Objects/Tanks/Jetpacks/blue.rsi/meta.json create mode 100644 Resources/Textures/Objects/Tanks/Jetpacks/blue.rsi/on-equipped-BACKPACK.png create mode 100644 Resources/Textures/Objects/Tanks/Jetpacks/captain.rsi/equipped-BACKPACK.png create mode 100644 Resources/Textures/Objects/Tanks/Jetpacks/captain.rsi/icon-on.png create mode 100644 Resources/Textures/Objects/Tanks/Jetpacks/captain.rsi/icon.png create mode 100644 Resources/Textures/Objects/Tanks/Jetpacks/captain.rsi/inhand-left.png create mode 100644 Resources/Textures/Objects/Tanks/Jetpacks/captain.rsi/inhand-right.png create mode 100644 Resources/Textures/Objects/Tanks/Jetpacks/captain.rsi/meta.json create mode 100644 Resources/Textures/Objects/Tanks/Jetpacks/captain.rsi/on-equipped-BACKPACK.png create mode 100644 Resources/Textures/Objects/Tanks/Jetpacks/mini.rsi/equipped-BACKPACK.png create mode 100644 Resources/Textures/Objects/Tanks/Jetpacks/mini.rsi/icon-on.png create mode 100644 Resources/Textures/Objects/Tanks/Jetpacks/mini.rsi/icon.png create mode 100644 Resources/Textures/Objects/Tanks/Jetpacks/mini.rsi/inhand-left.png create mode 100644 Resources/Textures/Objects/Tanks/Jetpacks/mini.rsi/inhand-right.png create mode 100644 Resources/Textures/Objects/Tanks/Jetpacks/mini.rsi/meta.json create mode 100644 Resources/Textures/Objects/Tanks/Jetpacks/mini.rsi/on-equipped-BACKPACK.png create mode 100644 Resources/Textures/Objects/Tanks/Jetpacks/security.rsi/equipped-BACKPACK.png create mode 100644 Resources/Textures/Objects/Tanks/Jetpacks/security.rsi/icon-on.png create mode 100644 Resources/Textures/Objects/Tanks/Jetpacks/security.rsi/icon.png create mode 100644 Resources/Textures/Objects/Tanks/Jetpacks/security.rsi/inhand-left.png create mode 100644 Resources/Textures/Objects/Tanks/Jetpacks/security.rsi/inhand-right.png create mode 100644 Resources/Textures/Objects/Tanks/Jetpacks/security.rsi/meta.json create mode 100644 Resources/Textures/Objects/Tanks/Jetpacks/security.rsi/on-equipped-BACKPACK.png create mode 100644 Resources/Textures/Objects/Tanks/Jetpacks/void.rsi/equipped-BACKPACK.png create mode 100644 Resources/Textures/Objects/Tanks/Jetpacks/void.rsi/icon-on.png create mode 100644 Resources/Textures/Objects/Tanks/Jetpacks/void.rsi/icon.png create mode 100644 Resources/Textures/Objects/Tanks/Jetpacks/void.rsi/inhand-left.png create mode 100644 Resources/Textures/Objects/Tanks/Jetpacks/void.rsi/inhand-right.png create mode 100644 Resources/Textures/Objects/Tanks/Jetpacks/void.rsi/meta.json create mode 100644 Resources/Textures/Objects/Tanks/Jetpacks/void.rsi/on-equipped-BACKPACK.png diff --git a/Content.Client/Clothing/MagbootsSystem.cs b/Content.Client/Clothing/MagbootsSystem.cs index 220d8db819..b832a3559b 100644 --- a/Content.Client/Clothing/MagbootsSystem.cs +++ b/Content.Client/Clothing/MagbootsSystem.cs @@ -1,5 +1,4 @@ using Content.Shared.Clothing; -using Content.Shared.Movement.EntitySystems; namespace Content.Client.Clothing { diff --git a/Content.Client/Movement/Components/ClimbableComponent.cs b/Content.Client/Movement/Components/ClimbableComponent.cs index 730c333693..1c695ac792 100644 --- a/Content.Client/Movement/Components/ClimbableComponent.cs +++ b/Content.Client/Movement/Components/ClimbableComponent.cs @@ -1,3 +1,4 @@ +using Content.Client.Movement.Systems; using Content.Shared.Climbing; namespace Content.Client.Movement.Components; diff --git a/Content.Client/Movement/Components/ClimbingComponent.cs b/Content.Client/Movement/Components/ClimbingComponent.cs index e68592bd77..ef5ada9529 100644 --- a/Content.Client/Movement/Components/ClimbingComponent.cs +++ b/Content.Client/Movement/Components/ClimbingComponent.cs @@ -1,4 +1,5 @@ -using Content.Shared.Climbing; +using Content.Client.Movement.Systems; +using Content.Shared.Climbing; namespace Content.Client.Movement.Components; diff --git a/Content.Client/Movement/ClimbSystem.cs b/Content.Client/Movement/Systems/ClimbSystem.cs similarity index 97% rename from Content.Client/Movement/ClimbSystem.cs rename to Content.Client/Movement/Systems/ClimbSystem.cs index f8b1afc3cf..0354ee020e 100644 --- a/Content.Client/Movement/ClimbSystem.cs +++ b/Content.Client/Movement/Systems/ClimbSystem.cs @@ -4,12 +4,12 @@ using Content.Shared.Climbing; using Content.Shared.DragDrop; using Robust.Shared.GameStates; -namespace Content.Client.Movement; +namespace Content.Client.Movement.Systems; public sealed class ClimbSystem : SharedClimbSystem { [Dependency] private readonly InteractionSystem _interactionSystem = default!; - + public override void Initialize() { base.Initialize(); diff --git a/Content.Client/Movement/Systems/JetpackSystem.cs b/Content.Client/Movement/Systems/JetpackSystem.cs new file mode 100644 index 0000000000..0a9b850e16 --- /dev/null +++ b/Content.Client/Movement/Systems/JetpackSystem.cs @@ -0,0 +1,80 @@ +using Content.Client.Clothing; +using Content.Shared.Movement.Components; +using Content.Shared.Movement.Systems; +using Content.Shared.Weapons.Ranged.Systems; +using Robust.Client.Animations; +using Robust.Client.GameObjects; +using Robust.Shared.GameStates; +using Robust.Shared.Map; +using Robust.Shared.Timing; + +namespace Content.Client.Movement.Systems; + +public sealed class JetpackSystem : SharedJetpackSystem +{ + [Dependency] private readonly IGameTiming _timing = default!; + [Dependency] private readonly IMapManager _mapManager = default!; + + public override void Initialize() + { + base.Initialize(); + SubscribeLocalEvent(OnJetpackAppearance); + } + + protected override bool CanEnable(JetpackComponent component) + { + // No predicted atmos so you'd have to do a lot of funny to get this working. + return false; + } + + private void OnJetpackAppearance(EntityUid uid, JetpackComponent component, ref AppearanceChangeEvent args) + { + args.Component.TryGetData(JetpackVisuals.Enabled, out bool enabled); + + var state = "icon" + (enabled ? "-on" : ""); + args.Sprite?.LayerSetState(0, state); + + if (TryComp(uid, out var clothing)) + clothing.EquippedPrefix = enabled ? "on" : null; + } + + public override void Update(float frameTime) + { + base.Update(frameTime); + + if (!_timing.IsFirstTimePredicted) return; + + foreach (var comp in EntityQuery()) + { + comp.Accumulator += frameTime; + + if (comp.Accumulator < comp.EffectCooldown) continue; + comp.Accumulator -= comp.EffectCooldown; + CreateParticles(comp.Owner); + } + } + + private void CreateParticles(EntityUid uid) + { + var uidXform = Transform(uid); + var coordinates = uidXform.Coordinates; + var gridUid = coordinates.GetGridUid(EntityManager); + + if (_mapManager.TryGetGrid(gridUid, out var grid)) + { + coordinates = new EntityCoordinates(grid.GridEntityId, grid.WorldToLocal(coordinates.ToMapPos(EntityManager))); + } + else if (uidXform.MapUid != null) + { + coordinates = new EntityCoordinates(uidXform.MapUid.Value, uidXform.WorldPosition); + } + else + { + return; + } + + var ent = Spawn("JetpackEffect", coordinates); + var xform = Transform(ent); + xform.Coordinates = coordinates; + } +} diff --git a/Content.Client/Nutrition/Components/HungerComponent.cs b/Content.Client/Nutrition/Components/HungerComponent.cs index 989c07d93a..4dea387b44 100644 --- a/Content.Client/Nutrition/Components/HungerComponent.cs +++ b/Content.Client/Nutrition/Components/HungerComponent.cs @@ -1,5 +1,5 @@ using Content.Shared.Movement.Components; -using Content.Shared.Movement.EntitySystems; +using Content.Shared.Movement.Systems; using Content.Shared.Nutrition.Components; using Robust.Shared.GameObjects; diff --git a/Content.Client/Physics/Controllers/MoverController.cs b/Content.Client/Physics/Controllers/MoverController.cs index 6e37d22a4c..6db507f00e 100644 --- a/Content.Client/Physics/Controllers/MoverController.cs +++ b/Content.Client/Physics/Controllers/MoverController.cs @@ -1,6 +1,7 @@ using Content.Shared.MobState.Components; using Content.Shared.Movement; using Content.Shared.Movement.Components; +using Content.Shared.Movement.Systems; using Content.Shared.Pulling.Components; using Robust.Client.Player; using Robust.Shared.Map; diff --git a/Content.Client/Spawners/TimedDespawnSystem.cs b/Content.Client/Spawners/TimedDespawnSystem.cs new file mode 100644 index 0000000000..e899eff099 --- /dev/null +++ b/Content.Client/Spawners/TimedDespawnSystem.cs @@ -0,0 +1,11 @@ +using Content.Shared.Spawners.EntitySystems; + +namespace Content.Client.Spawners; + +public sealed class TimedDespawnSystem : SharedTimedDespawnSystem +{ + protected override bool CanDelete(EntityUid uid) + { + return uid.IsClientSide(); + } +} diff --git a/Content.Server/Atmos/Components/GasTankComponent.cs b/Content.Server/Atmos/Components/GasTankComponent.cs index 5fa613dacf..53d45f9499 100644 --- a/Content.Server/Atmos/Components/GasTankComponent.cs +++ b/Content.Server/Atmos/Components/GasTankComponent.cs @@ -145,6 +145,10 @@ namespace Content.Server.Atmos.Components if (internals == null) return; IsConnected = internals.TryConnectTank(Owner); EntitySystem.Get().SetToggled(ToggleAction, IsConnected); + + // Couldn't toggle! + if (!IsConnected) return; + _connectStream?.Stop(); if (_connectSound != null) @@ -158,6 +162,7 @@ namespace Content.Server.Atmos.Components if (!IsConnected) return; IsConnected = false; EntitySystem.Get().SetToggled(ToggleAction, false); + GetInternalsComponent(owner)?.DisconnectTank(); _disconnectStream?.Stop(); diff --git a/Content.Server/Body/Systems/BodySystem.cs b/Content.Server/Body/Systems/BodySystem.cs index ea6e9d82d3..9aa05dd1ec 100644 --- a/Content.Server/Body/Systems/BodySystem.cs +++ b/Content.Server/Body/Systems/BodySystem.cs @@ -5,7 +5,7 @@ using Content.Server.Kitchen.Components; using Content.Server.Mind.Components; using Content.Shared.Body.Components; using Content.Shared.MobState.Components; -using Content.Shared.Movement.EntitySystems; +using Content.Shared.Movement.Events; using Robust.Shared.Timing; namespace Content.Server.Body.Systems diff --git a/Content.Server/Chemistry/ReagentEffects/MovespeedModifier.cs b/Content.Server/Chemistry/ReagentEffects/MovespeedModifier.cs index 75fc19b3f2..b779255f88 100644 --- a/Content.Server/Chemistry/ReagentEffects/MovespeedModifier.cs +++ b/Content.Server/Chemistry/ReagentEffects/MovespeedModifier.cs @@ -1,6 +1,6 @@ using Content.Shared.Chemistry.Components; using Content.Shared.Chemistry.Reagent; -using Content.Shared.Movement.EntitySystems; +using Content.Shared.Movement.Systems; using Robust.Shared.Timing; namespace Content.Server.Chemistry.ReagentEffects diff --git a/Content.Server/Disposal/Tube/DisposalTubeSystem.cs b/Content.Server/Disposal/Tube/DisposalTubeSystem.cs index eedea8fa55..e50e903ffb 100644 --- a/Content.Server/Disposal/Tube/DisposalTubeSystem.cs +++ b/Content.Server/Disposal/Tube/DisposalTubeSystem.cs @@ -3,6 +3,7 @@ using Content.Server.UserInterface; using Content.Server.Hands.Components; using Content.Shared.Destructible; using Content.Shared.Movement; +using Content.Shared.Movement.Events; using Content.Shared.Verbs; using Content.Shared.Popups; using Robust.Server.GameObjects; diff --git a/Content.Server/Disposal/Unit/EntitySystems/DisposalUnitSystem.cs b/Content.Server/Disposal/Unit/EntitySystems/DisposalUnitSystem.cs index 27024ed7a8..4e7a68d20d 100644 --- a/Content.Server/Disposal/Unit/EntitySystems/DisposalUnitSystem.cs +++ b/Content.Server/Disposal/Unit/EntitySystems/DisposalUnitSystem.cs @@ -18,6 +18,7 @@ using Content.Shared.Hands.EntitySystems; using Content.Shared.Interaction; using Content.Shared.Item; using Content.Shared.Movement; +using Content.Shared.Movement.Events; using Content.Shared.Throwing; using Content.Shared.Verbs; using Robust.Server.GameObjects; diff --git a/Content.Server/Ghost/GhostSystem.cs b/Content.Server/Ghost/GhostSystem.cs index 92b62f384d..37773a02c0 100644 --- a/Content.Server/Ghost/GhostSystem.cs +++ b/Content.Server/Ghost/GhostSystem.cs @@ -11,7 +11,7 @@ using Content.Shared.Examine; using Content.Shared.Follower; using Content.Shared.Ghost; using Content.Shared.MobState.Components; -using Content.Shared.Movement.EntitySystems; +using Content.Shared.Movement.Events; using JetBrains.Annotations; using Robust.Server.GameObjects; using Robust.Server.Player; diff --git a/Content.Server/Magic/MagicSystem.cs b/Content.Server/Magic/MagicSystem.cs index f7974e9593..f482272829 100644 --- a/Content.Server/Magic/MagicSystem.cs +++ b/Content.Server/Magic/MagicSystem.cs @@ -16,6 +16,7 @@ using Content.Shared.Doors.Systems; using Content.Shared.Interaction.Events; using Content.Shared.Maps; using Content.Shared.Physics; +using Content.Shared.Spawners.Components; using Content.Shared.Storage; using Robust.Shared.Audio; using Robust.Shared.Map; diff --git a/Content.Server/Medical/MedicalScannerSystem.cs b/Content.Server/Medical/MedicalScannerSystem.cs index cd8c42dbda..468630c90c 100644 --- a/Content.Server/Medical/MedicalScannerSystem.cs +++ b/Content.Server/Medical/MedicalScannerSystem.cs @@ -14,6 +14,7 @@ using Content.Shared.DragDrop; using Content.Shared.Interaction; using Content.Shared.MobState.Components; using Content.Shared.Movement; +using Content.Shared.Movement.Events; using Content.Shared.Preferences; using Content.Shared.Verbs; using Robust.Shared.Containers; diff --git a/Content.Server/Movement/Systems/JetpackSystem.cs b/Content.Server/Movement/Systems/JetpackSystem.cs new file mode 100644 index 0000000000..f7aa205113 --- /dev/null +++ b/Content.Server/Movement/Systems/JetpackSystem.cs @@ -0,0 +1,48 @@ +using Content.Server.Atmos.Components; +using Content.Server.Atmos.EntitySystems; +using Content.Server.Movement.Components; +using Content.Shared.Movement.Components; +using Content.Shared.Movement.Systems; +using Robust.Shared.Collections; +using Robust.Shared.GameStates; + +namespace Content.Server.Movement.Systems; + +public sealed class JetpackSystem : SharedJetpackSystem +{ + private const float UpdateCooldown = 0.5f; + + protected override bool CanEnable(JetpackComponent component) + { + return TryComp(component.Owner, out var gasTank) && !(gasTank.Air.Pressure < component.VolumeUsage); + } + + public override void Update(float frameTime) + { + base.Update(frameTime); + + var toDisable = new ValueList(); + + foreach (var (active, comp, gasTank) in EntityQuery()) + { + active.Accumulator += frameTime; + if (active.Accumulator < UpdateCooldown) continue; + + active.Accumulator -= UpdateCooldown; + + if (gasTank.Air.Pressure < comp.VolumeUsage) + { + toDisable.Add(comp); + continue; + } + + gasTank.RemoveAirVolume(comp.VolumeUsage); + gasTank.UpdateUserInterface(); + } + + foreach (var comp in toDisable) + { + SetEnabled(comp, false); + } + } +} diff --git a/Content.Server/Nutrition/Components/HungerComponent.cs b/Content.Server/Nutrition/Components/HungerComponent.cs index daa85433c6..f52c28b203 100644 --- a/Content.Server/Nutrition/Components/HungerComponent.cs +++ b/Content.Server/Nutrition/Components/HungerComponent.cs @@ -4,7 +4,7 @@ using Content.Shared.Damage; using Content.Shared.Database; using Content.Shared.MobState.Components; using Content.Shared.Movement.Components; -using Content.Shared.Movement.EntitySystems; +using Content.Shared.Movement.Systems; using Content.Shared.Nutrition.Components; using Robust.Shared.Random; diff --git a/Content.Server/Nutrition/EntitySystems/ThirstSystem.cs b/Content.Server/Nutrition/EntitySystems/ThirstSystem.cs index cfbcf9d72f..f31ccc4446 100644 --- a/Content.Server/Nutrition/EntitySystems/ThirstSystem.cs +++ b/Content.Server/Nutrition/EntitySystems/ThirstSystem.cs @@ -1,6 +1,5 @@ using Content.Server.Nutrition.Components; using JetBrains.Annotations; -using Content.Shared.Movement.EntitySystems; using Robust.Shared.Random; using Content.Shared.MobState.Components; using Content.Shared.Movement.Components; @@ -8,6 +7,7 @@ using Content.Shared.Alert; using Content.Server.Administration.Logs; using Content.Shared.Database; using Content.Shared.Damage; +using Content.Shared.Movement.Systems; namespace Content.Server.Nutrition.EntitySystems { diff --git a/Content.Server/Physics/Controllers/MoverController.cs b/Content.Server/Physics/Controllers/MoverController.cs index a0d99f2c52..4f230f9a23 100644 --- a/Content.Server/Physics/Controllers/MoverController.cs +++ b/Content.Server/Physics/Controllers/MoverController.cs @@ -4,6 +4,7 @@ using Content.Server.Shuttles.Systems; using Content.Shared.Vehicle.Components; using Content.Shared.Movement; using Content.Shared.Movement.Components; +using Content.Shared.Movement.Systems; using Content.Shared.Shuttles.Components; using Robust.Shared.Map; using Robust.Shared.Player; diff --git a/Content.Server/Resist/EscapeInventorySystem.cs b/Content.Server/Resist/EscapeInventorySystem.cs index aa8dbaab9e..6fc67a3dab 100644 --- a/Content.Server/Resist/EscapeInventorySystem.cs +++ b/Content.Server/Resist/EscapeInventorySystem.cs @@ -2,12 +2,12 @@ using Content.Shared.Movement; using Content.Server.DoAfter; using Robust.Shared.Containers; using Content.Server.Popups; -using Content.Shared.Movement.EntitySystems; using Robust.Shared.Player; using Content.Shared.Storage; using Content.Shared.Inventory; using Content.Shared.Hands.Components; using Content.Shared.ActionBlocker; +using Content.Shared.Movement.Events; namespace Content.Server.Resist; diff --git a/Content.Server/Resist/ResistLockerSystem.cs b/Content.Server/Resist/ResistLockerSystem.cs index 3d65d91c12..8506d3c3a3 100644 --- a/Content.Server/Resist/ResistLockerSystem.cs +++ b/Content.Server/Resist/ResistLockerSystem.cs @@ -5,6 +5,7 @@ using Content.Server.Lock; using Robust.Shared.Player; using Robust.Shared.Containers; using Content.Server.Popups; +using Content.Shared.Movement.Events; namespace Content.Server.Resist; diff --git a/Content.Server/Spawners/EntitySystems/TimedDespawnSystem.cs b/Content.Server/Spawners/EntitySystems/TimedDespawnSystem.cs index 172d57b436..66b3742e04 100644 --- a/Content.Server/Spawners/EntitySystems/TimedDespawnSystem.cs +++ b/Content.Server/Spawners/EntitySystems/TimedDespawnSystem.cs @@ -1,19 +1,11 @@ -using Content.Server.Spawners.Components; +using Content.Shared.Spawners.EntitySystems; namespace Content.Server.Spawners.EntitySystems; -public sealed class TimedDespawnSystem : EntitySystem +public sealed class TimedDespawnSystem : SharedTimedDespawnSystem { - public override void Update(float frameTime) + protected override bool CanDelete(EntityUid uid) { - base.Update(frameTime); - - foreach (var entity in EntityQuery()) - { - entity.Lifetime -= frameTime; - - if (entity.Lifetime <= 0) - EntityManager.QueueDeleteEntity(entity.Owner); - } + return true; } } diff --git a/Content.Server/Storage/EntitySystems/StorageSystem.cs b/Content.Server/Storage/EntitySystems/StorageSystem.cs index 38da912647..95cae59875 100644 --- a/Content.Server/Storage/EntitySystems/StorageSystem.cs +++ b/Content.Server/Storage/EntitySystems/StorageSystem.cs @@ -28,6 +28,7 @@ using Content.Server.Popups; using Content.Shared.Destructible; using static Content.Shared.Storage.SharedStorageComponent; using Content.Shared.ActionBlocker; +using Content.Shared.Movement.Events; namespace Content.Server.Storage.EntitySystems { diff --git a/Content.Shared/ActionBlocker/ActionBlockerSystem.cs b/Content.Shared/ActionBlocker/ActionBlockerSystem.cs index dc4d21dc08..4d3ff2619e 100644 --- a/Content.Shared/ActionBlocker/ActionBlockerSystem.cs +++ b/Content.Shared/ActionBlocker/ActionBlockerSystem.cs @@ -6,6 +6,7 @@ using Content.Shared.Interaction.Events; using Content.Shared.Item; using Content.Shared.Movement; using Content.Shared.Movement.Components; +using Content.Shared.Movement.Events; using Content.Shared.Speech; using Content.Shared.Throwing; using JetBrains.Annotations; diff --git a/Content.Shared/Administration/AdminFrozenSystem.cs b/Content.Shared/Administration/AdminFrozenSystem.cs index cb443aabf0..184b81affa 100644 --- a/Content.Shared/Administration/AdminFrozenSystem.cs +++ b/Content.Shared/Administration/AdminFrozenSystem.cs @@ -2,6 +2,7 @@ using Content.Shared.ActionBlocker; using Content.Shared.Interaction.Events; using Content.Shared.Item; using Content.Shared.Movement; +using Content.Shared.Movement.Events; using Content.Shared.Physics.Pull; using Content.Shared.Pulling; using Content.Shared.Pulling.Components; diff --git a/Content.Shared/Buckle/SharedBuckleSystem.cs b/Content.Shared/Buckle/SharedBuckleSystem.cs index 6a9ad32114..7adaac5b09 100644 --- a/Content.Shared/Buckle/SharedBuckleSystem.cs +++ b/Content.Shared/Buckle/SharedBuckleSystem.cs @@ -1,6 +1,7 @@ using Content.Shared.Buckle.Components; using Content.Shared.Interaction.Events; using Content.Shared.Movement; +using Content.Shared.Movement.Events; using Content.Shared.Standing; using Content.Shared.Throwing; using Robust.Shared.Physics.Dynamics; diff --git a/Content.Shared/Chemistry/MetabolismMovespeedModifierSystem.cs b/Content.Shared/Chemistry/MetabolismMovespeedModifierSystem.cs index 462a6c0d16..00746ef99d 100644 --- a/Content.Shared/Chemistry/MetabolismMovespeedModifierSystem.cs +++ b/Content.Shared/Chemistry/MetabolismMovespeedModifierSystem.cs @@ -2,7 +2,7 @@ using Content.Shared.Chemistry.Components; using Robust.Shared.GameStates; using Robust.Shared.Timing; using Content.Shared.Movement.Components; -using Content.Shared.Movement.EntitySystems; +using Content.Shared.Movement.Systems; using static Content.Shared.Chemistry.Components.MovespeedModifierMetabolismComponent; namespace Content.Shared.Chemistry diff --git a/Content.Shared/Climbing/SharedClimbSystem.cs b/Content.Shared/Climbing/SharedClimbSystem.cs index a230642cbe..53e20541f9 100644 --- a/Content.Shared/Climbing/SharedClimbSystem.cs +++ b/Content.Shared/Climbing/SharedClimbSystem.cs @@ -1,5 +1,6 @@ using Content.Shared.DragDrop; using Content.Shared.Movement; +using Content.Shared.Movement.Events; namespace Content.Shared.Climbing; diff --git a/Content.Shared/Clothing/ClothingSpeedModifierSystem.cs b/Content.Shared/Clothing/ClothingSpeedModifierSystem.cs index ee759cc96d..1da05a3970 100644 --- a/Content.Shared/Clothing/ClothingSpeedModifierSystem.cs +++ b/Content.Shared/Clothing/ClothingSpeedModifierSystem.cs @@ -1,4 +1,4 @@ -using Content.Shared.Movement.EntitySystems; +using Content.Shared.Movement.Systems; using Robust.Shared.Containers; using Robust.Shared.GameStates; diff --git a/Content.Shared/Cuffs/SharedCuffableSystem.cs b/Content.Shared/Cuffs/SharedCuffableSystem.cs index 895ba9b831..da28608950 100644 --- a/Content.Shared/Cuffs/SharedCuffableSystem.cs +++ b/Content.Shared/Cuffs/SharedCuffableSystem.cs @@ -5,6 +5,7 @@ using Content.Shared.Interaction.Events; using Content.Shared.Inventory.Events; using Content.Shared.Item; using Content.Shared.Movement; +using Content.Shared.Movement.Events; using Content.Shared.Physics.Pull; using Content.Shared.Pulling.Components; using Content.Shared.Pulling.Events; diff --git a/Content.Shared/Damage/Systems/SlowOnDamageSystem.cs b/Content.Shared/Damage/Systems/SlowOnDamageSystem.cs index 0d6222b194..833883c144 100644 --- a/Content.Shared/Damage/Systems/SlowOnDamageSystem.cs +++ b/Content.Shared/Damage/Systems/SlowOnDamageSystem.cs @@ -1,6 +1,6 @@ using Content.Shared.Damage.Components; using Content.Shared.FixedPoint; -using Content.Shared.Movement.EntitySystems; +using Content.Shared.Movement.Systems; namespace Content.Shared.Damage { diff --git a/Content.Shared/Follower/FollowerSystem.cs b/Content.Shared/Follower/FollowerSystem.cs index 42537d6e47..32ca86ce7c 100644 --- a/Content.Shared/Follower/FollowerSystem.cs +++ b/Content.Shared/Follower/FollowerSystem.cs @@ -1,7 +1,7 @@ using Content.Shared.Database; using Content.Shared.Follower.Components; using Content.Shared.Ghost; -using Content.Shared.Movement.EntitySystems; +using Content.Shared.Movement.Events; using Content.Shared.Verbs; namespace Content.Shared.Follower; diff --git a/Content.Shared/Friction/SharedTileFrictionController.cs b/Content.Shared/Friction/SharedTileFrictionController.cs index 122df273a9..1576265260 100644 --- a/Content.Shared/Friction/SharedTileFrictionController.cs +++ b/Content.Shared/Friction/SharedTileFrictionController.cs @@ -1,6 +1,7 @@ using Content.Shared.CCVar; using Content.Shared.Movement; using Content.Shared.Movement.Components; +using Content.Shared.Movement.Systems; using JetBrains.Annotations; using Robust.Shared.Configuration; using Robust.Shared.GameStates; diff --git a/Content.Shared/Inventory/InventorySystem.Equip.cs b/Content.Shared/Inventory/InventorySystem.Equip.cs index c3169fc5aa..88498a3ffe 100644 --- a/Content.Shared/Inventory/InventorySystem.Equip.cs +++ b/Content.Shared/Inventory/InventorySystem.Equip.cs @@ -8,7 +8,7 @@ using Content.Shared.Interaction; using Content.Shared.Interaction.Events; using Content.Shared.Inventory.Events; using Content.Shared.Item; -using Content.Shared.Movement.EntitySystems; +using Content.Shared.Movement.Systems; using Content.Shared.Popups; using Content.Shared.Strip.Components; using Robust.Shared.Audio; diff --git a/Content.Shared/Inventory/InventorySystem.Relay.cs b/Content.Shared/Inventory/InventorySystem.Relay.cs index 6cbe1a7e6f..35d25c0610 100644 --- a/Content.Shared/Inventory/InventorySystem.Relay.cs +++ b/Content.Shared/Inventory/InventorySystem.Relay.cs @@ -1,7 +1,7 @@ using Content.Shared.Damage; using Content.Shared.Electrocution; using Content.Shared.Explosion; -using Content.Shared.Movement.EntitySystems; +using Content.Shared.Movement.Systems; using Content.Shared.Slippery; namespace Content.Shared.Inventory; diff --git a/Content.Shared/MobState/EntitySystems/MobStateSystem.cs b/Content.Shared/MobState/EntitySystems/MobStateSystem.cs index 3884e2b8cf..0fdfbf905d 100644 --- a/Content.Shared/MobState/EntitySystems/MobStateSystem.cs +++ b/Content.Shared/MobState/EntitySystems/MobStateSystem.cs @@ -8,6 +8,7 @@ using Content.Shared.Item; using Content.Shared.MobState.Components; using Content.Shared.MobState.State; using Content.Shared.Movement; +using Content.Shared.Movement.Events; using Content.Shared.Pulling.Events; using Content.Shared.Speech; using Content.Shared.Standing; diff --git a/Content.Shared/Movement/Components/ActiveJetpackComponent.cs b/Content.Shared/Movement/Components/ActiveJetpackComponent.cs new file mode 100644 index 0000000000..b3318e23a0 --- /dev/null +++ b/Content.Shared/Movement/Components/ActiveJetpackComponent.cs @@ -0,0 +1,13 @@ +using Robust.Shared.GameStates; + +namespace Content.Shared.Movement.Components; + +/// +/// Added to an enabled jetpack. Tracks gas usage on server / effect spawning on client. +/// +[RegisterComponent, NetworkedComponent] +public sealed class ActiveJetpackComponent : Component +{ + public float EffectCooldown = 0.3f; + public float Accumulator = 0f; +} diff --git a/Content.Shared/Movement/Components/JetpackComponent.cs b/Content.Shared/Movement/Components/JetpackComponent.cs new file mode 100644 index 0000000000..7ea8dc16cf --- /dev/null +++ b/Content.Shared/Movement/Components/JetpackComponent.cs @@ -0,0 +1,24 @@ +using Content.Shared.Actions.ActionTypes; +using Content.Shared.Atmos; +using Robust.Shared.GameStates; + +namespace Content.Shared.Movement.Components; + +[RegisterComponent, NetworkedComponent] +public sealed class JetpackComponent : Component +{ + [ViewVariables(VVAccess.ReadWrite), DataField("volumeUsage")] + public float VolumeUsage = Atmospherics.BreathVolume; + + [ViewVariables, DataField("toggleAction", required: true)] + public InstantAction ToggleAction = new(); + + [ViewVariables(VVAccess.ReadWrite), DataField("acceleration")] + public float Acceleration = 1f; + + [ViewVariables(VVAccess.ReadWrite), DataField("friction")] + public float Friction = 0.3f; + + [ViewVariables(VVAccess.ReadWrite), DataField("weightlessModifier")] + public float WeightlessModifier = 1.2f; +} diff --git a/Content.Shared/Movement/Components/JetpackUserComponent.cs b/Content.Shared/Movement/Components/JetpackUserComponent.cs new file mode 100644 index 0000000000..05d99cf660 --- /dev/null +++ b/Content.Shared/Movement/Components/JetpackUserComponent.cs @@ -0,0 +1,14 @@ +using Robust.Shared.GameStates; + +namespace Content.Shared.Movement.Components; + +/// +/// Added to someone using a jetpack for movement purposes +/// +[RegisterComponent, NetworkedComponent] +public sealed class JetpackUserComponent : Component +{ + public float Acceleration = 1f; + public float Friction = 0.3f; + public float WeightlessModifier = 1.2f; +} diff --git a/Content.Shared/Movement/Components/MovementSpeedModifierComponent.cs b/Content.Shared/Movement/Components/MovementSpeedModifierComponent.cs index 0a43d1045a..7a6990e598 100644 --- a/Content.Shared/Movement/Components/MovementSpeedModifierComponent.cs +++ b/Content.Shared/Movement/Components/MovementSpeedModifierComponent.cs @@ -1,4 +1,4 @@ -using Content.Shared.Movement.EntitySystems; +using Content.Shared.Movement.Systems; using Robust.Shared.GameStates; namespace Content.Shared.Movement.Components diff --git a/Content.Shared/Movement/EntitySystems/SharedMobMoverSystem.cs b/Content.Shared/Movement/EntitySystems/SharedMobMoverSystem.cs deleted file mode 100644 index c0cccf795c..0000000000 --- a/Content.Shared/Movement/EntitySystems/SharedMobMoverSystem.cs +++ /dev/null @@ -1,48 +0,0 @@ -using Content.Shared.CCVar; -using Content.Shared.Movement.Components; -using Robust.Shared.Configuration; -using Robust.Shared.Physics; -using Robust.Shared.Physics.Dynamics; - -namespace Content.Shared.Movement.EntitySystems -{ - public sealed class SharedMobMoverSystem : EntitySystem - { - private bool _pushingEnabled; - - public override void Initialize() - { - base.Initialize(); - Get().KinematicControllerCollision += OnMobCollision; - IoCManager.Resolve().OnValueChanged(CCVars.MobPushing, SetPushing, true); - } - - private void SetPushing(bool value) - { - _pushingEnabled = value; - } - - public override void Shutdown() - { - base.Shutdown(); - IoCManager.Resolve().UnsubValueChanged(CCVars.MobPushing, SetPushing); - Get().KinematicControllerCollision -= OnMobCollision; - } - - /// - /// Fake pushing for player collisions. - /// - private void OnMobCollision(Fixture ourFixture, Fixture otherFixture, float frameTime, Vector2 worldNormal) - { - if (!_pushingEnabled) return; - - var otherBody = otherFixture.Body; - - if (otherBody.BodyType != BodyType.Dynamic || !otherFixture.Hard) return; - - if (!EntityManager.TryGetComponent(ourFixture.Body.Owner, out IMobMoverComponent? mobMover) || worldNormal == Vector2.Zero) return; - - otherBody.ApplyLinearImpulse(-worldNormal * mobMover.PushStrength * frameTime); - } - } -} diff --git a/Content.Shared/Movement/Events/RelayMoveInputEvent.cs b/Content.Shared/Movement/Events/RelayMoveInputEvent.cs new file mode 100644 index 0000000000..7f4f08fe31 --- /dev/null +++ b/Content.Shared/Movement/Events/RelayMoveInputEvent.cs @@ -0,0 +1,13 @@ +using Robust.Shared.Players; + +namespace Content.Shared.Movement.Events; + +public sealed class RelayMoveInputEvent : EntityEventArgs +{ + public ICommonSession Session { get; } + + public RelayMoveInputEvent(ICommonSession session) + { + Session = session; + } +} \ No newline at end of file diff --git a/Content.Shared/Movement/RelayMovementEntityEvent.cs b/Content.Shared/Movement/Events/RelayMovementEntityEvent.cs similarity index 84% rename from Content.Shared/Movement/RelayMovementEntityEvent.cs rename to Content.Shared/Movement/Events/RelayMovementEntityEvent.cs index 226aee739e..2208cdda97 100644 --- a/Content.Shared/Movement/RelayMovementEntityEvent.cs +++ b/Content.Shared/Movement/Events/RelayMovementEntityEvent.cs @@ -1,4 +1,4 @@ -namespace Content.Shared.Movement +namespace Content.Shared.Movement.Events { public sealed class RelayMovementEntityEvent : EntityEventArgs { diff --git a/Content.Shared/Movement/Events/ToggleJetpackEvent.cs b/Content.Shared/Movement/Events/ToggleJetpackEvent.cs new file mode 100644 index 0000000000..d344c7a9c3 --- /dev/null +++ b/Content.Shared/Movement/Events/ToggleJetpackEvent.cs @@ -0,0 +1,8 @@ +using Content.Shared.Actions; + +namespace Content.Shared.Movement.Events; + +/// +/// Raised on a jetpack whenever it is toggled. +/// +public sealed class ToggleJetpackEvent : InstantActionEvent {} diff --git a/Content.Shared/Movement/UpdateCanMoveEvent.cs b/Content.Shared/Movement/Events/UpdateCanMoveEvent.cs similarity index 90% rename from Content.Shared/Movement/UpdateCanMoveEvent.cs rename to Content.Shared/Movement/Events/UpdateCanMoveEvent.cs index a7509f1d78..d9772c1cf4 100644 --- a/Content.Shared/Movement/UpdateCanMoveEvent.cs +++ b/Content.Shared/Movement/Events/UpdateCanMoveEvent.cs @@ -1,6 +1,6 @@ using Content.Shared.Movement.Components; -namespace Content.Shared.Movement; +namespace Content.Shared.Movement.Events; /// /// Raised whenever needs to be updated. Cancel this event to prevent a diff --git a/Content.Shared/Movement/Events/WeightlessMoveEvent.cs b/Content.Shared/Movement/Events/WeightlessMoveEvent.cs new file mode 100644 index 0000000000..73eac0d306 --- /dev/null +++ b/Content.Shared/Movement/Events/WeightlessMoveEvent.cs @@ -0,0 +1,14 @@ +namespace Content.Shared.Movement.Events; + +/// +/// Raised on an entity to check if it can move while weightless. +/// +[ByRefEvent] +public struct CanWeightlessMoveEvent +{ + public bool CanMove = false; + + public CanWeightlessMoveEvent() + { + } +} diff --git a/Content.Shared/Movement/MobMovementProfileEvent.cs b/Content.Shared/Movement/MobMovementProfileEvent.cs new file mode 100644 index 0000000000..ffc928327e --- /dev/null +++ b/Content.Shared/Movement/MobMovementProfileEvent.cs @@ -0,0 +1,35 @@ +namespace Content.Shared.Movement; + +/// +/// Contains all of the relevant data for mob movement. +/// Raised on a mob if something wants to overwrite its movement characteristics. +/// +[ByRefEvent] +public struct MobMovementProfileEvent +{ + /// + /// Should we use this profile instead of the entity's default? + /// + public bool Override = false; + + public readonly bool Touching; + public readonly bool Weightless; + + public float Friction; + public float WeightlessModifier; + public float Acceleration; + + public MobMovementProfileEvent( + bool touching, + bool weightless, + float friction, + float weightlessModifier, + float acceleration) + { + Touching = touching; + Weightless = weightless; + Friction = friction; + WeightlessModifier = weightlessModifier; + Acceleration = acceleration; + } +} diff --git a/Content.Shared/Movement/EntitySystems/MovementIgnoreGravitySystem.cs b/Content.Shared/Movement/Systems/MovementIgnoreGravitySystem.cs similarity index 86% rename from Content.Shared/Movement/EntitySystems/MovementIgnoreGravitySystem.cs rename to Content.Shared/Movement/Systems/MovementIgnoreGravitySystem.cs index 4ecae7ca24..4ea0e08b97 100644 --- a/Content.Shared/Movement/EntitySystems/MovementIgnoreGravitySystem.cs +++ b/Content.Shared/Movement/Systems/MovementIgnoreGravitySystem.cs @@ -1,8 +1,7 @@ -using Content.Shared.Alert; -using Content.Shared.Movement.Components; +using Content.Shared.Movement.Components; using Robust.Shared.GameStates; -namespace Content.Shared.Movement.EntitySystems; +namespace Content.Shared.Movement.Systems; public sealed class MovementIgnoreGravitySystem : EntitySystem { diff --git a/Content.Shared/Movement/EntitySystems/MovementSpeedModifierSystem.cs b/Content.Shared/Movement/Systems/MovementSpeedModifierSystem.cs similarity index 80% rename from Content.Shared/Movement/EntitySystems/MovementSpeedModifierSystem.cs rename to Content.Shared/Movement/Systems/MovementSpeedModifierSystem.cs index 61413582eb..e6c14faf35 100644 --- a/Content.Shared/Movement/EntitySystems/MovementSpeedModifierSystem.cs +++ b/Content.Shared/Movement/Systems/MovementSpeedModifierSystem.cs @@ -3,26 +3,13 @@ using Content.Shared.Movement.Components; using Robust.Shared.GameStates; using Robust.Shared.Serialization; -namespace Content.Shared.Movement.EntitySystems +namespace Content.Shared.Movement.Systems { public sealed class MovementSpeedModifierSystem : EntitySystem { - private readonly HashSet _needsRefresh = new(); - - public override void Update(float frameTime) - { - foreach (var uid in _needsRefresh) - { - RecalculateMovementSpeedModifiers(uid); - } - - _needsRefresh.Clear(); - } - public override void Initialize() { base.Initialize(); - UpdatesOutsidePrediction = true; SubscribeLocalEvent(OnGetState); SubscribeLocalEvent(OnHandleState); } @@ -47,23 +34,18 @@ namespace Content.Shared.Movement.EntitySystems component.SprintSpeedModifier = state.SprintSpeedModifier; } - public void RefreshMovementSpeedModifiers(EntityUid uid) - { - _needsRefresh.Add(uid); - } - - private void RecalculateMovementSpeedModifiers(EntityUid uid, MovementSpeedModifierComponent? move = null) + public void RefreshMovementSpeedModifiers(EntityUid uid, MovementSpeedModifierComponent? move = null) { if (!Resolve(uid, ref move, false)) return; var ev = new RefreshMovementSpeedModifiersEvent(); - RaiseLocalEvent(uid, ev, false); + RaiseLocalEvent(uid, ev); move.WalkSpeedModifier = ev.WalkSpeedModifier; move.SprintSpeedModifier = ev.SprintSpeedModifier; - move.Dirty(); + Dirty(move); } [Serializable, NetSerializable] diff --git a/Content.Shared/Movement/Systems/SharedJetpackSystem.cs b/Content.Shared/Movement/Systems/SharedJetpackSystem.cs new file mode 100644 index 0000000000..3a871c88c0 --- /dev/null +++ b/Content.Shared/Movement/Systems/SharedJetpackSystem.cs @@ -0,0 +1,124 @@ +using Content.Shared.Actions; +using Content.Shared.Interaction.Events; +using Content.Shared.Inventory; +using Content.Shared.Movement.Components; +using Content.Shared.Movement.Events; +using Robust.Shared.Containers; +using Robust.Shared.Serialization; + +namespace Content.Shared.Movement.Systems; + +public abstract class SharedJetpackSystem : EntitySystem +{ + [Dependency] protected readonly SharedContainerSystem Container = default!; + + public override void Initialize() + { + base.Initialize(); + SubscribeLocalEvent(OnJetpackGetAction); + SubscribeLocalEvent(OnJetpackDropped); + SubscribeLocalEvent(OnJetpackToggle); + SubscribeLocalEvent(OnJetpackUserCanWeightless); + SubscribeLocalEvent(OnJetpackUserMovement); + } + + private void OnJetpackDropped(EntityUid uid, JetpackComponent component, DroppedEvent args) + { + SetEnabled(component, false, args.User); + } + + private void OnJetpackUserMovement(EntityUid uid, JetpackUserComponent component, ref MobMovementProfileEvent args) + { + // Only overwrite jetpack movement if they're offgrid. + if (args.Override || !args.Weightless) return; + + args.Override = true; + args.Acceleration = component.Acceleration; + args.WeightlessModifier = component.WeightlessModifier; + args.Friction = component.Friction; + } + + private void OnJetpackUserCanWeightless(EntityUid uid, JetpackUserComponent component, ref CanWeightlessMoveEvent args) + { + args.CanMove = true; + } + + private void SetupUser(EntityUid uid, JetpackComponent component) + { + var user = EnsureComp(uid); + user.Acceleration = component.Acceleration; + user.Friction = component.Friction; + user.WeightlessModifier = component.WeightlessModifier; + } + + private void OnJetpackToggle(EntityUid uid, JetpackComponent component, ToggleJetpackEvent args) + { + if (args.Handled) return; + + SetEnabled(component, !IsEnabled(uid)); + } + + private void OnJetpackGetAction(EntityUid uid, JetpackComponent component, GetItemActionsEvent args) + { + args.Actions.Add(component.ToggleAction); + } + + private bool IsEnabled(EntityUid uid) + { + return HasComp(uid); + } + + public void SetEnabled(JetpackComponent component, bool enabled, EntityUid? user = null) + { + if (IsEnabled(component.Owner) == enabled || + enabled && !CanEnable(component)) return; + + if (enabled) + { + EnsureComp(component.Owner); + } + else + { + RemComp(component.Owner); + } + + if (user == null) + { + Container.TryGetContainingContainer(component.Owner, out var container); + user = container?.Owner; + } + + // Can't activate if no one's using. + if (user == null && enabled) return; + + if (user != null) + { + if (enabled) + { + SetupUser(user.Value, component); + } + else + { + RemComp(user.Value); + } + } + + TryComp(component.Owner, out var appearance); + appearance?.SetData(JetpackVisuals.Enabled, enabled); + Dirty(component); + } + + protected abstract bool CanEnable(JetpackComponent component); + + [Serializable, NetSerializable] + protected sealed class JetpackComponentState : ComponentState + { + public bool Enabled; + } +} + +[Serializable, NetSerializable] +public enum JetpackVisuals : byte +{ + Enabled, +} diff --git a/Content.Shared/Movement/EntitySystems/SharedMoverSystem.cs b/Content.Shared/Movement/Systems/SharedMoverController.Input.cs similarity index 59% rename from Content.Shared/Movement/EntitySystems/SharedMoverSystem.cs rename to Content.Shared/Movement/Systems/SharedMoverController.Input.cs index 88926bab17..b84a295682 100644 --- a/Content.Shared/Movement/EntitySystems/SharedMoverSystem.cs +++ b/Content.Shared/Movement/Systems/SharedMoverController.Input.cs @@ -1,47 +1,43 @@ -using System.Diagnostics.CodeAnalysis; using Content.Shared.MobState.Components; using Content.Shared.Movement.Components; +using Content.Shared.Movement.Events; using Content.Shared.Vehicle.Components; using Robust.Shared.Containers; using Robust.Shared.Input; using Robust.Shared.Input.Binding; using Robust.Shared.Players; -namespace Content.Shared.Movement.EntitySystems +namespace Content.Shared.Movement.Systems { /// /// Handles converting inputs into movement. /// - public sealed class SharedMoverSystem : EntitySystem + public abstract partial class SharedMoverController { - public override void Initialize() + private void InitializeInput() { - base.Initialize(); - - var moveUpCmdHandler = new MoverDirInputCmdHandler(Direction.North); - var moveLeftCmdHandler = new MoverDirInputCmdHandler(Direction.West); - var moveRightCmdHandler = new MoverDirInputCmdHandler(Direction.East); - var moveDownCmdHandler = new MoverDirInputCmdHandler(Direction.South); + var moveUpCmdHandler = new MoverDirInputCmdHandler(this, Direction.North); + var moveLeftCmdHandler = new MoverDirInputCmdHandler(this, Direction.West); + var moveRightCmdHandler = new MoverDirInputCmdHandler(this, Direction.East); + var moveDownCmdHandler = new MoverDirInputCmdHandler(this, Direction.South); CommandBinds.Builder .Bind(EngineKeyFunctions.MoveUp, moveUpCmdHandler) .Bind(EngineKeyFunctions.MoveLeft, moveLeftCmdHandler) .Bind(EngineKeyFunctions.MoveRight, moveRightCmdHandler) .Bind(EngineKeyFunctions.MoveDown, moveDownCmdHandler) - .Bind(EngineKeyFunctions.Walk, new WalkInputCmdHandler()) - .Register(); + .Bind(EngineKeyFunctions.Walk, new WalkInputCmdHandler(this)) + .Register(); } - /// - public override void Shutdown() + private void ShutdownInput() { - CommandBinds.Unregister(); - base.Shutdown(); + CommandBinds.Unregister(); } private void HandleDirChange(ICommonSession? session, Direction dir, ushort subTick, bool state) { - if (!TryGetAttachedComponent(session, out var moverComp)) + if (!TryComp(session?.AttachedEntity, out var moverComp)) return; var owner = session?.AttachedEntity; @@ -71,9 +67,9 @@ namespace Content.Shared.Movement.EntitySystems moverComp.SetVelocityDirection(dir, subTick, state); } - private static void HandleRunChange(ICommonSession? session, ushort subTick, bool walking) + private void HandleRunChange(ICommonSession? session, ushort subTick, bool walking) { - if (!TryGetAttachedComponent(session, out var moverComp)) + if (!TryComp(session?.AttachedEntity, out var moverComp)) { return; } @@ -81,68 +77,42 @@ namespace Content.Shared.Movement.EntitySystems moverComp.SetSprinting(subTick, walking); } - private static bool TryGetAttachedComponent(ICommonSession? session, [NotNullWhen(true)] out T? component) - where T : class, IComponent - { - component = default; - - var ent = session?.AttachedEntity; - - var entMan = IoCManager.Resolve(); - - if (ent == null || !entMan.EntityExists(ent.Value)) - return false; - - if (!entMan.TryGetComponent(ent.Value, out T? comp)) - return false; - - component = comp; - return true; - } - private sealed class MoverDirInputCmdHandler : InputCmdHandler { + private SharedMoverController _controller; private readonly Direction _dir; - public MoverDirInputCmdHandler(Direction dir) + public MoverDirInputCmdHandler(SharedMoverController controller, Direction dir) { + _controller = controller; _dir = dir; } public override bool HandleCmdMessage(ICommonSession? session, InputCmdMessage message) { - if (message is not FullInputCmdMessage full) - { - return false; - } + if (message is not FullInputCmdMessage full) return false; - Get().HandleDirChange(session, _dir, message.SubTick, full.State == BoundKeyState.Down); + _controller.HandleDirChange(session, _dir, message.SubTick, full.State == BoundKeyState.Down); return false; } } private sealed class WalkInputCmdHandler : InputCmdHandler { + private SharedMoverController _controller; + + public WalkInputCmdHandler(SharedMoverController controller) + { + _controller = controller; + } + public override bool HandleCmdMessage(ICommonSession? session, InputCmdMessage message) { - if (message is not FullInputCmdMessage full) - { - return false; - } + if (message is not FullInputCmdMessage full) return false; - HandleRunChange(session, full.SubTick, full.State == BoundKeyState.Down); + _controller.HandleRunChange(session, full.SubTick, full.State == BoundKeyState.Down); return false; } } } - - public sealed class RelayMoveInputEvent : EntityEventArgs - { - public ICommonSession Session { get; } - - public RelayMoveInputEvent(ICommonSession session) - { - Session = session; - } - } } diff --git a/Content.Shared/Movement/Systems/SharedMoverController.Pushing.cs b/Content.Shared/Movement/Systems/SharedMoverController.Pushing.cs new file mode 100644 index 0000000000..02e45725a4 --- /dev/null +++ b/Content.Shared/Movement/Systems/SharedMoverController.Pushing.cs @@ -0,0 +1,56 @@ +using Content.Shared.CCVar; +using Content.Shared.Movement.Components; +using Robust.Shared.Physics; +using Robust.Shared.Physics.Dynamics; + +namespace Content.Shared.Movement.Systems; + +public abstract partial class SharedMoverController +{ + private bool _pushingEnabled; + + private void InitializePushing() + { + _configManager.OnValueChanged(CCVars.MobPushing, SetPushing, true); + } + + private void SetPushing(bool value) + { + if (_pushingEnabled == value) return; + + _pushingEnabled = value; + + if (_pushingEnabled) + { + _physics.KinematicControllerCollision += OnMobCollision; + } + else + { + _physics.KinematicControllerCollision -= OnMobCollision; + } + } + + private void ShutdownPushing() + { + if (_pushingEnabled) + _physics.KinematicControllerCollision -= OnMobCollision; + + _configManager.UnsubValueChanged(CCVars.MobPushing, SetPushing); + } + + /// + /// Fake pushing for player collisions. + /// + private void OnMobCollision(Fixture ourFixture, Fixture otherFixture, float frameTime, Vector2 worldNormal) + { + if (!_pushingEnabled) return; + + var otherBody = otherFixture.Body; + + if (otherBody.BodyType != BodyType.Dynamic || !otherFixture.Hard) return; + + if (!EntityManager.TryGetComponent(ourFixture.Body.Owner, out IMobMoverComponent? mobMover) || worldNormal == Vector2.Zero) return; + + otherBody.ApplyLinearImpulse(-worldNormal * mobMover.PushStrength * frameTime); + } +} diff --git a/Content.Shared/Movement/SharedMoverController.cs b/Content.Shared/Movement/Systems/SharedMoverController.cs similarity index 82% rename from Content.Shared/Movement/SharedMoverController.cs rename to Content.Shared/Movement/Systems/SharedMoverController.cs index 8139d34ff6..ae94221d93 100644 --- a/Content.Shared/Movement/SharedMoverController.cs +++ b/Content.Shared/Movement/Systems/SharedMoverController.cs @@ -6,6 +6,7 @@ using Content.Shared.Inventory; using Content.Shared.Maps; using Content.Shared.MobState.Components; using Content.Shared.Movement.Components; +using Content.Shared.Movement.Events; using Content.Shared.Pulling.Components; using Content.Shared.Tag; using Robust.Shared.Audio; @@ -16,14 +17,15 @@ using Robust.Shared.Physics.Controllers; using Robust.Shared.Player; using Robust.Shared.Utility; -namespace Content.Shared.Movement +namespace Content.Shared.Movement.Systems { /// /// Handles player and NPC mob movement. /// NPCs are handled server-side only. /// - public abstract class SharedMoverController : VirtualController + public abstract partial class SharedMoverController : VirtualController { + [Dependency] private readonly IConfigurationManager _configManager = default!; [Dependency] private readonly IMapManager _mapManager = default!; [Dependency] private readonly ITileDefinitionManager _tileDefinitionManager = default!; [Dependency] private readonly InventorySystem _inventory = default!; @@ -86,17 +88,18 @@ namespace Content.Shared.Movement public override void Initialize() { base.Initialize(); - var configManager = IoCManager.Resolve(); + InitializeInput(); + InitializePushing(); // Hello - configManager.OnValueChanged(CCVars.RelativeMovement, SetRelativeMovement, true); - configManager.OnValueChanged(CCVars.MinimumFrictionSpeed, SetMinimumFrictionSpeed, true); - configManager.OnValueChanged(CCVars.MobFriction, SetFrictionVelocity, true); - configManager.OnValueChanged(CCVars.MobWeightlessFriction, SetWeightlessFrictionVelocity, true); - configManager.OnValueChanged(CCVars.StopSpeed, SetStopSpeed, true); - configManager.OnValueChanged(CCVars.MobAcceleration, SetMobAcceleration, true); - configManager.OnValueChanged(CCVars.MobWeightlessAcceleration, SetMobWeightlessAcceleration, true); - configManager.OnValueChanged(CCVars.MobWeightlessFrictionNoInput, SetWeightlessFrictionNoInput, true); - configManager.OnValueChanged(CCVars.MobWeightlessModifier, SetMobWeightlessModifier, true); + _configManager.OnValueChanged(CCVars.RelativeMovement, SetRelativeMovement, true); + _configManager.OnValueChanged(CCVars.MinimumFrictionSpeed, SetMinimumFrictionSpeed, true); + _configManager.OnValueChanged(CCVars.MobFriction, SetFrictionVelocity, true); + _configManager.OnValueChanged(CCVars.MobWeightlessFriction, SetWeightlessFrictionVelocity, true); + _configManager.OnValueChanged(CCVars.StopSpeed, SetStopSpeed, true); + _configManager.OnValueChanged(CCVars.MobAcceleration, SetMobAcceleration, true); + _configManager.OnValueChanged(CCVars.MobWeightlessAcceleration, SetMobWeightlessAcceleration, true); + _configManager.OnValueChanged(CCVars.MobWeightlessFrictionNoInput, SetWeightlessFrictionNoInput, true); + _configManager.OnValueChanged(CCVars.MobWeightlessModifier, SetMobWeightlessModifier, true); UpdatesBefore.Add(typeof(SharedTileFrictionController)); } @@ -113,16 +116,17 @@ namespace Content.Shared.Movement public override void Shutdown() { base.Shutdown(); - var configManager = IoCManager.Resolve(); - configManager.UnsubValueChanged(CCVars.RelativeMovement, SetRelativeMovement); - configManager.UnsubValueChanged(CCVars.MinimumFrictionSpeed, SetMinimumFrictionSpeed); - configManager.UnsubValueChanged(CCVars.StopSpeed, SetStopSpeed); - configManager.UnsubValueChanged(CCVars.MobFriction, SetFrictionVelocity); - configManager.UnsubValueChanged(CCVars.MobWeightlessFriction, SetWeightlessFrictionVelocity); - configManager.UnsubValueChanged(CCVars.MobAcceleration, SetMobAcceleration); - configManager.UnsubValueChanged(CCVars.MobWeightlessAcceleration, SetMobWeightlessAcceleration); - configManager.UnsubValueChanged(CCVars.MobWeightlessFrictionNoInput, SetWeightlessFrictionNoInput); - configManager.UnsubValueChanged(CCVars.MobWeightlessModifier, SetMobWeightlessModifier); + ShutdownInput(); + ShutdownPushing(); + _configManager.UnsubValueChanged(CCVars.RelativeMovement, SetRelativeMovement); + _configManager.UnsubValueChanged(CCVars.MinimumFrictionSpeed, SetMinimumFrictionSpeed); + _configManager.UnsubValueChanged(CCVars.StopSpeed, SetStopSpeed); + _configManager.UnsubValueChanged(CCVars.MobFriction, SetFrictionVelocity); + _configManager.UnsubValueChanged(CCVars.MobWeightlessFriction, SetWeightlessFrictionVelocity); + _configManager.UnsubValueChanged(CCVars.MobAcceleration, SetMobAcceleration); + _configManager.UnsubValueChanged(CCVars.MobWeightlessAcceleration, SetMobWeightlessAcceleration); + _configManager.UnsubValueChanged(CCVars.MobWeightlessFrictionNoInput, SetWeightlessFrictionNoInput); + _configManager.UnsubValueChanged(CCVars.MobWeightlessModifier, SetMobWeightlessModifier); } public override void UpdateAfterSolve(bool prediction, float frameTime) @@ -187,13 +191,21 @@ namespace Content.Shared.Movement UsedMobMovement[mover.Owner] = true; var weightless = mover.Owner.IsWeightless(physicsComponent, mapManager: _mapManager, entityManager: EntityManager); var (walkDir, sprintDir) = mover.VelocityDir; - bool touching = true; + var touching = false; // Handle wall-pushes. if (weightless) { - // No gravity: is our entity touching anything? - touching = xform.GridUid != null || IsAroundCollider(_physics, xform, mobMover, physicsComponent); + if (xform.GridUid != null) + touching = true; + + if (!touching) + { + var ev = new CanWeightlessMoveEvent(); + RaiseLocalEvent(xform.Owner, ref ev); + // No gravity: is our entity touching anything? + touching = ev.CanMove || IsAroundCollider(_physics, xform, mobMover, physicsComponent); + } if (!touching) { @@ -233,6 +245,22 @@ namespace Content.Shared.Movement accel = _mobAcceleration; } + var profile = new MobMovementProfileEvent( + touching, + weightless, + friction, + weightlessModifier, + accel); + + RaiseLocalEvent(xform.Owner, ref profile); + + if (profile.Override) + { + friction = profile.Friction; + weightlessModifier = profile.WeightlessModifier; + accel = profile.Acceleration; + } + Friction(frameTime, friction, ref velocity); if (xform.GridUid != EntityUid.Invalid) @@ -242,7 +270,7 @@ namespace Content.Shared.Movement { // This should have its event run during island solver soooo xform.DeferUpdates = true; - xform.LocalRotation = xform.GridUid != EntityUid.Invalid + xform.LocalRotation = xform.GridUid != null ? total.ToWorldAngle() : worldTotal.ToWorldAngle(); xform.DeferUpdates = false; @@ -257,7 +285,7 @@ namespace Content.Shared.Movement worldTotal *= weightlessModifier; - if (touching) + if (!weightless || touching) Accelerate(ref velocity, in worldTotal, accel, frameTime); _physics.SetLinearVelocity(physicsComponent, velocity); diff --git a/Content.Shared/Movement/EntitySystems/SlowContactsSystem.cs b/Content.Shared/Movement/Systems/SlowContactsSystem.cs similarity index 91% rename from Content.Shared/Movement/EntitySystems/SlowContactsSystem.cs rename to Content.Shared/Movement/Systems/SlowContactsSystem.cs index 12b171ae9d..fb7010a2d0 100644 --- a/Content.Shared/Movement/EntitySystems/SlowContactsSystem.cs +++ b/Content.Shared/Movement/Systems/SlowContactsSystem.cs @@ -1,7 +1,7 @@ using Content.Shared.Movement.Components; using Robust.Shared.Physics.Dynamics; -namespace Content.Shared.Movement.EntitySystems; +namespace Content.Shared.Movement.Systems; public sealed class SlowContactsSystem : EntitySystem { @@ -52,7 +52,7 @@ public sealed class SlowContactsSystem : EntitySystem Logger.ErrorS("slowscontacts", $"The entity {otherUid} left a body ({uid}) it was never in."); _statusCapableInContact[otherUid]--; if (_statusCapableInContact[otherUid] == 0) - EntityManager.RemoveComponent(otherUid); + EntityManager.RemoveComponentDeferred(otherUid); _speedModifierSystem.RefreshMovementSpeedModifiers(otherUid); } @@ -65,8 +65,8 @@ public sealed class SlowContactsSystem : EntitySystem if (!_statusCapableInContact.ContainsKey(otherUid)) _statusCapableInContact[otherUid] = 0; _statusCapableInContact[otherUid]++; - if (!EntityManager.HasComponent(otherUid)) - EntityManager.AddComponent(otherUid); + + EnsureComp(otherUid); _speedModifierSystem.RefreshMovementSpeedModifiers(otherUid); } } diff --git a/Content.Shared/Nutrition/EntitySystems/SharedHungerSystem.cs b/Content.Shared/Nutrition/EntitySystems/SharedHungerSystem.cs index c9fa348ccf..0d6c5b17d3 100644 --- a/Content.Shared/Nutrition/EntitySystems/SharedHungerSystem.cs +++ b/Content.Shared/Nutrition/EntitySystems/SharedHungerSystem.cs @@ -1,4 +1,4 @@ -using Content.Shared.Movement.EntitySystems; +using Content.Shared.Movement.Systems; using Content.Shared.Nutrition.Components; namespace Content.Shared.Nutrition.EntitySystems diff --git a/Content.Shared/PAI/SharedPAISystem.cs b/Content.Shared/PAI/SharedPAISystem.cs index 8884b195d9..0e25d83824 100644 --- a/Content.Shared/PAI/SharedPAISystem.cs +++ b/Content.Shared/PAI/SharedPAISystem.cs @@ -4,6 +4,7 @@ using Content.Shared.DragDrop; using Content.Shared.Interaction.Events; using Content.Shared.Item; using Content.Shared.Movement; +using Content.Shared.Movement.Events; using Robust.Shared.Serialization; namespace Content.Shared.PAI diff --git a/Content.Shared/Pulling/Systems/SharedPullableSystem.cs b/Content.Shared/Pulling/Systems/SharedPullableSystem.cs index 846b12486a..d535c21a67 100644 --- a/Content.Shared/Pulling/Systems/SharedPullableSystem.cs +++ b/Content.Shared/Pulling/Systems/SharedPullableSystem.cs @@ -1,7 +1,7 @@ using Content.Shared.ActionBlocker; -using Content.Shared.Movement.EntitySystems; using Content.Shared.Pulling.Components; using Content.Shared.MobState.Components; +using Content.Shared.Movement.Events; namespace Content.Shared.Pulling.Systems { diff --git a/Content.Shared/Pulling/Systems/SharedPullerSystem.cs b/Content.Shared/Pulling/Systems/SharedPullerSystem.cs index 24d2392b0d..eb1c68baf4 100644 --- a/Content.Shared/Pulling/Systems/SharedPullerSystem.cs +++ b/Content.Shared/Pulling/Systems/SharedPullerSystem.cs @@ -1,6 +1,6 @@ using Content.Shared.Alert; using Content.Shared.Hands; -using Content.Shared.Movement.EntitySystems; +using Content.Shared.Movement.Systems; using Content.Shared.Physics.Pull; using Content.Shared.Pulling.Components; using JetBrains.Annotations; diff --git a/Content.Shared/Shuttles/Systems/SharedShuttleConsoleSystem.cs b/Content.Shared/Shuttles/Systems/SharedShuttleConsoleSystem.cs index 506fa84f10..28a0cf9c7c 100644 --- a/Content.Shared/Shuttles/Systems/SharedShuttleConsoleSystem.cs +++ b/Content.Shared/Shuttles/Systems/SharedShuttleConsoleSystem.cs @@ -1,5 +1,6 @@ using Content.Shared.ActionBlocker; using Content.Shared.Movement; +using Content.Shared.Movement.Events; using Content.Shared.Shuttles.Components; using Robust.Shared.Serialization; diff --git a/Content.Server/Spawners/Components/TimedDespawnComponent.cs b/Content.Shared/Spawners/Components/TimedDespawnComponent.cs similarity index 88% rename from Content.Server/Spawners/Components/TimedDespawnComponent.cs rename to Content.Shared/Spawners/Components/TimedDespawnComponent.cs index b5f6e9568c..3eb6ca7e9a 100644 --- a/Content.Server/Spawners/Components/TimedDespawnComponent.cs +++ b/Content.Shared/Spawners/Components/TimedDespawnComponent.cs @@ -1,4 +1,4 @@ -namespace Content.Server.Spawners.Components; +namespace Content.Shared.Spawners.Components; /// /// Put this component on something you would like to despawn after a certain amount of time diff --git a/Content.Shared/Spawners/EntitySystems/SharedTimedDespawnSystem.cs b/Content.Shared/Spawners/EntitySystems/SharedTimedDespawnSystem.cs new file mode 100644 index 0000000000..3129ca0fdc --- /dev/null +++ b/Content.Shared/Spawners/EntitySystems/SharedTimedDespawnSystem.cs @@ -0,0 +1,28 @@ +using Content.Shared.Spawners.Components; +using Robust.Shared.Timing; + +namespace Content.Shared.Spawners.EntitySystems; + +public abstract class SharedTimedDespawnSystem : EntitySystem +{ + [Dependency] private readonly IGameTiming _timing = default!; + + public override void Update(float frameTime) + { + base.Update(frameTime); + + if (!_timing.IsFirstTimePredicted) return; + + foreach (var comp in EntityQuery()) + { + if (!CanDelete(comp.Owner)) continue; + + comp.Lifetime -= frameTime; + + if (comp.Lifetime <= 0) + EntityManager.QueueDeleteEntity(comp.Owner); + } + } + + protected abstract bool CanDelete(EntityUid uid); +} diff --git a/Content.Shared/Stunnable/SharedStunSystem.cs b/Content.Shared/Stunnable/SharedStunSystem.cs index e0c0c5bca4..9d0a3e4fb7 100644 --- a/Content.Shared/Stunnable/SharedStunSystem.cs +++ b/Content.Shared/Stunnable/SharedStunSystem.cs @@ -6,7 +6,8 @@ using Content.Shared.Interaction.Events; using Content.Shared.Inventory.Events; using Content.Shared.Item; using Content.Shared.Movement; -using Content.Shared.Movement.EntitySystems; +using Content.Shared.Movement.Events; +using Content.Shared.Movement.Systems; using Content.Shared.Standing; using Content.Shared.StatusEffect; using Content.Shared.Throwing; @@ -31,7 +32,7 @@ namespace Content.Shared.Stunnable SubscribeLocalEvent(OnKnockRemove); SubscribeLocalEvent(OnSlowInit); - SubscribeLocalEvent(OnSlowRemove); + SubscribeLocalEvent(OnSlowRemove); SubscribeLocalEvent(UpdateCanMove); SubscribeLocalEvent(UpdateCanMove); @@ -105,7 +106,7 @@ namespace Content.Shared.Stunnable _movementSpeedModifierSystem.RefreshMovementSpeedModifiers(uid); } - private void OnSlowRemove(EntityUid uid, SlowedDownComponent component, ComponentRemove args) + private void OnSlowRemove(EntityUid uid, SlowedDownComponent component, ComponentShutdown args) { _movementSpeedModifierSystem.RefreshMovementSpeedModifiers(uid); } diff --git a/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.cs b/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.cs index e90671fd1c..343ae8850e 100644 --- a/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.cs +++ b/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.cs @@ -384,11 +384,11 @@ public abstract partial class SharedGunSystem : EntitySystem { public List<(EntityCoordinates coordinates, Angle angle, SpriteSpecifier Sprite, float Distance)> Sprites = new(); } +} - public enum EffectLayers : byte - { - Unshaded, - } +public enum EffectLayers : byte +{ + Unshaded, } [Serializable, NetSerializable] diff --git a/Resources/Prototypes/Entities/Objects/Tools/jetpacks.yml b/Resources/Prototypes/Entities/Objects/Tools/jetpacks.yml new file mode 100644 index 0000000000..335ab35b14 --- /dev/null +++ b/Resources/Prototypes/Entities/Objects/Tools/jetpacks.yml @@ -0,0 +1,235 @@ +- type: entity + id: JetpackEffect + noSpawn: true + components: + - type: TimedDespawn + lifetime: 2 + - type: Sprite + netsync: false + drawdepth: Effects + noRot: true + layers: + - shader: unshaded + map: ["enum.EffectLayers.Unshaded"] + sprite: Effects/atmospherics.rsi + state: freon_old + - type: EffectVisuals + - type: AnimationPlayer + +- type: entity + parent: GasTankBase + abstract: true + id: BaseJetpack + name: Jetpack + description: It's a jetpack. + components: + - type: Sprite + sprite: Objects/Tanks/Jetpacks/blue.rsi + state: icon + netsync: false + - type: Item + size: 100 + - type: UserInterface + interfaces: + - key: enum.SharedGasTankUiKey.Key + type: GasTankBoundUserInterface + - type: Clothing + sprite: Objects/Tanks/Jetpacks/blue.rsi + QuickEquip: false + size: 100 + Slots: + - Back + - type: GasTank + outputPressure: 21.27825 + air: + volume: 70 + temperature: 293.15 + - type: Jetpack + toggleAction: + icon: + sprite: Objects/Tanks/Jetpacks/blue.rsi + state: icon + iconOn: + sprite: Objects/Tanks/Jetpacks/blue.rsi + state: icon-on + name: action-name-jetpack-toggle + description: action-decription-jetpack-toggle + itemIconStyle: NoItem + event: !type:ToggleJetpackEvent + - type: Appearance + +#Empty blue +- type: entity + id: JetpackBlue + parent: BaseJetpack + name: jetpack + suffix: Empty + components: + - type: Sprite + sprite: Objects/Tanks/Jetpacks/blue.rsi + - type: Clothing + sprite: Objects/Tanks/Jetpacks/blue.rsi + Slots: + - Back + +# Filled blue +- type: entity + id: JetpackBlueFilled + parent: JetpackBlue + name: jetpack + suffix: Filled + components: + - type: GasTank + outputPressure: 21.27825 + air: + volume: 70 + temperature: 293.15 + moles: + - 22.6293856 + +#Empty black +- type: entity + id: JetpackBlack + parent: BaseJetpack + name: jetpack + suffix: Empty + components: + - type: Sprite + sprite: Objects/Tanks/Jetpacks/black.rsi + - type: Clothing + sprite: Objects/Tanks/Jetpacks/black.rsi + Slots: + - Back + +# Filled black +- type: entity + id: JetpackBlackFilled + parent: JetpackBlack + name: jetpack + suffix: Filled + components: + - type: GasTank + outputPressure: 21.27825 + air: + volume: 70 + temperature: 293.15 + moles: + - 22.6293856 + +#Empty captain +- type: entity + id: JetpackCaptain + parent: BaseJetpack + name: captain's jetpack + suffix: Empty + components: + - type: Sprite + sprite: Objects/Tanks/Jetpacks/captain.rsi + - type: Clothing + size: 30 + sprite: Objects/Tanks/Jetpacks/captain.rsi + Slots: + - Back + +# Filled captain +- type: entity + id: JetpackCaptainFilled + parent: JetpackCaptain + name: captain's jetpack + suffix: Filled + components: + - type: GasTank + outputPressure: 21.27825 + air: + volume: 70 + temperature: 293.15 + moles: + - 22.6293856 + +#Empty mini +- type: entity + id: JetpackMini + parent: BaseJetpack + name: mini jetpack + suffix: Empty + components: + - type: Sprite + sprite: Objects/Tanks/Jetpacks/mini.rsi + - type: Clothing + size: 50 + sprite: Objects/Tanks/Jetpacks/mini.rsi + Slots: + - Back + +# Filled mini +- type: entity + id: JetpackMiniFilled + parent: JetpackMini + name: mini jetpack + suffix: Filled + components: + - type: GasTank + outputPressure: 21.27825 + air: + temperature: 293.15 + volume: 2 + moles: + - 0.323460326 + +#Empty security +- type: entity + id: JetpackSecurity + parent: BaseJetpack + name: security jetpack + suffix: Empty + components: + - type: Sprite + sprite: Objects/Tanks/Jetpacks/security.rsi + - type: Clothing + sprite: Objects/Tanks/Jetpacks/security.rsi + Slots: + - Back + +#Filled security +- type: entity + id: JetpackSecurityFilled + parent: JetpackSecurity + name: security jetpack + suffix: Filled + components: + - type: GasTank + outputPressure: 21.27825 + air: + volume: 70 + temperature: 293.15 + moles: + - 22.6293856 + +#Empty void +- type: entity + id: JetpackVoid + parent: BaseJetpack + name: void jetpack + suffix: Empty + components: + - type: Sprite + sprite: Objects/Tanks/Jetpacks/void.rsi + - type: Clothing + sprite: Objects/Tanks/Jetpacks/void.rsi + Slots: + - Back + +# Filled void +- type: entity + id: JetpackVoidFilled + parent: JetpackVoid + name: void jetpack + suffix: Filled + components: + - type: GasTank + outputPressure: 21.27825 + air: + volume: 70 + temperature: 293.15 + moles: + - 22.6293856 diff --git a/Resources/Textures/Objects/Tanks/Jetpacks/black.rsi/equipped-BACKPACK.png b/Resources/Textures/Objects/Tanks/Jetpacks/black.rsi/equipped-BACKPACK.png new file mode 100644 index 0000000000000000000000000000000000000000..9041766c9cc19f79b3b17a2e093ad130416329e5 GIT binary patch literal 810 zcmV+_1J(SAP)=(-NevV7yi;ZSzE$WBg9@Z<0hZ`arH>*fYu_V?lZcF%G{U|CkGUayNvr6TI} zx&Q$0_1@l|2r5nz&fD$OYAy%PIhN9C0KiH%3jlZ=KX11umcv}AR;wcH@l|-f*jKf9 zLI@#*5JCtcgb*@K`yZ9Lzx9-Oj$YqgRaH?cm4vFQ!Z3`vD}-Sf;&F~Zv^@i%w~!fQ zVtIKP_xJbM-rmOT?JYJpH{rVOXw2E!*-URkKmIWC`8=+#uTd-((dl&Hvsg-}!8yljE*Edlz#{hF o6VG{(7VlZaoCzU>5JINvF9K{tuGwyg8vpBjE6vzK5m1Jt)Vzk-d?XWAj!EwQKQo&!Ka9LtQK1x1Jo6phO6l!Ws2W@P3GBl7$ zlMfnsxDF-8PL)czlagTWH=V@0_j`U=(mTLnu~;k?izNr=XRp+U^QI~)?m766^2!-w z%5fY3z-F_75F&MN-nfTSmjA^=XYPru>&+b{5a-z1f`|N8VZ#-F}w`(K(AQ1Lvx8^8a1;hAL8 z_xHv_^v3#rqXzuCx-!{rOc8#g2CUa>;{u-AZ}biTfM^y$N@-k(E>cQFvq*b?u7AK_ zFhIZGN2}EW0IXIkOs7*!CKK=zj!M_Ve6hGUP6(l0V3t1!0vwOJm_yH>Ye->?sd~M> zcQ1}(xULH+B`$wlqW7kUBuS7KXF3f1&mYYqbY6E*tyZ=C#*aV{1Q?BmrfIa{CmhG! zuJ-=S2J8+SX;i%I?@v~ar}SqwpxJ0-3d+n;wm-80A1^M94>Kk?%Jv)00kv8U^TlGj zj^h|flE8IcleCZO*FFwYN>TB=?KIYGH1PZ82Fv9Vk8vC>%AflyAcQ#TwA&zrfKqyI z9HkV55Omt@!hZa7@NXFnhkHj*&bi{8tKB#4Zp@+i_r!Pa-!0@&{T7SmaQFjx*Ex+I STw_510000P@upX=w0lZ%U<1ViU+Wj)m$lM9LE7*Hk+ZfPVCLf zn`3(&b0Gvm2pq>jDP;hHATU7?m^7YM001GxuX=90SSRr|5+Dh_?{jwd%JJwff^MiXvRs<^I92-+H55E)&NwNxZ*? zk@XXthInMtd;~3X$Mv1A0LcHBR0N{0kqazt!5J;1X9YCJSinY2wKf% zs(CJ)ce_7Ua2SRr3`4W{(-%4ag1PbX`Erl~1+w51%lw<)0vLVz00000NkvXXu0mjf D-BZX> literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Tanks/Jetpacks/black.rsi/inhand-left.png b/Resources/Textures/Objects/Tanks/Jetpacks/black.rsi/inhand-left.png new file mode 100644 index 0000000000000000000000000000000000000000..9f27af40edf9b00bb97a71ebe91472ba3b35fcca GIT binary patch literal 516 zcmV+f0{i`mP)b;z6b9g*s$Gz}cwvCCLzkpO7e-g&7DnPI9H7Ub%p9Q^nLssHs8=r?JGc{7Fwg*b z4ix?0#*^|pvg|Ot2M`ev5fKp)5fPnaJZgu@xEJF3WZVnmQG2W2R92N+si4{N0ayaS z=SKZ?rT{1a_AFUdZX`nTJP%4KD5a3+d8n#4m30WQ6HsQ13C=lq?`vmitwXol#cH(@ zc(ZLHCm=R`n_hHYnaBwk3v~ZX zBKKdM);g3oBL01@EFvNzA|fIpA|j%sq%Z36wa&i!K1n)5(mni` zpz!;eYMBZ&3b0-i&v9)3)69zpC1r0n6R zT>C1%0dO*iy=HLn_(^~uSc#Q3K8#8mSvMlq~ zS~%zS9$Q-hA^Br|aHzlZo4mCZFq_RVolXG&tJMnY^%~hc!{zL9r*6z}{s*d=L_Y`VdszFaN` zv;TpwJX-7Ed%p9JrM33ulU6?u(J^KwA|fIpA|fIpqJc_1Gmv~PK`G@!E#{_rAJ^~W zysbJzsb>bty}#J@&Ig2~nif2c@1FXzKsR(E2r)a%SMC{{Np!-G67lpW^!jng}U0 TxrBz(00000NkvXXu0mjf4Hft* literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Tanks/Jetpacks/black.rsi/meta.json b/Resources/Textures/Objects/Tanks/Jetpacks/black.rsi/meta.json new file mode 100644 index 0000000000..d57c3cdf00 --- /dev/null +++ b/Resources/Textures/Objects/Tanks/Jetpacks/black.rsi/meta.json @@ -0,0 +1,59 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from tgstation at commit https://github.com/tgstation/tgstation/commit/1592a112e3d33eec4a0704b518a138d5a976f455", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "icon", + "directions": 1 + }, + { + "name": "icon-on", + "directions": 1, + "delays": [ + [ + 0.2, + 0.2 + ] + ] + }, + { + "name": "inhand-left", + "directions": 4 + }, + { + "name": "inhand-right", + "directions": 4 + }, + { + "name": "equipped-BACKPACK", + "directions": 4 + }, + { + "name": "on-equipped-BACKPACK", + "directions": 4, + "delays": [ + [ + 0.2, + 0.2 + ], + [ + 0.2, + 0.2 + ], + [ + 0.2, + 0.2 + ], + [ + 0.2, + 0.2 + ] + ] + } + ] +} \ No newline at end of file diff --git a/Resources/Textures/Objects/Tanks/Jetpacks/black.rsi/on-equipped-BACKPACK.png b/Resources/Textures/Objects/Tanks/Jetpacks/black.rsi/on-equipped-BACKPACK.png new file mode 100644 index 0000000000000000000000000000000000000000..fdfc1f64a2f949da427a85cf3c3a25031913b442 GIT binary patch literal 1089 zcmV-H1it%;P)b2Lf>@`sEUszb^KTvk5$GvzEde*Cm zMLe~aBnJ^Xtbq=Zbg+jJFK;hRnkEx>-p;&vQ}_G1XnsE4H+fH-5q~cNL_|bHL_|b1 zL#x%2alZb&=L5iRzb=Mm%&PyJAEFLywOZ13-8;v)uB&YkOy>iD5JLWSRDuvf0zjkD zkYRNdkvCv>cQ*$Bo12@VA;bD`T+&SE3n8Qs0;{X5*xK3}E%vN>RFOAe$hK{zdeThi zkE@i+vFA|Ufb;WnrFzm#Vu6OB9R6(PNo= zibvvds;)x$M-YAWOY^7Lb8rJ^YQv1i7w@PNx%koA;%z^%o(N`Rlfg&)3%o zf&c(uSr!)ad03VO0HgZ4ZNu}t$nz@SGjDHiOV@Q#tyXb(c$gbLuGMNdI5^O951y6$ zpPxOGpRcd+aCsU2r%x!AO6d3dD6FhtSbuwRqJ0hi*Xs4Uyz3*SU~;j!_(ViRL_|bH zL_|bHL`3((&hxy{KmD1`2atS!eAGP4vShhjmX>8n$8l0y2;KQgEfhisxv;Q+o0}VW zo|kJh8uIAqC^uP8>dB4IyRor>e!q{kwKe#@KN@pW^2+OIsTGv91BDDICZcdh+=3R88j{P+Ix1HXw=q_$+3nnICxr*1w!W41xeb z5QO%}2SG3z7uRIoVm_b9yjjbSya8`dPI3>Imk|U3=H}-C01uXy0086lr26A0^M+Yz zF`YkC+WqmS`|nNXhf2FY-t>z%olitWL_|bHL_|bHL_|a*rhDj3=NscVjvViy2lSm8 z$YTC~6}yFGyg#x~DB$Aa0;N(3-EJ2;&J1KNKdx9$Y*uf4qtTGVp8COH0MGNZEQ0C$ zBxrf-;``dmuS2{88kI_Di}q!&_sub$q|OXvEk6^&7NB0QYdJHJ#r(LG|9?PKf4qJT z02mAgx*{^2A64vYK-fhvte0LF)A?~}xd`9aUVa_4Y`|hZKkBOokl2}l?2;D&(M%yyT!B&_sL7yGA)Y2xg@7h$0&*xJ6G`#udH9tz97hsGr#u#Jl zN~u(en)$pH7GL@;_hDDRinq}XQ>hf`y6(7*uIsK&f}|vA>39K>k|Y4oG>xq4u1O>k z6pO_ycM^-mD3M6Gdhp)K4ZDMx`-~(AkkyI$XovZWpn-P)2y*D~=8h z@cc~?=U+Z!>rroAU4-xiIGq8JNJMlvA=B^f;-Y^Hz!)Ta1bH5yOR2Am5WWO%l9?An zO^?yh6Yy3D>^`j>qHVo!p@Dc${QeCQZ{wmSw80yPe_M$+ApNueU<& z!QQHaXN)n%7-Nhv#u#Jm^!lmq#{cxx@{DHRT^gMt&yzWlMyE(s)f+bvs;W|TMxe1Z z1D3z>nF3A)0zR>-e7G%elcrUZkJA{uk9X?PNzLq6JQty zKD=5*cwhiW2W7`K1CGtn>b|>-rREd2(X&s}003{{*zr!^@I7F3WTdWk-A@3!3|3j~ zG&}*V=*72-NLJfRptc|H_xYO5)i!>guaf%|e~-m(&4BG0kj-Q~N_iQlr6Pv)IdlgC zE<|-lcOZaaeGaFkB9!tnvYE{PU#gwhe{Xr_PC9r~CuU}hF~%5ct3NcyP!K6dqxAp) N002ovPDHLkV1g#=kk$YI literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Tanks/Jetpacks/blue.rsi/icon-on.png b/Resources/Textures/Objects/Tanks/Jetpacks/blue.rsi/icon-on.png new file mode 100644 index 0000000000000000000000000000000000000000..290d3717bdc5a576ba30dff2bf59b24107d018eb GIT binary patch literal 592 zcmV-W0!UG#ZU20eg>D#LK;c zm{;6&@Mn_BjY?f)tW^NS;0L3F?Z~r9<7Oo-zcGt^m@hNTm&sVG7?rvJ@H|g=o+sks zR7lgGr~v@OeEF~Sg?Mru6*mvk@+WRU6t->i@Z&e`efWxP+bXH#{fEDJclcS_e?z4J z%QQK9@Tbcbz?n)mNq=>XBi5w-N)0&acBeP8D%lp}S871N-&ZbR(SD_W06@?T2*Xe{ zjWl5x5;Ozp^NDW2lRIzO+WJYcSOlQc>Ck92cz+81u8&nRX|>z`jC+0{U0)xEzc0$2OqgII)5>bENH$ZNRJjedWiD zN{+PsN^?Lim!s8gkJkXk;5#Ghwo2M7^-Dj8cW%DGGR^TcR&X2!=jXgWd(2flhv(&= zskmCTDo(oH@xvpk0DxYvN5OICa(%Cpe_X`H+Vec&`@ZmfUrhdKCu5e)KPA4rf4Pul e^=mYm<>5E8fnRKsrlt!30000>&*R literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Tanks/Jetpacks/blue.rsi/icon.png b/Resources/Textures/Objects/Tanks/Jetpacks/blue.rsi/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..059b976513090953c649d1f33675f426e4077800 GIT binary patch literal 476 zcmV<20VDp2P))6g4V>G<~-Mr{WsIprt>cKOksn?k{L7*EYc#t3gVdJ!lcU zD3FHG)Iq-up;%qsd1p=cOfN6b`@GNh2k#330t5&!1&;O>UIA4|kLI^2@kWM^b1_1i;?2mZZcs#b_&BTBm zG)-gY?uoVAM>I|Iq%r5mfT}3mY<`|n1?c>UI zdRI4auzW=>_eL_A1fX88Q>j$Aet~TxMMhDmndYy&lhW_nt_D#!UzP)X{cFy;B>i&8 zeO0o$@=hcY;bHL@JKm&WjTD)5+H<|5f$?Eu2USrVn@rMhG?37B#|C~h91WZo zi>?=z7Y$!?AR3KQGtE&95bi!RP?ub5cwWa_^QWkaGMa`7U8mdYanadlnsq$Y_3jo5 zvSC@H#bajxpxJDa(Dj)-pRI{uEQFATVMxO;|>AR;0nA|fIpBHGEIU$O3>ZlmMwpl%2K%GP*MS%oRL z=eFFQZ!Iovyr`^S=Mo8N&#mvY;5#jZ7Z^8QR8|tlQbA!_Yio?bLLf^iWgW-C^hF@- z2O=jRYBHYebzYdr3Aj0bK%?;r09Y=Uc2H-AkR7L@u{LS6}RPURW+0@Sl_Cq>@o zH?dhle_otY$||L7+~>c_A|fIpA|fIpA|lFF5jFh1?jew_;m6G((L<0+Wk|Y)A0^pC zAle_WSwPXU^dlTZZ7@s!fY=GpTH9JJpBjFYWIuw~2IN`8kCN<15W5BPtl{T5_dz@Z zvJkrkj4|jqE~Y^_Kd9kLg-0~kLo7b$3HK0ms$cUb?MD!AlPjWzFWrwIrsx_zdk84I Y5AcpQVPpMMo&W#<07*qoM6N<$f({e$asU7T literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Tanks/Jetpacks/blue.rsi/inhand-right.png b/Resources/Textures/Objects/Tanks/Jetpacks/blue.rsi/inhand-right.png new file mode 100644 index 0000000000000000000000000000000000000000..c9664e5679960859edc4ec7fb626cb749fe0e40e GIT binary patch literal 555 zcmV+`0@VG9P)c96AM}@;~ikb2}p<)p`xPJ159COjFj$J ztR%wD>VmV(s{dEP3$ydHnavjO0YpSZL_|bHL_}z}%BI^sG|TmF`_Qyo%em6r>262PSkCg6F1=Q z@eI*x4FFKm`>0}yUig6R`o%&WxXtPBtZq5;+u#PLvX`jaGG}@On(EkH+6`DGZ>AgY zmu=aK^H)Zr(uLL<01&?kE&u@4SqG!h$hy`C5i#T4YXIq)qrtf~uk|%pops_5mB3mr z(w_(7JR*qS^J$q^y{L#75ix1si|99ICL$stA|fIpBBFxwJu~2aF2VQAKwf)f>J0gw z8JO>r%eB{8BqByBwfQ4?X`G+7wR?lVZDt_Nw-X|O|CxbA|G%P47=}*TbD3^{@0kHx z|KHX5Tl*34IWypL?|(lZkm(VK2IpG~GXpa~YmG+GML%xE$1?*tg{;mx7=P^Zx&QA% trW-I10l>@5z*qhMjq=@pXTP7^dk3+mI7h*eV66ZE002ovPDHLkV1iL_1W*6~ literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Tanks/Jetpacks/blue.rsi/meta.json b/Resources/Textures/Objects/Tanks/Jetpacks/blue.rsi/meta.json new file mode 100644 index 0000000000..d57c3cdf00 --- /dev/null +++ b/Resources/Textures/Objects/Tanks/Jetpacks/blue.rsi/meta.json @@ -0,0 +1,59 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from tgstation at commit https://github.com/tgstation/tgstation/commit/1592a112e3d33eec4a0704b518a138d5a976f455", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "icon", + "directions": 1 + }, + { + "name": "icon-on", + "directions": 1, + "delays": [ + [ + 0.2, + 0.2 + ] + ] + }, + { + "name": "inhand-left", + "directions": 4 + }, + { + "name": "inhand-right", + "directions": 4 + }, + { + "name": "equipped-BACKPACK", + "directions": 4 + }, + { + "name": "on-equipped-BACKPACK", + "directions": 4, + "delays": [ + [ + 0.2, + 0.2 + ], + [ + 0.2, + 0.2 + ], + [ + 0.2, + 0.2 + ], + [ + 0.2, + 0.2 + ] + ] + } + ] +} \ No newline at end of file diff --git a/Resources/Textures/Objects/Tanks/Jetpacks/blue.rsi/on-equipped-BACKPACK.png b/Resources/Textures/Objects/Tanks/Jetpacks/blue.rsi/on-equipped-BACKPACK.png new file mode 100644 index 0000000000000000000000000000000000000000..e6efe984f80d15822c246da302fb3ce26793b971 GIT binary patch literal 1073 zcmV-11kU@3P)F$2s5m{_*p1+;PsM-e?5YRSc=_ zNU>N%tyT-H9~>O04yVji{-e!3{B(C8<6r)YH?LmdyN7!?{ACp{uAJ+ut5BYR5kHHCu;J24ABafl91o^&? zTCJ7|dhVaP*2_?n`7>4>n*j3fw*deX@3t|V%i+SiZT$YlQGLp)V?)6~6yAXY^Nprt<;B-ya_~&zim_nQs=wn!YBk>n3&}bms^5*bHJh75Oy! z6|&7gaJczn#`8Q`U0u!e*5lf_?s32V{7*ESO-xQsqSb13wpm+Si!Cp0`F%U1qdz`u zUi)T%sF8C;>EsN zVpkv<^CL|_9R2ZW%t|sp^b(YGe|&G=a4r|asOifO{R!AuU(Y!E5AdP2hbey%0B|Os z2LN=}H`doWBz{?xrL;=J$qzi1iQPt7#$tOi;w4^)?R)cv`oNoE{FX4?M`p~j8)eWliGY0S|;F3K94DX5g%H6aP}X>cF({`$v4h) rPrd21ru1@A|MMd`?c=F_FAhM%K=~eKs zfiRS9g6O~4TTf#zZutz&v9Y_ErzGTS7}OVV^@&*xI|#eOQjMs48wDbVHjO4LNPD0U$G{Nd65A?E|+6YaUKJH z2QDu!3xz^~WilD2>$=dsKa* zDp$Ol?Z>wzR1**J zd1Dy+^*yMKC46{)h~({!jyMnQ0(hMPilXpN$K}@GOUz9jU+d3a3t+-k%;vW{;yk!7 zfwSb^-Lb%P^mPHgZf^&kgR20BVZiAT2mrdS3#a{02;%3T8vuaX!4YZ)N7ymP5SJwE zm}CFN?Qwo_KeG#k0y7K)ilSh3bycvpM@B}lva-^Z{{Xg|*(|%Je!`dPbu{XAq*5tZ zmW4zz2|NCAbF-^C^xXLPIP>~E7upZ@Tpc_igb+dqA%qY@2#M0;S?SEbdI~*9yYDVe z&M;y60TU-@n5JoGt`M50v6DFh{?-h5zCyNJ&xXlRZ%)CoER2qhqS0uy#;mWe_w+UN z$sZ$;NMLt&7pYVV$qO5>bLVN7w-oatTU;1mTjdzrD#w_;7{M!nsJVT2E|+WNy|^&I zycSOQ?hJ*|i;oIVuC4`W@3YrTvtx{=X-t-7j?}^>%d+EH(4MQ;ngQ4LczZvdS!<5t zDwRsl?g5obMQ|#BWm&lY_7N^7hq3>A531?DX25fOz{$S*{P)X2^NrN2J1+nL<+T`$ zhWj|*_khWXiH=yWp8#$-IOXcbcLBoa#YcrFSJwix_v7P|6gaV{#3iYfHvrEy1FrXg z<34+q0mps!!6EMDL_IS&G=%5nY&dHM`mz5Wdd~fH@V0);nGiwBI?!N3(FStq=oHiZ9x>> zb`RpJsD)M9&K`;-(bkT6iAtUCGznkcZ|3D?G7pfFl9G~=l9Ce8YW^c%Up2X3zPG>+ ziNdX{!Y7Tc{kXwVD7O1PE9!f$g5rmt1J7kT$Yna1G(xbl3I_nj7-x)er;nvuVCk02 zM^TV`p#%T`OSc}4@4?P7OSfQZVVGLj^$b-(@r4u6Pr9ySdG`;#?HoYYbxJ4_|3~TC zGyel+0ufckwl&)w187o$5%}8#J}Ck9M#FU-AEQKj9lp>GJ)X+)@u_LV;-3HjR~LVA zdRWD0oV$D{NT8qZv|J?p34-JcRlr>0JMs%fm|AzssNZz3cB$a^`B#+p%9!~wgJ?85 z&{y!VXi@eWYenp7`VnNG6krs4A+p+N)Fml`k|gE35GQV%weBt;cU*BJmUb zeAL6xQ+#Iydf~tO3K+TvFvfU%Z16W2QPrMz&^LI&7%!Ddo{|tWf9OHTGz>5E_AN%x z{Gkch*xV#HGn5!X^GOFGP18`V)q3NXmLGi2?XVKF5K-0MY0NYX{JXtH`>KGKXovmc z3pYcBVmowpw}i^kJd~I<(5J*KRF39xcDLl);@<+lr`*bls|B@fo7=X{ovo?UGirPn l_~HGB6B$*$l$6xy=s&S+>U%4}u|5C*002ovPDHLkV1iRQBeVbj literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Tanks/Jetpacks/captain.rsi/icon.png b/Resources/Textures/Objects/Tanks/Jetpacks/captain.rsi/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..323f0606a289dcbb7c85043c54debf1b43c68d40 GIT binary patch literal 508 zcmVu4gg$ci_39_hQy)#sYa2@ z_chO&)s1j3QalwKAQc-RB)TBS843V|5K0K4lR6UVfkb*Loh<_ZKq9@FcvN^YCXpT_ z-VKR&tIpUqpoJg^IJtSn!Sw?KL9mo##f|}vWpO3%4`TqIe{G;ztEry-p2c&R`U`@4 zaT?s*g3rGO0BE<~P=73815K6g83AbN>czZn9a9}R3|u08l!wF*N2dBQ!09`Km*y^R zixfNCU+{Xpy1Lw)+_pOq4u`?9EK23Fr4E=fAjcV+KJKf(>|(Y9>w!CH>E>NV|K0(^ z86bpEzej%tIF=o2^=6<&2rU!}nkEb{B1sgDB!D?#tmLqD5%D~aQn@^i ztzdZ_Gd>v{%Z_hDNfhzj>7d`vVd?7_0CM@htIL3QBK%<-xqtXB{5GCfRvKzMAj%jczV8#! zW9BSo7T0y@^X(@42b-a2Bed7;t#w|M$~HPWy_DT@g@}kgMngK;9+L0-^nP$m(eant z>xJ{hv-VyGgB2-%`D-A10;M^Rp zbzYQ}1^7=?&Ji<9d1rdXFYTYv^bSB2y?QTm+X}b%ysXirPM+tj&u!52yaF>%KXmN5 z(WD-}Ds^7?o_SeXUtS$EOSllT9{*Jq00000000000Dx86HT-#VX!H!?!v2MqC53P&*^>ZZ6Fl{;avQ`VrLs2jo%1*X~D9lXndtJp_>54-uqR UEgHXjxc~qF07*qoM6N<$f>u3iSe$sBkFj1v(x3VS=C;rqP{i7$a7X9m*ToAUut-&o|#Kv4fbt-T`u p5GrzJ;Jf~Ru8Quzv)@nY`vS0iQ?R3RY6t)T002ovPDHLkV1nu%2uJ_` literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Tanks/Jetpacks/captain.rsi/meta.json b/Resources/Textures/Objects/Tanks/Jetpacks/captain.rsi/meta.json new file mode 100644 index 0000000000..d57c3cdf00 --- /dev/null +++ b/Resources/Textures/Objects/Tanks/Jetpacks/captain.rsi/meta.json @@ -0,0 +1,59 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from tgstation at commit https://github.com/tgstation/tgstation/commit/1592a112e3d33eec4a0704b518a138d5a976f455", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "icon", + "directions": 1 + }, + { + "name": "icon-on", + "directions": 1, + "delays": [ + [ + 0.2, + 0.2 + ] + ] + }, + { + "name": "inhand-left", + "directions": 4 + }, + { + "name": "inhand-right", + "directions": 4 + }, + { + "name": "equipped-BACKPACK", + "directions": 4 + }, + { + "name": "on-equipped-BACKPACK", + "directions": 4, + "delays": [ + [ + 0.2, + 0.2 + ], + [ + 0.2, + 0.2 + ], + [ + 0.2, + 0.2 + ], + [ + 0.2, + 0.2 + ] + ] + } + ] +} \ No newline at end of file diff --git a/Resources/Textures/Objects/Tanks/Jetpacks/captain.rsi/on-equipped-BACKPACK.png b/Resources/Textures/Objects/Tanks/Jetpacks/captain.rsi/on-equipped-BACKPACK.png new file mode 100644 index 0000000000000000000000000000000000000000..351623cf28fec733aa407dffc741b889352e818c GIT binary patch literal 1099 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 literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Tanks/Jetpacks/mini.rsi/icon-on.png b/Resources/Textures/Objects/Tanks/Jetpacks/mini.rsi/icon-on.png new file mode 100644 index 0000000000000000000000000000000000000000..0657c4bfd4605f2f43227e705db978cd40befe5c GIT binary patch literal 1457 zcmV;i1y1^jP)4qq^H#w8jZ%Vr{Ed-1_+OQtN@G;X0jEY63q zz3fl+vSib@#VOONQ=H%+#)=Iy8AimR$BmMmF<)oNw3i}ktl;|0Dl! z#TylLcXxBad4b&hxoHl?5lYrSW}~XAV$Pg7XqrYK5Ev)$MU7o}{W>S>P2}a}p=laE zpO1|%r<0d!Vdq|_azBkkIv?-c+8VpKb9acdE(@~?XE8W9NZ-vq)~yuG$WEs^N&obC z7cp(xG&D^kBO?RDFxa#6c>(b2$>#78HtfgknCkEH(|afB?rfvU3vX>Oi+M#W_~pz{ zltwbd^FMyF8B?Yiv-JgR-`Sw;9>0BDPfu41O}$3a{&5Qs3ub1+(<(TU4a$;9Qr2UlB zPyni{*NTZ6CG#(fAC4N6J_h&mUk!?aLcgz{Rkf?2{T>bb{z3^q&B^*l72slXGc7j< zxOC|fnx>)addx~@W@bi4fW=~o+JE}==_rko`IB`$aepx^Fk_~@x*c8DNeiVRhR09# ziTX#q2HoC~Urp2EUgY+Ht9ZTMh`7(^WBb6>$o{VvXNp)FquP^kKYxef5ZnA$@N|0! z{u3nV4${}t$2R{J9Ew9E>mOBs(IEt&>w2WUyu3V8;*xBIrNzYrgF%A9AnJ-0ymL)c zTFYjNMq8F>eDQT+X^hp5MFtI7KR9skU_{L2a#2-TDQw}k@~3-6ERAGH#NQzt3XF`3Dk_DovG1YzqpGSX zEiH}w)oiq7Mee}p5SvIa>U1CzFijj850Vc^1##B}R880Dq1T{Kzh!;)4ESUQ&$!<=FGq_418`MWkm*71p>R* zT7aQLwnL$*<^xhm!ubHBx-LYT!kJ6gvE=8HF;ivf-lfo~;rylrkM}wkulUK^+@#N2 zxICuDqe$F2AlCYPQ&T&uj_oMuHx`gTJD;v^yXZX8P0sWju6h=*>e!9~cfUf@`L>uE zk0J@@19CsFFf9Z#U=<;Ozu(XDoy(z9qviV!L`VP(ul{{^24MI<@Q0?74@fl$=L0IJ zfbb+|1PmB}j+&8#h6oCbfB_>Dpn$3815!=G`GD~IeFzxb+Sh^Sx`#kdfM8D$&)*)l z_H_UZ0z>&lpM_#+B$5wEHB-q4=%t#*{Ooz$cHQPy>n#>dU&tNj``NFp{%T-d$^OuT z)L7&EcH@mE25nf`dTb#*g*>FO%EbiBtx&m+j{j-{0F+5e}LQ0J2-@~ z3ZhWrpg2>gu!+!hwUWampC=?24Hk(jY z73Ff-QFEHZGXP^u#N%-g5xU*(h+wTG3;xT*&c_+VVlfaAbX~`TJF|$Lo5Si$RXWWv z%&b=jB9RD)2*F?wmSy3^>J0$^Z+B`Z6&XDI@EuLFhwbZ8v<~ao$bIXujt&QQRZHrh|0Qh23=k2b0QQd-p=p|QPY#F)b_wn)hZ}|i29x!UJj+d+e0000b;z6b9g*s$Gz}cwvCCLzkpO7e-g&7DnPI9H7Ub%p9Q^nLssHs8=r?JGc{7Fwg*b z4ix?0#*^|pvg|Ot2M`ev5fKp)5fPnaJZgu@xEJF3WZVnmQG2W2R92N+si4{N0ayaS z=SKZ?rT{1a_AFUdZX`nTJP%4KD5a3+d8n#4m30WQ6HsQ13C=lq?`vmitwXol#cH(@ zc(ZLHCm=R`n_hHYnaBwk3v~ZX zBKKdM);g3oBL01@EFvNzA|fIpA|j%sq%Z36wa&i!K1n)5(mni` zpz!;eYMBZ&3b0-i&v9)3)69zpC1r0n6R zT>C1%0dO*iy=HLn_(^~uSc#Q3K8#8mSvMlq~ zS~%zS9$Q-hA^Br|aHzlZo4mCZFq_RVolXG&tJMnY^%~hc!{zL9r*6z}{s*d=L_Y`VdszFaN` zv;TpwJX-7Ed%p9JrM33ulU6?u(J^KwA|fIpA|fIpqJc_1Gmv~PK`G@!E#{_rAJ^~W zysbJzsb>bty}#J@&Ig2~nif2c@1FXzKsR(E2r)a%SMC{{Np!-G67lpW^!jng}U0 TxrBz(00000NkvXXu0mjf4Hft* literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Tanks/Jetpacks/mini.rsi/meta.json b/Resources/Textures/Objects/Tanks/Jetpacks/mini.rsi/meta.json new file mode 100644 index 0000000000..d9ea7ada5f --- /dev/null +++ b/Resources/Textures/Objects/Tanks/Jetpacks/mini.rsi/meta.json @@ -0,0 +1,64 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from tgstation at commit https://github.com/tgstation/tgstation/commit/1592a112e3d33eec4a0704b518a138d5a976f455", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "icon", + "directions": 1 + }, + { + "name": "icon-on", + "directions": 1, + "delays": [ + [ + 0.5, + 0.1, + 0.1 + ] + ] + }, + { + "name": "inhand-left", + "directions": 4 + }, + { + "name": "inhand-right", + "directions": 4 + }, + { + "name": "equipped-BACKPACK", + "directions": 4 + }, + { + "name": "on-equipped-BACKPACK", + "directions": 4, + "delays": [ + [ + 0.5, + 0.2, + 0.1 + ], + [ + 0.5, + 0.2, + 0.1 + ], + [ + 0.5, + 0.2, + 0.1 + ], + [ + 0.5, + 0.2, + 0.1 + ] + ] + } + ] +} \ No newline at end of file diff --git a/Resources/Textures/Objects/Tanks/Jetpacks/mini.rsi/on-equipped-BACKPACK.png b/Resources/Textures/Objects/Tanks/Jetpacks/mini.rsi/on-equipped-BACKPACK.png new file mode 100644 index 0000000000000000000000000000000000000000..4348c5463c8f828b3cfa8b16a85cac34c5396253 GIT binary patch literal 2190 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 M07*qoM6N<$g8v>3%m4rY literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Tanks/Jetpacks/security.rsi/icon.png b/Resources/Textures/Objects/Tanks/Jetpacks/security.rsi/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..926a586a63af3d893cc96e40fe27a24393a01d72 GIT binary patch literal 479 zcmV<50U-W~P)1ppG0?};6RdsO$oB>-AL9U= zf3~n%Ev|`jd~%Oms1u9D2J*_kXa|0R4RemA#YNx!t^vA-jT1B>Tupw{a1D@7rCbey zXt)MAJUa5cu>5EQngj88oSRaqQ}b3ITEq7`uI40~5S?k5PNirxn@nC=jC>sf?B80E zL?MqYvs80(Ag`K}*fL9^kasorh3&1ao)v7GrZP=ab^r8k&Yz%d+<)I6Bt!@=_yYP} Vvi+uJ+))4k002ovPDHLkV1mZn*?9l} literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Tanks/Jetpacks/security.rsi/inhand-left.png b/Resources/Textures/Objects/Tanks/Jetpacks/security.rsi/inhand-left.png new file mode 100644 index 0000000000000000000000000000000000000000..97d9e6f8891e818ce948fd6e3783c9c9ef8a0bd4 GIT binary patch literal 563 zcmV-30?hr1P)NP*1oLSR^ zxq@CR2lQGQAHTicA|iEE|0HV~mIcTf37J`29Xv4-^0HnH{Wcy{R$vR@CWMfdWf8qM z=gu-sQ^sO3qQ@uhuW4J-5n3!17dp?0gF7m84!Sfg{}!*`Y! zTDCx194&O7la>YePgoY<#6QNJR&W~B5Q2i3$_K&S;KeZ>_=eR0y=B>I_E}z z09TOC8onE6KLYz7p&)Ab-2Dh_g0A7ChXCe8L|^YbQ#4l)u;Ty#002ovPDHLkV1fjq B`aJ*u literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Tanks/Jetpacks/security.rsi/inhand-right.png b/Resources/Textures/Objects/Tanks/Jetpacks/security.rsi/inhand-right.png new file mode 100644 index 0000000000000000000000000000000000000000..f19970f2dd481c3d00b4d419002170d408644abb GIT binary patch literal 564 zcmV-40?Yl0P)S5XZ+4R4nR2s9+QXAxLjM6g)|MjtEv?q;H~v4L*Ta>8)Z9z131Eg-Sj2=AkJ4 zATqIqHXqG4-MUf!KM37S!^}U!ZZ>3w00000000000000W%3W^S_qhYxoeH+`e{oDv zRL!e?#%A$|nnkbu>0z6Q_^8Y+ST<2LdlGP^r|j(d+RurevTtjZrD^s!Fpp;688D7v z7`CQqM5S_E?l%?l|p_R85tywCw==DsA<5b38+1PQ$gRc)dOeTnD zz;n4qQ{MlLp;N!}IPw=Y z0{{R30000000000Vv6dXfnj{i?EyNr@%&3{c%O;8*{bH3uRu0hK)iGGn7Z zK;$CTJp)1Ye;EkB2&wEDm{$M)RaDpCQSS$mA);@r%Tze6S_;bm0000h(G*mCD%P8HOR!=`{BC_N3;#Df#(~ zA&i+B+z-wG0Jgh-;n{K$t4B?Yjz6xB@82}GUjdf&^>wLnx9QHmDs}g+<2j@k;Naju zYTRwQ^7n(`vBxhC4=0Yx;48o;vww!Iz&rSQb_w4{mSFbJQ2ezxaa;yp0TK%00*`tx z@#E=B0DuU5G;v&p^a9XpUw-j{<2kqh4*dS~spC0EBzp(GryW#gwa01 zQnv>HD9;8k9}1z2a~OYPI9^RI0#*C-N?$Wu*W%VSxAk~sWd*ytyUIQT_#yw}jScZx z`vgD57tlFAMk0|wtJOj@7K1hZq*PLV4F1=$*{pcePx8R%!REmyA|fIpA|fIpA|fIp zx)r|rJf!tse=72&dqHmZlMtt7#puS+NDdU?dRBvzdxL}+xlbTb~`&eO3ndZ z9kw>ajg&U-5VQI zc?INEzM}>QBMVXS;%bK;P zkD9Q$^={rX;J19I9PQY&ZhS766F;;&0Dy9TfXZN?nCLswiLP+vWHiFzF;XsY|bl?tG_|oP=*{mtO@X3osuF4SV$fT)SuBrsT^| zvH;;o1m7fM*qynf)-T6dBL_|bHb!&A$<3{pK9pJ-)56>=l~WNU zNg~U>UdvOHWtDu9BuOMsO_nyUl6PPNy)kP3Lw%sfTlUEp>4{ZS0S0=!cm_{ZujV4C7GR*qOAB9i;C8#w&|>W4gOwUuzB9MmjfF2enu?%li_As_c=huB z>7%oV>9KZq)zSQzXq#ui{Fq4HU3KQ%0;_Q!)m*B;K~6b+WEMHdDX6(rfz`NAwFs&O zDDJ>;ILiL^KjLsO?Clqhc9EReR;@v7Cc!e>3bMO-Q-ZTXb~lgAwu0D9LUq(MtpXj< z6kJaGY$b3x9q5RrG_3-vS%sUGf13~r=0s}eE>ua;G;^VLgRstUhWUvdIN0F7wXMi0?k$l+4Lov ztrGNwoAuk9Z}}VWV>+(l_GTZ3S%vO*?H|bYeBsH*JDDch7W~^PPR<9eH?Zn_#u#Ia cF~-*1H%j;2w8h*h`~Uy|07*qoM6N<$f*S0@HUIzs literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Tanks/Jetpacks/void.rsi/icon.png b/Resources/Textures/Objects/Tanks/Jetpacks/void.rsi/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..fe5a89a6f0e3f507de041aa36becd01b7310e122 GIT binary patch literal 379 zcmV->0fhdEP)?9_X_}_} ZhIe}PZNxLI8Os0w002ovPDHLkV1k{!tH%HU literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Tanks/Jetpacks/void.rsi/inhand-left.png b/Resources/Textures/Objects/Tanks/Jetpacks/void.rsi/inhand-left.png new file mode 100644 index 0000000000000000000000000000000000000000..cfa34df1c27618d9ea433cf4059e83321bad0b7a GIT binary patch literal 579 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7T#lEVB+$0aSW-L^Y+$8Z|Ot{wh!)} zt_K|#-PMse;##1gK5OfgOSej1ukm=P#PYxCz(u{K&N~h|Zg6gI@bGvsMYE}`>_Ytk zMb@b)8c#z+T%7kjd3z<{cF11+_pt)=?*H5SzC8ZjKA!i?0)kMm^4GNOM^f&d6W?4K z8+z*B?w4CE3nAI?@c+bM8==i`!SBbUsag zq7VOrmv1Cl%Im(_zf!pzT=2$Q^Bv!VMPW<%Z=zLZ-VzJJvHlg8w;<+SpTx3VV~XQVOh zx)}YHLB?8d*-QpusY;fw<_a_C9dcdUX`t8mx{~F1U$6Aclq5pPmSFjQr?Ikw~D@&v#M?eFmW(= My85}Sb4q9e05OCRU;qFB literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Tanks/Jetpacks/void.rsi/inhand-right.png b/Resources/Textures/Objects/Tanks/Jetpacks/void.rsi/inhand-right.png new file mode 100644 index 0000000000000000000000000000000000000000..ede83bd77dae428918694d6830b1b1c03c7a07fd GIT binary patch literal 596 zcmV-a0;~OrP)7r%OU@chPvyZ5>GxNmu1fQX2Qh=_=YhzJ0% z|HY87GwATG)WLJ?6%84E`myE0-AzN@z3PcoV?IsfB`9}yy9<{Wi!Hx31^9EQG2J~# z&Se5~`!=9A0a&LaIH(L>cP+m%E+Rl>|FY}yC;WbNnt)Yz zkY0O+T=rZlKl*TXaRNc4pB=ze?w7OAWqR@)>9sygO$O)oZ9sPyFg#>pG-Uz+=2O7Y zF#rtfPpp}0Zr@Mf!Uld>k6}6)Ow2T3IvM=79wE{8#E1@Uxpy`VsZ|Fgm&-}5Iv`)S z#$s{$tLARon?@5Tm9u!AT0*Iug?$-=*AMmFzGr~zuvWnO=O=I)1=z{xAAl~E+=2gY zZy55o{s75-3oqVRW7C1S<|ZN{A|fIpA|fJ+zK-Va5u!Bh*ekX^?9bH?_p&$OS6hcW zk9%&Lzek-?19}tc^LJg`+TNW79Rf#VH@SNQD)V<;ygLiPj<)+MH6YBr0dMX3)I)i* zaHOT{N}oWOdjmIXhbGLu0dH+x_f&p&VeSohYwOZcdUyU_Hw&(bFd66XBf it^GFropXPpyZZ+^6G!=7b1b!&A$<3{pK9pJ-)56>=l~WNU zNg~U>UdvOHWtDu9BuOMsO_nyUl6PPNy)kP3Lw%sfTlUEp>4{ZS0S0=!cm_{ZujV4C7GR*qOAB9i;C8#w&|>W4gOwUuzB9MmjfF2enu?%li_As_c=huB z>7%oV>9KZq)zSQzXq#ui{Fq4HU3KQ%0;_Q!)m*B;K~6b+WEMHdDX6(rfz`NAwFs&O zDDJ>;ILiL^KjLsO?Clqhc9EReR;@v7Cc!e>3bMO-Q-ZTXb~lgAwu0D9LUq(MtpXj< z6kJaGY$b3x9q5RrG_3-vS%sUGf13~r=0s