diff --git a/code/game/machinery/camera/camera.dm b/code/game/machinery/camera/camera.dm
index 8afbe19633f..01459010385 100644
--- a/code/game/machinery/camera/camera.dm
+++ b/code/game/machinery/camera/camera.dm
@@ -138,25 +138,13 @@
if(!(. & EMP_PROTECT_SELF))
if(prob(150/severity))
update_icon()
- var/list/previous_network = network
network = list()
GLOB.cameranet.removeCamera(src)
stat |= EMPED
set_light(0)
emped = emped+1 //Increase the number of consecutive EMP's
update_icon()
- var/thisemp = emped //Take note of which EMP this proc is for
- spawn(900)
- if(loc) //qdel limbo
- triggerCameraAlarm() //camera alarm triggers even if multiple EMPs are in effect.
- if(emped == thisemp) //Only fix it if the camera hasn't been EMP'd again
- network = previous_network
- stat &= ~EMPED
- update_icon()
- if(can_use())
- GLOB.cameranet.addCamera(src)
- emped = 0 //Resets the consecutive EMP count
- addtimer(CALLBACK(src, .proc/cancelCameraAlarm), 100)
+ addtimer(CALLBACK(src, .proc/post_emp_reset, emped, network), 90 SECONDS)
for(var/i in GLOB.player_list)
var/mob/M = i
if (M.client.eye == src)
@@ -164,6 +152,20 @@
M.reset_perspective(null)
to_chat(M, "The screen bursts into static.")
+/obj/machinery/camera/proc/post_emp_reset(thisemp, previous_network)
+ if(QDELETED(src))
+ return
+ triggerCameraAlarm() //camera alarm triggers even if multiple EMPs are in effect.
+ if(emped != thisemp) //Only fix it if the camera hasn't been EMP'd again
+ return
+ network = previous_network
+ stat &= ~EMPED
+ update_icon()
+ if(can_use())
+ GLOB.cameranet.addCamera(src)
+ emped = 0 //Resets the consecutive EMP count
+ addtimer(CALLBACK(src, .proc/cancelCameraAlarm), 100)
+
/obj/machinery/camera/ex_act(severity, target)
if(invuln)
return
diff --git a/code/game/machinery/camera/tracking.dm b/code/game/machinery/camera/tracking.dm
index 1dbfe9d055b..26f08e0e295 100644
--- a/code/game/machinery/camera/tracking.dm
+++ b/code/game/machinery/camera/tracking.dm
@@ -86,39 +86,42 @@
to_chat(U, "Now tracking [target.get_visible_name()] on camera.")
+ INVOKE_ASYNC(src, .proc/do_track, target, U)
+
+/mob/living/silicon/ai/proc/do_track(mob/living/target, mob/living/silicon/ai/U)
var/cameraticks = 0
- spawn(0)
- while(U.cameraFollow == target)
- if(U.cameraFollow == null)
- return
- if(!target.can_track(usr))
- U.tracking = 1
- if(!cameraticks)
- to_chat(U, "Target is not near any active cameras. Attempting to reacquire...")
- cameraticks++
- if(cameraticks > 9)
- U.cameraFollow = null
- to_chat(U, "Unable to reacquire, cancelling track...")
- tracking = 0
- return
- else
- sleep(10)
- continue
+ while(U.cameraFollow == target)
+ if(U.cameraFollow == null)
+ return
- else
- cameraticks = 0
- U.tracking = 0
-
- if(U.eyeobj)
- U.eyeobj.setLoc(get_turf(target))
-
- else
- view_core()
+ if(!target.can_track(usr))
+ U.tracking = 1
+ if(!cameraticks)
+ to_chat(U, "Target is not near any active cameras. Attempting to reacquire...")
+ cameraticks++
+ if(cameraticks > 9)
U.cameraFollow = null
+ to_chat(U, "Unable to reacquire, cancelling track...")
+ tracking = 0
return
+ else
+ sleep(10)
+ continue
- sleep(10)
+ else
+ cameraticks = 0
+ U.tracking = 0
+
+ if(U.eyeobj)
+ U.eyeobj.setLoc(get_turf(target))
+
+ else
+ view_core()
+ U.cameraFollow = null
+ return
+
+ sleep(10)
/proc/near_camera(mob/living/M)
if (!isturf(M.loc))
diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm
index 1dcb4875441..5abcdaeb9bc 100644
--- a/code/game/machinery/doors/door.dm
+++ b/code/game/machinery/doors/door.dm
@@ -276,8 +276,7 @@
air_update_turf(1)
update_freelook_sight()
if(autoclose)
- spawn(autoclose)
- close()
+ addtimer(CALLBACK(src, .proc/close), autoclose)
return 1
/obj/machinery/door/proc/close()
diff --git a/code/game/machinery/embedded_controller/access_controller.dm b/code/game/machinery/embedded_controller/access_controller.dm
index 96f6b408cd8..6f4b228e162 100644
--- a/code/game/machinery/embedded_controller/access_controller.dm
+++ b/code/game/machinery/embedded_controller/access_controller.dm
@@ -209,11 +209,13 @@
goIdle(TRUE)
return
A.unbolt()
- spawn()
- if(A && A.open())
- if(stat | (NOPOWER) && !lostPower && A && !QDELETED(A))
- A.bolt()
- goIdle(TRUE)
+ INVOKE_ASYNC(src, .proc/do_openDoor, A)
+
+/obj/machinery/doorButtons/airlock_controller/proc/do_openDoor(obj/machinery/door/airlock/A)
+ if(A && A.open())
+ if(stat | (NOPOWER) && !lostPower && A && !QDELETED(A))
+ A.bolt()
+ goIdle(TRUE)
/obj/machinery/doorButtons/airlock_controller/proc/goIdle(update)
lostPower = FALSE
diff --git a/code/game/machinery/magnet.dm b/code/game/machinery/magnet.dm
index 370621e0c86..05a167f5866 100644
--- a/code/game/machinery/magnet.dm
+++ b/code/game/machinery/magnet.dm
@@ -292,8 +292,7 @@
radio_connection.post_signal(src, signal, filter = RADIO_MAGNETS)
- spawn(1)
- updateUsrDialog() // pretty sure this increases responsiveness
+ updateUsrDialog()
if(href_list["operation"])
switch(href_list["operation"])
@@ -316,7 +315,7 @@
if("togglemoving")
moving = !moving
if(moving)
- spawn() MagnetMove()
+ INVOKE_ASYNC(src, .proc/MagnetMove)
updateUsrDialog()
@@ -353,8 +352,7 @@
pathpos++ // increase iterator
// Broadcast the signal
- spawn()
- radio_connection.post_signal(src, signal, filter = RADIO_MAGNETS)
+ INVOKE_ASYNC(CALLBACK(radio_connection, /datum/radio_frequency.proc/post_signal, src, signal, RADIO_MAGNETS))
if(speed == 10)
sleep(1)
diff --git a/code/game/machinery/porta_turret/portable_turret_cover.dm b/code/game/machinery/porta_turret/portable_turret_cover.dm
index 4df7001c11d..e03c56a92b6 100644
--- a/code/game/machinery/porta_turret/portable_turret_cover.dm
+++ b/code/game/machinery/porta_turret/portable_turret_cover.dm
@@ -92,6 +92,5 @@
to_chat(user, "You short out [parent_turret]'s threat assessment circuits.")
visible_message("[parent_turret] hums oddly...")
parent_turret.obj_flags |= EMAGGED
- parent_turret.on = 0
- spawn(40)
- parent_turret.on = 1
+ parent_turret.on = FALSE
+ addtimer(VARSET_CALLBACK(parent_turret, on, TRUE), 4 SECONDS)
diff --git a/code/game/machinery/slotmachine.dm b/code/game/machinery/slotmachine.dm
index b15b2506e24..3a2cda5bf31 100644
--- a/code/game/machinery/slotmachine.dm
+++ b/code/game/machinery/slotmachine.dm
@@ -207,24 +207,28 @@
balance -= SPIN_PRICE
money += SPIN_PRICE
plays += 1
- working = 1
+ working = TRUE
toggle_reel_spin(1)
update_icon()
updateDialog()
- spawn(0)
- while(working)
- randomize_reels()
- updateDialog()
- sleep(2)
+ var/spin_loop = addtimer(CALLBACK(src, .proc/do_spin), 2, TIMER_LOOP|TIMER_STOPPABLE)
- spawn(SPIN_TIME - (REEL_DEACTIVATE_DELAY * reels.len)) //WARNING: no sanity checking for user since it's not needed and would complicate things (machine should still spin even if user is gone), be wary of this if you're changing this code.
- toggle_reel_spin(0, REEL_DEACTIVATE_DELAY)
- working = 0
- give_prizes(the_name, user)
- update_icon()
- updateDialog()
+ addtimer(CALLBACK(src, .proc/finish_spinning, spin_loop, user, the_name), SPIN_TIME - (REEL_DEACTIVATE_DELAY * reels.len))
+ //WARNING: no sanity checking for user since it's not needed and would complicate things (machine should still spin even if user is gone), be wary of this if you're changing this code.
+
+/obj/machinery/computer/slot_machine/proc/do_spin()
+ randomize_reels()
+ updateDialog()
+
+/obj/machinery/computer/slot_machine/proc/finish_spinning(spin_loop, mob/user, the_name)
+ toggle_reel_spin(0, REEL_DEACTIVATE_DELAY)
+ working = FALSE
+ deltimer(spin_loop)
+ give_prizes(the_name, user)
+ update_icon()
+ updateDialog()
/obj/machinery/computer/slot_machine/proc/can_spin(mob/user)
if(stat & NOPOWER)
diff --git a/code/game/mecha/equipment/tools/other_tools.dm b/code/game/mecha/equipment/tools/other_tools.dm
index 719c5ef474f..75f71f3dbff 100644
--- a/code/game/mecha/equipment/tools/other_tools.dm
+++ b/code/game/mecha/equipment/tools/other_tools.dm
@@ -121,15 +121,17 @@
var/mob/M = A
if(M.mob_negates_gravity())
continue
- spawn(0)
- var/iter = 5-get_dist(A,target)
- for(var/i=0 to iter)
- step_away(A,target)
- sleep(2)
+ INVOKE_ASYNC(src, .proc/do_scatter, A, target)
+
var/turf/T = get_turf(target)
log_game("[key_name(chassis.occupant)] used a Gravitational Catapult repulse wave on [AREACOORD(T)]")
return TRUE
+/obj/item/mecha_parts/mecha_equipment/gravcatapult/proc/do_scatter(atom/movable/A, atom/movable/target)
+ var/iter = 5-get_dist(A,target)
+ for(var/i in 0 to iter)
+ step_away(A,target)
+ sleep(2)
/obj/item/mecha_parts/mecha_equipment/gravcatapult/get_equip_info()
return "[..()] [mode==1?"([locked||"Nothing"])":null] \[S|P\]"
diff --git a/code/game/mecha/mech_fabricator.dm b/code/game/mecha/mech_fabricator.dm
index bad714cc785..1f006967069 100644
--- a/code/game/mecha/mech_fabricator.dm
+++ b/code/game/mecha/mech_fabricator.dm
@@ -351,12 +351,7 @@
add_part_set_to_queue(href_list["partset_to_queue"])
return update_queue_on_page()
if(href_list["process_queue"])
- spawn(0)
- if(processing_queue || being_built)
- return FALSE
- processing_queue = 1
- process_queue()
- processing_queue = 0
+ INVOKE_ASYNC(src, .proc/do_process_queue)
if(href_list["clear_temp"])
temp = null
if(href_list["screen"])
@@ -394,6 +389,13 @@
updateUsrDialog()
return
+/obj/machinery/mecha_part_fabricator/proc/do_process_queue()
+ if(processing_queue || being_built)
+ return FALSE
+ processing_queue = 1
+ process_queue()
+ processing_queue = 0
+
/obj/machinery/mecha_part_fabricator/on_deconstruction()
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
materials.retrieve_all()
diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm
index 3ad94550953..1556afd80b1 100644
--- a/code/game/mecha/mecha.dm
+++ b/code/game/mecha/mecha.dm
@@ -619,15 +619,14 @@
/obj/mecha/Bump(var/atom/obstacle)
if(phasing && get_charge() >= phasing_energy_drain && !throwing)
- spawn()
- if(can_move)
- can_move = 0
- if(phase_state)
- flick(phase_state, src)
- forceMove(get_step(src,dir))
- use_power(phasing_energy_drain)
- sleep(step_in*3)
- can_move = 1
+ if(!can_move)
+ return
+ can_move = 0
+ if(phase_state)
+ flick(phase_state, src)
+ forceMove(get_step(src,dir))
+ use_power(phasing_energy_drain)
+ addtimer(VARSET_CALLBACK(src, can_move, TRUE), step_in*3)
else
if(..()) //mech was thrown
return
diff --git a/code/game/objects/effects/anomalies.dm b/code/game/objects/effects/anomalies.dm
index 51927ce1cce..f05b4d602a2 100644
--- a/code/game/objects/effects/anomalies.dm
+++ b/code/game/objects/effects/anomalies.dm
@@ -235,21 +235,23 @@
if(!A.Move(newloc) && newloc) // if the atom, for some reason, can't move, FORCE them to move! :) We try Move() first to invoke any movement-related checks the atom needs to perform after moving
A.forceMove(newloc)
- spawn()
- if(ismob(A) && !(A in flashers)) // don't flash if we're already doing an effect
- var/mob/M = A
- if(M.client)
- var/obj/blueeffect = new /obj(src)
- blueeffect.screen_loc = "WEST,SOUTH to EAST,NORTH"
- blueeffect.icon = 'icons/effects/effects.dmi'
- blueeffect.icon_state = "shieldsparkles"
- blueeffect.layer = FLASH_LAYER
- blueeffect.plane = FULLSCREEN_PLANE
- blueeffect.mouse_opacity = MOUSE_OPACITY_TRANSPARENT
- M.client.screen += blueeffect
- sleep(20)
- M.client.screen -= blueeffect
- qdel(blueeffect)
+ if(ismob(A) && !(A in flashers)) // don't flash if we're already doing an effect
+ var/mob/M = A
+ if(M.client)
+ INVOKE_ASYNC(src, .proc/blue_effect, M)
+
+/obj/effect/anomaly/bluespace/proc/blue_effect(mob/M)
+ var/obj/blueeffect = new /obj(src)
+ blueeffect.screen_loc = "WEST,SOUTH to EAST,NORTH"
+ blueeffect.icon = 'icons/effects/effects.dmi'
+ blueeffect.icon_state = "shieldsparkles"
+ blueeffect.layer = FLASH_LAYER
+ blueeffect.plane = FULLSCREEN_PLANE
+ blueeffect.mouse_opacity = MOUSE_OPACITY_TRANSPARENT
+ M.client.screen += blueeffect
+ sleep(20)
+ M.client.screen -= blueeffect
+ qdel(blueeffect)
/////////////////////
diff --git a/code/game/objects/items/defib.dm b/code/game/objects/items/defib.dm
index 04f64a6e6de..484739a8423 100644
--- a/code/game/objects/items/defib.dm
+++ b/code/game/objects/items/defib.dm
@@ -232,17 +232,19 @@
return FALSE
/obj/item/defibrillator/proc/cooldowncheck(mob/user)
- spawn(50)
- if(cell)
- if(cell.charge >= paddles.revivecost)
- user.visible_message("[src] beeps: Unit ready.")
- playsound(src, 'sound/machines/defib_ready.ogg', 50, 0)
- else
- user.visible_message("[src] beeps: Charge depleted.")
- playsound(src, 'sound/machines/defib_failed.ogg', 50, 0)
- paddles.cooldown = FALSE
- paddles.update_icon()
- update_icon()
+ addtimer(CALLBACK(src, .proc/finish_charging), 5 SECONDS)
+
+/obj/item/defibrillator/proc/finish_charging()
+ if(cell)
+ if(cell.charge >= paddles.revivecost)
+ visible_message("[src] beeps: Unit ready.")
+ playsound(src, 'sound/machines/defib_ready.ogg', 50, 0)
+ else
+ visible_message("[src] beeps: Charge depleted.")
+ playsound(src, 'sound/machines/defib_failed.ogg', 50, 0)
+ paddles.cooldown = FALSE
+ paddles.update_icon()
+ update_icon()
/obj/item/defibrillator/compact
name = "compact defibrillator"
diff --git a/code/game/objects/items/storage/bags.dm b/code/game/objects/items/storage/bags.dm
index f006a36c974..19151dab924 100644
--- a/code/game/objects/items/storage/bags.dm
+++ b/code/game/objects/items/storage/bags.dm
@@ -298,11 +298,7 @@
STR.quick_empty()
// Make each item scatter a bit
for(var/obj/item/I in oldContents)
- spawn()
- for(var/i = 1, i <= rand(1,2), i++)
- if(I)
- step(I, pick(NORTH,SOUTH,EAST,WEST))
- sleep(rand(2,4))
+ INVOKE_ASYNC(src, .proc/do_scatter, I)
if(prob(50))
playsound(M, 'sound/items/trayhit1.ogg', 50, 1)
@@ -314,6 +310,12 @@
M.Paralyze(40)
update_icon()
+/obj/item/storage/bag/tray/proc/do_scatter(obj/item/I)
+ for(var/i in 1 to rand(1,2))
+ if(I)
+ step(I, pick(NORTH,SOUTH,EAST,WEST))
+ sleep(rand(2,4))
+
/obj/item/storage/bag/tray/update_icon()
cut_overlays()
for(var/obj/item/I in contents)
diff --git a/code/game/objects/items/storage/firstaid.dm b/code/game/objects/items/storage/firstaid.dm
index added8e02e7..0c8d0938d6c 100644
--- a/code/game/objects/items/storage/firstaid.dm
+++ b/code/game/objects/items/storage/firstaid.dm
@@ -201,13 +201,13 @@
var/obj/item/bot_assembly/medbot/A = new
if(istype(src, /obj/item/storage/firstaid/fire))
- A.skin = "ointment"
+ A.set_skin("ointment")
else if(istype(src, /obj/item/storage/firstaid/toxin))
- A.skin = "tox"
+ A.set_skin("tox")
else if(istype(src, /obj/item/storage/firstaid/o2))
- A.skin = "o2"
+ A.set_skin("o2")
else if(istype(src, /obj/item/storage/firstaid/brute))
- A.skin = "brute"
+ A.set_skin("brute")
user.put_in_hands(A)
to_chat(user, "You add [S] to [src].")
A.robot_arm = S.type
diff --git a/code/game/objects/items/tanks/watertank.dm b/code/game/objects/items/tanks/watertank.dm
index 76e00b98b66..4962cf45087 100644
--- a/code/game/objects/items/tanks/watertank.dm
+++ b/code/game/objects/items/tanks/watertank.dm
@@ -279,9 +279,7 @@
step_towards(A, target)
sleep(2)
A.Smoke()
- spawn(100)
- if(src)
- resin_cooldown = FALSE
+ addtimer(VARSET_CALLBACK(src, resin_cooldown, FALSE), 10 SECONDS)
return
if(nozzle_mode == RESIN_FOAM)
if(!Adj|| !isturf(target))
diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm
index 74144d762e2..64efa4a2565 100644
--- a/code/game/objects/items/toys.dm
+++ b/code/game/objects/items/toys.dm
@@ -553,14 +553,10 @@
/obj/item/toy/talking/attack_self(mob/user)
if(!cooldown)
- var/list/messages = generate_messages()
activation_message(user)
playsound(loc, 'sound/machines/click.ogg', 20, 1)
- spawn(0)
- for(var/message in messages)
- toy_talk(user, message)
- sleep(10)
+ INVOKE_ASYNC(src, .proc/do_toy_talk, user)
cooldown = TRUE
spawn(recharge_time)
@@ -577,6 +573,11 @@
/obj/item/toy/talking/proc/generate_messages()
return list(pick(messages))
+/obj/item/toy/talking/proc/do_toy_talk(mob/user)
+ for(var/message in generate_messages())
+ toy_talk(user, message)
+ sleep(10)
+
/obj/item/toy/talking/proc/toy_talk(mob/user, message)
user.loc.visible_message("[icon2html(src, viewers(user.loc))] [message]")
if(chattering)
@@ -1174,9 +1175,7 @@
var/list/possible_sounds = list('sound/voice/hiss1.ogg', 'sound/voice/hiss2.ogg', 'sound/voice/hiss3.ogg', 'sound/voice/hiss4.ogg')
var/chosen_sound = pick(possible_sounds)
playsound(get_turf(src), chosen_sound, 50, 1)
- spawn(45)
- if(src)
- icon_state = "[initial(icon_state)]"
+ addtimer(VARSET_CALLBACK(src, icon_state, "[initial(icon_state)]"), 4.5 SECONDS)
else
to_chat(user, "The string on [src] hasn't rewound all the way!")
return
diff --git a/code/game/objects/structures/musician.dm b/code/game/objects/structures/musician.dm
index 7de9375f920..4e669dd819d 100644
--- a/code/game/objects/structures/musician.dm
+++ b/code/game/objects/structures/musician.dm
@@ -268,8 +268,7 @@
else if(href_list["play"])
playing = TRUE
- spawn()
- playsong(usr)
+ INVOKE_ASYNC(src, .proc/playsong, usr)
else if(href_list["newline"])
var/newline = html_encode(input("Enter your line: ", instrumentObj.name) as text|null)
diff --git a/code/game/objects/structures/statues.dm b/code/game/objects/structures/statues.dm
index 9f7d96bf90d..7595865f504 100644
--- a/code/game/objects/structures/statues.dm
+++ b/code/game/objects/structures/statues.dm
@@ -254,10 +254,9 @@
/obj/structure/statue/bananium/proc/honk()
if(!spam_flag)
- spam_flag = 1
+ spam_flag = TRUE
playsound(src.loc, 'sound/items/bikehorn.ogg', 50, 1)
- spawn(20)
- spam_flag = 0
+ addtimer(VARSET_CALLBACK(src, spam_flag, FALSE), 2 SECONDS)
/////////////////////sandstone/////////////////////////////////////////
diff --git a/code/modules/admin/fun_balloon.dm b/code/modules/admin/fun_balloon.dm
index 636d2934259..d4b7a66ce02 100644
--- a/code/modules/admin/fun_balloon.dm
+++ b/code/modules/admin/fun_balloon.dm
@@ -158,10 +158,11 @@
var/mob/living/M = AM
M.forceMove(get_turf(LA))
to_chat(M, "You're trapped in a deadly arena! To escape, you'll need to drag a severed head to the escape portals.")
- spawn()
- var/obj/effect/mine/pickup/bloodbath/B = new (M)
- B.mineEffect(M)
+ INVOKE_ASYNC(src, .proc/do_bloodbath, M)
+/obj/effect/forcefield/arena_shuttle_entrance/proc/do_bloodbath(mob/living/L)
+ var/obj/effect/mine/pickup/bloodbath/B = new (L)
+ B.mineEffect(L)
/area/shuttle_arena
name = "arena"
diff --git a/code/modules/admin/secrets.dm b/code/modules/admin/secrets.dm
index bbbc998b0c7..5e770e62144 100644
--- a/code/modules/admin/secrets.dm
+++ b/code/modules/admin/secrets.dm
@@ -288,8 +288,7 @@
return
SSblackbox.record_feedback("nested tally", "admin_secrets_fun_used", 1, list("Monkeyize All Humans"))
for(var/mob/living/carbon/human/H in GLOB.carbon_list)
- spawn(0)
- H.monkeyize()
+ INVOKE_ASYNC(H, /mob/living/carbon.proc/monkeyize)
ok = 1
if("allspecies")
diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm
index b5682b7b559..5040423141f 100644
--- a/code/modules/admin/topic.dm
+++ b/code/modules/admin/topic.dm
@@ -753,8 +753,7 @@
L.Unconscious(100)
sleep(5)
L.forceMove(pick(GLOB.tdome1))
- spawn(50)
- to_chat(L, "You have been sent to the Thunderdome.")
+ addtimer(CALLBACK(GLOBAL_PROC, /proc/to_chat, L, "You have been sent to the Thunderdome."), 5 SECONDS)
log_admin("[key_name(usr)] has sent [key_name(L)] to the thunderdome. (Team 1)")
message_admins("[key_name_admin(usr)] has sent [key_name_admin(L)] to the thunderdome. (Team 1)")
@@ -780,8 +779,7 @@
L.Unconscious(100)
sleep(5)
L.forceMove(pick(GLOB.tdome2))
- spawn(50)
- to_chat(L, "You have been sent to the Thunderdome.")
+ addtimer(CALLBACK(GLOBAL_PROC, /proc/to_chat, L, "You have been sent to the Thunderdome."), 5 SECONDS)
log_admin("[key_name(usr)] has sent [key_name(L)] to the thunderdome. (Team 2)")
message_admins("[key_name_admin(usr)] has sent [key_name_admin(L)] to the thunderdome. (Team 2)")
@@ -804,8 +802,7 @@
L.Unconscious(100)
sleep(5)
L.forceMove(pick(GLOB.tdomeadmin))
- spawn(50)
- to_chat(L, "You have been sent to the Thunderdome.")
+ addtimer(CALLBACK(GLOBAL_PROC, /proc/to_chat, L, "You have been sent to the Thunderdome."), 5 SECONDS)
log_admin("[key_name(usr)] has sent [key_name(L)] to the thunderdome. (Admin.)")
message_admins("[key_name_admin(usr)] has sent [key_name_admin(L)] to the thunderdome. (Admin.)")
@@ -835,8 +832,7 @@
L.Unconscious(100)
sleep(5)
L.forceMove(pick(GLOB.tdomeobserve))
- spawn(50)
- to_chat(L, "You have been sent to the Thunderdome.")
+ addtimer(CALLBACK(GLOBAL_PROC, /proc/to_chat, L, "You have been sent to the Thunderdome."), 5 SECONDS)
log_admin("[key_name(usr)] has sent [key_name(L)] to the thunderdome. (Observer.)")
message_admins("[key_name_admin(usr)] has sent [key_name_admin(L)] to the thunderdome. (Observer.)")
diff --git a/code/modules/admin/verbs/debug.dm b/code/modules/admin/verbs/debug.dm
index 762d66a5cfc..d8985391e63 100644
--- a/code/modules/admin/verbs/debug.dm
+++ b/code/modules/admin/verbs/debug.dm
@@ -245,8 +245,7 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention)
if(ishuman(M))
log_admin("[key_name(src)] has robotized [M.key].")
var/mob/living/carbon/human/H = M
- spawn(0)
- H.Robotize()
+ INVOKE_ASYNC(H, /mob/living/carbon/human.proc/Robotize)
else
alert("Invalid mob")
@@ -283,8 +282,7 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention)
return
log_admin("[key_name(src)] has animalized [M.key].")
- spawn(0)
- M.Animalize()
+ INVOKE_ASYNC(M, /mob.proc/Animalize)
/client/proc/makepAI(turf/T in GLOB.mob_list)
diff --git a/code/modules/assembly/signaler.dm b/code/modules/assembly/signaler.dm
index 500f6f03053..c7140087e68 100644
--- a/code/modules/assembly/signaler.dm
+++ b/code/modules/assembly/signaler.dm
@@ -100,8 +100,7 @@ Code:
code = new_code
if(href_list["send"])
- spawn( 0 )
- signal()
+ INVOKE_ASYNC(src, .proc/signal)
if(usr)
attack_self(usr)
diff --git a/code/modules/atmospherics/machinery/components/binary_devices/dp_vent_pump.dm b/code/modules/atmospherics/machinery/components/binary_devices/dp_vent_pump.dm
index 8ad990b6095..97eba613358 100644
--- a/code/modules/atmospherics/machinery/components/binary_devices/dp_vent_pump.dm
+++ b/code/modules/atmospherics/machinery/components/binary_devices/dp_vent_pump.dm
@@ -167,13 +167,10 @@
if("set_external_pressure" in signal.data)
external_pressure_bound = CLAMP(text2num(signal.data["set_external_pressure"]),0,ONE_ATMOSPHERE*50)
- if("status" in signal.data)
- spawn(2)
- broadcast_status()
- return //do not update_icon
- spawn(2)
- broadcast_status()
- update_icon()
+ addtimer(CALLBACK(src, .proc/broadcast_status), 2)
+
+ if(!("status" in signal.data)) //do not update_icon
+ update_icon()
/obj/machinery/atmospherics/components/binary/dp_vent_pump/high_volume
name = "large dual-port air vent"
diff --git a/code/modules/atmospherics/machinery/components/unary_devices/outlet_injector.dm b/code/modules/atmospherics/machinery/components/unary_devices/outlet_injector.dm
index f0c744d6823..436e80ae018 100644
--- a/code/modules/atmospherics/machinery/components/unary_devices/outlet_injector.dm
+++ b/code/modules/atmospherics/machinery/components/unary_devices/outlet_injector.dm
@@ -127,15 +127,10 @@
var/datum/gas_mixture/air_contents = airs[1]
volume_rate = CLAMP(number, 0, air_contents.volume)
- if("status" in signal.data)
- spawn(2)
- broadcast_status()
- return //do not update_icon
+ addtimer(CALLBACK(src, .proc/broadcast_status), 2)
- spawn(2)
- broadcast_status()
-
- update_icon()
+ if(!("status" in signal.data)) //do not update_icon
+ update_icon()
/obj/machinery/atmospherics/components/unary/outlet_injector/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
diff --git a/code/modules/clothing/suits/reactive_armour.dm b/code/modules/clothing/suits/reactive_armour.dm
index 5a15cd1089e..fec931d54e9 100644
--- a/code/modules/clothing/suits/reactive_armour.dm
+++ b/code/modules/clothing/suits/reactive_armour.dm
@@ -141,8 +141,7 @@
E.Goto(owner, E.move_to_delay, E.minimum_distance)
owner.alpha = 0
owner.visible_message("[owner] is hit by [attack_text] in the chest!") //We pretend to be hit, since blocking it would stop the message otherwise
- spawn(40)
- owner.alpha = initial(owner.alpha)
+ addtimer(VARSET_CALLBACK(owner, alpha, initial(owner.alpha)), 4 SECONDS)
reactivearmor_cooldown = world.time + reactivearmor_cooldown_duration
return 1
diff --git a/code/modules/hydroponics/grown/tomato.dm b/code/modules/hydroponics/grown/tomato.dm
index f4ca793be99..a399c074cba 100644
--- a/code/modules/hydroponics/grown/tomato.dm
+++ b/code/modules/hydroponics/grown/tomato.dm
@@ -134,13 +134,16 @@
to_chat(user, "You begin to awaken the Killer Tomato...")
awakening = 1
- spawn(30)
- if(!QDELETED(src))
- var/mob/living/simple_animal/hostile/killertomato/K = new /mob/living/simple_animal/hostile/killertomato(get_turf(src.loc))
- K.maxHealth += round(seed.endurance / 3)
- K.melee_damage_lower += round(seed.potency / 10)
- K.melee_damage_upper += round(seed.potency / 10)
- K.move_to_delay -= round(seed.production / 50)
- K.health = K.maxHealth
- K.visible_message("The Killer Tomato growls as it suddenly awakens.")
- qdel(src)
+ addtimer(CALLBACK(src, .proc/awaken), 3 SECONDS)
+
+/obj/item/reagent_containers/food/snacks/grown/tomato/killer/proc/awaken()
+ if(QDELETED(src))
+ return
+ var/mob/living/simple_animal/hostile/killertomato/K = new /mob/living/simple_animal/hostile/killertomato(get_turf(src.loc))
+ K.maxHealth += round(seed.endurance / 3)
+ K.melee_damage_lower += round(seed.potency / 10)
+ K.melee_damage_upper += round(seed.potency / 10)
+ K.move_to_delay -= round(seed.production / 50)
+ K.health = K.maxHealth
+ K.visible_message("The Killer Tomato growls as it suddenly awakens.")
+ qdel(src)
diff --git a/code/modules/mob/living/simple_animal/bot/bot.dm b/code/modules/mob/living/simple_animal/bot/bot.dm
index 85dab7a91a0..89a8ff447af 100644
--- a/code/modules/mob/living/simple_animal/bot/bot.dm
+++ b/code/modules/mob/living/simple_animal/bot/bot.dm
@@ -478,8 +478,7 @@ Pass a positive integer as an argument to override a bot's default speed.
if(step_count >= 1 && tries < BOT_STEP_MAX_RETRIES)
for(var/step_number = 0, step_number < step_count,step_number++)
- spawn(BOT_STEP_DELAY*step_number)
- bot_step(dest)
+ addtimer(CALLBACK(src, .proc/bot_step, dest), BOT_STEP_DELAY*step_number)
else
return FALSE
return TRUE
diff --git a/code/modules/mob/living/simple_animal/bot/construction.dm b/code/modules/mob/living/simple_animal/bot/construction.dm
index 9fc83576988..fd66395d044 100644
--- a/code/modules/mob/living/simple_animal/bot/construction.dm
+++ b/code/modules/mob/living/simple_animal/bot/construction.dm
@@ -258,11 +258,10 @@
var/healthanalyzer = /obj/item/healthanalyzer
var/firstaid = /obj/item/storage/firstaid
-/obj/item/bot_assembly/medbot/Initialize()
- . = ..()
- spawn(5)
- if(skin)
- add_overlay("kit_skin_[skin]")
+/obj/item/bot_assembly/medbot/proc/set_skin(skin)
+ src.skin = skin
+ if(skin)
+ add_overlay("kit_skin_[skin]")
/obj/item/bot_assembly/medbot/attackby(obj/item/W, mob/user, params)
..()
diff --git a/code/modules/mob/living/simple_animal/bot/ed209bot.dm b/code/modules/mob/living/simple_animal/bot/ed209bot.dm
index 617963b8dcb..19ac3f75c77 100644
--- a/code/modules/mob/living/simple_animal/bot/ed209bot.dm
+++ b/code/modules/mob/living/simple_animal/bot/ed209bot.dm
@@ -362,8 +362,7 @@ Auto Patrol[]"},
playsound(src, pick('sound/voice/ed209_20sec.ogg', 'sound/voice/edplaceholder.ogg'), 50, FALSE)
visible_message("[src] points at [C.name]!")
mode = BOT_HUNT
- spawn(0)
- handle_automated_action() // ensure bot quickly responds to a perp
+ INVOKE_ASYNC(src, .proc/handle_automated_action) // ensure bot quickly responds to a perp
break
else
continue
@@ -542,8 +541,7 @@ Auto Patrol[]"},
/mob/living/simple_animal/bot/ed209/proc/stun_attack(mob/living/carbon/C)
playsound(src, 'sound/weapons/egloves.ogg', 50, TRUE, -1)
icon_state = "[lasercolor]ed209-c"
- spawn(2)
- icon_state = "[lasercolor]ed209[on]"
+ addtimer(VARSET_CALLBACK(src, icon_state, "[lasercolor]ed209[on]"), 2)
var/threat = 5
C.Paralyze(100)
C.stuttering = 5
diff --git a/code/modules/mob/living/simple_animal/bot/floorbot.dm b/code/modules/mob/living/simple_animal/bot/floorbot.dm
index 8b344ddaa6a..fd49d5c4be3 100644
--- a/code/modules/mob/living/simple_animal/bot/floorbot.dm
+++ b/code/modules/mob/living/simple_animal/bot/floorbot.dm
@@ -239,10 +239,7 @@
mode = BOT_REPAIRING
F.ReplaceWithLattice()
audible_message("[src] makes an excited booping sound.")
- spawn(5)
- anchored = FALSE
- mode = BOT_IDLE
- target = null
+ addtimer(CALLBACK(src, .proc/go_idle), 0.5 SECONDS)
path = list()
return
if(path.len == 0)
@@ -266,6 +263,11 @@
oldloc = loc
+/mob/living/simple_animal/bot/floorbot/proc/go_idle()
+ anchored = FALSE
+ mode = BOT_IDLE
+ target = null
+
/mob/living/simple_animal/bot/floorbot/proc/is_hull_breach(turf/t) //Ignore space tiles not considered part of a structure, also ignores shuttle docking areas.
var/area/t_area = get_area(t)
if(t_area && (t_area.name == "Space" || findtext(t_area.name, "huttle")))
diff --git a/code/modules/mob/living/simple_animal/bot/mulebot.dm b/code/modules/mob/living/simple_animal/bot/mulebot.dm
index 441e36e5465..bd88ccc168e 100644
--- a/code/modules/mob/living/simple_animal/bot/mulebot.dm
+++ b/code/modules/mob/living/simple_animal/bot/mulebot.dm
@@ -448,10 +448,8 @@
process_bot()
num_steps--
if(mode != BOT_IDLE)
- spawn(0)
- for(var/i=num_steps,i>0,i--)
- sleep(2)
- process_bot()
+ var/process_timer = addtimer(CALLBACK(src, .proc/process_bot), 2, TIMER_LOOP|TIMER_STOPPABLE)
+ addtimer(CALLBACK(GLOBAL_PROC, /proc/deltimer, process_timer), (num_steps*2) + 1)
/mob/living/simple_animal/bot/mulebot/proc/process_bot()
if(!on || client)
@@ -515,11 +513,7 @@
buzz(SIGH)
mode = BOT_WAIT_FOR_NAV
blockcount = 0
- spawn(20)
- calc_path(avoid=next)
- if(path.len > 0)
- buzz(DELIGHT)
- mode = BOT_BLOCKED
+ addtimer(CALLBACK(src, .proc/process_blocked, next), 2 SECONDS)
return
return
else
@@ -532,18 +526,26 @@
if(BOT_NAV) // calculate new path
mode = BOT_WAIT_FOR_NAV
- spawn(0)
- calc_path()
+ INVOKE_ASYNC(src, .proc/process_nav)
- if(path.len > 0)
- blockcount = 0
- mode = BOT_BLOCKED
- buzz(DELIGHT)
+/mob/living/simple_animal/bot/mulebot/proc/process_blocked(turf/next)
+ calc_path(avoid=next)
+ if(path.len > 0)
+ buzz(DELIGHT)
+ mode = BOT_BLOCKED
- else
- buzz(SIGH)
+/mob/living/simple_animal/bot/mulebot/proc/process_nav()
+ calc_path()
- mode = BOT_NO_ROUTE
+ if(path.len > 0)
+ blockcount = 0
+ mode = BOT_BLOCKED
+ buzz(DELIGHT)
+
+ else
+ buzz(SIGH)
+
+ mode = BOT_NO_ROUTE
// calculates a path to the current destination
// given an optional turf to avoid
@@ -573,11 +575,13 @@
/mob/living/simple_animal/bot/mulebot/proc/start_home()
if(!on)
return
- spawn(0)
- set_destination(home_destination)
- mode = BOT_BLOCKED
+ INVOKE_ASYNC(src, .proc/do_start_home)
update_icon()
+/mob/living/simple_animal/bot/mulebot/proc/do_start_home()
+ set_destination(home_destination)
+ mode = BOT_BLOCKED
+
// called when bot reaches current target
/mob/living/simple_animal/bot/mulebot/proc/at_target()
if(!reached_target)
diff --git a/code/modules/mob/living/simple_animal/hostile/mecha_pilot.dm b/code/modules/mob/living/simple_animal/hostile/mecha_pilot.dm
index b42627b2bbd..4294706cd3f 100644
--- a/code/modules/mob/living/simple_animal/hostile/mecha_pilot.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mecha_pilot.dm
@@ -241,8 +241,7 @@
addtimer(CALLBACK(mecha.overload_action, /datum/action/innate/mecha/mech_defense_mode.proc/Activate, FALSE), 100) //10 seconds of speeeeed, then toggle off
retreat_distance = 50
- spawn(100)
- retreat_distance = 0
+ addtimer(VARSET_CALLBACK(src, retreat_distance, 0), 10 SECONDS)
@@ -292,4 +291,4 @@
if(mecha)
walk_to(mecha, target, minimum_distance, mecha.step_in)
else
- ..()
\ No newline at end of file
+ ..()
diff --git a/code/modules/mob/living/simple_animal/slime/life.dm b/code/modules/mob/living/simple_animal/slime/life.dm
index 35f82beeead..33f51e19a28 100644
--- a/code/modules/mob/living/simple_animal/slime/life.dm
+++ b/code/modules/mob/living/simple_animal/slime/life.dm
@@ -66,9 +66,8 @@
if(Target in view(1,src))
if(!CanFeedon(Target)) //If they're not able to be fed upon, ignore them.
if(!Atkcool)
- Atkcool = 1
- spawn(45)
- Atkcool = 0
+ Atkcool = TRUE
+ addtimer(VARSET_CALLBACK(src, Atkcool, FALSE), 4.5 SECONDS)
if(Target.Adjacent(src))
Target.attack_slime(src)
@@ -77,9 +76,8 @@
if(Target.client && Target.health >= 20)
if(!Atkcool)
- Atkcool = 1
- spawn(45)
- Atkcool = 0
+ Atkcool = TRUE
+ addtimer(VARSET_CALLBACK(src, Atkcool, FALSE), 4.5 SECONDS)
if(Target.Adjacent(src))
Target.attack_slime(src)
diff --git a/code/modules/mob/living/simple_animal/slime/slime.dm b/code/modules/mob/living/simple_animal/slime/slime.dm
index eb7695a3e24..cd5b9301a9f 100644
--- a/code/modules/mob/living/simple_animal/slime/slime.dm
+++ b/code/modules/mob/living/simple_animal/slime/slime.dm
@@ -222,9 +222,8 @@
if(nutrition <= get_hunger_nutrition() && !Atkcool)
if (is_adult || prob(5))
O.attack_slime(src)
- Atkcool = 1
- spawn(45)
- Atkcool = 0
+ Atkcool = TRUE
+ addtimer(VARSET_CALLBACK(src, Atkcool, FALSE), 4.5 SECONDS)
/mob/living/simple_animal/slime/Process_Spacemove(movement_dir = 0)
return 2