From 7ee2f15a1420123ffd03fb1aea7bac856f532656 Mon Sep 17 00:00:00 2001 From: Leon Friedrich <60421075+ElectroJr@users.noreply.github.com> Date: Sat, 10 Dec 2022 16:45:18 +1300 Subject: [PATCH] Fix projectiles not inheriting velocities from the shooter/gun. (#12854) Fixes https://github.com/space-wizards/space-station-14/issues/12852 --- .../Weapons/Ranged/Systems/GunSystem.cs | 14 ++--------- Content.Server/Magic/MagicSystem.cs | 16 +++++++++--- .../Weapons/Ranged/Systems/GunSystem.cs | 25 +++++++++++++------ 3 files changed, 32 insertions(+), 23 deletions(-) diff --git a/Content.Client/Weapons/Ranged/Systems/GunSystem.cs b/Content.Client/Weapons/Ranged/Systems/GunSystem.cs index 55d670d054..e413565c89 100644 --- a/Content.Client/Weapons/Ranged/Systems/GunSystem.cs +++ b/Content.Client/Weapons/Ranged/Systems/GunSystem.cs @@ -158,18 +158,8 @@ public sealed partial class GunSystem : SharedGunSystem return; } - EntityCoordinates coordinates; - - // Bro why would I want a ternary here - // ReSharper disable once ConvertIfStatementToConditionalTernaryExpression - if (MapManager.TryFindGridAt(mousePos, out var grid)) - { - coordinates = EntityCoordinates.FromMap(grid.GridEntityId, mousePos, EntityManager); - } - else - { - coordinates = EntityCoordinates.FromMap(MapManager.GetMapEntityId(mousePos.MapId), mousePos, EntityManager); - } + // Define target coordinates relative to gun entity, so that network latency on moving grids doesn't fuck up the target location. + var coordinates = EntityCoordinates.FromMap(entity, mousePos, EntityManager); Sawmill.Debug($"Sending shoot request tick {Timing.CurTick} / {Timing.CurTime}"); diff --git a/Content.Server/Magic/MagicSystem.cs b/Content.Server/Magic/MagicSystem.cs index 69852aa337..76e5336673 100644 --- a/Content.Server/Magic/MagicSystem.cs +++ b/Content.Server/Magic/MagicSystem.cs @@ -1,4 +1,4 @@ -using System.Threading; +using System.Threading; using Content.Server.Body.Components; using Content.Server.Body.Systems; using Content.Server.Coordinates.Helpers; @@ -16,6 +16,7 @@ using Content.Shared.Maps; using Content.Shared.Physics; using Content.Shared.Spawners.Components; using Content.Shared.Storage; +using Robust.Server.GameObjects; using Robust.Shared.Audio; using Robust.Shared.Map; using Robust.Shared.Physics.Components; @@ -39,7 +40,9 @@ public sealed class MagicSystem : EntitySystem [Dependency] private readonly SharedActionsSystem _actionsSystem = default!; [Dependency] private readonly DoAfterSystem _doAfter = default!; [Dependency] private readonly GunSystem _gunSystem = default!; + [Dependency] private readonly PhysicsSystem _physics = default!; [Dependency] private readonly SharedTransformSystem _transformSystem = default!; + public override void Initialize() { base.Initialize(); @@ -155,11 +158,18 @@ public sealed class MagicSystem : EntitySystem return; var xform = Transform(ev.Performer); + var userVelocity = _physics.GetMapLinearVelocity(ev.Performer); foreach (var pos in GetSpawnPositions(xform, ev.Pos)) { - var ent = Spawn(ev.Prototype, pos.SnapToGrid(EntityManager, _mapManager)); - _gunSystem.ShootProjectile(ent, ev.Target.Position - Transform(ent).Coordinates.Position, ev.Performer); + // If applicable, this ensures the projectile is parented to grid on spawn, instead of the map. + var mapPos = pos.ToMap(EntityManager); + EntityCoordinates spawnCoords = _mapManager.TryFindGridAt(mapPos, out var grid) + ? pos.WithEntityId(grid.Owner, EntityManager) + : new(_mapManager.GetMapEntityId(mapPos.MapId), mapPos.Position); + + var ent = Spawn(ev.Prototype, spawnCoords); + _gunSystem.ShootProjectile(ent, ev.Target.Position - mapPos.Position, userVelocity, ev.Performer); } } diff --git a/Content.Server/Weapons/Ranged/Systems/GunSystem.cs b/Content.Server/Weapons/Ranged/Systems/GunSystem.cs index 445c4b68c9..a584c1e1ea 100644 --- a/Content.Server/Weapons/Ranged/Systems/GunSystem.cs +++ b/Content.Server/Weapons/Ranged/Systems/GunSystem.cs @@ -92,10 +92,15 @@ public sealed partial class GunSystem : SharedGunSystem var mapAngle = mapDirection.ToAngle(); var angle = GetRecoilAngle(Timing.CurTime, gun, mapDirection.ToAngle()); + // If applicable, this ensures the projectile is parented to grid on spawn, instead of the map. + EntityCoordinates fromEnt = MapManager.TryFindGridAt(fromMap, out var grid) + ? fromCoordinates.WithEntityId(grid.Owner, EntityManager) + : new(MapManager.GetMapEntityId(fromMap.MapId), fromMap.Position); + // Update shot based on the recoil toMap = fromMap.Position + angle.ToVec() * mapDirection.Length; mapDirection = toMap - fromMap.Position; - var entityDirection = Transform(fromCoordinates.EntityId).InvWorldMatrix.Transform(toMap) - fromCoordinates.Position; + var gunVelocity = Physics.GetMapLinearVelocity(gun.Owner); // I must be high because this was getting tripped even when true. // DebugTools.Assert(direction != Vector2.Zero); @@ -116,15 +121,15 @@ public sealed partial class GunSystem : SharedGunSystem for (var i = 0; i < cartridge.Count; i++) { - var uid = Spawn(cartridge.Prototype, fromMap); - ShootProjectile(uid, angles[i].ToVec(), user, gun.ProjectileSpeed); + var uid = Spawn(cartridge.Prototype, fromEnt); + ShootProjectile(uid, angles[i].ToVec(), gunVelocity, user, gun.ProjectileSpeed); shotProjectiles.Add(uid); } } else { - var uid = Spawn(cartridge.Prototype, fromMap); - ShootProjectile(uid, mapDirection, user, gun.ProjectileSpeed); + var uid = Spawn(cartridge.Prototype, fromEnt); + ShootProjectile(uid, mapDirection, gunVelocity, user, gun.ProjectileSpeed); shotProjectiles.Add(uid); } @@ -167,7 +172,7 @@ public sealed partial class GunSystem : SharedGunSystem break; } - ShootProjectile(newAmmo.Owner, mapDirection, user, gun.ProjectileSpeed); + ShootProjectile(newAmmo.Owner, mapDirection, gunVelocity, user, gun.ProjectileSpeed); break; case HitscanPrototype hitscan: var ray = new CollisionRay(fromMap.Position, mapDirection.Normalized, hitscan.CollisionMask); @@ -229,11 +234,15 @@ public sealed partial class GunSystem : SharedGunSystem }, false); } - public void ShootProjectile(EntityUid uid, Vector2 direction, EntityUid? user = null, float speed = 20f) + public void ShootProjectile(EntityUid uid, Vector2 direction, Vector2 gunVelocity, EntityUid? user = null, float speed = 20f) { var physics = EnsureComp(uid); physics.BodyStatus = BodyStatus.InAir; - Physics.SetLinearVelocity(physics, direction.Normalized * speed); + + var targetMapVelocity = gunVelocity + direction.Normalized * speed; + var currentMapVelocity = Physics.GetMapLinearVelocity(uid, physics); + var finalLinear = physics.LinearVelocity + targetMapVelocity - currentMapVelocity; + Physics.SetLinearVelocity(physics, finalLinear); if (user != null) {