diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 4bb47694b0a..728c761485b 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -955,7 +955,7 @@ modules/mob/living/carbon/human/life.dm if you die, you will be zoomed out. A.update_button_icon() /obj/item/proc/extinguish(atom/target, mob/user) - if (reagents.total_volume < 1) + if(reagents.total_volume < 1) to_chat(user, span_warning("\The [src]'s water reserves are empty.")) return @@ -964,91 +964,95 @@ modules/mob/living/carbon/human/life.dm if you die, you will be zoomed out. playsound(user.loc, 'sound/effects/extinguish.ogg', 52, 1, 7) - var/direction = get_dir(user,target) - - if(user.buckled && isobj(user.buckled) && !user.buckled.anchored ) - spawn(0) - var/obj/structure/bed/chair/C = null - if(istype(user.buckled, /obj/structure/bed/chair)) - C = user.buckled - var/obj/B = user.buckled - var/movementdirection = REVERSE_DIR(direction) - if(C) - C.propelled = 4 - B.Move(get_step(user,movementdirection), movementdirection) - sleep(0.1 SECONDS) - B.Move(get_step(user,movementdirection), movementdirection) - if(C) - C.propelled = 3 - sleep(0.1 SECONDS) - B.Move(get_step(user,movementdirection), movementdirection) - sleep(0.1 SECONDS) - B.Move(get_step(user,movementdirection), movementdirection) - if(C) - C.propelled = 2 - sleep(0.2 SECONDS) - B.Move(get_step(user,movementdirection), movementdirection) - if(C) - C.propelled = 1 - sleep(0.2 SECONDS) - B.Move(get_step(user,movementdirection), movementdirection) - if(C) - C.propelled = 0 - sleep(0.3 SECONDS) - B.Move(get_step(user,movementdirection), movementdirection) - sleep(0.3 SECONDS) - B.Move(get_step(user,movementdirection), movementdirection) - sleep(0.3 SECONDS) - B.Move(get_step(user,movementdirection), movementdirection) + var/direction = get_dir(user, target) - var/turf/T = get_turf(target) - var/turf/T1 = get_step(T,turn(direction, 90)) - var/turf/T2 = get_step(T,turn(direction, -90)) + if(user.buckled && isobj(user.buckled) && !user.buckled.anchored) + INVOKE_ASYNC(src, PROC_REF(propelle), target, user, direction) - var/list/the_targets = list(T,T1,T2) - - for(var/a=0, a<7, a++) - spawn(0) - var/obj/effect/particle_effect/water/W = new /obj/effect/particle_effect/water( get_turf(user) ) - var/turf/my_target = pick(the_targets) - var/datum/reagents/R = new/datum/reagents(5) - if(!W) - return - W.reagents = R - R.my_atom = WEAKREF(W) - if(!W || !src) - return - reagents.trans_to(W,1) - for(var/b=0, b<7, b++) - step_towards(W,my_target) - if(!(W?.reagents)) - return - W.reagents.reaction(get_turf(W)) - for(var/atom/atm in get_turf(W)) - if(!W) - return - if(!W.reagents) - break - W.reagents.reaction(atm) - if(isfire(atm)) - var/obj/fire/FF = atm - FF.set_fire(FF.burn_ticks - EXTINGUISH_AMOUNT) - continue - if(isliving(atm)) //For extinguishing mobs on fire - var/mob/living/M = atm - M.ExtinguishMob() - for(var/obj/item/clothing/mask/cigarette/C in M.contents) - if(C.item_state == C.icon_on) - C.die() - if(W.loc == my_target) - break - sleep(0.2 SECONDS) - qdel(W) + for(var/a = 0, a < 7, a++) + INVOKE_ASYNC(src, PROC_REF(extinguish_stage_two), target, user, direction) if(isspaceturf(user.loc)) user.inertia_dir = get_dir(target, user) step(user, user.inertia_dir) +/obj/item/proc/propelle(atom/target, mob/user, direction) + var/obj/structure/bed/chair/C = null + if(istype(user.buckled, /obj/structure/bed/chair)) + C = user.buckled + var/obj/B = user.buckled + var/movementdirection = REVERSE_DIR(direction) + if(C) + C.propelled = 4 + B.Move(get_step(user, movementdirection), movementdirection) + sleep(0.1 SECONDS) + B.Move(get_step(user, movementdirection), movementdirection) + if(C) + C.propelled = 3 + sleep(0.1 SECONDS) + B.Move(get_step(user, movementdirection), movementdirection) + sleep(0.1 SECONDS) + B.Move(get_step(user, movementdirection), movementdirection) + if(C) + C.propelled = 2 + sleep(0.2 SECONDS) + B.Move(get_step(user, movementdirection), movementdirection) + if(C) + C.propelled = 1 + sleep(0.2 SECONDS) + B.Move(get_step(user, movementdirection), movementdirection) + if(C) + C.propelled = 0 + sleep(0.3 SECONDS) + B.Move(get_step(user, movementdirection), movementdirection) + sleep(0.3 SECONDS) + B.Move(get_step(user, movementdirection), movementdirection) + sleep(0.3 SECONDS) + B.Move(get_step(user, movementdirection), movementdirection) + +/obj/item/proc/extinguish_stage_two(atom/target, mob/user, direction) + var/turf/T = get_turf(target) + var/turf/T1 = get_step(T, turn(direction, 90)) + var/turf/T2 = get_step(T, turn(direction, -90)) + + var/list/the_targets = list(T, T1, T2) + + var/obj/effect/particle_effect/water/W = new /obj/effect/particle_effect/water( get_turf(user) ) + var/turf/my_target = pick(the_targets) + var/datum/reagents/R = new/datum/reagents(5) + if(!W) + return + W.reagents = R + R.my_atom = WEAKREF(W) + if(!W || !src) + return + reagents.trans_to(W, 1) + for(var/b = 0, b < 7, b++) + step_towards(W,my_target) + if(!(W?.reagents)) + return + W.reagents.reaction(get_turf(W)) + for(var/atom/atm in get_turf(W)) + if(!W) + return + if(!W.reagents) + break + W.reagents.reaction(atm) + if(isfire(atm)) + var/obj/fire/FF = atm + FF.set_fire(FF.burn_ticks - EXTINGUISH_AMOUNT) + continue + if(isliving(atm)) //For extinguishing mobs on fire + var/mob/living/M = atm + M.ExtinguishMob() + for(var/obj/item/clothing/mask/cigarette/C in M.contents) + if(C.item_state != C.icon_on) + continue + C.die() + if(W.loc == my_target) + break + sleep(0.2 SECONDS) + qdel(W) // Called when a mob tries to use the item as a tool. // Handles most checks. @@ -1265,8 +1269,7 @@ modules/mob/living/carbon/human/life.dm if you die, you will be zoomed out. basic_spin_trick(arglist(arguments)) if(7) if(istype(double)) - spawn(0) - double.throw_catch_trick(user) + INVOKE_ASYNC(double, PROC_REF(throw_catch_trick), user) throw_catch_trick(user) else throw_catch_trick(user) diff --git a/code/game/objects/items/power_cells.dm b/code/game/objects/items/power_cells.dm index 27dd09a990a..1bfdc6d7f42 100644 --- a/code/game/objects/items/power_cells.dm +++ b/code/game/objects/items/power_cells.dm @@ -90,9 +90,11 @@ var/mob/living/carbon/C = user C.throw_mode_on() overlays += new/obj/effect/overlay/danger - spawn(rand(3,50)) - spark_system.start(src) - explode() + addtimer(CALLBACK(src, PROC_REF(delayed_explosion), spark_system), rand(3, 50)) + +/obj/item/cell/proc/delayed_explosion(datum/effect_system/spark_spread/spark_system) + spark_system.start(src) + explode() /obj/item/cell/attackby(obj/item/I, mob/user, params) . = ..() diff --git a/code/game/objects/items/reagent_containers/food/snacks.dm b/code/game/objects/items/reagent_containers/food/snacks.dm index 040a474a61f..0b941ab097e 100644 --- a/code/game/objects/items/reagent_containers/food/snacks.dm +++ b/code/game/objects/items/reagent_containers/food/snacks.dm @@ -545,21 +545,25 @@ icon_state = "donkpocket" filling_color = "#DEDEAB" list_reagents = list(/datum/reagent/consumable/nutriment = 4) - var/warm = 0 tastes = list("meat" = 2, "dough" = 2, "laziness" = 1) + var/warm = FALSE /obj/item/reagent_containers/food/snacks/donkpocket/proc/cooltime() - if(warm) - spawn( 4200 ) - if(!gc_destroyed) //not cdel'd - warm = 0 - reagents.del_reagent(/datum/reagent/medicine/tricordrazine) - name = "donk-pocket" + if(!warm) + return + addtimer(CALLBACK(src, PROC_REF(cool_down)), 7 MINUTES) + +/obj/item/reagent_containers/food/snacks/donkpocket/proc/cool_down() + if(QDELETED(src)) + return + warm = FALSE + reagents.del_reagent(/datum/reagent/medicine/tricordrazine) + name = "donk-pocket" /obj/item/reagent_containers/food/snacks/human + filling_color = "#D63C3C" var/hname = "" var/job = null - filling_color = "#D63C3C" /obj/item/reagent_containers/food/snacks/omelette name = "Omelette Du Fromage" diff --git a/code/game/objects/items/reagent_containers/spray.dm b/code/game/objects/items/reagent_containers/spray.dm index ddec7099e39..218ef32af4b 100644 --- a/code/game/objects/items/reagent_containers/spray.dm +++ b/code/game/objects/items/reagent_containers/spray.dm @@ -58,26 +58,26 @@ /obj/item/reagent_containers/spray/proc/Spray_at(atom/A) var/obj/effect/decal/chempuff/D = new/obj/effect/decal/chempuff(get_turf(src)) D.create_reagents(amount_per_transfer_from_this) - reagents.trans_to(D, amount_per_transfer_from_this, 1/spray_size) + reagents.trans_to(D, amount_per_transfer_from_this, 1 / spray_size) D.color = mix_color_from_reagents(D.reagents.reagent_list) - var/turf/A_turf = get_turf(A)//BS12 + INVOKE_ASYNC(src, PROC_REF(spray_step), A, D) +/obj/item/reagent_containers/spray/proc/spray_step(atom/our_atom, obj/effect/decal/chempuff/our_decal) + var/turf/A_turf = get_turf(our_atom)//BS12 var/spray_dist = spray_size - spawn(0) - for(var/i=0, i 9) + cameraFollow = null + to_chat(src, span_warning("Unable to reacquire, cancelling track...")) + tracking = FALSE return - - if(!target.can_track(src)) - tracking = TRUE - if(!cameraticks) - to_chat(src, span_warning("Target is not near any active cameras. Attempting to reacquire...")) - cameraticks++ - if(cameraticks > 9) - cameraFollow = null - to_chat(src, span_warning("Unable to reacquire, cancelling track...")) - tracking = FALSE - return - else - sleep(1 SECONDS) - continue - else - cameraticks = 0 - tracking = FALSE - - if(eyeobj) - eyeobj.setLoc(get_turf(target)) + sleep(1 SECONDS) + continue + else + cameraticks = 0 + tracking = FALSE - else - view_core() - cameraFollow = null - return + if(eyeobj) + eyeobj.setLoc(get_turf(target)) - sleep(1 SECONDS) + else + view_core() + cameraFollow = null + return + sleep(1 SECONDS) /proc/near_camera(mob/living/M) if(!isturf(M.loc)) diff --git a/code/game/objects/machinery/computer/area_air_control.dm b/code/game/objects/machinery/computer/area_air_control.dm index d609fb2bd46..4e22333b94a 100644 --- a/code/game/objects/machinery/computer/area_air_control.dm +++ b/code/game/objects/machinery/computer/area_air_control.dm @@ -87,20 +87,21 @@ var/obj/machinery/portable_atmospherics/scrubber/huge/scrubber = locate(href_list["scrub"]) if(!validscrubber(scrubber)) - spawn(20) - status = "ERROR: Couldn't connect to scrubber! (timeout)" - connectedscrubbers -= scrubber - src.updateUsrDialog() + addtimer(CALLBACK(src, PROC_REF(send_error_message), scrubber), 2 SECONDS) return scrubber.on = text2num(href_list["toggle"]) scrubber.update_icon() -/obj/machinery/computer/area_atmos/proc/validscrubber( obj/machinery/portable_atmospherics/scrubber/huge/scrubber as obj ) - if(!isobj(scrubber) || get_dist(scrubber.loc, src.loc) > src.range || scrubber.loc.z != src.loc.z) - return 0 +/obj/machinery/computer/area_atmos/proc/send_error_message(obj/machinery/portable_atmospherics/scrubber/huge/scrubber) + status = "ERROR: Couldn't connect to scrubber! (timeout)" + connectedscrubbers -= scrubber + updateUsrDialog() - return 1 +/obj/machinery/computer/area_atmos/proc/validscrubber(obj/machinery/portable_atmospherics/scrubber/huge/scrubber as obj) + if(!isobj(scrubber) || get_dist(scrubber.loc, src.loc) > src.range || scrubber.loc.z != src.loc.z) + return FALSE + return TRUE /obj/machinery/computer/area_atmos/proc/scanscrubbers() connectedscrubbers = new() diff --git a/code/game/objects/machinery/computer/communications.dm b/code/game/objects/machinery/computer/communications.dm index d447b229925..29c62ad5836 100644 --- a/code/game/objects/machinery/computer/communications.dm +++ b/code/game/objects/machinery/computer/communications.dm @@ -181,14 +181,8 @@ if(!SSevacuation.cancel_evacuation()) to_chat(usr, span_warning("You are unable to cancel the evacuation right now!")) return FALSE - - spawn(35)//some time between AI announcements for evac cancel and SD cancel. - if(SSevacuation.evac_status == EVACUATION_STATUS_STANDING_BY)//nothing changed during the wait - //if the self_destruct is active we try to cancel it (which includes lowering alert level to red) - if(!SSevacuation.cancel_self_destruct(1)) - //if SD wasn't active (likely canceled manually in the SD room), then we lower the alert level manually. - GLOB.marine_main_ship.set_security_level(SEC_LEVEL_RED, TRUE) //both SD and evac are inactive, lowering the security level. - + //some time between AI announcements for evac cancel and SD cancel. + addtimer(CALLBACK(src, PROC_REF(evacuation_cancel)), 3.5 SECONDS) log_game("[key_name(usr)] has canceled the emergency evacuation.") message_admins("[ADMIN_TPMONTY(usr)] has canceled the emergency evacuation.") return TRUE @@ -332,6 +326,14 @@ updateUsrDialog() +/obj/machinery/computer/communications/proc/evacuation_cancel() + if(SSevacuation.evac_status != EVACUATION_STATUS_STANDING_BY) // nothing changed during the wait + return + //if the self_destruct is active we try to cancel it (which includes lowering alert level to red) + if(SSevacuation.cancel_self_destruct(TRUE)) + return + //if SD wasn't active (likely canceled manually in the SD room), then we lower the alert level manually. + GLOB.marine_main_ship.set_security_level(SEC_LEVEL_RED, TRUE) //both SD and evac are inactive, lowering the security level. /obj/machinery/computer/communications/interact(mob/user) . = ..() diff --git a/code/game/objects/machinery/doors/airlock.dm b/code/game/objects/machinery/doors/airlock.dm index 6c7ac223929..229553d728e 100644 --- a/code/game/objects/machinery/doors/airlock.dm +++ b/code/game/objects/machinery/doors/airlock.dm @@ -55,8 +55,7 @@ if(!justzap) if(shock(user, 100)) justzap = TRUE - spawn(openspeed) - justzap = FALSE + addtimer(VARSET_CALLBACK(src, justzap, FALSE), openspeed) return else /*if(justzap)*/ return @@ -208,14 +207,16 @@ /obj/machinery/door/airlock/do_animate(animation) switch(animation) if("opening") - if(overlays) overlays.Cut() + if(overlays) + overlays.Cut() if(CHECK_BITFIELD(machine_stat, PANEL_OPEN)) spawn(2) // The only work around that works. Downside is that the door will be gone for a millisecond. flick("o_door_opening", src) //can not use flick due to BYOND bug updating overlays right before flicking else flick("door_opening", src) if("closing") - if(overlays) overlays.Cut() + if(overlays) + overlays.Cut() if(CHECK_BITFIELD(machine_stat, PANEL_OPEN)) flick("o_door_closing", src) else diff --git a/code/game/objects/machinery/doors/door.dm b/code/game/objects/machinery/doors/door.dm index dcb34c58043..76bbe4f2c16 100644 --- a/code/game/objects/machinery/doors/door.dm +++ b/code/game/objects/machinery/doors/door.dm @@ -140,8 +140,7 @@ if(prob(40/severity)) if(secondsElectrified == 0) secondsElectrified = -1 - spawn(300) - secondsElectrified = 0 + addtimer(VARSET_CALLBACK(src, secondsElectrified, 0), 30 SECONDS) return ..() /obj/machinery/door/ex_act(severity) diff --git a/code/game/objects/machinery/doors/firedoor.dm b/code/game/objects/machinery/doors/firedoor.dm index eb41d9fb34c..236fa75ec29 100644 --- a/code/game/objects/machinery/doors/firedoor.dm +++ b/code/game/objects/machinery/doors/firedoor.dm @@ -136,10 +136,12 @@ to_chat(xeno_attacker, span_warning("\The [src] is welded shut.")) return FALSE if(density) //Make sure it's still closed - spawn(0) - open(1) - xeno_attacker.visible_message(span_danger("\The [xeno_attacker] pries \the [src] open."), \ - span_danger("We pry \the [src] open."), null, 5) + INVOKE_ASYNC(src, PROC_REF(xeno_open), xeno_attacker) + +/obj/machinery/door/firedoor/proc/xeno_open(mob/living/carbon/xenomorph/xeno_attacker) + open(TRUE) + xeno_attacker.visible_message(span_danger("\The [xeno_attacker] pries \the [src] open."), \ + span_danger("We pry \the [src] open."), null, 5) /obj/machinery/door/firedoor/attack_hand(mob/living/user) . = ..() @@ -187,14 +189,16 @@ close() if(needs_to_close) - spawn(50) - alarmed = FALSE - for(var/area/A in areas_added) //Just in case a fire alarm is turned off while the firedoor is going through an autoclose cycle - if(A.flags_alarm_state & ALARM_WARNING_FIRE || A.air_doors_activated) - alarmed = TRUE - if(alarmed) - nextstate = FIREDOOR_CLOSED - close() + addtimer(CALLBACK(src, PROC_REF(closing_process)), 5 SECONDS) + +/obj/machinery/door/firedoor/proc/closing_process() + var/alarmed = FALSE + for(var/area/A in areas_added) // Just in case a fire alarm is turned off while the firedoor is going through an autoclose cycle + if(A.flags_alarm_state & ALARM_WARNING_FIRE || A.air_doors_activated) + alarmed = TRUE + if(alarmed) + nextstate = FIREDOOR_CLOSED + close() /obj/machinery/door/firedoor/attackby(obj/item/I, mob/user, params) . = ..() diff --git a/code/game/objects/machinery/fire_alarm.dm b/code/game/objects/machinery/fire_alarm.dm index 90d74f82c71..498d250372e 100644 --- a/code/game/objects/machinery/fire_alarm.dm +++ b/code/game/objects/machinery/fire_alarm.dm @@ -128,13 +128,15 @@ to_chat(user, span_warning("You need 5 pieces of cable to do wire \the [src].")) return else if(iscrowbar(I)) - to_chat(user, "You pry out the circuit!") + to_chat(user, "You start prying out the circuit!") playsound(loc, 'sound/items/crowbar.ogg', 25, 1) - spawn(20) - new /obj/item/circuitboard/firealarm(loc) - electronics = null - buildstage = 0 - update_icon() + + if(!do_after(user, 2 SECONDS, NONE, src, BUSY_ICON_BUILD)) + return + new /obj/item/circuitboard/firealarm(loc) + electronics = null + buildstage = 0 + update_icon() if(0) if(istype(I, /obj/item/circuitboard/firealarm)) to_chat(user, "You insert the circuit!") diff --git a/code/game/objects/machinery/kitchen/smartfridge.dm b/code/game/objects/machinery/kitchen/smartfridge.dm index a7b045e0a83..214015960b9 100644 --- a/code/game/objects/machinery/kitchen/smartfridge.dm +++ b/code/game/objects/machinery/kitchen/smartfridge.dm @@ -193,30 +193,27 @@ /obj/machinery/smartfridge/proc/throw_item() var/obj/throw_item = null - var/mob/living/target = locate() in view(7,src) + var/mob/living/target = locate() in view(7, src) if(!target) - return 0 + return FALSE - for (var/O in item_quants) + for(var/O in item_quants) if(item_quants[O] <= 0) //Try to use a record that actually has something to dump. continue item_quants[O]-- for(var/obj/T in contents) - if(T.name == O) - T.loc = src.loc - throw_item = T - break + if(T.name != O) + continue + T.loc = loc + throw_item = T + break break if(!throw_item) - return 0 - spawn(0) - throw_item.throw_at(target,16,3,src) - src.visible_message(span_danger("[src] launches [throw_item.name] at [target.name]!")) - return 1 - - - + return FALSE + INVOKE_ASYNC(throw_item, TYPE_PROC_REF(/atom/movable, throw_at), target, 16, 3, src) + visible_message(span_danger("[src] launches [throw_item.name] at [target.name]!")) + return TRUE /******************** * Smartfridge types diff --git a/code/game/objects/machinery/telecomms/machines/broadcaster.dm b/code/game/objects/machinery/telecomms/machines/broadcaster.dm index 50396e5ad28..14d399caaba 100644 --- a/code/game/objects/machinery/telecomms/machines/broadcaster.dm +++ b/code/game/objects/machinery/telecomms/machines/broadcaster.dm @@ -52,13 +52,14 @@ GLOBAL_VAR_INIT(message_delay, 0) // To make sure restarting the recentmessages if(!GLOB.message_delay) GLOB.message_delay = 1 - spawn(10) - GLOB.message_delay = 0 - GLOB.recentmessages = list() + addtimer(CALLBACK(src, PROC_REF(clear_recent_messages)), 1 SECONDS) /* --- Do a snazzy animation! --- */ flick("broadcaster_send", src) +/obj/machinery/telecomms/broadcaster/proc/clear_recent_messages() + GLOB.message_delay = 0 + GLOB.recentmessages = list() /obj/machinery/telecomms/broadcaster/Destroy() // In case message_delay is left on 1, otherwise it won't reset the list and people can't say the same thing twice anymore. diff --git a/code/game/objects/machinery/vending/vending.dm b/code/game/objects/machinery/vending/vending.dm index d26262b8afe..cc1a0d1f872 100644 --- a/code/game/objects/machinery/vending/vending.dm +++ b/code/game/objects/machinery/vending/vending.dm @@ -480,10 +480,8 @@ vend_ready = 0 //One thing at a time!! R.amount-- - if(((src.last_reply + (src.vend_delay + 200)) <= world.time) && src.vend_reply) - spawn(0) - src.speak(src.vend_reply) - src.last_reply = world.time + if(((last_reply + (src.vend_delay + 200)) <= world.time) && vend_reply) + INVOKE_ASYNC(src, PROC_REF(speak_on_vend)) var/obj/item/new_item = release_item(R, vend_delay) @@ -491,6 +489,10 @@ new_item.on_vend(user, faction, fill_container = TRUE) vend_ready = 1 +/obj/machinery/vending/proc/speak_on_vend() + speak(vend_reply) + last_reply = world.time + /obj/machinery/vending/proc/release_item(datum/vending_product/R, delay_vending = 0, dump_product = 0) if(delay_vending) if(powered(power_channel)) @@ -778,8 +780,7 @@ break if (!throw_item) return FALSE - spawn(0) - throw_item.throw_at(target, 16, 3, src) + INVOKE_ASYNC(throw_item, TYPE_PROC_REF(/atom/movable, throw_at), target, 16, 3, src) src.visible_message(span_warning("[src] launches [throw_item.name] at [target]!")) . = TRUE diff --git a/code/game/objects/structures/barricade.dm b/code/game/objects/structures/barricade.dm index e18c35d6c0a..41229db0680 100644 --- a/code/game/objects/structures/barricade.dm +++ b/code/game/objects/structures/barricade.dm @@ -151,18 +151,20 @@ return ..() /obj/structure/barricade/ex_act(severity, direction) + if(QDELETED(src)) + return for(var/obj/structure/barricade/barricade in get_step(src, dir)) //discourage double-stacking barricades by removing health from opposing barricade - if(barricade.dir == REVERSE_DIR(dir)) - spawn(1) - if(barricade) - barricade.ex_act(severity, direction) + if(barricade.dir != REVERSE_DIR(dir)) + continue + INVOKE_ASYNC(src, TYPE_PROC_REF(/atom, ex_act), severity, direction) take_damage(severity, BRUTE, BOMB, attack_dir = direction) update_icon() /obj/structure/barricade/on_explosion_destruction(severity, direction) create_shrapnel(get_turf(src), rand(2,5), direction, shrapnel_type = /datum/ammo/bullet/shrapnel/light) if(prob(50)) // no message spam pls - visible_message(span_warning("[src] blows apart in the explosion, sending shards flying!")) + return + visible_message(span_warning("[src] blows apart in the explosion, sending shards flying!")) /obj/structure/barricade/get_explosion_resistance(direction) if(!density || direction == turn(dir, 90) || direction == turn(dir, -90)) diff --git a/code/game/objects/structures/crates_lockers/closets/fireaxe.dm b/code/game/objects/structures/crates_lockers/closets/fireaxe.dm index 69449f3b73a..2d3beb7b887 100644 --- a/code/game/objects/structures/crates_lockers/closets/fireaxe.dm +++ b/code/game/objects/structures/crates_lockers/closets/fireaxe.dm @@ -2,17 +2,18 @@ /obj/structure/closet/fireaxecabinet name = "Fire Axe Cabinet" desc = "There is small label that reads \"For Emergency use only\" along with details for safe use of the axe. As if." - var/obj/item/weapon/twohanded/fireaxe/fireaxe = new/obj/item/weapon/twohanded/fireaxe icon_state = "fireaxe1000" icon_closed = "fireaxe1000" icon_opened = "fireaxe1100" anchored = TRUE density = FALSE - var/localopened = 0 //Setting this to keep it from behaviouring like a normal closet and obstructing movement in the map. -Agouri opened = 1 - var/hitstaken = 0 locked = TRUE + var/hitstaken = 0 + ///Setting this to keep it from behaviouring like a normal closet and obstructing movement in the map. -Agouri + var/localopened = 0 var/smashed = 0 + var/obj/item/weapon/twohanded/fireaxe/fireaxe = new/obj/item/weapon/twohanded/fireaxe /obj/structure/closet/fireaxecabinet/attackby(obj/item/O, mob/user) //Marker -Agouri //..() //That's very useful, Erro @@ -21,7 +22,7 @@ if(fireaxe) hasaxe = 1 - if (locked) + if(locked) if(ismultitool(O)) to_chat(user, span_warning("Resetting circuitry...")) playsound(user, 'sound/machines/lockreset.ogg', 25, 1) @@ -32,65 +33,62 @@ return else if(!(O.flags_item & NOBLUDGEON) && O.force) var/obj/item/W = O - if(src.smashed || src.localopened) + if(smashed || localopened) if(localopened) localopened = 0 icon_state = "fireaxe[hasaxe][localopened][hitstaken][smashed]closing" - spawn(10) update_icon() + addtimer(CALLBACK(src, TYPE_PROC_REF(/atom, update_icon)), 1 SECONDS) return else playsound(user, 'sound/effects/Glasshit.ogg', 25, 1) //We don't want this playing every time if(W.force < 15) to_chat(user, span_notice("The cabinet's protective glass glances off the hit.")) else - src.hitstaken++ - if(src.hitstaken == 4) + hitstaken++ + if(hitstaken == 4) playsound(user, 'sound/effects/glassbr3.ogg', 50, 1) //Break cabinet, receive goodies. Cabinet's fucked for life after that. - src.smashed = 1 - src.locked = 0 - src.localopened = 1 + smashed = 1 + locked = 0 + localopened = 1 update_icon() return - if (istype(O, /obj/item/weapon/twohanded/fireaxe) && src.localopened) + if(istype(O, /obj/item/weapon/twohanded/fireaxe) && localopened) if(!fireaxe) if(O.flags_item & WIELDED) to_chat(user, span_warning("Unwield the axe first.")) return fireaxe = O user.drop_held_item() - src.contents += O - to_chat(user, span_notice("You place the fire axe back in the [src.name].")) + contents += O + to_chat(user, span_notice("You place the fire axe back in the [name].")) update_icon() else - if(src.smashed) + if(smashed) return else localopened = !localopened if(localopened) icon_state = "fireaxe[hasaxe][localopened][hitstaken][smashed]opening" - spawn(10) - update_icon() + addtimer(CALLBACK(src, TYPE_PROC_REF(/atom, update_icon)), 1 SECONDS) else icon_state = "fireaxe[hasaxe][localopened][hitstaken][smashed]closing" - spawn(10) - update_icon() + addtimer(CALLBACK(src, TYPE_PROC_REF(/atom, update_icon)), 1 SECONDS) else - if(src.smashed) + if(smashed) return if(ismultitool(O)) if(localopened) localopened = 0 icon_state = "fireaxe[hasaxe][localopened][hitstaken][smashed]closing" - spawn(10) - update_icon() + addtimer(CALLBACK(src, TYPE_PROC_REF(/atom, update_icon)), 1 SECONDS) return else to_chat(user, span_warning("Resetting circuitry...")) sleep(5 SECONDS) - src.locked = 1 + locked = 1 to_chat(user, span_notice("You re-enable the locking modules.")) playsound(user, 'sound/machines/lockenable.ogg', 25, 1) - if(do_after(user,20, NONE, src, BUSY_ICON_BUILD)) + if(do_after(user, 20, NONE, src, BUSY_ICON_BUILD)) locked = TRUE to_chat(user, " You re-enable the locking modules.") return @@ -98,22 +96,17 @@ localopened = !localopened if(localopened) icon_state = "fireaxe[hasaxe][localopened][hitstaken][smashed]opening" - spawn(10) - update_icon() + addtimer(CALLBACK(src, TYPE_PROC_REF(/atom, update_icon)), 1 SECONDS) else icon_state = "fireaxe[hasaxe][localopened][hitstaken][smashed]closing" - spawn(10) - update_icon() - - - + addtimer(CALLBACK(src, TYPE_PROC_REF(/atom, update_icon)), 1 SECONDS) /obj/structure/closet/fireaxecabinet/attack_hand(mob/user as mob) var/hasaxe = 0 if(fireaxe) hasaxe = 1 if(!ishuman(user)) return - if(src.locked) + if(locked) to_chat(user, span_warning("The cabinet won't budge!")) return if(localopened) @@ -123,38 +116,34 @@ to_chat(user, span_notice("You take the fire axe from the [name].")) update_icon() else - if(src.smashed) + if(smashed) return else localopened = !localopened if(localopened) - src.icon_state = "fireaxe[hasaxe][localopened][hitstaken][smashed]opening" - spawn(10) - update_icon() + icon_state = "fireaxe[hasaxe][localopened][hitstaken][smashed]opening" + addtimer(CALLBACK(src, TYPE_PROC_REF(/atom, update_icon)), 1 SECONDS) else - src.icon_state = "fireaxe[hasaxe][localopened][hitstaken][smashed]closing" - spawn(10) - update_icon() + icon_state = "fireaxe[hasaxe][localopened][hitstaken][smashed]closing" + addtimer(CALLBACK(src, TYPE_PROC_REF(/atom, update_icon)), 1 SECONDS) else - localopened = !localopened //I'm pretty sure we don't need an if(src.smashed) in here. In case I'm wrong and it fucks up teh cabinet, **MARKER**. -Agouri + localopened = !localopened //I'm pretty sure we don't need an if(smashed) in here. In case I'm wrong and it fucks up teh cabinet, **MARKER**. -Agouri if(localopened) - src.icon_state = "fireaxe[hasaxe][localopened][hitstaken][smashed]opening" - spawn(10) - update_icon() + icon_state = "fireaxe[hasaxe][localopened][hitstaken][smashed]opening" + addtimer(CALLBACK(src, TYPE_PROC_REF(/atom, update_icon)), 1 SECONDS) else - src.icon_state = "fireaxe[hasaxe][localopened][hitstaken][smashed]closing" - spawn(10) - update_icon() + icon_state = "fireaxe[hasaxe][localopened][hitstaken][smashed]closing" + addtimer(CALLBACK(src, TYPE_PROC_REF(/atom, update_icon)), 1 SECONDS) /obj/structure/closet/fireaxecabinet/verb/toggle_openness() //nice name, huh? HUH?! -Erro //YEAH -Agouri set name = "Open/Close" set category = "Object" if (locked || smashed) - if(src.locked) + if(locked) to_chat(usr, span_warning("The cabinet won't budge!")) - else if(src.smashed) + else if(smashed) to_chat(usr, span_notice("The protective glass is broken!")) return @@ -165,22 +154,22 @@ set name = "Remove Fire Axe" set category = "Object" - if (istype(usr, /mob/living/carbon/xenomorph)) + if(istype(usr, /mob/living/carbon/xenomorph)) return - if (localopened) + if(localopened) if(fireaxe) usr.put_in_hands(fireaxe) fireaxe = null to_chat(usr, span_notice("You take the Fire axe from the [name].")) else - to_chat(usr, span_notice("The [src.name] is empty.")) + to_chat(usr, span_notice("The [name] is empty.")) else - to_chat(usr, span_notice("The [src.name] is closed.")) + to_chat(usr, span_notice("The [name] is closed.")) update_icon() /obj/structure/closet/fireaxecabinet/attack_ai(mob/user as mob) - if(src.smashed) + if(smashed) to_chat(user, span_warning("The security of the cabinet is compromised.")) return else diff --git a/code/game/objects/structures/crates_lockers/secure_crates.dm b/code/game/objects/structures/crates_lockers/secure_crates.dm index ac69840f78c..97483d65894 100644 --- a/code/game/objects/structures/crates_lockers/secure_crates.dm +++ b/code/game/objects/structures/crates_lockers/secure_crates.dm @@ -32,7 +32,6 @@ /obj/structure/closet/crate/secure/can_open() return !locked - /obj/structure/closet/crate/secure/verb/verb_togglelock() set src in oview(1) // One square distance set category = "Object" @@ -42,28 +41,30 @@ return togglelock(usr) - /obj/structure/closet/crate/secure/emp_act(severity) for(var/obj/O in src) O.emp_act(severity) - if(!broken && !opened && prob(50/severity)) + if(!broken && !opened && prob(50 / severity)) if(!locked) locked = 1 else overlays.Cut() overlays += sparks - spawn(6) overlays -= sparks //Tried lots of stuff but nothing works right. so i have to use this *sadface* + addtimer(CALLBACK(src, PROC_REF(clear_sparks)), 0.6 SECONDS) playsound(src.loc, 'sound/effects/sparks4.ogg', 25, 1) locked = 0 update_icon() - if(!opened && prob(20/severity)) + if(!opened && prob(20 / severity)) if(!locked) open() else req_access = list() req_access += pick(ALL_ACCESS) - ..() + return ..() +/// Used in emp_act to clear sparks with delay +/obj/structure/closet/crate/secure/proc/clear_sparks() + overlays -= sparks //------------------------------------ // Secure Crates diff --git a/code/game/objects/structures/lattice.dm b/code/game/objects/structures/lattice.dm index 869b506bc49..9e94dfb7949 100644 --- a/code/game/objects/structures/lattice.dm +++ b/code/game/objects/structures/lattice.dm @@ -51,22 +51,12 @@ qdel(src) /obj/structure/lattice/proc/updateOverlays() - //if(!isspaceturf(loc)) - // qdel(src) - spawn(1) - overlays = list() - - var/dir_sum = 0 - - for (var/direction in GLOB.cardinals) - if(locate(/obj/structure/lattice, get_step(src, direction))) - dir_sum += direction - else - if(!isspaceturf(get_step(src, direction))) - dir_sum += direction - - icon_state = "lattice[dir_sum]" - return + var/dir_sum = 0 + for(var/direction in GLOB.cardinals) + if(!locate(/obj/structure/lattice, get_step(src, direction)) || isspaceturf(get_step(src, direction))) + continue + dir_sum += direction + icon_state = "lattice[dir_sum]" /obj/structure/catwalk icon = 'icons/obj/smooth_objects/catwalk.dmi' diff --git a/code/game/objects/structures/watercloset.dm b/code/game/objects/structures/watercloset.dm index b546c2c910b..ad608ce8c3f 100644 --- a/code/game/objects/structures/watercloset.dm +++ b/code/game/objects/structures/watercloset.dm @@ -234,21 +234,27 @@ if(watertemp == WATER_TEMP_FREEZING) return if(!ismist) - spawn(50) - if(src && on) - ismist = TRUE - mymist = new /obj/effect/mist(loc) + addtimer(CALLBACK(src, PROC_REF(spawn_mist)), 5 SECONDS) else ismist = TRUE mymist = new /obj/effect/mist(loc) else if(ismist) ismist = TRUE mymist = new /obj/effect/mist(loc) - spawn(250) - if(src && !on) - qdel(mymist) - mymist = null - ismist = FALSE + addtimer(CALLBACK(src, PROC_REF(clean_mist)), 25 SECONDS) + +/obj/machinery/shower/proc/spawn_mist() + if(!on) + return + ismist = TRUE + mymist = new /obj/effect/mist(loc) + +/obj/machinery/shower/proc/clean_mist() + if(on) + return + qdel(mymist) + mymist = null + ismist = FALSE /obj/machinery/shower/update_overlays() . = ..() diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm index d5c5f485530..1e8a6abafaf 100644 --- a/code/game/turfs/turf.dm +++ b/code/game/turfs/turf.dm @@ -411,44 +411,41 @@ /turf/proc/ceiling_debris(size = 1) //debris falling in response to airstrikes, etc var/area/A = get_area(src) if(!A.ceiling) return - - var/amount = size - var/spread = round(sqrt(size)*1.5) + var/spread = round(sqrt(size) * 1.5) var/list/turfs = list() - for(var/turf/open/floor/F in range(src,spread)) + for(var/turf/open/floor/F in range(src, spread)) turfs += F + var/drop_message + var/list/debris_list switch(A.ceiling) + if(CEILING_NONE) + return if(CEILING_GLASS) playsound(src, 'sound/effects/glassbr1.ogg', 60, 1) - spawn(8) - if(amount >1) - visible_message(span_boldnotice("Shards of glass rain down from above!")) - for(var/i=1, i<=amount, i++) - new /obj/item/shard(pick(turfs)) - new /obj/item/shard(pick(turfs)) + drop_message = "Shards of glass rain down from above!" + debris_list = list(/obj/item/shard, /obj/item/shard) if(CEILING_METAL, CEILING_OBSTRUCTED) playsound(src, 'sound/effects/metal_crash.ogg', 30, 1) - spawn(8) - if(amount >1) - visible_message(span_boldnotice("Pieces of metal crash down from above!")) - for(var/i=1, i<=amount, i++) - new /obj/item/stack/sheet/metal(pick(turfs)) + drop_message = "Pieces of metal crash down from above!" + debris_list = list(/obj/item/stack/sheet/metal) if(CEILING_UNDERGROUND, CEILING_DEEP_UNDERGROUND) playsound(src, 'sound/effects/meteorimpact.ogg', 60, 1) - spawn(8) - if(amount >1) - visible_message(span_boldnotice("Chunks of rock crash down from above!")) - for(var/i = 1, i <= amount, i++) - new /obj/item/ore(pick(turfs)) - new /obj/item/ore(pick(turfs)) + drop_message = "Chunks of rock crash down from above!" + debris_list = list(/obj/item/ore, /obj/item/ore) if(CEILING_UNDERGROUND_METAL, CEILING_DEEP_UNDERGROUND_METAL) playsound(src, 'sound/effects/metal_crash.ogg', 60, 1) - spawn(8) - for(var/i = 1, i <= amount, i++) - new /obj/item/stack/sheet/metal(pick(turfs)) - new /obj/item/ore(pick(turfs)) + debris_list = list(/obj/item/stack/sheet/metal, /obj/item/ore) + addtimer(CALLBACK(src, PROC_REF(drop_ceiling_debris), debris_list, size, drop_message, turfs), 0.8 SECONDS) + +/// Drop amount of listed stuff in listed turfs, with a message if amount is more than 1 +/turf/proc/drop_ceiling_debris(list/stuff_to_drop, amount, drop_message, list/turfs) + if(amount > 1 && drop_message) + visible_message(span_boldnotice(drop_message)) + for(var/i = 1, i <= amount, i++) + for(var/item_to_drop AS in stuff_to_drop) + new item_to_drop(pick(turfs)) /turf/proc/ceiling_desc() var/area/A = get_area(src) diff --git a/code/modules/animations/animation_library.dm b/code/modules/animations/animation_library.dm index ad35e283ead..21ce7ed07d2 100644 --- a/code/modules/animations/animation_library.dm +++ b/code/modules/animations/animation_library.dm @@ -52,9 +52,7 @@ Instead of being uniform, it starts out a littler slower, goes fast in the middl A.status_flags |= INCORPOREAL var/initial_matrix = A.transform animate(A, transform = matrix(0, 4, MATRIX_SCALE), alpha = 0, time = speed, easing = BACK_EASING) - spawn(speed) - A.transform = initial_matrix - A.status_flags &= ~INCORPOREAL + addtimer(CALLBACK(A, PROC_REF(transform_initial_matrix), A, initial_matrix), speed) return speed //We want to make sure to reset color here as it can be changed by other animations. @@ -64,9 +62,7 @@ Instead of being uniform, it starts out a littler slower, goes fast in the middl A.transform = matrix(0, 4, MATRIX_SCALE) A.alpha = 0 //Start with transparency, just in case. animate(A, alpha = 255, transform = null, color = "#FFFFFF", time = speed, easing = BACK_EASING) - spawn(speed) - A.transform = initial_matrix - A.status_flags &= ~INCORPOREAL + addtimer(CALLBACK(A, PROC_REF(transform_initial_matrix), A, initial_matrix), speed) return speed /*A magical teleport animation, for when the person is transported with some magic. Good for Halloween type events. @@ -79,10 +75,8 @@ Can look good elsewhere as well.*/ animate(alpha = 0, time = speed) var/image/I = image('icons/effects/effects.dmi',A,"sparkle") flick_overlay_view(I, A, 9) - spawn(speed) - A.transform = initial_matrix - A.status_flags &= ~INCORPOREAL - return speed*3 + addtimer(CALLBACK(A, PROC_REF(transform_initial_matrix), A, initial_matrix), speed) + return speed * 3 /proc/animation_teleport_magic_in(atom/A, speed = 6) A.status_flags |= INCORPOREAL @@ -94,9 +88,7 @@ Can look good elsewhere as well.*/ animate(transform = null, time = speed-1) var/image/I = image('icons/effects/effects.dmi',A,"sparkle") flick_overlay_view(I, A, 10) - spawn(speed) - A.transform = initial_matrix - A.status_flags &= ~INCORPOREAL + addtimer(CALLBACK(A, PROC_REF(transform_initial_matrix), A, initial_matrix), speed) return speed //A spooky teleport for evil dolls, horrors, and whatever else. Halloween type stuff. @@ -108,9 +100,7 @@ Can look good elsewhere as well.*/ animate(alpha = 0, time = speed) var/image/I = image('icons/effects/effects.dmi',A,"spooky") flick_overlay_view(I, A, 9) - spawn(speed) - A.transform = initial_matrix - A.status_flags &= ~INCORPOREAL + addtimer(CALLBACK(A, PROC_REF(transform_initial_matrix), A, initial_matrix), speed) return speed*3 /proc/animation_teleport_spooky_in(atom/A, speed = 4) @@ -122,9 +112,7 @@ Can look good elsewhere as well.*/ animate(transform = null, color = "#FFFFFF", time = speed, easing = QUAD_EASING|EASE_OUT) var/image/I = image('icons/effects/effects.dmi',A,"spooky") flick_overlay_view(I, A, 10) - spawn(speed) - A.transform = initial_matrix - A.status_flags &= ~INCORPOREAL + addtimer(CALLBACK(A, PROC_REF(transform_initial_matrix), A, initial_matrix), speed) return speed //Regular fadeout disappear, for most objects. @@ -166,3 +154,7 @@ Can look good elsewhere as well.*/ animate(src, transform = matrix_list[1], time = speed, loop_amount) for(var/i in 2 to sections) animate(transform = matrix_list[i], time = speed) + +/proc/transform_initial_matrix(atom/our_atom, initial_matrix) + our_atom.transform = initial_matrix + our_atom.status_flags &= ~INCORPOREAL diff --git a/code/modules/clothing/glasses/thermal.dm b/code/modules/clothing/glasses/thermal.dm index f93bbc91c8c..d34cc6edc93 100644 --- a/code/modules/clothing/glasses/thermal.dm +++ b/code/modules/clothing/glasses/thermal.dm @@ -15,10 +15,7 @@ if(M.glasses == src) M.blind_eyes(3) M.blur_eyes(5) - M.disabilities |= NEARSIGHTED - spawn(100) - M.disabilities &= ~NEARSIGHTED - ..() + return ..() /obj/item/clothing/glasses/thermal/yautja name = "bio-mask thermal" @@ -37,14 +34,14 @@ /obj/item/clothing/glasses/thermal/yautja/dropped(mob/living/carbon/human/user) if(istype(user) && user.glasses == src) user.clear_fullscreen("machine", 5) - ..() + return ..() /obj/item/clothing/glasses/thermal/yautja/equipped(mob/living/carbon/human/user, slot) if(slot == SLOT_GLASSES) user.overlay_fullscreen("machine", /atom/movable/screen/fullscreen/machine/pred) - ..() + return ..() /obj/item/clothing/glasses/thermal/yautja/unequipped(mob/living/carbon/human/user, slot) if(slot == SLOT_GLASSES) user.clear_fullscreen("machine", 5) - ..() + return ..() diff --git a/code/modules/economy/EFTPOS.dm b/code/modules/economy/EFTPOS.dm index 1da5cd8857d..497d330dc88 100644 --- a/code/modules/economy/EFTPOS.dm +++ b/code/modules/economy/EFTPOS.dm @@ -16,52 +16,51 @@ . = ..() machine_id = "EFTPOS #[GLOB.num_financial_terminals++]" access_code = rand(1111,111111) - spawn(0) - print_reference() - - //create a short manual as well - var/obj/item/paper/R = new(src.loc) - R.name = "Steps to success: Correct EFTPOS Usage" - /* - R.info += "When first setting up your EFTPOS device:" - R.info += "1. Memorise your EFTPOS command code (provided with all EFTPOS devices).
" - R.info += "2. Confirm that your EFTPOS device is connected to your local accounts database. For additional assistance with this step, contact NanoTrasen IT Support
" - R.info += "3. Confirm that your EFTPOS device has been linked to the account that you wish to recieve funds for all transactions processed on this device.
" - R.info += "When starting a new transaction with your EFTPOS device:" - R.info += "1. Ensure the device is UNLOCKED so that new data may be entered.
" - R.info += "2. Enter a sum of money and reference message for the new transaction.
" - R.info += "3. Lock the transaction, it is now ready for your customer.
" - R.info += "4. If at this stage you wish to modify or cancel your transaction, you may simply reset (unlock) your EFTPOS device.
" - R.info += "5. Give your EFTPOS device to the customer, they must authenticate the transaction by swiping their ID card and entering their PIN number.
" - R.info += "6. If done correctly, the transaction will be logged to both accounts with the reference you have entered, the terminal ID of your EFTPOS device and the money transferred across accounts.
" - */ - //Temptative new manual: - R.info += "First EFTPOS setup:
" - R.info += "1. Memorise your EFTPOS command code (provided with all EFTPOS devices).
" - R.info += "2. Connect the EFTPOS to the account in which you want to receive the funds.

