diff --git a/code/datums/martial/sleeping_carp.dm b/code/datums/martial/sleeping_carp.dm index 3d7de61e753..cd5f87775ba 100644 --- a/code/datums/martial/sleeping_carp.dm +++ b/code/datums/martial/sleeping_carp.dm @@ -113,7 +113,7 @@ A.visible_message("[A] effortlessly swats the projectile aside! They can block bullets with their bare hands!", "You deflect the projectile!") playsound(get_turf(A), pick('sound/weapons/bulletflyby.ogg', 'sound/weapons/bulletflyby2.ogg', 'sound/weapons/bulletflyby3.ogg'), 75, TRUE) P.firer = A - P.setAngle(rand(0, 360))//SHING + P.set_angle(rand(0, 360))//SHING return BULLET_ACT_FORCE_PIERCE return BULLET_ACT_HIT diff --git a/code/datums/position_point_vector.dm b/code/datums/position_point_vector.dm index 66073656a01..0438d514195 100644 --- a/code/datums/position_point_vector.dm +++ b/code/datums/position_point_vector.dm @@ -11,8 +11,8 @@ /proc/point_midpoint_points(datum/point/a, datum/point/b) //Obviously will not support multiZ calculations! Same for the two below. var/datum/point/P = new - P.x = a.x + (b.x - a.x) / 2 - P.y = a.y + (b.y - a.y) / 2 + P.x = a.x + (b.x - a.x) * 0.5 + P.y = a.y + (b.y - a.y) * 0.5 P.z = a.z return P @@ -22,7 +22,8 @@ /proc/angle_between_points(datum/point/a, datum/point/b) return ATAN2((b.y - a.y), (b.x - a.x)) -/datum/position //For positions with map x/y/z and pixel x/y so you don't have to return lists. Could use addition/subtraction in the future I guess. +/// For positions with map x/y/z and pixel x/y so you don't have to return lists. Could use addition/subtraction in the future I guess. +/datum/position var/x = 0 var/y = 0 var/z = 0 @@ -66,7 +67,8 @@ /datum/position/proc/return_point() return new /datum/point(src) -/datum/point //A precise point on the map in absolute pixel locations based on world.icon_size. Pixels are FROM THE EDGE OF THE MAP! +/// A precise point on the map in absolute pixel locations based on world.icon_size. Pixels are FROM THE EDGE OF THE MAP! +/datum/point var/x = 0 var/y = 0 var/z = 0 @@ -80,7 +82,8 @@ p.z = z return p -/datum/point/New(_x, _y, _z, _pixel_x = 0, _pixel_y = 0) //first argument can also be a /datum/position or /atom. +/// First argument can also be a /datum/position or /atom. +/datum/point/New(_x, _y, _z, _pixel_x = 0, _pixel_y = 0) if(istype(_x, /datum/position)) var/datum/position/P = _x _x = P.x @@ -99,9 +102,9 @@ /datum/point/proc/initialize_location(tile_x, tile_y, tile_z, p_x = 0, p_y = 0) if(!isnull(tile_x)) - x = ((tile_x - 1) * world.icon_size) + world.icon_size / 2 + p_x + 1 + x = ((tile_x - 1) * world.icon_size) + world.icon_size * 0.5 + p_x + 1 if(!isnull(tile_y)) - y = ((tile_y - 1) * world.icon_size) + world.icon_size / 2 + p_y + 1 + y = ((tile_y - 1) * world.icon_size) + world.icon_size * 0.5 + p_y + 1 if(!isnull(tile_z)) z = tile_z @@ -130,10 +133,13 @@ return MODULUS(y, world.icon_size) - 16 - 1 /datum/point/vector - var/speed = 32 //pixels per iteration + /// Pixels per iteration + var/speed = 32 var/iteration = 0 var/angle = 0 - var/mpx = 0 //calculated x/y movement amounts to prevent having to do trig every step. + /// Calculated x movement amounts to prevent having to do trig every step. + var/mpx = 0 + /// Calculated y movement amounts to prevent having to do trig every step. var/mpy = 0 var/starting_x = 0 //just like before, pixels from EDGE of map! This is set in initialize_location(). var/starting_y = 0 @@ -151,6 +157,15 @@ starting_y = y starting_z = z +/// Same effect as initiliaze_location, but without setting the starting_x/y/z +/datum/point/vector/proc/set_location(tile_x, tile_y, tile_z, p_x = 0, p_y = 0) + if(!isnull(tile_x)) + x = ((tile_x - 1) * world.icon_size) + world.icon_size * 0.5 + p_x + 1 + if(!isnull(tile_y)) + y = ((tile_y - 1) * world.icon_size) + world.icon_size * 0.5 + p_y + 1 + if(!isnull(tile_z)) + z = tile_z + /datum/point/vector/copy_to(datum/point/vector/v = new) ..(v) v.speed = speed @@ -168,7 +183,8 @@ speed = pixel_speed set_angle(new_angle) -/datum/point/vector/proc/set_angle(new_angle) //calculations use "byond angle" where north is 0 instead of 90, and south is 180 instead of 270. +/// Calculations use "byond angle" where north is 0 instead of 90, and south is 180 instead of 270. +/datum/point/vector/proc/set_angle(new_angle) if(isnull(angle)) return angle = new_angle diff --git a/code/game/atoms.dm b/code/game/atoms.dm index 2239e587f3a..d2b8192da54 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -303,7 +303,7 @@ if((a_incidence_s < 90 && a_incidence_s < 90 - P.ricochet_incidence_leeway) || (a_incidence_s > 270 && a_incidence_s -270 > P.ricochet_incidence_leeway)) return FALSE var/new_angle_s = SIMPLIFY_DEGREES(face_angle + incidence_s) - P.setAngle(new_angle_s) + P.set_angle(new_angle_s) return TRUE ///Can the mover object pass this atom, while heading for the target turf diff --git a/code/game/objects/structures/reflector.dm b/code/game/objects/structures/reflector.dm index 774be92e78d..229d663b6c0 100644 --- a/code/game/objects/structures/reflector.dm +++ b/code/game/objects/structures/reflector.dm @@ -26,9 +26,9 @@ add_overlay(deflector_overlay) if(rotation_angle == -1) - setAngle(dir2angle(dir)) + set_angle(dir2angle(dir)) else - setAngle(rotation_angle) + set_angle(rotation_angle) if(admin) can_rotate = FALSE @@ -43,7 +43,7 @@ else . += "Use screwdriver to unlock the rotation." -/obj/structure/reflector/proc/setAngle(new_angle) +/obj/structure/reflector/proc/set_angle(new_angle) if(can_rotate) rotation_angle = new_angle if(deflector_overlay) @@ -160,7 +160,7 @@ if(!user.canUseTopic(src, BE_CLOSE, NO_DEXTERITY, FALSE, !iscyborg(user))) return if(!isnull(new_angle)) - setAngle(SIMPLIFY_DEGREES(new_angle)) + set_angle(SIMPLIFY_DEGREES(new_angle)) return TRUE /obj/structure/reflector/AltClick(mob/user) @@ -195,7 +195,7 @@ if(abs(incidence) > 90 && abs(incidence) < 270) return FALSE var/new_angle = SIMPLIFY_DEGREES(rotation_angle + incidence) - P.setAngle(new_angle) + P.set_angle_centered(new_angle) return ..() //DOUBLE @@ -219,7 +219,7 @@ /obj/structure/reflector/double/auto_reflect(obj/projectile/P, pdir, turf/ploc, pangle) var/incidence = GET_ANGLE_OF_INCIDENCE(rotation_angle, (P.Angle + 180)) var/new_angle = SIMPLIFY_DEGREES(rotation_angle + incidence) - P.setAngle(new_angle) + P.set_angle_centered(new_angle) return ..() //BOX @@ -241,7 +241,7 @@ anchored = TRUE /obj/structure/reflector/box/auto_reflect(obj/projectile/P) - P.setAngle(rotation_angle) + P.set_angle_centered(rotation_angle) return ..() /obj/structure/reflector/ex_act() diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index 1eb236b2243..5f52c270428 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -90,7 +90,7 @@ var/new_angle_s = P.Angle + rand(120,240) while(new_angle_s > 180) // Translate to regular projectile degrees new_angle_s -= 360 - P.setAngle(new_angle_s) + P.set_angle(new_angle_s) return BULLET_ACT_FORCE_PIERCE // complete projectile permutation diff --git a/code/modules/mob/living/simple_animal/constructs.dm b/code/modules/mob/living/simple_animal/constructs.dm index 554d925bced..ad52620fa0f 100644 --- a/code/modules/mob/living/simple_animal/constructs.dm +++ b/code/modules/mob/living/simple_animal/constructs.dm @@ -170,7 +170,7 @@ var/new_angle_s = P.Angle + rand(120,240) while(new_angle_s > 180) // Translate to regular projectile degrees new_angle_s -= 360 - P.setAngle(new_angle_s) + P.set_angle(new_angle_s) return BULLET_ACT_FORCE_PIERCE // complete projectile permutation diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm index 35b6436d7ab..d83c40bf6a0 100644 --- a/code/modules/projectiles/projectile.dm +++ b/code/modules/projectiles/projectile.dm @@ -317,11 +317,11 @@ unlucky_sob = L if(unlucky_sob) - setAngle(Get_Angle(src, unlucky_sob.loc)) + set_angle(Get_Angle(src, unlucky_sob.loc)) -/obj/projectile/proc/store_hitscan_collision(datum/point/pcache) - beam_segments[beam_index] = pcache - beam_index = pcache +/obj/projectile/proc/store_hitscan_collision(datum/point/point_cache) + beam_segments[beam_index] = point_cache + beam_index = point_cache beam_segments[beam_index] = null /obj/projectile/Bump(atom/A) @@ -347,7 +347,7 @@ return FALSE if(impacted[A]) // NEVER doublehit return FALSE - var/datum/point/pcache = trajectory.copy_to() + var/datum/point/point_cache = trajectory.copy_to() var/turf/T = get_turf(A) if(ricochets < ricochets_max && check_ricochet_flag(A) && check_ricochet(A)) ricochets++ @@ -360,7 +360,7 @@ damage *= ricochet_decay_damage range = decayedRange if(hitscan) - store_hitscan_collision(pcache) + store_hitscan_collision(point_cache) return TRUE var/distance = get_dist(T, starting) // Get the distance between the turf shot from and the mob we hit and use that for the calculations. @@ -663,9 +663,9 @@ if(QDELETED(src)) return if(isnum(angle)) - setAngle(angle) + set_angle(angle) if(spread) - setAngle(Angle + ((rand() - 0.5) * spread)) + set_angle(Angle + ((rand() - 0.5) * spread)) var/turf/starting = get_turf(src) if(isnull(Angle)) //Try to resolve through offsets if there's no angle set. if(isnull(xo) || isnull(yo)) @@ -673,12 +673,12 @@ 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)) + set_angle(Get_Angle(src, target)) original_angle = Angle if(!nondirectional_sprite) - var/matrix/M = new - M.Turn(Angle) - transform = M + var/matrix/matrix = new + matrix.Turn(Angle) + transform = matrix trajectory_ignore_forcemove = TRUE forceMove(starting) trajectory_ignore_forcemove = FALSE @@ -692,23 +692,43 @@ START_PROCESSING(SSprojectiles, src) pixel_move(1, FALSE) //move it now! -/obj/projectile/proc/setAngle(new_angle) //wrapper for overrides. +/obj/projectile/proc/set_angle(new_angle) //wrapper for overrides. Angle = new_angle if(!nondirectional_sprite) - var/matrix/M = new - M.Turn(Angle) - transform = M + var/matrix/matrix = new + matrix.Turn(Angle) + transform = matrix if(trajectory) trajectory.set_angle(new_angle) if(fired && hitscan && isloc(loc) && (loc != last_angle_set_hitscan_store)) last_angle_set_hitscan_store = loc - var/datum/point/pcache = new (src) - var/list/coordinates = trajectory.return_coordinates() - pcache.initialize_location(coordinates[1], coordinates[2], coordinates[3]) // Take the center of the hitscan collision tile, so it looks good on reflector boxes and the like - trajectory.initialize_location(coordinates[1], coordinates[2], coordinates[3]) // Sets the trajectory to it as well, to prevent a strange visual bug - store_hitscan_collision(pcache) + var/datum/point/point_cache = new (src) + point_cache = trajectory.copy_to() + store_hitscan_collision(point_cache) return TRUE +/// Same as set_angle, but the reflection continues from the center of the object that reflects it instead of the side +/obj/projectile/proc/set_angle_centered(new_angle) + Angle = new_angle + if(!nondirectional_sprite) + var/matrix/matrix = new + matrix.Turn(Angle) + transform = matrix + if(trajectory) + trajectory.set_angle(new_angle) + + var/list/coordinates = trajectory.return_coordinates() + trajectory.set_location(coordinates[1], coordinates[2], coordinates[3]) // Sets the trajectory to the center of the tile it bounced at + + if(fired && hitscan && isloc(loc) && (loc != last_angle_set_hitscan_store)) // Handles hitscan projectiles + last_angle_set_hitscan_store = loc + var/datum/point/point_cache = new (src) + point_cache.initialize_location(coordinates[1], coordinates[2], coordinates[3]) // Take the center of the hitscan collision tile + store_hitscan_collision(point_cache) + return TRUE + + + /obj/projectile/forceMove(atom/target) if(!isloc(target) || !isloc(loc) || !z) return ..() @@ -735,7 +755,7 @@ /obj/projectile/vv_edit_var(var_name, var_value) switch(var_name) if(NAMEOF(src, Angle)) - setAngle(var_value) + set_angle(var_value) return TRUE else return ..() @@ -746,10 +766,10 @@ return TRUE return FALSE -/obj/projectile/proc/record_hitscan_start(datum/point/pcache) - if(pcache) +/obj/projectile/proc/record_hitscan_start(datum/point/point_cache) + if(point_cache) beam_segments = list() - beam_index = pcache + beam_index = point_cache beam_segments[beam_index] = null //record start. /obj/projectile/proc/process_hitscan() @@ -772,9 +792,9 @@ return last_projectile_move = world.time if(!nondirectional_sprite && !hitscanning) - var/matrix/M = new - M.Turn(Angle) - transform = M + var/matrix/matrix = new + matrix.Turn(Angle) + transform = matrix if(homing) process_homing() var/forcemoved = FALSE @@ -814,7 +834,7 @@ 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)) + set_angle(Angle + clamp(angle, -homing_turn_speed, homing_turn_speed)) /obj/projectile/proc/set_homing_target(atom/A) if(!A || (!isturf(A) && !isturf(A.loc))) @@ -840,18 +860,18 @@ if(targloc || !params) yo = targloc.y - curloc.y xo = targloc.x - curloc.x - setAngle(Get_Angle(src, targloc) + spread) + set_angle(Get_Angle(src, targloc) + spread) if(isliving(source) && params) var/list/calculated = calculate_projectile_angle_and_pixel_offsets(source, params) p_x = calculated[2] p_y = calculated[3] - setAngle(calculated[1] + spread) + set_angle(calculated[1] + spread) else if(targloc) yo = targloc.y - curloc.y xo = targloc.x - curloc.x - setAngle(Get_Angle(src, targloc) + spread) + set_angle(Get_Angle(src, targloc) + spread) else stack_trace("WARNING: Projectile [type] fired without either mouse parameters, or a target atom to aim at!") qdel(src) @@ -902,8 +922,8 @@ /obj/projectile/proc/finalize_hitscan_and_generate_tracers(impacting = TRUE) if(trajectory && beam_index) - var/datum/point/pcache = trajectory.copy_to() - beam_segments[beam_index] = pcache + var/datum/point/point_cache = trajectory.copy_to() + beam_segments[beam_index] = point_cache generate_hitscan_tracers(null, null, impacting) /obj/projectile/proc/generate_hitscan_tracers(cleanup = TRUE, duration = 3, impacting = TRUE) @@ -917,9 +937,9 @@ var/datum/point/p = beam_segments[1] var/atom/movable/thing = new muzzle_type p.move_atom_to_src(thing) - var/matrix/M = new - M.Turn(original_angle) - thing.transform = M + var/matrix/matrix = new + matrix.Turn(original_angle) + thing.transform = matrix thing.color = color thing.set_light(muzzle_flash_range, muzzle_flash_intensity, muzzle_flash_color_override? muzzle_flash_color_override : color) QDEL_IN(thing, duration) @@ -927,9 +947,9 @@ var/datum/point/p = beam_segments[beam_segments[beam_segments.len]] var/atom/movable/thing = new impact_type p.move_atom_to_src(thing) - var/matrix/M = new - M.Turn(Angle) - thing.transform = M + var/matrix/matrix = new + matrix.Turn(Angle) + thing.transform = matrix thing.color = color thing.set_light(impact_light_range, impact_light_intensity, impact_light_color_override? impact_light_color_override : color) QDEL_IN(thing, duration)