This commit is contained in:
kevinz000
2020-06-13 09:24:22 -07:00
parent b3b67a6a4f
commit 180b7d31d9
10 changed files with 88 additions and 45 deletions
@@ -45,13 +45,15 @@
desc = "A solid wall of slightly twitching tendrils with a reflective glow."
damaged_desc = "A wall of twitching tendrils with a reflective glow."
icon_state = "blob_glow"
flags_1 = CHECK_RICOCHET_1
point_return = 8
max_integrity = 100
brute_resist = 1
explosion_block = 2
/obj/structure/blob/shield/reflective/handle_ricochet(obj/item/projectile/P)
/obj/structure/blob/shield/reflective/check_projectile_ricochet(obj/item/projectile/P)
return PROJECTILE_RICOCHET_FORCE
/obj/structure/blob/shield/reflective/handle_projectile_ricochet(obj/item/projectile/P)
var/turf/p_turf = get_turf(P)
var/face_direction = get_dir(src, p_turf)
var/face_angle = dir2angle(face_direction)
@@ -61,4 +63,4 @@
var/new_angle_s = SIMPLIFY_DEGREES(face_angle + incidence_s)
P.setAngle(new_angle_s)
visible_message("<span class='warning'>[P] reflects off [src]!</span>")
return TRUE
return TRUE
+50 -27
View File
@@ -45,6 +45,8 @@
var/pixels_range_leftover = 0
/// "leftover" tick pixels and stuff yeah, so we don't round off things and introducing tracing inaccuracy.
var/pixels_tick_leftover = 0
/// Used to detect jumps in the middle of a pixel_move. Yes, this is ugly as sin code-wise but it works.
var/pixel_move_interrupted = FALSE
/// Pixels moved per second.
var/pixels_per_second = TILES_TO_PIXELS(12.5)
@@ -249,27 +251,54 @@
else
return 50 //if the projectile doesn't do damage, play its hitsound at 50% volume
/obj/item/projectile/proc/on_ricochet(atom/A)
return
/obj/item/projectile/proc/store_hitscan_collision(datum/point/pcache)
beam_segments[beam_index] = pcache
beam_index = pcache
beam_segments[beam_index] = null
/obj/item/projectile/Bump(atom/A)
var/turf/T = get_turf(A)
if(trajectory && check_ricochet(A) && check_ricochet_flag(A) && ricochets < ricochets_max)
var/datum/point/pcache = trajectory.copy_to()
ricochets++
if(A.handle_ricochet(src))
on_ricochet(A)
ignore_source_check = TRUE
decayedRange = max(0, decayedRange - reflect_range_decrease)
range = decayedRange
if(hitscan)
store_hitscan_collision(pcache)
/**
* Determines if we should ricochet off of something.
* By default, asks the thing if we should ricochet off it, but because we're called first, we get final say.
* Returns TRUE or FALSE.
*/
/obj/item/projectile/proc/check_ricochet(atom/A)
if(ricochets > ricochets_max) //safety thing, we don't care about what the other thing says about this.
return FALSE
var/them = A.check_projectile_ricochet(src)
switch(them)
if(PROJECTILE_RICOCHET_PREVENT)
return FALSE
if(PROJECTILE_RICOCHET_FORCE)
return TRUE
if(PROJECTILE_RICOCHET_NO)
return FALSE
if(PROJECTILE_RICOCHET_YES)
return prob(ricochet_chance)
else
CRASH("Invalid return value for projectile ricochet check from [A].")
/**
* Handles ricocheting off of something.
* By default, also asks the thing to handle it, but because we're called first, we get final say.
*/
/obj/item/projectile/proc/handle_ricochet(atom/A)
ricochets++
ignore_source_check = TRUE
decayedRange = max(0, decayedRange - reflect_range_decrease)
pixel_move_interrupted = TRUE
range = decayedRange
return A.handle_projectile_ricochet(src)
/obj/item/projectile/Bump(atom/A)
if(!trajectory)
return
var/turf/T = get_turf(A)
if(check_ricochet(A))
var/datum/point/pcache = trajectory.copy_to()
if(hitscan)
store_hitscan_collision(pcache)
handle_ricochet(A)
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.
if(def_zone && check_zone(def_zone) != BODY_ZONE_CHEST)
@@ -344,16 +373,6 @@
return T
//Returns null if nothing at all was found.
/obj/item/projectile/proc/check_ricochet()
if(prob(ricochet_chance))
return TRUE
return FALSE
/obj/item/projectile/proc/check_ricochet_flag(atom/A)
if(A.flags_1 & CHECK_RICOCHET_1)
return TRUE
return FALSE
/// one move is a tile.
/obj/item/projectile/proc/return_predicted_turf_after_moves(moves, forced_angle) //I say predicted because there's no telling that the projectile won't change direction/location in flight.
if(!trajectory && isnull(forced_angle) && isnull(Angle))
@@ -457,6 +476,7 @@
trajectory.initialize_location(target.x, target.y, target.z, 0, 0)
if(hitscan)
record_hitscan_start(RETURN_PRECISE_POINT(src))
pixel_move_interrupted = TRUE
if(zc)
after_z_change(old, target)
@@ -505,7 +525,7 @@
* The proc to make the projectile go, using a simulated pixel movement line trace.
* Note: deciseconds_equivalent is currently only used for homing, times is the number of times to move pixel_increment_amount.
* Trajectory multiplier directly modifies the factor of pixel_increment_amount to go per time.
* It's complicated, so probably just don'ot mess with this unless you know what you're doing.
* It's complicated, so probably just don't mess with this unless you know what you're doing.
*/
/obj/item/projectile/proc/pixel_move(times, hitscanning = FALSE, deciseconds_equivalent = world.tick_lag, trajectory_multiplier = 1, allow_animation = TRUE)
if(!loc || !trajectory)
@@ -515,6 +535,7 @@
M.Turn(Angle)
transform = M
var/forcemoved = FALSE
pixel_move_interrupted = FALSE // reset that
var/turf/oldloc = loc
var/old_px = pixel_x
var/old_py = pixel_y
@@ -550,7 +571,9 @@
if(!--safety)
CRASH("[type] took too long (allowed: [CEILING(pixel_increment_amount/world.icon_size,1)*2] moves) to get to its location.")
step_towards(src, T)
if(QDELETED(src))
if(QDELETED(src) || pixel_move_interrupted) // this doesn't take into account with pixel_move_interrupted the portion of the move cut off by any forcemoves, but we're opting to ignore that for now
// the reason is the entire point of moving to pixel speed rather than tile speed is smoothness, which will be crucial when pixel movement is done in the future
// reverting back to tile is more or less the only way of fixing this issue.
return
pixels_range_leftover += pixel_increment_amount
if(pixels_range_leftover > world.icon_size)