Merge pull request #7366 from Citadel-Station-13/mirror-38933
[requires testmerge]upstream mirror - projectile pathing/hitscan lighting refactor
This commit is contained in:
@@ -4,3 +4,20 @@ PROCESSING_SUBSYSTEM_DEF(projectiles)
|
||||
stat_tag = "PP"
|
||||
flags = SS_NO_INIT|SS_TICKER
|
||||
var/global_max_tick_moves = 10
|
||||
var/global_pixel_speed = 2
|
||||
var/global_iterations_per_move = 16
|
||||
|
||||
/datum/controller/subsystem/processing/projectiles/proc/set_pixel_speed(new_speed)
|
||||
global_pixel_speed = new_speed
|
||||
for(var/i in processing)
|
||||
var/obj/item/projectile/P = i
|
||||
if(istype(P)) //there's non projectiles on this too.
|
||||
P.set_pixel_speed(new_speed)
|
||||
|
||||
/datum/controller/subsystem/processing/projectiles/vv_edit_var(var_name, var_value)
|
||||
switch(var_name)
|
||||
if(NAMEOF(src, global_pixel_speed))
|
||||
set_pixel_speed(var_value)
|
||||
return TRUE
|
||||
else
|
||||
return ..()
|
||||
|
||||
@@ -4,9 +4,6 @@
|
||||
icon_state = "nothing"
|
||||
layer = ABOVE_MOB_LAYER
|
||||
anchored = TRUE
|
||||
light_power = 1
|
||||
light_range = 2
|
||||
light_color = "#00ffff"
|
||||
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
|
||||
appearance_flags = 0
|
||||
|
||||
@@ -53,3 +50,7 @@
|
||||
for(var/i in 1 to increment)
|
||||
pixel_x += round((sin(angle_override)+16*sin(angle_override)*2), 1)
|
||||
pixel_y += round((cos(angle_override)+16*cos(angle_override)*2), 1)
|
||||
|
||||
/obj/effect/projectile_lighting/Initialize(mapload, color, range, intensity)
|
||||
. = ..()
|
||||
set_light(range, intensity, color)
|
||||
|
||||
@@ -1,10 +1,18 @@
|
||||
/proc/generate_tracer_between_points(datum/point/starting, datum/point/ending, beam_type, color, qdel_in = 5) //Do not pass z-crossing points as that will not be properly (and likely will never be properly until it's absolutely needed) supported!
|
||||
/proc/generate_tracer_between_points(datum/point/starting, datum/point/ending, beam_type, color, qdel_in = 5, light_range = 2, light_color_override, light_intensity = 1) //Do not pass z-crossing points as that will not be properly (and likely will never be properly until it's absolutely needed) supported!
|
||||
if(!istype(starting) || !istype(ending) || !ispath(beam_type))
|
||||
return
|
||||
var/datum/point/midpoint = point_midpoint_points(starting, ending)
|
||||
var/obj/effect/projectile/tracer/PB = new beam_type
|
||||
if(isnull(light_color_override))
|
||||
light_color_override = color
|
||||
PB.apply_vars(angle_between_points(starting, ending), midpoint.return_px(), midpoint.return_py(), color, pixel_length_between_points(starting, ending) / world.icon_size, midpoint.return_turf(), 0)
|
||||
. = PB
|
||||
if(light_range > 0 && light_intensity > 0)
|
||||
var/list/turf/line = getline(starting.return_turf(), ending.return_turf())
|
||||
for(var/i in line)
|
||||
var/turf/T = i
|
||||
QDEL_IN(new /obj/effect/projectile_lighting(T, light_color_override, light_range, light_intensity), qdel_in > 0? qdel_in : 5)
|
||||
line = null
|
||||
if(qdel_in)
|
||||
QDEL_IN(PB, qdel_in)
|
||||
|
||||
|
||||
@@ -565,10 +565,10 @@
|
||||
if(highlander && istype(gun))
|
||||
QDEL_LIST(gun.current_tracers)
|
||||
for(var/datum/point/p in beam_segments)
|
||||
gun.current_tracers += generate_tracer_between_points(p, beam_segments[p], tracer_type, color, 0)
|
||||
gun.current_tracers += generate_tracer_between_points(p, beam_segments[p], tracer_type, color, 0, hitscan_light_range, hitscan_light_color_override, hitscan_light_intensity)
|
||||
else
|
||||
for(var/datum/point/p in beam_segments)
|
||||
generate_tracer_between_points(p, beam_segments[p], tracer_type, color, duration)
|
||||
generate_tracer_between_points(p, beam_segments[p], tracer_type, color, duration, hitscan_light_range, hitscan_light_color_override, hitscan_light_intensity)
|
||||
if(cleanup)
|
||||
QDEL_LIST(beam_segments)
|
||||
beam_segments = null
|
||||
@@ -582,6 +582,9 @@
|
||||
nodamage = TRUE
|
||||
damage = 0
|
||||
constant_tracer = TRUE
|
||||
hitscan_light_range = 0
|
||||
hitscan_light_intensity = 0
|
||||
hitscan_light_color_override = "#99ff99"
|
||||
|
||||
/obj/item/projectile/beam/beam_rifle/hitscan/aiming_beam/prehit(atom/target)
|
||||
qdel(src)
|
||||
|
||||
@@ -36,7 +36,6 @@
|
||||
var/trajectory_ignore_forcemove = FALSE //instructs forceMove to NOT reset our trajectory to the new location!
|
||||
|
||||
var/speed = 0.8 //Amount of deciseconds it takes for projectile to travel
|
||||
var/pixel_speed = 32 //pixels per move - DO NOT FUCK WITH THIS UNLESS YOU ABSOLUTELY KNOW WHAT YOU ARE DOING OR UNEXPECTED THINGS /WILL/ HAPPEN!
|
||||
var/Angle = 0
|
||||
var/original_angle = 0 //Angle at firing
|
||||
var/nondirectional_sprite = FALSE //Set TRUE to prevent projectiles from having their sprites rotated based on firing angle
|
||||
@@ -55,6 +54,17 @@
|
||||
var/muzzle_type
|
||||
var/impact_type
|
||||
|
||||
//Fancy hitscan lighting effects!
|
||||
var/hitscan_light_intensity = 1.5
|
||||
var/hitscan_light_range = 0.75
|
||||
var/hitscan_light_color_override
|
||||
var/muzzle_flash_intensity = 3
|
||||
var/muzzle_flash_range = 1.5
|
||||
var/muzzle_flash_color_override
|
||||
var/impact_light_intensity = 3
|
||||
var/impact_light_range = 2
|
||||
var/impact_light_color_override
|
||||
|
||||
//Homing
|
||||
var/homing = FALSE
|
||||
var/atom/homing_target
|
||||
@@ -287,8 +297,8 @@
|
||||
var/datum/point/vector/current = trajectory
|
||||
if(!current)
|
||||
var/turf/T = get_turf(src)
|
||||
current = new(T.x, T.y, T.z, pixel_x, pixel_y, isnull(forced_angle)? Angle : forced_angle, pixel_speed)
|
||||
var/datum/point/vector/v = current.return_vector_after_increments(moves)
|
||||
current = new(T.x, T.y, T.z, pixel_x, pixel_y, isnull(forced_angle)? Angle : forced_angle, SSprojectiles.global_pixel_speed)
|
||||
var/datum/point/vector/v = current.return_vector_after_increments(moves * SSprojectiles.global_iterations_per_move)
|
||||
return v.return_turf()
|
||||
|
||||
/obj/item/projectile/proc/return_pathing_turfs_in_moves(moves, forced_angle)
|
||||
@@ -320,7 +330,7 @@
|
||||
time_offset += MODULUS(elapsed_time_deciseconds, speed)
|
||||
|
||||
for(var/i in 1 to required_moves)
|
||||
pixel_move(required_moves)
|
||||
pixel_move(1, FALSE)
|
||||
|
||||
/obj/item/projectile/proc/fire(angle, atom/direct_target)
|
||||
//If no angle needs to resolve it from xo/yo!
|
||||
@@ -351,14 +361,14 @@
|
||||
trajectory_ignore_forcemove = TRUE
|
||||
forceMove(starting)
|
||||
trajectory_ignore_forcemove = FALSE
|
||||
trajectory = new(starting.x, starting.y, starting.z, pixel_x, pixel_y, Angle, pixel_speed)
|
||||
trajectory = new(starting.x, starting.y, starting.z, pixel_x, pixel_y, Angle, SSprojectiles.global_pixel_speed)
|
||||
last_projectile_move = world.time
|
||||
fired = TRUE
|
||||
if(hitscan)
|
||||
process_hitscan()
|
||||
if(!(datum_flags & DF_ISPROCESSING))
|
||||
START_PROCESSING(SSprojectiles, src)
|
||||
pixel_move(1) //move it now!
|
||||
pixel_move(1, FALSE) //move it now!
|
||||
|
||||
/obj/item/projectile/proc/setAngle(new_angle) //wrapper for overrides.
|
||||
Angle = new_angle
|
||||
@@ -391,6 +401,20 @@
|
||||
|
||||
/obj/item/projectile/proc/before_z_change(atom/oldloc, atom/newloc)
|
||||
|
||||
/obj/item/projectile/vv_edit_var(var_name, var_value)
|
||||
switch(var_name)
|
||||
if(NAMEOF(src, Angle))
|
||||
setAngle(var_value)
|
||||
return TRUE
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/item/projectile/proc/set_pixel_speed(new_speed)
|
||||
if(trajectory)
|
||||
trajectory.set_speed(new_speed)
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/obj/item/projectile/proc/record_hitscan_start(datum/point/pcache)
|
||||
if(pcache)
|
||||
beam_segments = list()
|
||||
@@ -405,12 +429,14 @@
|
||||
stoplag(1)
|
||||
continue
|
||||
if(safety-- <= 0)
|
||||
qdel(src)
|
||||
stack_trace("WARNING: [type] projectile encountered infinite recursion during hitscanning in [__FILE__]/[__LINE__]!")
|
||||
if(loc)
|
||||
Collide(loc)
|
||||
if(!QDELETED(src))
|
||||
qdel(src)
|
||||
return //Kill!
|
||||
pixel_move(1, 1, TRUE)
|
||||
pixel_move(1, TRUE)
|
||||
|
||||
/obj/item/projectile/proc/pixel_move(moves, trajectory_multiplier = 1, hitscanning = FALSE)
|
||||
/obj/item/projectile/proc/pixel_move(trajectory_multiplier, hitscanning = FALSE)
|
||||
if(!loc || !trajectory)
|
||||
return
|
||||
last_projectile_move = world.time
|
||||
@@ -420,32 +446,36 @@
|
||||
transform = M
|
||||
if(homing)
|
||||
process_homing()
|
||||
trajectory.increment(trajectory_multiplier)
|
||||
var/turf/T = trajectory.return_turf()
|
||||
if(!istype(T))
|
||||
qdel(src)
|
||||
return
|
||||
if(T.z != loc.z)
|
||||
var/old = loc
|
||||
before_z_change(loc, T)
|
||||
trajectory_ignore_forcemove = TRUE
|
||||
forceMove(T)
|
||||
trajectory_ignore_forcemove = FALSE
|
||||
after_z_change(old, loc)
|
||||
if(!hitscanning)
|
||||
pixel_x = trajectory.return_px()
|
||||
pixel_y = trajectory.return_py()
|
||||
else
|
||||
step_towards(src, T)
|
||||
if(!hitscanning)
|
||||
pixel_x = trajectory.return_px() - trajectory.mpx * trajectory_multiplier
|
||||
pixel_y = trajectory.return_py() - trajectory.mpy * trajectory_multiplier
|
||||
if(!hitscanning)
|
||||
var/forcemoved = FALSE
|
||||
for(var/i in 1 to SSprojectiles.global_iterations_per_move)
|
||||
if(QDELETED(src))
|
||||
return
|
||||
trajectory.increment(trajectory_multiplier)
|
||||
var/turf/T = trajectory.return_turf()
|
||||
if(!istype(T))
|
||||
qdel(src)
|
||||
return
|
||||
if(T.z != loc.z)
|
||||
var/old = loc
|
||||
before_z_change(loc, T)
|
||||
trajectory_ignore_forcemove = TRUE
|
||||
forceMove(T)
|
||||
trajectory_ignore_forcemove = FALSE
|
||||
after_z_change(old, loc)
|
||||
if(!hitscanning)
|
||||
pixel_x = trajectory.return_px()
|
||||
pixel_y = trajectory.return_py()
|
||||
forcemoved = TRUE
|
||||
hitscan_last = loc
|
||||
else if(T != loc)
|
||||
step_towards(src, T)
|
||||
hitscan_last = loc
|
||||
if(can_hit_target(original, permutated))
|
||||
Collide(original)
|
||||
if(!hitscanning && !forcemoved)
|
||||
pixel_x = trajectory.return_px() - trajectory.mpx * trajectory_multiplier * SSprojectiles.global_iterations_per_move
|
||||
pixel_y = trajectory.return_py() - trajectory.mpy * trajectory_multiplier * SSprojectiles.global_iterations_per_move
|
||||
animate(src, pixel_x = trajectory.return_px(), pixel_y = trajectory.return_py(), time = 1, flags = ANIMATION_END_NOW)
|
||||
if(isturf(loc))
|
||||
hitscan_last = loc
|
||||
if(can_hit_target(original, permutated))
|
||||
Collide(original)
|
||||
Range()
|
||||
|
||||
/obj/item/projectile/proc/process_homing() //may need speeding up in the future performance wise.
|
||||
@@ -568,7 +598,7 @@
|
||||
return
|
||||
if(tracer_type)
|
||||
for(var/datum/point/p in beam_segments)
|
||||
generate_tracer_between_points(p, beam_segments[p], tracer_type, color, duration)
|
||||
generate_tracer_between_points(p, beam_segments[p], tracer_type, color, duration, hitscan_light_range, hitscan_light_color_override, hitscan_light_intensity)
|
||||
if(muzzle_type && duration > 0)
|
||||
var/datum/point/p = beam_segments[1]
|
||||
var/atom/movable/thing = new muzzle_type
|
||||
@@ -576,6 +606,8 @@
|
||||
var/matrix/M = new
|
||||
M.Turn(original_angle)
|
||||
thing.transform = M
|
||||
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)
|
||||
if(impacting && impact_type && duration > 0)
|
||||
var/datum/point/p = beam_segments[beam_segments[beam_segments.len]]
|
||||
@@ -584,6 +616,8 @@
|
||||
var/matrix/M = new
|
||||
M.Turn(Angle)
|
||||
thing.transform = M
|
||||
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)
|
||||
if(cleanup)
|
||||
cleanup_beam_segments()
|
||||
|
||||
Reference in New Issue
Block a user