diff --git a/code/datums/beam.dm b/code/datums/beam.dm index 80deb27adc2..9dd4136123f 100644 --- a/code/datums/beam.dm +++ b/code/datums/beam.dm @@ -1,101 +1,86 @@ -//Beam Datum and effect + +/** # Beam Datum and Effect + * **IF YOU ARE LAZY AND DO NOT WANT TO READ, GO TO THE BOTTOM OF THE FILE AND USE THAT PROC!** + * + * This is the beam datum! It's a really neat effect for the game in drawing a line from one atom to another. + * It has two parts: + * The datum itself which manages redrawing the beam to constantly keep it pointing from the origin to the target. + * The effect which is what the beams are made out of. They're placed in a line from the origin to target, rotated towards the target and snipped off at the end. + * These effects are kept in a list and constantly created and destroyed (hence the proc names draw and reset, reset destroying all effects and draw creating more.) + * + * You can add more special effects to the beam itself by changing what the drawn beam effects do. For example you can make a vine that pricks people by making the beam_type + * include a crossed proc that damages the crosser. Examples in venus_human_trap.dm +*/ /datum/beam + ///where the beam goes from var/atom/origin = null + ///where the beam goes to var/atom/target = null + ///list of beam objects. These have their visuals set by the visuals var which is created on starting var/list/elements = list() - var/icon/base_icon = null + ///icon used by the beam. var/icon - var/icon_state = "" //icon state of the main segments of the beam + ///icon state of the main segments of the beam + var/icon_state = "" + ///The beam will qdel if it's longer than this many tiles. var/max_distance = 0 - var/sleep_time = 3 - var/finished = 0 - var/target_oldloc = null - var/origin_oldloc = null - var/static_beam = 0 - var/beam_type = /obj/effect/ebeam //must be subtype - var/timing_id = null - var/recalculating = FALSE + ///the objects placed in the elements list + var/beam_type = /obj/effect/ebeam + ///This is used as the visual_contents of beams, so you can apply one effect to this and the whole beam will look like that. never gets deleted on redrawing. + var/obj/effect/ebeam/visuals - var/obj/effect/ebeam/visuals //what we add to the ebeam's visual contents. never gets deleted on redrawing. - -/datum/beam/New(beam_origin,beam_target,beam_icon='icons/effects/beam.dmi',beam_icon_state="b_beam",time=50,maxdistance=10,btype = /obj/effect/ebeam,beam_sleep_time=3) +/datum/beam/New(beam_origin,beam_target,beam_icon='icons/effects/beam.dmi',beam_icon_state="b_beam",time=INFINITY,maxdistance=INFINITY,btype = /obj/effect/ebeam) origin = beam_origin - origin_oldloc = get_turf(origin) target = beam_target - target_oldloc = get_turf(target) - sleep_time = beam_sleep_time - if(origin_oldloc == origin && target_oldloc == target) - static_beam = 1 max_distance = maxdistance - base_icon = new(beam_icon,beam_icon_state) icon = beam_icon icon_state = beam_icon_state beam_type = btype if(time < INFINITY) - addtimer(CALLBACK(src,.proc/End), time) + QDEL_IN(src, time) +/** + * Proc called by the atom Beam() proc. Sets up signals, and draws the beam for the first time. + */ /datum/beam/proc/Start() visuals = new beam_type() visuals.icon = icon visuals.icon_state = icon_state Draw() - recalculate_in(sleep_time) + RegisterSignal(origin, COMSIG_MOVABLE_MOVED, .proc/redrawing) + RegisterSignal(target, COMSIG_MOVABLE_MOVED, .proc/redrawing) -/datum/beam/proc/recalculate() - if(recalculating) - recalculate_in(sleep_time) - return - recalculating = TRUE - timing_id = null +/** + * Triggered by signals set up when the beam is set up. If it's still sane to create a beam, it removes the old beam, creates a new one. Otherwise it kills the beam. + * + * Arguments: + * mover: either the origin of the beam or the target of the beam that moved. + * oldloc: from where mover moved. + * direction: in what direction mover moved from. + */ +/datum/beam/proc/redrawing(atom/movable/mover, atom/oldloc, direction) if(origin && target && get_dist(origin,target)length) //went past the target, needs to be cut short - var/icon/II = new(icon, icon_state) //the way to keep this the same as the vis_contents is unreasonable right now, maybe in the far future. - II.DrawBox(null,1,(length-N),32,32)//anyway we cut the icon on the ebeam to end at the target instead of overshooting + if(N+32>length) //went past the target, we draw a box of space to cut away from the beam sprite so the icon actually ends at the center of the target sprite + var/icon/II = new(icon, icon_state)//this means we exclude the overshooting object from the visual contents which does mean those visuals don't show up for the final bit of the beam... + II.DrawBox(null,1,(length-N),32,32)//in the future if you want to improve this, remove the drawbox and instead use a 513 filter to cut away at the final object's icon X.icon = II else X.vis_contents += visuals @@ -147,7 +132,6 @@ X.pixel_x = Pixel_x X.pixel_y = Pixel_y CHECK_TICK - afterDraw() /obj/effect/ebeam mouse_opacity = MOUSE_OPACITY_TRANSPARENT @@ -163,7 +147,19 @@ /obj/effect/ebeam/singularity_act() return -/atom/proc/Beam(atom/BeamTarget,icon_state="b_beam",icon='icons/effects/beam.dmi',time=50, maxdistance=10,beam_type=/obj/effect/ebeam,beam_sleep_time = 3) - var/datum/beam/newbeam = new(src,BeamTarget,icon,icon_state,time,maxdistance,beam_type,beam_sleep_time) +/** + * This is what you use to start a beam. Example: origin.Beam(target, args). **Store the return of this proc if you don't set maxdist or time, you need it to delete the beam.** + * + * Unless you're making a custom beam effect (see the beam_type argument), you won't actually have to mess with any other procs. Make sure you store the return of this Proc, you'll need it + * to kill the beam. + * **Arguments:** + * BeamTarget: Where you're beaming from. Where do you get origin? You didn't read the docs, fuck you. + * icon_state: What the beam's icon_state is. The datum effect isn't the ebeam object, it doesn't hold any icon and isn't type dependent. + * icon: What the beam's icon file is. Don't change this, man. All beam icons should be in beam.dmi anyways. + * maxdistance: how far the beam will go before stopping itself. Used mainly for two things: preventing lag if the beam may go in that direction and setting a range to abilities that use beams. + * beam_type: The type of your custom beam. This is for adding other wacky stuff for your beam only. Most likely, you won't (and shouldn't) change it. + */ +/atom/proc/Beam(atom/BeamTarget,icon_state="b_beam",icon='icons/effects/beam.dmi',time=INFINITY,maxdistance=INFINITY,beam_type=/obj/effect/ebeam) + var/datum/beam/newbeam = new(src,BeamTarget,icon,icon_state,time,maxdistance,beam_type) INVOKE_ASYNC(newbeam, /datum/beam/.proc/Start) return newbeam diff --git a/code/datums/dash_weapon.dm b/code/datums/dash_weapon.dm index 0e22a4f350f..93ef1e2edc7 100644 --- a/code/datums/dash_weapon.dm +++ b/code/datums/dash_weapon.dm @@ -37,7 +37,7 @@ user.forceMove(T) playsound(T, dash_sound, 25, TRUE) var/obj/spot2 = new phasein(get_turf(user), user.dir) - spot1.Beam(spot2,beam_effect,time=20) + spot1.Beam(spot2,beam_effect,time=2 SECONDS) current_charges-- holder.update_action_buttons_icon() addtimer(CALLBACK(src, .proc/charge), charge_rate) diff --git a/code/datums/martial/plasma_fist.dm b/code/datums/martial/plasma_fist.dm index 34ab345a1d9..261abb73c8c 100644 --- a/code/datums/martial/plasma_fist.dm +++ b/code/datums/martial/plasma_fist.dm @@ -84,7 +84,7 @@ A.color = "#9C00FF" flash_color(A, flash_color = "#9C00FF", flash_time = 3 SECONDS) animate(A, color = oldcolor, time = 3 SECONDS) - + /datum/martial_art/plasma_fist/proc/Apotheosis(mob/living/carbon/human/A, mob/living/carbon/human/D) A.say("APOTHEOSIS!!", forced="plasma fist") @@ -164,7 +164,7 @@ . = ..() beam_target = _beam_target if(beam_target) - var/datum/beam/beam = Beam(beam_target, "plasmabeam", time= 3 SECONDS, maxdistance=INFINITY, beam_type=/obj/effect/ebeam/plasma_fist) + var/datum/beam/beam = Beam(beam_target, "plasmabeam", beam_type=/obj/effect/ebeam/plasma_fist, time = 3 SECONDS) animate(beam.visuals, alpha = 0, time = 3 SECONDS) animate(src, alpha = 0, transform = matrix()*0.5, time = 3 SECONDS) diff --git a/code/game/objects/items/RCD.dm b/code/game/objects/items/RCD.dm index 5c8d1ab8456..5ca389e3ffa 100644 --- a/code/game/objects/items/RCD.dm +++ b/code/game/objects/items/RCD.dm @@ -750,7 +750,7 @@ RLD if(!range_check(A,user)) return if(target_check(A,user)) - user.Beam(A,icon_state="rped_upgrade",time=30) + user.Beam(A,icon_state="rped_upgrade", time = 3 SECONDS) rcd_create(A,user) @@ -827,7 +827,7 @@ RLD if(istype(A, /obj/machinery/light/)) if(checkResource(deconcost, user)) to_chat(user, "You start deconstructing [A]...") - user.Beam(A,icon_state="light_beam",time=15) + user.Beam(A,icon_state="light_beam", time = 15) playsound(src.loc, 'sound/machines/click.ogg', 50, TRUE) if(do_after(user, decondelay, target = A)) if(!useResource(deconcost, user)) @@ -841,7 +841,7 @@ RLD var/turf/closed/wall/W = A if(checkResource(floorcost, user)) to_chat(user, "You start building a wall light...") - user.Beam(A,icon_state="light_beam",time=15) + user.Beam(A,icon_state="light_beam", time = 15) playsound(src.loc, 'sound/machines/click.ogg', 50, TRUE) playsound(src.loc, 'sound/effects/light_flicker.ogg', 50, FALSE) if(do_after(user, floordelay, target = A)) @@ -887,7 +887,7 @@ RLD var/turf/open/floor/F = A if(checkResource(floorcost, user)) to_chat(user, "You start building a floor light...") - user.Beam(A,icon_state="light_beam",time=15) + user.Beam(A,icon_state="light_beam", time = 15) playsound(src.loc, 'sound/machines/click.ogg', 50, TRUE) playsound(src.loc, 'sound/effects/light_flicker.ogg', 50, TRUE) if(do_after(user, floordelay, target = A)) diff --git a/code/game/objects/items/melee/misc.dm b/code/game/objects/items/melee/misc.dm index 6365ef7a56a..7f46f525433 100644 --- a/code/game/objects/items/melee/misc.dm +++ b/code/game/objects/items/melee/misc.dm @@ -640,7 +640,7 @@ if (istype(target, /obj/singularity) && get_dist(user, target) < 10) to_chat(user, "You send [held_sausage] towards [target].") playsound(src, 'sound/items/rped.ogg', 50, TRUE) - beam = user.Beam(target,icon_state="rped_upgrade",time=100) + beam = user.Beam(target,icon_state="rped_upgrade", time = 10 SECONDS) else if (user.Adjacent(target)) to_chat(user, "You extend [src] towards [target].") playsound(src.loc, 'sound/weapons/batonextend.ogg', 50, TRUE) diff --git a/code/modules/antagonists/changeling/powers/mutations.dm b/code/modules/antagonists/changeling/powers/mutations.dm index 382ac5c819f..a68bd22c8b5 100644 --- a/code/modules/antagonists/changeling/powers/mutations.dm +++ b/code/modules/antagonists/changeling/powers/mutations.dm @@ -310,7 +310,7 @@ /obj/projectile/tentacle/fire(setAngle) if(firer) - chain = firer.Beam(src, icon_state = "tentacle", time = INFINITY, maxdistance = INFINITY, beam_sleep_time = 1) + chain = firer.Beam(src, icon_state = "tentacle") ..() /obj/projectile/tentacle/proc/reset_throw(mob/living/carbon/human/H) diff --git a/code/modules/antagonists/cult/blood_magic.dm b/code/modules/antagonists/cult/blood_magic.dm index b453c09ec6d..ac3be2db118 100644 --- a/code/modules/antagonists/cult/blood_magic.dm +++ b/code/modules/antagonists/cult/blood_magic.dm @@ -743,7 +743,7 @@ H.updatehealth() playsound(get_turf(H), 'sound/magic/staff_healing.ogg', 25) new /obj/effect/temp_visual/cult/sparks(get_turf(H)) - user.Beam(H,icon_state="sendbeam",time=15) + user.Beam(H, icon_state="sendbeam", time = 15) else if(H.stat == DEAD) to_chat(user,"[H.p_their(TRUE)] blood has stopped flowing, you'll have to find another way to extract it.") @@ -754,7 +754,7 @@ if(H.blood_volume > BLOOD_VOLUME_SAFE) H.blood_volume -= 100 uses += 50 - user.Beam(H,icon_state="drainbeam",time=10) + user.Beam(H, icon_state="drainbeam", time = 1 SECONDS) playsound(get_turf(H), 'sound/magic/enter_blood.ogg', 50) H.visible_message("[user] drains some of [H]'s blood!") to_chat(user,"Your blood rite gains 50 charges from draining [H]'s blood.") @@ -775,7 +775,7 @@ M.visible_message("[M] is partially healed by [user]'s blood magic!") uses = 0 playsound(get_turf(M), 'sound/magic/staff_healing.ogg', 25) - user.Beam(M,icon_state="sendbeam",time=10) + user.Beam(M, icon_state="sendbeam", time = 1 SECONDS) if(istype(target, /obj/effect/decal/cleanable/blood)) blood_draw(target, user) ..() @@ -795,7 +795,7 @@ for(var/obj/effect/decal/cleanable/trail_holder/TH in view(T, 2)) qdel(TH) if(temp) - user.Beam(T,icon_state="drainbeam",time=15) + user.Beam(T,icon_state="drainbeam", time = 15) new /obj/effect/temp_visual/cult/sparks(get_turf(user)) playsound(T, 'sound/magic/enter_blood.ogg', 50) to_chat(user, "Your blood rite has gained [round(temp)] charge\s from blood sources around you!") diff --git a/code/modules/antagonists/cult/cult_comms.dm b/code/modules/antagonists/cult/cult_comms.dm index fb0f9312a72..5d85e2b49c2 100644 --- a/code/modules/antagonists/cult/cult_comms.dm +++ b/code/modules/antagonists/cult/cult_comms.dm @@ -456,7 +456,7 @@ if(distance >= 16) return playsound(target,'sound/magic/exit_blood.ogg') - attached_action.throwee.Beam(target,icon_state="sendbeam",time=4) + attached_action.throwee.Beam(target,icon_state="sendbeam", time = 4) attached_action.throwee.forceMove(get_turf(target)) new /obj/effect/temp_visual/cult/sparks(get_turf(target), ranged_ability_user.dir) attached_action.throwing = FALSE diff --git a/code/modules/antagonists/cult/cult_items.dm b/code/modules/antagonists/cult/cult_items.dm index 7147c920049..68c739d23ed 100644 --- a/code/modules/antagonists/cult/cult_items.dm +++ b/code/modules/antagonists/cult/cult_items.dm @@ -912,8 +912,7 @@ L.adjustBruteLoss(45) playsound(L, 'sound/hallucinations/wail.ogg', 50, TRUE) L.emote("scream") - var/datum/beam/current_beam = new(user,temp_target,time=7,beam_icon_state="blood_beam",btype=/obj/effect/ebeam/blood) - INVOKE_ASYNC(current_beam, /datum/beam.proc/Start) + user.Beam(temp_target, icon_state="blood_beam", time = 7, beam_type = /obj/effect/ebeam/blood) /obj/effect/ebeam/blood diff --git a/code/modules/antagonists/cult/runes.dm b/code/modules/antagonists/cult/runes.dm index d7f6d22d1c2..557e379a71f 100644 --- a/code/modules/antagonists/cult/runes.dm +++ b/code/modules/antagonists/cult/runes.dm @@ -845,7 +845,7 @@ structure_check() searches for nearby cultist structures required for the invoca while(!QDELETED(affecting)) if(!(affecting in T)) user.visible_message("A spectral tendril wraps around [affecting] and pulls [affecting.p_them()] back to the rune!") - Beam(affecting, icon_state="drainbeam", time=2) + Beam(affecting, icon_state="drainbeam", time = 2) affecting.forceMove(get_turf(src)) //NO ESCAPE :^) if(affecting.key) affecting.visible_message("[affecting] slowly relaxes, the glow around [affecting.p_them()] dimming.", \ diff --git a/code/modules/antagonists/revenant/revenant_abilities.dm b/code/modules/antagonists/revenant/revenant_abilities.dm index 0c86660c4b2..22cfb964f97 100644 --- a/code/modules/antagonists/revenant/revenant_abilities.dm +++ b/code/modules/antagonists/revenant/revenant_abilities.dm @@ -71,7 +71,7 @@ "Violet lights, dancing in your vision, receding--") draining = FALSE return - var/datum/beam/B = Beam(target,icon_state="drain_life",time=INFINITY) + var/datum/beam/B = Beam(target,icon_state="drain_life") if(do_after(src, 46, target, timed_action_flags = IGNORE_HELD_ITEM)) //As one cannot prove the existance of ghosts, ghosts cannot prove the existance of the target they were draining. change_essence_amount(essence_drained, FALSE, target) if(essence_drained <= 90 && target.stat != DEAD) @@ -214,7 +214,7 @@ for(var/mob/living/carbon/human/M in view(shock_range, L)) if(M == user) continue - L.Beam(M,icon_state="purple_lightning",time=5) + L.Beam(M,icon_state="purple_lightning", time = 5) if(!M.anti_magic_check(FALSE, TRUE)) M.electrocute_act(shock_damage, L, flags = SHOCK_NOGLOVES) do_sparks(4, FALSE, M) diff --git a/code/modules/mining/lavaland/necropolis_chests.dm b/code/modules/mining/lavaland/necropolis_chests.dm index 8bb3aa8540c..97342b60bf3 100644 --- a/code/modules/mining/lavaland/necropolis_chests.dm +++ b/code/modules/mining/lavaland/necropolis_chests.dm @@ -413,7 +413,7 @@ /obj/projectile/hook/fire(setAngle) if(firer) - chain = firer.Beam(src, icon_state = "chain", time = INFINITY, maxdistance = INFINITY) + chain = firer.Beam(src, icon_state = "chain") ..() //TODO: root the firer until the chain returns diff --git a/code/modules/mob/living/simple_animal/constructs.dm b/code/modules/mob/living/simple_animal/constructs.dm index 390db50ed38..bfd38ef7f18 100644 --- a/code/modules/mob/living/simple_animal/constructs.dm +++ b/code/modules/mob/living/simple_animal/constructs.dm @@ -94,7 +94,7 @@ if(health < maxHealth) adjustHealth(-5) if(src != M) - Beam(M,icon_state="sendbeam",time=4) + Beam(M, icon_state="sendbeam", time = 4) M.visible_message("[M] repairs some of \the [src]'s dents.", \ "You repair some of [src]'s dents, leaving [src] at [health]/[maxHealth] health.") else diff --git a/code/modules/mob/living/simple_animal/guardian/types/lightning.dm b/code/modules/mob/living/simple_animal/guardian/types/lightning.dm index a70bf4edae2..837ab08c374 100644 --- a/code/modules/mob/living/simple_animal/guardian/types/lightning.dm +++ b/code/modules/mob/living/simple_animal/guardian/types/lightning.dm @@ -33,7 +33,7 @@ var/datum/beam/C = pick(enemychains) qdel(C) enemychains -= C - enemychains += Beam(target, "lightning[rand(1,12)]", time=70, maxdistance=7, beam_type=/obj/effect/ebeam/chain) + enemychains += Beam(target, "lightning[rand(1,12)]", maxdistance=7, beam_type=/obj/effect/ebeam/chain) /mob/living/simple_animal/hostile/guardian/beam/Destroy() removechains() @@ -43,7 +43,7 @@ . = ..() if(.) if(summoner) - summonerchain = Beam(summoner, "lightning[rand(1,12)]", time=INFINITY, maxdistance=INFINITY, beam_type=/obj/effect/ebeam/chain) + summonerchain = Beam(summoner, "lightning[rand(1,12)]", beam_type=/obj/effect/ebeam/chain) while(loc != summoner) if(successfulshocks > 5) successfulshocks = 0 @@ -70,7 +70,7 @@ cleardeletedchains() if(summoner) if(!summonerchain) - summonerchain = Beam(summoner, "lightning[rand(1,12)]", time=INFINITY, maxdistance=INFINITY, beam_type=/obj/effect/ebeam/chain) + summonerchain = Beam(summoner, "lightning[rand(1,12)]", beam_type=/obj/effect/ebeam/chain) . += chainshock(summonerchain) if(enemychains.len) for(var/chain in enemychains) diff --git a/code/modules/mob/living/simple_animal/hostile/venus_human_trap.dm b/code/modules/mob/living/simple_animal/hostile/venus_human_trap.dm index 4b19ba89cc3..6e3b5852ded 100644 --- a/code/modules/mob/living/simple_animal/hostile/venus_human_trap.dm +++ b/code/modules/mob/living/simple_animal/hostile/venus_human_trap.dm @@ -38,8 +38,7 @@ anchors += locate(x+2,y-2,z) for(var/turf/T in anchors) - var/datum/beam/B = Beam(T, "vine", time=INFINITY, maxdistance=5, beam_type=/obj/effect/ebeam/vine) - B.sleep_time = 10 //these shouldn't move, so let's slow down updates to 1 second (any slower and the deletion of the vines would be too slow) + Beam(T, "vine", maxdistance=5, beam_type=/obj/effect/ebeam/vine) finish_time = world.time + growth_time addtimer(CALLBACK(src, .proc/bear_fruit), growth_time) addtimer(CALLBACK(src, .proc/progress_growth), growth_time/4) @@ -153,7 +152,7 @@ if(O.density) return - var/datum/beam/newVine = Beam(the_target, "vine", time=INFINITY, maxdistance = vine_grab_distance, beam_type=/obj/effect/ebeam/vine) + var/datum/beam/newVine = Beam(the_target, icon_state = "vine", maxdistance = vine_grab_distance, beam_type=/obj/effect/ebeam/vine) RegisterSignal(newVine, COMSIG_PARENT_QDELETING, .proc/remove_vine, newVine) vines += newVine if(isliving(the_target)) @@ -205,7 +204,7 @@ if(!AM.anchored) step(AM,get_dir(AM,src)) if(get_dist(src,B.target) == 0) - B.End() + qdel(B) /** * Removes a vine from the list. @@ -215,5 +214,5 @@ * Arguments: * * datum/beam/vine - The vine to be removed from the list. */ -/mob/living/simple_animal/hostile/venus_human_trap/proc/remove_vine(datum/beam/vine, force) +/mob/living/simple_animal/hostile/venus_human_trap/proc/remove_vine(datum/beam/vine) vines -= vine diff --git a/code/modules/mob/living/simple_animal/shade.dm b/code/modules/mob/living/simple_animal/shade.dm index c8082564be6..227aff99cc9 100644 --- a/code/modules/mob/living/simple_animal/shade.dm +++ b/code/modules/mob/living/simple_animal/shade.dm @@ -57,7 +57,7 @@ return if(health < maxHealth) adjustHealth(-25) - Beam(M,icon_state="sendbeam",time=4) + Beam(M,icon_state="sendbeam", time = 4) M.visible_message("[M] heals \the [src].", \ "You heal [src], leaving [src] at [health]/[maxHealth] health.") else diff --git a/code/modules/ninja/suit/ninja_equipment_actions/ninja_net.dm b/code/modules/ninja/suit/ninja_equipment_actions/ninja_net.dm index 82c585f93f5..ab52f3e0180 100644 --- a/code/modules/ninja/suit/ninja_equipment_actions/ninja_net.dm +++ b/code/modules/ninja/suit/ninja_equipment_actions/ninja_net.dm @@ -25,7 +25,7 @@ to_chat(ninja, "You may not use an energy net through solid obstacles!") return if(!ninjacost(400,N_STEALTH_CANCEL)) - ninja.Beam(net_target, "n_beam",time=15) + ninja.Beam(net_target, "n_beam", time = 15) ninja.say("Get over here!", forced = "ninja net") var/obj/structure/energy_net/net = new /obj/structure/energy_net(net_target.drop_location()) net.affecting = net_target diff --git a/code/modules/power/supermatter/supermatter.dm b/code/modules/power/supermatter/supermatter.dm index 39cd3036c58..456555a75bb 100644 --- a/code/modules/power/supermatter/supermatter.dm +++ b/code/modules/power/supermatter/supermatter.dm @@ -1184,7 +1184,7 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal) //Do the animation to zap to it from here if(!(zap_flags & ZAP_ALLOW_DUPLICATES)) LAZYSET(targets_hit, target, TRUE) - zapstart.Beam(target, icon_state=zap_icon, time=5) + zapstart.Beam(target, icon_state=zap_icon, time = 5) var/zapdir = get_dir(zapstart, target) if(zapdir) . = zapdir diff --git a/code/modules/power/tesla/energy_ball.dm b/code/modules/power/tesla/energy_ball.dm index cbe97233182..0c7e810fe14 100644 --- a/code/modules/power/tesla/energy_ball.dm +++ b/code/modules/power/tesla/energy_ball.dm @@ -310,7 +310,7 @@ if(!closest_atom) return //common stuff - source.Beam(closest_atom, icon_state="lightning[rand(1,12)]", time=5, maxdistance = INFINITY) + source.Beam(closest_atom, icon_state="lightning[rand(1,12)]", time = 5) var/zapdir = get_dir(source, closest_atom) if(zapdir) . = zapdir diff --git a/code/modules/projectiles/guns/misc/medbeam.dm b/code/modules/projectiles/guns/misc/medbeam.dm index ef7bef4b209..390a5ec6aea 100644 --- a/code/modules/projectiles/guns/misc/medbeam.dm +++ b/code/modules/projectiles/guns/misc/medbeam.dm @@ -33,6 +33,9 @@ ..() LoseTarget() +/** + * Proc that always is called when we want to end the beam and makes sure things are cleaned up, see beam_died() + */ /obj/item/gun/medbeam/proc/LoseTarget() if(active) qdel(current_beam) @@ -41,6 +44,17 @@ on_beam_release(current_target) current_target = null +/** + * Proc that is only called when the beam fails due to something, so not when manually ended. + * manual disconnection = LoseTarget, so it can silently end + * automatic disconnection = beam_died, so we can give a warning message first + */ +/obj/item/gun/medbeam/proc/beam_died() + active = FALSE //skip qdelling the beam again if we're doing this proc, because + if(isliving(loc)) + to_chat(loc, "You lose control of the beam!") + LoseTarget() + /obj/item/gun/medbeam/process_fire(atom/target, mob/living/user, message = TRUE, params = null, zone_override = "", bonus_spread = 0) if(isliving(user)) add_fingerprint(user) @@ -52,15 +66,13 @@ current_target = target active = TRUE - current_beam = new(user,current_target,time=6000,beam_icon_state="medbeam",btype=/obj/effect/ebeam/medical) - INVOKE_ASYNC(current_beam, /datum/beam.proc/Start) + current_beam = user.Beam(current_target, icon_state="medbeam", time = 10 MINUTES, maxdistance = max_range, beam_type = /obj/effect/ebeam/medical) + RegisterSignal(current_beam, COMSIG_PARENT_QDELETING, .proc/beam_died)//this is a WAY better rangecheck than what was done before (process check) SSblackbox.record_feedback("tally", "gun_fired", 1, type) /obj/item/gun/medbeam/process() - - var/source = loc - if(!mounted && !isliving(source)) + if(!mounted && !isliving(loc)) LoseTarget() return @@ -73,10 +85,8 @@ last_check = world.time - if(get_dist(source, current_target)>max_range || !los_check(source, current_target)) - LoseTarget() - if(isliving(source)) - to_chat(source, "You lose control of the beam!") + if(!los_check(loc, current_target)) + qdel(current_beam)//this will give the target lost message return if(current_target) diff --git a/code/modules/projectiles/projectile/magic.dm b/code/modules/projectiles/projectile/magic.dm index 618f9e0f59b..ab5f7eafd2b 100644 --- a/code/modules/projectiles/projectile/magic.dm +++ b/code/modules/projectiles/projectile/magic.dm @@ -639,7 +639,7 @@ /obj/projectile/magic/aoe/lightning/fire(setAngle) if(caster) - chain = caster.Beam(src, icon_state = "lightning[rand(1, 12)]", time = INFINITY, maxdistance = INFINITY) + chain = caster.Beam(src, icon_state = "lightning[rand(1, 12)]") ..() /obj/projectile/magic/aoe/lightning/on_hit(target) diff --git a/code/modules/projectiles/projectile/special/curse.dm b/code/modules/projectiles/projectile/special/curse.dm index a60bf444c6d..0758aa4d531 100644 --- a/code/modules/projectiles/projectile/special/curse.dm +++ b/code/modules/projectiles/projectile/special/curse.dm @@ -25,7 +25,7 @@ /obj/projectile/curse_hand/fire(setAngle) if(starting) - arm = starting.Beam(src, icon_state = "curse[handedness]", time = INFINITY, maxdistance = INFINITY, beam_type=/obj/effect/ebeam/curse_arm) + arm = starting.Beam(src, icon_state = "curse[handedness]", beam_type=/obj/effect/ebeam/curse_arm) ..() /obj/projectile/curse_hand/prehit_pierce(atom/target) @@ -33,8 +33,7 @@ /obj/projectile/curse_hand/Destroy() if(arm) - arm.End() - arm = null + QDEL_NULL(arm) if((movement_type & PHASING)) playsound(src, 'sound/effects/curse3.ogg', 25, TRUE, -1) var/turf/T = get_step(src, dir) @@ -43,9 +42,7 @@ for(var/obj/effect/temp_visual/dir_setting/curse/grasp_portal/G in starting) qdel(G) new /obj/effect/temp_visual/dir_setting/curse/grasp_portal/fading(starting, dir) - var/datum/beam/D = starting.Beam(T, icon_state = "curse[handedness]", time = 32, maxdistance = INFINITY, beam_type=/obj/effect/ebeam/curse_arm, beam_sleep_time = 1) - for(var/b in D.elements) - var/obj/effect/ebeam/B = b - animate(B, alpha = 0, time = 32) + var/datum/beam/D = starting.Beam(T, icon_state = "curse[handedness]", time = 32, beam_type=/obj/effect/ebeam/curse_arm) + animate(D.visuals, alpha = 0, time = 32) return ..() diff --git a/code/modules/research/stock_parts.dm b/code/modules/research/stock_parts.dm index 17ed354741b..f3d7d0d18df 100644 --- a/code/modules/research/stock_parts.dm +++ b/code/modules/research/stock_parts.dm @@ -20,7 +20,7 @@ If you create T5+ please take a pass at mech_fabricator.dm. The parts being good return ..() if(user.Adjacent(T)) // no TK upgrading. if(works_from_distance) - user.Beam(T, icon_state = "rped_upgrade", time = 5) + Beam(T, icon_state = "rped_upgrade", time = 5) T.exchange_parts(user, src) return TRUE return ..() @@ -29,7 +29,7 @@ If you create T5+ please take a pass at mech_fabricator.dm. The parts being good if(adjacent || !istype(T) || !T.component_parts) return ..() if(works_from_distance) - user.Beam(T, icon_state = "rped_upgrade", time = 5) + Beam(T, icon_state = "rped_upgrade", time = 5) T.exchange_parts(user, src) return return ..() diff --git a/code/modules/spells/spell_types/lichdom.dm b/code/modules/spells/spell_types/lichdom.dm index 8119cf05049..76739d03321 100644 --- a/code/modules/spells/spell_types/lichdom.dm +++ b/code/modules/spells/spell_types/lichdom.dm @@ -149,7 +149,7 @@ var/wheres_wizdo = dir2text(get_dir(body_turf, item_turf)) if(wheres_wizdo) old_body.visible_message("Suddenly [old_body.name]'s corpse falls to pieces! You see a strange energy rise from the remains, and speed off towards the [wheres_wizdo]!") - body_turf.Beam(item_turf,icon_state="lichbeam",time=10+10*resurrections,maxdistance=INFINITY) + body_turf.Beam(item_turf,icon_state="lichbeam", time = 10 + 10 * resurrections) old_body.dust() diff --git a/code/modules/spells/spell_types/lightning.dm b/code/modules/spells/spell_types/lightning.dm index 968008ed790..ce96f06ba19 100644 --- a/code/modules/spells/spell_types/lightning.dm +++ b/code/modules/spells/spell_types/lightning.dm @@ -57,13 +57,13 @@ return playsound(get_turf(user), 'sound/magic/lightningbolt.ogg', 50, TRUE) - user.Beam(target,icon_state="lightning[rand(1,12)]",time=5) + user.Beam(target,icon_state="lightning[rand(1,12)]", time = 5) Bolt(user,target,30,5,user) Reset(user) /obj/effect/proc_holder/spell/targeted/tesla/proc/Bolt(mob/origin,mob/target,bolt_energy,bounces,mob/user = usr) - origin.Beam(target,icon_state="lightning[rand(1,12)]",time=5) + origin.Beam(target,icon_state="lightning[rand(1,12)]", time = 5) var/mob/living/carbon/current = target if(current.anti_magic_check()) playsound(get_turf(current), 'sound/magic/lightningshock.ogg', 50, TRUE, -1) diff --git a/code/modules/station_goals/bsa.dm b/code/modules/station_goals/bsa.dm index fc15e0dc099..a7d34cf97ce 100644 --- a/code/modules/station_goals/bsa.dm +++ b/code/modules/station_goals/bsa.dm @@ -199,7 +199,7 @@ break else SSexplosions.highturf += tile //also fucks everything else on the turf - point.Beam(target, icon_state = "bsa_beam", time = 50, maxdistance = world.maxx) //ZZZAP + point.Beam(target, icon_state = "bsa_beam", time = 5 SECONDS, maxdistance = world.maxx) //ZZZAP new /obj/effect/temp_visual/bsa_splash(point, dir) if(!blocker) diff --git a/code/modules/station_goals/shield.dm b/code/modules/station_goals/shield.dm index 11ad4339f96..8d8b16a3518 100644 --- a/code/modules/station_goals/shield.dm +++ b/code/modules/station_goals/shield.dm @@ -158,7 +158,7 @@ if(get_dist(M,src) > kill_range) continue if(!(obj_flags & EMAGGED) && space_los(M)) - Beam(get_turf(M),icon_state="sat_beam",time=5,maxdistance=kill_range) + Beam(get_turf(M),icon_state="sat_beam", time = 5) qdel(M) /obj/machinery/satellite/meteor_shield/toggle(user) diff --git a/code/modules/vehicles/mecha/equipment/weapons/weapons.dm b/code/modules/vehicles/mecha/equipment/weapons/weapons.dm index 2bf2b35e412..c8e7926d46c 100644 --- a/code/modules/vehicles/mecha/equipment/weapons/weapons.dm +++ b/code/modules/vehicles/mecha/equipment/weapons/weapons.dm @@ -489,8 +489,7 @@ else PG.throwforce = 0 - //has to be low sleep or it looks weird, the beam doesn't exist for very long so it's a non-issue - chassis.Beam(PG, icon_state = "chain", time = missile_range * 20, maxdistance = missile_range + 2, beam_sleep_time = 1) + chassis.Beam(PG, icon_state = "chain", time = missile_range * 20, maxdistance = missile_range + 2) /obj/item/punching_glove name = "punching glove"