From ee30451d9af68967d4455972806a425eeb5c0b21 Mon Sep 17 00:00:00 2001 From: VMSolidus Date: Sun, 30 Nov 2025 06:18:35 -0500 Subject: [PATCH] Fix Ship Acceleration (Without Byond 516) (#21625) This PR fixes some math errors in Overmap Ship math that were causing ships to have entirely wrong acceleration when moving in any diagonal direction. It was off by about 30% in the diagonal directions. This is also an alternate PR to #21620 which doesn't require changing the repo to Byond 516 I hate this so much more than the other PR, I really badly need Vectors for doing what I do, and to do stuff like this PR so much better. --- code/__HELPERS/type2type.dm | 15 +++++++ code/modules/overmap/ships/ship.dm | 39 ++++++++++++------- html/changelogs/hellfirejag-fix-ship-math.yml | 4 ++ 3 files changed, 45 insertions(+), 13 deletions(-) create mode 100644 html/changelogs/hellfirejag-fix-ship-math.yml diff --git a/code/__HELPERS/type2type.dm b/code/__HELPERS/type2type.dm index 006c6a516f7..4bb4860e797 100644 --- a/code/__HELPERS/type2type.dm +++ b/code/__HELPERS/type2type.dm @@ -109,6 +109,21 @@ if (degree < 315) return WEST return NORTH|WEST +/** + * Returns the trigonometric degrees of a given direction. + * Use this instead of dir2angle if you're using cos() and sin() to generate a velocity or acceleration vector. + */ +/proc/dir2degree(var/D) + switch (D) // Starting from 0 on a Unit Circle + if (EAST) return 0 + if (NORTHEAST) return 45 + if (NORTH) return 90 + if (NORTHWEST) return 135 + if (WEST) return 180 + if (SOUTHWEST) return 225 + if (SOUTH) return 270 + if (SOUTHEAST) return 315 + // Returns the north-zero clockwise angle in degrees, given a direction /proc/dir2angle(var/D) switch (D) diff --git a/code/modules/overmap/ships/ship.dm b/code/modules/overmap/ships/ship.dm index 1f4de2c40ea..d7f47ac5604 100644 --- a/code/modules/overmap/ships/ship.dm +++ b/code/modules/overmap/ships/ship.dm @@ -199,25 +199,38 @@ return round(num_burns/burns_per_grid) /obj/effect/overmap/visitable/ship/proc/decelerate() - if(((speed[1]) || (speed[2])) && can_burn()) - if (speed[1]) - adjust_speed(-SIGN(speed[1]) * min(get_burn_acceleration(),abs(speed[1])), 0) - if (speed[2]) - adjust_speed(0, -SIGN(speed[2]) * min(get_burn_acceleration(),abs(speed[2]))) + if(can_burn()) + // Pythagorean theorem gives us the magnitude of the ship's velocity, which is always an absolute value. + // This is also the mathematical definition for Vector.size + var/magnitude_velocity = ((speed[1] ** 2) + (speed[2] **2)) ** (1/2) + + // Get the magnitude of our desired change in velocity + var/alpha = min(get_burn_acceleration(), magnitude_velocity) + + // First we "Normalize" the current velocity to get the direction without a distance + // Then we take the exact negative of this direction to get its true opposite + // And finally multiply by the magnitude of our desired delta_v to get the true delta_v + var/delta_x = -(speed[1] / magnitude_velocity) * alpha + var/delta_y = -(speed[2] / magnitude_velocity) * alpha + + adjust_speed(delta_x, delta_y) last_burn = world.time /obj/effect/overmap/visitable/ship/proc/accelerate(direction, accel_limit) if(can_burn()) last_burn = world.time + + // Get our "Alpha" value as the ship's desired acceleration (change in Velocity) var/acceleration = min(get_burn_acceleration(), accel_limit) - if(direction & EAST) - adjust_speed(acceleration, 0) - if(direction & WEST) - adjust_speed(-acceleration, 0) - if(direction & NORTH) - adjust_speed(0, acceleration) - if(direction & SOUTH) - adjust_speed(0, -acceleration) + + // Convert from cardinal directions to an angle (in degrees) + // !This is absolutely terrible and should at some point be swapped to Radians + // !But for now it's "Okay" until overmap ships are updated to work on time differentials properly. + var/theta = dir2degree(direction) + + // This comes from the actual definition of a Vector2d, , where theta is an Angle, and A is a constant multiplier that traditionally represents distance. + // In this case A is our DeltaVelocity, or Acceleration. + adjust_speed(acceleration * cos(theta), acceleration * sin(theta)) /obj/effect/overmap/visitable/ship/process() ..() diff --git a/html/changelogs/hellfirejag-fix-ship-math.yml b/html/changelogs/hellfirejag-fix-ship-math.yml new file mode 100644 index 00000000000..ad2bedecf90 --- /dev/null +++ b/html/changelogs/hellfirejag-fix-ship-math.yml @@ -0,0 +1,4 @@ +author: Hellfirejag +delete-after: True +changes: + - bugfix: "Fixed math errors in overmap ship math that caused severe precision errors when accelerating diagonally."