Skip to content

Commit

Permalink
Refactors Get_Angle() and related procs (#5212)
Browse files Browse the repository at this point in the history
# About the pull request

To begin, fixes #5206.
`Get_Compass_Dir()` needed atoms with valid coordinates, but didn't test
for them. Adding some checks and `get_turf`s resolved that issue.

But then if `Get_Compass_Dir()` needed those checks, `Get_Angle()` did
too. And `get_angle()` (lowercase!). And `get_angle_raw()`. And half of
`Get_Compass_Dir()` was just duplicated code from `Get_Angle()`. And--

So I took inspiration from how TG and TGMC did it and refactored the
lot.

https://github.com/tgstation/tgstation/blob/32fb42d19e0c763f7e5e3dafb9844d0f05e86630/code/__HELPERS/maths.dm#L1-L17

https://github.com/tgstation/TerraGov-Marine-Corps/blob/3963b2d5b89dd60b88a7a1534ee77bd654abe953/code/__HELPERS/unsorted.dm#L99-L159

REMOVED:
- `get_angle_raw()` - never used
- `get_angle()` - used 3 places, identical use case to `Get_Angle()`
- `get_pixel_angle()` - used once, replaced by `delta_to_angle()`

ADDED:
- `angle_to_dir()` - pulls out the only unique thing `Get_Compass_Dir()`
actually did
- only difference from TGMC is it retains our angle breakpoints instead
of theirs
- `delta_to_angle()` - the only thing that actually calculates an angle,
uses the 2-argument version of `arctan()`

CHANGED:
- `Get_Angle()` - removed the `tile_bound` branch (never used), added
checks and `get_turf`s, position deltas passed to `delta_to_angle()`
- only difference from TGMC is it retains `return 0`s instead of
`CRASH`es, retains `get_pixel_position_x`/`y`, and passing to
`delta_to_angle()`
- `Get_Compass_Dir()` - gutted, now just a convenience function of
`Get_Angle()` piped into `angle_to_dir()`

<!-- Remove this text and explain what the purpose of your PR is.

Mention if you have tested your changes. If you changed a map, make sure
you used the mapmerge tool.
If this is an Issue Correction, you can type "Fixes Issue #169420" to
link the PR to the corresponding Issue number #169420.

Remember: something that is self-evident to you might not be to others.
Explain your rationale fully, even if you feel it goes without saying.
-->

# Explain why it's good for the game

Having multiple unused or barely used functions trying to do the same
thing makes code maintenance harder.
# Testing Photographs and Procedure
- [x] doesn't crash
- [x] security tuner APC detection works
- [x] SL/queen tracker works
- [x] bullets face the right way


# Changelog
:cl:
fix: Fixed security tuner not dispalying direction to room's APC
refactor: Refactored code handling angles
/:cl:
  • Loading branch information
Doubleumc committed Dec 22, 2023
1 parent de541db commit c0c308f
Show file tree
Hide file tree
Showing 6 changed files with 31 additions and 91 deletions.
44 changes: 1 addition & 43 deletions code/__HELPERS/#maths.dm
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,6 @@ GLOBAL_LIST_INIT(sqrtTable, list(1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4,

// MATH DEFINES

#define Atan2(x, y) (!x && !y ? 0 : \
(y >= 0 ? \
arccos(x / sqrt(x*x + y*y)) : \
-(arccos(x / sqrt(x*x + y*y))) \
) \
)
#define Ceiling(x) (-round(-x))
#define Clamp(val, min_val, max_val) (max(min_val, min(val, max_val)))
#define CLAMP01(x) (clamp(x, 0, 1))
Expand Down Expand Up @@ -78,7 +72,7 @@ GLOBAL_LIST_INIT(sqrtTable, list(1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4,

// Convert to polar coordinates
var/radius = sqrt(relative_coords[1]**2 + relative_coords[2]**2)
var/phi = Atan2(relative_coords[1], relative_coords[2])
var/phi = arctan(relative_coords[1], relative_coords[2])

// Rotate the point around the axis
phi += degrees
Expand Down Expand Up @@ -106,42 +100,6 @@ GLOBAL_LIST_INIT(sqrtTable, list(1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4,
return "[round((powerused * 0.000001),0.001)] MW"
return "[round((powerused * 0.000000001),0.0001)] GW"

///Calculate the angle between two movables and the west|east coordinate
/proc/get_angle(atom/movable/start, atom/movable/end)//For beams.
if(!start || !end)
return 0
var/dy =(32 * end.y + end.pixel_y) - (32 * start.y + start.pixel_y)
var/dx =(32 * end.x + end.pixel_x) - (32 * start.x + start.pixel_x)
if(!dy)
return (dx >= 0) ? 90 : 270
. = arctan(dx/dy)
if(dy < 0)
. += 180
else if(dx < 0)
. += 360

/// Angle between two arbitrary points and horizontal line same as [/proc/get_angle]
/proc/get_angle_raw(start_x, start_y, start_pixel_x, start_pixel_y, end_x, end_y, end_pixel_x, end_pixel_y)
var/dy = (32 * end_y + end_pixel_y) - (32 * start_y + start_pixel_y)
var/dx = (32 * end_x + end_pixel_x) - (32 * start_x + start_pixel_x)
if(!dy)
return (dx >= 0) ? 90 : 270
. = arctan(dx/dy)
if(dy < 0)
. += 180
else if(dx < 0)
. += 360

///for getting the angle when animating something's pixel_x and pixel_y
/proc/get_pixel_angle(y, x)
if(!y)
return (x >= 0) ? 90 : 270
. = arctan(x/y)
if(y < 0)
. += 180
else if(x < 0)
. += 360

/**
* Get a list of turfs in a line from `starting_atom` to `ending_atom`.
*
Expand Down
57 changes: 25 additions & 32 deletions code/__HELPERS/unsorted.dm
Original file line number Diff line number Diff line change
Expand Up @@ -99,38 +99,29 @@
var/atom/movable/big_subject = subject
. += (big_subject.bound_height - world.icon_size) / 2

/proc/Get_Angle(atom/start,atom/end, tile_bound = FALSE)//For beams.
if(!start || !end) return 0
if(!start.z || !end.z) return 0 //Atoms are not on turfs.
var/dx
var/dy
if(tile_bound)
dy=end.y-start.y
dx=end.x-start.x
else
dy = get_pixel_position_y(end) - get_pixel_position_y(start)
dx = get_pixel_position_x(end) - get_pixel_position_x(start)
if(!dy)
return (dx>=0)?90:270
.=arctan(dx/dy)
if(dy<0)
.+=180
else if(dx<0)
.+=360

/proc/Get_Compass_Dir(atom/start,atom/end)//get_dir() only considers an object to be north/south/east/west if there is zero deviation. This uses rounding instead.
if(!start || !end) return 0
if(!start.z || !end.z) return 0 //Atoms are not on turfs.
var/dy=end.y-start.y
var/dx=end.x-start.x
if(!dy)
return (dx>=0)?4:8
var/angle=arctan(dx/dy)
if(dy<0)
angle+=180
else if(dx<0)
angle+=360

/// Calculate the angle between two atoms. Uses north-clockwise convention: NORTH = 0, EAST = 90, etc.
/proc/Get_Angle(atom/start, atom/end)//For beams.
if(!start || !end)
return 0
if(!start.z)
start = get_turf(start)
if(!start)
return 0 //Atoms are not on turfs.
if(!end.z)
end = get_turf(end)
if(!end)
return 0 //Atoms are not on turfs.
var/dy = get_pixel_position_y(end) - get_pixel_position_y(start)
var/dx = get_pixel_position_x(end) - get_pixel_position_x(start)
return delta_to_angle(dx, dy)

/// Calculate the angle produced by a pair of x and y deltas. Uses north-clockwise convention: NORTH = 0, EAST = 90, etc.
/proc/delta_to_angle(dx, dy)
. = arctan(dy, dx) //y-then-x results in north-clockwise convention: https://en.wikipedia.org/wiki/Atan2#East-counterclockwise,_north-clockwise_and_south-clockwise_conventions,_etc.
if(. < 0)
. += 360

/proc/angle_to_dir(angle)
switch(angle) //diagonal directions get priority over straight directions in edge cases
if (22.5 to 67.5)
return NORTHEAST
Expand All @@ -151,6 +142,8 @@
else
return NORTH

/proc/Get_Compass_Dir(atom/start, atom/end)//get_dir() only considers an object to be north/south/east/west if there is zero deviation. This uses rounding instead.
return angle_to_dir(Get_Angle(get_turf(start), get_turf(end)))

// Among other things, used by flamethrower and boiler spray to calculate if flame/spray can pass through.
// Returns an atom for specific effects (primarily flames and acid spray) that damage things upon contact
Expand Down
2 changes: 1 addition & 1 deletion code/modules/cm_marines/radar.dm
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@

if(get_dist_euclidian(here_turf, target_turf) > 24)
userot = TRUE
rot = round(get_angle(here_turf, target_turf))
rot = round(Get_Angle(here_turf, target_turf))
else
if(target_turf.z > here_turf.z)
pointer="caret-up"
Expand Down
2 changes: 1 addition & 1 deletion code/modules/cm_marines/smartgun_mount.dm
Original file line number Diff line number Diff line change
Expand Up @@ -698,7 +698,7 @@
if(!istype(in_chamber, /obj/projectile))
return

var/angle = get_angle(T, U)
var/angle = Get_Angle(T, U)

if((dir == NORTH) && (angle > 180) && (abs(360 - angle) > shoot_degree)) // If north and shooting to the left, we do some extra math
return
Expand Down
15 changes: 2 additions & 13 deletions code/modules/projectiles/projectile.dm
Original file line number Diff line number Diff line change
Expand Up @@ -246,20 +246,9 @@
vis_source_pixel_x = process_start_pixel_x
vis_source_pixel_y = process_start_pixel_y

angle = 0 // Stolen from Get_Angle() basically
var/dx = p_x + aim_turf.x * 32 - source_turf.x * 32 // todo account for firer offsets
var/dy = p_y + aim_turf.y * 32 - source_turf.y * 32
if(!dy)
if(dx >= 0)
angle = 90
else
angle = 280
else
angle = arctan(dx/dy)
if(dy < 0)
angle += 180
else if(dx < 0)
angle += 360
angle = delta_to_angle(dx, dy)

/obj/projectile/process(delta_time)
. = PROC_RETURN_SLEEP
Expand Down Expand Up @@ -301,7 +290,7 @@

//Change the bullet angle to its visual path

var/vis_angle = get_pixel_angle(x = pixel_x_target - pixel_x_source, y = pixel_y_target - pixel_y_source) //naming vars because the proc takes y then x and that's WEIRD
var/vis_angle = delta_to_angle(pixel_x_target - pixel_x_source, pixel_y_target - pixel_y_source)
var/matrix/rotate = matrix()
rotate.Turn(vis_angle)
apply_transform(rotate)
Expand Down
2 changes: 1 addition & 1 deletion code/modules/vehicles/hardpoints/hardpoint.dm
Original file line number Diff line number Diff line change
Expand Up @@ -688,7 +688,7 @@
if(muzzle_turf == target_turf)
return FALSE

var/angle_diff = SIMPLIFY_DEGREES(dir2angle(dir) - get_angle(muzzle_turf, target_turf))
var/angle_diff = SIMPLIFY_DEGREES(dir2angle(dir) - Get_Angle(muzzle_turf, target_turf))
if(angle_diff < -180)
angle_diff += 360
else if(angle_diff > 180)
Expand Down

0 comments on commit c0c308f

Please sign in to comment.