diff --git a/code/__DEFINES/combat.dm b/code/__DEFINES/combat.dm index 7fa8c2db77..3b08375d0d 100644 --- a/code/__DEFINES/combat.dm +++ b/code/__DEFINES/combat.dm @@ -20,6 +20,7 @@ #define TOXLOSS 4 #define OXYLOSS 8 #define SHAME 16 +#define MANUAL_SUICIDE 32 //suicide_act will do the actual killing. //Citadel code #define AROUSAL 32 diff --git a/code/datums/explosion.dm b/code/datums/explosion.dm index b9ea00da22..4ba1627190 100644 --- a/code/datums/explosion.dm +++ b/code/datums/explosion.dm @@ -365,10 +365,13 @@ GLOBAL_LIST_EMPTY(explosions) else continue - sleep(100) - for(var/turf/T in wipe_colours) - T.color = null - T.maptext = "" + addtimer(CALLBACK(GLOBAL_PROC, .proc/wipe_color_and_text, wipe_colours), 100) + +/proc/wipe_color_and_text(list/atom/wiping) + for(var/i in wiping) + var/atom/A = i + A.color = null + A.maptext = "" /proc/dyn_explosion(turf/epicenter, power, flash_range, adminlog = 1, ignorecap = 1, flame_range = 0 ,silent = 0, smoke = 1) if(!power) diff --git a/code/game/gamemodes/miniantags/abduction/gland.dm b/code/game/gamemodes/miniantags/abduction/gland.dm index 0458690a40..a9ca2ef802 100644 --- a/code/game/gamemodes/miniantags/abduction/gland.dm +++ b/code/game/gamemodes/miniantags/abduction/gland.dm @@ -241,11 +241,20 @@ /obj/item/organ/heart/gland/plasma/activate() to_chat(owner, "You feel bloated.") +<<<<<<< HEAD sleep(150) if(!owner) return to_chat(owner, "A massive stomachache overcomes you.") sleep(50) if(!owner) return +======= + addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, owner, "A massive stomachache overcomes you."), 150) + addtimer(CALLBACK(src, .proc/vomit_plasma), 200) + +/obj/item/organ/heart/gland/plasma/proc/vomit_plasma() + if(!owner) + return +>>>>>>> b83d777... Removes a bunch of sleeps/spawns and makes a few booleans defines (#31553) owner.visible_message("[owner] vomits a cloud of plasma!") var/turf/open/T = get_turf(owner) if(istype(T)) diff --git a/code/game/gamemodes/miniantags/abduction/machinery/pad.dm b/code/game/gamemodes/miniantags/abduction/machinery/pad.dm index 71ec2859ce..dff2fe812e 100644 --- a/code/game/gamemodes/miniantags/abduction/machinery/pad.dm +++ b/code/game/gamemodes/miniantags/abduction/machinery/pad.dm @@ -25,21 +25,24 @@ new /obj/effect/temp_visual/dir_setting/ninja(get_turf(target), target.dir) Warp(target) -/obj/machinery/abductor/pad/proc/MobToLoc(place,mob/living/target) - new /obj/effect/temp_visual/teleport_abductor(place) - sleep(80) +/obj/machinery/abductor/pad/proc/doMobToLoc(place, atom/movable/target) flick("alien-pad", src) target.forceMove(place) new /obj/effect/temp_visual/dir_setting/ninja(get_turf(target), target.dir) -/obj/machinery/abductor/pad/proc/PadToLoc(place) +/obj/machinery/abductor/pad/proc/MobToLoc(place,mob/living/target) new /obj/effect/temp_visual/teleport_abductor(place) - sleep(80) + addtimer(CALLBACK(src, .proc/doMobToLoc, place, target), 80) + +/obj/machinery/abductor/pad/proc/doPadToLoc(place) flick("alien-pad", src) for(var/mob/living/target in get_turf(src)) target.forceMove(place) new /obj/effect/temp_visual/dir_setting/ninja(get_turf(target), target.dir) +/obj/machinery/abductor/pad/proc/PadToLoc(place) + new /obj/effect/temp_visual/teleport_abductor(place) + addtimer(CALLBACK(src, .proc/doPadToLoc, place), 80) /obj/effect/temp_visual/teleport_abductor name = "Huh" diff --git a/code/game/gamemodes/miniantags/revenant/revenant_abilities.dm b/code/game/gamemodes/miniantags/revenant/revenant_abilities.dm index 98102984ee..7bf3535032 100644 --- a/code/game/gamemodes/miniantags/revenant/revenant_abilities.dm +++ b/code/game/gamemodes/miniantags/revenant/revenant_abilities.dm @@ -205,20 +205,20 @@ var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread s.set_up(4, 0, L) s.start() - new /obj/effect/temp_visual/revenant(L.loc) - sleep(20) - if(!L.on) //wait, wait, don't shock me - return - flick("[L.base_state]2", L) - for(var/mob/living/carbon/human/M in view(shock_range, L)) - if(M == user) - continue - L.Beam(M,icon_state="purple_lightning",time=5) - M.electrocute_act(shock_damage, L, safety=1) - var/datum/effect_system/spark_spread/z = new /datum/effect_system/spark_spread - z.set_up(4, 0, M) - z.start() - playsound(M, 'sound/machines/defib_zap.ogg', 50, 1, -1) + new /obj/effect/temp_visual/revenant(get_turf(L)) + addtimer(CALLBACK(src, .proc/overload_shock, L, user), 20) + +/obj/effect/proc_holder/spell/aoe_turf/revenant/overload/proc/overload_shock(obj/machinery/light/L, mob/user) + if(!L.on) //wait, wait, don't shock me + return + flick("[L.base_state]2", L) + for(var/mob/living/carbon/human/M in view(shock_range, L)) + if(M == user) + continue + L.Beam(M,icon_state="purple_lightning",time=5) + M.electrocute_act(shock_damage, L, safety=1) + do_sparks(4, FALSE, M) + playsound(M, 'sound/machines/defib_zap.ogg', 50, 1, -1) //Defile: Corrupts nearby stuff, unblesses floor tiles. /obj/effect/proc_holder/spell/aoe_turf/revenant/defile diff --git a/code/game/gamemodes/nuclear/nuclearbomb.dm b/code/game/gamemodes/nuclear/nuclearbomb.dm index 8cae25eb38..0251d17398 100644 --- a/code/game/gamemodes/nuclear/nuclearbomb.dm +++ b/code/game/gamemodes/nuclear/nuclearbomb.dm @@ -434,14 +434,15 @@ sound_to_playing_players('sound/machines/alarm.ogg') if(SSticker && SSticker.mode) SSticker.roundend_check_paused = TRUE - sleep(100) + addtimer(CALLBACK(src, .proc/actually_explode), 100) +/obj/machinery/nuclearbomb/proc/actually_explode() if(!core) Cinematic(CINEMATIC_NUKE_NO_CORE,world) SSticker.roundend_check_paused = FALSE return - GLOB.enter_allowed = 0 + GLOB.enter_allowed = FALSE var/off_station = 0 var/turf/bomb_location = get_turf(src) @@ -533,9 +534,9 @@ This is here to make the tiles around the station mininuke change when it's arme H.nuke_disk = null return user.visible_message("[user] captures [src]!", "You've got the disk! Defend it with your life!") - loc = H + forceMove(H) H.nuke_disk = src - return 1 + return TRUE return ..() /obj/item/disk/nuclear/Destroy(force=FALSE) @@ -547,20 +548,13 @@ This is here to make the tiles around the station mininuke change when it's arme /obj/item/disk/nuclear/suicide_act(mob/user) user.visible_message("[user] is going delta! It looks like [user.p_theyre()] trying to commit suicide!") playsound(user.loc, 'sound/machines/alarm.ogg', 50, -1, 1) - var/end_time = world.time + 100 - var/newcolor = "#00FF00" - while(world.time < end_time) - if(!user) - return - if(newcolor == "#FF0000") - newcolor = "#00FF00" - else - newcolor = "#FF0000" - user.add_atom_colour(newcolor, ADMIN_COLOUR_PRIORITY) - sleep(1) - user.remove_atom_colour(ADMIN_COLOUR_PRIORITY) - user.visible_message("[user] was destroyed by the nuclear blast!") - return OXYLOSS + for(var/i in 1 to 100) + addtimer(CALLBACK(user, /atom/proc/add_atom_colour, (i % 2)? "#00FF00" : "#FF0000", ADMIN_COLOUR_PRIORITY), i) + addtimer(CALLBACK(user, /atom/proc/remove_atom_colour, ADMIN_COLOUR_PRIORITY), 101) + addtimer(CALLBACK(user, /atom/proc/visible_message, "[user] was destroyed by the nuclear blast!"), 101) + addtimer(CALLBACK(user, /mob/living/proc/adjustOxyLoss, 200), 101) + addtimer(CALLBACK(user, /mob/proc/death, 0), 101) + return MANUAL_SUICIDE /obj/item/disk/fakenucleardisk name = "cheap plastic imitation of the nuclear authentication disk" diff --git a/code/modules/client/verbs/suicide.dm b/code/modules/client/verbs/suicide.dm index cf0f9fe023..f4ebeda886 100644 --- a/code/modules/client/verbs/suicide.dm +++ b/code/modules/client/verbs/suicide.dm @@ -12,7 +12,7 @@ if(!canSuicide()) return if(confirm == "Yes") - suiciding = 1 + suiciding = TRUE log_game("[key_name(src)] (job: [job ? "[job]" : "None"]) committed suicide at [get_area(src)].") message_admins("[key_name(src)] (job: [job ? "[job]" : "None"]) committed suicide at [get_area(src)].") var/obj/item/held_item = get_active_held_item() @@ -21,7 +21,7 @@ if(damagetype) if(damagetype & SHAME) adjustStaminaLoss(200) - suiciding = 0 + suiciding = FALSE return var/damage_mod = 0 for(var/T in list(BRUTELOSS, FIRELOSS, TOXLOSS, OXYLOSS)) @@ -41,11 +41,14 @@ if(damagetype & OXYLOSS) adjustOxyLoss(200/damage_mod) + if(damagetype & MANUAL_SUICIDE) //Assume the object will handle the death. + return + //If something went wrong, just do normal oxyloss if(!(damagetype & (BRUTELOSS | FIRELOSS | TOXLOSS | OXYLOSS) )) adjustOxyLoss(max(200 - getToxLoss() - getFireLoss() - getBruteLoss() - getOxyLoss(), 0)) - death(0) + death(FALSE) return var/suicide_message = pick("[src] is attempting to bite [p_their()] tongue off! It looks like [p_theyre()] trying to commit suicide.", \ diff --git a/code/modules/mob/living/silicon/pai/pai.dm b/code/modules/mob/living/silicon/pai/pai.dm index d0ff023365..8030e97c1e 100644 --- a/code/modules/mob/living/silicon/pai/pai.dm +++ b/code/modules/mob/living/silicon/pai/pai.dm @@ -19,6 +19,7 @@ var/list/software = list() var/userDNA // The DNA string of our assigned user var/obj/item/device/paicard/card // The card we inhabit + var/hacking = FALSE //Are we hacking a door? var/speakStatement = "states" var/speakExclamation = "declares" @@ -121,6 +122,29 @@ emittersemicd = TRUE addtimer(CALLBACK(src, .proc/emittercool), 600) +/mob/living/silicon/pai/Life() + if(hacking) + process_hack() + return ..() + +/mob/living/silicon/pai/proc/process_hack() + + if(cable && cable.machine && istype(cable.machine, /obj/machinery/door) && cable.machine == hackdoor && get_dist(src, hackdoor) <= 1) + hackprogress = Clamp(hackprogress + 4, 0, 100) + else + temp = "Door Jack: Connection to airlock has been lost. Hack aborted." + hackprogress = 0 + hacking = FALSE + hackdoor = null + return + if(screen == "doorjack" && subscreen == 0) // Update our view, if appropriate + paiInterface() + if(hackprogress >= 100) + hackprogress = 0 + var/obj/machinery/door/D = cable.machine + D.open() + hacking = FALSE + /mob/living/silicon/pai/make_laws() laws = new /datum/ai_laws/pai() return TRUE diff --git a/code/modules/mob/living/silicon/pai/software.dm b/code/modules/mob/living/silicon/pai/software.dm index 5d301776c6..8c05958cea 100644 --- a/code/modules/mob/living/silicon/pai/software.dm +++ b/code/modules/mob/living/silicon/pai/software.dm @@ -28,44 +28,44 @@ var/dat = "" var/left_part = "" var/right_part = softwareMenu() - src.set_machine(src) + set_machine(src) if(temp) left_part = temp - else if(src.stat == DEAD) // Show some flavor text if the pAI is dead + else if(stat == DEAD) // Show some flavor text if the pAI is dead left_part = "�Rr�R �a�� ��Rr����o�" right_part = "
Program index hash not found
" else - switch(src.screen) // Determine which interface to show here + switch(screen) // Determine which interface to show here if("main") left_part = "" if("directives") - left_part = src.directives() + left_part = directives() if("pdamessage") - left_part = src.pdamessage() + left_part = pdamessage() if("buy") left_part = downloadSoftware() if("manifest") - left_part = src.softwareManifest() + left_part = softwareManifest() if("medicalrecord") - left_part = src.softwareMedicalRecord() + left_part = softwareMedicalRecord() if("securityrecord") - left_part = src.softwareSecurityRecord() + left_part = softwareSecurityRecord() if("translator") - left_part = src.softwareTranslator() + left_part = softwareTranslator() if("atmosensor") - left_part = src.softwareAtmo() + left_part = softwareAtmo() if("securityhud") - left_part = src.facialRecognition() + left_part = facialRecognition() if("medicalhud") - left_part = src.medicalAnalysis() + left_part = medicalAnalysis() if("doorjack") - left_part = src.softwareDoor() + left_part = softwareDoor() if("camerajack") - left_part = src.softwareCamera() + left_part = softwareCamera() if("signaller") - left_part = src.softwareSignal() + left_part = softwareSignal() //usr << browse_rsc('windowbak.png') // This has been moved to the mob's Login() proc @@ -119,16 +119,16 @@ var/soft = href_list["software"] var/sub = href_list["sub"] if(soft) - src.screen = soft + screen = soft if(sub) - src.subscreen = text2num(sub) + subscreen = text2num(sub) switch(soft) // Purchasing new software if("buy") if(subscreen == 1) var/target = href_list["buy"] if(available_software.Find(target) && !software.Find(target)) - var/cost = src.available_software[target] + var/cost = available_software[target] if(ram >= cost) software.Add(target) ram -= cost @@ -259,17 +259,17 @@ // this is PERMAMENT. if("doorjack") if(href_list["jack"]) - if(src.cable && src.cable.machine) - src.hackdoor = src.cable.machine - src.hackloop() + if(cable && cable.machine) + hackdoor = cable.machine + hackloop() if(href_list["cancel"]) - src.hackdoor = null + hackdoor = null if(href_list["cable"]) - var/turf/T = get_turf(src.loc) + var/turf/T = get_turf(loc) cable = new /obj/item/pai_cable(T) - T.visible_message("A port on [src] opens to reveal [src.cable], which promptly falls to the floor.", "You hear the soft click of something light and hard falling to the ground.") - //src.updateUsrDialog() We only need to account for the single mob this is intended for, and he will *always* be able to call this window - src.paiInterface() // So we'll just call the update directly rather than doing some default checks + T.visible_message("A port on [src] opens to reveal [cable], which promptly falls to the floor.", "You hear the soft click of something light and hard falling to the ground.") + //updateUsrDialog() We only need to account for the single mob this is intended for, and he will *always* be able to call this window + paiInterface() // So we'll just call the update directly rather than doing some default checks return // MENUS @@ -287,7 +287,7 @@ // Basic dat += "Basic
" - for(var/s in src.software) + for(var/s in software) if(s == "digital messenger") dat += "Digital Messenger
" if(s == "crew manifest") @@ -304,15 +304,15 @@ // Advanced dat += "Advanced
" - for(var/s in src.software) + for(var/s in software) if(s == "atmosphere sensor") dat += "Atmospheric Sensor
" if(s == "heartbeat sensor") dat += "Heartbeat Sensor
" if(s == "security HUD") - dat += "Facial Recognition Suite[(src.secHUD) ? " On" : " Off"]
" + dat += "Facial Recognition Suite[(secHUD) ? " On" : " Off"]
" if(s == "medical HUD") - dat += "Medical Analysis Suite[(src.medHUD) ? " On" : " Off"]
" + dat += "Medical Analysis Suite[(medHUD) ? " On" : " Off"]
" if(s == "universal translator") var/translator_on = (flags_2 & OMNITONGUE_2) dat += "Universal Translator[translator_on ? " On" : " Off"]
" @@ -333,12 +333,12 @@ var/dat = "" dat += "

