diff --git a/code/__HELPERS/angles.dm b/code/__HELPERS/angles.dm new file mode 100644 index 0000000000..aa39ee4f6e --- /dev/null +++ b/code/__HELPERS/angles.dm @@ -0,0 +1,39 @@ +/proc/get_projectile_angle(atom/source, atom/target) + var/sx = source.x * world.icon_size + var/sy = source.y * world.icon_size + var/tx = target.x * world.icon_size + var/ty = target.y * world.icon_size + var/atom/movable/AM + if(ismovable(source)) + AM = source + sx += AM.step_x + sy += AM.step_y + if(ismovable(target)) + AM = target + tx += AM.step_x + ty += AM.step_y + return SIMPLIFY_DEGREES(arctan(tx - sx, ty - sy)) + +/proc/Get_Angle(atom/movable/start,atom/movable/end)//For beams. + if(!start || !end) + return 0 + var/dy + var/dx + dy=(32*end.y+end.pixel_y)-(32*start.y+start.pixel_y) + 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 + +/proc/Get_Pixel_Angle(var/y, var/x)//for getting the angle when animating something's pixel_x and pixel_y + if(!y) + return (x>=0)?90:270 + .=arctan(x/y) + if(y<0) + .+=180 + else if(x<0) + .+=360 diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm index 13ac820778..08bcf58292 100644 --- a/code/__HELPERS/unsorted.dm +++ b/code/__HELPERS/unsorted.dm @@ -17,30 +17,6 @@ var/textb = copytext(HTMLstring, 6, 8) return rgb(255 - hex2num(textr), 255 - hex2num(textg), 255 - hex2num(textb)) -/proc/Get_Angle(atom/movable/start,atom/movable/end)//For beams. - if(!start || !end) - return 0 - var/dy - var/dx - dy=(32*end.y+end.pixel_y)-(32*start.y+start.pixel_y) - 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 - -/proc/Get_Pixel_Angle(var/y, var/x)//for getting the angle when animating something's pixel_x and pixel_y - if(!y) - return (x>=0)?90:270 - .=arctan(x/y) - if(y<0) - .+=180 - else if(x<0) - .+=360 - //Returns location. Returns null if no location was found. /proc/get_teleport_loc(turf/location,mob/target,distance = 1, density = FALSE, errorx = 0, errory = 0, eoffsetx = 0, eoffsety = 0) /* diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm index 2bda65c608..f7ef721cba 100644 --- a/code/modules/projectiles/projectile.dm +++ b/code/modules/projectiles/projectile.dm @@ -32,7 +32,6 @@ //Fired processing vars var/fired = FALSE //Have we been fired yet var/paused = FALSE //for suspending the projectile midair - var/last_projectile_move = 0 var/time_offset = 0 var/datum/point/vector/trajectory var/trajectory_ignore_forcemove = FALSE //instructs forceMove to NOT reset our trajectory to the new location! @@ -78,12 +77,16 @@ //Homing var/homing = FALSE var/atom/homing_target - var/homing_turn_speed = 10 //Angle per tick. + /// How fast the projectile turns towards its homing targets, in angle per second. + var/homing_turn_speed = 100 var/homing_inaccuracy_min = 0 //in pixels for these. offsets are set once when setting target. var/homing_inaccuracy_max = 0 var/homing_offset_x = 0 var/homing_offset_y = 0 + /// How many deciseconds are each hitscan movement considered + var/hitscan_movement_decisecond_equivalency = 0.1 + var/ignore_source_check = FALSE var/damage = 10 @@ -362,9 +365,10 @@ return PROCESS_KILL if(paused || !isturf(loc)) return + var/required_pixels = (pixels_per_second * (((SSprojectiles.flags & SS_TICKER)? (wait * world.tick_lag) : wait) * 0.1)) + pixels_tick_leftover - pixel_move(round(required_pixels, pixel_increment_amount), FALSE) pixels_tick_leftover = MODULUS(required_pixels, pixel_increment_amount) + pixel_move(FLOOR(required_pixels / pixel_increment_amount, pixel_increment_amount), FALSE) /obj/item/projectile/proc/fire(angle, atom/direct_target) if(fired_from) @@ -387,7 +391,7 @@ qdel(src) return var/turf/target = locate(clamp(starting + xo, 1, world.maxx), clamp(starting + yo, 1, world.maxy), starting.z) - setAngle(Get_Angle(src, target)) + setAngle(get_projectile_angle(src, target)) original_angle = Angle if(!nondirectional_sprite) var/matrix/M = new @@ -399,7 +403,6 @@ if(isnull(pixel_increment_amount)) pixel_increment_amount = SSprojectiles.global_pixel_increment_amount trajectory = new(starting.x, starting.y, starting.z, pixel_x, pixel_y, Angle, pixel_increment_amount) - last_projectile_move = world.time fired = TRUE if(hitscan) process_hitscan() @@ -476,20 +479,26 @@ if(!QDELETED(src)) qdel(src) return //Kill! - pixel_move(1, TRUE) + pixel_move(1, TRUE, hitscan_movement_decisecond_equivalency) /obj/item/projectile/proc/pixel_move(times, hitscanning = FALSE, trajectory_multiplier = 1) if(!loc || !trajectory) return - last_projectile_move = world.time if(!nondirectional_sprite && !hitscanning) var/matrix/M = new M.Turn(Angle) transform = M - if(homing) - process_homing() var/forcemoved = FALSE + var/turf/oldloc = loc + var/old_px = pixel_x + var/old_py = pixel_y for(var/i in 1 to times) + // HOMING START - Too expensive to proccall at this point. + if(homing_target) + // No datum/points, too expensive. + var/angle = closer_angle_difference(Angle, get_projectile_angle(src, homing_target)) + setAngle(Angle + clamp(angle, -homing_turn_speed, homing_turn_speed)) + // HOMING END trajectory.increment(trajectory_multiplier) var/turf/T = trajectory.return_turf() if(!istype(T)) @@ -513,20 +522,11 @@ if(QDELETED(src)) return if(!hitscanning && !forcemoved) - pixel_x = trajectory.return_px() - trajectory.mpx * times * trajectory_multiplier - pixel_y = trajectory.return_py() - trajectory.mpy * times * trajectory_multiplier - animate(src, pixel_x = trajectory.return_px(), pixel_y = trajectory.return_py(), time = 1, flags = ANIMATION_END_NOW) + pixel_x = ((oldloc.x - x) * world.icon_size) + old_px + pixel_y = ((oldloc.y - y) * world.icon_size) + old_py + animate(src, pixel_x = trajectory.return_px(), pixel_y = trajectory.return_py(), time = ((SSprojectiles.flags & SS_TICKER)? (SSprojectiles.wait * world.tick_lag) : SSprojectiles.wait), flags = ANIMATION_END_NOW) Range() -/obj/item/projectile/proc/process_homing() //may need speeding up in the future performance wise. - if(!homing_target) - return FALSE - var/datum/point/PT = RETURN_PRECISE_POINT(homing_target) - PT.x += clamp(homing_offset_x, 1, world.maxx) - PT.y += clamp(homing_offset_y, 1, world.maxy) - var/angle = closer_angle_difference(Angle, angle_between_points(RETURN_PRECISE_POINT(src), PT)) - setAngle(Angle + clamp(angle, -homing_turn_speed, homing_turn_speed)) - /obj/item/projectile/proc/set_homing_target(atom/A) if(!A || (!isturf(A) && !isturf(A.loc))) return FALSE @@ -575,7 +575,7 @@ if(targloc || !params) yo = targloc.y - curloc.y xo = targloc.x - curloc.x - setAngle(Get_Angle(src, targloc) + spread) + setAngle(get_projectile_angle(src, targloc) + spread) if(isliving(source) && params) var/list/calculated = calculate_projectile_angle_and_pixel_offsets(source, params) @@ -586,7 +586,7 @@ else if(targloc) yo = targloc.y - curloc.y xo = targloc.x - curloc.x - setAngle(Get_Angle(src, targloc) + spread) + setAngle(get_projectile_angle(src, targloc) + spread) else stack_trace("WARNING: Projectile [type] fired without either mouse parameters, or a target atom to aim at!") qdel(src) diff --git a/tgstation.dme b/tgstation.dme index dc02385b48..c594c0d07f 100755 --- a/tgstation.dme +++ b/tgstation.dme @@ -135,6 +135,7 @@ #include "code\__HELPERS\_lists.dm" #include "code\__HELPERS\_logging.dm" #include "code\__HELPERS\_string_lists.dm" +#include "code\__HELPERS\angles.dm" #include "code\__HELPERS\areas.dm" #include "code\__HELPERS\AStar.dm" #include "code\__HELPERS\cmp.dm"