From 4eaa3a22c286a44590c789fef0f1d12b96a7c72f Mon Sep 17 00:00:00 2001 From: kevinz000 <2003111+kevinz000@users.noreply.github.com> Date: Fri, 20 Mar 2020 18:45:34 -0700 Subject: [PATCH] fixes beam rifles and some micro optimizations to projectiles and readds the chameleon gun for debugging (#11528) * wew * ah * k * k * faster --- .../projectiles/projectile_effects.dm | 4 +- .../temporary_visuals/projectiles/tracer.dm | 16 +- .../projectiles/guns/misc/beam_rifle.dm | 37 ++-- .../projectiles/guns/misc/chameleon.dm | 169 ++++++++++++++++++ code/modules/projectiles/projectile.dm | 17 +- tgstation.dme | 1 + 6 files changed, 204 insertions(+), 40 deletions(-) create mode 100644 code/modules/projectiles/guns/misc/chameleon.dm diff --git a/code/game/objects/effects/temporary_visuals/projectiles/projectile_effects.dm b/code/game/objects/effects/temporary_visuals/projectiles/projectile_effects.dm index 49cdc3667c..9f2530e43e 100644 --- a/code/game/objects/effects/temporary_visuals/projectiles/projectile_effects.dm +++ b/code/game/objects/effects/temporary_visuals/projectiles/projectile_effects.dm @@ -52,9 +52,7 @@ pixel_y += round((cos(angle_override)+16*cos(angle_override)*2), 1) /obj/effect/projectile_lighting - var/owner -/obj/effect/projectile_lighting/Initialize(mapload, color, range, intensity, owner_key) +/obj/effect/projectile_lighting/Initialize(mapload, color, range, intensity) . = ..() set_light(range, intensity, color) - owner = owner_key diff --git a/code/game/objects/effects/temporary_visuals/projectiles/tracer.dm b/code/game/objects/effects/temporary_visuals/projectiles/tracer.dm index bd2c6c6e87..eb50ae43a7 100644 --- a/code/game/objects/effects/temporary_visuals/projectiles/tracer.dm +++ b/code/game/objects/effects/temporary_visuals/projectiles/tracer.dm @@ -1,4 +1,4 @@ -/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, instance_key) //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, list/turfs) //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) @@ -9,17 +9,15 @@ . = PB if(light_range > 0 && light_intensity > 0) var/list/turf/line = getline(starting.return_turf(), ending.return_turf()) - tracing_line: - for(var/i in line) - var/turf/T = i - for(var/obj/effect/projectile_lighting/PL in T) - if(PL.owner == instance_key) - continue tracing_line - QDEL_IN(new /obj/effect/projectile_lighting(T, light_color_override, light_range, light_intensity, instance_key), qdel_in > 0? qdel_in : 5) + for(var/i in line) + if(turfs[i]) + continue + turfs[i] = TRUE + QDEL_IN(new /obj/effect/projectile_lighting(i, light_color_override, light_range, light_intensity), qdel_in > 0? qdel_in : 5) line = null if(qdel_in) QDEL_IN(PB, qdel_in) - +d /obj/effect/projectile/tracer name = "beam" icon = 'icons/obj/projectiles_tracer.dmi' diff --git a/code/modules/projectiles/guns/misc/beam_rifle.dm b/code/modules/projectiles/guns/misc/beam_rifle.dm index c295adde60..f230dc7fea 100644 --- a/code/modules/projectiles/guns/misc/beam_rifle.dm +++ b/code/modules/projectiles/guns/misc/beam_rifle.dm @@ -181,13 +181,6 @@ listeningTo = null return ..() -/obj/item/gun/energy/beam_rifle/emp_act(severity) - . = ..() - if(. & EMP_PROTECT_SELF) - return - chambered = null - recharge_newshot() - /obj/item/gun/energy/beam_rifle/proc/aiming_beam(force_update = FALSE) var/diff = abs(aiming_lastangle - lastangle) if(!check_user()) @@ -302,7 +295,7 @@ if(istype(object, /obj/screen) && !istype(object, /obj/screen/click_catcher)) return process_aim() - if(aiming_time_left <= aiming_time_fire_threshold && check_user() && ((lastfire + delay) <= world.time)) + if(fire_check()) sync_ammo() do_fire(M.client.mouseObject, M, FALSE, M.client.mouseParams, M.zone_selected) stop_aiming() @@ -310,11 +303,16 @@ return ..() /obj/item/gun/energy/beam_rifle/do_fire(atom/target, mob/living/user, message = TRUE, params, zone_override = "", bonus_spread = 0) + if(!fire_check()) + return . = ..() if(.) lastfire = world.time stop_aiming() +/obj/item/gun/energy/beam_rifle/proc/fire_check() + return (aiming_time_left <= aiming_time_fire_threshold) && check_user() && ((lastfire + delay) <= world.time) + /obj/item/gun/energy/beam_rifle/proc/sync_ammo() for(var/obj/item/ammo_casing/energy/beam_rifle/AC in contents) AC.sync_stats() @@ -531,21 +529,15 @@ tracer_type = /obj/effect/projectile/tracer/tracer/beam_rifle var/constant_tracer = FALSE -/obj/item/projectile/beam/beam_rifle/hitscan/generate_hitscan_tracers(cleanup = TRUE, duration = 5, impacting = TRUE, highlander) - set waitfor = FALSE - if(isnull(highlander)) - highlander = constant_tracer - 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, hitscan_light_range, hitscan_light_color_override, hitscan_light_intensity) +/obj/item/projectile/beam/beam_rifle/hitscan/generate_hitscan_tracers(cleanup = TRUE, duration = 5, impacting = TRUE, generation, highlander = constant_tracer) + if(!highlander) + return ..() else - for(var/datum/point/p in beam_segments) - 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 - QDEL_NULL(beam_index) + duration = 0 + . = ..() + if(!generation) //first one + QDEL_LIST(gun.current_tracers) + gun.current_tracers += . /obj/item/projectile/beam/beam_rifle/hitscan/aiming_beam tracer_type = /obj/effect/projectile/tracer/tracer/aiming @@ -560,4 +552,5 @@ hitscan_light_color_override = "#99ff99" /obj/item/projectile/beam/beam_rifle/hitscan/aiming_beam/prehit(atom/target) + qdel(src) return FALSE diff --git a/code/modules/projectiles/guns/misc/chameleon.dm b/code/modules/projectiles/guns/misc/chameleon.dm new file mode 100644 index 0000000000..d2afe2bd78 --- /dev/null +++ b/code/modules/projectiles/guns/misc/chameleon.dm @@ -0,0 +1,169 @@ +// this is all shitcode never ever add it to the game it's for debugging only. + +/datum/action/item_action/chameleon/change/gun/update_look(mob/user, obj/item/picked_item) + . = ..() + var/obj/item/gun/energy/laser/chameleon/CG = target + CG.get_chameleon_projectile(picked_item) + +/obj/item/gun/energy/laser/chameleon + name = "practice laser gun" + desc = "A modified version of the basic laser gun, this one fires less concentrated energy bolts designed for target practice." + ammo_type = list(/obj/item/ammo_casing/energy/chameleon) + clumsy_check = 0 + item_flags = NONE + pin = /obj/item/firing_pin + cell_type = /obj/item/stock_parts/cell/bluespace + + var/datum/action/item_action/chameleon/change/gun/chameleon_action + var/list/chameleon_projectile_vars + var/list/chameleon_ammo_vars + var/list/chameleon_gun_vars + var/list/projectile_copy_vars + var/list/ammo_copy_vars + var/list/gun_copy_vars + var/badmin_mode = FALSE + var/can_hitscan = FALSE + var/hitscan_mode = FALSE + +/obj/item/gun/energy/laser/chameleon/Initialize() + . = ..() + chameleon_action = new(src) + chameleon_action.chameleon_type = /obj/item/gun + chameleon_action.chameleon_name = "Gun" + chameleon_action.chameleon_blacklist = typecacheof(/obj/item/gun/magic, ignore_root_path = FALSE) + chameleon_action.initialize_disguises() + + projectile_copy_vars = list("name", "icon", "icon_state", "item_state", "speed", "color", "hitsound", "forcedodge", "impact_effect_type", "range", "suppressed", "hitsound_wall", "impact_effect_type", "pass_flags", "tracer_type", "muzzle_type", "impact_type") + chameleon_projectile_vars = list("name" = "practice laser", "icon" = 'icons/obj/projectiles.dmi', "icon_state" = "laser") + gun_copy_vars = list("fire_sound", "burst_size", "fire_delay") + chameleon_gun_vars = list() + ammo_copy_vars = list("firing_effect_type") + chameleon_ammo_vars = list() + recharge_newshot() + get_chameleon_projectile(/obj/item/gun/energy/laser) + +/obj/item/gun/energy/laser/chameleon/emp_act(severity) + return + +/obj/item/gun/energy/laser/chameleon/proc/reset_chameleon_vars() + chameleon_ammo_vars = list() + chameleon_gun_vars = list() + chameleon_projectile_vars = list() + var/static/list/blacklisted_vars = list("locs", "loc", "contents", "x", "y", "z", "parent_type", "type", "vars") + if(chambered) + for(var/v in ammo_copy_vars) + if(v in blacklisted_vars) //Just in case admins go crazy. + continue + chambered.vv_edit_var(v, initial(chambered.vars[v])) + for(var/v in gun_copy_vars) + if(v in blacklisted_vars) + continue + vv_edit_var(v, initial(vars[v])) + vars[v] = initial(vars[v]) + QDEL_NULL(chambered.BB) + chambered.newshot() + +/obj/item/gun/energy/laser/chameleon/proc/set_chameleon_ammo(obj/item/ammo_casing/AC, passthrough = TRUE, reset = FALSE) + if(!istype(AC)) + CRASH("[AC] is not /obj/item/ammo_casing!") + return FALSE + for(var/V in ammo_copy_vars) + if(AC.vars.Find(V)) + chameleon_ammo_vars[V] = AC.vars[V] + chambered?.vv_edit_var(V, AC.vars[V]) + if(passthrough) + var/obj/item/projectile/P = AC.BB + set_chameleon_projectile(P) + +/obj/item/gun/energy/laser/chameleon/proc/set_chameleon_projectile(obj/item/projectile/P) + if(!istype(P)) + CRASH("[P] is not /obj/item/projectile!") + return FALSE + chameleon_projectile_vars = list("name" = "practice laser", "icon" = 'icons/obj/projectiles.dmi', "icon_state" = "laser", "nodamage" = TRUE) + for(var/V in projectile_copy_vars) + if(P.vars.Find(V)) + chameleon_projectile_vars[V] = P.vars[V] + if(istype(chambered, /obj/item/ammo_casing/energy/chameleon)) + var/obj/item/ammo_casing/energy/chameleon/AC = chambered + AC.projectile_vars = chameleon_projectile_vars.Copy() + if(!P.tracer_type) + can_hitscan = FALSE + set_hitscan(FALSE) + else + can_hitscan = TRUE + if(badmin_mode) + qdel(chambered.BB) + chambered.projectile_type = P.type + chambered.newshot() + +/obj/item/gun/energy/laser/chameleon/proc/set_chameleon_gun(obj/item/gun/G , passthrough = TRUE) + if(!istype(G)) + CRASH("[G] is not /obj/item/gun!") + return FALSE + for(var/V in gun_copy_vars) + if(vars.Find(V) && G.vars.Find(V)) + chameleon_gun_vars[V] = G.vars[V] + vv_edit_var(V, G.vars[V]) + if(passthrough) + if(istype(G, /obj/item/gun/ballistic)) + var/obj/item/gun/ballistic/BG = G + var/obj/item/ammo_box/AB = new BG.mag_type(G) + qdel(BG) + if(!istype(AB)||!AB.ammo_type) + qdel(AB) + return FALSE + var/obj/item/ammo_casing/AC = new AB.ammo_type(G) + set_chameleon_ammo(AC) + else if(istype(G, /obj/item/gun/magic)) + var/obj/item/gun/magic/MG = G + var/obj/item/ammo_casing/AC = new MG.ammo_type(G) + set_chameleon_ammo(AC) + else if(istype(G, /obj/item/gun/energy)) + var/obj/item/gun/energy/EG = G + if(islist(EG.ammo_type) && EG.ammo_type.len) + var/obj/item/ammo_casing/AC = EG.ammo_type[1] + set_chameleon_ammo(AC) + else if(istype(G, /obj/item/gun/syringe)) + var/obj/item/ammo_casing/AC = new /obj/item/ammo_casing/syringegun(src) + set_chameleon_ammo(AC) + +/obj/item/gun/energy/laser/chameleon/attack_self(mob/user) + . = ..() + if(!can_hitscan) + to_chat(user, "[src]'s current disguised gun does not allow it to enable high velocity mode!") + return + if(!chambered) + to_chat(user, "Unknown error in energy lens: Please reset chameleon disguise and try again.") + return + set_hitscan(!hitscan_mode) + to_chat(user, "You toggle [src]'s high velocity beam mode to [hitscan_mode? "on" : "off"].") + +/obj/item/gun/energy/laser/chameleon/proc/set_hitscan(hitscan) + var/obj/item/ammo_casing/energy/chameleon/AC = chambered + AC.hitscan_mode = hitscan + hitscan_mode = hitscan + +/obj/item/gun/energy/laser/chameleon/proc/get_chameleon_projectile(guntype) + reset_chameleon_vars() + var/obj/item/gun/G = new guntype(src) + set_chameleon_gun(G) + qdel(G) + +/obj/item/ammo_casing/energy/chameleon + projectile_type = /obj/item/projectile/energy/chameleon + e_cost = 0 + var/hitscan_mode = FALSE + var/list/projectile_vars = list() + +/obj/item/ammo_casing/energy/chameleon/ready_proj(atom/target, mob/living/user, quiet, zone_override = "") + . = ..() + if(!BB) + newshot() + for(var/V in projectile_vars) + if(BB.vars.Find(V)) + BB.vv_edit_var(V, projectile_vars[V]) + if(hitscan_mode) + BB.hitscan = TRUE + +/obj/item/projectile/energy/chameleon + nodamage = TRUE diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm index 139f5a051c..9b60f96d16 100644 --- a/code/modules/projectiles/projectile.dm +++ b/code/modules/projectiles/projectile.dm @@ -52,6 +52,8 @@ var/hitscan = FALSE //Whether this is hitscan. If it is, speed is basically ignored. var/list/beam_segments //assoc list of datum/point or datum/point/vector, start = end. Used for hitscan effect generation. var/datum/point/beam_index + /// Used in generate_hitscan_tracers to determine which "cycle" we're on. + var/hitscan_effect_generation = 0 var/tracer_type var/muzzle_type var/impact_type @@ -89,10 +91,10 @@ var/decayedRange //stores original range var/reflect_range_decrease = 5 //amount of original range that falls off when reflecting, so it doesn't go forever var/is_reflectable = FALSE // Can it be reflected or not? - + /// factor to multiply by for zone accuracy percent. var/zone_accuracy_factor = 1 - + //Effects var/stun = 0 var/knockdown = 0 @@ -656,18 +658,20 @@ if(trajectory && beam_index) var/datum/point/pcache = trajectory.copy_to() beam_segments[beam_index] = pcache - generate_hitscan_tracers(null, null, impacting) + generate_hitscan_tracers(null, null, impacting, hitscan_effect_generation++) -/obj/item/projectile/proc/generate_hitscan_tracers(cleanup = TRUE, duration = 3, impacting = TRUE) +/obj/item/projectile/proc/generate_hitscan_tracers(cleanup = TRUE, duration = 3, impacting = TRUE, generation) if(!length(beam_segments)) return + . = list() if(tracer_type) - var/tempref = REF(src) + var/list/turfs = list() for(var/datum/point/p in beam_segments) - generate_tracer_between_points(p, beam_segments[p], tracer_type, color, duration, hitscan_light_range, hitscan_light_color_override, hitscan_light_intensity, tempref) + . += generate_tracer_between_points(p, beam_segments[p], tracer_type, color, duration, hitscan_light_range, hitscan_light_color_override, hitscan_light_intensity, turfs) if(muzzle_type && duration > 0) var/datum/point/p = beam_segments[1] var/atom/movable/thing = new muzzle_type + . += thing p.move_atom_to_src(thing) var/matrix/M = new M.Turn(original_angle) @@ -678,6 +682,7 @@ if(impacting && impact_type && duration > 0) var/datum/point/p = beam_segments[beam_segments[beam_segments.len]] var/atom/movable/thing = new impact_type + . += thing p.move_atom_to_src(thing) var/matrix/M = new M.Turn(Angle) diff --git a/tgstation.dme b/tgstation.dme index c10faebf81..ee105be14a 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -2734,6 +2734,7 @@ #include "code\modules\projectiles\guns\magic\wand.dm" #include "code\modules\projectiles\guns\misc\beam_rifle.dm" #include "code\modules\projectiles\guns\misc\blastcannon.dm" +#include "code\modules\projectiles\guns\misc\chameleon.dm" #include "code\modules\projectiles\guns\misc\chem_gun.dm" #include "code\modules\projectiles\guns\misc\grenade_launcher.dm" #include "code\modules\projectiles\guns\misc\medbeam.dm"