mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-27 15:17:01 +01:00
[MIRROR] Refactors Beams to use signals: Revived from 2019 edition! BONUS: Medbeams are also refactored to use signals (#2237)
* Refactors Beams to use signals: Revived from 2019 edition! BONUS: Medbeams are also refactored to use signals (#55193) Huge removal of dead vars, bad timers, and other sloppy jitteriness from beams. They go from checking movement to waiting for a signal. VARIABLE KILL LIST: sleep_time: signals baby finished: signals BAYBEEE target_oldloc: not only not typecasted as a turf or named as a turf, it was unused. when are we going to use this? the beam starts from the origin! origin_oldloc: bad name, not typecasted. renamed to originturf static_beam: how are you an unused variable and still get replaced by signals like really timing_id: signallllss bbbaaaabbyy recalculating: you get the drill by now signals baby base_icon: unused, seemingly replaced by visuals I think * Refactors Beams to use signals: Revived from 2019 edition! BONUS: Medbeams are also refactored to use signals Co-authored-by: tralezab <40974010+tralezab@users.noreply.github.com>
This commit is contained in:
+68
-72
@@ -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)<max_distance && origin.z == target.z)
|
||||
var/origin_turf = get_turf(origin)
|
||||
var/target_turf = get_turf(target)
|
||||
if(!static_beam && (origin_turf != origin_oldloc || target_turf != target_oldloc))
|
||||
origin_oldloc = origin_turf //so we don't keep checking against their initial positions, leading to endless Reset()+Draw() calls
|
||||
target_oldloc = target_turf
|
||||
Reset()
|
||||
Draw()
|
||||
after_calculate()
|
||||
recalculating = FALSE
|
||||
QDEL_LIST(elements)
|
||||
Draw()
|
||||
else
|
||||
End()
|
||||
|
||||
/datum/beam/proc/afterDraw()
|
||||
return
|
||||
|
||||
/datum/beam/proc/recalculate_in(time)
|
||||
if(timing_id)
|
||||
deltimer(timing_id)
|
||||
timing_id = addtimer(CALLBACK(src, .proc/recalculate), time, TIMER_STOPPABLE)
|
||||
|
||||
/datum/beam/proc/after_calculate()
|
||||
if((sleep_time == null) || finished) //Does not automatically recalculate.
|
||||
return
|
||||
if(isnull(timing_id))
|
||||
timing_id = addtimer(CALLBACK(src, .proc/recalculate), sleep_time, TIMER_STOPPABLE)
|
||||
|
||||
/datum/beam/proc/End(destroy_self = TRUE)
|
||||
finished = TRUE
|
||||
if(!isnull(timing_id))
|
||||
deltimer(timing_id)
|
||||
if(!QDELETED(src) && destroy_self)
|
||||
qdel(src)
|
||||
|
||||
/datum/beam/proc/Reset()
|
||||
for(var/obj/effect/ebeam/B in elements)
|
||||
qdel(B)
|
||||
elements.Cut()
|
||||
|
||||
/datum/beam/Destroy()
|
||||
Reset()
|
||||
QDEL_LIST(elements)
|
||||
qdel(visuals)
|
||||
UnregisterSignal(origin, COMSIG_MOVABLE_MOVED)
|
||||
UnregisterSignal(target, COMSIG_MOVABLE_MOVED)
|
||||
target = null
|
||||
origin = null
|
||||
return ..()
|
||||
|
||||
/**
|
||||
* Creates the beam effects and places them in a line from the origin to the target. Sets their rotation to make the beams face the target, too.
|
||||
*/
|
||||
/datum/beam/proc/Draw()
|
||||
var/Angle = round(Get_Angle(origin,target))
|
||||
var/matrix/rot_matrix = matrix()
|
||||
var/turf/origin_turf = get_turf(origin)
|
||||
rot_matrix.Turn(Angle)
|
||||
|
||||
//Translation vector for origin and target
|
||||
@@ -105,17 +90,17 @@
|
||||
var/length = round(sqrt((DX)**2+(DY)**2)) //hypotenuse of the triangle formed by target and origin's displacement
|
||||
|
||||
for(N in 0 to length-1 step 32)//-1 as we want < not <=, but we want the speed of X in Y to Z and step X
|
||||
if(QDELETED(src) || finished)
|
||||
if(QDELETED(src))
|
||||
break
|
||||
var/obj/effect/ebeam/X = new beam_type(origin_oldloc)
|
||||
var/obj/effect/ebeam/X = new beam_type(origin_turf)
|
||||
X.owner = src
|
||||
elements += X
|
||||
|
||||
//Assign our single visual ebeam to each ebeam's vis_contents
|
||||
//ends are cropped by a transparent box icon of length-N pixel size laid over the visuals obj
|
||||
if(N+32>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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user