diff --git a/code/datums/components/storage/concrete/emergency.dm b/code/datums/components/storage/concrete/emergency.dm index 48880ff605..348821a913 100644 --- a/code/datums/components/storage/concrete/emergency.dm +++ b/code/datums/components/storage/concrete/emergency.dm @@ -36,3 +36,4 @@ /datum/component/storage/concrete/emergency/proc/unlock_me(datum/source) if(locked) set_locked(source, FALSE) + return TRUE diff --git a/code/game/atoms.dm b/code/game/atoms.dm index 88fe2c8d13..6665e4d59b 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -379,7 +379,7 @@ SEND_SIGNAL(src, COMSIG_ATOM_ACID_ACT, acidpwr, acid_volume) /atom/proc/emag_act() - SEND_SIGNAL(src, COMSIG_ATOM_EMAG_ACT) + return SEND_SIGNAL(src, COMSIG_ATOM_EMAG_ACT) /atom/proc/rad_act(strength) SEND_SIGNAL(src, COMSIG_ATOM_RAD_ACT, strength) diff --git a/code/game/machinery/Sleeper.dm b/code/game/machinery/Sleeper.dm index aa363428fb..76ea855c77 100644 --- a/code/game/machinery/Sleeper.dm +++ b/code/game/machinery/Sleeper.dm @@ -193,8 +193,10 @@ to_chat(usr, "Chem System Re-route detected, results may not be as expected!") /obj/machinery/sleeper/emag_act(mob/user) + . = ..() scramble_chem_buttons() to_chat(user, "You scramble the sleeper's user interface!") + return TRUE /obj/machinery/sleeper/proc/inject_chem(chem, mob/user) if((chem in available_chems) && chem_allowed(chem)) diff --git a/code/game/machinery/announcement_system.dm b/code/game/machinery/announcement_system.dm index 884b818f32..56227cdd53 100644 --- a/code/game/machinery/announcement_system.dm +++ b/code/game/machinery/announcement_system.dm @@ -177,7 +177,9 @@ GLOBAL_LIST_EMPTY(announcement_systems) act_up() /obj/machinery/announcement_system/emag_act() + . = ..() if(obj_flags & EMAGGED) return obj_flags |= EMAGGED act_up() + return TRUE diff --git a/code/game/machinery/buttons.dm b/code/game/machinery/buttons.dm index 879be046c9..968cbe7254 100644 --- a/code/game/machinery/buttons.dm +++ b/code/game/machinery/buttons.dm @@ -101,12 +101,14 @@ return ..() /obj/machinery/button/emag_act(mob/user) + . = ..() if(obj_flags & EMAGGED) return req_access = list() req_one_access = list() playsound(src, "sparks", 100, 1) obj_flags |= EMAGGED + return TRUE /obj/machinery/button/attack_ai(mob/user) if(!panel_open) diff --git a/code/game/machinery/cloning.dm b/code/game/machinery/cloning.dm index 4f04335852..a175558f74 100644 --- a/code/game/machinery/cloning.dm +++ b/code/game/machinery/cloning.dm @@ -320,10 +320,12 @@ return ..() /obj/machinery/clonepod/emag_act(mob/user) + . = ..() if(!occupant) return to_chat(user, "You corrupt the genetic compiler.") malfunction() + return TRUE //Put messages in the connected computer's temp var for display. /obj/machinery/clonepod/proc/connected_message(message) diff --git a/code/game/machinery/computer/apc_control.dm b/code/game/machinery/computer/apc_control.dm index e51d623c2f..1c517d6e8f 100644 --- a/code/game/machinery/computer/apc_control.dm +++ b/code/game/machinery/computer/apc_control.dm @@ -185,15 +185,19 @@ ui_interact(usr) //Refresh the UI after a filter changes /obj/machinery/computer/apc_control/emag_act(mob/user) + . = ..() if(!authenticated) to_chat(user, "You bypass [src]'s access requirements using your emag.") authenticated = TRUE log_activity("logged in") - else if(!(obj_flags & EMAGGED)) + else + if(obj_flags & EMAGGED) + return user.visible_message("You emag [src], disabling precise logging and allowing you to clear logs.") log_game("[key_name(user)] emagged [src] at [AREACOORD(src)], disabling operator tracking.") obj_flags |= EMAGGED - playsound(src, "sparks", 50, 1) + playsound(src, "sparks", 50, 1) + return TRUE /obj/machinery/computer/apc_control/proc/log_activity(log_text) var/op_string = operator && !(obj_flags & EMAGGED) ? operator : "\[NULL OPERATOR\]" diff --git a/code/game/machinery/computer/arcade/battle.dm b/code/game/machinery/computer/arcade/battle.dm index ded9cf95f6..b906b1afb5 100644 --- a/code/game/machinery/computer/arcade/battle.dm +++ b/code/game/machinery/computer/arcade/battle.dm @@ -186,6 +186,7 @@ /obj/machinery/computer/arcade/battle/emag_act(mob/user) + . = ..() if(obj_flags & EMAGGED) return to_chat(user, "A mesmerizing Rhumba beat starts playing from the arcade machine's speakers!") @@ -202,5 +203,5 @@ enemy_name = "Cuban Pete" name = "Outbomb Cuban Pete" - updateUsrDialog() + return TRUE \ No newline at end of file diff --git a/code/game/machinery/computer/arcade/minesweeper.dm b/code/game/machinery/computer/arcade/minesweeper.dm index e90e05966c..641ef1c9cd 100644 --- a/code/game/machinery/computer/arcade/minesweeper.dm +++ b/code/game/machinery/computer/arcade/minesweeper.dm @@ -284,6 +284,7 @@ return /obj/machinery/computer/arcade/minesweeper/emag_act(mob/user) + . = ..() if(CHECK_BITFIELD(obj_flags, EMAGGED)) return desc = "An arcade machine that generates grids. It's clunking and sparking everywhere, almost as if threatening to explode at any moment!" @@ -298,6 +299,7 @@ to_chat(user, "The machine buzzes and sparks... the game has been reset!") playsound(user, 'sound/machines/buzz-sigh.ogg', 100, 0, extrarange = 3, falloff = 10) //Loud buzz game_status = MINESWEEPER_GAME_MAIN_MENU + return TRUE /obj/machinery/computer/arcade/minesweeper/proc/custom_generation(mob/user) playsound(loc, 'sound/arcade/minesweeper_menuselect.ogg', 50, 0, extrarange = -3, falloff = 10) //Entered into the menu so ping sound diff --git a/code/game/machinery/computer/arcade/orion_trail.dm b/code/game/machinery/computer/arcade/orion_trail.dm index 12941dea35..023b1048ce 100644 --- a/code/game/machinery/computer/arcade/orion_trail.dm +++ b/code/game/machinery/computer/arcade/orion_trail.dm @@ -736,6 +736,7 @@ desc = "Learn how our ancestors got to Orion, and have fun in the process!" /obj/machinery/computer/arcade/orion_trail/emag_act(mob/user) + . = ..() if(obj_flags & EMAGGED) return to_chat(user, "You override the cheat code menu and skip to Cheat #[rand(1, 50)]: Realism Mode.") @@ -743,6 +744,7 @@ desc = "Learn how our ancestors got to Orion, and try not to die in the process!" newgame() obj_flags |= EMAGGED + return TRUE /mob/living/simple_animal/hostile/syndicate/ranged/smg/orion name = "spaceport security" diff --git a/code/game/machinery/computer/communications.dm b/code/game/machinery/computer/communications.dm index 752765baa1..eceaefd2b2 100755 --- a/code/game/machinery/computer/communications.dm +++ b/code/game/machinery/computer/communications.dm @@ -432,6 +432,7 @@ return ..() /obj/machinery/computer/communications/emag_act(mob/user) + . = ..() if(obj_flags & EMAGGED) return obj_flags |= EMAGGED @@ -440,6 +441,7 @@ authenticated = 2 to_chat(user, "You scramble the communication routing circuits!") playsound(src, 'sound/machines/terminal_alert.ogg', 50, 0) + return TRUE /obj/machinery/computer/communications/ui_interact(mob/user) . = ..() diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm index 1081cb5fa7..365d19b826 100644 --- a/code/game/machinery/doors/airlock.dm +++ b/code/game/machinery/doors/airlock.dm @@ -1280,20 +1280,23 @@ return !density || (check_access(ID) && !locked && hasPower()) /obj/machinery/door/airlock/emag_act(mob/user) - if(!operating && density && hasPower() && !(obj_flags & EMAGGED)) - operating = TRUE - update_icon(AIRLOCK_EMAG, 1) - sleep(6) - if(QDELETED(src)) - return - operating = FALSE - if(!open()) - update_icon(AIRLOCK_CLOSED, 1) - obj_flags |= EMAGGED - lights = FALSE - locked = TRUE - loseMainPower() - loseBackupPower() + . = ..() + if(operating || !density || !hasPower() || obj_flags & EMAGGED) + return + operating = TRUE + update_icon(AIRLOCK_EMAG, 1) + addtimer(CALLBACK(src, .proc/open_sesame), 6) + return TRUE + +/obj/machinery/door/airlock/proc/open_sesame() + operating = FALSE + if(!open()) + update_icon(AIRLOCK_CLOSED, 1) + obj_flags |= EMAGGED + lights = FALSE + locked = TRUE + loseMainPower() + loseBackupPower() /obj/machinery/door/airlock/attack_alien(mob/living/carbon/alien/humanoid/user) add_fingerprint(user) diff --git a/code/game/machinery/doors/unpowered.dm b/code/game/machinery/doors/unpowered.dm index 2e7e7d5cba..702f700617 100644 --- a/code/game/machinery/doors/unpowered.dm +++ b/code/game/machinery/doors/unpowered.dm @@ -13,9 +13,6 @@ else return ..() -/obj/machinery/door/unpowered/emag_act() - return - /obj/machinery/door/unpowered/shuttle icon = 'icons/turf/shuttle.dmi' name = "door" diff --git a/code/game/machinery/doors/windowdoor.dm b/code/game/machinery/doors/windowdoor.dm index 97ab664b85..933bb4f42a 100644 --- a/code/game/machinery/doors/windowdoor.dm +++ b/code/game/machinery/doors/windowdoor.dm @@ -206,15 +206,20 @@ ..() /obj/machinery/door/window/emag_act(mob/user) - if(!operating && density && !(obj_flags & EMAGGED)) - obj_flags |= EMAGGED - operating = TRUE - flick("[src.base_state]spark", src) - playsound(src, "sparks", 75, 1) - sleep(6) - operating = FALSE - desc += "
Its access panel is smoking slightly." - open(2) + . = ..() + if(operating || !density || obj_flags & EMAGGED) + return + obj_flags |= EMAGGED + operating = TRUE + flick("[src.base_state]spark", src) + playsound(src, "sparks", 75, 1) + addtimer(CALLBACK(src, .proc/open_windows_me), 6) + return TRUE + +/obj/machinery/door/window/proc/open_windows_me() + operating = FALSE + desc += "
Its access panel is smoking slightly." + open(2) /obj/machinery/door/window/attackby(obj/item/I, mob/living/user, params) diff --git a/code/game/machinery/embedded_controller/access_controller.dm b/code/game/machinery/embedded_controller/access_controller.dm index 70ce3d36ae..3b9322d207 100644 --- a/code/game/machinery/embedded_controller/access_controller.dm +++ b/code/game/machinery/embedded_controller/access_controller.dm @@ -26,6 +26,7 @@ findObjsByTag() /obj/machinery/doorButtons/emag_act(mob/user) + . = ..() if(obj_flags & EMAGGED) return obj_flags |= EMAGGED @@ -33,6 +34,7 @@ req_one_access = list() playsound(src, "sparks", 100, 1) to_chat(user, "You short out the access controller.") + return TRUE /obj/machinery/doorButtons/proc/removeMe() diff --git a/code/game/machinery/firealarm.dm b/code/game/machinery/firealarm.dm index 8f0d56a49e..5c2676c2b9 100644 --- a/code/game/machinery/firealarm.dm +++ b/code/game/machinery/firealarm.dm @@ -97,6 +97,7 @@ alarm() /obj/machinery/firealarm/emag_act(mob/user) + . = ..() if(obj_flags & EMAGGED) return obj_flags |= EMAGGED @@ -104,6 +105,7 @@ user.visible_message("Sparks fly out of [src]!", "You emag [src], disabling its thermal sensors.") playsound(src, "sparks", 50, 1) + return TRUE /obj/machinery/firealarm/temperature_expose(datum/gas_mixture/air, temperature, volume) if((temperature > T0C + 200 || temperature < BODYTEMP_COLD_DAMAGE_LIMIT) && (last_alarm+FIREALARM_COOLDOWN < world.time) && !(obj_flags & EMAGGED) && detecting && !stat) diff --git a/code/game/machinery/gulag_item_reclaimer.dm b/code/game/machinery/gulag_item_reclaimer.dm index f6cb58bbbc..320430be39 100644 --- a/code/game/machinery/gulag_item_reclaimer.dm +++ b/code/game/machinery/gulag_item_reclaimer.dm @@ -24,10 +24,12 @@ return ..() /obj/machinery/gulag_item_reclaimer/emag_act(mob/user) + . = ..() if(obj_flags & EMAGGED) // emagging lets anyone reclaim all the items return req_access = list() obj_flags |= EMAGGED + return TRUE /obj/machinery/gulag_item_reclaimer/attackby(obj/item/I, mob/user) if(istype(I, /obj/item/card/id)) diff --git a/code/game/machinery/harvester.dm b/code/game/machinery/harvester.dm index 8be7becfdd..1fccadda21 100644 --- a/code/game/machinery/harvester.dm +++ b/code/game/machinery/harvester.dm @@ -158,11 +158,13 @@ open_machine() /obj/machinery/harvester/emag_act(mob/user) + . = ..() if(obj_flags & EMAGGED) return obj_flags |= EMAGGED allow_living = TRUE to_chat(user, "You overload [src]'s lifesign scanners.") + return TRUE /obj/machinery/harvester/container_resist(mob/living/user) if(!harvesting) diff --git a/code/game/machinery/limbgrower.dm b/code/game/machinery/limbgrower.dm index a3250fe1b0..59806e97a4 100644 --- a/code/game/machinery/limbgrower.dm +++ b/code/game/machinery/limbgrower.dm @@ -215,6 +215,7 @@ return dat /obj/machinery/limbgrower/emag_act(mob/user) + . = ..() if(obj_flags & EMAGGED) return for(var/id in SSresearch.techweb_designs) @@ -223,3 +224,4 @@ stored_research.add_design(D) to_chat(user, "A warning flashes onto the screen, stating that safety overrides have been deactivated!") obj_flags |= EMAGGED + return TRUE diff --git a/code/game/machinery/porta_turret/portable_turret.dm b/code/game/machinery/porta_turret/portable_turret.dm index b0204ddeb8..b0a75c99dc 100644 --- a/code/game/machinery/porta_turret/portable_turret.dm +++ b/code/game/machinery/porta_turret/portable_turret.dm @@ -290,6 +290,7 @@ return ..() /obj/machinery/porta_turret/emag_act(mob/user) + . = ..() if(obj_flags & EMAGGED) return to_chat(user, "You short out [src]'s threat assessment circuits.") @@ -300,6 +301,7 @@ update_icon() sleep(60) //6 seconds for the traitor to gtfo of the area before the turret decides to ruin his shit on = TRUE //turns it back on. The cover popUp() popDown() are automatically called in process(), no need to define it here + return TRUE /obj/machinery/porta_turret/emp_act(severity) @@ -837,6 +839,7 @@ to_chat(user, "Access denied.") /obj/machinery/turretid/emag_act(mob/user) + . = ..() if(obj_flags & EMAGGED) return to_chat(user, "You short out the turret controls' access analysis module.") @@ -844,6 +847,7 @@ locked = FALSE if(user && user.machine == src) attack_hand(user) + return TRUE /obj/machinery/turretid/attack_ai(mob/user) if(!ailock || IsAdminGhost(user)) diff --git a/code/game/machinery/porta_turret/portable_turret_cover.dm b/code/game/machinery/porta_turret/portable_turret_cover.dm index 6ff795c1cc..afb00d4ee2 100644 --- a/code/game/machinery/porta_turret/portable_turret_cover.dm +++ b/code/game/machinery/porta_turret/portable_turret_cover.dm @@ -86,10 +86,13 @@ . = 0 /obj/machinery/porta_turret_cover/emag_act(mob/user) - if(!(parent_turret.obj_flags & EMAGGED)) - to_chat(user, "You short out [parent_turret]'s threat assessment circuits.") - visible_message("[parent_turret] hums oddly...") - parent_turret.obj_flags |= EMAGGED - parent_turret.on = 0 - spawn(40) - parent_turret.on = 1 + . = ..() + if(parent_turret.obj_flags & EMAGGED) + return + to_chat(user, "You short out [parent_turret]'s threat assessment circuits.") + visible_message("[parent_turret] hums oddly...") + parent_turret.obj_flags |= EMAGGED + parent_turret.on = 0 + spawn(40) + parent_turret.on = 1 + return TRUE diff --git a/code/game/machinery/recycler.dm b/code/game/machinery/recycler.dm index ff40a8539a..9d431487e0 100644 --- a/code/game/machinery/recycler.dm +++ b/code/game/machinery/recycler.dm @@ -65,6 +65,7 @@ return ..() /obj/machinery/recycler/emag_act(mob/user) + . = ..() if(obj_flags & EMAGGED) return obj_flags |= EMAGGED @@ -73,6 +74,7 @@ update_icon() playsound(src, "sparks", 75, 1, -1) to_chat(user, "You use the cryptographic sequencer on [src].") + return TRUE /obj/machinery/recycler/update_icon() ..() diff --git a/code/game/machinery/shieldgen.dm b/code/game/machinery/shieldgen.dm index e2aebd2370..fc6577a4f1 100644 --- a/code/game/machinery/shieldgen.dm +++ b/code/game/machinery/shieldgen.dm @@ -195,6 +195,7 @@ return ..() /obj/machinery/shieldgen/emag_act(mob/user) + . = ..() if(obj_flags & EMAGGED) to_chat(user, "The access controller is damaged!") return @@ -202,6 +203,7 @@ locked = FALSE playsound(src, "sparks", 100, 1) to_chat(user, "You short out the access controller.") + return TRUE /obj/machinery/shieldgen/update_icon() if(active) @@ -387,6 +389,7 @@ add_fingerprint(user) /obj/machinery/shieldwallgen/emag_act(mob/user) + . = ..() if(obj_flags & EMAGGED) to_chat(user, "The access controller is damaged!") return @@ -394,6 +397,7 @@ locked = FALSE playsound(src, "sparks", 100, 1) to_chat(user, "You short out the access controller.") + return TRUE //////////////Containment Field START /obj/machinery/shieldwall diff --git a/code/game/machinery/slotmachine.dm b/code/game/machinery/slotmachine.dm index 298587cdea..4b73032a8a 100644 --- a/code/game/machinery/slotmachine.dm +++ b/code/game/machinery/slotmachine.dm @@ -99,6 +99,7 @@ return ..() /obj/machinery/computer/slot_machine/emag_act() + . = ..() if(obj_flags & EMAGGED) return obj_flags |= EMAGGED @@ -106,6 +107,7 @@ spark_system.set_up(4, 0, src.loc) spark_system.start() playsound(src, "sparks", 50, 1) + return TRUE /obj/machinery/computer/slot_machine/ui_interact(mob/living/user) . = ..() diff --git a/code/game/machinery/telecomms/computers/message.dm b/code/game/machinery/telecomms/computers/message.dm index b11c6c102d..ebb40148d8 100644 --- a/code/game/machinery/telecomms/computers/message.dm +++ b/code/game/machinery/telecomms/computers/message.dm @@ -42,21 +42,23 @@ return ..() /obj/machinery/computer/message_monitor/emag_act(mob/user) + . = ..() if(obj_flags & EMAGGED) return - if(!isnull(linkedServer)) - obj_flags |= EMAGGED - screen = 2 - spark_system.set_up(5, 0, src) - spark_system.start() - var/obj/item/paper/monitorkey/MK = new(loc, linkedServer) - // Will help make emagging the console not so easy to get away with. - MK.info += "

