diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index 5311d642a2..36ec5f00da 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -18,6 +18,7 @@ var/icon_scale = 1 // Used to scale icons up or down in update_transform(). var/old_x = 0 var/old_y = 0 + var/does_spin = TRUE // Does the atom spin when thrown (of course it does :P) /atom/movable/Destroy() . = ..() @@ -125,17 +126,23 @@ src.throw_impact(A,speed) /atom/movable/proc/throw_at(atom/target, range, speed, thrower) - if(!target || !src) return 0 + if(!target || !src) + return 0 + if(target.z != src.z) + return 0 //use a modified version of Bresenham's algorithm to get from the atom's current position to that of the target - src.throwing = 1 src.thrower = thrower src.throw_source = get_turf(src) //store the origin turf - + src.pixel_z = 0 if(usr) if(HULK in usr.mutations) src.throwing = 2 // really strong throw! + var/dist_travelled = 0 + var/dist_since_sleep = 0 + var/area/a = get_area(src.loc) + var/dist_x = abs(target.x - src.x) var/dist_y = abs(target.y - src.y) @@ -150,77 +157,57 @@ dy = NORTH else dy = SOUTH - var/dist_travelled = 0 - var/dist_since_sleep = 0 - var/area/a = get_area(src.loc) + + var/error + var/major_dir + var/major_dist + var/minor_dir + var/minor_dist if(dist_x > dist_y) - var/error = dist_x/2 - dist_y - - - - while(src && target &&((((src.x < target.x && dx == EAST) || (src.x > target.x && dx == WEST)) && dist_travelled < range) || (a && a.has_gravity == 0) || istype(src.loc, /turf/space)) && src.throwing && istype(src.loc, /turf)) - // only stop when we've gone the whole distance (or max throw range) and are on a non-space tile, or hit something, or hit the end of the map, or someone picks it up - if(error < 0) - var/atom/step = get_step(src, dy) - if(!step) // going off the edge of the map makes get_step return null, don't let things go off the edge - break - src.Move(step) - hit_check(speed) - error += dist_x - dist_travelled++ - dist_since_sleep++ - if(dist_since_sleep >= speed) - dist_since_sleep = 0 - sleep(1) - else - var/atom/step = get_step(src, dx) - if(!step) // going off the edge of the map makes get_step return null, don't let things go off the edge - break - src.Move(step) - hit_check(speed) - error -= dist_y - dist_travelled++ - dist_since_sleep++ - if(dist_since_sleep >= speed) - dist_since_sleep = 0 - sleep(1) - a = get_area(src.loc) + error = dist_x/2 - dist_y + major_dir = dx + major_dist = dist_x + minor_dir = dy + minor_dist = dist_y else - var/error = dist_y/2 - dist_x - while(src && target &&((((src.y < target.y && dy == NORTH) || (src.y > target.y && dy == SOUTH)) && dist_travelled < range) || (a && a.has_gravity == 0) || istype(src.loc, /turf/space)) && src.throwing && istype(src.loc, /turf)) - // only stop when we've gone the whole distance (or max throw range) and are on a non-space tile, or hit something, or hit the end of the map, or someone picks it up - if(error < 0) - var/atom/step = get_step(src, dx) - if(!step) // going off the edge of the map makes get_step return null, don't let things go off the edge - break - src.Move(step) - hit_check(speed) - error += dist_y - dist_travelled++ - dist_since_sleep++ - if(dist_since_sleep >= speed) - dist_since_sleep = 0 - sleep(1) - else - var/atom/step = get_step(src, dy) - if(!step) // going off the edge of the map makes get_step return null, don't let things go off the edge - break - src.Move(step) - hit_check(speed) - error -= dist_x - dist_travelled++ - dist_since_sleep++ - if(dist_since_sleep >= speed) - dist_since_sleep = 0 - sleep(1) + error = dist_y/2 - dist_x + major_dir = dy + major_dist = dist_y + minor_dir = dx + minor_dist = dist_x - a = get_area(src.loc) + while(src && target && src.throwing && istype(src.loc, /turf) \ + && ((abs(target.x - src.x)+abs(target.y - src.y) > 0 && dist_travelled < range) \ + || (a && a.has_gravity == 0) \ + || istype(src.loc, /turf/space))) + // only stop when we've gone the whole distance (or max throw range) and are on a non-space tile, or hit something, or hit the end of the map, or someone picks it up + var/atom/step + if(error >= 0) + step = get_step(src, major_dir) + error -= minor_dist + else + step = get_step(src, minor_dir) + error += major_dist + if(!step) // going off the edge of the map makes get_step return null, don't let things go off the edge + break + src.Move(step) + hit_check(speed) + dist_travelled++ + dist_since_sleep++ + if(dist_since_sleep >= speed) + dist_since_sleep = 0 + sleep(1) + a = get_area(src.loc) + // and yet it moves + if(src.does_spin) + src.SpinAnimation(speed = 4, loops = 1) //done throwing, either because it hit something or it finished moving if(isobj(src)) src.throw_impact(get_turf(src),speed) src.throwing = 0 src.thrower = null src.throw_source = null + fall() //Overlays