" - R.info += "When starting a new transaction:
" - R.info += "1. Enter the amount of money you want to charge and a purpose message for the new transaction.
" - R.info += "2. Lock the new transaction. If you want to modify or cancel the transaction, you simply have to reset your EFTPOS device.
" - R.info += "3. Give the EFTPOS device to your customer, he/she must finish the transaction by swiping their ID card or a charge card with enough funds.
" - R.info += "4. If everything is done correctly, the money will be transferred. To unlock the device you will have to reset the EFTPOS device.
" - - - //stamp the paper - var/image/stampoverlay = image('icons/obj/items/paper.dmi') - stampoverlay.icon_state = "paper_stamp-cent" - if(!R.stamped) - R.stamped = new - R.offset_x += 0 - R.offset_y += 0 - R.ico += "paper_stamp-cent" - R.stamped += /obj/item/tool/stamp - R.overlays += stampoverlay - R.stamps += "
This paper has been stamped by the EFTPOS device." - + INVOKE_ASYNC(src, PROC_REF(print_paper)) //by default, connect to the station account //the user of the EFTPOS device can change the target account though, and no-one will be the wiser (except whoever's being charged) linked_account = GLOB.station_account +/obj/item/eftpos/proc/print_paper() + print_reference() + //create a short manual as well + var/obj/item/paper/R = new(src.loc) + R.name = "Steps to success: Correct EFTPOS Usage" + /* + R.info += "When first setting up your EFTPOS device:" + R.info += "1. Memorise your EFTPOS command code (provided with all EFTPOS devices).
" + R.info += "2. Confirm that your EFTPOS device is connected to your local accounts database. For additional assistance with this step, contact NanoTrasen IT Support
" + R.info += "3. Confirm that your EFTPOS device has been linked to the account that you wish to recieve funds for all transactions processed on this device.
" + R.info += "When starting a new transaction with your EFTPOS device:" + R.info += "1. Ensure the device is UNLOCKED so that new data may be entered.
" + R.info += "2. Enter a sum of money and reference message for the new transaction.
" + R.info += "3. Lock the transaction, it is now ready for your customer.
" + R.info += "4. If at this stage you wish to modify or cancel your transaction, you may simply reset (unlock) your EFTPOS device.
" + R.info += "5. Give your EFTPOS device to the customer, they must authenticate the transaction by swiping their ID card and entering their PIN number.
" + R.info += "6. If done correctly, the transaction will be logged to both accounts with the reference you have entered, the terminal ID of your EFTPOS device and the money transferred across accounts.
" + */ + //Temptative new manual: + R.info += "First EFTPOS setup:
" + R.info += "1. Memorise your EFTPOS command code (provided with all EFTPOS devices).
" + R.info += "2. Connect the EFTPOS to the account in which you want to receive the funds.