�%@%(*$%&(�&?*(%&�/{}" - var/time = 100 * length(linkedServer.decryptkey) - addtimer(CALLBACK(src, .proc/UnmagConsole), time) - message = rebootmsg - else + if(isnull(linkedServer)) to_chat(user, "A no server error appears on the screen.") + return + obj_flags |= EMAGGED + screen = 2 + spark_system.set_up(5, 0, src) + spark_system.start() + var/obj/item/paper/monitorkey/MK = new(loc, linkedServer) + // Will help make emagging the console not so easy to get away with. + MK.info += "

�%@%(*$%&(�&?*(%&�/{}" + var/time = 100 * length(linkedServer.decryptkey) + addtimer(CALLBACK(src, .proc/UnmagConsole), time) + message = rebootmsg + return TRUE /obj/machinery/computer/message_monitor/New() . = ..() diff --git a/code/game/mecha/mech_fabricator.dm b/code/game/mecha/mech_fabricator.dm index 01e304872f..e1dc80911f 100644 --- a/code/game/mecha/mech_fabricator.dm +++ b/code/game/mecha/mech_fabricator.dm @@ -64,10 +64,15 @@ /obj/machinery/mecha_part_fabricator/emag_act() + . = ..() if(obj_flags & EMAGGED) return obj_flags |= EMAGGED req_access = list() + INVOKE_ASYNC(src, .proc/error_action_sucessful) + return TRUE + +/obj/machinery/mecha_part_fabricator/proc/error_action_sucessful() say("DB error \[Code 0x00F1\]") sleep(10) say("Attempting auto-repair...") diff --git a/code/game/objects/items/RSF.dm b/code/game/objects/items/RSF.dm index f0d15cc3a2..01205ee889 100644 --- a/code/game/objects/items/RSF.dm +++ b/code/game/objects/items/RSF.dm @@ -134,12 +134,14 @@ RSF return /obj/item/cookiesynth/emag_act(mob/user) + . = ..() obj_flags ^= EMAGGED if(obj_flags & EMAGGED) to_chat(user, "You short out [src]'s reagent safety checker!") else to_chat(user, "You reset [src]'s reagent safety checker!") - toxin = 0 + toxin = FALSE + return TRUE /obj/item/cookiesynth/attack_self(mob/user) var/mob/living/silicon/robot/P = null diff --git a/code/game/objects/items/cards_ids.dm b/code/game/objects/items/cards_ids.dm index 96bbe759ca..05ffcbf2fd 100644 --- a/code/game/objects/items/cards_ids.dm +++ b/code/game/objects/items/cards_ids.dm @@ -93,34 +93,22 @@ /obj/item/card/emag/afterattack(atom/target, mob/user, proximity) . = ..() var/atom/A = target - if(!proximity && prox_check) + if(!proximity && prox_check || !(isobj(A) || issilicon(A) || isbot(A) || isdrone(A))) + return + if(istype(A, /obj/item/storage) && !(istype(A, /obj/item/storage/lockbox) || istype(A, /obj/item/storage/pod))) return - //Citadel changes: modular code misfiring, so we're bypassing into main code. if(!uses) user.visible_message("[src] emits a weak spark. It's burnt out!") playsound(src, 'sound/effects/light_flicker.ogg', 100, 1) return else if(uses <= 3) playsound(src, 'sound/effects/light_flicker.ogg', 30, 1) //Tiiiiiiny warning sound to let ya know your emag's almost dead - - if(isturf(A)) + if(!A.emag_act(user)) return - if(istype(A,/obj/item/storage/lockbox) || istype(A, /obj/item/storage/pod)) - A.emag_act(user) - uses = max(uses - 1, 0) - if(!uses) - user.visible_message("[src] fizzles and sparks. It seems like it's out of charges.") - playsound(src, 'sound/effects/light_flicker.ogg', 100, 1) - if(istype(A,/obj/item/storage)) - return - if(!(isobj(A) || issilicon(A) || isbot(A) || isdrone(A))) - return - else - A.emag_act(user) - uses = max(uses - 1, 0) - if(!uses) - user.visible_message("[src] fizzles and sparks. It seems like it's out of charges.") - playsound(src, 'sound/effects/light_flicker.ogg', 100, 1) + uses = max(uses - 1, 0) + if(!uses) + user.visible_message("[src] fizzles and sparks. It seems like it's out of charges.") + playsound(src, 'sound/effects/light_flicker.ogg', 100, 1) /obj/item/card/emagfake diff --git a/code/game/objects/items/cigs_lighters.dm b/code/game/objects/items/cigs_lighters.dm index 000c52ae43..09a128c558 100644 --- a/code/game/objects/items/cigs_lighters.dm +++ b/code/game/objects/items/cigs_lighters.dm @@ -764,20 +764,22 @@ CIGARETTE PACKETS ARE IN FANCY.DM ..() /obj/item/clothing/mask/vape/emag_act(mob/user)// I WON'T REGRET WRITTING THIS, SURLY. - if(screw) - if(!(obj_flags & EMAGGED)) - cut_overlays() - obj_flags |= EMAGGED - super = FALSE - to_chat(user, "You maximize the voltage of [src].") - add_overlay("vapeopen_high") - var/datum/effect_system/spark_spread/sp = new /datum/effect_system/spark_spread //for effect - sp.set_up(5, 1, src) - sp.start() - else - to_chat(user, "[src] is already emagged!") - else + . = ..() + if(!screw) to_chat(user, "You need to open the cap to do that.") + return + if(obj_flags & EMAGGED) + to_chat(user, "[src] is already emagged!") + return + cut_overlays() + obj_flags |= EMAGGED + super = FALSE + to_chat(user, "You maximize the voltage of [src].") + add_overlay("vapeopen_high") + var/datum/effect_system/spark_spread/sp = new /datum/effect_system/spark_spread //for effect + sp.set_up(5, 1, src) + sp.start() + return TRUE /obj/item/clothing/mask/vape/attack_self(mob/user) if(reagents.total_volume > 0) diff --git a/code/game/objects/items/circuitboards/computer_circuitboards.dm b/code/game/objects/items/circuitboards/computer_circuitboards.dm index 7d2ffe0a02..bb45f80f2d 100644 --- a/code/game/objects/items/circuitboards/computer_circuitboards.dm +++ b/code/game/objects/items/circuitboards/computer_circuitboards.dm @@ -217,10 +217,13 @@ to_chat(user, "The spectrum chip is unresponsive.") /obj/item/circuitboard/computer/cargo/emag_act(mob/living/user) - if(!(obj_flags & EMAGGED)) - contraband = TRUE - obj_flags |= EMAGGED - to_chat(user, "You adjust [src]'s routing and receiver spectrum, unlocking special supplies and contraband.") + . = ..() + if(obj_flags & EMAGGED) + return + contraband = TRUE + obj_flags |= EMAGGED + to_chat(user, "You adjust [src]'s routing and receiver spectrum, unlocking special supplies and contraband.") + return TRUE /obj/item/circuitboard/computer/cargo/express name = "Express Supply Console (Computer Board)" @@ -234,8 +237,12 @@ obj_flags &= ~EMAGGED /obj/item/circuitboard/computer/cargo/express/emag_act(mob/living/user) - to_chat(user, "You change the routing protocols, allowing the Drop Pod to land anywhere on the station.") - obj_flags |= EMAGGED + . = SEND_SIGNAL(src, COMSIG_ATOM_EMAG_ACT) + if(obj_flags & EMAGGED) + return + to_chat(user, "You change the routing protocols, allowing the Drop Pod to land anywhere on the station.") + obj_flags |= EMAGGED + return TRUE /obj/item/circuitboard/computer/cargo/request name = "Supply Request Console (Computer Board)" diff --git a/code/game/objects/items/defib.dm b/code/game/objects/items/defib.dm index 55e75b3992..5bef86c6d2 100644 --- a/code/game/objects/items/defib.dm +++ b/code/game/objects/items/defib.dm @@ -140,12 +140,10 @@ return ..() /obj/item/defibrillator/emag_act(mob/user) - if(safety) - safety = FALSE - to_chat(user, "You silently disable [src]'s safety protocols with the cryptographic sequencer.") - else - safety = TRUE - to_chat(user, "You silently enable [src]'s safety protocols with the cryptographic sequencer.") + . = ..() + safety = !safety + to_chat(user, "You silently [safety ? "enable" : "disable"] [src]'s safety protocols with the cryptographic sequencer.") + return TRUE /obj/item/defibrillator/emp_act(severity) . = ..() diff --git a/code/game/objects/items/devices/geiger_counter.dm b/code/game/objects/items/devices/geiger_counter.dm index 7823e570e0..38133e37bc 100644 --- a/code/game/objects/items/devices/geiger_counter.dm +++ b/code/game/objects/items/devices/geiger_counter.dm @@ -192,13 +192,15 @@ update_icon() /obj/item/geiger_counter/emag_act(mob/user) + . = ..() if(obj_flags & EMAGGED) return if(scanning) to_chat(user, "Turn off [src] before you perform this action!") - return 0 + return to_chat(user, "You override [src]'s radiation storing protocols. It will now generate small doses of radiation, and stored rads are now projected into creatures you scan.") obj_flags |= EMAGGED + return TRUE /obj/item/geiger_counter/cyborg var/datum/component/mobhook diff --git a/code/game/objects/items/devices/lightreplacer.dm b/code/game/objects/items/devices/lightreplacer.dm index 6615ebe8a8..1e31f14cfd 100644 --- a/code/game/objects/items/devices/lightreplacer.dm +++ b/code/game/objects/items/devices/lightreplacer.dm @@ -149,9 +149,11 @@ to_chat(user, "You fill \the [src] with lights from \the [S]. " + status_string() + "") /obj/item/lightreplacer/emag_act() + . = ..() if(obj_flags & EMAGGED) return Emag() + return TRUE /obj/item/lightreplacer/attack_self(mob/user) to_chat(user, status_string()) diff --git a/code/game/objects/items/devices/megaphone.dm b/code/game/objects/items/devices/megaphone.dm index 347bb6894d..915fcac504 100644 --- a/code/game/objects/items/devices/megaphone.dm +++ b/code/game/objects/items/devices/megaphone.dm @@ -38,11 +38,13 @@ speech_args[SPEECH_SPANS] |= voicespan /obj/item/megaphone/emag_act(mob/user) + . = ..() if(obj_flags & EMAGGED) return to_chat(user, "You overload \the [src]'s voice synthesizer.") obj_flags |= EMAGGED voicespan = list(SPAN_REALLYBIG, "userdanger") + return TRUE /obj/item/megaphone/sec name = "security megaphone" diff --git a/code/game/objects/items/robot/robot_items.dm b/code/game/objects/items/robot/robot_items.dm index 6d7c3036f9..5454b0fdb8 100644 --- a/code/game/objects/items/robot/robot_items.dm +++ b/code/game/objects/items/robot/robot_items.dm @@ -282,11 +282,13 @@ var/cooldown = 0 /obj/item/harmalarm/emag_act(mob/user) + . = ..() obj_flags ^= EMAGGED if(obj_flags & EMAGGED) to_chat(user, "You short out the safeties on [src]!") else to_chat(user, "You reset the safeties on [src]!") + return TRUE /obj/item/harmalarm/attack_self(mob/user) var/safety = !(obj_flags & EMAGGED) diff --git a/code/game/objects/items/storage/lockbox.dm b/code/game/objects/items/storage/lockbox.dm index 4924051855..eeebc6f4c5 100644 --- a/code/game/objects/items/storage/lockbox.dm +++ b/code/game/objects/items/storage/lockbox.dm @@ -48,14 +48,16 @@ to_chat(user, "It's locked!") /obj/item/storage/lockbox/emag_act(mob/user) - if(!broken) - broken = TRUE - SEND_SIGNAL(src, COMSIG_TRY_STORAGE_SET_LOCKSTATE, FALSE) - desc += "It appears to be broken." - icon_state = src.icon_broken - if(user) - visible_message("\The [src] has been broken by [user] with an electromagnetic card!") - return + . = ..() + if(broken) + return + broken = TRUE + SEND_SIGNAL(src, COMSIG_TRY_STORAGE_SET_LOCKSTATE, FALSE) + desc += "It appears to be broken." + icon_state = src.icon_broken + if(user) + visible_message("\The [src] has been broken by [user] with an electromagnetic card!") + return TRUE /obj/item/storage/lockbox/Entered() . = ..() diff --git a/code/game/objects/structures/barsigns.dm b/code/game/objects/structures/barsigns.dm index 1ab28a33de..2093ae5660 100644 --- a/code/game/objects/structures/barsigns.dm +++ b/code/game/objects/structures/barsigns.dm @@ -112,12 +112,16 @@ /obj/structure/sign/barsign/emag_act(mob/user) + . = ..() if(broken || (obj_flags & EMAGGED)) to_chat(user, "Nothing interesting happens!") return obj_flags |= EMAGGED to_chat(user, "You emag the barsign. Takeover in progress...") - sleep(10 SECONDS) + addtimer(CALLBACK(src, .proc/syndie_bar_good), 10 SECONDS) + return TRUE + +/obj/structure/sign/barsign/proc/syndie_bar_good() set_sign(new /datum/barsign/hiddensigns/syndibarsign) req_access = list(ACCESS_SYNDICATE) diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm index f097d2903a..edcb4a6181 100644 --- a/code/game/objects/structures/crates_lockers/closets.dm +++ b/code/game/objects/structures/crates_lockers/closets.dm @@ -1,616 +1,617 @@ -/obj/structure/closet - name = "closet" - desc = "It's a basic storage unit." - icon = 'icons/obj/closet.dmi' - icon_state = "generic" - density = TRUE - layer = BELOW_OBJ_LAYER - var/icon_door = null - var/icon_door_override = FALSE //override to have open overlay use icon different to its base's - var/secure = FALSE //secure locker or not, also used if overriding a non-secure locker with a secure door overlay to add fancy lights - var/opened = FALSE - var/welded = FALSE - var/locked = FALSE - var/large = TRUE - var/wall_mounted = 0 //never solid (You can always pass over it) - max_integrity = 200 - integrity_failure = 50 - armor = list("melee" = 20, "bullet" = 10, "laser" = 10, "energy" = 0, "bomb" = 10, "bio" = 0, "rad" = 0, "fire" = 70, "acid" = 60) - var/breakout_time = 1200 - var/message_cooldown - var/can_weld_shut = TRUE - var/horizontal = FALSE - var/allow_objects = FALSE - var/allow_dense = FALSE - var/dense_when_open = FALSE //if it's dense when open or not - var/max_mob_size = MOB_SIZE_HUMAN //Biggest mob_size accepted by the container - var/mob_storage_capacity = 3 // how many human sized mob/living can fit together inside a closet. - var/storage_capacity = 30 //This is so that someone can't pack hundreds of items in a locker/crate then open it in a populated area to crash clients. - var/cutting_tool = /obj/item/weldingtool - var/open_sound = 'sound/machines/click.ogg' - var/close_sound = 'sound/machines/click.ogg' - var/material_drop = /obj/item/stack/sheet/metal - var/material_drop_amount = 2 - var/delivery_icon = "deliverycloset" //which icon to use when packagewrapped. null to be unwrappable. - var/anchorable = TRUE - var/icon_welded = "welded" - var/obj/item/electronics/airlock/lockerelectronics //Installed electronics - var/lock_in_use = FALSE //Someone is doing some stuff with the lock here, better not proceed further - var/eigen_teleport = FALSE //If the closet leads to Mr Tumnus. - var/obj/structure/closet/eigen_target //Where you go to. - - -/obj/structure/closet/Initialize(mapload) - . = ..() - update_icon() - PopulateContents() - if(mapload && !opened) // if closed, any item at the crate's loc is put in the contents - take_contents() - if(secure) - lockerelectronics = new(src) - lockerelectronics.accesses = req_access - -//USE THIS TO FILL IT, NOT INITIALIZE OR NEW -/obj/structure/closet/proc/PopulateContents() - return - -/obj/structure/closet/Destroy() - dump_contents(override = FALSE) - return ..() - -/obj/structure/closet/update_icon() - cut_overlays() - if(opened & icon_door_override) - add_overlay("[icon_door]_open") - layer = OBJ_LAYER - return - else if(opened) - add_overlay("[icon_state]_open") - return - if(icon_door) - add_overlay("[icon_door]_door") - else - layer = BELOW_OBJ_LAYER - add_overlay("[icon_state]_door") - if(welded) - add_overlay("welded") - if(!secure) - return - if(broken) - add_overlay("off") - add_overlay("sparking") - else if(locked) - add_overlay("locked") - else - add_overlay("unlocked") - -/obj/structure/closet/examine(mob/user) - ..() - if(welded) - to_chat(user, "It's welded shut.") - if(anchored) - to_chat(user, "It is bolted to the ground.") - if(opened) - to_chat(user, "The parts are welded together.") - else if(secure && !opened) - else if(broken) - to_chat(user, "The lock is screwed in.") - else if(secure) - to_chat(user, "Alt-click to [locked ? "unlock" : "lock"].") - if(isliving(user)) - var/mob/living/L = user - if(HAS_TRAIT(L, TRAIT_SKITTISH)) - to_chat(user, "Ctrl-Shift-click [src] to jump inside.") - -/obj/structure/closet/CanPass(atom/movable/mover, turf/target) - if(wall_mounted) - return TRUE - return !density - -/obj/structure/closet/proc/can_open(mob/living/user) - if(welded || locked) - return FALSE - var/turf/T = get_turf(src) - for(var/mob/living/L in T) - if(L.anchored || horizontal && L.mob_size > MOB_SIZE_TINY && L.density) - if(user) - to_chat(user, "There's something large on top of [src], preventing it from opening." ) - return FALSE - return TRUE - -/obj/structure/closet/proc/can_close(mob/living/user) - var/turf/T = get_turf(src) - for(var/obj/structure/closet/closet in T) - if(closet != src && !closet.wall_mounted) - return FALSE - for(var/mob/living/L in T) - if(L.anchored || horizontal && L.mob_size > MOB_SIZE_TINY && L.density) - if(user) - to_chat(user, "There's something too large in [src], preventing it from closing.") - return FALSE - return TRUE - -/obj/structure/closet/proc/can_lock(mob/living/user, var/check_access = TRUE) //set check_access to FALSE if you only need to check if a locker has a functional lock rather than access - if(!secure) - return FALSE - if(broken) - to_chat(user, "[src] is broken!") - return FALSE - if(QDELETED(lockerelectronics) && !locked) //We want to be able to unlock it regardless of electronics, but only lockable with electronics - to_chat(user, "[src] is missing locker electronics!") - return FALSE - if(!check_access) - return TRUE - if(allowed(user)) - return TRUE - to_chat(user, "Access denied.") - -/obj/structure/closet/proc/togglelock(mob/living/user) - add_fingerprint(user) - if(eigen_target) - return - if(opened) - return - if(!can_lock(user)) - return - locked = !locked - user.visible_message("[user] [locked ? null : "un"]locks [src].", - "You [locked ? null : "un"]lock [src].") - update_icon() - -/obj/structure/closet/proc/dump_contents(var/override = TRUE) //Override is for not revealing the locker electronics when you open the locker, for example - var/atom/L = drop_location() - for(var/atom/movable/AM in src) - if(AM == lockerelectronics && override) - continue - AM.forceMove(L) - if(throwing) // you keep some momentum when getting out of a thrown closet - step(AM, dir) - if(throwing) - throwing.finalize(FALSE) - -/obj/structure/closet/proc/take_contents() - var/atom/L = drop_location() - for(var/atom/movable/AM in L) - if(AM != src && insert(AM) == -1) // limit reached - break - -/obj/structure/closet/proc/open(mob/living/user) - if(opened || !can_open(user)) - return - playsound(loc, open_sound, 15, 1, -3) - opened = TRUE - if(!dense_when_open) - density = FALSE - climb_time *= 0.5 //it's faster to climb onto an open thing - dump_contents() - update_icon() - return 1 - -/obj/structure/closet/proc/insert(atom/movable/AM) - if(contents.len >= storage_capacity) - return -1 - if(insertion_allowed(AM)) - if(eigen_teleport) // For teleporting people with linked lockers. - do_teleport(AM, get_turf(eigen_target), 0) - if(eigen_target.opened == FALSE) - eigen_target.bust_open() - else - AM.forceMove(src) - return TRUE - else - return FALSE - - -/obj/structure/closet/proc/insertion_allowed(atom/movable/AM) - if(ismob(AM)) - if(!isliving(AM)) //let's not put ghosts or camera mobs inside closets... - return FALSE - var/mob/living/L = AM - if(L.anchored || L.buckled || L.incorporeal_move || L.has_buckled_mobs()) - return FALSE - if(L.mob_size > MOB_SIZE_TINY) // Tiny mobs are treated as items. - if(horizontal && L.density) - return FALSE - if(L.mob_size > max_mob_size) - return FALSE - var/mobs_stored = 0 - for(var/mob/living/M in contents) - if(++mobs_stored >= mob_storage_capacity) - return FALSE - L.stop_pulling() - - else if(istype(AM, /obj/structure/closet)) - return FALSE - - else if(istype(AM, /obj/effect)) - return FALSE - - else if(isobj(AM)) - if((!allow_dense && AM.density) || AM.anchored || AM.has_buckled_mobs()) - return FALSE - if(isitem(AM) && !HAS_TRAIT(AM, TRAIT_NODROP)) - return TRUE - else if(!allow_objects && !istype(AM, /obj/effect/dummy/chameleon)) - return FALSE - else - return FALSE - - return TRUE - -/obj/structure/closet/proc/close(mob/living/user) - if(!opened || !can_close(user)) - return FALSE - take_contents() - playsound(loc, close_sound, 15, 1, -3) - climb_time = initial(climb_time) - opened = FALSE - density = TRUE - update_icon() - return TRUE - -/obj/structure/closet/proc/toggle(mob/living/user) - if(opened) - return close(user) - else - return open(user) - -/obj/structure/closet/proc/bust_open() - welded = FALSE //applies to all lockers - locked = FALSE //applies to critter crates and secure lockers only - broken = TRUE //applies to secure lockers only - open() - -/obj/structure/closet/proc/handle_lock_addition(mob/user, obj/item/electronics/airlock/E) - add_fingerprint(user) - if(lock_in_use) - to_chat(user, "Wait for work on [src] to be done first!") - return - if(secure) - to_chat(user, "This locker already has a lock!") - return - if(broken) - to_chat(user, "Unscrew the broken lock first!") - return - if(!istype(E)) - return - user.visible_message("[user] begins installing a lock on [src]...","You begin installing a lock on [src]...") - lock_in_use = TRUE - playsound(loc, 'sound/items/screwdriver.ogg', 50, 1) - if(!do_after(user, 60, target = src)) - lock_in_use = FALSE - return - lock_in_use = FALSE - to_chat(user, "You finish the lock on [src]!") - E.forceMove(src) - lockerelectronics = E - req_access = E.accesses - secure = TRUE - update_icon() - return TRUE - -/obj/structure/closet/proc/handle_lock_removal(mob/user, obj/item/screwdriver/S) - if(lock_in_use) - to_chat(user, "Wait for work on [src] to be done first!") - return - if(locked) - to_chat(user, "Unlock it first!") - return - if(!secure) - to_chat(user, "[src] doesn't have a lock that you can remove!") - return - if(!istype(S)) - return - var/brokenword = broken ? "broken " : null - user.visible_message("[user] begins removing the [brokenword]lock on [src]...","You begin removing the [brokenword]lock on [src]...") - playsound(loc, S.usesound, 50, 1) - lock_in_use = TRUE - if(!do_after(user, 100 * S.toolspeed, target = src)) - lock_in_use = FALSE - return - to_chat(user, "You remove the [brokenword]lock from [src]!") - if(!QDELETED(lockerelectronics)) - lockerelectronics.add_fingerprint(user) - lockerelectronics.forceMove(user.loc) - lockerelectronics = null - req_access = null - secure = FALSE - broken = FALSE - locked = FALSE - lock_in_use = FALSE - update_icon() - return TRUE - - -/obj/structure/closet/deconstruct(disassembled = TRUE) - if(ispath(material_drop) && material_drop_amount && !(flags_1 & NODECONSTRUCT_1)) - new material_drop(loc, material_drop_amount) - qdel(src) - -/obj/structure/closet/obj_break(damage_flag) - if(!broken && !(flags_1 & NODECONSTRUCT_1)) - bust_open() - -/obj/structure/closet/attackby(obj/item/W, mob/user, params) - if(user in src) - return - if(src.tool_interact(W,user)) - return 1 // No afterattack - else - return ..() - -/obj/structure/closet/proc/tool_interact(obj/item/W, mob/user)//returns TRUE if attackBy call shouldnt be continued (because tool was used/closet was of wrong type), FALSE if otherwise - . = TRUE - if(opened) - if(istype(W, cutting_tool)) - if(istype(W, /obj/item/weldingtool)) - if(!W.tool_start_check(user, amount=0)) - return - - to_chat(user, "You begin cutting \the [src] apart...") - if(W.use_tool(src, user, 40, volume=50)) - if(eigen_teleport) - to_chat(user, "The unstable nature of \the [src] makes it impossible to cut!") - return - if(!opened) - return - user.visible_message("[user] slices apart \the [src].", - "You cut \the [src] apart with \the [W].", - "You hear welding.") - deconstruct(TRUE) - return - else // for example cardboard box is cut with wirecutters - user.visible_message("[user] cut apart \the [src].", \ - "You cut \the [src] apart with \the [W].") - deconstruct(TRUE) - return - if(user.transferItemToLoc(W, drop_location())) // so we put in unlit welder too - return TRUE - else if(istype(W, /obj/item/electronics/airlock)) - handle_lock_addition(user, W) - else if(istype(W, /obj/item/screwdriver)) - handle_lock_removal(user, W) - else if(istype(W, /obj/item/weldingtool) && can_weld_shut) - if(!W.tool_start_check(user, amount=0)) - return - - to_chat(user, "You begin [welded ? "unwelding":"welding"] \the [src]...") - if(W.use_tool(src, user, 40, volume=50)) - if(eigen_teleport) - to_chat(user, "The unstable nature of \the [src] makes it impossible to weld!") - return - if(opened) - return - welded = !welded - after_weld(welded) - user.visible_message("[user] [welded ? "welds shut" : "unwelds"] \the [src].", - "You [welded ? "weld" : "unwelded"] \the [src] with \the [W].", - "You hear welding.") - update_icon() - else if(istype(W, /obj/item/wrench) && anchorable) - if(isinspace() && !anchored) - return - setAnchored(!anchored) - W.play_tool_sound(src, 75) - user.visible_message("[user] [anchored ? "anchored" : "unanchored"] \the [src] [anchored ? "to" : "from"] the ground.", \ - "You [anchored ? "anchored" : "unanchored"] \the [src] [anchored ? "to" : "from"] the ground.", \ - "You hear a ratchet.") - else if(user.a_intent != INTENT_HARM && !(W.item_flags & NOBLUDGEON)) - if(W.GetID() || !toggle(user)) - togglelock(user) - else - return FALSE - -/obj/structure/closet/proc/after_weld(weld_state) - return - -/obj/structure/closet/MouseDrop_T(atom/movable/O, mob/living/user) - if(!istype(O) || O.anchored || istype(O, /obj/screen)) - return - if(!istype(user) || user.incapacitated() || user.lying) - return - if(!Adjacent(user) || !user.Adjacent(O)) - return - if(user == O) //try to climb onto it - return ..() - if(!opened) - return - if(!isturf(O.loc)) - return - - var/actuallyismob = 0 - if(isliving(O)) - actuallyismob = 1 - else if(!isitem(O)) - return - var/turf/T = get_turf(src) - var/list/targets = list(O, src) - add_fingerprint(user) - user.visible_message("[user] [actuallyismob ? "tries to ":""]stuff [O] into [src].", \ - "You [actuallyismob ? "try to ":""]stuff [O] into [src].", \ - "You hear clanging.") - if(actuallyismob) - if(do_after_mob(user, targets, 40)) - user.visible_message("[user] stuffs [O] into [src].", \ - "You stuff [O] into [src].", \ - "You hear a loud metal bang.") - var/mob/living/L = O - if(!issilicon(L)) - L.Knockdown(40) - O.forceMove(T) - close() - else - O.forceMove(T) - return 1 - -/obj/structure/closet/relaymove(mob/user) - if(user.stat || !isturf(loc) || !isliving(user)) - return - if(locked) - if(message_cooldown <= world.time) - message_cooldown = world.time + 50 - to_chat(user, "[src]'s door won't budge!") - return - container_resist(user) - -/obj/structure/closet/attack_hand(mob/user) - . = ..() - if(.) - return - if(user.lying && get_dist(src, user) > 0) - return - - if(!toggle(user)) - togglelock(user) - -/obj/structure/closet/attack_paw(mob/user) - return attack_hand(user) - -/obj/structure/closet/attack_robot(mob/user) - if(user.Adjacent(src)) - return attack_hand(user) - -// tk grab then use on self -/obj/structure/closet/attack_self_tk(mob/user) - return attack_hand(user) - -/obj/structure/closet/verb/verb_toggleopen() - set src in oview(1) - set category = "Object" - set name = "Toggle Open" - - if(!usr.canmove || usr.stat || usr.restrained()) - return - - if(iscarbon(usr) || issilicon(usr) || isdrone(usr)) - return attack_hand(usr) - else - to_chat(usr, "This mob type can't use this verb.") - -// Objects that try to exit a locker by stepping were doing so successfully, -// and due to an oversight in turf/Enter() were going through walls. That -// should be independently resolved, but this is also an interesting twist. -/obj/structure/closet/Exit(atom/movable/AM) - open() - if(AM.loc == src) - return 0 - return 1 - -/obj/structure/closet/container_resist(mob/living/user) - if(opened) - return - if(ismovableatom(loc)) - user.changeNext_move(CLICK_CD_BREAKOUT) - user.last_special = world.time + CLICK_CD_BREAKOUT - var/atom/movable/AM = loc - AM.relay_container_resist(user, src) - return - if(!welded && !locked) - open() - return - - //okay, so the closet is either welded or locked... resist!!! - user.changeNext_move(CLICK_CD_BREAKOUT) - user.last_special = world.time + CLICK_CD_BREAKOUT - user.visible_message("[src] begins to shake violently!", \ - "You lean on the back of [src] and start pushing the door open... (this will take about [DisplayTimeText(breakout_time)].)", \ - "You hear banging from [src].") - if(do_after(user,(breakout_time), target = src)) - if(!user || user.stat != CONSCIOUS || user.loc != src || opened || (!locked && !welded) ) - return - //we check after a while whether there is a point of resisting anymore and whether the user is capable of resisting - user.visible_message("[user] successfully broke out of [src]!", - "You successfully break out of [src]!") - bust_open() - else - if(user.loc == src) //so we don't get the message if we resisted multiple times and succeeded. - to_chat(user, "You fail to break out of [src]!") - -/obj/structure/closet/AltClick(mob/user) - ..() - if(!user.canUseTopic(src, be_close=TRUE) || !isturf(loc)) - to_chat(user, "You can't do that right now!") - return - togglelock(user) - -/obj/structure/closet/CtrlShiftClick(mob/living/user) - if(!HAS_TRAIT(user, TRAIT_SKITTISH)) - return ..() - if(!user.canUseTopic(src) || !isturf(user.loc)) - return - dive_into(user) - -/obj/structure/closet/emag_act(mob/user) - if(secure && !broken) - user.visible_message("Sparks fly from [src]!", - "You scramble [src]'s lock, breaking it open!", - "You hear a faint electrical spark.") - playsound(src, "sparks", 50, 1) - broken = TRUE - locked = FALSE - if(!QDELETED(lockerelectronics)) - qdel(lockerelectronics) - lockerelectronics = null - update_icon() - -/obj/structure/closet/get_remote_view_fullscreens(mob/user) - if(user.stat == DEAD || !(user.sight & (SEEOBJS|SEEMOBS))) - user.overlay_fullscreen("remote_view", /obj/screen/fullscreen/impaired, 1) - -/obj/structure/closet/emp_act(severity) - . = ..() - if(. & EMP_PROTECT_SELF) - return - if (!(. & EMP_PROTECT_CONTENTS)) - for(var/obj/O in src) - O.emp_act(severity) - if(!secure || broken) - return ..() - if(prob(50 / severity)) - locked = !locked - update_icon() - if(prob(20 / severity) && !opened) - if(!locked) - open() - else - req_access = list() - req_access += pick(get_all_accesses()) - if(!QDELETED(lockerelectronics)) - lockerelectronics.accesses = req_access - -/obj/structure/closet/contents_explosion(severity, target) - for(var/atom/A in contents) - A.ex_act(severity, target) - CHECK_TICK - -/obj/structure/closet/singularity_act() - dump_contents() - ..() - -/obj/structure/closet/AllowDrop() - return TRUE - - -/obj/structure/closet/return_temperature() - return - -/obj/structure/closet/proc/dive_into(mob/living/user) - var/turf/T1 = get_turf(user) - var/turf/T2 = get_turf(src) - if(!opened) - if(locked) - togglelock(user, TRUE) - if(!open(user)) - to_chat(user, "It won't budge!") - return - step_towards(user, T2) - T1 = get_turf(user) - if(T1 == T2) - user.resting = TRUE //so people can jump into crates without slamming the lid on their head - if(!close(user)) - to_chat(user, "You can't get [src] to close!") - user.resting = FALSE - return - user.resting = FALSE - togglelock(user) - T1.visible_message("[user] dives into [src]!") +/obj/structure/closet + name = "closet" + desc = "It's a basic storage unit." + icon = 'icons/obj/closet.dmi' + icon_state = "generic" + density = TRUE + layer = BELOW_OBJ_LAYER + var/icon_door = null + var/icon_door_override = FALSE //override to have open overlay use icon different to its base's + var/secure = FALSE //secure locker or not, also used if overriding a non-secure locker with a secure door overlay to add fancy lights + var/opened = FALSE + var/welded = FALSE + var/locked = FALSE + var/large = TRUE + var/wall_mounted = 0 //never solid (You can always pass over it) + max_integrity = 200 + integrity_failure = 50 + armor = list("melee" = 20, "bullet" = 10, "laser" = 10, "energy" = 0, "bomb" = 10, "bio" = 0, "rad" = 0, "fire" = 70, "acid" = 60) + var/breakout_time = 1200 + var/message_cooldown + var/can_weld_shut = TRUE + var/horizontal = FALSE + var/allow_objects = FALSE + var/allow_dense = FALSE + var/dense_when_open = FALSE //if it's dense when open or not + var/max_mob_size = MOB_SIZE_HUMAN //Biggest mob_size accepted by the container + var/mob_storage_capacity = 3 // how many human sized mob/living can fit together inside a closet. + var/storage_capacity = 30 //This is so that someone can't pack hundreds of items in a locker/crate then open it in a populated area to crash clients. + var/cutting_tool = /obj/item/weldingtool + var/open_sound = 'sound/machines/click.ogg' + var/close_sound = 'sound/machines/click.ogg' + var/material_drop = /obj/item/stack/sheet/metal + var/material_drop_amount = 2 + var/delivery_icon = "deliverycloset" //which icon to use when packagewrapped. null to be unwrappable. + var/anchorable = TRUE + var/icon_welded = "welded" + var/obj/item/electronics/airlock/lockerelectronics //Installed electronics + var/lock_in_use = FALSE //Someone is doing some stuff with the lock here, better not proceed further + var/eigen_teleport = FALSE //If the closet leads to Mr Tumnus. + var/obj/structure/closet/eigen_target //Where you go to. + + +/obj/structure/closet/Initialize(mapload) + . = ..() + update_icon() + PopulateContents() + if(mapload && !opened) // if closed, any item at the crate's loc is put in the contents + take_contents() + if(secure) + lockerelectronics = new(src) + lockerelectronics.accesses = req_access + +//USE THIS TO FILL IT, NOT INITIALIZE OR NEW +/obj/structure/closet/proc/PopulateContents() + return + +/obj/structure/closet/Destroy() + dump_contents(override = FALSE) + return ..() + +/obj/structure/closet/update_icon() + cut_overlays() + if(opened & icon_door_override) + add_overlay("[icon_door]_open") + layer = OBJ_LAYER + return + else if(opened) + add_overlay("[icon_state]_open") + return + if(icon_door) + add_overlay("[icon_door]_door") + else + layer = BELOW_OBJ_LAYER + add_overlay("[icon_state]_door") + if(welded) + add_overlay("welded") + if(!secure) + return + if(broken) + add_overlay("off") + add_overlay("sparking") + else if(locked) + add_overlay("locked") + else + add_overlay("unlocked") + +/obj/structure/closet/examine(mob/user) + ..() + if(welded) + to_chat(user, "It's welded shut.") + if(anchored) + to_chat(user, "It is bolted to the ground.") + if(opened) + to_chat(user, "The parts are welded together.") + else if(secure && !opened) + else if(broken) + to_chat(user, "The lock is screwed in.") + else if(secure) + to_chat(user, "Alt-click to [locked ? "unlock" : "lock"].") + if(isliving(user)) + var/mob/living/L = user + if(HAS_TRAIT(L, TRAIT_SKITTISH)) + to_chat(user, "Ctrl-Shift-click [src] to jump inside.") + +/obj/structure/closet/CanPass(atom/movable/mover, turf/target) + if(wall_mounted) + return TRUE + return !density + +/obj/structure/closet/proc/can_open(mob/living/user) + if(welded || locked) + return FALSE + var/turf/T = get_turf(src) + for(var/mob/living/L in T) + if(L.anchored || horizontal && L.mob_size > MOB_SIZE_TINY && L.density) + if(user) + to_chat(user, "There's something large on top of [src], preventing it from opening." ) + return FALSE + return TRUE + +/obj/structure/closet/proc/can_close(mob/living/user) + var/turf/T = get_turf(src) + for(var/obj/structure/closet/closet in T) + if(closet != src && !closet.wall_mounted) + return FALSE + for(var/mob/living/L in T) + if(L.anchored || horizontal && L.mob_size > MOB_SIZE_TINY && L.density) + if(user) + to_chat(user, "There's something too large in [src], preventing it from closing.") + return FALSE + return TRUE + +/obj/structure/closet/proc/can_lock(mob/living/user, var/check_access = TRUE) //set check_access to FALSE if you only need to check if a locker has a functional lock rather than access + if(!secure) + return FALSE + if(broken) + to_chat(user, "[src] is broken!") + return FALSE + if(QDELETED(lockerelectronics) && !locked) //We want to be able to unlock it regardless of electronics, but only lockable with electronics + to_chat(user, "[src] is missing locker electronics!") + return FALSE + if(!check_access) + return TRUE + if(allowed(user)) + return TRUE + to_chat(user, "Access denied.") + +/obj/structure/closet/proc/togglelock(mob/living/user) + add_fingerprint(user) + if(eigen_target) + return + if(opened) + return + if(!can_lock(user)) + return + locked = !locked + user.visible_message("[user] [locked ? null : "un"]locks [src].", + "You [locked ? null : "un"]lock [src].") + update_icon() + +/obj/structure/closet/proc/dump_contents(var/override = TRUE) //Override is for not revealing the locker electronics when you open the locker, for example + var/atom/L = drop_location() + for(var/atom/movable/AM in src) + if(AM == lockerelectronics && override) + continue + AM.forceMove(L) + if(throwing) // you keep some momentum when getting out of a thrown closet + step(AM, dir) + if(throwing) + throwing.finalize(FALSE) + +/obj/structure/closet/proc/take_contents() + var/atom/L = drop_location() + for(var/atom/movable/AM in L) + if(AM != src && insert(AM) == -1) // limit reached + break + +/obj/structure/closet/proc/open(mob/living/user) + if(opened || !can_open(user)) + return + playsound(loc, open_sound, 15, 1, -3) + opened = TRUE + if(!dense_when_open) + density = FALSE + climb_time *= 0.5 //it's faster to climb onto an open thing + dump_contents() + update_icon() + return 1 + +/obj/structure/closet/proc/insert(atom/movable/AM) + if(contents.len >= storage_capacity) + return -1 + if(insertion_allowed(AM)) + if(eigen_teleport) // For teleporting people with linked lockers. + do_teleport(AM, get_turf(eigen_target), 0) + if(eigen_target.opened == FALSE) + eigen_target.bust_open() + else + AM.forceMove(src) + return TRUE + else + return FALSE + + +/obj/structure/closet/proc/insertion_allowed(atom/movable/AM) + if(ismob(AM)) + if(!isliving(AM)) //let's not put ghosts or camera mobs inside closets... + return FALSE + var/mob/living/L = AM + if(L.anchored || L.buckled || L.incorporeal_move || L.has_buckled_mobs()) + return FALSE + if(L.mob_size > MOB_SIZE_TINY) // Tiny mobs are treated as items. + if(horizontal && L.density) + return FALSE + if(L.mob_size > max_mob_size) + return FALSE + var/mobs_stored = 0 + for(var/mob/living/M in contents) + if(++mobs_stored >= mob_storage_capacity) + return FALSE + L.stop_pulling() + + else if(istype(AM, /obj/structure/closet)) + return FALSE + + else if(istype(AM, /obj/effect)) + return FALSE + + else if(isobj(AM)) + if((!allow_dense && AM.density) || AM.anchored || AM.has_buckled_mobs()) + return FALSE + if(isitem(AM) && !HAS_TRAIT(AM, TRAIT_NODROP)) + return TRUE + else if(!allow_objects && !istype(AM, /obj/effect/dummy/chameleon)) + return FALSE + else + return FALSE + + return TRUE + +/obj/structure/closet/proc/close(mob/living/user) + if(!opened || !can_close(user)) + return FALSE + take_contents() + playsound(loc, close_sound, 15, 1, -3) + climb_time = initial(climb_time) + opened = FALSE + density = TRUE + update_icon() + return TRUE + +/obj/structure/closet/proc/toggle(mob/living/user) + if(opened) + return close(user) + else + return open(user) + +/obj/structure/closet/proc/bust_open() + welded = FALSE //applies to all lockers + locked = FALSE //applies to critter crates and secure lockers only + broken = TRUE //applies to secure lockers only + open() + +/obj/structure/closet/proc/handle_lock_addition(mob/user, obj/item/electronics/airlock/E) + add_fingerprint(user) + if(lock_in_use) + to_chat(user, "Wait for work on [src] to be done first!") + return + if(secure) + to_chat(user, "This locker already has a lock!") + return + if(broken) + to_chat(user, "Unscrew the broken lock first!") + return + if(!istype(E)) + return + user.visible_message("[user] begins installing a lock on [src]...","You begin installing a lock on [src]...") + lock_in_use = TRUE + playsound(loc, 'sound/items/screwdriver.ogg', 50, 1) + if(!do_after(user, 60, target = src)) + lock_in_use = FALSE + return + lock_in_use = FALSE + to_chat(user, "You finish the lock on [src]!") + E.forceMove(src) + lockerelectronics = E + req_access = E.accesses + secure = TRUE + update_icon() + return TRUE + +/obj/structure/closet/proc/handle_lock_removal(mob/user, obj/item/screwdriver/S) + if(lock_in_use) + to_chat(user, "Wait for work on [src] to be done first!") + return + if(locked) + to_chat(user, "Unlock it first!") + return + if(!secure) + to_chat(user, "[src] doesn't have a lock that you can remove!") + return + if(!istype(S)) + return + var/brokenword = broken ? "broken " : null + user.visible_message("[user] begins removing the [brokenword]lock on [src]...","You begin removing the [brokenword]lock on [src]...") + playsound(loc, S.usesound, 50, 1) + lock_in_use = TRUE + if(!do_after(user, 100 * S.toolspeed, target = src)) + lock_in_use = FALSE + return + to_chat(user, "You remove the [brokenword]lock from [src]!") + if(!QDELETED(lockerelectronics)) + lockerelectronics.add_fingerprint(user) + lockerelectronics.forceMove(user.loc) + lockerelectronics = null + req_access = null + secure = FALSE + broken = FALSE + locked = FALSE + lock_in_use = FALSE + update_icon() + return TRUE + + +/obj/structure/closet/deconstruct(disassembled = TRUE) + if(ispath(material_drop) && material_drop_amount && !(flags_1 & NODECONSTRUCT_1)) + new material_drop(loc, material_drop_amount) + qdel(src) + +/obj/structure/closet/obj_break(damage_flag) + if(!broken && !(flags_1 & NODECONSTRUCT_1)) + bust_open() + +/obj/structure/closet/attackby(obj/item/W, mob/user, params) + if(user in src) + return + if(src.tool_interact(W,user)) + return 1 // No afterattack + else + return ..() + +/obj/structure/closet/proc/tool_interact(obj/item/W, mob/user)//returns TRUE if attackBy call shouldnt be continued (because tool was used/closet was of wrong type), FALSE if otherwise + . = TRUE + if(opened) + if(istype(W, cutting_tool)) + if(istype(W, /obj/item/weldingtool)) + if(!W.tool_start_check(user, amount=0)) + return + + to_chat(user, "You begin cutting \the [src] apart...") + if(W.use_tool(src, user, 40, volume=50)) + if(eigen_teleport) + to_chat(user, "The unstable nature of \the [src] makes it impossible to cut!") + return + if(!opened) + return + user.visible_message("[user] slices apart \the [src].", + "You cut \the [src] apart with \the [W].", + "You hear welding.") + deconstruct(TRUE) + return + else // for example cardboard box is cut with wirecutters + user.visible_message("[user] cut apart \the [src].", \ + "You cut \the [src] apart with \the [W].") + deconstruct(TRUE) + return + if(user.transferItemToLoc(W, drop_location())) // so we put in unlit welder too + return TRUE + else if(istype(W, /obj/item/electronics/airlock)) + handle_lock_addition(user, W) + else if(istype(W, /obj/item/screwdriver)) + handle_lock_removal(user, W) + else if(istype(W, /obj/item/weldingtool) && can_weld_shut) + if(!W.tool_start_check(user, amount=0)) + return + + to_chat(user, "You begin [welded ? "unwelding":"welding"] \the [src]...") + if(W.use_tool(src, user, 40, volume=50)) + if(eigen_teleport) + to_chat(user, "The unstable nature of \the [src] makes it impossible to weld!") + return + if(opened) + return + welded = !welded + after_weld(welded) + user.visible_message("[user] [welded ? "welds shut" : "unwelds"] \the [src].", + "You [welded ? "weld" : "unwelded"] \the [src] with \the [W].", + "You hear welding.") + update_icon() + else if(istype(W, /obj/item/wrench) && anchorable) + if(isinspace() && !anchored) + return + setAnchored(!anchored) + W.play_tool_sound(src, 75) + user.visible_message("[user] [anchored ? "anchored" : "unanchored"] \the [src] [anchored ? "to" : "from"] the ground.", \ + "You [anchored ? "anchored" : "unanchored"] \the [src] [anchored ? "to" : "from"] the ground.", \ + "You hear a ratchet.") + else if(user.a_intent != INTENT_HARM && !(W.item_flags & NOBLUDGEON)) + if(W.GetID() || !toggle(user)) + togglelock(user) + else + return FALSE + +/obj/structure/closet/proc/after_weld(weld_state) + return + +/obj/structure/closet/MouseDrop_T(atom/movable/O, mob/living/user) + if(!istype(O) || O.anchored || istype(O, /obj/screen)) + return + if(!istype(user) || user.incapacitated() || user.lying) + return + if(!Adjacent(user) || !user.Adjacent(O)) + return + if(user == O) //try to climb onto it + return ..() + if(!opened) + return + if(!isturf(O.loc)) + return + + var/actuallyismob = 0 + if(isliving(O)) + actuallyismob = 1 + else if(!isitem(O)) + return + var/turf/T = get_turf(src) + var/list/targets = list(O, src) + add_fingerprint(user) + user.visible_message("[user] [actuallyismob ? "tries to ":""]stuff [O] into [src].", \ + "You [actuallyismob ? "try to ":""]stuff [O] into [src].", \ + "You hear clanging.") + if(actuallyismob) + if(do_after_mob(user, targets, 40)) + user.visible_message("[user] stuffs [O] into [src].", \ + "You stuff [O] into [src].", \ + "You hear a loud metal bang.") + var/mob/living/L = O + if(!issilicon(L)) + L.Knockdown(40) + O.forceMove(T) + close() + else + O.forceMove(T) + return 1 + +/obj/structure/closet/relaymove(mob/user) + if(user.stat || !isturf(loc) || !isliving(user)) + return + if(locked) + if(message_cooldown <= world.time) + message_cooldown = world.time + 50 + to_chat(user, "[src]'s door won't budge!") + return + container_resist(user) + +/obj/structure/closet/attack_hand(mob/user) + . = ..() + if(.) + return + if(user.lying && get_dist(src, user) > 0) + return + + if(!toggle(user)) + togglelock(user) + +/obj/structure/closet/attack_paw(mob/user) + return attack_hand(user) + +/obj/structure/closet/attack_robot(mob/user) + if(user.Adjacent(src)) + return attack_hand(user) + +// tk grab then use on self +/obj/structure/closet/attack_self_tk(mob/user) + return attack_hand(user) + +/obj/structure/closet/verb/verb_toggleopen() + set src in oview(1) + set category = "Object" + set name = "Toggle Open" + + if(!usr.canmove || usr.stat || usr.restrained()) + return + + if(iscarbon(usr) || issilicon(usr) || isdrone(usr)) + return attack_hand(usr) + else + to_chat(usr, "This mob type can't use this verb.") + +// Objects that try to exit a locker by stepping were doing so successfully, +// and due to an oversight in turf/Enter() were going through walls. That +// should be independently resolved, but this is also an interesting twist. +/obj/structure/closet/Exit(atom/movable/AM) + open() + if(AM.loc == src) + return 0 + return 1 + +/obj/structure/closet/container_resist(mob/living/user) + if(opened) + return + if(ismovableatom(loc)) + user.changeNext_move(CLICK_CD_BREAKOUT) + user.last_special = world.time + CLICK_CD_BREAKOUT + var/atom/movable/AM = loc + AM.relay_container_resist(user, src) + return + if(!welded && !locked) + open() + return + + //okay, so the closet is either welded or locked... resist!!! + user.changeNext_move(CLICK_CD_BREAKOUT) + user.last_special = world.time + CLICK_CD_BREAKOUT + user.visible_message("[src] begins to shake violently!", \ + "You lean on the back of [src] and start pushing the door open... (this will take about [DisplayTimeText(breakout_time)].)", \ + "You hear banging from [src].") + if(do_after(user,(breakout_time), target = src)) + if(!user || user.stat != CONSCIOUS || user.loc != src || opened || (!locked && !welded) ) + return + //we check after a while whether there is a point of resisting anymore and whether the user is capable of resisting + user.visible_message("[user] successfully broke out of [src]!", + "You successfully break out of [src]!") + bust_open() + else + if(user.loc == src) //so we don't get the message if we resisted multiple times and succeeded. + to_chat(user, "You fail to break out of [src]!") + +/obj/structure/closet/AltClick(mob/user) + ..() + if(!user.canUseTopic(src, be_close=TRUE) || !isturf(loc)) + to_chat(user, "You can't do that right now!") + return + togglelock(user) + +/obj/structure/closet/CtrlShiftClick(mob/living/user) + if(!HAS_TRAIT(user, TRAIT_SKITTISH)) + return ..() + if(!user.canUseTopic(src) || !isturf(user.loc)) + return + dive_into(user) + +/obj/structure/closet/emag_act(mob/user) + . = ..() + if(!secure || broken) + return + user.visible_message("Sparks fly from [src]!", + "You scramble [src]'s lock, breaking it open!", + "You hear a faint electrical spark.") + playsound(src, "sparks", 50, 1) + broken = TRUE + locked = FALSE + if(!QDELETED(lockerelectronics)) + QDEL_NULL(lockerelectronics) + update_icon() + +/obj/structure/closet/get_remote_view_fullscreens(mob/user) + if(user.stat == DEAD || !(user.sight & (SEEOBJS|SEEMOBS))) + user.overlay_fullscreen("remote_view", /obj/screen/fullscreen/impaired, 1) + +/obj/structure/closet/emp_act(severity) + . = ..() + if(. & EMP_PROTECT_SELF) + return + if (!(. & EMP_PROTECT_CONTENTS)) + for(var/obj/O in src) + O.emp_act(severity) + if(!secure || broken) + return ..() + if(prob(50 / severity)) + locked = !locked + update_icon() + if(prob(20 / severity) && !opened) + if(!locked) + open() + else + req_access = list() + req_access += pick(get_all_accesses()) + if(!QDELETED(lockerelectronics)) + lockerelectronics.accesses = req_access + +/obj/structure/closet/contents_explosion(severity, target) + for(var/atom/A in contents) + A.ex_act(severity, target) + CHECK_TICK + +/obj/structure/closet/singularity_act() + dump_contents() + ..() + +/obj/structure/closet/AllowDrop() + return TRUE + + +/obj/structure/closet/return_temperature() + return + +/obj/structure/closet/proc/dive_into(mob/living/user) + var/turf/T1 = get_turf(user) + var/turf/T2 = get_turf(src) + if(!opened) + if(locked) + togglelock(user, TRUE) + if(!open(user)) + to_chat(user, "It won't budge!") + return + step_towards(user, T2) + T1 = get_turf(user) + if(T1 == T2) + user.resting = TRUE //so people can jump into crates without slamming the lid on their head + if(!close(user)) + to_chat(user, "You can't get [src] to close!") + user.resting = FALSE + return + user.resting = FALSE + togglelock(user) + T1.visible_message("[user] dives into [src]!") diff --git a/code/modules/VR/vr_sleeper.dm b/code/modules/VR/vr_sleeper.dm index bfbf6b5b79..89e9c33ecc 100644 --- a/code/modules/VR/vr_sleeper.dm +++ b/code/modules/VR/vr_sleeper.dm @@ -54,12 +54,16 @@ only_current_user_can_interact = TRUE /obj/machinery/vr_sleeper/hugbox/emag_act(mob/user) - return + return SEND_SIGNAL(src, COMSIG_ATOM_EMAG_ACT) /obj/machinery/vr_sleeper/emag_act(mob/user) + . = ..() + if(you_die_in_the_game_you_die_for_real) + return you_die_in_the_game_you_die_for_real = TRUE sparks.start() addtimer(CALLBACK(src, .proc/emagNotify), 150) + return TRUE /obj/machinery/vr_sleeper/update_icon() icon_state = "[initial(icon_state)][state_open ? "-open" : ""]" diff --git a/code/modules/atmospherics/machinery/airalarm.dm b/code/modules/atmospherics/machinery/airalarm.dm index 3bf54a1178..6ca25c0d80 100644 --- a/code/modules/atmospherics/machinery/airalarm.dm +++ b/code/modules/atmospherics/machinery/airalarm.dm @@ -1,880 +1,882 @@ -/datum/tlv - var/min2 - var/min1 - var/max1 - var/max2 - -/datum/tlv/New(min2 as num, min1 as num, max1 as num, max2 as num) - if(min2) src.min2 = min2 - if(min1) src.min1 = min1 - if(max1) src.max1 = max1 - if(max2) src.max2 = max2 - -/datum/tlv/proc/get_danger_level(val as num) - if(max2 != -1 && val >= max2) - return 2 - if(min2 != -1 && val <= min2) - return 2 - if(max1 != -1 && val >= max1) - return 1 - if(min1 != -1 && val <= min1) - return 1 - return 0 - -/datum/tlv/no_checks - min2 = -1 - min1 = -1 - max1 = -1 - max2 = -1 - -/datum/tlv/dangerous - min2 = -1 - min1 = -1 - max1 = 0.2 - max2 = 0.5 - -/obj/item/electronics/airalarm - name = "air alarm electronics" - icon_state = "airalarm_electronics" - -/obj/item/wallframe/airalarm - name = "air alarm frame" - desc = "Used for building Air Alarms." - icon = 'icons/obj/monitors.dmi' - icon_state = "alarm_bitem" - result_path = /obj/machinery/airalarm - -#define AALARM_MODE_SCRUBBING 1 -#define AALARM_MODE_VENTING 2 //makes draught -#define AALARM_MODE_PANIC 3 //like siphon, but stronger (enables widenet) -#define AALARM_MODE_REPLACEMENT 4 //sucks off all air, then refill and swithes to scrubbing -#define AALARM_MODE_OFF 5 -#define AALARM_MODE_FLOOD 6 //Emagged mode; turns off scrubbers and pressure checks on vents -#define AALARM_MODE_SIPHON 7 //Scrubbers suck air -#define AALARM_MODE_CONTAMINATED 8 //Turns on all filtering and widenet scrubbing. -#define AALARM_MODE_REFILL 9 //just like normal, but with triple the air output - -#define AALARM_REPORT_TIMEOUT 100 - -#define AALARM_OVERLAY_OFF "alarm_off" -#define AALARM_OVERLAY_GREEN "alarm_green" -#define AALARM_OVERLAY_WARN "alarm_amber" -#define AALARM_OVERLAY_DANGER "alarm_red" - -/obj/machinery/airalarm - name = "air alarm" - desc = "A machine that monitors atmosphere levels. Goes off if the area is dangerous." - icon = 'icons/obj/monitors.dmi' - icon_state = "alarm0" - use_power = IDLE_POWER_USE - idle_power_usage = 4 - active_power_usage = 8 - power_channel = ENVIRON - req_access = list(ACCESS_ATMOSPHERICS) - max_integrity = 250 - integrity_failure = 80 - armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 100, "bomb" = 0, "bio" = 100, "rad" = 100, "fire" = 90, "acid" = 30) - resistance_flags = FIRE_PROOF - - var/danger_level = 0 - var/mode = AALARM_MODE_SCRUBBING - - var/locked = TRUE - var/aidisabled = 0 - var/shorted = 0 - var/buildstage = 2 // 2 = complete, 1 = no wires, 0 = circuit gone - var/brightness_on = 1 - - var/frequency = FREQ_ATMOS_CONTROL - var/alarm_frequency = FREQ_ATMOS_ALARMS - var/datum/radio_frequency/radio_connection - - var/list/TLV = list( // Breathable air. - "pressure" = new/datum/tlv(ONE_ATMOSPHERE * 0.8, ONE_ATMOSPHERE* 0.9, ONE_ATMOSPHERE * 1.1, ONE_ATMOSPHERE * 1.2), // kPa - "temperature" = new/datum/tlv(T0C, T0C+10, T0C+40, T0C+66), - /datum/gas/oxygen = new/datum/tlv(16, 19, 135, 140), // Partial pressure, kpa - /datum/gas/nitrogen = new/datum/tlv(-1, -1, 1000, 1000), - /datum/gas/carbon_dioxide = new/datum/tlv(-1, -1, 5, 10), - /datum/gas/miasma = new/datum/tlv/(-1, -1, 2, 5), - /datum/gas/plasma = new/datum/tlv/dangerous, - /datum/gas/nitrous_oxide = new/datum/tlv/dangerous, - /datum/gas/bz = new/datum/tlv/dangerous, - /datum/gas/hypernoblium = new/datum/tlv(-1, -1, 1000, 1000), // Hyper-Noblium is inert and nontoxic - /datum/gas/water_vapor = new/datum/tlv/dangerous, - /datum/gas/tritium = new/datum/tlv/dangerous, - /datum/gas/stimulum = new/datum/tlv(-1, -1, 1000, 1000), // Stimulum has only positive effects - /datum/gas/nitryl = new/datum/tlv/dangerous, - /datum/gas/pluoxium = new/datum/tlv(-1, -1, 1000, 1000) // Unlike oxygen, pluoxium does not fuel plasma/tritium fires - ) - -/obj/machinery/airalarm/server // No checks here. - TLV = list( - "pressure" = new/datum/tlv/no_checks, - "temperature" = new/datum/tlv/no_checks, - /datum/gas/oxygen = new/datum/tlv/no_checks, - /datum/gas/nitrogen = new/datum/tlv/no_checks, - /datum/gas/carbon_dioxide = new/datum/tlv/no_checks, - /datum/gas/miasma = new/datum/tlv/no_checks, - /datum/gas/plasma = new/datum/tlv/no_checks, - /datum/gas/nitrous_oxide = new/datum/tlv/no_checks, - /datum/gas/bz = new/datum/tlv/no_checks, - /datum/gas/hypernoblium = new/datum/tlv/no_checks, - /datum/gas/water_vapor = new/datum/tlv/no_checks, - /datum/gas/tritium = new/datum/tlv/no_checks, - /datum/gas/stimulum = new/datum/tlv/no_checks, - /datum/gas/nitryl = new/datum/tlv/no_checks, - /datum/gas/pluoxium = new/datum/tlv/no_checks - ) - -/obj/machinery/airalarm/kitchen_cold_room // Copypasta: to check temperatures. - TLV = list( - "pressure" = new/datum/tlv(ONE_ATMOSPHERE * 0.8, ONE_ATMOSPHERE* 0.9, ONE_ATMOSPHERE * 1.1, ONE_ATMOSPHERE * 1.2), // kPa - "temperature" = new/datum/tlv(T0C-73.15, T0C-63.15, T0C, T0C+10), - /datum/gas/oxygen = new/datum/tlv(16, 19, 135, 140), // Partial pressure, kpa - /datum/gas/nitrogen = new/datum/tlv(-1, -1, 1000, 1000), - /datum/gas/carbon_dioxide = new/datum/tlv(-1, -1, 5, 10), - /datum/gas/miasma = new/datum/tlv/(-1, -1, 2, 5), - /datum/gas/plasma = new/datum/tlv/dangerous, - /datum/gas/nitrous_oxide = new/datum/tlv/dangerous, - /datum/gas/bz = new/datum/tlv/dangerous, - /datum/gas/hypernoblium = new/datum/tlv(-1, -1, 1000, 1000), // Hyper-Noblium is inert and nontoxic - /datum/gas/water_vapor = new/datum/tlv/dangerous, - /datum/gas/tritium = new/datum/tlv/dangerous, - /datum/gas/stimulum = new/datum/tlv(-1, -1, 1000, 1000), // Stimulum has only positive effects - /datum/gas/nitryl = new/datum/tlv/dangerous, - /datum/gas/pluoxium = new/datum/tlv(-1, -1, 1000, 1000) // Unlike oxygen, pluoxium does not fuel plasma/tritium fires - ) - -/obj/machinery/airalarm/unlocked - locked = FALSE - -/obj/machinery/airalarm/engine - name = "engine air alarm" - locked = FALSE - req_access = null - req_one_access = list(ACCESS_ATMOSPHERICS, ACCESS_ENGINE) - -/obj/machinery/airalarm/mixingchamber - name = "chamber air alarm" - locked = FALSE - req_access = null - req_one_access = list(ACCESS_ATMOSPHERICS, ACCESS_TOX, ACCESS_TOX_STORAGE) - -/obj/machinery/airalarm/all_access - name = "all-access air alarm" - desc = "This particular atmos control unit appears to have no access restrictions." - locked = FALSE - req_access = null - req_one_access = null - -/obj/machinery/airalarm/syndicate //general syndicate access - req_access = list(ACCESS_SYNDICATE) - -/obj/machinery/airalarm/directional/north //Pixel offsets get overwritten on New() - dir = SOUTH - pixel_y = 24 - -/obj/machinery/airalarm/directional/south - dir = NORTH - pixel_y = -24 - -/obj/machinery/airalarm/directional/east - dir = WEST - pixel_x = 24 - -/obj/machinery/airalarm/directional/west - dir = EAST - pixel_x = -24 - -//all air alarms in area are connected via magic -/area - var/list/air_vent_names = list() - var/list/air_scrub_names = list() - var/list/air_vent_info = list() - var/list/air_scrub_info = list() - -/obj/machinery/airalarm/Initialize(mapload, ndir, nbuild) - . = ..() - wires = new /datum/wires/airalarm(src) - - if(ndir) - setDir(ndir) - - if(nbuild) - buildstage = 0 - panel_open = TRUE - pixel_x = (dir & 3)? 0 : (dir == 4 ? -24 : 24) - pixel_y = (dir & 3)? (dir == 1 ? -24 : 24) : 0 - - if(name == initial(name)) - name = "[get_area_name(src)] Air Alarm" - - power_change() - set_frequency(frequency) - -/obj/machinery/airalarm/Destroy() - SSradio.remove_object(src, frequency) - qdel(wires) - wires = null - return ..() - -/obj/machinery/airalarm/examine(mob/user) - . = ..() - switch(buildstage) - if(0) - to_chat(user, "It is missing air alarm electronics.") - if(1) - to_chat(user, "It is missing wiring.") - if(2) - to_chat(user, "Alt-click to [locked ? "unlock" : "lock"] the interface.") - -/obj/machinery/airalarm/ui_status(mob/user) - if(user.has_unlimited_silicon_privilege && aidisabled) - to_chat(user, "AI control has been disabled.") - else if(!shorted) - return ..() - return UI_CLOSE - -/obj/machinery/airalarm/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \ - datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state) - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) - if(!ui) - ui = new(user, src, ui_key, "airalarm", name, 440, 650, master_ui, state) - ui.open() - -/obj/machinery/airalarm/ui_data(mob/user) - var/data = list( - "locked" = locked, - "siliconUser" = user.has_unlimited_silicon_privilege, - "emagged" = (obj_flags & EMAGGED ? 1 : 0), - "danger_level" = danger_level, - ) - - var/area/A = get_area(src) - data["atmos_alarm"] = A.atmosalm - data["fire_alarm"] = A.fire - - var/turf/T = get_turf(src) - var/datum/gas_mixture/environment = T.return_air() - var/datum/tlv/cur_tlv - - data["environment_data"] = list() - var/pressure = environment.return_pressure() - cur_tlv = TLV["pressure"] - data["environment_data"] += list(list( - "name" = "Pressure", - "value" = pressure, - "unit" = "kPa", - "danger_level" = cur_tlv.get_danger_level(pressure) - )) - var/temperature = environment.temperature - cur_tlv = TLV["temperature"] - data["environment_data"] += list(list( - "name" = "Temperature", - "value" = temperature, - "unit" = "K ([round(temperature - T0C, 0.1)]C)", - "danger_level" = cur_tlv.get_danger_level(temperature) - )) - var/total_moles = environment.total_moles() - var/partial_pressure = R_IDEAL_GAS_EQUATION * environment.temperature / environment.volume - for(var/gas_id in environment.gases) - if(!(gas_id in TLV)) // We're not interested in this gas, it seems. - continue - cur_tlv = TLV[gas_id] - data["environment_data"] += list(list( - "name" = GLOB.meta_gas_names[gas_id], - "value" = environment.gases[gas_id] / total_moles * 100, - "unit" = "%", - "danger_level" = cur_tlv.get_danger_level(environment.gases[gas_id] * partial_pressure) - )) - - if(!locked || user.has_unlimited_silicon_privilege) - data["vents"] = list() - for(var/id_tag in A.air_vent_names) - var/long_name = A.air_vent_names[id_tag] - var/list/info = A.air_vent_info[id_tag] - if(!info || info["frequency"] != frequency) - continue - data["vents"] += list(list( - "id_tag" = id_tag, - "long_name" = sanitize(long_name), - "power" = info["power"], - "checks" = info["checks"], - "excheck" = info["checks"]&1, - "incheck" = info["checks"]&2, - "direction" = info["direction"], - "external" = info["external"], - "internal" = info["internal"], - "extdefault"= (info["external"] == ONE_ATMOSPHERE), - "intdefault"= (info["internal"] == 0) - )) - data["scrubbers"] = list() - for(var/id_tag in A.air_scrub_names) - var/long_name = A.air_scrub_names[id_tag] - var/list/info = A.air_scrub_info[id_tag] - if(!info || info["frequency"] != frequency) - continue - data["scrubbers"] += list(list( - "id_tag" = id_tag, - "long_name" = sanitize(long_name), - "power" = info["power"], - "scrubbing" = info["scrubbing"], - "widenet" = info["widenet"], - "filter_types" = info["filter_types"] - )) - data["mode"] = mode - data["modes"] = list() - data["modes"] += list(list("name" = "Filtering - Scrubs out contaminants", "mode" = AALARM_MODE_SCRUBBING, "selected" = mode == AALARM_MODE_SCRUBBING, "danger" = 0)) - data["modes"] += list(list("name" = "Contaminated - Scrubs out ALL contaminants quickly","mode" = AALARM_MODE_CONTAMINATED, "selected" = mode == AALARM_MODE_CONTAMINATED, "danger" = 0)) - data["modes"] += list(list("name" = "Draught - Siphons out air while replacing", "mode" = AALARM_MODE_VENTING, "selected" = mode == AALARM_MODE_VENTING, "danger" = 0)) - data["modes"] += list(list("name" = "Refill - Triple vent output", "mode" = AALARM_MODE_REFILL, "selected" = mode == AALARM_MODE_REFILL, "danger" = 1)) - data["modes"] += list(list("name" = "Cycle - Siphons air before replacing", "mode" = AALARM_MODE_REPLACEMENT, "selected" = mode == AALARM_MODE_REPLACEMENT, "danger" = 1)) - data["modes"] += list(list("name" = "Siphon - Siphons air out of the room", "mode" = AALARM_MODE_SIPHON, "selected" = mode == AALARM_MODE_SIPHON, "danger" = 1)) - data["modes"] += list(list("name" = "Panic Siphon - Siphons air out of the room quickly","mode" = AALARM_MODE_PANIC, "selected" = mode == AALARM_MODE_PANIC, "danger" = 1)) - data["modes"] += list(list("name" = "Off - Shuts off vents and scrubbers", "mode" = AALARM_MODE_OFF, "selected" = mode == AALARM_MODE_OFF, "danger" = 0)) - if(obj_flags & EMAGGED) - data["modes"] += list(list("name" = "Flood - Shuts off scrubbers and opens vents", "mode" = AALARM_MODE_FLOOD, "selected" = mode == AALARM_MODE_FLOOD, "danger" = 1)) - - var/datum/tlv/selected - var/list/thresholds = list() - - selected = TLV["pressure"] - thresholds += list(list("name" = "Pressure", "settings" = list())) - thresholds[thresholds.len]["settings"] += list(list("env" = "pressure", "val" = "min2", "selected" = selected.min2)) - thresholds[thresholds.len]["settings"] += list(list("env" = "pressure", "val" = "min1", "selected" = selected.min1)) - thresholds[thresholds.len]["settings"] += list(list("env" = "pressure", "val" = "max1", "selected" = selected.max1)) - thresholds[thresholds.len]["settings"] += list(list("env" = "pressure", "val" = "max2", "selected" = selected.max2)) - - selected = TLV["temperature"] - thresholds += list(list("name" = "Temperature", "settings" = list())) - thresholds[thresholds.len]["settings"] += list(list("env" = "temperature", "val" = "min2", "selected" = selected.min2)) - thresholds[thresholds.len]["settings"] += list(list("env" = "temperature", "val" = "min1", "selected" = selected.min1)) - thresholds[thresholds.len]["settings"] += list(list("env" = "temperature", "val" = "max1", "selected" = selected.max1)) - thresholds[thresholds.len]["settings"] += list(list("env" = "temperature", "val" = "max2", "selected" = selected.max2)) - - for(var/gas_id in GLOB.meta_gas_names) - if(!(gas_id in TLV)) // We're not interested in this gas, it seems. - continue - selected = TLV[gas_id] - thresholds += list(list("name" = GLOB.meta_gas_names[gas_id], "settings" = list())) - thresholds[thresholds.len]["settings"] += list(list("env" = gas_id, "val" = "min2", "selected" = selected.min2)) - thresholds[thresholds.len]["settings"] += list(list("env" = gas_id, "val" = "min1", "selected" = selected.min1)) - thresholds[thresholds.len]["settings"] += list(list("env" = gas_id, "val" = "max1", "selected" = selected.max1)) - thresholds[thresholds.len]["settings"] += list(list("env" = gas_id, "val" = "max2", "selected" = selected.max2)) - - data["thresholds"] = thresholds - return data - -/obj/machinery/airalarm/ui_act(action, params) - if(..() || buildstage != 2) - return - if((locked && !usr.has_unlimited_silicon_privilege) || (usr.has_unlimited_silicon_privilege && aidisabled)) - return - var/device_id = params["id_tag"] - switch(action) - if("lock") - if(usr.has_unlimited_silicon_privilege && !wires.is_cut(WIRE_IDSCAN)) - locked = !locked - . = TRUE - if("power", "toggle_filter", "widenet", "scrubbing") - send_signal(device_id, list("[action]" = params["val"]), usr) - . = TRUE - if("excheck") - send_signal(device_id, list("checks" = text2num(params["val"])^1), usr) - . = TRUE - if("incheck") - send_signal(device_id, list("checks" = text2num(params["val"])^2), usr) - . = TRUE - if("set_external_pressure", "set_internal_pressure") - var/area/A = get_area(src) - var/target = input("New target pressure:", name, A.air_vent_info[device_id][(action == "set_external_pressure" ? "external" : "internal")]) as num|null - if(!isnull(target) && !..()) - send_signal(device_id, list("[action]" = target), usr) - . = TRUE - if("reset_external_pressure") - send_signal(device_id, list("reset_external_pressure"), usr) - . = TRUE - if("reset_internal_pressure") - send_signal(device_id, list("reset_internal_pressure"), usr) - . = TRUE - if("threshold") - var/env = params["env"] - if(text2path(env)) - env = text2path(env) - - var/name = params["var"] - var/datum/tlv/tlv = TLV[env] - if(isnull(tlv)) - return - var/value = input("New [name] for [env]:", name, tlv.vars[name]) as num|null - if(!isnull(value) && !..()) - if(value < 0) - tlv.vars[name] = -1 - else - tlv.vars[name] = round(value, 0.01) - investigate_log(" treshold value for [env]:[name] was set to [value] by [key_name(usr)]",INVESTIGATE_ATMOS) - . = TRUE - if("mode") - mode = text2num(params["mode"]) - investigate_log("was turned to [get_mode_name(mode)] mode by [key_name(usr)]",INVESTIGATE_ATMOS) - apply_mode() - . = TRUE - if("alarm") - var/area/A = get_area(src) - if(A.atmosalert(2, src)) - post_alert(2) - . = TRUE - if("reset") - var/area/A = get_area(src) - if(A.atmosalert(0, src)) - post_alert(0) - . = TRUE - update_icon() - -/obj/machinery/airalarm/proc/reset(wire) - switch(wire) - if(WIRE_POWER) - if(!wires.is_cut(WIRE_POWER)) - shorted = FALSE - update_icon() - if(WIRE_AI) - if(!wires.is_cut(WIRE_AI)) - aidisabled = FALSE - - -/obj/machinery/airalarm/proc/shock(mob/user, prb) - if((stat & (NOPOWER))) // unpowered, no shock - return 0 - if(!prob(prb)) - return 0 //you lucked out, no shock for you - var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread - s.set_up(5, 1, src) - s.start() //sparks always. - if (electrocute_mob(user, get_area(src), src, 1, TRUE)) - return 1 - else - return 0 - -/obj/machinery/airalarm/proc/refresh_all() - var/area/A = get_area(src) - for(var/id_tag in A.air_vent_names) - var/list/I = A.air_vent_info[id_tag] - if(I && I["timestamp"] + AALARM_REPORT_TIMEOUT / 2 > world.time) - continue - send_signal(id_tag, list("status")) - for(var/id_tag in A.air_scrub_names) - var/list/I = A.air_scrub_info[id_tag] - if(I && I["timestamp"] + AALARM_REPORT_TIMEOUT / 2 > world.time) - continue - send_signal(id_tag, list("status")) - -/obj/machinery/airalarm/proc/set_frequency(new_frequency) - SSradio.remove_object(src, frequency) - frequency = new_frequency - radio_connection = SSradio.add_object(src, frequency, RADIO_TO_AIRALARM) - -/obj/machinery/airalarm/proc/send_signal(target, list/command, mob/user)//sends signal 'command' to 'target'. Returns 0 if no radio connection, 1 otherwise - if(!radio_connection) - return 0 - - var/datum/signal/signal = new(command) - signal.data["tag"] = target - signal.data["sigtype"] = "command" - signal.data["user"] = user - radio_connection.post_signal(src, signal, RADIO_FROM_AIRALARM) - - return 1 - -/obj/machinery/airalarm/proc/get_mode_name(mode_value) - switch(mode_value) - if(AALARM_MODE_SCRUBBING) - return "Filtering" - if(AALARM_MODE_CONTAMINATED) - return "Contaminated" - if(AALARM_MODE_VENTING) - return "Draught" - if(AALARM_MODE_REFILL) - return "Refill" - if(AALARM_MODE_PANIC) - return "Panic Siphon" - if(AALARM_MODE_REPLACEMENT) - return "Cycle" - if(AALARM_MODE_SIPHON) - return "Siphon" - if(AALARM_MODE_OFF) - return "Off" - if(AALARM_MODE_FLOOD) - return "Flood" - -/obj/machinery/airalarm/proc/apply_mode() - var/area/A = get_area(src) - switch(mode) - if(AALARM_MODE_SCRUBBING) - for(var/device_id in A.air_scrub_names) - send_signal(device_id, list( - "power" = 1, - "set_filters" = list(/datum/gas/carbon_dioxide, /datum/gas/miasma), - "scrubbing" = 1, - "widenet" = 0, - )) - for(var/device_id in A.air_vent_names) - send_signal(device_id, list( - "power" = 1, - "checks" = 1, - "set_external_pressure" = ONE_ATMOSPHERE - )) - if(AALARM_MODE_CONTAMINATED) - for(var/device_id in A.air_scrub_names) - send_signal(device_id, list( - "power" = 1, - "set_filters" = list( - /datum/gas/carbon_dioxide, - /datum/gas/miasma, - /datum/gas/plasma, - /datum/gas/water_vapor, - /datum/gas/hypernoblium, - /datum/gas/nitrous_oxide, - /datum/gas/nitryl, - /datum/gas/tritium, - /datum/gas/bz, - /datum/gas/stimulum, - /datum/gas/pluoxium - ), - "scrubbing" = 1, - "widenet" = 1, - )) - for(var/device_id in A.air_vent_names) - send_signal(device_id, list( - "power" = 1, - "checks" = 1, - "set_external_pressure" = ONE_ATMOSPHERE - )) - if(AALARM_MODE_VENTING) - for(var/device_id in A.air_scrub_names) - send_signal(device_id, list( - "power" = 1, - "widenet" = 0, - "scrubbing" = 0 - )) - for(var/device_id in A.air_vent_names) - send_signal(device_id, list( - "power" = 1, - "checks" = 1, - "set_external_pressure" = ONE_ATMOSPHERE*2 - )) - if(AALARM_MODE_REFILL) - for(var/device_id in A.air_scrub_names) - send_signal(device_id, list( - "power" = 1, - "set_filters" = list(/datum/gas/carbon_dioxide, /datum/gas/miasma), - "scrubbing" = 1, - "widenet" = 0, - )) - for(var/device_id in A.air_vent_names) - send_signal(device_id, list( - "power" = 1, - "checks" = 1, - "set_external_pressure" = ONE_ATMOSPHERE * 3 - )) - if(AALARM_MODE_PANIC, - AALARM_MODE_REPLACEMENT) - for(var/device_id in A.air_scrub_names) - send_signal(device_id, list( - "power" = 1, - "widenet" = 1, - "scrubbing" = 0 - )) - for(var/device_id in A.air_vent_names) - send_signal(device_id, list( - "power" = 0 - )) - if(AALARM_MODE_SIPHON) - for(var/device_id in A.air_scrub_names) - send_signal(device_id, list( - "power" = 1, - "widenet" = 0, - "scrubbing" = 0 - )) - for(var/device_id in A.air_vent_names) - send_signal(device_id, list( - "power" = 0 - )) - - if(AALARM_MODE_OFF) - for(var/device_id in A.air_scrub_names) - send_signal(device_id, list( - "power" = 0 - )) - for(var/device_id in A.air_vent_names) - send_signal(device_id, list( - "power" = 0 - )) - if(AALARM_MODE_FLOOD) - for(var/device_id in A.air_scrub_names) - send_signal(device_id, list( - "power" = 0 - )) - for(var/device_id in A.air_vent_names) - send_signal(device_id, list( - "power" = 1, - "checks" = 2, - "set_internal_pressure" = 0 - )) - -/obj/machinery/airalarm/update_icon() - set_light(0) - cut_overlays() - SSvis_overlays.remove_vis_overlay(src, managed_vis_overlays) - if(stat & NOPOWER) - icon_state = "alarm0" - return - - if(stat & BROKEN) - icon_state = "alarmx" - return - - if(panel_open) - switch(buildstage) - if(2) - icon_state = "alarmx" - if(1) - icon_state = "alarm_b2" - if(0) - icon_state = "alarm_b1" - return - - icon_state = "alarm1" - var/overlay_state = AALARM_OVERLAY_OFF - var/area/A = get_area(src) - switch(max(danger_level, A.atmosalm)) - if(0) - add_overlay(AALARM_OVERLAY_GREEN) - overlay_state = AALARM_OVERLAY_GREEN - light_color = LIGHT_COLOR_GREEN - set_light(brightness_on) - if(1) - add_overlay(AALARM_OVERLAY_WARN) - overlay_state = AALARM_OVERLAY_WARN - light_color = LIGHT_COLOR_LAVA - set_light(brightness_on) - if(2) - add_overlay(AALARM_OVERLAY_DANGER) - overlay_state = AALARM_OVERLAY_DANGER - light_color = LIGHT_COLOR_RED - set_light(brightness_on) - - SSvis_overlays.add_vis_overlay(src, icon, overlay_state, ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE, dir) - update_light() - -/obj/machinery/airalarm/process() - if((stat & (NOPOWER|BROKEN)) || shorted) - return - - var/turf/location = get_turf(src) - if(!location) - return - - var/datum/tlv/cur_tlv - - var/datum/gas_mixture/environment = location.return_air() - var/list/env_gases = environment.gases - var/partial_pressure = R_IDEAL_GAS_EQUATION * environment.temperature / environment.volume - - cur_tlv = TLV["pressure"] - var/environment_pressure = environment.return_pressure() - var/pressure_dangerlevel = cur_tlv.get_danger_level(environment_pressure) - - cur_tlv = TLV["temperature"] - var/temperature_dangerlevel = cur_tlv.get_danger_level(environment.temperature) - - var/gas_dangerlevel = 0 - for(var/gas_id in env_gases) - if(!(gas_id in TLV)) // We're not interested in this gas, it seems. - continue - cur_tlv = TLV[gas_id] - gas_dangerlevel = max(gas_dangerlevel, cur_tlv.get_danger_level(env_gases[gas_id] * partial_pressure)) - - GAS_GARBAGE_COLLECT(environment.gases) - - var/old_danger_level = danger_level - danger_level = max(pressure_dangerlevel, temperature_dangerlevel, gas_dangerlevel) - - if(old_danger_level != danger_level) - apply_danger_level() - if(mode == AALARM_MODE_REPLACEMENT && environment_pressure < ONE_ATMOSPHERE * 0.05) - mode = AALARM_MODE_SCRUBBING - apply_mode() - - return - - -/obj/machinery/airalarm/proc/post_alert(alert_level) - var/datum/radio_frequency/frequency = SSradio.return_frequency(alarm_frequency) - - if(!frequency) - return - - var/datum/signal/alert_signal = new(list( - "zone" = get_area_name(src), - "type" = "Atmospheric" - )) - if(alert_level==2) - alert_signal.data["alert"] = "severe" - else if (alert_level==1) - alert_signal.data["alert"] = "minor" - else if (alert_level==0) - alert_signal.data["alert"] = "clear" - - frequency.post_signal(src, alert_signal, range = -1) - -/obj/machinery/airalarm/proc/apply_danger_level() - var/area/A = get_area(src) - - var/new_area_danger_level = 0 - for(var/obj/machinery/airalarm/AA in A) - if (!(AA.stat & (NOPOWER|BROKEN)) && !AA.shorted) - new_area_danger_level = max(new_area_danger_level,AA.danger_level) - if(A.atmosalert(new_area_danger_level,src)) //if area was in normal state or if area was in alert state - post_alert(new_area_danger_level) - - update_icon() - -/obj/machinery/airalarm/attackby(obj/item/W, mob/user, params) - switch(buildstage) - if(2) - if(istype(W, /obj/item/wirecutters) && panel_open && wires.is_all_cut()) - W.play_tool_sound(src) - to_chat(user, "You cut the final wires.") - new /obj/item/stack/cable_coil(loc, 5) - buildstage = 1 - update_icon() - return - else if(istype(W, /obj/item/screwdriver)) // Opening that Air Alarm up. - W.play_tool_sound(src) - panel_open = !panel_open - to_chat(user, "The wires have been [panel_open ? "exposed" : "unexposed"].") - update_icon() - return - else if(istype(W, /obj/item/card/id) || istype(W, /obj/item/pda))// trying to unlock the interface with an ID card - togglelock(user) - else if(panel_open && is_wire_tool(W)) - wires.interact(user) - return - if(1) - if(istype(W, /obj/item/crowbar)) - user.visible_message("[user.name] removes the electronics from [src.name].",\ - "You start prying out the circuit...") - W.play_tool_sound(src) - if (W.use_tool(src, user, 20)) - if (buildstage == 1) - to_chat(user, "You remove the air alarm electronics.") - new /obj/item/electronics/airalarm( src.loc ) - playsound(src.loc, 'sound/items/deconstruct.ogg', 50, 1) - buildstage = 0 - update_icon() - return - - if(istype(W, /obj/item/stack/cable_coil)) - var/obj/item/stack/cable_coil/cable = W - if(cable.get_amount() < 5) - to_chat(user, "You need five lengths of cable to wire the air alarm!") - return - user.visible_message("[user.name] wires the air alarm.", \ - "You start wiring the air alarm...") - if (do_after(user, 20, target = src)) - if (cable.get_amount() >= 5 && buildstage == 1) - cable.use(5) - to_chat(user, "You wire the air alarm.") - wires.repair() - aidisabled = 0 - locked = FALSE - mode = 1 - shorted = 0 - post_alert(0) - buildstage = 2 - update_icon() - return - if(0) - if(istype(W, /obj/item/electronics/airalarm)) - if(user.temporarilyRemoveItemFromInventory(W)) - to_chat(user, "You insert the circuit.") - buildstage = 1 - update_icon() - qdel(W) - return - - if(istype(W, /obj/item/electroadaptive_pseudocircuit)) - var/obj/item/electroadaptive_pseudocircuit/P = W - if(!P.adapt_circuit(user, 25)) - return - user.visible_message("[user] fabricates a circuit and places it into [src].", \ - "You adapt an air alarm circuit and slot it into the assembly.") - buildstage = 1 - update_icon() - return - - if(istype(W, /obj/item/wrench)) - to_chat(user, "You detach \the [src] from the wall.") - W.play_tool_sound(src) - new /obj/item/wallframe/airalarm( user.loc ) - qdel(src) - return - - return ..() - -/obj/machinery/airalarm/AltClick(mob/user) - ..() - if(!user.canUseTopic(src, !issilicon(user)) || !isturf(loc)) - return - else - togglelock(user) - -/obj/machinery/airalarm/proc/togglelock(mob/living/user) - if(stat & (NOPOWER|BROKEN)) - to_chat(user, "It does nothing!") - else - if(src.allowed(usr) && !wires.is_cut(WIRE_IDSCAN)) - locked = !locked - updateUsrDialog() - to_chat(user, "You [ locked ? "lock" : "unlock"] the air alarm interface.") - else - to_chat(user, "Access denied.") - return - -/obj/machinery/airalarm/power_change() - ..() - if(stat & NOPOWER) - set_light(0) - update_icon() - -/obj/machinery/airalarm/emag_act(mob/user) - if(obj_flags & EMAGGED) - return - obj_flags |= EMAGGED - visible_message("Sparks fly out of [src]!", "You emag [src], disabling its safeties.") - playsound(src, "sparks", 50, 1) - -/obj/machinery/airalarm/obj_break(damage_flag) - ..() - update_icon() - set_light(0) - -/obj/machinery/airalarm/deconstruct(disassembled = TRUE) - if(!(flags_1 & NODECONSTRUCT_1)) - new /obj/item/stack/sheet/metal(loc, 2) - var/obj/item/I = new /obj/item/electronics/airalarm(loc) - if(!disassembled) - I.obj_integrity = I.max_integrity * 0.5 - new /obj/item/stack/cable_coil(loc, 3) - qdel(src) - -#undef AALARM_MODE_SCRUBBING -#undef AALARM_MODE_VENTING -#undef AALARM_MODE_PANIC -#undef AALARM_MODE_REPLACEMENT -#undef AALARM_MODE_OFF -#undef AALARM_MODE_FLOOD -#undef AALARM_MODE_SIPHON -#undef AALARM_MODE_CONTAMINATED -#undef AALARM_MODE_REFILL -#undef AALARM_REPORT_TIMEOUT +/datum/tlv + var/min2 + var/min1 + var/max1 + var/max2 + +/datum/tlv/New(min2 as num, min1 as num, max1 as num, max2 as num) + if(min2) src.min2 = min2 + if(min1) src.min1 = min1 + if(max1) src.max1 = max1 + if(max2) src.max2 = max2 + +/datum/tlv/proc/get_danger_level(val as num) + if(max2 != -1 && val >= max2) + return 2 + if(min2 != -1 && val <= min2) + return 2 + if(max1 != -1 && val >= max1) + return 1 + if(min1 != -1 && val <= min1) + return 1 + return 0 + +/datum/tlv/no_checks + min2 = -1 + min1 = -1 + max1 = -1 + max2 = -1 + +/datum/tlv/dangerous + min2 = -1 + min1 = -1 + max1 = 0.2 + max2 = 0.5 + +/obj/item/electronics/airalarm + name = "air alarm electronics" + icon_state = "airalarm_electronics" + +/obj/item/wallframe/airalarm + name = "air alarm frame" + desc = "Used for building Air Alarms." + icon = 'icons/obj/monitors.dmi' + icon_state = "alarm_bitem" + result_path = /obj/machinery/airalarm + +#define AALARM_MODE_SCRUBBING 1 +#define AALARM_MODE_VENTING 2 //makes draught +#define AALARM_MODE_PANIC 3 //like siphon, but stronger (enables widenet) +#define AALARM_MODE_REPLACEMENT 4 //sucks off all air, then refill and swithes to scrubbing +#define AALARM_MODE_OFF 5 +#define AALARM_MODE_FLOOD 6 //Emagged mode; turns off scrubbers and pressure checks on vents +#define AALARM_MODE_SIPHON 7 //Scrubbers suck air +#define AALARM_MODE_CONTAMINATED 8 //Turns on all filtering and widenet scrubbing. +#define AALARM_MODE_REFILL 9 //just like normal, but with triple the air output + +#define AALARM_REPORT_TIMEOUT 100 + +#define AALARM_OVERLAY_OFF "alarm_off" +#define AALARM_OVERLAY_GREEN "alarm_green" +#define AALARM_OVERLAY_WARN "alarm_amber" +#define AALARM_OVERLAY_DANGER "alarm_red" + +/obj/machinery/airalarm + name = "air alarm" + desc = "A machine that monitors atmosphere levels. Goes off if the area is dangerous." + icon = 'icons/obj/monitors.dmi' + icon_state = "alarm0" + use_power = IDLE_POWER_USE + idle_power_usage = 4 + active_power_usage = 8 + power_channel = ENVIRON + req_access = list(ACCESS_ATMOSPHERICS) + max_integrity = 250 + integrity_failure = 80 + armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 100, "bomb" = 0, "bio" = 100, "rad" = 100, "fire" = 90, "acid" = 30) + resistance_flags = FIRE_PROOF + + var/danger_level = 0 + var/mode = AALARM_MODE_SCRUBBING + + var/locked = TRUE + var/aidisabled = 0 + var/shorted = 0 + var/buildstage = 2 // 2 = complete, 1 = no wires, 0 = circuit gone + var/brightness_on = 1 + + var/frequency = FREQ_ATMOS_CONTROL + var/alarm_frequency = FREQ_ATMOS_ALARMS + var/datum/radio_frequency/radio_connection + + var/list/TLV = list( // Breathable air. + "pressure" = new/datum/tlv(ONE_ATMOSPHERE * 0.8, ONE_ATMOSPHERE* 0.9, ONE_ATMOSPHERE * 1.1, ONE_ATMOSPHERE * 1.2), // kPa + "temperature" = new/datum/tlv(T0C, T0C+10, T0C+40, T0C+66), + /datum/gas/oxygen = new/datum/tlv(16, 19, 135, 140), // Partial pressure, kpa + /datum/gas/nitrogen = new/datum/tlv(-1, -1, 1000, 1000), + /datum/gas/carbon_dioxide = new/datum/tlv(-1, -1, 5, 10), + /datum/gas/miasma = new/datum/tlv/(-1, -1, 2, 5), + /datum/gas/plasma = new/datum/tlv/dangerous, + /datum/gas/nitrous_oxide = new/datum/tlv/dangerous, + /datum/gas/bz = new/datum/tlv/dangerous, + /datum/gas/hypernoblium = new/datum/tlv(-1, -1, 1000, 1000), // Hyper-Noblium is inert and nontoxic + /datum/gas/water_vapor = new/datum/tlv/dangerous, + /datum/gas/tritium = new/datum/tlv/dangerous, + /datum/gas/stimulum = new/datum/tlv(-1, -1, 1000, 1000), // Stimulum has only positive effects + /datum/gas/nitryl = new/datum/tlv/dangerous, + /datum/gas/pluoxium = new/datum/tlv(-1, -1, 1000, 1000) // Unlike oxygen, pluoxium does not fuel plasma/tritium fires + ) + +/obj/machinery/airalarm/server // No checks here. + TLV = list( + "pressure" = new/datum/tlv/no_checks, + "temperature" = new/datum/tlv/no_checks, + /datum/gas/oxygen = new/datum/tlv/no_checks, + /datum/gas/nitrogen = new/datum/tlv/no_checks, + /datum/gas/carbon_dioxide = new/datum/tlv/no_checks, + /datum/gas/miasma = new/datum/tlv/no_checks, + /datum/gas/plasma = new/datum/tlv/no_checks, + /datum/gas/nitrous_oxide = new/datum/tlv/no_checks, + /datum/gas/bz = new/datum/tlv/no_checks, + /datum/gas/hypernoblium = new/datum/tlv/no_checks, + /datum/gas/water_vapor = new/datum/tlv/no_checks, + /datum/gas/tritium = new/datum/tlv/no_checks, + /datum/gas/stimulum = new/datum/tlv/no_checks, + /datum/gas/nitryl = new/datum/tlv/no_checks, + /datum/gas/pluoxium = new/datum/tlv/no_checks + ) + +/obj/machinery/airalarm/kitchen_cold_room // Copypasta: to check temperatures. + TLV = list( + "pressure" = new/datum/tlv(ONE_ATMOSPHERE * 0.8, ONE_ATMOSPHERE* 0.9, ONE_ATMOSPHERE * 1.1, ONE_ATMOSPHERE * 1.2), // kPa + "temperature" = new/datum/tlv(T0C-73.15, T0C-63.15, T0C, T0C+10), + /datum/gas/oxygen = new/datum/tlv(16, 19, 135, 140), // Partial pressure, kpa + /datum/gas/nitrogen = new/datum/tlv(-1, -1, 1000, 1000), + /datum/gas/carbon_dioxide = new/datum/tlv(-1, -1, 5, 10), + /datum/gas/miasma = new/datum/tlv/(-1, -1, 2, 5), + /datum/gas/plasma = new/datum/tlv/dangerous, + /datum/gas/nitrous_oxide = new/datum/tlv/dangerous, + /datum/gas/bz = new/datum/tlv/dangerous, + /datum/gas/hypernoblium = new/datum/tlv(-1, -1, 1000, 1000), // Hyper-Noblium is inert and nontoxic + /datum/gas/water_vapor = new/datum/tlv/dangerous, + /datum/gas/tritium = new/datum/tlv/dangerous, + /datum/gas/stimulum = new/datum/tlv(-1, -1, 1000, 1000), // Stimulum has only positive effects + /datum/gas/nitryl = new/datum/tlv/dangerous, + /datum/gas/pluoxium = new/datum/tlv(-1, -1, 1000, 1000) // Unlike oxygen, pluoxium does not fuel plasma/tritium fires + ) + +/obj/machinery/airalarm/unlocked + locked = FALSE + +/obj/machinery/airalarm/engine + name = "engine air alarm" + locked = FALSE + req_access = null + req_one_access = list(ACCESS_ATMOSPHERICS, ACCESS_ENGINE) + +/obj/machinery/airalarm/mixingchamber + name = "chamber air alarm" + locked = FALSE + req_access = null + req_one_access = list(ACCESS_ATMOSPHERICS, ACCESS_TOX, ACCESS_TOX_STORAGE) + +/obj/machinery/airalarm/all_access + name = "all-access air alarm" + desc = "This particular atmos control unit appears to have no access restrictions." + locked = FALSE + req_access = null + req_one_access = null + +/obj/machinery/airalarm/syndicate //general syndicate access + req_access = list(ACCESS_SYNDICATE) + +/obj/machinery/airalarm/directional/north //Pixel offsets get overwritten on New() + dir = SOUTH + pixel_y = 24 + +/obj/machinery/airalarm/directional/south + dir = NORTH + pixel_y = -24 + +/obj/machinery/airalarm/directional/east + dir = WEST + pixel_x = 24 + +/obj/machinery/airalarm/directional/west + dir = EAST + pixel_x = -24 + +//all air alarms in area are connected via magic +/area + var/list/air_vent_names = list() + var/list/air_scrub_names = list() + var/list/air_vent_info = list() + var/list/air_scrub_info = list() + +/obj/machinery/airalarm/Initialize(mapload, ndir, nbuild) + . = ..() + wires = new /datum/wires/airalarm(src) + + if(ndir) + setDir(ndir) + + if(nbuild) + buildstage = 0 + panel_open = TRUE + pixel_x = (dir & 3)? 0 : (dir == 4 ? -24 : 24) + pixel_y = (dir & 3)? (dir == 1 ? -24 : 24) : 0 + + if(name == initial(name)) + name = "[get_area_name(src)] Air Alarm" + + power_change() + set_frequency(frequency) + +/obj/machinery/airalarm/Destroy() + SSradio.remove_object(src, frequency) + qdel(wires) + wires = null + return ..() + +/obj/machinery/airalarm/examine(mob/user) + . = ..() + switch(buildstage) + if(0) + to_chat(user, "It is missing air alarm electronics.") + if(1) + to_chat(user, "It is missing wiring.") + if(2) + to_chat(user, "Alt-click to [locked ? "unlock" : "lock"] the interface.") + +/obj/machinery/airalarm/ui_status(mob/user) + if(user.has_unlimited_silicon_privilege && aidisabled) + to_chat(user, "AI control has been disabled.") + else if(!shorted) + return ..() + return UI_CLOSE + +/obj/machinery/airalarm/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \ + datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state) + ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) + if(!ui) + ui = new(user, src, ui_key, "airalarm", name, 440, 650, master_ui, state) + ui.open() + +/obj/machinery/airalarm/ui_data(mob/user) + var/data = list( + "locked" = locked, + "siliconUser" = user.has_unlimited_silicon_privilege, + "emagged" = (obj_flags & EMAGGED ? 1 : 0), + "danger_level" = danger_level, + ) + + var/area/A = get_area(src) + data["atmos_alarm"] = A.atmosalm + data["fire_alarm"] = A.fire + + var/turf/T = get_turf(src) + var/datum/gas_mixture/environment = T.return_air() + var/datum/tlv/cur_tlv + + data["environment_data"] = list() + var/pressure = environment.return_pressure() + cur_tlv = TLV["pressure"] + data["environment_data"] += list(list( + "name" = "Pressure", + "value" = pressure, + "unit" = "kPa", + "danger_level" = cur_tlv.get_danger_level(pressure) + )) + var/temperature = environment.temperature + cur_tlv = TLV["temperature"] + data["environment_data"] += list(list( + "name" = "Temperature", + "value" = temperature, + "unit" = "K ([round(temperature - T0C, 0.1)]C)", + "danger_level" = cur_tlv.get_danger_level(temperature) + )) + var/total_moles = environment.total_moles() + var/partial_pressure = R_IDEAL_GAS_EQUATION * environment.temperature / environment.volume + for(var/gas_id in environment.gases) + if(!(gas_id in TLV)) // We're not interested in this gas, it seems. + continue + cur_tlv = TLV[gas_id] + data["environment_data"] += list(list( + "name" = GLOB.meta_gas_names[gas_id], + "value" = environment.gases[gas_id] / total_moles * 100, + "unit" = "%", + "danger_level" = cur_tlv.get_danger_level(environment.gases[gas_id] * partial_pressure) + )) + + if(!locked || user.has_unlimited_silicon_privilege) + data["vents"] = list() + for(var/id_tag in A.air_vent_names) + var/long_name = A.air_vent_names[id_tag] + var/list/info = A.air_vent_info[id_tag] + if(!info || info["frequency"] != frequency) + continue + data["vents"] += list(list( + "id_tag" = id_tag, + "long_name" = sanitize(long_name), + "power" = info["power"], + "checks" = info["checks"], + "excheck" = info["checks"]&1, + "incheck" = info["checks"]&2, + "direction" = info["direction"], + "external" = info["external"], + "internal" = info["internal"], + "extdefault"= (info["external"] == ONE_ATMOSPHERE), + "intdefault"= (info["internal"] == 0) + )) + data["scrubbers"] = list() + for(var/id_tag in A.air_scrub_names) + var/long_name = A.air_scrub_names[id_tag] + var/list/info = A.air_scrub_info[id_tag] + if(!info || info["frequency"] != frequency) + continue + data["scrubbers"] += list(list( + "id_tag" = id_tag, + "long_name" = sanitize(long_name), + "power" = info["power"], + "scrubbing" = info["scrubbing"], + "widenet" = info["widenet"], + "filter_types" = info["filter_types"] + )) + data["mode"] = mode + data["modes"] = list() + data["modes"] += list(list("name" = "Filtering - Scrubs out contaminants", "mode" = AALARM_MODE_SCRUBBING, "selected" = mode == AALARM_MODE_SCRUBBING, "danger" = 0)) + data["modes"] += list(list("name" = "Contaminated - Scrubs out ALL contaminants quickly","mode" = AALARM_MODE_CONTAMINATED, "selected" = mode == AALARM_MODE_CONTAMINATED, "danger" = 0)) + data["modes"] += list(list("name" = "Draught - Siphons out air while replacing", "mode" = AALARM_MODE_VENTING, "selected" = mode == AALARM_MODE_VENTING, "danger" = 0)) + data["modes"] += list(list("name" = "Refill - Triple vent output", "mode" = AALARM_MODE_REFILL, "selected" = mode == AALARM_MODE_REFILL, "danger" = 1)) + data["modes"] += list(list("name" = "Cycle - Siphons air before replacing", "mode" = AALARM_MODE_REPLACEMENT, "selected" = mode == AALARM_MODE_REPLACEMENT, "danger" = 1)) + data["modes"] += list(list("name" = "Siphon - Siphons air out of the room", "mode" = AALARM_MODE_SIPHON, "selected" = mode == AALARM_MODE_SIPHON, "danger" = 1)) + data["modes"] += list(list("name" = "Panic Siphon - Siphons air out of the room quickly","mode" = AALARM_MODE_PANIC, "selected" = mode == AALARM_MODE_PANIC, "danger" = 1)) + data["modes"] += list(list("name" = "Off - Shuts off vents and scrubbers", "mode" = AALARM_MODE_OFF, "selected" = mode == AALARM_MODE_OFF, "danger" = 0)) + if(obj_flags & EMAGGED) + data["modes"] += list(list("name" = "Flood - Shuts off scrubbers and opens vents", "mode" = AALARM_MODE_FLOOD, "selected" = mode == AALARM_MODE_FLOOD, "danger" = 1)) + + var/datum/tlv/selected + var/list/thresholds = list() + + selected = TLV["pressure"] + thresholds += list(list("name" = "Pressure", "settings" = list())) + thresholds[thresholds.len]["settings"] += list(list("env" = "pressure", "val" = "min2", "selected" = selected.min2)) + thresholds[thresholds.len]["settings"] += list(list("env" = "pressure", "val" = "min1", "selected" = selected.min1)) + thresholds[thresholds.len]["settings"] += list(list("env" = "pressure", "val" = "max1", "selected" = selected.max1)) + thresholds[thresholds.len]["settings"] += list(list("env" = "pressure", "val" = "max2", "selected" = selected.max2)) + + selected = TLV["temperature"] + thresholds += list(list("name" = "Temperature", "settings" = list())) + thresholds[thresholds.len]["settings"] += list(list("env" = "temperature", "val" = "min2", "selected" = selected.min2)) + thresholds[thresholds.len]["settings"] += list(list("env" = "temperature", "val" = "min1", "selected" = selected.min1)) + thresholds[thresholds.len]["settings"] += list(list("env" = "temperature", "val" = "max1", "selected" = selected.max1)) + thresholds[thresholds.len]["settings"] += list(list("env" = "temperature", "val" = "max2", "selected" = selected.max2)) + + for(var/gas_id in GLOB.meta_gas_names) + if(!(gas_id in TLV)) // We're not interested in this gas, it seems. + continue + selected = TLV[gas_id] + thresholds += list(list("name" = GLOB.meta_gas_names[gas_id], "settings" = list())) + thresholds[thresholds.len]["settings"] += list(list("env" = gas_id, "val" = "min2", "selected" = selected.min2)) + thresholds[thresholds.len]["settings"] += list(list("env" = gas_id, "val" = "min1", "selected" = selected.min1)) + thresholds[thresholds.len]["settings"] += list(list("env" = gas_id, "val" = "max1", "selected" = selected.max1)) + thresholds[thresholds.len]["settings"] += list(list("env" = gas_id, "val" = "max2", "selected" = selected.max2)) + + data["thresholds"] = thresholds + return data + +/obj/machinery/airalarm/ui_act(action, params) + if(..() || buildstage != 2) + return + if((locked && !usr.has_unlimited_silicon_privilege) || (usr.has_unlimited_silicon_privilege && aidisabled)) + return + var/device_id = params["id_tag"] + switch(action) + if("lock") + if(usr.has_unlimited_silicon_privilege && !wires.is_cut(WIRE_IDSCAN)) + locked = !locked + . = TRUE + if("power", "toggle_filter", "widenet", "scrubbing") + send_signal(device_id, list("[action]" = params["val"]), usr) + . = TRUE + if("excheck") + send_signal(device_id, list("checks" = text2num(params["val"])^1), usr) + . = TRUE + if("incheck") + send_signal(device_id, list("checks" = text2num(params["val"])^2), usr) + . = TRUE + if("set_external_pressure", "set_internal_pressure") + var/area/A = get_area(src) + var/target = input("New target pressure:", name, A.air_vent_info[device_id][(action == "set_external_pressure" ? "external" : "internal")]) as num|null + if(!isnull(target) && !..()) + send_signal(device_id, list("[action]" = target), usr) + . = TRUE + if("reset_external_pressure") + send_signal(device_id, list("reset_external_pressure"), usr) + . = TRUE + if("reset_internal_pressure") + send_signal(device_id, list("reset_internal_pressure"), usr) + . = TRUE + if("threshold") + var/env = params["env"] + if(text2path(env)) + env = text2path(env) + + var/name = params["var"] + var/datum/tlv/tlv = TLV[env] + if(isnull(tlv)) + return + var/value = input("New [name] for [env]:", name, tlv.vars[name]) as num|null + if(!isnull(value) && !..()) + if(value < 0) + tlv.vars[name] = -1 + else + tlv.vars[name] = round(value, 0.01) + investigate_log(" treshold value for [env]:[name] was set to [value] by [key_name(usr)]",INVESTIGATE_ATMOS) + . = TRUE + if("mode") + mode = text2num(params["mode"]) + investigate_log("was turned to [get_mode_name(mode)] mode by [key_name(usr)]",INVESTIGATE_ATMOS) + apply_mode() + . = TRUE + if("alarm") + var/area/A = get_area(src) + if(A.atmosalert(2, src)) + post_alert(2) + . = TRUE + if("reset") + var/area/A = get_area(src) + if(A.atmosalert(0, src)) + post_alert(0) + . = TRUE + update_icon() + +/obj/machinery/airalarm/proc/reset(wire) + switch(wire) + if(WIRE_POWER) + if(!wires.is_cut(WIRE_POWER)) + shorted = FALSE + update_icon() + if(WIRE_AI) + if(!wires.is_cut(WIRE_AI)) + aidisabled = FALSE + + +/obj/machinery/airalarm/proc/shock(mob/user, prb) + if((stat & (NOPOWER))) // unpowered, no shock + return 0 + if(!prob(prb)) + return 0 //you lucked out, no shock for you + var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread + s.set_up(5, 1, src) + s.start() //sparks always. + if (electrocute_mob(user, get_area(src), src, 1, TRUE)) + return 1 + else + return 0 + +/obj/machinery/airalarm/proc/refresh_all() + var/area/A = get_area(src) + for(var/id_tag in A.air_vent_names) + var/list/I = A.air_vent_info[id_tag] + if(I && I["timestamp"] + AALARM_REPORT_TIMEOUT / 2 > world.time) + continue + send_signal(id_tag, list("status")) + for(var/id_tag in A.air_scrub_names) + var/list/I = A.air_scrub_info[id_tag] + if(I && I["timestamp"] + AALARM_REPORT_TIMEOUT / 2 > world.time) + continue + send_signal(id_tag, list("status")) + +/obj/machinery/airalarm/proc/set_frequency(new_frequency) + SSradio.remove_object(src, frequency) + frequency = new_frequency + radio_connection = SSradio.add_object(src, frequency, RADIO_TO_AIRALARM) + +/obj/machinery/airalarm/proc/send_signal(target, list/command, mob/user)//sends signal 'command' to 'target'. Returns 0 if no radio connection, 1 otherwise + if(!radio_connection) + return 0 + + var/datum/signal/signal = new(command) + signal.data["tag"] = target + signal.data["sigtype"] = "command" + signal.data["user"] = user + radio_connection.post_signal(src, signal, RADIO_FROM_AIRALARM) + + return 1 + +/obj/machinery/airalarm/proc/get_mode_name(mode_value) + switch(mode_value) + if(AALARM_MODE_SCRUBBING) + return "Filtering" + if(AALARM_MODE_CONTAMINATED) + return "Contaminated" + if(AALARM_MODE_VENTING) + return "Draught" + if(AALARM_MODE_REFILL) + return "Refill" + if(AALARM_MODE_PANIC) + return "Panic Siphon" + if(AALARM_MODE_REPLACEMENT) + return "Cycle" + if(AALARM_MODE_SIPHON) + return "Siphon" + if(AALARM_MODE_OFF) + return "Off" + if(AALARM_MODE_FLOOD) + return "Flood" + +/obj/machinery/airalarm/proc/apply_mode() + var/area/A = get_area(src) + switch(mode) + if(AALARM_MODE_SCRUBBING) + for(var/device_id in A.air_scrub_names) + send_signal(device_id, list( + "power" = 1, + "set_filters" = list(/datum/gas/carbon_dioxide, /datum/gas/miasma), + "scrubbing" = 1, + "widenet" = 0, + )) + for(var/device_id in A.air_vent_names) + send_signal(device_id, list( + "power" = 1, + "checks" = 1, + "set_external_pressure" = ONE_ATMOSPHERE + )) + if(AALARM_MODE_CONTAMINATED) + for(var/device_id in A.air_scrub_names) + send_signal(device_id, list( + "power" = 1, + "set_filters" = list( + /datum/gas/carbon_dioxide, + /datum/gas/miasma, + /datum/gas/plasma, + /datum/gas/water_vapor, + /datum/gas/hypernoblium, + /datum/gas/nitrous_oxide, + /datum/gas/nitryl, + /datum/gas/tritium, + /datum/gas/bz, + /datum/gas/stimulum, + /datum/gas/pluoxium + ), + "scrubbing" = 1, + "widenet" = 1, + )) + for(var/device_id in A.air_vent_names) + send_signal(device_id, list( + "power" = 1, + "checks" = 1, + "set_external_pressure" = ONE_ATMOSPHERE + )) + if(AALARM_MODE_VENTING) + for(var/device_id in A.air_scrub_names) + send_signal(device_id, list( + "power" = 1, + "widenet" = 0, + "scrubbing" = 0 + )) + for(var/device_id in A.air_vent_names) + send_signal(device_id, list( + "power" = 1, + "checks" = 1, + "set_external_pressure" = ONE_ATMOSPHERE*2 + )) + if(AALARM_MODE_REFILL) + for(var/device_id in A.air_scrub_names) + send_signal(device_id, list( + "power" = 1, + "set_filters" = list(/datum/gas/carbon_dioxide, /datum/gas/miasma), + "scrubbing" = 1, + "widenet" = 0, + )) + for(var/device_id in A.air_vent_names) + send_signal(device_id, list( + "power" = 1, + "checks" = 1, + "set_external_pressure" = ONE_ATMOSPHERE * 3 + )) + if(AALARM_MODE_PANIC, + AALARM_MODE_REPLACEMENT) + for(var/device_id in A.air_scrub_names) + send_signal(device_id, list( + "power" = 1, + "widenet" = 1, + "scrubbing" = 0 + )) + for(var/device_id in A.air_vent_names) + send_signal(device_id, list( + "power" = 0 + )) + if(AALARM_MODE_SIPHON) + for(var/device_id in A.air_scrub_names) + send_signal(device_id, list( + "power" = 1, + "widenet" = 0, + "scrubbing" = 0 + )) + for(var/device_id in A.air_vent_names) + send_signal(device_id, list( + "power" = 0 + )) + + if(AALARM_MODE_OFF) + for(var/device_id in A.air_scrub_names) + send_signal(device_id, list( + "power" = 0 + )) + for(var/device_id in A.air_vent_names) + send_signal(device_id, list( + "power" = 0 + )) + if(AALARM_MODE_FLOOD) + for(var/device_id in A.air_scrub_names) + send_signal(device_id, list( + "power" = 0 + )) + for(var/device_id in A.air_vent_names) + send_signal(device_id, list( + "power" = 1, + "checks" = 2, + "set_internal_pressure" = 0 + )) + +/obj/machinery/airalarm/update_icon() + set_light(0) + cut_overlays() + SSvis_overlays.remove_vis_overlay(src, managed_vis_overlays) + if(stat & NOPOWER) + icon_state = "alarm0" + return + + if(stat & BROKEN) + icon_state = "alarmx" + return + + if(panel_open) + switch(buildstage) + if(2) + icon_state = "alarmx" + if(1) + icon_state = "alarm_b2" + if(0) + icon_state = "alarm_b1" + return + + icon_state = "alarm1" + var/overlay_state = AALARM_OVERLAY_OFF + var/area/A = get_area(src) + switch(max(danger_level, A.atmosalm)) + if(0) + add_overlay(AALARM_OVERLAY_GREEN) + overlay_state = AALARM_OVERLAY_GREEN + light_color = LIGHT_COLOR_GREEN + set_light(brightness_on) + if(1) + add_overlay(AALARM_OVERLAY_WARN) + overlay_state = AALARM_OVERLAY_WARN + light_color = LIGHT_COLOR_LAVA + set_light(brightness_on) + if(2) + add_overlay(AALARM_OVERLAY_DANGER) + overlay_state = AALARM_OVERLAY_DANGER + light_color = LIGHT_COLOR_RED + set_light(brightness_on) + + SSvis_overlays.add_vis_overlay(src, icon, overlay_state, ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE, dir) + update_light() + +/obj/machinery/airalarm/process() + if((stat & (NOPOWER|BROKEN)) || shorted) + return + + var/turf/location = get_turf(src) + if(!location) + return + + var/datum/tlv/cur_tlv + + var/datum/gas_mixture/environment = location.return_air() + var/list/env_gases = environment.gases + var/partial_pressure = R_IDEAL_GAS_EQUATION * environment.temperature / environment.volume + + cur_tlv = TLV["pressure"] + var/environment_pressure = environment.return_pressure() + var/pressure_dangerlevel = cur_tlv.get_danger_level(environment_pressure) + + cur_tlv = TLV["temperature"] + var/temperature_dangerlevel = cur_tlv.get_danger_level(environment.temperature) + + var/gas_dangerlevel = 0 + for(var/gas_id in env_gases) + if(!(gas_id in TLV)) // We're not interested in this gas, it seems. + continue + cur_tlv = TLV[gas_id] + gas_dangerlevel = max(gas_dangerlevel, cur_tlv.get_danger_level(env_gases[gas_id] * partial_pressure)) + + GAS_GARBAGE_COLLECT(environment.gases) + + var/old_danger_level = danger_level + danger_level = max(pressure_dangerlevel, temperature_dangerlevel, gas_dangerlevel) + + if(old_danger_level != danger_level) + apply_danger_level() + if(mode == AALARM_MODE_REPLACEMENT && environment_pressure < ONE_ATMOSPHERE * 0.05) + mode = AALARM_MODE_SCRUBBING + apply_mode() + + return + + +/obj/machinery/airalarm/proc/post_alert(alert_level) + var/datum/radio_frequency/frequency = SSradio.return_frequency(alarm_frequency) + + if(!frequency) + return + + var/datum/signal/alert_signal = new(list( + "zone" = get_area_name(src), + "type" = "Atmospheric" + )) + if(alert_level==2) + alert_signal.data["alert"] = "severe" + else if (alert_level==1) + alert_signal.data["alert"] = "minor" + else if (alert_level==0) + alert_signal.data["alert"] = "clear" + + frequency.post_signal(src, alert_signal, range = -1) + +/obj/machinery/airalarm/proc/apply_danger_level() + var/area/A = get_area(src) + + var/new_area_danger_level = 0 + for(var/obj/machinery/airalarm/AA in A) + if (!(AA.stat & (NOPOWER|BROKEN)) && !AA.shorted) + new_area_danger_level = max(new_area_danger_level,AA.danger_level) + if(A.atmosalert(new_area_danger_level,src)) //if area was in normal state or if area was in alert state + post_alert(new_area_danger_level) + + update_icon() + +/obj/machinery/airalarm/attackby(obj/item/W, mob/user, params) + switch(buildstage) + if(2) + if(istype(W, /obj/item/wirecutters) && panel_open && wires.is_all_cut()) + W.play_tool_sound(src) + to_chat(user, "You cut the final wires.") + new /obj/item/stack/cable_coil(loc, 5) + buildstage = 1 + update_icon() + return + else if(istype(W, /obj/item/screwdriver)) // Opening that Air Alarm up. + W.play_tool_sound(src) + panel_open = !panel_open + to_chat(user, "The wires have been [panel_open ? "exposed" : "unexposed"].") + update_icon() + return + else if(istype(W, /obj/item/card/id) || istype(W, /obj/item/pda))// trying to unlock the interface with an ID card + togglelock(user) + else if(panel_open && is_wire_tool(W)) + wires.interact(user) + return + if(1) + if(istype(W, /obj/item/crowbar)) + user.visible_message("[user.name] removes the electronics from [src.name].",\ + "You start prying out the circuit...") + W.play_tool_sound(src) + if (W.use_tool(src, user, 20)) + if (buildstage == 1) + to_chat(user, "You remove the air alarm electronics.") + new /obj/item/electronics/airalarm( src.loc ) + playsound(src.loc, 'sound/items/deconstruct.ogg', 50, 1) + buildstage = 0 + update_icon() + return + + if(istype(W, /obj/item/stack/cable_coil)) + var/obj/item/stack/cable_coil/cable = W + if(cable.get_amount() < 5) + to_chat(user, "You need five lengths of cable to wire the air alarm!") + return + user.visible_message("[user.name] wires the air alarm.", \ + "You start wiring the air alarm...") + if (do_after(user, 20, target = src)) + if (cable.get_amount() >= 5 && buildstage == 1) + cable.use(5) + to_chat(user, "You wire the air alarm.") + wires.repair() + aidisabled = 0 + locked = FALSE + mode = 1 + shorted = 0 + post_alert(0) + buildstage = 2 + update_icon() + return + if(0) + if(istype(W, /obj/item/electronics/airalarm)) + if(user.temporarilyRemoveItemFromInventory(W)) + to_chat(user, "You insert the circuit.") + buildstage = 1 + update_icon() + qdel(W) + return + + if(istype(W, /obj/item/electroadaptive_pseudocircuit)) + var/obj/item/electroadaptive_pseudocircuit/P = W + if(!P.adapt_circuit(user, 25)) + return + user.visible_message("[user] fabricates a circuit and places it into [src].", \ + "You adapt an air alarm circuit and slot it into the assembly.") + buildstage = 1 + update_icon() + return + + if(istype(W, /obj/item/wrench)) + to_chat(user, "You detach \the [src] from the wall.") + W.play_tool_sound(src) + new /obj/item/wallframe/airalarm( user.loc ) + qdel(src) + return + + return ..() + +/obj/machinery/airalarm/AltClick(mob/user) + ..() + if(!user.canUseTopic(src, !issilicon(user)) || !isturf(loc)) + return + else + togglelock(user) + +/obj/machinery/airalarm/proc/togglelock(mob/living/user) + if(stat & (NOPOWER|BROKEN)) + to_chat(user, "It does nothing!") + else + if(src.allowed(usr) && !wires.is_cut(WIRE_IDSCAN)) + locked = !locked + updateUsrDialog() + to_chat(user, "You [ locked ? "lock" : "unlock"] the air alarm interface.") + else + to_chat(user, "Access denied.") + return + +/obj/machinery/airalarm/power_change() + ..() + if(stat & NOPOWER) + set_light(0) + update_icon() + +/obj/machinery/airalarm/emag_act(mob/user) + . = ..() + if(obj_flags & EMAGGED) + return + obj_flags |= EMAGGED + visible_message("Sparks fly out of [src]!", "You emag [src], disabling its safeties.") + playsound(src, "sparks", 50, 1) + return TRUE + +/obj/machinery/airalarm/obj_break(damage_flag) + ..() + update_icon() + set_light(0) + +/obj/machinery/airalarm/deconstruct(disassembled = TRUE) + if(!(flags_1 & NODECONSTRUCT_1)) + new /obj/item/stack/sheet/metal(loc, 2) + var/obj/item/I = new /obj/item/electronics/airalarm(loc) + if(!disassembled) + I.obj_integrity = I.max_integrity * 0.5 + new /obj/item/stack/cable_coil(loc, 3) + qdel(src) + +#undef AALARM_MODE_SCRUBBING +#undef AALARM_MODE_VENTING +#undef AALARM_MODE_PANIC +#undef AALARM_MODE_REPLACEMENT +#undef AALARM_MODE_OFF +#undef AALARM_MODE_FLOOD +#undef AALARM_MODE_SIPHON +#undef AALARM_MODE_CONTAMINATED +#undef AALARM_MODE_REFILL +#undef AALARM_REPORT_TIMEOUT diff --git a/code/modules/cargo/console.dm b/code/modules/cargo/console.dm index b5b9a616d0..1a607b4b96 100644 --- a/code/modules/cargo/console.dm +++ b/code/modules/cargo/console.dm @@ -36,6 +36,7 @@ cat |= EXPORT_EMAG /obj/machinery/computer/cargo/emag_act(mob/user) + . = ..() if(obj_flags & EMAGGED) return user.visible_message("[user] swipes a suspicious card through [src]!", @@ -48,6 +49,8 @@ var/obj/item/circuitboard/computer/cargo/board = circuit board.contraband = TRUE board.obj_flags |= EMAGGED + req_access = list() + return TRUE /obj/machinery/computer/cargo/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \ datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state) diff --git a/code/modules/cargo/expressconsole.dm b/code/modules/cargo/expressconsole.dm index 5288c27ff6..0097346a34 100644 --- a/code/modules/cargo/expressconsole.dm +++ b/code/modules/cargo/expressconsole.dm @@ -54,6 +54,7 @@ ..() /obj/machinery/computer/cargo/express/emag_act(mob/living/user) + . = SEND_SIGNAL(src, COMSIG_ATOM_EMAG_ACT) if(obj_flags & EMAGGED) return user.visible_message("[user] swipes a suspicious card through [src]!", @@ -63,6 +64,8 @@ var/obj/item/circuitboard/computer/cargo/board = circuit board.obj_flags |= EMAGGED packin_up() + req_access = list() + return TRUE /obj/machinery/computer/cargo/express/proc/packin_up() // oh shit, I'm sorry meme_pack_data = list() // sorry for what? diff --git a/code/modules/clothing/glasses/hud.dm b/code/modules/clothing/glasses/hud.dm index a87e95e28c..387aa65d20 100644 --- a/code/modules/clothing/glasses/hud.dm +++ b/code/modules/clothing/glasses/hud.dm @@ -24,11 +24,13 @@ desc = "[desc] The display is flickering slightly." /obj/item/clothing/glasses/hud/emag_act(mob/user) + . = ..() if(obj_flags & EMAGGED) return obj_flags |= EMAGGED to_chat(user, "PZZTTPFFFT") desc = "[desc] The display is flickering slightly." + return TRUE /obj/item/clothing/glasses/hud/health name = "health scanner HUD" diff --git a/code/modules/clothing/masks/hailer.dm b/code/modules/clothing/masks/hailer.dm index f004f07bf5..086d47e8bf 100644 --- a/code/modules/clothing/masks/hailer.dm +++ b/code/modules/clothing/masks/hailer.dm @@ -69,12 +69,14 @@ /obj/item/clothing/mask/gas/sechailer/attack_self() halt() -/obj/item/clothing/mask/gas/sechailer/emag_act(mob/user as mob) - if(safety) - safety = FALSE - to_chat(user, "You silently fry [src]'s vocal circuit with the cryptographic sequencer.") - else + +/obj/item/clothing/mask/gas/sechailer/emag_act(mob/user) + . = ..() + if(!safety) return + safety = FALSE + to_chat(user, "You silently fry [src]'s vocal circuit with the cryptographic sequencer.") + return TRUE /obj/item/clothing/mask/gas/sechailer/verb/halt() set category = "Object" diff --git a/code/modules/holodeck/computer.dm b/code/modules/holodeck/computer.dm index 4ffc10f9c2..6cc11afdf5 100644 --- a/code/modules/holodeck/computer.dm +++ b/code/modules/holodeck/computer.dm @@ -149,6 +149,7 @@ active_power_usage = 50 + spawned.len * 3 + effects.len * 5 /obj/machinery/computer/holodeck/emag_act(mob/user) + . = ..() if(obj_flags & EMAGGED) return if(!LAZYLEN(emag_programs)) @@ -160,6 +161,7 @@ to_chat(user, "Warning. Automatic shutoff and derezing protocols have been corrupted. Please call Nanotrasen maintenance and do not use the simulator.") log_game("[key_name(user)] emagged the Holodeck Control Console") nerf(!(obj_flags & EMAGGED)) + return TRUE /obj/machinery/computer/holodeck/emp_act(severity) . = ..() diff --git a/code/modules/library/lib_machines.dm b/code/modules/library/lib_machines.dm index 699df5de12..ef58943731 100644 --- a/code/modules/library/lib_machines.dm +++ b/code/modules/library/lib_machines.dm @@ -343,8 +343,11 @@ GLOBAL_LIST(cachedbooks) // List of our cached book datums return ..() /obj/machinery/computer/libraryconsole/bookmanagement/emag_act(mob/user) - if(density && !(obj_flags & EMAGGED)) - obj_flags |= EMAGGED + . = ..() + if(!density || obj_flags & EMAGGED) + return + obj_flags |= EMAGGED + return TRUE /obj/machinery/computer/libraryconsole/bookmanagement/Topic(href, href_list) if(..()) diff --git a/code/modules/mining/abandoned_crates.dm b/code/modules/mining/abandoned_crates.dm index 86499e694b..4a0faf69f5 100644 --- a/code/modules/mining/abandoned_crates.dm +++ b/code/modules/mining/abandoned_crates.dm @@ -214,8 +214,11 @@ return ..() /obj/structure/closet/crate/secure/loot/emag_act(mob/user) - if(locked) - boom(user) + . = SEND_SIGNAL(src, COMSIG_ATOM_EMAG_ACT) + if(!locked) + return + boom(user) + return TRUE /obj/structure/closet/crate/secure/loot/togglelock(mob/user) if(locked) diff --git a/code/modules/mining/laborcamp/laborstacker.dm b/code/modules/mining/laborcamp/laborstacker.dm index 4a628c5f34..953da6cbb0 100644 --- a/code/modules/mining/laborcamp/laborstacker.dm +++ b/code/modules/mining/laborcamp/laborstacker.dm @@ -128,9 +128,12 @@ GLOBAL_LIST(labor_sheet_values) qdel(src) /obj/machinery/mineral/labor_claim_console/emag_act(mob/user) - if(!(obj_flags & EMAGGED)) - obj_flags |= EMAGGED - to_chat(user, "PZZTTPFFFT") + . = ..() + if(obj_flags & EMAGGED) + return + obj_flags |= EMAGGED + to_chat(user, "PZZTTPFFFT") + return TRUE /**********************Prisoner Collection Unit**************************/ diff --git a/code/modules/mob/living/silicon/robot/robot_defense.dm b/code/modules/mob/living/silicon/robot/robot_defense.dm index c90c719e8a..0f09b6f62a 100644 --- a/code/modules/mob/living/silicon/robot/robot_defense.dm +++ b/code/modules/mob/living/silicon/robot/robot_defense.dm @@ -92,17 +92,18 @@ /mob/living/silicon/robot/emag_act(mob/user) if(user == src)//To prevent syndieborgs from emagging themselves - return + return FALSE + if(world.time < emag_cooldown) + return FALSE + . = ..() if(!opened)//Cover is closed if(locked) to_chat(user, "You emag the cover lock.") locked = FALSE if(shell) //A warning to Traitors who may not know that emagging AI shells does not slave them. to_chat(user, "[src] seems to be controlled remotely! Emagging the interface may not work as expected.") - else - to_chat(user, "The cover is already unlocked!") - return - if(world.time < emag_cooldown) + return TRUE + to_chat(user, "The cover is already unlocked!") return if(wiresexposed) to_chat(user, "You must unexpose the wires first!") @@ -115,20 +116,24 @@ to_chat(src, "\"[text2ratvar("You will serve Engine above all else")]!\"\n\ ALERT: Subversion attempt denied.") log_game("[key_name(user)] attempted to emag cyborg [key_name(src)], but they serve only Ratvar.") - return + return TRUE if(connected_ai && connected_ai.mind && connected_ai.mind.has_antag_datum(/datum/antagonist/traitor)) to_chat(src, "ALERT: Foreign software execution prevented.") to_chat(connected_ai, "ALERT: Cyborg unit \[[src]] successfully defended against subversion.") log_game("[key_name(user)] attempted to emag cyborg [key_name(src)], but they were slaved to traitor AI [connected_ai].") - return + return TRUE if(shell) //AI shells cannot be emagged, so we try to make it look like a standard reset. Smart players may see through this, however. to_chat(user, "[src] is remotely controlled! Your emag attempt has triggered a system reset instead!") log_game("[key_name(user)] attempted to emag an AI shell belonging to [key_name(src) ? key_name(src) : connected_ai]. The shell has been reset as a result.") ResetModule() - return + return TRUE + INVOKE_ASYNC(src, .proc/beep_boop_rogue_bot, user) + return TRUE + +/mob/living/silicon/robot/proc/beep_boop_rogue_bot(mob/user) SetEmagged(1) SetStun(60) //Borgs were getting into trouble because they would attack the emagger before the new laws were shown lawupdate = 0 diff --git a/code/modules/mob/living/simple_animal/bot/bot.dm b/code/modules/mob/living/simple_animal/bot/bot.dm index 91515e4511..49261d6e38 100644 --- a/code/modules/mob/living/simple_animal/bot/bot.dm +++ b/code/modules/mob/living/simple_animal/bot/bot.dm @@ -187,22 +187,23 @@ qdel(src) /mob/living/simple_animal/bot/emag_act(mob/user) + . = ..() if(locked) //First emag application unlocks the bot's interface. Apply a screwdriver to use the emag again. locked = FALSE emagged = 1 to_chat(user, "You bypass [src]'s controls.") - return - if(!locked && open) //Bot panel is unlocked by ID or emag, and the panel is screwed open. Ready for emagging. - emagged = 2 - remote_disabled = 1 //Manually emagging the bot locks out the AI built in panel. - locked = TRUE //Access denied forever! - bot_reset() - turn_on() //The bot automatically turns on when emagged, unless recently hit with EMP. - to_chat(src, "(#$*#$^^( OVERRIDE DETECTED") - log_combat(user, src, "emagged") - return - else //Bot is unlocked, but the maint panel has not been opened with a screwdriver yet. + return TRUE + if(!open) to_chat(user, "You need to open maintenance panel first!") + return + emagged = 2 + remote_disabled = 1 //Manually emagging the bot locks out the AI built in panel. + locked = TRUE //Access denied forever! + bot_reset() + turn_on() //The bot automatically turns on when emagged, unless recently hit with EMP. + to_chat(src, "(#$*#$^^( OVERRIDE DETECTED") + log_combat(user, src, "emagged") + return TRUE /mob/living/simple_animal/bot/examine(mob/user) ..() diff --git a/code/modules/mob/living/simple_animal/bot/cleanbot.dm b/code/modules/mob/living/simple_animal/bot/cleanbot.dm index e09eb13886..bdffb032a3 100644 --- a/code/modules/mob/living/simple_animal/bot/cleanbot.dm +++ b/code/modules/mob/living/simple_animal/bot/cleanbot.dm @@ -78,7 +78,7 @@ return ..() /mob/living/simple_animal/bot/cleanbot/emag_act(mob/user) - ..() + . = ..() if(emagged == 2) if(user) to_chat(user, "[src] buzzes and beeps.") diff --git a/code/modules/mob/living/simple_animal/bot/ed209bot.dm b/code/modules/mob/living/simple_animal/bot/ed209bot.dm index 0781c2907a..e272878574 100644 --- a/code/modules/mob/living/simple_animal/bot/ed209bot.dm +++ b/code/modules/mob/living/simple_animal/bot/ed209bot.dm @@ -195,7 +195,7 @@ Auto Patrol[]"}, shootAt(user) /mob/living/simple_animal/bot/ed209/emag_act(mob/user) - ..() + . = ..() if(emagged == 2) if(user) to_chat(user, "You short out [src]'s target assessment circuits.") diff --git a/code/modules/mob/living/simple_animal/bot/firebot.dm b/code/modules/mob/living/simple_animal/bot/firebot.dm index 1c2a6393ae..2b52da6821 100644 --- a/code/modules/mob/living/simple_animal/bot/firebot.dm +++ b/code/modules/mob/living/simple_animal/bot/firebot.dm @@ -120,7 +120,7 @@ return dat /mob/living/simple_animal/bot/firebot/emag_act(mob/user) - ..() + . = ..() if(emagged == 1) if(user) to_chat(user, "[src] buzzes and beeps.") diff --git a/code/modules/mob/living/simple_animal/bot/floorbot.dm b/code/modules/mob/living/simple_animal/bot/floorbot.dm index 4709680ad9..396c6de166 100644 --- a/code/modules/mob/living/simple_animal/bot/floorbot.dm +++ b/code/modules/mob/living/simple_animal/bot/floorbot.dm @@ -124,7 +124,7 @@ ..() /mob/living/simple_animal/bot/floorbot/emag_act(mob/user) - ..() + . = ..() if(emagged == 2) if(user) to_chat(user, "[src] buzzes and beeps.") diff --git a/code/modules/mob/living/simple_animal/bot/honkbot.dm b/code/modules/mob/living/simple_animal/bot/honkbot.dm index e069b46e9d..1c19cd82a1 100644 --- a/code/modules/mob/living/simple_animal/bot/honkbot.dm +++ b/code/modules/mob/living/simple_animal/bot/honkbot.dm @@ -127,10 +127,9 @@ Maintenance panel panel is [open ? "opened" : "closed"]"}, ..() /mob/living/simple_animal/bot/honkbot/emag_act(mob/user) - ..() + . = ..() if(emagged == 2) if(user) - user << "You short out [src]'s sound control system. It gives out an evil laugh!!" oldtarget_name = user.name audible_message("[src] gives out an evil laugh!") playsound(src, 'sound/machines/honkbot_evil_laugh.ogg', 75, 1, -1) // evil laughter diff --git a/code/modules/mob/living/simple_animal/bot/medbot.dm b/code/modules/mob/living/simple_animal/bot/medbot.dm index 5eaaaea175..1bff7dc10c 100644 --- a/code/modules/mob/living/simple_animal/bot/medbot.dm +++ b/code/modules/mob/living/simple_animal/bot/medbot.dm @@ -240,7 +240,7 @@ step_to(src, (get_step_away(src,user))) /mob/living/simple_animal/bot/medbot/emag_act(mob/user) - ..() + . = ..() if(emagged == 2) declare_crit = 0 if(user) diff --git a/code/modules/mob/living/simple_animal/bot/mulebot.dm b/code/modules/mob/living/simple_animal/bot/mulebot.dm index 2efdf09f24..1bc7493684 100644 --- a/code/modules/mob/living/simple_animal/bot/mulebot.dm +++ b/code/modules/mob/living/simple_animal/bot/mulebot.dm @@ -115,6 +115,7 @@ return /mob/living/simple_animal/bot/mulebot/emag_act(mob/user) + . = SEND_SIGNAL(src, COMSIG_ATOM_EMAG_ACT) if(emagged < 1) emagged = TRUE if(!open) @@ -122,6 +123,7 @@ to_chat(user, "You [locked ? "lock" : "unlock"] [src]'s controls!") flick("mulebot-emagged", src) playsound(src, "sparks", 100, 0) + return TRUE /mob/living/simple_animal/bot/mulebot/update_icon() if(open) diff --git a/code/modules/mob/living/simple_animal/bot/secbot.dm b/code/modules/mob/living/simple_animal/bot/secbot.dm index b6ef509d54..9572b4dafc 100644 --- a/code/modules/mob/living/simple_animal/bot/secbot.dm +++ b/code/modules/mob/living/simple_animal/bot/secbot.dm @@ -190,7 +190,7 @@ Auto Patrol: []"}, return /mob/living/simple_animal/bot/secbot/emag_act(mob/user) - ..() + . = ..() if(emagged == 2) if(user) to_chat(user, "You short out [src]'s target assessment circuits.") diff --git a/code/modules/modular_computers/computers/item/computer.dm b/code/modules/modular_computers/computers/item/computer.dm index 580374c5c0..db4cdc2ff5 100644 --- a/code/modules/modular_computers/computers/item/computer.dm +++ b/code/modules/modular_computers/computers/item/computer.dm @@ -178,13 +178,13 @@ turn_on(user) /obj/item/modular_computer/emag_act(mob/user) + . = ..() if(obj_flags & EMAGGED) to_chat(user, "\The [src] was already emagged.") - return 0 - else - obj_flags |= EMAGGED - to_chat(user, "You emag \the [src]. It's screen briefly shows a \"OVERRIDE ACCEPTED: New software downloads available.\" message.") - return 1 + return + obj_flags |= EMAGGED + to_chat(user, "You emag \the [src]. It's screen briefly shows a \"OVERRIDE ACCEPTED: New software downloads available.\" message.") + return TRUE /obj/item/modular_computer/examine(mob/user) ..() diff --git a/code/modules/modular_computers/computers/machinery/modular_computer.dm b/code/modules/modular_computers/computers/machinery/modular_computer.dm index 19d3b56046..b3476e7046 100644 --- a/code/modules/modular_computers/computers/machinery/modular_computer.dm +++ b/code/modules/modular_computers/computers/machinery/modular_computer.dm @@ -44,7 +44,9 @@ cpu.attack_ghost(user) /obj/machinery/modular_computer/emag_act(mob/user) - return cpu ? cpu.emag_act(user) : 1 + . = ..() + if(cpu) + . |= cpu.emag_act(user) /obj/machinery/modular_computer/update_icon() cut_overlays() diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm index 7c377ffa22..d837f0d420 100644 --- a/code/modules/power/apc.dm +++ b/code/modules/power/apc.dm @@ -267,7 +267,7 @@ to_chat(user, "There is an integration cog installed!") to_chat(user, "Alt-Click the APC to [ locked ? "unlock" : "lock"] the interface.") - + if(issilicon(user)) to_chat(user, "Ctrl-Click the APC to switch the breaker [ operating ? "off" : "on"].") @@ -747,7 +747,7 @@ if(damage_flag == "melee" && damage_amount < damage_deflection) return 0 . = ..() - + /obj/machinery/power/apc/deconstruct(disassembled = TRUE) if(!(flags_1 & NODECONSTRUCT_1)) if(!(stat & BROKEN)) @@ -759,21 +759,23 @@ update_icon() /obj/machinery/power/apc/emag_act(mob/user) - if(!(obj_flags & EMAGGED) && !malfhack) - if(opened) - to_chat(user, "You must close the cover to swipe an ID card!") - else if(panel_open) - to_chat(user, "You must close the panel first!") - else if(stat & (BROKEN|MAINT)) - to_chat(user, "Nothing happens!") - else - flick("apc-spark", src) - playsound(src, "sparks", 75, 1) - obj_flags |= EMAGGED - locked = FALSE - to_chat(user, "You emag the APC interface.") - update_icon() - + . = ..() + if(obj_flags & EMAGGED || malfhack) + return + if(opened) + to_chat(user, "You must close the cover to swipe an ID card!") + else if(panel_open) + to_chat(user, "You must close the panel first!") + else if(stat & (BROKEN|MAINT)) + to_chat(user, "Nothing happens!") + else + flick("apc-spark", src) + playsound(src, "sparks", 75, 1) + obj_flags |= EMAGGED + locked = FALSE + to_chat(user, "You emag the APC interface.") + update_icon() + return TRUE // attack with hand - remove cell (if cover open) or interact with the APC diff --git a/code/modules/power/port_gen.dm b/code/modules/power/port_gen.dm index 7a6e313cd0..7375a3e17a 100644 --- a/code/modules/power/port_gen.dm +++ b/code/modules/power/port_gen.dm @@ -194,10 +194,12 @@ return ..() /obj/machinery/power/port_gen/pacman/emag_act(mob/user) + . = ..() if(obj_flags & EMAGGED) return obj_flags |= EMAGGED emp_act(EMP_HEAVY) + return TRUE /obj/machinery/power/port_gen/pacman/attack_ai(mob/user) interact(user) diff --git a/code/modules/power/singularity/emitter.dm b/code/modules/power/singularity/emitter.dm index d805713fa6..4d6ede69d1 100644 --- a/code/modules/power/singularity/emitter.dm +++ b/code/modules/power/singularity/emitter.dm @@ -339,12 +339,13 @@ projectile_sound = initial(projectile_sound) /obj/machinery/power/emitter/emag_act(mob/user) + . = ..() if(obj_flags & EMAGGED) return locked = FALSE obj_flags |= EMAGGED - if(user) - user.visible_message("[user.name] emags [src].","You short out the lock.") + user?.visible_message("[user.name] emags [src].","You short out the lock.") + return TRUE /obj/machinery/power/emitter/prototype diff --git a/code/modules/projectiles/pins.dm b/code/modules/projectiles/pins.dm index 05d6367306..da3743f053 100644 --- a/code/modules/projectiles/pins.dm +++ b/code/modules/projectiles/pins.dm @@ -37,10 +37,12 @@ to_chat(user, "This firearm already has a firing pin installed.") /obj/item/firing_pin/emag_act(mob/user) + . = ..() if(obj_flags & EMAGGED) return obj_flags |= EMAGGED to_chat(user, "You override the authentication mechanism.") + return TRUE /obj/item/firing_pin/proc/gun_insert(mob/living/user, obj/item/gun/G) gun = G diff --git a/code/modules/reagents/chemistry/machinery/chem_dispenser.dm b/code/modules/reagents/chemistry/machinery/chem_dispenser.dm index bc998c6657..9a228b28e3 100644 --- a/code/modules/reagents/chemistry/machinery/chem_dispenser.dm +++ b/code/modules/reagents/chemistry/machinery/chem_dispenser.dm @@ -139,12 +139,14 @@ /obj/machinery/chem_dispenser/emag_act(mob/user) + . = ..() if(obj_flags & EMAGGED) to_chat(user, "[src] has no functional safeties to emag.") return to_chat(user, "You short out [src]'s safeties.") dispensable_reagents |= emagged_reagents//add the emagged reagents to the dispensable ones obj_flags |= EMAGGED + return TRUE /obj/machinery/chem_dispenser/ex_act(severity, target) if(severity < 3) diff --git a/code/modules/research/nanites/nanite_remote.dm b/code/modules/research/nanites/nanite_remote.dm index 60dd78cf94..824d033bf4 100644 --- a/code/modules/research/nanites/nanite_remote.dm +++ b/code/modules/research/nanites/nanite_remote.dm @@ -37,6 +37,7 @@ to_chat(user, "Access denied.") /obj/item/nanite_remote/emag_act(mob/user) + . = ..() if(obj_flags & EMAGGED) return to_chat(user, "You override [src]'s ID lock.") @@ -44,6 +45,7 @@ if(locked) locked = FALSE update_icon() + return TRUE /obj/item/nanite_remote/update_icon() . = ..() diff --git a/code/modules/research/rdconsole.dm b/code/modules/research/rdconsole.dm index cb5062904d..a7d7857a24 100644 --- a/code/modules/research/rdconsole.dm +++ b/code/modules/research/rdconsole.dm @@ -184,12 +184,14 @@ Nothing else in the console has ID requirements. ..() /obj/machinery/computer/rdconsole/emag_act(mob/user) - if(!(obj_flags & EMAGGED)) - to_chat(user, "You disable the security protocols[locked? " and unlock the console":""].") - playsound(src, "sparks", 75, 1) - obj_flags |= EMAGGED - locked = FALSE - return ..() + . = ..() + if(obj_flags & EMAGGED) + return + to_chat(user, "You disable the security protocols[locked? " and unlock the console":""].") + playsound(src, "sparks", 75, 1) + obj_flags |= EMAGGED + locked = FALSE + return TRUE /obj/machinery/computer/rdconsole/multitool_act(mob/user, obj/item/multitool/I) var/lathe = linked_lathe && linked_lathe.multitool_act(user, I) diff --git a/code/modules/research/server.dm b/code/modules/research/server.dm index 20e05782ef..b3e114d2ad 100644 --- a/code/modules/research/server.dm +++ b/code/modules/research/server.dm @@ -155,8 +155,10 @@ src.updateUsrDialog() /obj/machinery/computer/rdservercontrol/emag_act(mob/user) + . = ..() if(obj_flags & EMAGGED) return playsound(src, "sparks", 75, 1) obj_flags |= EMAGGED to_chat(user, "You disable the security protocols.") + return TRUE diff --git a/code/modules/shuttle/computer.dm b/code/modules/shuttle/computer.dm index 0c957919a1..946f0fb9a4 100644 --- a/code/modules/shuttle/computer.dm +++ b/code/modules/shuttle/computer.dm @@ -63,11 +63,13 @@ to_chat(usr, "Unable to comply.") /obj/machinery/computer/shuttle/emag_act(mob/user) + . = ..() if(obj_flags & EMAGGED) return req_access = list() obj_flags |= EMAGGED to_chat(user, "You fried the consoles ID checking system.") + return TRUE /obj/machinery/computer/shuttle/proc/connect_to_shuttle(obj/docking_port/mobile/port, obj/docking_port/stationary/dock, idnum, override=FALSE) if(port && (shuttleId == initial(shuttleId) || override)) diff --git a/code/modules/shuttle/emergency.dm b/code/modules/shuttle/emergency.dm index 020b4b29ab..119023d465 100644 --- a/code/modules/shuttle/emergency.dm +++ b/code/modules/shuttle/emergency.dm @@ -134,6 +134,8 @@ . = TRUE /obj/machinery/computer/emergency_shuttle/emag_act(mob/user) + . = ..() + // How did you even get on the shuttle before it go to the station? if(!IS_DOCKED) return @@ -159,6 +161,7 @@ authorized += ID process() + return TRUE /obj/machinery/computer/emergency_shuttle/Destroy() // Our fake IDs that the emag generated are just there for colour @@ -459,10 +462,12 @@ return /obj/machinery/computer/shuttle/pod/emag_act(mob/user) + . = SEND_SIGNAL(src, COMSIG_ATOM_EMAG_ACT) if(obj_flags & EMAGGED) return obj_flags |= EMAGGED to_chat(user, "You fry the pod's alert level checking system.") + return TRUE /obj/machinery/computer/shuttle/pod/connect_to_shuttle(obj/docking_port/mobile/port, obj/docking_port/stationary/dock, idnum, override=FALSE) . = ..() diff --git a/code/modules/shuttle/ferry.dm b/code/modules/shuttle/ferry.dm index 06e38bb3eb..39ab087f9c 100644 --- a/code/modules/shuttle/ferry.dm +++ b/code/modules/shuttle/ferry.dm @@ -12,7 +12,7 @@ /obj/machinery/computer/shuttle/ferry/emag_act(mob/user) if(!allow_emag) to_chat(user, "[src]'s security firewall is far too powerful for you to bypass.") - return FALSE + return SEND_SIGNAL(src, COMSIG_ATOM_EMAG_ACT) return ..() /obj/machinery/computer/shuttle/ferry/attack_ai() diff --git a/code/modules/shuttle/special.dm b/code/modules/shuttle/special.dm index d1435a554c..9bea790957 100644 --- a/code/modules/shuttle/special.dm +++ b/code/modules/shuttle/special.dm @@ -48,7 +48,7 @@ return /obj/machinery/power/emitter/energycannon/magical/emag_act(mob/user) - return + return SEND_SIGNAL(src, COMSIG_ATOM_EMAG_ACT) /obj/structure/table/abductor/wabbajack name = "wabbajack altar" diff --git a/code/modules/station_goals/shield.dm b/code/modules/station_goals/shield.dm index be88d0ecdc..b09dee04c7 100644 --- a/code/modules/station_goals/shield.dm +++ b/code/modules/station_goals/shield.dm @@ -198,9 +198,11 @@ change_meteor_chance(0.5) /obj/machinery/satellite/meteor_shield/emag_act(mob/user) + . = ..() if(obj_flags & EMAGGED) return obj_flags |= EMAGGED to_chat(user, "You access the satellite's debug mode, increasing the chance of meteor strikes.") if(active) change_meteor_chance(4) + return TRUE diff --git a/code/modules/surgery/organs/augments_arms.dm b/code/modules/surgery/organs/augments_arms.dm index 33e62d21e4..2489aa0705 100644 --- a/code/modules/surgery/organs/augments_arms.dm +++ b/code/modules/surgery/organs/augments_arms.dm @@ -185,11 +185,12 @@ zone = BODY_ZONE_L_ARM /obj/item/organ/cyberimp/arm/toolset/emag_act() - if(!(locate(/obj/item/kitchen/knife/combat/cyborg) in items_list)) - to_chat(usr, "You unlock [src]'s integrated knife!") - items_list += new /obj/item/kitchen/knife/combat/cyborg(src) - return 1 - return 0 + . = ..() + if(locate(/obj/item/kitchen/knife/combat/cyborg) in items_list) + return + to_chat(usr, "You unlock [src]'s integrated knife!") + items_list += new /obj/item/kitchen/knife/combat/cyborg(src) + return TRUE /obj/item/organ/cyberimp/arm/esword name = "arm-mounted energy blade" diff --git a/code/modules/vehicles/cars/clowncar.dm b/code/modules/vehicles/cars/clowncar.dm index 63ef4fda5a..e504ea84f2 100644 --- a/code/modules/vehicles/cars/clowncar.dm +++ b/code/modules/vehicles/cars/clowncar.dm @@ -63,11 +63,13 @@ DumpMobs(TRUE) /obj/vehicle/sealed/car/clowncar/emag_act(mob/user) + . = ..() if(obj_flags & EMAGGED) return obj_flags |= EMAGGED to_chat(user, "You scramble the clowncar child safety lock and a panel with 6 colorful buttons appears!") initialize_controller_action_type(/datum/action/vehicle/sealed/RollTheDice, VEHICLE_CONTROL_DRIVE) + return TRUE /obj/vehicle/sealed/car/clowncar/Destroy() playsound(src, 'sound/vehicles/clowncar_fart.ogg', 100) diff --git a/code/modules/vending/_vending.dm b/code/modules/vending/_vending.dm index 410952397d..5165343993 100644 --- a/code/modules/vending/_vending.dm +++ b/code/modules/vending/_vending.dm @@ -65,7 +65,7 @@ IF YOU MODIFY THE PRODUCTS LIST OF A MACHINE, MAKE SURE TO UPDATE ITS RESUPPLY C var/scan_id = 1 var/obj/item/coin/coin var/obj/item/stack/spacecash/bill - + var/global/vending_cache = list() //used for storing the icons of items being vended var/dish_quants = list() //used by the snack machine's custom compartment to count dishes. @@ -306,10 +306,12 @@ IF YOU MODIFY THE PRODUCTS LIST OF A MACHINE, MAKE SURE TO UPDATE ITS RESUPPLY C . = ..() /obj/machinery/vending/emag_act(mob/user) + . = ..() if(obj_flags & EMAGGED) return obj_flags |= EMAGGED to_chat(user, "You short out the product lock on [src].") + return TRUE /obj/machinery/vending/_try_interact(mob/user) if(seconds_electrified && !(stat & NOPOWER)) diff --git a/modular_citadel/code/game/machinery/plasmacases.dm b/modular_citadel/code/game/machinery/plasmacases.dm index ac3621b58a..c45eb48caa 100644 --- a/modular_citadel/code/game/machinery/plasmacases.dm +++ b/modular_citadel/code/game/machinery/plasmacases.dm @@ -19,5 +19,6 @@ return MouseDrop(user) /obj/structure/guncase/plasma/emag_act() - to_chat(usr, "The locking mechanism is fitted with old style parts, The card has no effect.") - return \ No newline at end of file + . = SEND_SIGNAL(src, COMSIG_ATOM_EMAG_ACT) + if(!.) + to_chat(usr, "The locking mechanism is fitted with old style parts, The card has no effect.") \ No newline at end of file diff --git a/modular_citadel/code/modules/cargo/console.dm b/modular_citadel/code/modules/cargo/console.dm index 490f72d1d1..f54a6c577a 100644 --- a/modular_citadel/code/modules/cargo/console.dm +++ b/modular_citadel/code/modules/cargo/console.dm @@ -1,13 +1,9 @@ /obj/machinery/computer/cargo req_access = list(ACCESS_CARGO) - + /obj/machinery/computer/cargo/request req_access = list() -/obj/machinery/computer/cargo/emag_act(mob/user) - req_access = list() - . = ..() - /obj/machinery/computer/cargo/ui_act(action, params, datum/tgui/ui) if(!allowed(usr)) to_chat(usr, "Access denied.") diff --git a/modular_citadel/code/modules/reagents/reagent container/hypospraymkii.dm b/modular_citadel/code/modules/reagents/reagent container/hypospraymkii.dm index 6cd9e1badc..9e7da03f9b 100755 --- a/modular_citadel/code/modules/reagents/reagent container/hypospraymkii.dm +++ b/modular_citadel/code/modules/reagents/reagent container/hypospraymkii.dm @@ -141,12 +141,18 @@ // Gunna allow this for now, still really don't approve - Pooj /obj/item/hypospray/mkii/emag_act(mob/user) + . = ..() + if(obj_flags & EMAGGED) + to_chat(user, "[src] happens to be already overcharged.") + return inject_wait = COMBAT_WAIT_INJECT spray_wait = COMBAT_WAIT_SPRAY spray_self = COMBAT_SELF_INJECT inject_self = COMBAT_SELF_SPRAY penetrates = TRUE to_chat(user, "You overcharge [src]'s control circuit.") + obj_flags |= EMAGGED + return TRUE /obj/item/hypospray/mkii/attack_hand(mob/user) . = ..() //Don't bother changing this or removing it from containers will break.