diff --git a/code/__DEFINES/dcs/signals/signals_atom/signals_atom_x_act.dm b/code/__DEFINES/dcs/signals/signals_atom/signals_atom_x_act.dm
index b9cf29bf2d47..b88753f47d6e 100644
--- a/code/__DEFINES/dcs/signals/signals_atom/signals_atom_x_act.dm
+++ b/code/__DEFINES/dcs/signals/signals_atom/signals_atom_x_act.dm
@@ -20,7 +20,7 @@
#define COMPONENT_CANCEL_BLOB_ACT (1<<0)
///from base of atom/acid_act(): (acidpwr, acid_volume)
#define COMSIG_ATOM_ACID_ACT "atom_acid_act"
-///from base of atom/emag_act(): (/mob/user)
+///from base of atom/emag_act(): (/mob/user, /obj/item/card/emag)
#define COMSIG_ATOM_EMAG_ACT "atom_emag_act"
///! from base of atom/rad_act(intensity, collectable_radiation)
#define COMSIG_ATOM_RAD_ACT "atom_rad_act"
diff --git a/code/__DEFINES/obj_flags.dm b/code/__DEFINES/obj_flags.dm
index 1a71280c7d22..71ef7984b589 100644
--- a/code/__DEFINES/obj_flags.dm
+++ b/code/__DEFINES/obj_flags.dm
@@ -11,6 +11,7 @@
#define USES_TGUI (1<<7) //put on things that use tgui on ui_interact instead of custom/old UI.
#define FROZEN (1<<8)
#define UNIQUE_REDESC (1<<9) // can you customize the description of the thing?
+#define CMAGGED (1<<10)
// If you add new ones, be sure to add them to /obj/Initialize as well for complete mapping support
diff --git a/code/_globalvars/bitfields.dm b/code/_globalvars/bitfields.dm
index c970d848baf4..9bcbf6b2d377 100644
--- a/code/_globalvars/bitfields.dm
+++ b/code/_globalvars/bitfields.dm
@@ -33,6 +33,7 @@ GLOBAL_LIST_INIT(bitfields, list(
"USES_TGUI" = USES_TGUI,
"FROZEN" = FROZEN,
"UNIQUE_REDESC" = UNIQUE_REDESC,
+ "CMAGGED" = CMAGGED,
),
"datum_flags" = list(
"DF_USE_TAG" = DF_USE_TAG,
diff --git a/code/_onclick/ai.dm b/code/_onclick/ai.dm
index e1ed79d14053..bd596b8e165c 100644
--- a/code/_onclick/ai.dm
+++ b/code/_onclick/ai.dm
@@ -131,14 +131,14 @@
/* Airlocks */
/obj/machinery/door/airlock/AICtrlClick() // Bolts doors
- if(obj_flags & EMAGGED)
+ if((obj_flags & EMAGGED) || (obj_flags & CMAGGED))
return
toggle_bolt(usr)
add_hiddenprint(usr)
/obj/machinery/door/airlock/AIAltClick() // Eletrifies doors.
- if(obj_flags & EMAGGED)
+ if((obj_flags & EMAGGED) || (obj_flags & CMAGGED))
return
if(!secondsElectrified)
@@ -147,14 +147,14 @@
shock_restore(usr)
/obj/machinery/door/airlock/AIShiftClick() // Opens and closes doors!
- if(obj_flags & EMAGGED)
+ if((obj_flags & EMAGGED) || (obj_flags & CMAGGED))
return
user_toggle_open(usr)
add_hiddenprint(usr)
/obj/machinery/door/airlock/AICtrlShiftClick() // Sets/Unsets Emergency Access Override
- if(obj_flags & EMAGGED)
+ if((obj_flags & EMAGGED) || (obj_flags & CMAGGED))
return
toggle_emergency(usr)
diff --git a/code/game/atoms.dm b/code/game/atoms.dm
index b0bc53f77efb..1caefc8eda38 100644
--- a/code/game/atoms.dm
+++ b/code/game/atoms.dm
@@ -94,7 +94,6 @@
var/base_pixel_y = 0
///the base icon state used for anything that changes their icon state.
var/base_icon_state
-
///Mobs that are currently do_after'ing this atom, to be cleared from on Destroy()
var/list/targeted_by
@@ -798,10 +797,16 @@
/**
* Respond to an emag being used on our atom
*
- * Default behaviour is to send COMSIG_ATOM_EMAG_ACT and return
+ * Args:
+ * * mob/user: The mob that used the emag. Nullable.
+ * * obj/item/card/emag/emag_card: The emag that was used. Nullable.
+ *
+ * Returns:
+ * TRUE if the emag had any effect, falsey otherwise.
*/
-/atom/proc/emag_act()
- SEND_SIGNAL(src, COMSIG_ATOM_EMAG_ACT)
+/atom/proc/emag_act(mob/user, obj/item/card/emag/emag_card)
+ SHOULD_CALL_PARENT(FALSE) // Emag act should either be: overridden (no signal) or default (signal).
+ return (SEND_SIGNAL(src, COMSIG_ATOM_EMAG_ACT, user, emag_card))
/**
* Respond to a radioactive wave hitting this atom
diff --git a/code/game/machinery/Sleeper.dm b/code/game/machinery/Sleeper.dm
index c7171b87591e..21005c0b3417 100644
--- a/code/game/machinery/Sleeper.dm
+++ b/code/game/machinery/Sleeper.dm
@@ -118,11 +118,12 @@
if(is_operational() && occupant)
open_machine()
-/obj/machinery/sleeper/emag_act(mob/user)
+/obj/machinery/sleeper/emag_act(mob/user, obj/item/card/emag/emag_card)
if(obj_flags & EMAGGED)
- return
+ return FALSE
to_chat(user, span_danger("You disable the chemical injection inhibitors on the sleeper..."))
obj_flags |= EMAGGED
+ return TRUE
/obj/machinery/sleeper/MouseDrop_T(mob/target, mob/user)
if(user.stat || !Adjacent(user) || !user.Adjacent(target) || !iscarbon(target) || !user.IsAdvancedToolUser())
diff --git a/code/game/machinery/airlock_cycle_control.dm b/code/game/machinery/airlock_cycle_control.dm
index fc62172ae40e..852ac542b135 100644
--- a/code/game/machinery/airlock_cycle_control.dm
+++ b/code/game/machinery/airlock_cycle_control.dm
@@ -786,12 +786,13 @@
. = ..()
update_cycle_icon()
-/obj/machinery/advanced_airlock_controller/emag_act(mob/user)
+/obj/machinery/advanced_airlock_controller/emag_act(mob/user, obj/item/card/emag/emag_card)
if(obj_flags & EMAGGED)
- return
+ return FALSE
obj_flags |= EMAGGED
visible_message(span_warning("Sparks fly out of [src]!"), span_notice("You emag [src], disabling its safeties."))
playsound(src, "sparks", 50, 1)
+ return TRUE
/obj/machinery/advanced_airlock_controller/obj_break(damage_flag)
..()
diff --git a/code/game/machinery/announcement_system.dm b/code/game/machinery/announcement_system.dm
index 692bf18f87ac..d833e35e6170 100644
--- a/code/game/machinery/announcement_system.dm
+++ b/code/game/machinery/announcement_system.dm
@@ -160,18 +160,20 @@ GLOBAL_LIST_EMPTY(announcement_systems)
/obj/machinery/announcement_system/proc/act_up() //does funny breakage stuff
if(!obj_break()) // if badmins flag this unbreakable or its already broken
- return
+ return FALSE
arrival = pick("#!@%ERR-34%2 CANNOT LOCAT@# JO# F*LE!", "CRITICAL ERROR 99.", "ERR)#: DA#AB@#E NOT F(*ND!")
newhead = pick("OV#RL()D: \[UNKNOWN??\] DET*#CT)D!", "ER)#R - B*@ TEXT F*O(ND!", "AAS.exe is not responding. NanoOS is searching for a solution to the problem.")
+ return TRUE
/obj/machinery/announcement_system/emp_act(severity)
. = ..()
if(!(stat & (NOPOWER|BROKEN)) && !(. & EMP_PROTECT_SELF))
act_up()
-/obj/machinery/announcement_system/emag_act()
+
+/obj/machinery/announcement_system/emag_act(mob/user, obj/item/card/emag/emag_card)
if(obj_flags & EMAGGED)
- return
+ return FALSE
obj_flags |= EMAGGED
- act_up()
+ return act_up()
diff --git a/code/game/machinery/autolathe.dm b/code/game/machinery/autolathe.dm
index 662394bc1061..387bf22c4320 100644
--- a/code/game/machinery/autolathe.dm
+++ b/code/game/machinery/autolathe.dm
@@ -311,14 +311,15 @@
. = ..()
adjust_hacked(TRUE)
-/obj/machinery/autolathe/emag_act(mob/user)
+/obj/machinery/autolathe/emag_act(mob/user, obj/item/card/emag/emag_card)
if(obj_flags & EMAGGED)
- return
+ return FALSE
obj_flags |= EMAGGED
if(!hacked)
adjust_hacked(TRUE)
playsound(src, "sparks", 75, TRUE, -1)
to_chat(user, span_notice("You use the cryptographic sequencer on [src]."))
+ return TRUE
//Called when the object is constructed by an autolathe
//Has a reference to the autolathe so you can do !!FUN!! things with hacked lathes
diff --git a/code/game/machinery/buttons.dm b/code/game/machinery/buttons.dm
index 0b4197a8ba15..f42cb3761b23 100644
--- a/code/game/machinery/buttons.dm
+++ b/code/game/machinery/buttons.dm
@@ -133,14 +133,15 @@
else
return ..()
-/obj/machinery/button/emag_act(mob/user)
+/obj/machinery/button/emag_act(mob/user, obj/item/card/emag/emag_card)
if(obj_flags & EMAGGED)
- return
+ return FALSE
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)
return attack_hand(user)
diff --git a/code/game/machinery/cloning.dm b/code/game/machinery/cloning.dm
index 298aac00fe45..5b8ded73c998 100644
--- a/code/game/machinery/cloning.dm
+++ b/code/game/machinery/cloning.dm
@@ -435,14 +435,15 @@ GLOBAL_VAR_INIT(clones, 0)
else
return ..()
-/obj/machinery/clonepod/emag_act(mob/user)
+/obj/machinery/clonepod/emag_act(mob/user, obj/item/card/emag/emag_card)
if(!occupant)
- return
+ return FALSE
to_chat(user, span_warning("You corrupt the genetic compiler."))
malfunction()
add_fingerprint(user)
log_cloning("[key_name(user)] emagged [src] at [AREACOORD(src)], causing it to malfunction.")
log_combat(user, src, "emagged", null, occupant ? "[occupant] inside, killing them via malfunction." : null)
+ 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 9150858e5757..e6dbb51f4608 100644
--- a/code/game/machinery/computer/apc_control.dm
+++ b/code/game/machinery/computer/apc_control.dm
@@ -181,12 +181,13 @@
var/setTo = target.operating ? "On" : "Off"
log_activity("Turned APC [target.area.name]'s breaker [setTo]")
-/obj/machinery/computer/apc_control/emag_act(mob/user)
+/obj/machinery/computer/apc_control/emag_act(mob/user, obj/item/card/emag/emag_card)
if(obj_flags & EMAGGED)
- return
+ return FALSE
obj_flags |= EMAGGED
log_game("[key_name(user)] emagged [src] at [AREACOORD(src)]")
playsound(src, "sparks", 50, TRUE)
+ return TRUE
/obj/machinery/computer/apc_control/proc/log_activity(log_text)
if(!should_log)
diff --git a/code/game/machinery/computer/arcade.dm b/code/game/machinery/computer/arcade.dm
index bb6cf07f3ba2..280f8d08f02c 100644
--- a/code/game/machinery/computer/arcade.dm
+++ b/code/game/machinery/computer/arcade.dm
@@ -330,9 +330,9 @@ GLOBAL_LIST_INIT(arcade_prize_pool, list(
return
-/obj/machinery/computer/arcade/battle/emag_act(mob/user)
+/obj/machinery/computer/arcade/battle/emag_act(mob/user, obj/item/card/emag/emag_card)
if(obj_flags & EMAGGED)
- return
+ return FALSE
to_chat(user, span_warning("A mesmerizing Rhumba beat starts playing from the arcade machine's speakers!"))
temp = "If you die in the game, you die for real!"
player_hp = 30
@@ -341,16 +341,11 @@ GLOBAL_LIST_INIT(arcade_prize_pool, list(
enemy_mp = 20
gameover = FALSE
blocked = FALSE
-
obj_flags |= EMAGGED
-
enemy_name = "Cuban Pete"
name = "Outbomb Cuban Pete"
-
-
updateUsrDialog()
-
-
+ return TRUE
// *** THE ORION TRAIL ** //
@@ -1084,14 +1079,15 @@ GLOBAL_LIST_INIT(arcade_prize_pool, list(
name = "The Orion Trail"
desc = "Learn how our ancestors planned to colonize Orion, and have fun in the process!"
-/obj/machinery/computer/arcade/orion_trail/emag_act(mob/user)
+/obj/machinery/computer/arcade/orion_trail/emag_act(mob/user, obj/item/card/emag/emag_card)
if(obj_flags & EMAGGED)
- return
+ return FALSE
to_chat(user, span_notice("You override the cheat code menu and skip to Cheat #[rand(1, 50)]: Realism Mode."))
name = "The Orion Trail: Realism Edition"
desc = "Learn how our ancestors planned to colonize 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 2895becc2d95..2914a3fbdf0b 100755
--- a/code/game/machinery/computer/communications.dm
+++ b/code/game/machinery/computer/communications.dm
@@ -81,14 +81,15 @@
else
return ..()
-/obj/machinery/computer/communications/emag_act(mob/user)
- if (obj_flags & EMAGGED)
- return
+/obj/machinery/computer/communications/emag_act(mob/user, obj/item/card/emag/emag_card)
+ if(obj_flags & EMAGGED)
+ return FALSE
obj_flags |= EMAGGED
if (authenticated)
authorize_access = get_all_accesses()
to_chat(user, span_danger("You scramble the communication routing circuits!"))
playsound(src, 'sound/machines/terminal_alert.ogg', 50, 0)
+ return TRUE
/obj/machinery/computer/communications/ui_act(action, list/params)
var/static/list/approved_states = list(STATE_BUYING_SHUTTLE, STATE_CHANGING_STATUS, STATE_MAIN, STATE_MESSAGES)
diff --git a/code/game/machinery/computer/security.dm b/code/game/machinery/computer/security.dm
index 03ebd90fc623..4c3a77264c0d 100644
--- a/code/game/machinery/computer/security.dm
+++ b/code/game/machinery/computer/security.dm
@@ -846,7 +846,9 @@
//Cancel silicon alert after 1 minute
addtimer(CALLBACK(SILICON, TYPE_PROC_REF(/mob/living/silicon, cancelAlarm),"Burglar",src,alarmed), 600)
-/obj/machinery/computer/secure_data/emag_act(mob/user)
+/obj/machinery/computer/secure_data/emag_act(mob/user, obj/item/card/emag/emag_card)
+ if(logged_in) // What was the point then?
+ return FALSE
var/name
if(ishuman(user))
var/mob/living/carbon/human/human_user = user
@@ -855,18 +857,16 @@
name = "[ID.registered_name]"
else
name = "Unknown"
-
if(issilicon(user))
name = "[user.name]"
-
- if(!logged_in)
- logged_in = TRUE
- to_chat(user, span_warning("You override [src]'s ID lock."))
- trigger_alarm()
- playsound(src, 'sound/effects/alert.ogg', 50, TRUE)
- var/area/A = get_area(loc)
- radio.talk_into(src, "Alert: security breach alarm triggered in [A.map_name]!! Unauthorized access by [name] of [src]!!", sec_freq)
- radio.talk_into(src, "Alert: security breach alarm triggered in [A.map_name]!! Unauthorized access by [name] of [src]!!", command_freq)
+ logged_in = TRUE
+ to_chat(user, span_warning("You override [src]'s ID lock."))
+ trigger_alarm()
+ playsound(src, 'sound/effects/alert.ogg', 50, TRUE)
+ var/area/A = get_area(loc)
+ radio.talk_into(src, "Alert: security breach alarm triggered in [A.map_name]!! Unauthorized access by [name] of [src]!!", sec_freq)
+ radio.talk_into(src, "Alert: security breach alarm triggered in [A.map_name]!! Unauthorized access by [name] of [src]!!", command_freq)
+ return TRUE
/obj/machinery/computer/secure_data/emp_act(severity)
. = ..()
diff --git a/code/game/machinery/decontamination.dm b/code/game/machinery/decontamination.dm
index 878cb7e0d2be..585c4f15992f 100644
--- a/code/game/machinery/decontamination.dm
+++ b/code/game/machinery/decontamination.dm
@@ -169,19 +169,20 @@
s.start()
electrocute_mob(user, src, src, 1, TRUE)
-/obj/machinery/decontamination_unit/emag_act(mob/user)
+/obj/machinery/decontamination_unit/emag_act(mob/user, obj/item/card/emag/emag_card)
if(obj_flags & EMAGGED)
to_chat(user, span_warning("[src] has no functional safeties to emag."))
- return
+ return FALSE
if(!state_open)
if(!panel_open)
to_chat(user, span_warning("Open the panel first."))
- return
+ return FALSE
else
- return
+ return FALSE
to_chat(user, span_warning("You short out [src]'s safeties."))
uv_emagged = TRUE
obj_flags |= EMAGGED
+ return TRUE
/obj/machinery/decontamination_unit/relaymove(mob/user)
if(locked)
@@ -249,7 +250,7 @@
/obj/machinery/decontamination_unit/examine(mob/user)
. = ..()
if(obj_flags & EMAGGED)
- . += span_warning("Its maintenance panel is smoking slightly.")
+ . += span_warning("The maintenance panel is smoking slightly.")
if(in_range(user, src) || isobserver(user))
if (contents.len >= max_n_of_items)
. += span_notice("The status display reads: Inventory full! Please remove items or upgrade the parts of this storage unit.")
diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm
index ecf6c1718e51..7d9f72c774f2 100644
--- a/code/game/machinery/doors/airlock.dm
+++ b/code/game/machinery/doors/airlock.dm
@@ -475,18 +475,24 @@
return
if(ismecha(AM))
var/obj/mecha/mecha = AM
- if(density)
- if(mecha.occupant)
- if(world.time - mecha.occupant.last_bumped <= 10)
- return
- mecha.occupant.last_bumped = world.time
- if(locked && (allowed(mecha.occupant) || check_access_list(mecha.operation_req_access)) && aac)
- aac.request_from_door(src)
+ if(!density) // Somehow bumped into it while it's already open.
+ return
+ var/has_access = (obj_flags & CMAGGED) ? !check_access_list(mecha.operation_req_access) : check_access_list(mecha.operation_req_access)
+ if(mecha.occupant)
+ if(world.time - mecha.occupant.last_bumped <= 10)
return
- if(mecha.occupant && (src.allowed(mecha.occupant) || src.check_access_list(mecha.operation_req_access)))
- open()
- else
- do_animate("deny")
+ mecha.occupant.last_bumped = world.time
+ // If there is an occupant, check their access too.
+ has_access = (obj_flags & CMAGGED) ? cmag_allowed(mecha.occupant) && has_access : allowed(mecha.occupant) || has_access
+ if(aac && locked && has_access)
+ aac.request_from_door(src)
+ return
+ if(has_access)
+ open()
+ else
+ if(obj_flags & CMAGGED)
+ try_play_cmagsound()
+ do_animate("deny")
return
. = ..()
@@ -507,13 +513,14 @@
if(G.siemens_coefficient)//not insulated
new /datum/hallucination/shock(H)
return
+ var/allowed = (obj_flags & CMAGGED) ? cmag_allowed(user) : allowed(user)
if (cyclelinkedairlock)
- if (!shuttledocked && !emergency && !cyclelinkedairlock.shuttledocked && !cyclelinkedairlock.emergency && allowed(user))
+ if (!shuttledocked && !emergency && !cyclelinkedairlock.shuttledocked && !cyclelinkedairlock.emergency && allowed)
if(cyclelinkedairlock.operating)
cyclelinkedairlock.delayed_close_requested = TRUE
else
addtimer(CALLBACK(cyclelinkedairlock, PROC_REF(close)), 2)
- if(locked && allowed(user) && aac)
+ if(locked && aac && allowed)
aac.request_from_door(src)
return
..()
@@ -782,7 +789,9 @@
/obj/machinery/door/airlock/examine(mob/user)
. = ..()
if(obj_flags & EMAGGED)
- . += span_warning("Its access panel is smoking slightly.")
+ . += span_warning("The access panel is smoking slightly.")
+ if(obj_flags & CMAGGED)
+ . += span_warning("The access panel is coated in yellow ooze...")
if(charge && !panel_open && in_range(user, src))
. += span_warning("The maintenance panel seems haphazardly fastened.")
if(charge && panel_open)
@@ -826,10 +835,23 @@
if(!canAIControl(user))
if(canAIHack())
hack(user)
- return
else
to_chat(user, span_warning("Airlock AI control has been blocked with a firewall. Unable to hack."))
- if(obj_flags & EMAGGED)
+ return
+ if((obj_flags & EMAGGED) || (obj_flags & CMAGGED))
+ to_chat(user, span_warning("Unable to interface: Airlock is unresponsive."))
+ return
+ if(detonated)
+ to_chat(user, span_warning("Unable to interface. Airlock control panel damaged."))
+ return
+
+ ui_interact(user)
+
+/obj/machinery/door/airlock/attack_robot(mob/user)
+ if(!canAIControl(user))
+ to_chat(user, span_warning("Airlock AI control has been blocked. Unable to access.")) // Hacking should be AI-exclusive.
+ return
+ if((obj_flags & EMAGGED) || (obj_flags & CMAGGED))
to_chat(user, span_warning("Unable to interface: Airlock is unresponsive."))
return
if(detonated)
@@ -894,7 +916,8 @@
return attack_hand(user)
/obj/machinery/door/airlock/attack_hand(mob/user)
- if(locked && allowed(user) && aac)
+ var/allowed = (obj_flags & CMAGGED) ? cmag_allowed(user) : allowed(user)
+ if(locked && allowed && aac)
aac.request_from_door(src)
. = TRUE
else
@@ -1505,21 +1528,26 @@
//Airlock is passable if it is open (!density), bot has access, and is not bolted shut or powered off)
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(state = AIRLOCK_EMAG, override = TRUE)
- sleep(0.6 SECONDS)
- if(QDELETED(src))
- return
- operating = FALSE
- if(!open())
- update_icon(state = AIRLOCK_CLOSED, override = TRUE)
- obj_flags |= EMAGGED
- lights = FALSE
- locked = TRUE
- loseMainPower()
- loseBackupPower()
+/obj/machinery/door/airlock/emag_act(mob/user, obj/item/card/emag/emag_card)
+ if(operating || !density || !hasPower() || (obj_flags & EMAGGED))
+ return FALSE
+ operating = TRUE
+ update_icon(state = AIRLOCK_EMAG, override = TRUE)
+ addtimer(CALLBACK(src, PROC_REF(finish_emag_act), user, emag_card), 0.6 SECONDS)
+ return TRUE
+
+/obj/machinery/door/airlock/proc/finish_emag_act(mob/user, obj/item/card/emag/emag_card)
+ if(QDELETED(src))
+ return
+ operating = FALSE
+
+ if(!open()) // Something prevented it from being opened. For example, bolted/welded shut.
+ update_icon(state = AIRLOCK_CLOSED, override = TRUE)
+ 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/door.dm b/code/game/machinery/doors/door.dm
index 22cfd5e6c768..20a82701e250 100644
--- a/code/game/machinery/doors/door.dm
+++ b/code/game/machinery/doors/door.dm
@@ -57,6 +57,7 @@
var/unres_sides = 0
// door open speed.
var/open_speed = 0.5 SECONDS
+ COOLDOWN_DECLARE(cmagsound_cooldown)
/obj/machinery/door/examine(mob/user)
. = ..()
@@ -129,24 +130,34 @@
if(ismecha(AM))
var/obj/mecha/mecha = AM
- if(density)
- if(mecha.occupant)
- if(world.time - mecha.occupant.last_bumped <= 10)
- return
- mecha.occupant.last_bumped = world.time
- if(mecha.occupant && (src.allowed(mecha.occupant) || src.check_access_list(mecha.operation_req_access)))
- open()
- else
- do_animate("deny")
+ if(!density)
+ return
+ // If an empty mech somehow bumps into something that it has access to, it should open:
+ var/has_access = (obj_flags & CMAGGED) ? !check_access_list(mecha.operation_req_access) : check_access_list(mecha.operation_req_access)
+ if(mecha.occupant)
+ if(world.time - mecha.occupant.last_bumped <= 10)
+ return
+ mecha.occupant.last_bumped = world.time
+ // If there is an occupant, check their access too.
+ has_access = (obj_flags & CMAGGED) ? cmag_allowed(mecha.occupant) && has_access : allowed(mecha.occupant) || has_access
+ if(has_access)
+ open()
+ else
+ if(obj_flags & CMAGGED)
+ try_play_cmagsound()
+ do_animate("deny")
return
if(isitem(AM))
var/obj/item/I = AM
if(!density || (I.w_class < WEIGHT_CLASS_NORMAL && !LAZYLEN(I.GetAccess())))
return
- if(check_access(I))
+ var/has_access = obj_flags & CMAGGED ? !check_access(I) : check_access(I)
+ if(has_access)
open()
else
+ if(obj_flags & CMAGGED)
+ try_play_cmagsound()
do_animate("deny")
return
@@ -164,18 +175,7 @@
return !opacity //yogs end
/obj/machinery/door/proc/bumpopen(mob/user)
- if(operating)
- return
- src.add_fingerprint(user)
- if(!src.requiresID())
- user = null
-
- if(density && !(obj_flags & EMAGGED))
- if(allowed(user))
- open()
- else
- do_animate("deny")
- return
+ return try_to_activate_door(user)
/obj/machinery/door/attack_hand(mob/user)
. = ..()
@@ -194,14 +194,41 @@
return
if(!requiresID())
user = null //so allowed(user) always succeeds
- if(allowed(user))
- if(density)
- open()
- else
+ if(obj_flags & CMAGGED)
+ if(ishuman(user))
+ var/mob/living/carbon/human/H = user
+ var/obj/item/card/id/idcard = H.get_idcard()
+ if(!idcard?.assignment) // You cannot game the inverted access by taking off your ID or wearing a blank ID.
+ if(density)
+ to_chat(H, span_warning("The airlock speaker chuckles: 'What's wrong, pal? Lost your ID? Nyuk nyuk nyuk!'")) // We also will include this too.
+ try_play_cmagsound()
+ do_animate("deny")
+ return FALSE
+ if(!cmag_allowed(user))
+ try_play_cmagsound()
+ if(density)
+ do_animate("deny")
+ return FALSE
+ if(!density)
close()
+ else
+ open()
return TRUE
- if(density)
- do_animate("deny")
+ if(!allowed(user))
+ if(density)
+ do_animate("deny")
+ return FALSE
+
+ if(!density)
+ close()
+ else
+ open()
+ return TRUE
+
+/obj/machinery/door/proc/try_play_cmagsound()
+ if(COOLDOWN_FINISHED(src, cmagsound_cooldown))
+ playsound(loc, 'sound/machines/honkbot_evil_laugh.ogg', 25, TRUE, ignore_walls = FALSE)
+ COOLDOWN_START(src, cmagsound_cooldown, 1 SECONDS)
/obj/machinery/door/allowed(mob/M)
if(emergency)
@@ -210,6 +237,12 @@
return TRUE
return ..()
+/// Returns the opposite of '/allowed', but makes exceptions for things like IsAdminGhost().
+/obj/machinery/door/proc/cmag_allowed(mob/M)
+ if(IsAdminGhost(M))
+ return TRUE
+ return !allowed(M)
+
/obj/machinery/door/proc/unrestricted_side(mob/M) //Allows for specific side of airlocks to be unrestrected (IE, can exit maint freely, but need access to enter)
return get_dir(src, M) & unres_sides
diff --git a/code/game/machinery/doors/unpowered.dm b/code/game/machinery/doors/unpowered.dm
index 4ff4bd15d714..0f7fd4ec4da7 100644
--- a/code/game/machinery/doors/unpowered.dm
+++ b/code/game/machinery/doors/unpowered.dm
@@ -13,7 +13,7 @@
else
return ..()
-/obj/machinery/door/unpowered/emag_act()
+/obj/machinery/door/unpowered/emag_act(mob/user, obj/item/card/emag/emag_card)
return
/obj/machinery/door/unpowered/shuttle
@@ -22,4 +22,4 @@
icon_state = "door1"
opacity = 1
density = TRUE
- explosion_block = 1
\ No newline at end of file
+ explosion_block = 1
diff --git a/code/game/machinery/doors/windowdoor.dm b/code/game/machinery/doors/windowdoor.dm
index 834aa255a5e4..edb6ef9f4a75 100644
--- a/code/game/machinery/doors/windowdoor.dm
+++ b/code/game/machinery/doors/windowdoor.dm
@@ -65,17 +65,22 @@
close()
/obj/machinery/door/window/Bumped(atom/movable/AM)
- if( operating || !density )
+ if(operating || !density)
return
- if (!( ismob(AM) ))
+ if(!(ismob(AM)))
if(ismecha(AM))
var/obj/mecha/mecha = AM
- if(mecha.occupant && allowed(mecha.occupant))
+ var/has_access = (obj_flags & CMAGGED) ? !check_access_list(mecha.operation_req_access) : check_access_list(mecha.operation_req_access)
+ if(mecha.occupant) // If there is an occupant, check their access too.
+ has_access = (obj_flags & CMAGGED) ? cmag_allowed(mecha.occupant) && has_access : allowed(mecha.occupant) || has_access
+ if(has_access)
open_and_close()
- else
- do_animate("deny")
+ return
+ if(obj_flags & CMAGGED)
+ try_play_cmagsound()
+ do_animate("deny")
return
- if (!( SSticker ))
+ if(!(SSticker))
return
var/mob/M = AM
if(M.restrained() || ((isdrone(M) || iscyborg(M)) && M.stat))
@@ -89,11 +94,13 @@
if(!requiresID())
user = null
- if(allowed(user))
+ var/allowed = (obj_flags & CMAGGED) ? cmag_allowed(user) : allowed(user)
+ if(allowed)
open_and_close()
- else
- do_animate("deny")
- return
+ return
+ if(obj_flags & CMAGGED)
+ try_play_cmagsound()
+ do_animate("deny")
/obj/machinery/door/window/CanAllowThrough(atom/movable/mover, turf/target)
. = ..()
@@ -209,16 +216,28 @@
take_damage(round(exposed_volume / 200), BURN, 0, 0)
..()
-/obj/machinery/door/window/emag_act(mob/user)
- if(!operating && density && !(obj_flags & EMAGGED))
- obj_flags |= EMAGGED
- operating = TRUE
- flick("[base_state]spark", src)
- playsound(src, "sparks", 75, 1)
- sleep(0.6 SECONDS)
- operating = FALSE
- desc += "
[span_warning("Its access panel is smoking slightly.")]"
- open(2)
+/obj/machinery/door/window/emag_act(mob/user, obj/item/card/emag/emag_card)
+ if(operating || !density || (obj_flags & CMAGGED))
+ return FALSE
+ obj_flags |= EMAGGED
+ operating = TRUE
+ flick("[base_state]spark", src)
+ playsound(src, "sparks", 75, 1)
+ addtimer(CALLBACK(src, PROC_REF(finish_emag_act), user, emag_card), 0.6 SECONDS)
+ return TRUE
+
+/obj/machinery/door/window/proc/finish_emag_act()
+ if(QDELETED(src))
+ return
+ operating = FALSE
+ open(2)
+
+/obj/machinery/door/window/examine(mob/user)
+ . = ..()
+ if(obj_flags & EMAGGED)
+ . += span_warning("The access panel is smoking slightly.")
+ if(obj_flags & CMAGGED)
+ . += span_warning("The access panel is coated in yellow ooze...")
/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 1a2fb972d1d7..ff8bcd91022a 100644
--- a/code/game/machinery/embedded_controller/access_controller.dm
+++ b/code/game/machinery/embedded_controller/access_controller.dm
@@ -25,15 +25,16 @@
/obj/machinery/doorButtons/LateInitialize()
findObjsByTag()
-/obj/machinery/doorButtons/emag_act(mob/user)
+/obj/machinery/doorButtons/emag_act(mob/user, obj/item/card/emag/emag_card)
if(obj_flags & EMAGGED)
- return
+ return FALSE
obj_flags |= EMAGGED
req_access = list()
req_one_access = list()
playsound(src, "sparks", 100, 1)
to_chat(user, span_warning("You short out the access controller."))
-
+ return TRUE
+
/obj/machinery/doorButtons/proc/removeMe()
return
diff --git a/code/game/machinery/fat_sucker.dm b/code/game/machinery/fat_sucker.dm
index 729601badbdf..97cbb9198d9c 100644
--- a/code/game/machinery/fat_sucker.dm
+++ b/code/game/machinery/fat_sucker.dm
@@ -203,10 +203,11 @@
if(default_deconstruction_crowbar(I))
return TRUE
-/obj/machinery/fat_sucker/emag_act(mob/living/user)
+/obj/machinery/fat_sucker/emag_act(mob/user, obj/item/card/emag/emag_card)
if(obj_flags & EMAGGED)
- return
+ return FALSE
+ obj_flags |= EMAGGED
start_at = 100
stop_at = 0
to_chat(user, span_notice("You remove the access restrictions and lower the automatic ejection threshold!"))
- obj_flags |= EMAGGED
+ return TRUE
diff --git a/code/game/machinery/firealarm.dm b/code/game/machinery/firealarm.dm
index cb06f9a4c90c..23f9934c3181 100644
--- a/code/game/machinery/firealarm.dm
+++ b/code/game/machinery/firealarm.dm
@@ -104,15 +104,16 @@
if(prob(50 / severity))
alarm()
-/obj/machinery/firealarm/emag_act(mob/user)
+/obj/machinery/firealarm/emag_act(mob/user, obj/item/card/emag/emag_card)
if(obj_flags & EMAGGED)
- return
+ return FALSE
obj_flags |= EMAGGED
update_appearance(UPDATE_ICON)
if(user)
user.visible_message(span_warning("Sparks fly out of [src]!"),
span_notice("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)
var/turf/open/T = get_turf(src)
diff --git a/code/game/machinery/gulag_item_reclaimer.dm b/code/game/machinery/gulag_item_reclaimer.dm
index 428b2e6f4f09..316db99bf7ee 100644
--- a/code/game/machinery/gulag_item_reclaimer.dm
+++ b/code/game/machinery/gulag_item_reclaimer.dm
@@ -23,11 +23,12 @@
inserted_id = null
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/machinery/gulag_item_reclaimer/emag_act(mob/user, obj/item/card/emag/emag_card)
+ if(obj_flags & EMAGGED)
+ return FALSE
obj_flags |= EMAGGED
+ req_access = list() // Emagging lets anyone reclaim all the items.
+ return TRUE
/obj/machinery/gulag_item_reclaimer/attackby(obj/item/I, mob/user)
if(istype(I, /obj/item/card/id/prisoner))
diff --git a/code/game/machinery/harvester.dm b/code/game/machinery/harvester.dm
index 0cad7fb217b3..427f4ff9de99 100644
--- a/code/game/machinery/harvester.dm
+++ b/code/game/machinery/harvester.dm
@@ -156,12 +156,13 @@
visible_message(span_notice("[usr] pries open \the [src]."), span_notice("You pry open [src]."))
open_machine()
-/obj/machinery/harvester/emag_act(mob/user)
+/obj/machinery/harvester/emag_act(mob/user, obj/item/card/emag/emag_card)
if(obj_flags & EMAGGED)
- return
+ return FALSE
obj_flags |= EMAGGED
allow_living = TRUE
to_chat(user, span_warning("You overload [src]'s lifesign scanners."))
+ return TRUE
/obj/machinery/harvester/container_resist(mob/living/user)
if(!harvesting)
diff --git a/code/game/machinery/lightswitch.dm b/code/game/machinery/lightswitch.dm
index d930835cfb75..bccc9137bd39 100644
--- a/code/game/machinery/lightswitch.dm
+++ b/code/game/machinery/lightswitch.dm
@@ -76,11 +76,12 @@
electrocute_mob(user, get_area(src), src, 0.7, TRUE)
-/obj/machinery/light_switch/emag_act(mob/user)
+/obj/machinery/light_switch/emag_act(mob/user, obj/item/card/emag/emag_card)
if(obj_flags & EMAGGED)
to_chat(user, span_warning("Nothing new seems to happen when you swipe the emag."))
- return
+ return FALSE
to_chat(user, span_notice("You swipe the emag on the light switch. "))
if(user.can_hear())
to_chat(user, span_notice("The light switch gives off a soft hum."))
obj_flags |= EMAGGED
+ return TRUE
diff --git a/code/game/machinery/limbgrower.dm b/code/game/machinery/limbgrower.dm
index 0c0a1d3548a8..54287ec7a5bd 100644
--- a/code/game/machinery/limbgrower.dm
+++ b/code/game/machinery/limbgrower.dm
@@ -302,9 +302,9 @@
return TRUE
/// Emagging a limbgrower allows you to build synthetic armblades.
-/obj/machinery/limbgrower/emag_act(mob/user)
+/obj/machinery/limbgrower/emag_act(mob/user, obj/item/card/emag/emag_card)
if(obj_flags & EMAGGED)
- return
+ return FALSE
for(var/design_id in SSresearch.techweb_designs)
var/datum/design/found_design = SSresearch.techweb_design_by_id(design_id)
if((found_design.build_type & LIMBGROWER) && ("emagged" in found_design.category))
@@ -312,3 +312,4 @@
to_chat(user, span_warning("A warning flashes onto the screen, stating that safety overrides have been deactivated!"))
obj_flags |= EMAGGED
update_static_data(user)
+ return TRUE
diff --git a/code/game/machinery/medical_kiosk.dm b/code/game/machinery/medical_kiosk.dm
index 06c1e2b4bd4d..5b3d25dab013 100644
--- a/code/game/machinery/medical_kiosk.dm
+++ b/code/game/machinery/medical_kiosk.dm
@@ -135,10 +135,9 @@
qdel(scanner_wand)
return ..()
-/obj/machinery/medical_kiosk/emag_act(mob/user)
- ..()
+/obj/machinery/medical_kiosk/emag_act(mob/user, obj/item/card/emag/emag_card)
if(obj_flags & EMAGGED)
- return
+ return FALSE
if(user)
user.visible_message("[user] waves a suspicious card by the [src]'s biometric scanner!",
"You overload the sensory electronics, the diagnostic readouts start jittering across the screen..")
@@ -146,6 +145,7 @@
var/obj/item/circuitboard/computer/cargo/board = circuit
board.obj_flags |= EMAGGED //Mirrors emag status onto the board as well.
pandemonium = TRUE
+ return TRUE
/obj/machinery/medical_kiosk/examine(mob/user)
. = ..()
diff --git a/code/game/machinery/porta_turret/portable_turret.dm b/code/game/machinery/porta_turret/portable_turret.dm
index c587a14a66e0..f8b8930c2981 100644
--- a/code/game/machinery/porta_turret/portable_turret.dm
+++ b/code/game/machinery/porta_turret/portable_turret.dm
@@ -276,18 +276,22 @@
else
return ..()
-/obj/machinery/porta_turret/emag_act(mob/user)
+/obj/machinery/porta_turret/emag_act(mob/user, obj/item/card/emag/emag_card)
if(obj_flags & EMAGGED)
- return
+ return FALSE
to_chat(user, span_warning("You short out [src]'s threat assessment circuits."))
visible_message("[src] hums oddly...")
obj_flags |= EMAGGED
controllock = TRUE
on = FALSE //turns off the turret temporarily
update_appearance(UPDATE_ICON)
- sleep(6 SECONDS) //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
+ addtimer(CALLBACK(src, PROC_REF(finish_emag_act)), 6 SECONDS) // 6 seconds to get away.
+ return TRUE
+/obj/machinery/porta_turret/proc/finish_emag_act()
+ if(QDELETED(src))
+ return
+ on = TRUE // Turns it back on. The cover popUp() popDown() are automatically called in process(), no need to define it here.
/obj/machinery/porta_turret/emp_act(severity)
. = ..()
@@ -869,14 +873,15 @@
else
to_chat(user, span_warning("Access denied."))
-/obj/machinery/turretid/emag_act(mob/user)
+/obj/machinery/turretid/emag_act(mob/user, obj/item/card/emag/emag_card)
if(obj_flags & EMAGGED)
- return
+ return FALSE
to_chat(user, span_danger("You short out the turret controls' access analysis module."))
obj_flags |= EMAGGED
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 fcfdad3df641..58772c7d8fe4 100644
--- a/code/game/machinery/porta_turret/portable_turret_cover.dm
+++ b/code/game/machinery/porta_turret/portable_turret_cover.dm
@@ -87,11 +87,17 @@
/obj/machinery/porta_turret_cover/can_be_overridden()
. = 0
-/obj/machinery/porta_turret_cover/emag_act(mob/user)
- if(!(parent_turret.obj_flags & EMAGGED))
- to_chat(user, span_notice("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
+/obj/machinery/porta_turret_cover/emag_act(mob/user, obj/item/card/emag/emag_card)
+ if((parent_turret.obj_flags & EMAGGED))
+ return FALSE
+ to_chat(user, span_notice("You short out [parent_turret]'s threat assessment circuits."))
+ visible_message("[parent_turret] hums oddly...")
+ parent_turret.obj_flags |= EMAGGED
+ parent_turret.on = FALSE
+ addtimer(CALLBACK(src, PROC_REF(finish_emag_act)), 4 SECONDS) // 4 seconds to get away.
+ return TRUE
+
+/obj/machinery/porta_turret_cover/proc/finish_emag_act()
+ if(QDELETED(parent_turret))
+ return
+ parent_turret.on = TRUE
diff --git a/code/game/machinery/recycler.dm b/code/game/machinery/recycler.dm
index 1611bef65ea3..e9fdd712afde 100644
--- a/code/game/machinery/recycler.dm
+++ b/code/game/machinery/recycler.dm
@@ -61,16 +61,17 @@
return
return ..()
-/obj/machinery/recycler/emag_act(mob/user)
+/obj/machinery/recycler/emag_act(mob/user, obj/item/card/emag/emag_card)
if(obj_flags & EMAGGED)
- return
+ return FALSE
obj_flags |= EMAGGED
if(safety_mode)
safety_mode = FALSE
update_appearance(UPDATE_ICON)
playsound(src, "sparks", 75, TRUE, -1)
to_chat(user, span_notice("You use the cryptographic sequencer on [src]."))
-
+ return TRUE
+
/obj/machinery/recycler/update_icon_state()
. = ..()
var/is_powered = !(stat & (BROKEN|NOPOWER))
diff --git a/code/game/machinery/scan_gate.dm b/code/game/machinery/scan_gate.dm
index 046557a8814c..4f47a96e6c34 100644
--- a/code/game/machinery/scan_gate.dm
+++ b/code/game/machinery/scan_gate.dm
@@ -82,13 +82,14 @@
else
return ..()
-/obj/machinery/scanner_gate/emag_act(mob/user)
+/obj/machinery/scanner_gate/emag_act(mob/user, obj/item/card/emag/emag_card)
if(obj_flags & EMAGGED)
- return
+ return FALSE
locked = FALSE
req_access = list()
obj_flags |= EMAGGED
to_chat(user, span_notice("You fry the ID checking system."))
+ return TRUE
/obj/machinery/scanner_gate/proc/perform_scan(mob/living/M)
var/beep = FALSE
diff --git a/code/game/machinery/shieldgen.dm b/code/game/machinery/shieldgen.dm
index 332e2de1ef04..00b2dd57f2a7 100644
--- a/code/game/machinery/shieldgen.dm
+++ b/code/game/machinery/shieldgen.dm
@@ -194,14 +194,15 @@
else
return ..()
-/obj/machinery/shieldgen/emag_act(mob/user)
+/obj/machinery/shieldgen/emag_act(mob/user, obj/item/card/emag/emag_card)
if(obj_flags & EMAGGED)
to_chat(user, span_warning("The access controller is damaged!"))
- return
+ return FALSE
obj_flags |= EMAGGED
locked = FALSE
playsound(src, "sparks", 100, 1)
to_chat(user, span_warning("You short out the access controller."))
+ return TRUE
/obj/machinery/shieldgen/update_icon_state()
. = ..()
@@ -387,14 +388,15 @@
update_activity()
add_fingerprint(user)
-/obj/machinery/shieldwallgen/emag_act(mob/user)
+/obj/machinery/shieldwallgen/emag_act(mob/user, obj/item/card/emag/emag_card)
if(obj_flags & EMAGGED)
to_chat(user, span_warning("The access controller is damaged!"))
- return
+ return FALSE
obj_flags |= EMAGGED
locked = FALSE
playsound(src, "sparks", 100, 1)
to_chat(user, span_warning("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 265fd3106a48..dfa0d85f206d 100644
--- a/code/game/machinery/slotmachine.dm
+++ b/code/game/machinery/slotmachine.dm
@@ -119,14 +119,15 @@
else
return ..()
-/obj/machinery/computer/slot_machine/emag_act()
+/obj/machinery/computer/slot_machine/emag_act(mob/user, obj/item/card/emag/emag_card)
if(obj_flags & EMAGGED)
- return
+ return FALSE
obj_flags |= EMAGGED
var/datum/effect_system/spark_spread/spark_system = new /datum/effect_system/spark_spread()
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/stasis.dm b/code/game/machinery/stasis.dm
index 401360aa8d1b..0b3068846a59 100644
--- a/code/game/machinery/stasis.dm
+++ b/code/game/machinery/stasis.dm
@@ -209,9 +209,10 @@
else
..()
-/obj/machinery/stasis/emag_act(mob/user)
+/obj/machinery/stasis/emag_act(mob/user, obj/item/card/emag/emag_card)
if(obj_flags & EMAGGED)
to_chat(user, span_warning("The stasis bed's safeties are already overridden!"))
- return
+ return FALSE
to_chat(user, span_notice("You override the stasis bed's safeties!"))
obj_flags |= EMAGGED
+ return TRUE
diff --git a/code/game/machinery/telecomms/computers/message.dm b/code/game/machinery/telecomms/computers/message.dm
index 374fd9f2ae09..715140a1cdf0 100644
--- a/code/game/machinery/telecomms/computers/message.dm
+++ b/code/game/machinery/telecomms/computers/message.dm
@@ -47,22 +47,23 @@
else
return ..()
-/obj/machinery/computer/message_monitor/emag_act(mob/user)
+/obj/machinery/computer/message_monitor/emag_act(mob/user, obj/item/card/emag/emag_card)
if(obj_flags & EMAGGED)
- return
- if(!isnull(linkedServer))
- obj_flags |= EMAGGED
- screen = MSG_MON_SCREEN_HACKED
- 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_REF(UnmagConsole)), time)
- message = rebootmsg
- else
+ return FALSE
+ if(isnull(linkedServer))
to_chat(user, span_notice("A no server error appears on the screen."))
+ return FALSE
+ obj_flags |= EMAGGED
+ screen = MSG_MON_SCREEN_HACKED
+ 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_REF(UnmagConsole)), time)
+ message = rebootmsg
+ return TRUE
/obj/machinery/computer/message_monitor/New()
..()
diff --git a/code/game/machinery/telecomms/telecomunications.dm b/code/game/machinery/telecomms/telecomunications.dm
index c9f897d4d1e1..6bf5c01110be 100644
--- a/code/game/machinery/telecomms/telecomunications.dm
+++ b/code/game/machinery/telecomms/telecomunications.dm
@@ -199,7 +199,8 @@ GLOBAL_LIST_EMPTY(telecomms_list)
/obj/machinery/telecomms/proc/de_emp()
stat &= ~EMPED
-/obj/machinery/telecomms/emag_act()
+/obj/machinery/telecomms/emag_act(mob/user, obj/item/card/emag/emag_card)
obj_flags |= EMAGGED
visible_message(span_notice("Sparks fly out of the [src]!"))
traffic += 50
+ return TRUE
diff --git a/code/game/mecha/mech_fabricator.dm b/code/game/mecha/mech_fabricator.dm
index e5e59901c37b..02c698f74fe1 100644
--- a/code/game/mecha/mech_fabricator.dm
+++ b/code/game/mecha/mech_fabricator.dm
@@ -767,15 +767,17 @@
return FALSE
return TRUE
-/obj/machinery/mecha_part_fabricator/emag_act(mob/user)
+/obj/machinery/mecha_part_fabricator/emag_act(mob/user, obj/item/card/emag/emag_card)
if(obj_flags & EMAGGED)
to_chat(user, span_warning("[src] has no functional safeties to emag."))
- return
+ return FALSE
do_sparks(1, FALSE, src)
to_chat(user, span_notice("You short out [src]'s safeties."))
authorization_override = TRUE
obj_flags |= EMAGGED
update_static_data(user)
+ return TRUE
+
/obj/machinery/mecha_part_fabricator/maint
link_on_init = FALSE
diff --git a/code/game/objects/items/RSF.dm b/code/game/objects/items/RSF.dm
index 6a36a7cb64e1..dce2f155e9e7 100644
--- a/code/game/objects/items/RSF.dm
+++ b/code/game/objects/items/RSF.dm
@@ -182,12 +182,13 @@ RSF
/obj/item/rsf/cookiesynth/attackby()
return
-/obj/item/rsf/cookiesynth/emag_act(mob/user)
+/obj/item/rsf/cookiesynth/emag_act(mob/user, obj/item/card/emag/emag_card)
obj_flags ^= EMAGGED
if(obj_flags & EMAGGED)
to_chat(user, span_warning("You short out [src]'s reagent safety checker!"))
else
to_chat(user, span_warning("You reset [src]'s reagent safety checker!"))
+ return TRUE
/obj/item/rsf/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 eb4abd2b6701..9a233ed619da 100644
--- a/code/game/objects/items/cards_ids.dm
+++ b/code/game/objects/items/cards_ids.dm
@@ -67,10 +67,14 @@
lefthand_file = 'icons/mob/inhands/equipment/idcards_lefthand.dmi'
righthand_file = 'icons/mob/inhands/equipment/idcards_righthand.dmi'
item_flags = NO_MAT_REDEMPTION | NOBLUDGEON
- var/max_charges = 5 // How many charges can the emag hold?
- var/charges = 5 // How many charges does the emag start with?
- var/recharge_rate = 0.4 // How fast charges are regained (per second)
- var/prox_check = TRUE //If the emag requires you to be in range
+ /// How many charges can the emag hold?
+ var/max_charges = 5
+ /// How many charges does the emag start with?
+ var/charges = 5
+ /// How fast (in seconds) does charges increase by 1?
+ var/recharge_rate = 0.4
+ /// Does usage require you to be in range?
+ var/prox_check = TRUE
/obj/item/card/emag/Initialize(mapload)
. = ..()
@@ -104,13 +108,14 @@
. = ..()
var/atom/A = target
if(!proximity && prox_check)
- return
+ return
if(charges < 1)
to_chat(user, span_danger("\The [src] is still recharging!"))
return
log_combat(user, A, "attempted to emag")
charges--
- A.emag_act(user)
+ if(!A.emag_act(user, src) && ((charges + 1) > max_charges)) // This is here because some emag_act use sleep and that could mess things up.
+ charges++ // No charge usage if they fail (likely because either no interaction or already emagged).
/obj/item/card/emag/bluespace
name = "bluespace cryptographic sequencer"
@@ -137,23 +142,97 @@
emagging = TRUE
if(do_after(user, rand(5, 10) SECONDS, target))
charges--
- if (prob(40))
+ if(prob(40))
to_chat(user, span_notice("[src] emits a puff of smoke, but nothing happens."))
emagging = FALSE
return
- if (prob(5))
+ if(prob(5))
var/mob/living/M = user
M.adjust_fire_stacks(1)
M.ignite_mob()
to_chat(user, span_danger("The card shorts out and catches fire in your hands!"))
log_combat(user, target, "attempted to emag")
- if(istype(target, /obj/machinery/computer/bounty)) //we can't have nice things
- to_chat(user, span_notice("The cheap circuitry isn't strong enough to subvert this!"))
- emagging = FALSE
- return
- target.emag_act(user)
+ if(!target.emag_act(user, src) && !((charges + 1) > max_charges))
+ charges++
emagging = FALSE
+/// A replica of an emag in most ways, except what it "cmags" what it interacts with.
+/obj/item/card/cmag
+ name = "jestographic sequencer"
+ desc = "It's a card coated in a slurry of electromagnetic bananium."
+ icon_state = "cmag"
+ item_state = "card-id"
+ lefthand_file = 'icons/mob/inhands/equipment/idcards_lefthand.dmi'
+ righthand_file = 'icons/mob/inhands/equipment/idcards_righthand.dmi'
+ item_flags = NO_MAT_REDEMPTION | NOBLUDGEON
+ /// How many charges can the cmag hold?
+ var/max_charges = 5
+ /// How many charges does the cmag start with?
+ var/charges = 5
+ /// How fast (in seconds) does charges increase by 1?
+ var/recharge_rate = 0.4
+ /// Does usage require you to be in range?
+ var/prox_check = TRUE
+
+/obj/item/card/cmag/Initialize(mapload)
+ . = ..()
+ if(recharge_rate != 0)
+ START_PROCESSING(SSobj, src)
+ AddComponent(/datum/component/slippery, 8 SECONDS, GALOSHES_DONT_HELP) // It wouldn't be funny if it couldn't slip!
+
+/obj/item/card/cmag/Destroy()
+ STOP_PROCESSING(SSobj, src)
+ . = ..()
+
+/obj/item/card/cmag/process(delta_time)
+ charges = clamp(charges + (recharge_rate * delta_time), 0, max_charges)
+
+/obj/item/card/cmag/attackby(obj/item/W, mob/user, params)
+ . = ..()
+ if(max_charges > charges)
+ if(istype(W, /obj/item/stack/sheet/mineral/uranium))
+ var/obj/item/stack/sheet/mineral/uranium/T = W
+ T.use(1)
+ charges = min(charges + 1, max_charges)
+ to_chat(user, span_notice("You add another charge to the [src]. It now has [charges] use[charges == 1 ? "" : "s"] remaining."))
+
+/obj/item/card/cmag/examine(mob/user)
+ . = ..()
+ . += span_notice("The charge meter indicates that it has [charges] charge[charges == 1 ? "" : "s"] remaining out of [max_charges] charges.")
+
+/obj/item/card/cmag/attack()
+ return
+
+/obj/item/card/cmag/afterattack(atom/target, mob/user, proximity)
+ . = ..()
+ if(!proximity && prox_check)
+ return
+ if(charges < 1)
+ to_chat(user, span_danger("\The [src] is still recharging!"))
+ return
+
+ log_combat(user, target, "attempted to cmag")
+ // Since cmag only has very few interactions, all of it is handled in `afterattack` instead of being a child of emag/`emag_act`.
+ if(istype(target, /obj/machinery/door/airlock))
+ var/obj/machinery/door/airlock/airlock = target
+ if(airlock.operating || !airlock.density || !airlock.hasPower() || (airlock.obj_flags & EMAGGED) || (airlock.obj_flags & CMAGGED))
+ return
+
+ charges--
+ playsound(airlock, 'sound/items/bikehorn.ogg', 20, 1) // Was it an innocent bike horn or was is it someone actively cmagging your airlock? The only tell if someone is actively cmagging things.
+ airlock.obj_flags |= CMAGGED
+ return
+
+ if(istype(target, /obj/machinery/door/window))
+ var/obj/machinery/door/window/windoor = target
+ if(windoor.operating || !windoor.density || (windoor.obj_flags & EMAGGED) || (windoor.obj_flags & CMAGGED))
+ return
+
+ charges--
+ playsound(windoor, 'sound/items/bikehorn.ogg', 20, 1)
+ windoor.obj_flags |= CMAGGED
+ return
+
/obj/item/card/emagfake
desc = "It's a card with a magnetic strip attached to some circuitry. Closer inspection shows that this card is a poorly made replica, with a \"DonkCo\" logo stamped on the back."
name = "cryptographic sequencer"
diff --git a/code/game/objects/items/cigs_lighters.dm b/code/game/objects/items/cigs_lighters.dm
index 42b4b0e3112a..9138e4e70ae8 100644
--- a/code/game/objects/items/cigs_lighters.dm
+++ b/code/game/objects/items/cigs_lighters.dm
@@ -864,21 +864,21 @@ 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 = 0
- to_chat(user, span_warning("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, span_warning("[src] is already emagged!"))
- else
+/obj/item/clothing/mask/vape/emag_act(mob/user, obj/item/card/emag/emag_card)// I WON'T REGRET WRITTING THIS, SURLY.
+ if(!screw)
to_chat(user, span_notice("You need to open the cap to do that."))
+ return FALSE
+ if(obj_flags & EMAGGED)
+ to_chat(user, span_warning("[src] is already emagged!"))
+ return FALSE
+ cut_overlays()
+ obj_flags |= EMAGGED
+ super = 0
+ to_chat(user, span_warning("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()
/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 b8ad9044010f..611ed0868c6a 100644
--- a/code/game/objects/items/circuitboards/computer_circuitboards.dm
+++ b/code/game/objects/items/circuitboards/computer_circuitboards.dm
@@ -487,12 +487,14 @@
else
to_chat(user, span_notice("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, span_notice("You adjust [src]'s routing and receiver spectrum, unlocking special supplies and contraband."))
-
+/obj/item/circuitboard/computer/cargo/emag_act(mob/user, obj/item/card/emag/emag_card)
+ if(obj_flags & EMAGGED)
+ return FALSE
+ contraband = TRUE
+ obj_flags |= EMAGGED
+ to_chat(user, span_notice("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)"
build_path = /obj/machinery/computer/cargo/express
@@ -504,9 +506,12 @@
to_chat(user, span_notice("You reset the routing protocols to: \"factory defaults\"."))
obj_flags &= ~EMAGGED
-/obj/item/circuitboard/computer/cargo/express/emag_act(mob/living/user)
- to_chat(user, span_notice("You change the routing protocols, allowing the Drop Pod to land anywhere on the station."))
- obj_flags |= EMAGGED
+/obj/item/circuitboard/computer/cargo/express/emag_act(mob/user, obj/item/card/emag/emag_card)
+ if(obj_flags & EMAGGED)
+ return FALSE
+ obj_flags |= EMAGGED
+ to_chat(user, span_notice("You change the routing protocols, allowing the Drop Pod to land anywhere on the station."))
+ return TRUE
/obj/item/circuitboard/computer/cargo/request
name = "Supply Request Console (Computer Board)"
diff --git a/code/game/objects/items/clown_items.dm b/code/game/objects/items/clown_items.dm
index 1c6cad4140e7..585805a53625 100644
--- a/code/game/objects/items/clown_items.dm
+++ b/code/game/objects/items/clown_items.dm
@@ -102,21 +102,22 @@
//So this is a workaround. This also makes more sense from an IC standpoint. ~Carn
if(user.client && ((target in user.client.screen) && !user.is_holding(target)))
to_chat(user, span_warning("You need to take that [target.name] off before cleaning it!"))
- else if(istype(target, /obj/effect/decal/cleanable))
+ return
+ if(istype(target, /obj/effect/decal/cleanable))
user.visible_message("[user] begins to scrub \the [target.name] out with [src].", span_warning("You begin to scrub \the [target.name] out with [src]..."))
if(do_after(user, cleanspeed, target))
to_chat(user, span_notice("You scrub \the [target.name] out."))
qdel(target)
decreaseUses(user)
-
- else if(ishuman(target) && user.zone_selected == BODY_ZONE_PRECISE_MOUTH)
+ return
+ if(ishuman(target) && user.zone_selected == BODY_ZONE_PRECISE_MOUTH)
var/mob/living/carbon/human/H = user
user.visible_message(span_warning("\the [user] washes \the [target]'s mouth out with [src.name]!"), span_notice("You wash \the [target]'s mouth out with [src.name]!")) //washes mouth out with soap sounds better than 'the soap' here if(user.zone_selected == "mouth")
H.lip_style = null //removes lipstick
H.update_body()
decreaseUses(user)
return
- else if(istype(target, /obj/structure/window))
+ if(istype(target, /obj/structure/window))
user.visible_message("[user] begins to clean \the [target.name] with [src]...", span_notice("You begin to clean \the [target.name] with [src]..."))
if(do_after(user, cleanspeed, target))
to_chat(user, span_notice("You clean \the [target.name]."))
@@ -128,17 +129,25 @@
qdel(iter_blood)
our_window.bloodied = FALSE
decreaseUses(user)
- else
- user.visible_message("[user] begins to clean \the [target.name] with [src]...", span_notice("You begin to clean \the [target.name] with [src]..."))
- if(do_after(user, cleanspeed, target))
- to_chat(user, span_notice("You clean \the [target.name]."))
- target.wash(CLEAN_SCRUB)
- target.remove_atom_colour(WASHABLE_COLOUR_PRIORITY)
- target.wash_cream()
- decreaseUses(user)
+ return
+ if(istype(target, /obj/machinery/door))
+ var/obj/machinery/door/door = target
+ if(door.obj_flags && CMAGGED)
+ user.visible_message("[user] starts to clean the ooze off \the [door.name]'s access panel.", "You start to clean the ooze off \the [door.name]'s access panel.")
+ if(do_after(user, src.cleanspeed, door))
+ to_chat(span_notice(" You clean the ooze off [src]'s access panel."))
+ door.obj_flags &= ~CMAGGED
+ decreaseUses(user)
+ return
+ user.visible_message("[user] begins to clean \the [target.name] with [src]...", span_notice("You begin to clean \the [target.name] with [src]..."))
+ if(do_after(user, cleanspeed, target))
+ to_chat(user, span_notice("You clean \the [target.name]."))
+ target.wash(CLEAN_SCRUB)
+ target.remove_atom_colour(WASHABLE_COLOUR_PRIORITY)
+ target.wash_cream()
+ decreaseUses(user)
return
-
/*
* Bike Horns
*/
diff --git a/code/game/objects/items/defib.dm b/code/game/objects/items/defib.dm
index b666ae3b887a..589103941ff1 100644
--- a/code/game/objects/items/defib.dm
+++ b/code/game/objects/items/defib.dm
@@ -140,13 +140,14 @@
else
return ..()
-/obj/item/defibrillator/emag_act(mob/user)
+/obj/item/defibrillator/emag_act(mob/user, obj/item/card/emag/emag_card)
if(safety)
safety = FALSE
to_chat(user, span_warning("You silently disable [src]'s safety protocols with the cryptographic sequencer."))
else
safety = TRUE
to_chat(user, span_notice("You silently enable [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 215a06b610be..0d37b5fbcc28 100644
--- a/code/game/objects/items/devices/geiger_counter.dm
+++ b/code/game/objects/items/devices/geiger_counter.dm
@@ -178,16 +178,15 @@
to_chat(usr, span_notice("You flush [src]'s radiation counts, resetting it to normal."))
update_appearance(UPDATE_ICON)
-/obj/item/geiger_counter/emag_act(mob/user)
+/obj/item/geiger_counter/emag_act(mob/user, obj/item/card/emag/emag_card)
if(obj_flags & EMAGGED)
- return
+ return FALSE
if(scanning)
to_chat(user, span_warning("Turn off [src] before you perform this action!"))
- return 0
- to_chat(user, span_warning("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."))
+ return FALSE
obj_flags |= EMAGGED
-
-
+ to_chat(user, span_warning("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."))
+ return TRUE
/obj/item/geiger_counter/cyborg
var/mob/listeningTo
diff --git a/code/game/objects/items/devices/lightreplacer.dm b/code/game/objects/items/devices/lightreplacer.dm
index 4c550782183d..b8c26361f0b7 100644
--- a/code/game/objects/items/devices/lightreplacer.dm
+++ b/code/game/objects/items/devices/lightreplacer.dm
@@ -142,10 +142,13 @@
to_chat(user, span_notice("You fill \the [src] with lights from \the [S]. " + status_string() + ""))
-/obj/item/lightreplacer/emag_act()
+/obj/item/lightreplacer/emag_act(mob/user, obj/item/card/emag/emag_card)
if(obj_flags & EMAGGED)
- return
- Emag()
+ return FALSE
+ obj_flags |= EMAGGED
+ playsound(src.loc, "sparks", 100, 1)
+ update_appearance()
+ return TRUE
/obj/item/lightreplacer/attack_self(mob/user)
for(var/obj/machinery/light/target in user.loc)
@@ -156,6 +159,13 @@
. = ..()
icon_state = "lightreplacer[(obj_flags & EMAGGED ? 1 : 0)]"
+/obj/item/lightreplacer/update_name(updates=ALL)
+ . = ..()
+ if(obj_flags & EMAGGED)
+ name = "shortcircuited [initial(name)]"
+ else
+ name = initial(name)
+
/obj/item/lightreplacer/proc/status_string()
return "It has [uses] light\s remaining (plus [bulb_shards] fragment\s)."
@@ -219,15 +229,6 @@
to_chat(U, span_warning("There is a working [target.fitting] already inserted!"))
return
-/obj/item/lightreplacer/proc/Emag()
- obj_flags ^= EMAGGED
- playsound(src.loc, "sparks", 100, 1)
- if(obj_flags & EMAGGED)
- name = "shortcircuited [initial(name)]"
- else
- name = initial(name)
- update_appearance(UPDATE_ICON)
-
/obj/item/lightreplacer/proc/CanUse(mob/living/user)
src.add_fingerprint(user)
if(uses > 0)
diff --git a/code/game/objects/items/devices/megaphone.dm b/code/game/objects/items/devices/megaphone.dm
index 7e06311398d4..8f2e996ef16e 100644
--- a/code/game/objects/items/devices/megaphone.dm
+++ b/code/game/objects/items/devices/megaphone.dm
@@ -63,13 +63,14 @@
playsound(loc, 'sound/items/megaphone.ogg', 100, 0, 1)
speech_args[SPEECH_SPANS] |= voicespan
-/obj/item/megaphone/emag_act(mob/user)
+/obj/item/megaphone/emag_act(mob/user, obj/item/card/emag/emag_card)
if(obj_flags & EMAGGED)
- return
- to_chat(user, span_warning("You overload \the [src]'s voice synthesizer."))
+ return FALSE
obj_flags |= EMAGGED
voicespan = list(SPAN_REALLYBIG, "userdanger")
-
+ to_chat(user, span_warning("You overload \the [src]'s voice synthesizer."))
+ return TRUE
+
/obj/item/megaphone/sec
name = "security megaphone"
icon_state = "megaphone-sec"
diff --git a/code/game/objects/items/robot/robot_items.dm b/code/game/objects/items/robot/robot_items.dm
index 4b374292f405..6f92539acf28 100644
--- a/code/game/objects/items/robot/robot_items.dm
+++ b/code/game/objects/items/robot/robot_items.dm
@@ -299,12 +299,14 @@
icon_state = "megaphone"
var/cooldown = 0
-/obj/item/harmalarm/emag_act(mob/user)
+/obj/item/harmalarm/emag_act(mob/user, obj/item/card/emag/emag_card)
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]!")
+ if(user)
+ 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 88a0cdd65df8..98342c6c4910 100644
--- a/code/game/objects/items/storage/lockbox.dm
+++ b/code/game/objects/items/storage/lockbox.dm
@@ -50,15 +50,16 @@
to_chat(user, span_danger("Access Denied."))
return
-/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(span_warning("\The [src] has been broken by [user] with an electromagnetic card!"))
- return
+/obj/item/storage/lockbox/emag_act(mob/user, obj/item/card/emag/emag_card)
+ if(broken)
+ return FALSE
+ 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(span_warning("\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 38236af658f7..e6c35e8eb24f 100644
--- a/code/game/objects/structures/barsigns.dm
+++ b/code/game/objects/structures/barsigns.dm
@@ -112,14 +112,18 @@
set_sign(new /datum/barsign/hiddensigns/empbarsign)
broken = TRUE
-/obj/structure/sign/barsign/emag_act(mob/user)
+/obj/structure/sign/barsign/emag_act(mob/user, obj/item/card/emag/emag_card)
if(broken)
to_chat(user, span_warning("Nothing interesting happens!"))
- return
+ return FALSE
to_chat(user, span_notice("You load an illegal barsign into the memory buffer..."))
- sleep(10 SECONDS)
- chosen_sign = set_sign(new /datum/barsign/hiddensigns/syndibarsign)
+ addtimer(CALLBACK(src, PROC_REF(finish_emag_act)), 10 SECONDS)
+ return TRUE
+/obj/structure/sign/barsign/proc/finish_emag_act()
+ if(QDELETED(src))
+ return
+ chosen_sign = set_sign(new /datum/barsign/hiddensigns/syndibarsign)
/obj/structure/sign/barsign/proc/pick_sign(mob/user)
var/picked_name = input(user, "Available Signage", "Bar Sign", name) as null|anything in get_bar_names()
diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm
index bbd1bdda7d04..75861b1dc5ee 100644
--- a/code/game/objects/structures/crates_lockers/closets.dm
+++ b/code/game/objects/structures/crates_lockers/closets.dm
@@ -520,16 +520,18 @@ GLOBAL_LIST_EMPTY(lockers)
else if(secure && broken)
to_chat(user, span_warning("\The [src] is broken!"))
-/obj/structure/closet/emag_act(mob/user)
- if(secure && !broken)
- user.visible_message(span_warning("Sparks fly from [src]!"),
- span_warning("You scramble [src]'s lock, breaking it open!"),
- span_italics("You hear a faint electrical spark."))
- playsound(src, "sparks", 50, 1)
- broken = TRUE
- locked = FALSE
- update_appearance(UPDATE_ICON)
-
+/obj/structure/closet/emag_act(mob/user, obj/item/card/emag/emag_card)
+ if(!secure || broken)
+ return FALSE
+ user.visible_message(span_warning("Sparks fly from [src]!"),
+ span_warning("You scramble [src]'s lock, breaking it open!"),
+ span_italics("You hear a faint electrical spark."))
+ playsound(src, "sparks", 50, 1)
+ broken = TRUE
+ locked = FALSE
+ update_appearance(UPDATE_ICON)
+ return TRUE
+
/obj/structure/closet/get_remote_view_fullscreens(mob/user)
if(user.stat == DEAD || !(user.sight & (SEEOBJS|SEEMOBS)))
user.overlay_fullscreen("remote_view", /atom/movable/screen/fullscreen/impaired, 1)
diff --git a/code/game/objects/structures/fireaxe.dm b/code/game/objects/structures/fireaxe.dm
index c584efd74012..f1e980ca95fc 100644
--- a/code/game/objects/structures/fireaxe.dm
+++ b/code/game/objects/structures/fireaxe.dm
@@ -288,12 +288,12 @@
trigger_alarm() //already checks for alert var
toggle_lock(user)
-/obj/structure/fireaxecabinet/bridge/spare/emag_act(mob/user)
+/obj/structure/fireaxecabinet/bridge/spare/emag_act(mob/user, obj/item/card/emag/emag_card)
. = ..()
if(!.)
- return
+ return FALSE
trigger_alarm()
-
+ return TRUE
/obj/structure/fireaxecabinet/fishingrod
name = "fishing cabinet"
diff --git a/code/modules/VR/vr_sleeper.dm b/code/modules/VR/vr_sleeper.dm
index 8b5a342b8abd..af38ac4bd161 100644
--- a/code/modules/VR/vr_sleeper.dm
+++ b/code/modules/VR/vr_sleeper.dm
@@ -53,14 +53,15 @@
flags_1 = NODECONSTRUCT_1
only_current_user_can_interact = TRUE
-/obj/machinery/vr_sleeper/hugbox/emag_act(mob/user)
+/obj/machinery/vr_sleeper/hugbox/emag_act(mob/user, obj/item/card/emag/emag_card)
return
-/obj/machinery/vr_sleeper/emag_act(mob/user)
+/obj/machinery/vr_sleeper/emag_act(mob/user, obj/item/card/emag/emag_card)
you_die_in_the_game_you_die_for_real = TRUE
sparks.start()
addtimer(CALLBACK(src, PROC_REF(emagNotify)), 150)
-
+ return TRUE
+
/obj/machinery/vr_sleeper/update_icon_state()
. = ..()
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 73b615216cb6..8f332b1f6a0f 100644
--- a/code/modules/atmospherics/machinery/airalarm.dm
+++ b/code/modules/atmospherics/machinery/airalarm.dm
@@ -846,12 +846,13 @@
to_chat(user, span_danger("Access denied."))
return
-/obj/machinery/airalarm/emag_act(mob/user)
+/obj/machinery/airalarm/emag_act(mob/user, obj/item/card/emag/emag_card)
if(obj_flags & EMAGGED)
- return
+ return FALSE
obj_flags |= EMAGGED
visible_message(span_warning("Sparks fly out of [src]!"), span_notice("You emag [src], disabling its safeties."))
playsound(src, "sparks", 50, 1)
+ return TRUE
/obj/machinery/airalarm/deconstruct(disassembled = TRUE)
if(!(flags_1 & NODECONSTRUCT_1))
diff --git a/code/modules/cargo/bounty_console.dm b/code/modules/cargo/bounty_console.dm
index fc6891985393..de917a924e00 100644
--- a/code/modules/cargo/bounty_console.dm
+++ b/code/modules/cargo/bounty_console.dm
@@ -31,12 +31,16 @@