" + R.info += "When starting a new transaction:
" + R.info += "1. Enter the amount of money you want to charge and a purpose message for the new transaction.
" + R.info += "2. Lock the new transaction. If you want to modify or cancel the transaction, you simply have to reset your EFTPOS device.
" + R.info += "3. Give the EFTPOS device to your customer, he/she must finish the transaction by swiping their ID card or a charge card with enough funds.
" + R.info += "4. If everything is done correctly, the money will be transferred. To unlock the device you will have to reset the EFTPOS device.
" + + //stamp the paper + var/image/stampoverlay = image('icons/obj/items/paper.dmi') + stampoverlay.icon_state = "paper_stamp-cent" + if(!R.stamped) + R.stamped = new + R.offset_x += 0 + R.offset_y += 0 + R.ico += "paper_stamp-cent" + R.stamped += /obj/item/tool/stamp + R.overlays += stampoverlay + R.stamps += "
This paper has been stamped by the EFTPOS device." + /obj/item/eftpos/proc/print_reference() var/obj/item/paper/R = new(src.loc) R.name = "Reference: [eftpos_name]" diff --git a/code/modules/error_handler/error_handler.dm b/code/modules/error_handler/error_handler.dm index e1c233a5dc9..178669835ef 100644 --- a/code/modules/error_handler/error_handler.dm +++ b/code/modules/error_handler/error_handler.dm @@ -64,21 +64,13 @@ GLOBAL_VAR_INIT(total_runtimes_skipped, 0) CE = /datum/config_entry/number/error_silence_time configured_error_silence_time = initial(CE.config_entry_value) - //Each occurence of a unique error adds to its cooldown time... cooldown = max(0, cooldown - (world.time - last_seen)) + configured_error_cooldown // ... which is used to silence an error if it occurs too often, too fast if(cooldown > configured_error_cooldown * configured_error_limit) cooldown = -1 silencing = TRUE - spawn(0) //Has to be used here - usr = null - sleep(configured_error_silence_time) //Has to be used here - var/skipcount = abs(error_cooldown[erroruid]) - 1 - error_cooldown[erroruid] = 0 - if(skipcount > 0) - SEND_TEXT(world.log, "\[[time_stamp()]] Skipped [skipcount] runtimes in [E.file],[E.line].") - GLOB.error_cache.log_error(E, skip_count = skipcount) + INVOKE_ASYNC(src, PROC_REF(log_errors), configured_error_silence_time, error_cooldown, erroruid, E) error_last_seen[erroruid] = world.time error_cooldown[erroruid] = cooldown @@ -125,6 +117,14 @@ GLOBAL_VAR_INIT(total_runtimes_skipped, 0) GLOB.current_test.Fail("[main_line]\n[desclines.Join("\n")]") #endif - // This writes the regular format (unwrapping newlines and inserting timestamps as needed). log_runtime("runtime error: [E.name]\n[E.desc]") + +/world/proc/log_errors(silence_time, error_cooldown, erroruid, exception/our_exception) + usr = null + sleep(silence_time) //Has to be used here + var/skipcount = abs(error_cooldown[erroruid]) - 1 + error_cooldown[erroruid] = 0 + if(skipcount > 0) + SEND_TEXT(world.log, "\[[time_stamp()]] Skipped [skipcount] runtimes in [our_exception.file], [our_exception.line].") + GLOB.error_cache.log_error(our_exception, skip_count = skipcount) diff --git a/code/modules/mob/living/carbon/xenomorph/castes/predalien/abilities_predalien.dm b/code/modules/mob/living/carbon/xenomorph/castes/predalien/abilities_predalien.dm index de0646270f2..2b1215319b2 100644 --- a/code/modules/mob/living/carbon/xenomorph/castes/predalien/abilities_predalien.dm +++ b/code/modules/mob/living/carbon/xenomorph/castes/predalien/abilities_predalien.dm @@ -190,10 +190,7 @@ carbon.apply_damage(base_damage + damage_scale * min(xeno.life_kills_total, xeno.max_bonus_life_kills), BRUTE, "chest", MELEE, FALSE, FALSE, TRUE, 20) xeno.do_attack_animation(carbon, ATTACK_EFFECT_CLAW) - spawn() - for(var/x in 1 to 4) - sleep(1) - xeno.setDir(turn(xeno.dir, 90)) + INVOKE_ASYNC(src, PROC_REF(ability_spin)) xeno.do_attack_animation(carbon, ATTACK_EFFECT_BITE) playsound(xeno, 'sound/voice/alien/predalien/growl.ogg', 75, 0) @@ -207,3 +204,9 @@ add_cooldown() succeed_activate() + +/datum/action/ability/activable/xeno/devastate/proc/ability_spin() + var/mob/living/carbon/xenomorph/predalien/xeno = owner + for(var/x in 1 to 4) + sleep(1) + xeno.setDir(turn(xeno.dir, 90)) diff --git a/code/modules/mob/living/simple_animal/friendly/farm_animals.dm b/code/modules/mob/living/simple_animal/friendly/farm_animals.dm index e11d50dbcb8..e4cc0a91146 100644 --- a/code/modules/mob/living/simple_animal/friendly/farm_animals.dm +++ b/code/modules/mob/living/simple_animal/friendly/farm_animals.dm @@ -79,25 +79,24 @@ to_chat(src, span_userdanger("You are tipped over by [user]!")) Paralyze(20 SECONDS) icon_state = icon_dead - spawn(rand(20, 50)) - if(!stat && user) - icon_state = icon_living - var/external - var/internal - switch(pick(1,2,3,4)) - if(1,2,3) - var/text = pick("imploringly.", "pleadingly.", - "with a resigned expression.") - external = "[src] looks at [user] [text]" - internal = "You look at [user] [text]" - if(4) - external = "[src] seems resigned to its fate." - internal = "You resign yourself to your fate." - visible_message(span_notice("[external]"), - span_revennotice("[internal]")) + addtimer(CALLBACK(src, PROC_REF(tip_message), user), rand(2 SECONDS, 5 SECONDS)) else return ..() +/mob/living/simple_animal/cow/proc/tip_message(mob/living/user) + if(stat || !user) + return + icon_state = icon_living + var/external + var/internal + if(prob(75)) + var/text = pick("imploringly.", "pleadingly.", "with a resigned expression.") + external = "[src] looks at [user] [text]" + internal = "You look at [user] [text]" + else + external = "[src] seems resigned to its fate." + internal = "You resign yourself to your fate." + visible_message(span_notice("[external]"), span_revennotice("[internal]")) /mob/living/simple_animal/chick name = "\improper chick" diff --git a/code/modules/paperwork/paper.dm b/code/modules/paperwork/paper.dm index aa8693dd92a..ba2778e0619 100644 --- a/code/modules/paperwork/paper.dm +++ b/code/modules/paperwork/paper.dm @@ -219,27 +219,28 @@ /obj/item/paper/proc/burnpaper(obj/item/P, mob/user) var/class = "" - if(P.heat >= 400 && !user.restrained()) - if(istype(P, /obj/item/tool/lighter/zippo)) - class = "" - - user.visible_message("[class][user] holds \the [P] up to \the [src], it looks like [user.p_theyre()] trying to burn it!", \ - "[class]You hold \the [P] up to \the [src], burning it slowly.") + if(P.heat < 400 || user.restrained()) + return + if(istype(P, /obj/item/tool/lighter/zippo)) + class = "" - spawn(20) - if(get_dist(src, user) < 2 && user.get_active_held_item() == P && P.heat) - user.visible_message("[class][user] burns right through \the [src], turning it to ash. It flutters through the air before settling on the floor in a heap.", \ - "[class]You burn right through \the [src], turning it to ash. It flutters through the air before settling on the floor in a heap.") + user.visible_message("[class][user] holds \the [P] up to \the [src], it looks like [user.p_theyre()] trying to burn it!", \ + "[class]You hold \the [P] up to \the [src], burning it slowly.") - if(user.get_inactive_held_item() == src) - user.dropItemToGround(src) + if(!do_after(user, 2 SECONDS, NONE, src)) + to_chat(user, span_warning("You must hold \the [P] steady to burn \the [src].")) + return - new /obj/effect/decal/cleanable/ash(src.loc) - qdel(src) + if(!P.heat) + return + user.visible_message("[class][user] burns right through \the [src], turning it to ash. It flutters through the air before settling on the floor in a heap.", \ + "[class]You burn right through \the [src], turning it to ash. It flutters through the air before settling on the floor in a heap.") - else - to_chat(user, span_warning("You must hold \the [P] steady to burn \the [src].")) + if(user.get_inactive_held_item() == src) + user.dropItemToGround(src) + new /obj/effect/decal/cleanable/ash(src.loc) + qdel(src) /obj/item/paper/Topic(href, href_list) . = ..() diff --git a/code/modules/paperwork/paper_bundle.dm b/code/modules/paperwork/paper_bundle.dm index 7197a28b951..58ed494b9fb 100644 --- a/code/modules/paperwork/paper_bundle.dm +++ b/code/modules/paperwork/paper_bundle.dm @@ -62,30 +62,31 @@ update_icon() attack_self(user) //Update the browsed page. - /obj/item/paper_bundle/proc/burnpaper(obj/item/P, mob/user) var/class = "" - if(P.heat >= 400 && !user.restrained()) - if(istype(P, /obj/item/tool/lighter/zippo)) - class = "" + if(P.heat < 400 || user.restrained()) + return + if(istype(P, /obj/item/tool/lighter/zippo)) + class = "" - user.visible_message("[class][user] holds \the [P] up to \the [src], it looks like [user.p_theyre()] trying to burn it!", \ + user.visible_message("[class][user] holds \the [P] up to \the [src], it looks like [user.p_theyre()] trying to burn it!", \ "[class]You hold \the [P] up to \the [src], burning it slowly.") - spawn(20) - if(get_dist(src, user) < 2 && user.get_active_held_item() == P && P.heat) - user.visible_message("[class][user] burns right through \the [src], turning it to ash. It flutters through the air before settling on the floor in a heap.", \ - "[class]You burn right through \the [src], turning it to ash. It flutters through the air before settling on the floor in a heap.") + if(!do_after(user, 2 SECONDS, NONE, src)) + to_chat(user, span_warning("You must hold \the [P] steady to burn \the [src].")) + return - if(user.get_inactive_held_item() == src) - user.dropItemToGround(src) + if(!P.heat) + return + user.visible_message("[class][user] burns right through \the [src], turning it to ash. It flutters through the air before settling on the floor in a heap.", \ + "[class]You burn right through \the [src], turning it to ash. It flutters through the air before settling on the floor in a heap.") - new /obj/effect/decal/cleanable/ash(src.loc) - qdel(src) + if(user.get_inactive_held_item() == src) + user.dropItemToGround(src) - else - to_chat(user, span_warning("You must hold \the [P] steady to burn \the [src].")) + new /obj/effect/decal/cleanable/ash(src.loc) + qdel(src) /obj/item/paper_bundle/examine(mob/user) . = ..() diff --git a/code/modules/power/lighting.dm b/code/modules/power/lighting.dm index b3c011ddc13..78b15cfe79d 100644 --- a/code/modules/power/lighting.dm +++ b/code/modules/power/lighting.dm @@ -350,15 +350,17 @@ if(flickering) return flickering = TRUE - spawn(0) - if(light_on && status == LIGHT_OK) - for(var/i = 0; i < amount; i++) - if(status != LIGHT_OK) - break - update(FALSE) - sleep(rand(5, 15)) - update(FALSE) - flickering = FALSE + INVOKE_ASYNC(src, PROC_REF(flicker_stage_2), amount) + +/obj/machinery/light/proc/flicker_stage_2(amount) + if(light_on && status == LIGHT_OK) + for(var/i = 0; i < amount; i++) + if(status != LIGHT_OK) + break + update(FALSE, FALSE) + sleep(rand(5, 15)) + update(FALSE) + flickering = FALSE // ai attack - make lights flicker, because why not diff --git a/code/modules/power/smes_construction.dm b/code/modules/power/smes_construction.dm index 4441018438b..f78389b8b20 100644 --- a/code/modules/power/smes_construction.dm +++ b/code/modules/power/smes_construction.dm @@ -141,29 +141,31 @@ if (prob(50)) visible_message("DANGER! Magnetic containment field unstable! Containment field failure imminent!") failing = 1 - // 30 - 60 seconds and then BAM! - spawn(rand(300,600)) - if(!failing) // Admin can manually set this var back to 0 to stop overload, for use when griffed. - update_icon() - visible_message("Magnetic containment stabilised.") - return - visible_message("DANGER! Magnetic containment field failure in 3 ... 2 ... 1 ...") - cell_explosion(loc, 250, 50) - // Not sure if this is necessary, but just in case the SMES *somehow* survived.. - qdel(src) - - // Gets powernet APCs and overloads lights or breaks the APC completely, depending on percentages. + addtimer(CALLBACK(src, PROC_REF(smes_overload)), rand(30 SECONDS, 60 SECONDS)) + +/obj/machinery/power/smes/buildable/proc/smes_overload() + if(!failing) // Admin can manually set this var back to 0 to stop overload, for use when griffed. + update_icon() + visible_message("Magnetic containment stabilised.") + return + visible_message("DANGER! Magnetic containment field failure in 3 ... 2 ... 1 ...") + cell_explosion(loc, 250, 50) + // Not sure if this is necessary, but just in case the SMES *somehow* survived.. + qdel(src) + +/// Gets powernet APCs and overloads lights or breaks the APC completely, depending on percentages. /obj/machinery/power/smes/buildable/proc/apcs_overload(failure_chance, overload_chance) - if (!src.powernet) + if(!src.powernet) return for(var/obj/machinery/power/terminal/T in src.powernet.nodes) - if(istype(T.master, /obj/machinery/power/apc)) - var/obj/machinery/power/apc/A = T.master - if (prob(overload_chance)) - A.overload_lighting() - if (prob(failure_chance)) - A.set_broken() + if(!istype(T.master, /obj/machinery/power/apc)) + continue + var/obj/machinery/power/apc/A = T.master + if(prob(overload_chance)) + A.overload_lighting() + if(prob(failure_chance)) + A.set_broken() // Failing SMES has special icon overlay. /obj/machinery/power/smes/buildable/update_overlays() diff --git a/code/modules/predator/smartdisc.dm b/code/modules/predator/smartdisc.dm index d99b83b2e8f..f5c3aaaff57 100644 --- a/code/modules/predator/smartdisc.dm +++ b/code/modules/predator/smartdisc.dm @@ -120,9 +120,7 @@ active = TRUE playsound(loc, 'sound/items/countdown.ogg', 25, 1) update_icon() - spawn(det_time) - prime() - return + addtimer(CALLBACK(src, PROC_REF(prime)), det_time) /obj/item/explosive/grenade/spawnergrenade/smartdisc/prime() if(spawner_type && deliveryamt) @@ -212,10 +210,8 @@ /mob/living/simple_animal/hostile/smartdisc/death() visible_message("\The [src] stops whirring and spins out onto the floor.") drop_real_disc() - ..() - spawn(1) - if(src) - qdel(src) + . = ..() + QDEL_IN(src, 0.1 SECONDS) /mob/living/simple_animal/hostile/smartdisc/proc/drop_real_disc() spawner_item.forceMove(loc) @@ -230,9 +226,7 @@ /mob/living/simple_animal/hostile/smartdisc/gib() visible_message("\The [src] explodes!") . = ..() - spawn(1) - if(src) - qdel(src) + QDEL_IN(src, 0.1 SECONDS) /mob/living/simple_animal/hostile/smartdisc/FindTarget() var/atom/T = null diff --git a/code/modules/predator/yautja/bracers.dm b/code/modules/predator/yautja/bracers.dm index c518d61ca9f..376e9b344c0 100644 --- a/code/modules/predator/yautja/bracers.dm +++ b/code/modules/predator/yautja/bracers.dm @@ -530,8 +530,7 @@ sparks.set_up(5, 4, src) sparks.start() - spawn() - decloak(wearer, TRUE) + INVOKE_ASYNC(src, PROC_REF(decloak), wearer, TRUE) /obj/item/clothing/gloves/yautja/proc/track_gear_internal(mob/caller, forced = FALSE) . = check_random_function(caller, forced) diff --git a/code/modules/predator/yautja/weapons/ranged.dm b/code/modules/predator/yautja/weapons/ranged.dm index afed63d1489..741409c6ec2 100644 --- a/code/modules/predator/yautja/weapons/ranged.dm +++ b/code/modules/predator/yautja/weapons/ranged.dm @@ -462,13 +462,16 @@ /mob/living/carbon/apply_pred_laser() overlays_standing[PRED_LASER_LAYER] = image("icon" = 'icons/mob/hunter/pred_gear.dmi', "icon_state" = "locking-y", "layer" = -PRED_LASER_LAYER) apply_overlay(PRED_LASER_LAYER) - spawn(2 SECONDS) - if(overlays_standing[PRED_LASER_LAYER]) - remove_overlay(PRED_LASER_LAYER) - overlays_standing[PRED_LASER_LAYER] = image("icon" = 'icons/mob/hunter/pred_gear.dmi', "icon_state" = "locked-y", "layer" = -PRED_LASER_LAYER) - apply_overlay(PRED_LASER_LAYER) + addtimer(CALLBACK(src, PROC_REF(delayed_apply_pred_laser)), 2 SECONDS) return TRUE +/mob/living/carbon/proc/delayed_apply_pred_laser() + if(!overlays_standing[PRED_LASER_LAYER]) + return + remove_overlay(PRED_LASER_LAYER) + overlays_standing[PRED_LASER_LAYER] = image("icon" = 'icons/mob/hunter/pred_gear.dmi', "icon_state" = "locked-y", "layer" = -PRED_LASER_LAYER) + apply_overlay(PRED_LASER_LAYER) + /atom/proc/remove_pred_laser() return FALSE diff --git a/code/modules/reagents/machinery/chem_master.dm b/code/modules/reagents/machinery/chem_master.dm index b00ed1571bc..c14146efe2b 100644 --- a/code/modules/reagents/machinery/chem_master.dm +++ b/code/modules/reagents/machinery/chem_master.dm @@ -341,21 +341,8 @@ . = ..() if(.) return - // if(user.skills.getRating(SKILL_MEDICAL) < SKILL_MEDICAL_PRACTICED) //RUTGMC edit - marines can use chem machines once again - // balloon_alert(user, "skill issue") - // return - if(!(user.client in has_sprites)) - spawn() - has_sprites += user.client - for(var/i = 1 to MAX_PILL_BOTTLE_SPRITE) - user << browse_rsc(icon('icons/obj/items/chemistry.dmi', pill_bottle_names[i]), pill_bottle_names[i]+".png") - for(var/i = 1 to MAX_PILL_SPRITE) - user << browse_rsc(icon('icons/obj/items/chemistry.dmi', "pill" + num2text(i)), "pill[i].png") - for(var/i = 1 to MAX_BOTTLE_SPRITE) - user << browse_rsc(icon('icons/obj/items/chemistry.dmi', "bottle-" + num2text(i)), "bottle-[i].png") - for(var/i = 1 to MAX_AUTOINJECTOR_SPRITE) - user << browse_rsc(icon('icons/obj/items/syringe.dmi', "autoinjector-" + num2text(i)), "autoinjector-[i].png") + INVOKE_ASYNC(src, PROC_REF(show_container_choises), user) var/dat = "" if(!beaker) dat = "Please insert beaker.
" @@ -407,6 +394,17 @@ popup.set_content(dat) popup.open() +/obj/machinery/chem_master/proc/show_container_choises(mob/user) + has_sprites += user.client + for(var/i = 1 to MAX_PILL_BOTTLE_SPRITE) + user << browse_rsc(icon('icons/obj/items/chemistry.dmi', pill_bottle_names[i]), pill_bottle_names[i]+".png") + for(var/i = 1 to MAX_PILL_SPRITE) + user << browse_rsc(icon('icons/obj/items/chemistry.dmi', "pill" + num2text(i)), "pill[i].png") + for(var/i = 1 to MAX_BOTTLE_SPRITE) + user << browse_rsc(icon('icons/obj/items/chemistry.dmi', "bottle-" + num2text(i)), "bottle-[i].png") + for(var/i = 1 to MAX_AUTOINJECTOR_SPRITE) + user << browse_rsc(icon('icons/obj/items/syringe.dmi', "autoinjector-" + num2text(i)), "autoinjector-[i].png") + /obj/machinery/chem_master/update_icon() . = ..() if(machine_stat & (NOPOWER)) diff --git a/code/modules/recycling/disposal.dm b/code/modules/recycling/disposal.dm index 4172a70df4d..d1b8a971a11 100644 --- a/code/modules/recycling/disposal.dm +++ b/code/modules/recycling/disposal.dm @@ -400,8 +400,7 @@ target = get_offset_target_turf(loc, rand(5) - rand(5), rand(5) - rand(5)) AM.loc = loc AM.pipe_eject(0) - spawn(1) - AM?.throw_at(target, 5, 1) + addtimer(CALLBACK(AM, TYPE_PROC_REF(/atom/movable, throw_at), target, 3, 1), 0.5 SECONDS) qdel(H) @@ -664,9 +663,8 @@ for(var/atom/movable/AM in H) AM.loc = T AM.pipe_eject(direction) - spawn(1) - if(AM) - AM.throw_at(target, 100, 1) + if(AM) + addtimer(CALLBACK(AM, TYPE_PROC_REF(/atom/movable, throw_at), target, 100, 1), 0.1 SECONDS) qdel(H) else //No specified direction, so throw in random direction @@ -678,9 +676,8 @@ AM.loc = T AM.pipe_eject(0) - spawn(1) - if(AM) - AM.throw_at(target, 5, 1) + if(AM) + addtimer(CALLBACK(AM, TYPE_PROC_REF(/atom/movable, throw_at), target, 5, 1), 0.1 SECONDS) qdel(H) @@ -1289,8 +1286,7 @@ for(var/atom/movable/AM in H) AM.loc = src.loc AM.pipe_eject(dir) - spawn(5) - AM.throw_at(target, 3, 1) + addtimer(CALLBACK(AM, TYPE_PROC_REF(/atom/movable, throw_at), target, 3, 1), 0.5 SECONDS) qdel(H) /obj/structure/disposaloutlet/attackby(obj/item/I, mob/user, params)