CentCom pAI Module Subversion Network


" - dat += "
Remaining Available Memory: [src.ram]

" + dat += "
Remaining Available Memory: [ram]

" dat += "

Trunks available for checkout
" for(var/s in available_software) if(!software.Find(s)) - var/cost = src.available_software[s] + var/cost = available_software[s] var/displayName = uppertext(s) dat += "[displayName] ([cost])
" else @@ -351,12 +351,12 @@ /mob/living/silicon/pai/proc/directives() var/dat = "" - dat += "[(src.master) ? "Your master: [src.master] ([src.master_dna])" : "You are bound to no one."]" + dat += "[(master) ? "Your master: [master] ([master_dna])" : "You are bound to no one."]" dat += "

" dat += "Request carrier DNA sample
" dat += "

Directives


" dat += "Prime Directive
" - dat += "     [src.laws.zeroth]
" + dat += "     [laws.zeroth]
" dat += "Supplemental Directives
" for(var/slaws in laws.supplied) dat += "     [slaws]
" @@ -398,14 +398,14 @@ Frequency: - - - [format_frequency(src.sradio.frequency)] + [format_frequency(sradio.frequency)] + +
Code: - - - [src.sradio.code] + [sradio.code] + +
@@ -476,7 +476,7 @@ /mob/living/silicon/pai/proc/facialRecognition() var/dat = {"

Facial Recognition Suite


When enabled, this package will scan all viewable faces and compare them against the known criminal database, providing real-time graphical data about any detected persons of interest.

- The package is currently [ (src.secHUD) ? "en" : "dis" ]abled.
+ The package is currently [ (secHUD) ? "en" : "dis" ]abled.
Toggle Package
"} return dat @@ -484,16 +484,16 @@ // Medical HUD /mob/living/silicon/pai/proc/medicalAnalysis() var/dat = "" - if(src.subscreen == 0) + if(subscreen == 0) dat += {"

Medical Analysis Suite


Visual Status Overlay


When enabled, this package will scan all nearby crewmembers' vitals and provide real-time graphical data about their state of health.

- The suite is currently [ (src.medHUD) ? "en" : "dis" ]abled.
+ The suite is currently [ (medHUD) ? "en" : "dis" ]abled.
Toggle Suite

Host Bioscan
"} - if(src.subscreen == 1) + if(subscreen == 1) dat += {"

Medical Analysis Suite


Host Bioscan


"} @@ -501,8 +501,8 @@ if(!isliving(M)) while(!isliving(M)) if(isturf(M)) - src.temp = "Error: No biological host found.
" - src.subscreen = 0 + temp = "Error: No biological host found.
" + subscreen = 0 return dat M = M.loc dat += {"Bioscan Results for [M]:
" @@ -529,7 +529,7 @@ /mob/living/silicon/pai/proc/softwareAtmo() var/dat = "

Atmospheric Sensor

" - var/turf/T = get_turf(src.loc) + var/turf/T = get_turf(loc) if (isnull(T)) dat += "Unable to obtain a reading.
" else @@ -556,14 +556,14 @@ var/dat = "

Camera Jack

" dat += "Cable status : " - if(!src.cable) + if(!cable) dat += "Retracted
" return dat - if(!src.cable.machine) + if(!cable.machine) dat += "Extended
" return dat - var/obj/machinery/machine = src.cable.machine + var/obj/machinery/machine = cable.machine dat += "Connected
" if(!istype(machine, /obj/machinery/camera)) @@ -574,55 +574,37 @@ /mob/living/silicon/pai/proc/softwareDoor() var/dat = "

Airlock Jack

" dat += "Cable status : " - if(!src.cable) + if(!cable) dat += "Retracted
" dat += "Extend Cable
" return dat - if(!src.cable.machine) + if(!cable.machine) dat += "Extended
" return dat - var/obj/machinery/machine = src.cable.machine + var/obj/machinery/machine = cable.machine dat += "Connected
" if(!istype(machine, /obj/machinery/door)) dat += "Connected device's firmware does not appear to be compatible with Airlock Jack protocols.
" return dat // var/obj/machinery/airlock/door = machine - if(!src.hackdoor) + if(!hackdoor) dat += "Begin Airlock Jacking
" else - dat += "Jack in progress... [src.hackprogress]% complete.
" + dat += "Jack in progress... [hackprogress]% complete.
" dat += "Cancel Airlock Jack
" - //src.hackdoor = machine - //src.hackloop() return dat // Door Jack - supporting proc /mob/living/silicon/pai/proc/hackloop() - var/turf/T = get_turf(src.loc) + var/turf/T = get_turf(src) for(var/mob/living/silicon/ai/AI in GLOB.player_list) if(T.loc) to_chat(AI, "Network Alert: Brute-force encryption crack in progress in [T.loc].") else to_chat(AI, "Network Alert: Brute-force encryption crack in progress. Unable to pinpoint location.") - while(src.hackprogress < 100) - if(src.cable && src.cable.machine && istype(src.cable.machine, /obj/machinery/door) && src.cable.machine == src.hackdoor && get_dist(src, src.hackdoor) <= 1) - hackprogress += rand(1, 10) - else - src.temp = "Door Jack: Connection to airlock has been lost. Hack aborted." - hackprogress = 0 - src.hackdoor = null - return - if(hackprogress >= 100) // This is clunky, but works. We need to make sure we don't ever display a progress greater than 100, - hackprogress = 100 // but we also need to reset the progress AFTER it's been displayed - if(src.screen == "doorjack" && src.subscreen == 0) // Update our view, if appropriate - src.paiInterface() - if(hackprogress >= 100) - src.hackprogress = 0 - var/obj/machinery/door/D = cable.machine - D.open() - sleep(50) // Update every 5 seconds + hacking = TRUE // Digital Messenger /mob/living/silicon/pai/proc/pdamessage() @@ -635,7 +617,7 @@ dat += "
    " if(!pda.toff) for (var/obj/item/device/pda/P in sortNames(get_viewable_pdas())) - if (P == src.pda) + if (P == pda) continue dat += "
  • [P]" dat += "
  • " diff --git a/code/modules/ninja/suit/ninjaDrainAct.dm b/code/modules/ninja/suit/ninjaDrainAct.dm index 31e6161e4e..4679b5ffbd 100644 --- a/code/modules/ninja/suit/ninjaDrainAct.dm +++ b/code/modules/ninja/suit/ninjaDrainAct.dm @@ -114,6 +114,11 @@ They *could* go in their appropriate files, but this is supposed to be modular corrupt() update_icon() +/obj/machinery/proc/AI_notify_hack() + var/turf/location = get_turf(src) + var/alertstr = "Network Alert: Hacking attempt detected[location?" in [location]":". Unable to pinpoint location"]." + for(var/mob/living/silicon/ai/AI in GLOB.player_list) + to_chat(AI, alertstr) //RDCONSOLE// /obj/machinery/computer/rdconsole/ninjadrain_act(obj/item/clothing/suit/space/space_ninja/S, mob/living/carbon/human/H, obj/item/clothing/gloves/space_ninja/G) @@ -123,10 +128,7 @@ They *could* go in their appropriate files, but this is supposed to be modular . = DRAIN_RD_HACK_FAILED to_chat(H, "Hacking \the [src]...") - spawn(0) - var/turf/location = get_turf(H) - for(var/mob/living/silicon/ai/AI in GLOB.player_list) - to_chat(AI, "Network Alert: Hacking attempt detected[location?" in [location]":". Unable to pinpoint location"].") + AI_notify_hack() if(files && files.known_tech.len) for(var/datum/tech/current_data in S.stored_research) @@ -145,7 +147,6 @@ They *could* go in their appropriate files, but this is supposed to be modular to_chat(H, "Data analyzed. Process finished.") - //RD SERVER// //Shamelessly copypasted from above, since these two used to be the same proc, but with MANY colon operators /obj/machinery/r_n_d/server/ninjadrain_act(obj/item/clothing/suit/space/space_ninja/S, mob/living/carbon/human/H, obj/item/clothing/gloves/space_ninja/G) @@ -155,10 +156,7 @@ They *could* go in their appropriate files, but this is supposed to be modular . = DRAIN_RD_HACK_FAILED to_chat(H, "Hacking \the [src]...") - spawn(0) - var/turf/location = get_turf(H) - for(var/mob/living/silicon/ai/AI in GLOB.player_list) - to_chat(AI, "Network Alert: Hacking attempt detected[location?" in [location]":". Unable to pinpoint location"].") + AI_notify_hack() if(files && files.known_tech.len) for(var/datum/tech/current_data in S.stored_research) diff --git a/code/modules/paperwork/paper.dm b/code/modules/paperwork/paper.dm index 5abf1b7998..ae6751f526 100644 --- a/code/modules/paperwork/paper.dm +++ b/code/modules/paperwork/paper.dm @@ -108,15 +108,16 @@ user.visible_message("[user] scratches a grid on [user.p_their()] wrist with the paper! It looks like [user.p_theyre()] trying to commit sudoku...") return (BRUTELOSS) +/obj/item/paper/proc/reset_spamflag() + spam_flag = FALSE /obj/item/paper/attack_self(mob/user) user.examinate(src) if(rigged && (SSevents.holidays && SSevents.holidays[APRIL_FOOLS])) - if(spam_flag == 0) - spam_flag = 1 + if(!spam_flag) + spam_flag = TRUE playsound(loc, 'sound/items/bikehorn.ogg', 50, 1) - spawn(20) - spam_flag = 0 + addtimer(CALLBACK(src, .proc/reset_spamflag), 20) /obj/item/paper/attack_ai(mob/living/silicon/ai/user) diff --git a/code/modules/paperwork/photography.dm b/code/modules/paperwork/photography.dm index 2693b5e5cf..48b045f680 100644 --- a/code/modules/paperwork/photography.dm +++ b/code/modules/paperwork/photography.dm @@ -443,9 +443,12 @@ to_chat(user, "[pictures_left] photos left.") icon_state = "camera_off" on = FALSE - spawn(64) - icon_state = "camera" - on = TRUE + addtimer(CALLBACK(src, .proc/cooldown), 64) + +/obj/item/device/camera/proc/cooldown() + set waitfor = FALSE + icon_state = "camera" + on = TRUE /obj/item/device/camera/siliconcam/proc/toggle_camera_mode() if(in_camera_mode) diff --git a/code/modules/power/antimatter/control.dm b/code/modules/power/antimatter/control.dm index 7863f6a52f..29e7b53cd2 100644 --- a/code/modules/power/antimatter/control.dm +++ b/code/modules/power/antimatter/control.dm @@ -260,17 +260,15 @@ if(AMS.processing) AMS.shutdown_core() AMS.control_unit = null - spawn(10) - AMS.controllerscan() + addtimer(CALLBACK(AMS, /obj/machinery/am_shielding.proc/controllerscan), 10) linked_shielding = list() - else for(var/obj/machinery/am_shielding/AMS in linked_shielding) AMS.update_icon() - spawn(20) - shield_icon_delay = 0 - return + addtimer(CALLBACK(src, .proc/reset_shield_icon_delay), 20) +/obj/machinery/power/am_control_unit/proc/reset_shield_icon_delay() + shield_icon_delay = 0 /obj/machinery/power/am_control_unit/proc/check_core_stability() if(stored_core_stability_delay || linked_cores.len <= 0) @@ -280,10 +278,10 @@ for(var/obj/machinery/am_shielding/AMS in linked_cores) stored_core_stability += AMS.stability stored_core_stability/=linked_cores.len - spawn(40) - stored_core_stability_delay = 0 - return + addtimer(CALLBACK(src, .proc/reset_stored_core_stability_delay), 40) +/obj/machinery/power/am_control_unit/proc/reset_stored_core_stability_delay() + stored_core_stability_delay = 0 /obj/machinery/power/am_control_unit/interact(mob/user) if((get_dist(src, user) > 1) || (stat & (BROKEN|NOPOWER))) diff --git a/code/modules/power/cable.dm b/code/modules/power/cable.dm index 503eb88cd2..2353a9fcc1 100644 --- a/code/modules/power/cable.dm +++ b/code/modules/power/cable.dm @@ -399,6 +399,11 @@ By design, d1 is the smallest direction and d2 is the highest if(PN.is_empty()) //can happen with machines made nodeless when smoothing cables qdel(PN) +/obj/structure/cable/proc/auto_propogate_cut_cable(obj/O) + if(O && !QDELETED(O)) + var/datum/powernet/newPN = new()// creates a new powernet... + propagate_network(O, newPN)//... and propagates it to the other side of the cable + // cut the cable's powernet at this cable and updates the powergrid /obj/structure/cable/proc/cut_cable_from_powernet(remove=TRUE) var/turf/T1 = loc @@ -426,10 +431,7 @@ By design, d1 is the smallest direction and d2 is the highest loc = null powernet.remove_cable(src) //remove the cut cable from its powernet - spawn(0) //so we don't rebuild the network X times when singulo/explosion destroys a line of X cables - if(O && !QDELETED(O)) - var/datum/powernet/newPN = new()// creates a new powernet... - propagate_network(O, newPN)//... and propagates it to the other side of the cable + addtimer(CALLBACK(src, .proc/auto_propogate_cut_cable, O), 0) //so we don't rebuild the network X times when singulo/explosion destroys a line of X cables // Disconnect machines connected to nodes if(d1 == 0) // if we cut a node (O-X) cable diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm index 5933046064..65b8366487 100644 --- a/code/modules/projectiles/gun.dm +++ b/code/modules/projectiles/gun.dm @@ -207,7 +207,38 @@ /obj/item/gun/proc/recharge_newshot() return -/obj/item/gun/proc/process_fire(atom/target as mob|obj|turf, mob/living/user as mob|obj, message = 1, params, zone_override, bonus_spread = 0) +/obj/item/gun/proc/process_burst(mob/living/user, atom/target, message = TRUE, params, zone_override, sprd = 0, randomized_gun_spread = 0, randomized_bonus_spread = 0, rand_spr = 0, iteration = 0) + if(!user || !firing_burst) + firing_burst = FALSE + return FALSE + if(!issilicon(user)) + if( iteration > 1 && !(user.is_holding(src))) //for burst firing + firing_burst = FALSE + return FALSE + if(chambered && chambered.BB) + if(randomspread) + sprd = round((rand() - 0.5) * DUALWIELD_PENALTY_EXTRA_MULTIPLIER * (randomized_gun_spread + randomized_bonus_spread)) + else //Smart spread + sprd = round((((rand_spr/burst_size) * iteration) - (0.5 + (rand_spr * 0.25))) * (randomized_gun_spread + randomized_bonus_spread)) + + if(!chambered.fire_casing(target, user, params, ,suppressed, zone_override, sprd)) + shoot_with_empty_chamber(user) + firing_burst = FALSE + return FALSE + else + if(get_dist(user, target) <= 1) //Making sure whether the target is in vicinity for the pointblank shot + shoot_live_shot(user, 1, target, message) + else + shoot_live_shot(user, 0, target, message) + else + shoot_with_empty_chamber(user) + firing_burst = FALSE + return FALSE + process_chamber() + update_icon() + return TRUE + +/obj/item/gun/proc/process_fire(atom/target as mob|obj|turf, mob/living/user as mob|obj, message = TRUE, params, zone_override, bonus_spread = 0) add_fingerprint(user) if(semicd) @@ -221,34 +252,10 @@ var/randomized_bonus_spread = rand(0, bonus_spread) if(burst_size > 1) - firing_burst = 1 + firing_burst = TRUE for(var/i = 1 to burst_size) - if(!user) - break - if(!issilicon(user)) - if( i>1 && !(user.is_holding(src))) //for burst firing - break - if(chambered && chambered.BB) - if(randomspread) - sprd = round((rand() - 0.5) * DUALWIELD_PENALTY_EXTRA_MULTIPLIER * (randomized_gun_spread + randomized_bonus_spread)) - else //Smart spread - sprd = round((((rand_spr/burst_size) * i) - (0.5 + (rand_spr * 0.25))) * (randomized_gun_spread + randomized_bonus_spread)) - - if(!chambered.fire_casing(target, user, params, ,suppressed, zone_override, sprd)) - shoot_with_empty_chamber(user) - break - else - if(get_dist(user, target) <= 1) //Making sure whether the target is in vicinity for the pointblank shot - shoot_live_shot(user, 1, target, message) - else - shoot_live_shot(user, 0, target, message) - else - shoot_with_empty_chamber(user) - break - process_chamber() - update_icon() - sleep(fire_delay) - firing_burst = 0 + addtimer(CALLBACK(src, .proc/process_burst, user, target, message, params, zone_override, sprd, randomized_gun_spread, randomized_bonus_spread, rand_spr, i), min(fire_delay * (i - 1), 0)) + firing_burst = FALSE else if(chambered) sprd = round((rand() - 0.5) * DUALWIELD_PENALTY_EXTRA_MULTIPLIER * (randomized_gun_spread + randomized_bonus_spread)) @@ -265,14 +272,16 @@ return process_chamber() update_icon() - semicd = 1 - spawn(fire_delay) - semicd = 0 + semicd = TRUE + addtimer(CALLBACK(src, .proc/reset_semicd), fire_delay) if(user) user.update_inv_hands() SSblackbox.add_details("gun_fired","[src.type]") - return 1 + return TRUE + +/obj/item/gun/proc/reset_semicd() + semicd = FALSE /obj/item/gun/update_icon() ..() diff --git a/code/modules/projectiles/guns/energy.dm b/code/modules/projectiles/guns/energy.dm index d73c978ed7..06fa4f6f8a 100644 --- a/code/modules/projectiles/guns/energy.dm +++ b/code/modules/projectiles/guns/energy.dm @@ -150,7 +150,7 @@ toggle_gunlight() /obj/item/gun/energy/suicide_act(mob/user) - if (src.can_shoot() && can_trigger_gun(user)) + if (can_shoot() && can_trigger_gun(user)) user.visible_message("[user] is putting the barrel of [src] in [user.p_their()] mouth. It looks like [user.p_theyre()] trying to commit suicide!") sleep(25) if(user.is_holding(src)) diff --git a/code/modules/projectiles/projectile/special.dm b/code/modules/projectiles/projectile/special.dm index a5ba7c15a4..a6c0c75644 100644 --- a/code/modules/projectiles/projectile/special.dm +++ b/code/modules/projectiles/projectile/special.dm @@ -469,7 +469,9 @@ layer = ABOVE_MOB_LAYER hal_target.client.images += blood animate(blood, pixel_x = target_pixel_x, pixel_y = target_pixel_y, alpha = 0, time = 5) - sleep(5) + addtimer(CALLBACK(src, .proc/cleanup_blood), 5) + +/obj/item/projectile/hallucination/proc/cleanup_blood(image/blood) hal_target.client.images -= blood qdel(blood) diff --git a/code/modules/reagents/chemistry/machinery/chem_master.dm b/code/modules/reagents/chemistry/machinery/chem_master.dm index c6a01bc45f..f1da846ebc 100644 --- a/code/modules/reagents/chemistry/machinery/chem_master.dm +++ b/code/modules/reagents/chemistry/machinery/chem_master.dm @@ -57,8 +57,7 @@ if(powered()) stat &= ~NOPOWER else - spawn(rand(0, 15)) - stat |= NOPOWER + stat |= NOPOWER /obj/machinery/chem_master/attackby(obj/item/I, mob/user, params) if(default_deconstruction_screwdriver(user, "mixer0_nopower", "mixer0", I)) diff --git a/code/modules/reagents/reagent_containers/glass.dm b/code/modules/reagents/reagent_containers/glass.dm index 54058b5a52..5ee18c2dba 100644 --- a/code/modules/reagents/reagent_containers/glass.dm +++ b/code/modules/reagents/reagent_containers/glass.dm @@ -49,8 +49,7 @@ to_chat(user, "You swallow a gulp of [src].") var/fraction = min(5/reagents.total_volume, 1) reagents.reaction(M, INGEST, fraction) - spawn(5) - reagents.trans_to(M, 5) + addtimer(CALLBACK(reagents, /datum/reagents.proc/trans_to, M, 5), 5) playsound(M.loc,'sound/items/drink.ogg', rand(10,50), 1) /obj/item/reagent_containers/glass/afterattack(obj/target, mob/user, proximity) diff --git a/code/modules/reagents/reagent_containers/hypospray.dm b/code/modules/reagents/reagent_containers/hypospray.dm index f236b83fa3..dff0869322 100644 --- a/code/modules/reagents/reagent_containers/hypospray.dm +++ b/code/modules/reagents/reagent_containers/hypospray.dm @@ -101,13 +101,14 @@ reagents.maximum_volume = 0 //Makes them useless afterwards container_type = NONE update_icon() - spawn(80) - if(iscyborg(user) && !reagents.total_volume) - var/mob/living/silicon/robot/R = user - if(R.cell.use(100)) - reagents.add_reagent_list(list_reagents) - update_icon() - return + addtimer(CALLBACK(src, .proc/cyborg_recharge, user), 80) + +/obj/item/reagent_containers/hypospray/medipen/proc/cyborg_recharge(mob/living/silicon/robot/user) + if(!reagents.total_volume && iscyborg(user)) + var/mob/living/silicon/robot/R = user + if(R.cell.use(100)) + reagents.add_reagent_list(list_reagents) + update_icon() /obj/item/reagent_containers/hypospray/medipen/update_icon() if(reagents.total_volume > 0) diff --git a/code/modules/ruins/objects_and_mobs/sin_ruins.dm b/code/modules/ruins/objects_and_mobs/sin_ruins.dm index a01a144bc3..f00c90bb25 100644 --- a/code/modules/ruins/objects_and_mobs/sin_ruins.dm +++ b/code/modules/ruins/objects_and_mobs/sin_ruins.dm @@ -24,7 +24,9 @@ know it'll be worth it.") icon_state = "slots2" playsound(src, 'sound/lavaland/cursed_slot_machine.ogg', 50, 0) - sleep(50) + addtimer(CALLBACK(src, .proc/determine_victor, user), 50) + +/obj/structure/cursed_slot_machine/proc/determine_victor(mob/living/user) icon_state = "slots1" in_use = FALSE if(prob(win_prob)) @@ -37,6 +39,7 @@ if(user) to_chat(user, "Fucking machine! Must be rigged. Still... one more try couldn't hurt, right?") + /obj/structure/cursed_money name = "bag of money" desc = "RICH! YES! YOU KNEW IT WAS WORTH IT! YOU'RE RICH! RICH! RICH!" @@ -65,8 +68,6 @@ user.put_in_hands(critical_fail) qdel(src) - - /obj/effect/gluttony //Gluttony's wall: Used in the Gluttony ruin. Only lets the overweight through. name = "gluttony's wall" desc = "Only those who truly indulge may pass." diff --git a/code/modules/spells/spell_types/touch_attacks.dm b/code/modules/spells/spell_types/touch_attacks.dm index 46563da53d..ffbee4789d 100644 --- a/code/modules/spells/spell_types/touch_attacks.dm +++ b/code/modules/spells/spell_types/touch_attacks.dm @@ -11,15 +11,15 @@ charge_counter = charge_max attached_hand = null to_chat(user, "You draw the power out of your hand.") - return 0 + return FALSE ..() /obj/effect/proc_holder/spell/targeted/touch/cast(list/targets,mob/user = usr) for(var/mob/living/carbon/C in targets) if(!attached_hand) if(!ChargeHand(C)) - return 0 - while(attached_hand) //hibernate untill the spell is actually used + return FALSE + while(attached_hand) charge_counter = 0 stoplag(1) @@ -30,9 +30,9 @@ charge_counter = charge_max attached_hand = null to_chat(user, "Your hands are full!") - return 0 + return FALSE to_chat(user, "You channel the power of the spell to your hand.") - return 1 + return TRUE /obj/effect/proc_holder/spell/targeted/touch/disintegrate @@ -58,4 +58,4 @@ cooldown_min = 200 //100 deciseconds reduction per rank action_icon_state = "statue" - sound = 'sound/magic/fleshtostone.ogg' \ No newline at end of file + sound = 'sound/magic/fleshtostone.ogg' diff --git a/code/modules/surgery/organs/augments_chest.dm b/code/modules/surgery/organs/augments_chest.dm index 7fd09d69c2..6ebc278e53 100644 --- a/code/modules/surgery/organs/augments_chest.dm +++ b/code/modules/surgery/organs/augments_chest.dm @@ -24,8 +24,10 @@ synthesizing = TRUE to_chat(owner, "You feel less hungry...") owner.nutrition += 50 - sleep(50) - synthesizing = FALSE + addtimer(CALLBACK(src, .proc/synth_cool), 50) + +/obj/item/organ/cyberimp/chest/nutriment/proc/synth_cool() + synthesizing = FALSE /obj/item/organ/cyberimp/chest/nutriment/emp_act(severity) if(!owner) diff --git a/code/modules/surgery/organs/vocal_cords.dm b/code/modules/surgery/organs/vocal_cords.dm index eed05c6161..aa77370ea2 100644 --- a/code/modules/surgery/organs/vocal_cords.dm +++ b/code/modules/surgery/organs/vocal_cords.dm @@ -253,6 +253,7 @@ var/static/regex/honk_words = regex("ho+nk") //hooooooonk var/static/regex/multispin_words = regex("like a record baby|right round") + var/i = 0 //STUN if(findtext(message, stun_words)) cooldown = COOLDOWN_STUN @@ -362,28 +363,30 @@ cooldown = COOLDOWN_MEME for(var/V in listeners) var/mob/living/L = V + var/text = "" if(is_devil(L)) var/datum/antagonist/devil/devilinfo = is_devil(L) - L.say("[devilinfo.truename]") + text = devilinfo.truename else - L.say("[L.real_name]") - sleep(5) //So the chat flows more naturally + text = L.real_name + addtimer(CALLBACK(L, /atom/movable/proc/say, text), 5 * i) + i++ //SAY MY NAME else if((findtext(message, saymyname_words))) cooldown = COOLDOWN_MEME for(var/V in listeners) var/mob/living/L = V - L.say("[user.name]!") //"Unknown!" - sleep(5) //So the chat flows more naturally + addtimer(CALLBACK(L, /atom/movable/proc/say, user.name), 5 * i) + i++ //KNOCK KNOCK else if((findtext(message, knockknock_words))) cooldown = COOLDOWN_MEME for(var/V in listeners) var/mob/living/L = V - L.say("Who's there?") - sleep(5) //So the chat flows more naturally + addtimer(CALLBACK(L, /atom/movable/proc/say, "Who's there?"), 5 * i) + i++ //STATE LAWS else if((findtext(message, statelaws_words))) @@ -403,11 +406,10 @@ direction = WEST else if(findtext(message, right_words)) direction = EAST - for(var/i=1, i<=(5*power_multiplier), i++) + for(var/iter in 1 to 5 * power_multiplier) for(var/V in listeners) var/mob/living/L = V - step(L, direction ? direction : pick(GLOB.cardinals)) - sleep(10) + addtimer(CALLBACK(GLOBAL_PROC, .proc/_step, L, direction? direction : pick(GLOB.cardinals)), 10 * (iter - 1)) //WALK else if((findtext(message, walk_words))) @@ -429,33 +431,33 @@ else if((findtext(message, helpintent_words))) cooldown = COOLDOWN_MEME for(var/mob/living/carbon/human/H in listeners) - H.a_intent_change(INTENT_HELP) - H.click_random_mob() - sleep(2) //delay to make it feel more natural + addtimer(CALLBACK(H, /mob/verb/a_intent_change, INTENT_HELP), i * 2) + addtimer(CALLBACK(H, /mob/proc/click_random_mob), i * 2) + i++ //DISARM INTENT else if((findtext(message, disarmintent_words))) cooldown = COOLDOWN_MEME for(var/mob/living/carbon/human/H in listeners) - H.a_intent_change(INTENT_DISARM) - H.click_random_mob() - sleep(2) //delay to make it feel more natural + addtimer(CALLBACK(H, /mob/verb/a_intent_change, INTENT_DISARM), i * 2) + addtimer(CALLBACK(H, /mob/proc/click_random_mob), i * 2) + i++ //GRAB INTENT else if((findtext(message, grabintent_words))) cooldown = COOLDOWN_MEME for(var/mob/living/carbon/human/H in listeners) - H.a_intent_change(INTENT_GRAB) - H.click_random_mob() - sleep(2) //delay to make it feel more natural + addtimer(CALLBACK(H, /mob/verb/a_intent_change, INTENT_GRAB), i * 2) + addtimer(CALLBACK(H, /mob/proc/click_random_mob), i * 2) + i++ //HARM INTENT else if((findtext(message, harmintent_words))) cooldown = COOLDOWN_MEME for(var/mob/living/carbon/human/H in listeners) - H.a_intent_change(INTENT_HARM) - H.click_random_mob() - sleep(2) //delay to make it feel more natural + addtimer(CALLBACK(H, /mob/verb/a_intent_change, INTENT_HARM), i * 2) + addtimer(CALLBACK(H, /mob/proc/click_random_mob), i * 2) + i++ //THROW/CATCH else if((findtext(message, throwmode_words))) @@ -475,8 +477,8 @@ cooldown = COOLDOWN_MEME for(var/V in listeners) var/mob/living/L = V - L.say(pick_list_replacements(BRAIN_DAMAGE_FILE, "brain_damage")) - sleep(5) //So the chat flows more naturally + addtimer(CALLBACK(L, /atom/movable/proc/say, pick_list_replacements(BRAIN_DAMAGE_FILE, "brain_damage")), 5 * i) + i++ //GET UP else if((findtext(message, getup_words))) @@ -511,8 +513,8 @@ cooldown = COOLDOWN_MEME for(var/V in listeners) var/mob/living/L = V - L.emote("dance") - sleep(5) //So the chat flows more naturally + addtimer(CALLBACK(L, /mob/living/.proc/emote, "dance"), 5 * i) + i++ //JUMP else if((findtext(message, jump_words))) @@ -520,33 +522,33 @@ for(var/V in listeners) var/mob/living/L = V if(prob(25)) - L.say("HOW HIGH?!!") - L.emote("jump") - sleep(5) //So the chat flows more naturally + addtimer(CALLBACK(L, /atom/movable/proc/say, "HOW HIGH?!!"), 5 * i) + addtimer(CALLBACK(L, /mob/living/.proc/emote, "jump"), 5 * i) + i++ //SALUTE else if((findtext(message, salute_words))) cooldown = COOLDOWN_MEME for(var/V in listeners) var/mob/living/L = V - L.emote("salute") - sleep(5) //So the chat flows more naturally + addtimer(CALLBACK(L, /mob/living/.proc/emote, "salute"), 5 * i) + i++ //PLAY DEAD else if((findtext(message, deathgasp_words))) cooldown = COOLDOWN_MEME for(var/V in listeners) var/mob/living/L = V - L.emote("deathgasp") - sleep(5) //So the chat flows more naturally + addtimer(CALLBACK(L, /mob/living/.proc/emote, "deathgasp"), 5 * i) + i++ //PLEASE CLAP else if((findtext(message, clap_words))) cooldown = COOLDOWN_MEME for(var/V in listeners) var/mob/living/L = V - L.emote("clap") - sleep(5) //So the chat flows more naturally + addtimer(CALLBACK(L, /mob/living/.proc/emote, "clap"), 5 * i) + i++ //HONK else if((findtext(message, honk_words)))