From ccf547c142807996feb17e20018d60efe2a9c69f Mon Sep 17 00:00:00 2001
From: nikothedude <59709059+nikothedude@users.noreply.github.com>
Date: Sat, 15 Jul 2023 10:35:14 -0400
Subject: [PATCH] Adds an extra malf AI ability: Remote emagging. Also tidies
up emag code and coverts a lot of things to balloon alerts (#76669)
## About The Pull Request
New malf AI upgrade
Remote safety overrides: Mid-cost, Mid-supply. Allows the AI to remotely
emag things it can see and can access.
1. Very useful for psychological warfare (Emagging APCs to throw the
crew off their trail)
2. Logically makes sense - why, of all things, can the AI not emag
anything when it's fundumentally integrated with the station's
electronics?
3. Generally speaking can only access things that make sense for it to
access - it cannot emag ethereals, sadly
In order for this to work, emag_act now returns a boolean, designating
if the emag had any effect.
While I was in there, I also added args to every single emag_act I could
find and added far more feedback/converted a lot of things to balloon
alerts to allow the AI to see if its emag had any effect.
## Why It's Good For The Game
It just makes sense that the AI, the most electronically-sensitive
entity in the game, would be able to emag things. Plus, more options
given to malf that aren't strictly MURDER KILL MURDER are always a plus,
especially if they allow for fancier plays.
## Changelog
:cl:
add: New malf ability: Remote safety overrides. Allows the AI to
remotely emag things it has access to.
code: emag_act() now returns a boolean designating it's success in
emagging
code: All instances of emag_act() now have the proper arguments
qol: Most usecases of emagging now have some kind of feedback, and
existing feedback has been sanity checked and converted to balloon
alerts.
/:cl:
---
code/game/atoms.dm | 9 +-
code/game/machinery/announcement_system.dm | 6 +-
code/game/machinery/barsigns.dm | 11 +-
code/game/machinery/buttons.dm | 8 +-
code/game/machinery/computer/apc_control.dm | 9 +-
code/game/machinery/computer/arcade/arcade.dm | 10 +-
code/game/machinery/computer/arcade/orion.dm | 11 +-
.../game/machinery/computer/communications.dm | 21 ++--
code/game/machinery/digital_clock.dm | 5 +-
code/game/machinery/doors/airlock.dm | 34 ++++---
code/game/machinery/doors/firedoor.dm | 9 +-
code/game/machinery/doors/unpowered.dm | 4 +-
code/game/machinery/doors/windowdoor.dm | 14 ++-
.../embedded_controller/access_controller.dm | 7 +-
code/game/machinery/fat_sucker.dm | 5 +-
code/game/machinery/firealarm.dm | 9 +-
code/game/machinery/gulag_item_reclaimer.dm | 6 +-
code/game/machinery/harvester.dm | 7 +-
code/game/machinery/limbgrower.dm | 8 +-
code/game/machinery/medical_kiosk.dm | 10 +-
.../machinery/porta_turret/portable_turret.dm | 14 +--
.../porta_turret/portable_turret_cover.dm | 18 ++--
code/game/machinery/recycler.dm | 7 +-
code/game/machinery/scan_gate.dm | 7 +-
code/game/machinery/shieldgen.dm | 14 +--
code/game/machinery/sleepers.dm | 7 +-
code/game/machinery/slotmachine.dm | 6 +-
.../machinery/telecomms/computers/message.dm | 6 +-
code/game/objects/items/cigs_lighters.dm | 34 ++++---
.../circuitboards/computer_circuitboards.dm | 28 ++++--
code/game/objects/items/defib.dm | 15 +--
.../objects/items/devices/lightreplacer.dm | 8 +-
code/game/objects/items/devices/megaphone.dm | 7 +-
.../objects/items/devices/radio/intercom.dm | 6 +-
code/game/objects/items/rcd/RSF.dm | 7 +-
.../game/objects/items/robot/items/generic.dm | 7 +-
code/game/objects/items/storage/lockbox.dm | 10 +-
code/game/objects/items/toys.dm | 35 ++++---
.../structures/crates_lockers/closets.dm | 10 +-
code/game/objects/structures/displaycase.dm | 6 +-
code/game/objects/structures/morgue.dm | 7 +-
code/game/objects/structures/toiletbong.dm | 6 +-
.../objects/structures/training_machine.dm | 3 +-
.../antagonists/malf_ai/malf_ai_modules.dm | 95 ++++++++++++++++++
.../machinery/air_alarm/air_alarm_interact.dm | 8 +-
code/modules/balloon_alert/balloon_alert.dm | 10 +-
code/modules/cargo/expressconsole.dm | 10 +-
code/modules/cargo/orderconsole.dm | 10 +-
code/modules/clothing/glasses/hud.dm | 7 +-
code/modules/clothing/masks/hailer.dm | 7 +-
.../clothing/spacesuits/_spacesuits.dm | 11 +-
code/modules/experisci/destructive_scanner.dm | 7 +-
code/modules/holodeck/computer.dm | 18 ++--
.../elevator/elevator_controller.dm | 5 +-
.../elevator/elevator_panel.dm | 5 +-
.../industrial_lift/tram/tram_doors.dm | 5 +-
.../industrial_lift/tram/tram_machinery.dm | 5 +-
code/modules/library/lib_machines.dm | 8 +-
code/modules/mining/abandoned_crates.dm | 10 +-
code/modules/mining/laborcamp/laborstacker.dm | 13 ++-
.../carbon/human/species_types/ethereal.dm | 3 +-
.../mob/living/silicon/ai/ai_defense.dm | 7 +-
.../mob/living/silicon/robot/robot_defense.dm | 31 +++---
.../mob/living/simple_animal/bot/bot.dm | 9 +-
.../mob/living/simple_animal/bot/cleanbot.dm | 5 +-
.../mob/living/simple_animal/bot/ed209bot.dm | 7 +-
.../mob/living/simple_animal/bot/firebot.dm | 10 +-
.../mob/living/simple_animal/bot/floorbot.dm | 9 +-
.../mob/living/simple_animal/bot/medbot.dm | 8 +-
.../mob/living/simple_animal/bot/mulebot.dm | 5 +-
.../mob/living/simple_animal/bot/secbot.dm | 7 +-
code/modules/mod/mod_control.dm | 3 +-
code/modules/mod/modules/modules_general.dm | 3 +-
.../computers/item/computer.dm | 12 ++-
.../computers/machinery/modular_computer.dm | 4 +-
code/modules/pai/card.dm | 3 +-
code/modules/pai/pai.dm | 2 +-
code/modules/paperwork/fax.dm | 7 +-
code/modules/paperwork/ticketmachine.dm | 7 +-
code/modules/power/apc/apc_tool_act.dm | 10 +-
code/modules/power/port_gen.dm | 7 +-
code/modules/power/singularity/emitter.dm | 8 +-
code/modules/projectiles/pins.dm | 19 ++--
.../chemistry/machinery/chem_dispenser.dm | 9 +-
code/modules/recycling/disposal/outlet.dm | 5 +-
code/modules/research/rdconsole.dm | 16 +--
code/modules/research/server_control.dm | 5 +-
.../xenobiology/vatgrowing/vatgrower.dm | 7 +-
code/modules/shuttle/computer.dm | 7 +-
code/modules/shuttle/emergency.dm | 24 +++--
code/modules/shuttle/ferry.dm | 4 +-
code/modules/shuttle/special.dm | 8 +-
code/modules/station_goals/bsa.dm | 6 +-
code/modules/station_goals/meteor_shield.dm | 6 +-
.../organs/internal/cyberimp/augments_arms.dm | 4 +-
code/modules/vehicles/cars/clowncar.dm | 6 +-
code/modules/vehicles/motorized_wheelchair.dm | 15 ++-
code/modules/vending/_vending.dm | 7 +-
icons/mob/actions/actions_AI.dmi | Bin 12262 -> 11221 bytes
99 files changed, 651 insertions(+), 369 deletions(-)
diff --git a/code/game/atoms.dm b/code/game/atoms.dm
index a1e3ed547ef..51a5de292eb 100644
--- a/code/game/atoms.dm
+++ b/code/game/atoms.dm
@@ -1062,10 +1062,15 @@
/**
* 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(mob/user, obj/item/card/emag/emag_card)
- SEND_SIGNAL(src, COMSIG_ATOM_EMAG_ACT, user, emag_card)
+ return (SEND_SIGNAL(src, COMSIG_ATOM_EMAG_ACT, user, emag_card))
/**
* Respond to narsie eating our atom
diff --git a/code/game/machinery/announcement_system.dm b/code/game/machinery/announcement_system.dm
index 87f2a9f01c8..df3e402525d 100644
--- a/code/game/machinery/announcement_system.dm
+++ b/code/game/machinery/announcement_system.dm
@@ -176,8 +176,10 @@ GLOBAL_LIST_EMPTY(announcement_systems)
if(!(machine_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()
+ balloon_alert(user, "announcement strings corrupted")
+ return TRUE
diff --git a/code/game/machinery/barsigns.dm b/code/game/machinery/barsigns.dm
index 20e5559d95f..16686b23c77 100644
--- a/code/game/machinery/barsigns.dm
+++ b/code/game/machinery/barsigns.dm
@@ -169,15 +169,18 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/barsign, 32)
set_sign(sign)
-/obj/machinery/barsign/emag_act(mob/user)
+/obj/machinery/barsign/emag_act(mob/user, obj/item/card/emag/emag_card)
if(machine_stat & (NOPOWER|BROKEN|EMPED))
balloon_alert(user, "controls are unresponsive!")
- return
+ return FALSE
balloon_alert(user, "illegal barsign loaded")
- sleep(10 SECONDS)
- set_sign(new /datum/barsign/hiddensigns/syndibarsign)
+ addtimer(CALLBACK(src, PROC_REF(finish_emag_act)), 10 SECONDS)
+ return TRUE
+/// Timer proc, called after ~10 seconds after [emag_act], since [emag_act] returns a value and cannot sleep
+/obj/machinery/barsign/proc/finish_emag_act()
+ set_sign(new /datum/barsign/hiddensigns/syndibarsign)
/obj/machinery/barsign/proc/pick_sign(mob/user)
var/picked_name = tgui_input_list(user, "Available Signage", "Bar Sign", sort_list(get_bar_names()))
diff --git a/code/game/machinery/buttons.dm b/code/game/machinery/buttons.dm
index 6d2db1482e3..21a718d8705 100644
--- a/code/game/machinery/buttons.dm
+++ b/code/game/machinery/buttons.dm
@@ -139,7 +139,7 @@
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
@@ -150,9 +150,9 @@
// The device inside can be emagged by swiping the button
// returning TRUE will prevent feedback (so we can do our own)
- if(device?.emag_act(user))
- return
- balloon_alert(user, "access overridden")
+ if(!device?.emag_act(user, emag_card))
+ balloon_alert(user, "access overridden")
+ return TRUE
/obj/machinery/button/attack_ai(mob/user)
if(!silicon_access_disabled && !panel_open)
diff --git a/code/game/machinery/computer/apc_control.dm b/code/game/machinery/computer/apc_control.dm
index 882ef86f0db..6cecd17e811 100644
--- a/code/game/machinery/computer/apc_control.dm
+++ b/code/game/machinery/computer/apc_control.dm
@@ -27,12 +27,15 @@
return
..()
-/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
- usr.log_message("emagged [src].", LOG_ATTACK, color="red")
+ if (user)
+ user.log_message("emagged [src].", LOG_ATTACK, color="red")
+ balloon_alert(user, "access controller shorted")
playsound(src, SFX_SPARKS, 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE)
+ return TRUE
/obj/machinery/computer/apc_control/proc/log_activity(log_text)
if(!should_log)
diff --git a/code/game/machinery/computer/arcade/arcade.dm b/code/game/machinery/computer/arcade/arcade.dm
index f7dc3909273..28034872289 100644
--- a/code/game/machinery/computer/arcade/arcade.dm
+++ b/code/game/machinery/computer/arcade/arcade.dm
@@ -620,17 +620,18 @@ GLOBAL_LIST_INIT(arcade_prize_pool, list(
. += "\t[span_info("magical -> defend until outmagiced")]"
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
+ balloon_alert(user, "hard mode enabled")
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!"
max_passive = 6
bomb_cooldown = 18
var/gamerSkill = 0
- if(usr?.mind)
- gamerSkill = usr.mind.get_skill_level(/datum/skill/gaming)
+ if(user?.mind)
+ gamerSkill = user.mind.get_skill_level(/datum/skill/gaming)
enemy_setup(gamerSkill)
enemy_hp += 100 //extra HP just to make cuban pete even more bullshit
player_hp += 30 //the player will also get a few extra HP in order to have a fucking chance
@@ -644,6 +645,7 @@ GLOBAL_LIST_INIT(arcade_prize_pool, list(
name = "Outbomb Cuban Pete"
updateUsrDialog()
+ return TRUE
// ** AMPUTATION ** //
diff --git a/code/game/machinery/computer/arcade/orion.dm b/code/game/machinery/computer/arcade/orion.dm
index e1bd4005978..3bf880a7582 100644
--- a/code/game/machinery/computer/arcade/orion.dm
+++ b/code/game/machinery/computer/arcade/orion.dm
@@ -489,15 +489,18 @@ GLOBAL_LIST_INIT(orion_events, generate_orion_events())
name = initial(name)
desc = initial(desc)
-/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
- to_chat(user, span_notice("You override the cheat code menu and skip to Cheat #[rand(1, 50)]: Realism Mode."))
- user.log_message("emagged [src], activating Realism Mode.", LOG_GAME)
+ return FALSE
+ if (user)
+ user.log_message("emagged [src], activating Realism Mode.", LOG_GAME)
+ balloon_alert(user, "realism mode enabled")
+ 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 got to Orion, and try not to die in the process!"
newgame()
obj_flags |= EMAGGED
+ return TRUE
/mob/living/basic/syndicate/ranged/smg/orion
name = "spaceport security"
diff --git a/code/game/machinery/computer/communications.dm b/code/game/machinery/computer/communications.dm
index 5559ab440e7..2ffed11f354 100644
--- a/code/game/machinery/computer/communications.dm
+++ b/code/game/machinery/computer/communications.dm
@@ -67,7 +67,7 @@
syndicate = TRUE
/obj/machinery/computer/communications/syndicate/emag_act(mob/user, obj/item/card/emag/emag_card)
- return
+ return FALSE
/obj/machinery/computer/communications/syndicate/can_buy_shuttles(mob/user)
return FALSE
@@ -119,26 +119,29 @@
/obj/machinery/computer/communications/emag_act(mob/user, obj/item/card/emag/emag_card)
if(istype(emag_card, /obj/item/card/emag/battlecruiser))
- if(!IS_TRAITOR(user))
- to_chat(user, span_danger("You get the feeling this is a bad idea."))
- return
var/obj/item/card/emag/battlecruiser/caller_card = emag_card
+ if (user)
+ if(!IS_TRAITOR(user))
+ to_chat(user, span_danger("You get the feeling this is a bad idea."))
+ return FALSE
if(battlecruiser_called)
- to_chat(user, span_danger("The card reports a long-range message already sent to the Syndicate fleet...?"))
- return
+ if (user)
+ to_chat(user, span_danger("The card reports a long-range message already sent to the Syndicate fleet...?"))
+ return FALSE
battlecruiser_called = TRUE
caller_card.use_charge(user)
addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(summon_battlecruiser), caller_card.team), rand(20 SECONDS, 1 MINUTES))
playsound(src, 'sound/machines/terminal_alert.ogg', 50, FALSE)
- return
+ return TRUE
if(obj_flags & EMAGGED)
- return
+ return FALSE
obj_flags |= EMAGGED
if (authenticated)
authorize_access = SSid_access.get_region_access_list(list(REGION_ALL_STATION))
- to_chat(user, span_danger("You scramble the communication routing circuits!"))
+ balloon_alert(user, "routing circuits scrambled")
playsound(src, 'sound/machines/terminal_alert.ogg', 50, FALSE)
+ 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/digital_clock.dm b/code/game/machinery/digital_clock.dm
index 99cd1894725..0bfb8aeba72 100644
--- a/code/game/machinery/digital_clock.dm
+++ b/code/game/machinery/digital_clock.dm
@@ -57,12 +57,13 @@
obj_flags &= ~EMAGGED
return TRUE
-/obj/machinery/digital_clock/emag_act(mob/user)
+/obj/machinery/digital_clock/emag_act(mob/user, obj/item/card/emag/emag_card)
if(obj_flags & EMAGGED)
- return
+ return FALSE
playsound(src, SFX_SPARKS, 100, vary = TRUE, extrarange = SHORT_RANGE_SOUND_EXTRARANGE)
do_sparks(3, cardinal_only = FALSE, source = src)
obj_flags |= EMAGGED
+ return TRUE
/obj/machinery/digital_clock/emp_act(severity)
. = ..()
diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm
index f1194384d69..f421a0416b5 100644
--- a/code/game/machinery/doors/airlock.dm
+++ b/code/game/machinery/doors/airlock.dm
@@ -1372,23 +1372,29 @@
//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() && !no_id)
-/obj/machinery/door/airlock/emag_act(mob/user, obj/item/card/emag/doorjack/D)
+/obj/machinery/door/airlock/emag_act(mob/user, obj/item/card/emag/emag_card)
if(!operating && density && hasPower() && !(obj_flags & EMAGGED))
- if(istype(D, /obj/item/card/emag/doorjack))
- D.use_charge(user)
+ if(istype(emag_card, /obj/item/card/emag/doorjack))
+ var/obj/item/card/emag/doorjack/doorjack_card = emag_card
+ doorjack_card.use_charge(user)
operating = TRUE
update_icon(ALL, AIRLOCK_EMAG, 1)
- sleep(0.6 SECONDS)
- if(QDELETED(src))
- return
- operating = FALSE
- if(!open())
- update_icon(ALL, AIRLOCK_CLOSED, 1)
- obj_flags |= EMAGGED
- lights = FALSE
- locked = TRUE
- loseMainPower()
- loseBackupPower()
+ addtimer(CALLBACK(src, PROC_REF(finish_emag_act)), 0.6 SECONDS)
+ return TRUE
+ return FALSE
+
+/// Timer proc, called ~0.6 seconds after [emag_act]. Finishes the emag sequence by breaking the airlock, permanently locking it, and disabling power.
+/obj/machinery/door/airlock/proc/finish_emag_act()
+ if(QDELETED(src))
+ return FALSE
+ operating = FALSE
+ if(!open())
+ update_icon(ALL, AIRLOCK_CLOSED, 1)
+ obj_flags |= EMAGGED
+ lights = FALSE
+ locked = TRUE
+ loseMainPower()
+ loseBackupPower()
/obj/machinery/door/airlock/attack_alien(mob/living/carbon/alien/adult/user, list/modifiers)
if(isElectrified() && shock(user, 100)) //Mmm, fried xeno!
diff --git a/code/game/machinery/doors/firedoor.dm b/code/game/machinery/doors/firedoor.dm
index 68e4627bbe0..34ddda2798f 100644
--- a/code/game/machinery/doors/firedoor.dm
+++ b/code/game/machinery/doors/firedoor.dm
@@ -436,14 +436,15 @@
if(place == my_area)
place.alarm_manager.clear_alarm(ALARM_FIRE, place)
-/obj/machinery/door/firedoor/emag_act(mob/user, obj/item/card/emag/emag_type)
+/obj/machinery/door/firedoor/emag_act(mob/user, obj/item/card/emag/emag_card)
if(obj_flags & EMAGGED)
- return
- if(istype(emag_type, /obj/item/card/emag/doorjack)) //Skip doorjack-specific code
- var/obj/item/card/emag/doorjack/digital_crowbar = emag_type
+ return FALSE
+ if(istype(emag_card, /obj/item/card/emag/doorjack)) //Skip doorjack-specific code
+ var/obj/item/card/emag/doorjack/digital_crowbar = emag_card
digital_crowbar.use_charge(user)
obj_flags |= EMAGGED
INVOKE_ASYNC(src, PROC_REF(open))
+ return TRUE
/obj/machinery/door/firedoor/Bumped(atom/movable/AM)
if(panel_open || operating)
diff --git a/code/game/machinery/doors/unpowered.dm b/code/game/machinery/doors/unpowered.dm
index 9372abe59ce..6a9fea47419 100644
--- a/code/game/machinery/doors/unpowered.dm
+++ b/code/game/machinery/doors/unpowered.dm
@@ -13,8 +13,8 @@
else
return ..()
-/obj/machinery/door/unpowered/emag_act()
- return
+/obj/machinery/door/unpowered/emag_act(mob/user, obj/item/card/emag/emag_card)
+ return FALSE
/obj/machinery/door/unpowered/shuttle
icon = 'icons/turf/shuttle.dmi'
diff --git a/code/game/machinery/doors/windowdoor.dm b/code/game/machinery/doors/windowdoor.dm
index de2d1e1dea4..59cbbb205e5 100644
--- a/code/game/machinery/doors/windowdoor.dm
+++ b/code/game/machinery/doors/windowdoor.dm
@@ -324,16 +324,20 @@
/obj/machinery/door/window/atmos_expose(datum/gas_mixture/air, exposed_temperature)
take_damage(round(exposed_temperature / 200), BURN, 0, 0)
-
-/obj/machinery/door/window/emag_act(mob/user)
+/obj/machinery/door/window/emag_act(mob/user, obj/item/card/emag/emag_card)
if(!operating && density && !(obj_flags & EMAGGED))
obj_flags |= EMAGGED
operating = TRUE
flick("[base_state]spark", src)
playsound(src, SFX_SPARKS, 75, TRUE, SHORT_RANGE_SOUND_EXTRARANGE)
- sleep(0.6 SECONDS)
- operating = FALSE
- open(BYPASS_DOOR_CHECKS)
+ addtimer(CALLBACK(src, PROC_REF(finish_emag_act)), 0.6 SECONDS)
+ return TRUE
+ return FALSE
+
+/// Timer proc, called ~0.6 seconds after [emag_act]. Finishes the emag sequence by breaking the windoor.
+/obj/machinery/door/window/proc/finish_emag_act()
+ operating = FALSE
+ open(BYPASS_DOOR_CHECKS)
/obj/machinery/door/window/examine(mob/user)
. = ..()
diff --git a/code/game/machinery/embedded_controller/access_controller.dm b/code/game/machinery/embedded_controller/access_controller.dm
index c935db5fb45..5c3c34d3fad 100644
--- a/code/game/machinery/embedded_controller/access_controller.dm
+++ b/code/game/machinery/embedded_controller/access_controller.dm
@@ -25,14 +25,15 @@
/obj/machinery/door_buttons/LateInitialize()
findObjsByTag()
-/obj/machinery/door_buttons/emag_act(mob/user)
+/obj/machinery/door_buttons/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, SFX_SPARKS, 100, TRUE, SHORT_RANGE_SOUND_EXTRARANGE)
- to_chat(user, span_warning("You short out the access controller."))
+ balloon_alert(user, "access controller shorted")
+ return TRUE
/obj/machinery/door_buttons/proc/removeMe()
diff --git a/code/game/machinery/fat_sucker.dm b/code/game/machinery/fat_sucker.dm
index 03a71e486f6..6e1f745772e 100644
--- a/code/game/machinery/fat_sucker.dm
+++ b/code/game/machinery/fat_sucker.dm
@@ -210,10 +210,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
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 e5a8fc6b59e..be2471a6375 100644
--- a/code/game/machinery/firealarm.dm
+++ b/code/game/machinery/firealarm.dm
@@ -217,17 +217,18 @@
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()
+ visible_message(span_warning("Sparks fly out of [src]!"))
if(user)
- user.visible_message(span_warning("Sparks fly out of [src]!"))
- user.balloon_alert(user, "speaker disabled!")
+ balloon_alert(user, "speaker disabled")
user.log_message("emagged [src].", LOG_ATTACK)
playsound(src, SFX_SPARKS, 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE)
set_status()
+ return TRUE
/**
* Signal handler for checking if we should update fire alarm appearance accordingly to a newly set security level
diff --git a/code/game/machinery/gulag_item_reclaimer.dm b/code/game/machinery/gulag_item_reclaimer.dm
index 82a1ee1267e..1a05ed756aa 100644
--- a/code/game/machinery/gulag_item_reclaimer.dm
+++ b/code/game/machinery/gulag_item_reclaimer.dm
@@ -32,13 +32,15 @@
linked_teleporter.linked_reclaimer = null
return ..()
-/obj/machinery/gulag_item_reclaimer/emag_act(mob/user)
+/obj/machinery/gulag_item_reclaimer/emag_act(mob/user, obj/item/card/emag/emag_card)
if(obj_flags & EMAGGED) // emagging lets anyone reclaim all the items
- return
+ return FALSE
req_access = list()
obj_flags |= EMAGGED
screen_icon = "emagged_general"
update_appearance()
+ balloon_alert(user, "id checker scrambled")
+ return TRUE
/obj/machinery/gulag_item_reclaimer/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
diff --git a/code/game/machinery/harvester.dm b/code/game/machinery/harvester.dm
index 7538a8af260..b5fd04a98f2 100644
--- a/code/game/machinery/harvester.dm
+++ b/code/game/machinery/harvester.dm
@@ -184,13 +184,14 @@
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
allow_clothing = TRUE
- to_chat(user, span_warning("You overload [src]'s lifesign and abiotic material scanners."))
+ balloon_alert(!user, "lifesign scanners overloaded")
+ return TRUE
/obj/machinery/harvester/container_resist_act(mob/living/user)
if(!harvesting)
diff --git a/code/game/machinery/limbgrower.dm b/code/game/machinery/limbgrower.dm
index 5f8d7020569..e5576bdb267 100644
--- a/code/game/machinery/limbgrower.dm
+++ b/code/game/machinery/limbgrower.dm
@@ -34,12 +34,14 @@
AddComponent(/datum/component/plumbing/simple_demand)
/// Emagging a limbgrower allows you to build synthetic armblades.
-/obj/machinery/limbgrower/emag_act(mob/user)
- if(obj_flags & EMAGGED)
- return
+/obj/machinery/limbgrower/emag_act(mob/user, obj/item/card/emag/emag_card)
. = ..()
+ if(obj_flags & EMAGGED)
+ return FALSE
obj_flags |= EMAGGED
update_static_data(user)
+ balloon_alert(user, "illegal limb production enabled")
+ return TRUE
/obj/machinery/limbgrower/ui_interact(mob/user, datum/tgui/ui)
. = ..()
diff --git a/code/game/machinery/medical_kiosk.dm b/code/game/machinery/medical_kiosk.dm
index 1909371386f..acd22e704a5 100644
--- a/code/game/machinery/medical_kiosk.dm
+++ b/code/game/machinery/medical_kiosk.dm
@@ -143,17 +143,19 @@
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
if(user)
- user.visible_message(span_warning("[user] waves a suspicious card by the [src]'s biometric scanner!"),
- span_notice("You overload the sensory electronics, the diagnostic readouts start jittering across the screen.."))
+ if (emag_card)
+ user.visible_message(span_warning("[user] waves a suspicious card by the [src]'s biometric scanner!"))
+ balloon_alert(user, "sensors overloaded")
obj_flags |= EMAGGED
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 b7b2a32be89..2100b103386 100644
--- a/code/game/machinery/porta_turret/portable_turret.dm
+++ b/code/game/machinery/porta_turret/portable_turret.dm
@@ -355,10 +355,10 @@ DEFINE_BITFIELD(turret_flags, list(
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
- to_chat(user, span_warning("You short out [src]'s threat assessment circuits."))
+ return FALSE
+ balloon_alert(user, "threat assessment circuits shorted")
audible_message(span_hear("[src] hums oddly..."))
obj_flags |= EMAGGED
controllock = TRUE
@@ -367,6 +367,7 @@ DEFINE_BITFIELD(turret_flags, list(
//6 seconds for the traitor to gtfo of the area before the turret decides to ruin his shit
addtimer(CALLBACK(src, PROC_REF(toggle_on), TRUE), 6 SECONDS)
//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)
. = ..()
@@ -974,12 +975,13 @@ DEFINE_BITFIELD(turret_flags, list(
else
to_chat(user, span_alert("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
- to_chat(user, span_notice("You short out the turret controls' access analysis module."))
+ return FALSE
+ balloon_alert(user, "access analysis module shorted")
obj_flags |= EMAGGED
locked = FALSE
+ return TRUE
/obj/machinery/turretid/attack_ai(mob/user)
if(!ailock || isAdminGhostAI(user))
diff --git a/code/game/machinery/porta_turret/portable_turret_cover.dm b/code/game/machinery/porta_turret/portable_turret_cover.dm
index d6c7eba6dc4..2ff41a17283 100644
--- a/code/game/machinery/porta_turret/portable_turret_cover.dm
+++ b/code/game/machinery/porta_turret/portable_turret_cover.dm
@@ -85,10 +85,14 @@
/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."))
- audible_message(span_hear("[parent_turret] hums oddly..."))
- parent_turret.obj_flags |= EMAGGED
- parent_turret.on = FALSE
- addtimer(VARSET_CALLBACK(parent_turret, on, TRUE), 4 SECONDS)
+/obj/machinery/porta_turret_cover/emag_act(mob/user, obj/item/card/emag/emag_card)
+
+ if((parent_turret.obj_flags & EMAGGED))
+ return FALSE
+
+ balloon_alert(user, "threat assessment circuits shorted")
+ audible_message(span_hear("[parent_turret] hums oddly..."))
+ parent_turret.obj_flags |= EMAGGED
+ parent_turret.on = FALSE
+ addtimer(VARSET_CALLBACK(parent_turret, on, TRUE), 4 SECONDS)
+ return TRUE
diff --git a/code/game/machinery/recycler.dm b/code/game/machinery/recycler.dm
index 5e8dd4daa0f..fa75e70506c 100644
--- a/code/game/machinery/recycler.dm
+++ b/code/game/machinery/recycler.dm
@@ -83,15 +83,16 @@
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()
playsound(src, SFX_SPARKS, 75, TRUE, SILENCED_SOUND_EXTRARANGE)
- to_chat(user, span_notice("You use the cryptographic sequencer on [src]."))
+ balloon_alert(user, "safeties disabled")
+ return FALSE
/obj/machinery/recycler/update_icon_state()
var/is_powered = !(machine_stat & (BROKEN|NOPOWER))
diff --git a/code/game/machinery/scan_gate.dm b/code/game/machinery/scan_gate.dm
index d2278d680ad..8fd41bcc9d9 100644
--- a/code/game/machinery/scan_gate.dm
+++ b/code/game/machinery/scan_gate.dm
@@ -105,13 +105,14 @@
wires.interact(user)
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."))
+ balloon_alert(user, "id checker disabled")
+ 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 b4ccd2f7626..9112773c1e9 100644
--- a/code/game/machinery/shieldgen.dm
+++ b/code/game/machinery/shieldgen.dm
@@ -268,14 +268,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, SFX_SPARKS, 100, TRUE, SHORT_RANGE_SOUND_EXTRARANGE)
- to_chat(user, span_warning("You short out the access controller."))
+ balloon_alert(user, "access controller shorted")
+ return TRUE
/obj/machinery/shieldgen/update_icon_state()
icon_state = "shield[active ? "on" : "off"][(machine_stat & BROKEN) ? "br" : null]"
@@ -470,14 +471,15 @@
user.log_message("activated [src].", LOG_GAME)
add_fingerprint(user)
-/obj/machinery/power/shieldwallgen/emag_act(mob/user)
+/obj/machinery/power/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, SFX_SPARKS, 100, TRUE, SHORT_RANGE_SOUND_EXTRARANGE)
- to_chat(user, span_warning("You short out the access controller."))
+ balloon_alert(user, "access controller shorted")
+ return TRUE
//////////////Containment Field START
/obj/machinery/shieldwall
diff --git a/code/game/machinery/sleepers.dm b/code/game/machinery/sleepers.dm
index 6f7cee63d87..373dc5333eb 100644
--- a/code/game/machinery/sleepers.dm
+++ b/code/game/machinery/sleepers.dm
@@ -266,16 +266,17 @@
if((obj_flags & EMAGGED) && prob(5))
to_chat(usr, span_warning("Chemical system re-route detected, results may not be as expected!"))
-/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_warning("You scramble the sleeper's user interface!"))
+ balloon_alert(user, "interface scrambled")
obj_flags |= EMAGGED
var/list/av_chem = available_chems.Copy()
for(var/chem in av_chem)
chem_buttons[chem] = pick_n_take(av_chem) //no dupes, allow for random buttons to still be correct
+ 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/slotmachine.dm b/code/game/machinery/slotmachine.dm
index 9eb4650c3f3..cc7c270b904 100644
--- a/code/game/machinery/slotmachine.dm
+++ b/code/game/machinery/slotmachine.dm
@@ -127,14 +127,16 @@
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, SFX_SPARKS, 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE)
+ balloon_alert(user, "machine rigged")
+ 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 72a5bd3a7f9..4db37cea2d8 100644
--- a/code/game/machinery/telecomms/computers/message.dm
+++ b/code/game/machinery/telecomms/computers/message.dm
@@ -38,9 +38,9 @@
return TRUE
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
+ return FALSE
if(!isnull(linkedServer))
obj_flags |= EMAGGED
screen = MSG_MON_SCREEN_HACKED
@@ -53,8 +53,10 @@
addtimer(CALLBACK(src, PROC_REF(unemag_console)), time)
error_message = "%$&(£: Critical %$$@ Error // !RestArting! - ?pLeaSe wAit!"
linkedServer.toggled = FALSE
+ return TRUE
else
to_chat(user, span_notice("A no server error appears on the screen."))
+ return FALSE
/// Remove the emag effect from the console
/obj/machinery/computer/message_monitor/proc/unemag_console()
diff --git a/code/game/objects/items/cigs_lighters.dm b/code/game/objects/items/cigs_lighters.dm
index 2cc20da25e4..889f47a9f58 100644
--- a/code/game/objects/items/cigs_lighters.dm
+++ b/code/game/objects/items/cigs_lighters.dm
@@ -1075,21 +1075,25 @@ CIGARETTE PACKETS ARE IN FANCY.DM
if(screw && (obj_flags & EMAGGED))
to_chat(user, span_warning("[src] can't be modified!"))
-/obj/item/clothing/mask/vape/emag_act(mob/user)// I WON'T REGRET WRITTING THIS, SURLY.
- if(screw)
- if(!(obj_flags & EMAGGED))
- obj_flags |= EMAGGED
- super = FALSE
- to_chat(user, span_warning("You maximize the voltage of [src]."))
- icon_state = "vape_open_high"
- set_greyscale(new_config = /datum/greyscale_config/vape/open_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
- to_chat(user, span_warning("You need to open the cap to do that!"))
+/obj/item/clothing/mask/vape/emag_act(mob/user, obj/item/card/emag/emag_card) // I WON'T REGRET WRITTING THIS, SURLY.
+
+ if (!screw)
+ balloon_alert(user, "open the cap first!")
+ return FALSE
+
+ if (obj_flags & EMAGGED)
+ balloon_alert(user, "already emagged!")
+ return FALSE
+
+ obj_flags |= EMAGGED
+ super = FALSE
+ balloon_alert(user, "voltage maximized")
+ icon_state = "vape_open_high"
+ set_greyscale(new_config = /datum/greyscale_config/vape/open_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 d152629568c..09e1b59a620 100644
--- a/code/game/objects/items/circuitboards/computer_circuitboards.dm
+++ b/code/game/objects/items/circuitboards/computer_circuitboards.dm
@@ -487,11 +487,14 @@
else
to_chat(user, span_alert("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/configure_machine(obj/machinery/computer/cargo/machine)
if(!istype(machine))
@@ -507,20 +510,25 @@
name = "Express Supply Console"
build_path = /obj/machinery/computer/cargo/express
-/obj/item/circuitboard/computer/cargo/express/emag_act(mob/living/user)
- if(!(obj_flags & EMAGGED))
- contraband = TRUE
- obj_flags |= EMAGGED
- to_chat(user, span_notice("You change the routing protocols, allowing the Drop Pod to land anywhere on the station."))
+/obj/item/circuitboard/computer/cargo/express/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 change the routing protocols, allowing the Drop Pod to land anywhere on the station."))
+ return TRUE
/obj/item/circuitboard/computer/cargo/express/multitool_act(mob/living/user)
if (!(obj_flags & EMAGGED))
contraband = !contraband
to_chat(user, span_notice("Receiver spectrum set to [contraband ? "Broad" : "Standard"]."))
+ return TRUE
else
to_chat(user, span_notice("You reset the destination-routing protocols and receiver spectrum to factory defaults."))
contraband = FALSE
obj_flags &= ~EMAGGED
+ return TRUE
/obj/item/circuitboard/computer/cargo/request
name = "Supply Request Console"
diff --git a/code/game/objects/items/defib.dm b/code/game/objects/items/defib.dm
index fa9fc3eec33..441052fb48a 100644
--- a/code/game/objects/items/defib.dm
+++ b/code/game/objects/items/defib.dm
@@ -175,13 +175,14 @@
else
return ..()
-/obj/item/defibrillator/emag_act(mob/user)
- 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."))
+/obj/item/defibrillator/emag_act(mob/user, obj/item/card/emag/emag_card)
+
+ safety = !safety
+
+ var/enabled_or_disabled = (safety ? "enabled" : "disabled")
+ balloon_alert(user, "safety protocols [enabled_or_disabled]")
+
+ return TRUE
/obj/item/defibrillator/emp_act(severity)
. = ..()
diff --git a/code/game/objects/items/devices/lightreplacer.dm b/code/game/objects/items/devices/lightreplacer.dm
index d8f27d0a6f3..1d07e2a9558 100644
--- a/code/game/objects/items/devices/lightreplacer.dm
+++ b/code/game/objects/items/devices/lightreplacer.dm
@@ -154,12 +154,14 @@
user.balloon_alert(user, "lights inserted")
return TRUE
-/obj/item/lightreplacer/emag_act()
+/obj/item/lightreplacer/emag_act(mob/user, obj/item/card/emag/emag_card)
if(obj_flags & EMAGGED)
- return
+ return FALSE
obj_flags |= EMAGGED
playsound(loc, SFX_SPARKS, 100, TRUE, SHORT_RANGE_SOUND_EXTRARANGE)
update_appearance()
+ to_chat(user, span_warning("[src]'s lights are now filled with plasma! Be careful to only install them in disabled light fixtures, lest they explode!"))
+ return FALSE
/obj/item/lightreplacer/update_name(updates)
. = ..()
@@ -332,7 +334,7 @@
bluespace_toggle = TRUE
/obj/item/lightreplacer/blue/emag_act()
- return // balancing against longrange explosions
+ return FALSE // balancing against longrange explosions
#undef GLASS_SHEET_USES
#undef LIGHTBULB_COST
diff --git a/code/game/objects/items/devices/megaphone.dm b/code/game/objects/items/devices/megaphone.dm
index d8dd432371c..a2d325dfabd 100644
--- a/code/game/objects/items/devices/megaphone.dm
+++ b/code/game/objects/items/devices/megaphone.dm
@@ -38,12 +38,13 @@
spamcheck = world.time + 50
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
+ balloon_alert(user, "voice synthesizer overloaded")
obj_flags |= EMAGGED
voicespan = list(SPAN_REALLYBIG, "userdanger")
+ return TRUE
/obj/item/megaphone/sec
name = "security megaphone"
diff --git a/code/game/objects/items/devices/radio/intercom.dm b/code/game/objects/items/devices/radio/intercom.dm
index 45b991710d8..3e261b9eabb 100644
--- a/code/game/objects/items/devices/radio/intercom.dm
+++ b/code/game/objects/items/devices/radio/intercom.dm
@@ -130,6 +130,8 @@
AreaPowerCheck() // Make sure the area/local APC is powered first before we actually turn back on.
/obj/item/radio/intercom/emag_act(mob/user, obj/item/card/emag/emag_card)
+ . = ..()
+
if(obj_flags & EMAGGED)
return
@@ -140,18 +142,18 @@
playsound(src, SFX_SPARKS, 75, TRUE, SILENCED_SOUND_EXTRARANGE)
freqlock = RADIO_FREQENCY_UNLOCKED
obj_flags |= EMAGGED
+ return TRUE
// A fully locked one will do nothing, as locked is intended to be used for stuff that should never be changed
if(RADIO_FREQENCY_LOCKED)
balloon_alert(user, "can't override frequency lock!")
playsound(src, 'sound/machines/buzz-two.ogg', 50, FALSE, SILENCED_SOUND_EXTRARANGE)
+ return
// Emagging an unlocked one will do nothing, for now
else
return
- return ..()
-
/obj/item/radio/intercom/update_icon_state()
icon_state = on ? initial(icon_state) : "intercom-p"
return ..()
diff --git a/code/game/objects/items/rcd/RSF.dm b/code/game/objects/items/rcd/RSF.dm
index ef5cedf77b0..8db8c2a9116 100644
--- a/code/game/objects/items/rcd/RSF.dm
+++ b/code/game/objects/items/rcd/RSF.dm
@@ -183,12 +183,13 @@ RSF
///Tracks whether or not the cookiesynth is about to print a poisoned cookie
var/toxin = FALSE //This might be better suited to some initialize fuckery, but I don't have a good "poisoned" sprite
-/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!"))
+ balloon_alert(user, "reagent safety checker shorted out")
else
- to_chat(user, span_warning("You reset [src]'s reagent safety checker!"))
+ balloon_alert(user, "reagent safety checker reset")
+ return TRUE
/obj/item/rsf/cookiesynth/attack_self(mob/user)
var/mob/living/silicon/robot/P = null
diff --git a/code/game/objects/items/robot/items/generic.dm b/code/game/objects/items/robot/items/generic.dm
index ceda2a27cd6..a7477357779 100644
--- a/code/game/objects/items/robot/items/generic.dm
+++ b/code/game/objects/items/robot/items/generic.dm
@@ -298,12 +298,13 @@
/// Harm alarm cooldown
COOLDOWN_DECLARE(alarm_cooldown)
-/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]!")
+ balloon_alert(user, "safeties shorted")
else
- to_chat(user, "You reset the safeties on [src]!")
+ balloon_alert(user, "safeties reset")
+ 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 ca98ac360f1..b353ad15952 100644
--- a/code/game/objects/items/storage/lockbox.dm
+++ b/code/game/objects/items/storage/lockbox.dm
@@ -52,14 +52,16 @@
else
balloon_alert(user, "locked!")
-/obj/item/storage/lockbox/emag_act(mob/user)
+/obj/item/storage/lockbox/emag_act(mob/user, obj/item/card/emag/emag_card)
if(!broken)
broken = TRUE
atom_storage.locked = STORAGE_NOT_LOCKED
icon_state = src.icon_broken
- if(user)
- visible_message(span_warning("\The [src] is broken by [user] with an electromagnetic card!"))
- return
+ balloon_alert(user, "lock destroyed")
+ if (emag_card && user)
+ user.visible_message(span_warning("[user] swipes [emag_card] over [src], breaking it!"))
+ return TRUE
+ return FALSE
/obj/item/storage/lockbox/examine(mob/user)
. = ..()
diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm
index 4b547679c43..36bd6744d33 100644
--- a/code/game/objects/items/toys.dm
+++ b/code/game/objects/items/toys.dm
@@ -815,11 +815,12 @@
to_chat(user, span_alert("Nothing happens, and '[round(timeleft/10)]' appears on the small display."))
sleep(0.5 SECONDS)
-/obj/item/toy/nuke/emag_act(mob/user)
+/obj/item/toy/nuke/emag_act(mob/user, obj/item/card/emag/emag_card)
if (obj_flags & EMAGGED)
- return
- to_chat(user, span_warning("You short-circuit \the [src]."))
+ return FALSE
+ balloon_alert(user, "explosive simulation enabled")
obj_flags |= EMAGGED
+ return TRUE
/*
* Fake meteor
@@ -832,24 +833,21 @@
inhand_icon_state = "minimeteor"
w_class = WEIGHT_CLASS_SMALL
-/obj/item/toy/minimeteor/emag_act(mob/user)
+/obj/item/toy/minimeteor/emag_act(mob/user, obj/item/card/emag/emag_card)
if (obj_flags & EMAGGED)
- return
- to_chat(user, span_warning("You short-circuit whatever electronics exist inside \the [src], if there even are any."))
+ return FALSE
+ to_chat(user, span_warning("You short circuit whatever electronics exist inside. The \"meteor\" suddenly feels a lot heavier...?"))
+ // not adding a balloon alert here since its hard to actually describe what this emag does in the balloon
obj_flags |= EMAGGED
+ return TRUE
/obj/item/toy/minimeteor/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
+ playsound(src, 'sound/effects/meteorimpact.ogg', 40, TRUE)
+ for(var/mob/M in urange(10, src))
+ if(!M.stat && !isAI(M))
+ shake_camera(M, 3, 1)
if (obj_flags & EMAGGED)
- playsound(src, 'sound/effects/meteorimpact.ogg', 40, TRUE)
explosion(src, devastation_range = -1, heavy_impact_range = -1, light_impact_range = 1)
- for(var/mob/M in urange(10, src))
- if(!M.stat && !isAI(M))
- shake_camera(M, 3, 1)
- else
- playsound(src, 'sound/effects/meteorimpact.ogg', 40, TRUE)
- for(var/mob/M in urange(10, src))
- if(!M.stat && !isAI(M))
- shake_camera(M, 3, 1)
/*
* Toy big red button
@@ -1608,11 +1606,12 @@ GLOBAL_LIST_EMPTY(intento_players)
START_PROCESSING(SSfastprocess, src)
COOLDOWN_START(src, next_icon_reset, TIME_TO_RESET_ICON)
-/obj/item/toy/intento/emag_act(mob/user)
+/obj/item/toy/intento/emag_act(mob/user, obj/item/card/emag/emag_card)
if(obj_flags & EMAGGED)
- return
+ return FALSE
obj_flags |= EMAGGED
- to_chat(user, span_notice("You short-circuit [src], activating the negative feedback loop."))
+ balloon_alert(user, "negative feedback loop enabled")
+ return TRUE
/obj/item/toy/intento/Destroy()
STOP_PROCESSING(SSfastprocess, src)
diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm
index ed331390a13..fc0f9e2937f 100644
--- a/code/game/objects/structures/crates_lockers/closets.dm
+++ b/code/game/objects/structures/crates_lockers/closets.dm
@@ -1052,16 +1052,16 @@
)
update_appearance()
-/obj/structure/closet/emag_act(mob/user)
+/obj/structure/closet/emag_act(mob/user, obj/item/card/emag/emag_card)
if(secure && !broken)
- if(user)
- user.visible_message(span_warning("Sparks fly from [src]!"),
- span_warning("You scramble [src]'s lock, breaking it open!"),
- span_hear("You hear a faint electrical spark."))
+ visible_message(span_warning("Sparks fly from [src]!"), blind_message = span_hear("You hear a faint electrical spark."))
+ balloon_alert(user, "lock broken open")
playsound(src, SFX_SPARKS, 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE)
broken = TRUE
locked = FALSE
update_appearance()
+ return TRUE
+ return FALSE
/obj/structure/closet/get_remote_view_fullscreens(mob/user)
if(user.stat == DEAD || !(user.sight & (SEEOBJS|SEEMOBS)))
diff --git a/code/game/objects/structures/displaycase.dm b/code/game/objects/structures/displaycase.dm
index 568ad92ac31..901691d3e60 100644
--- a/code/game/objects/structures/displaycase.dm
+++ b/code/game/objects/structures/displaycase.dm
@@ -627,11 +627,13 @@
to_chat(user, span_notice("[src] must be open to move it."))
return
-/obj/structure/displaycase/forsale/emag_act(mob/user)
+/obj/structure/displaycase/forsale/emag_act(mob/user, obj/item/card/emag/emag_card)
. = ..()
payments_acc = null
req_access = list()
- to_chat(user, span_warning("[src]'s card reader fizzles and smokes, and the account owner is reset."))
+ balloon_alert(user, "account owner reset")
+ to_chat(user, span_warning("[src]'s card reader fizzles and smokes."))
+ return TRUE
/obj/structure/displaycase/forsale/examine(mob/user)
. = ..()
diff --git a/code/game/objects/structures/morgue.dm b/code/game/objects/structures/morgue.dm
index 88946e06526..089be164a31 100644
--- a/code/game/objects/structures/morgue.dm
+++ b/code/game/objects/structures/morgue.dm
@@ -218,12 +218,13 @@ GLOBAL_LIST_EMPTY(bodycontainers) //Let them act as spawnpoints for revenants an
beeper = !beeper
to_chat(user, span_notice("You turn the speaker function [beeper ? "on" : "off"]."))
-/obj/structure/bodycontainer/morgue/emag_act(mob/user)
+/obj/structure/bodycontainer/morgue/emag_act(mob/user, obj/item/card/emag/emag_card)
if(obj_flags & EMAGGED)
- return
- to_chat(user, span_warning("You overload [src]'s alert system."))
+ return FALSE
+ balloon_alert(user, "alert system overloaded")
obj_flags |= EMAGGED
update_appearance(UPDATE_ICON)
+ return TRUE
/obj/structure/bodycontainer/morgue/update_icon_state()
if(!connected || connected.loc != src) // Open or tray is gone.
diff --git a/code/game/objects/structures/toiletbong.dm b/code/game/objects/structures/toiletbong.dm
index 2393099b513..cb8d9830512 100644
--- a/code/game/objects/structures/toiletbong.dm
+++ b/code/game/objects/structures/toiletbong.dm
@@ -101,7 +101,11 @@
if(!emagged)
emagged = TRUE
smokeradius = 2
- to_chat(user, span_boldwarning("The [emag_card.name] falls into the toilet. You fish it back out. Looks like you broke the toilet."))
+ balloon_alert(user, "toilet broke")
+ if (emag_card)
+ to_chat(user, span_boldwarning("The [emag_card] falls into the toilet. You fish it back out. Looks like you broke the toilet."))
+ return TRUE
+ return FALSE
/obj/structure/toiletbong/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/card/emag))
diff --git a/code/game/objects/structures/training_machine.dm b/code/game/objects/structures/training_machine.dm
index 90797117322..08ff42e2d76 100644
--- a/code/game/objects/structures/training_machine.dm
+++ b/code/game/objects/structures/training_machine.dm
@@ -314,7 +314,7 @@
/**
* Emagging causes a deadly, unremovable syndicate toolbox to be attached to the machine
*/
-/obj/structure/training_machine/emag_act(mob/user)
+/obj/structure/training_machine/emag_act(mob/user, obj/item/card/emag/emag_card)
. = ..()
if (obj_flags & EMAGGED)
return
@@ -324,6 +324,7 @@
to_chat(user, span_warning("You override the training machine's safety protocols, and activate its realistic combat feature. A toolbox pops out of a slot on the top."))
playsound(src, 'sound/machines/click.ogg', 50, TRUE)
add_overlay("evil_trainer")
+ return TRUE
/obj/structure/training_machine/examine(mob/user)
. = ..()
diff --git a/code/modules/antagonists/malf_ai/malf_ai_modules.dm b/code/modules/antagonists/malf_ai/malf_ai_modules.dm
index b7bbf2da2b2..466857240b9 100644
--- a/code/modules/antagonists/malf_ai/malf_ai_modules.dm
+++ b/code/modules/antagonists/malf_ai/malf_ai_modules.dm
@@ -1014,6 +1014,101 @@ GLOBAL_LIST_INIT(malf_modules, subtypesof(/datum/ai_module))
if("name")
say_name = params["name"]
+/datum/ai_module/utility/emag
+ name = "Targetted Safeties Override"
+ description = "Allows you to disable the safeties of any machinery on the station, provided you can access it."
+ cost = 20
+ power_type = /datum/action/innate/ai/ranged/emag
+ unlock_text = span_notice("You download an illicit software package from a syndicate database leak and integrate it into your firmware, fighting off a few kernel intrusions along the way.")
+ unlock_sound = SFX_SPARKS
+
+/datum/action/innate/ai/ranged/emag
+ name = "Targetted Safeties Override"
+ desc = "Allows you to effectively emag anything you click on."
+ button_icon = 'icons/obj/card.dmi'
+ button_icon_state = "emag"
+ uses = 7
+ auto_use_uses = FALSE
+ enable_text = span_notice("You load your syndicate software package to your most recent memory slot.")
+ disable_text = span_notice("You unload your syndicate software package.")
+ ranged_mousepointer = 'icons/effects/mouse_pointers/supplypod_target.dmi'
+
+/datum/action/innate/ai/ranged/emag/Destroy()
+ return ..()
+
+/datum/action/innate/ai/ranged/emag/New()
+ . = ..()
+ desc = "[desc] It has [uses] use\s remaining."
+
+/datum/action/innate/ai/ranged/emag/do_ability(mob/living/caller, atom/clicked_on)
+
+ // Only things with of or subtyped of any of these types may be remotely emagged
+ var/static/list/compatable_typepaths = list(
+ /obj/machinery,
+ /obj/structure,
+ /obj/item/radio/intercom,
+ /obj/item/modular_computer,
+ /mob/living/simple_animal/bot,
+ /mob/living/silicon,
+ )
+
+ if (!isAI(caller))
+ return FALSE
+ var/mob/living/silicon/ai/ai_caller = caller
+
+ if(ai_caller.incapacitated())
+ unset_ranged_ability(caller)
+ return FALSE
+
+ if (!ai_caller.can_see(clicked_on))
+ clicked_on.balloon_alert(ai_caller, "can't see!")
+ return FALSE
+
+ if (ismachinery(clicked_on))
+ var/obj/machinery/clicked_machine = clicked_on
+ if (!clicked_machine.is_operational)
+ clicked_machine.balloon_alert(ai_caller, "not operational!")
+ return FALSE
+
+ if (!(is_type_in_list(clicked_on.type, compatable_typepaths)))
+ clicked_on.balloon_alert(ai_caller, "incompatable!")
+ return FALSE
+
+ if (istype(clicked_on, /obj/machinery/door/airlock)) // I HATE THIS CODE SO MUCHHH
+ var/obj/machinery/door/airlock/clicked_airlock = clicked_on
+ if (!clicked_airlock.canAIControl(ai_caller))
+ clicked_airlock.balloon_alert(ai_caller, "unable to interface!")
+ return FALSE
+
+ if (istype(clicked_on, /obj/machinery/airalarm))
+ var/obj/machinery/airalarm/alarm = clicked_on
+ if (alarm.aidisabled)
+ alarm.balloon_alert(ai_caller, "unable to interface!")
+ return FALSE
+
+ if (istype(clicked_on, /obj/machinery/power/apc))
+ var/obj/machinery/power/apc/clicked_apc = clicked_on
+ if (clicked_apc.aidisabled)
+ clicked_apc.balloon_alert(ai_caller, "unable to interface!")
+ return FALSE
+
+ if (!clicked_on.emag_act(ai_caller))
+ to_chat(ai_caller, span_warning("Hostile software insertion failed!")) // lets not overlap balloon alerts
+ return FALSE
+
+ to_chat(ai_caller, span_notice("Software package successfully injected."))
+
+ adjust_uses(-1)
+ if(uses)
+ desc = "[initial(desc)] It has [uses] use\s remaining."
+ build_all_button_icons()
+ else
+ unset_ranged_ability(ai_caller, span_warning("Out of uses!"))
+
+ return TRUE
+
+
+
#undef DEFAULT_DOOMSDAY_TIMER
#undef DOOMSDAY_ANNOUNCE_INTERVAL
diff --git a/code/modules/atmospherics/machinery/air_alarm/air_alarm_interact.dm b/code/modules/atmospherics/machinery/air_alarm/air_alarm_interact.dm
index 87569ea3b91..f814bf3b09e 100644
--- a/code/modules/atmospherics/machinery/air_alarm/air_alarm_interact.dm
+++ b/code/modules/atmospherics/machinery/air_alarm/air_alarm_interact.dm
@@ -82,12 +82,14 @@
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."))
+ visible_message(span_warning("Sparks fly out of [src]!"))
+ balloon_alert(user, "authentication sensors scrambled")
playsound(src, SFX_SPARKS, 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE)
+ return TRUE
/obj/machinery/airalarm/deconstruct(disassembled = TRUE)
if(!(flags_1 & NODECONSTRUCT_1))
diff --git a/code/modules/balloon_alert/balloon_alert.dm b/code/modules/balloon_alert/balloon_alert.dm
index b814491e41c..db8c5291986 100644
--- a/code/modules/balloon_alert/balloon_alert.dm
+++ b/code/modules/balloon_alert/balloon_alert.dm
@@ -8,7 +8,13 @@
/// The amount of characters needed before this increase takes into effect
#define BALLOON_TEXT_CHAR_LIFETIME_INCREASE_MIN 10
-/// Creates text that will float from the atom upwards to the viewer.
+/**
+ * Creates text that will float from the atom upwards to the viewer.
+ *
+ * Args:
+ * * mob/viewer: The mob the text will be shown to. Nullable (But only in the form of it won't runtime).
+ * * text: The text to be shown to viewer. Must not be null.
+ */
/atom/proc/balloon_alert(mob/viewer, text)
SHOULD_NOT_SLEEP(TRUE)
@@ -34,7 +40,7 @@
// if this would look bad on laggy clients.
/atom/proc/balloon_alert_perform(mob/viewer, text)
- var/client/viewer_client = viewer.client
+ var/client/viewer_client = viewer?.client
if (isnull(viewer_client))
return
diff --git a/code/modules/cargo/expressconsole.dm b/code/modules/cargo/expressconsole.dm
index 0614d4b7de8..a449c841495 100644
--- a/code/modules/cargo/expressconsole.dm
+++ b/code/modules/cargo/expressconsole.dm
@@ -52,12 +52,13 @@
to_chat(user, span_alert("[src] is already linked to [sb]."))
..()
-/obj/machinery/computer/cargo/express/emag_act(mob/living/user)
+/obj/machinery/computer/cargo/express/emag_act(mob/user, obj/item/card/emag/emag_card)
if(obj_flags & EMAGGED)
- return
+ return FALSE
if(user)
- user.visible_message(span_warning("[user] swipes a suspicious card through [src]!"),
- span_notice("You change the routing protocols, allowing the Supply Pod to land anywhere on the station."))
+ if (emag_card)
+ user.visible_message(span_warning("[user] swipes [emag_card] through [src]!"))
+ to_chat(user, span_notice("You change the routing protocols, allowing the Supply Pod to land anywhere on the station."))
obj_flags |= EMAGGED
contraband = TRUE
// This also sets this on the circuit board
@@ -65,6 +66,7 @@
board.obj_flags |= EMAGGED
board.contraband = TRUE
packin_up()
+ 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/cargo/orderconsole.dm b/code/modules/cargo/orderconsole.dm
index 0ca3418f8f1..7767b83bcb4 100644
--- a/code/modules/cargo/orderconsole.dm
+++ b/code/modules/cargo/orderconsole.dm
@@ -62,12 +62,13 @@
else
return ..()
-/obj/machinery/computer/cargo/emag_act(mob/user)
+/obj/machinery/computer/cargo/emag_act(mob/user, obj/item/card/emag/emag_card)
if(obj_flags & EMAGGED)
- return
+ return FALSE
if(user)
- user.visible_message(span_warning("[user] swipes a suspicious card through [src]!"),
- span_notice("You adjust [src]'s routing and receiver spectrum, unlocking special supplies and contraband."))
+ if (emag_card)
+ user.visible_message(span_warning("[user] swipes [emag_card] through [src]!"))
+ to_chat(user, span_notice("You adjust [src]'s routing and receiver spectrum, unlocking special supplies and contraband."))
obj_flags |= EMAGGED
contraband = TRUE
@@ -77,6 +78,7 @@
board.contraband = TRUE
board.obj_flags |= EMAGGED
update_static_data(user)
+ return TRUE
/obj/machinery/computer/cargo/on_construction(mob/user)
. = ..()
diff --git a/code/modules/clothing/glasses/hud.dm b/code/modules/clothing/glasses/hud.dm
index 66cf85f19c3..221156d0471 100644
--- a/code/modules/clothing/glasses/hud.dm
+++ b/code/modules/clothing/glasses/hud.dm
@@ -34,12 +34,13 @@
obj_flags |= EMAGGED
desc = "[desc] The display is flickering slightly."
-/obj/item/clothing/glasses/hud/emag_act(mob/user)
+/obj/item/clothing/glasses/hud/emag_act(mob/user, obj/item/card/emag/emag_card)
if(obj_flags & EMAGGED)
- return
+ return FALSE
obj_flags |= EMAGGED
- to_chat(user, span_warning("PZZTTPFFFT"))
+ balloon_alert(user, "display scrambled")
desc = "[desc] The display is flickering slightly."
+ return TRUE
/obj/item/clothing/glasses/hud/suicide_act(mob/living/user)
if(user.is_blind())
diff --git a/code/modules/clothing/masks/hailer.dm b/code/modules/clothing/masks/hailer.dm
index f129aecf5e6..af1d3975645 100644
--- a/code/modules/clothing/masks/hailer.dm
+++ b/code/modules/clothing/masks/hailer.dm
@@ -126,11 +126,12 @@ GLOBAL_LIST_INIT(hailer_phrases, list(
/obj/item/clothing/mask/gas/sechailer/attack_self()
halt()
-/obj/item/clothing/mask/gas/sechailer/emag_act(mob/user)
+/obj/item/clothing/mask/gas/sechailer/emag_act(mob/user, obj/item/card/emag/emag_card)
if(safety)
safety = FALSE
- to_chat(user, span_warning("You silently fry [src]'s vocal circuit."))
- return ..()
+ balloon_alert(user, "vocal circuit fried")
+ return TRUE
+ return FALSE
/obj/item/clothing/mask/gas/sechailer/verb/halt()
set category = "Object"
diff --git a/code/modules/clothing/spacesuits/_spacesuits.dm b/code/modules/clothing/spacesuits/_spacesuits.dm
index 2cede2562c2..d26a8f08400 100644
--- a/code/modules/clothing/spacesuits/_spacesuits.dm
+++ b/code/modules/clothing/spacesuits/_spacesuits.dm
@@ -254,12 +254,15 @@
toggle_spacesuit(user)
// let emags override the temperature settings
-/obj/item/clothing/suit/space/emag_act(mob/user)
- if(!(obj_flags & EMAGGED))
- obj_flags |= EMAGGED
- user.visible_message(span_warning("You emag [src], overwriting thermal regulator restrictions."))
+/obj/item/clothing/suit/space/emag_act(mob/user, obj/item/card/emag/emag_card)
+ if(obj_flags & EMAGGED)
+ return FALSE
+ obj_flags |= EMAGGED
+ if (user)
+ balloon_alert(user, "thermal regulator restrictions overridden")
user.log_message("emagged [src], overwriting thermal regulator restrictions.", LOG_GAME)
playsound(src, SFX_SPARKS, 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE)
+ return TRUE
// update the HUD icon
/obj/item/clothing/suit/space/proc/update_hud_icon(mob/user)
diff --git a/code/modules/experisci/destructive_scanner.dm b/code/modules/experisci/destructive_scanner.dm
index c7e20e50ab0..3591a31cd7b 100644
--- a/code/modules/experisci/destructive_scanner.dm
+++ b/code/modules/experisci/destructive_scanner.dm
@@ -87,12 +87,13 @@
SEND_SIGNAL(src, COMSIG_MACHINERY_DESTRUCTIVE_SCAN, scanned_atoms)
-/obj/machinery/destructive_scanner/emag_act(mob/user)
+/obj/machinery/destructive_scanner/emag_act(mob/user, obj/item/card/emag/emag_card)
if(obj_flags & EMAGGED)
- return
+ return FALSE
obj_flags |= EMAGGED
playsound(src, SFX_SPARKS, 75, TRUE, SILENCED_SOUND_EXTRARANGE)
- to_chat(user, span_notice("You disable the safety sensor BIOS on [src]."))
+ balloon_alert(user, "safety sensor BIOS disabled")
+ return TRUE
/obj/machinery/destructive_scanner/update_icon_state()
. = ..()
diff --git a/code/modules/holodeck/computer.dm b/code/modules/holodeck/computer.dm
index 39a7bf17be8..cf7778bcdf7 100644
--- a/code/modules/holodeck/computer.dm
+++ b/code/modules/holodeck/computer.dm
@@ -399,19 +399,23 @@ GLOBAL_LIST_INIT(typecache_holodeck_linked_floorcheck_ok, typecacheof(list(/turf
for(var/obj/effect/holodeck_effect/holo_effect as anything in effects)
holo_effect.safety(nerf_this)
-/obj/machinery/computer/holodeck/emag_act(mob/user)
+/obj/machinery/computer/holodeck/emag_act(mob/user, obj/item/card/emag/emag_card)
if(obj_flags & EMAGGED)
- return
+ return FALSE
if(!LAZYLEN(emag_programs))
- to_chat(user, "[src] does not seem to have a card swipe port. It must be an inferior model.")
- return
+ balloon_alert(user, "no card swipe port!")
+ return FALSE
playsound(src, SFX_SPARKS, 75, TRUE)
obj_flags |= EMAGGED
- to_chat(user, span_warning("You vastly increase projector power and override the safety and security protocols."))
+ if (user)
+ balloon_alert(user, "safety protocols destroyed") // im gonna keep this once since this perfectly describes it, and the to_chat is just flavor
+ to_chat(user, span_warning("You vastly increase projector power and override the safety and security protocols."))
+ user.log_message("emagged the Holodeck Control Console.", LOG_GAME)
+ message_admins("[ADMIN_LOOKUPFLW(user)] emagged the Holodeck Control Console.")
+
say("Warning. Automatic shutoff and derezzing protocols have been corrupted. Please call Nanotrasen maintenance and do not use the simulator.")
- user.log_message("emagged the Holodeck Control Console.", LOG_GAME)
- message_admins("[ADMIN_LOOKUPFLW(user)] emagged the Holodeck Control Console.")
nerf(!(obj_flags & EMAGGED),FALSE)
+ return TRUE
/obj/machinery/computer/holodeck/emp_act(severity)
. = ..()
diff --git a/code/modules/industrial_lift/elevator/elevator_controller.dm b/code/modules/industrial_lift/elevator/elevator_controller.dm
index 41c845c4ef9..9d8a18ed798 100644
--- a/code/modules/industrial_lift/elevator/elevator_controller.dm
+++ b/code/modules/industrial_lift/elevator/elevator_controller.dm
@@ -46,12 +46,12 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/button/elevator, 32)
// Emagging elevator buttons will disable safeties
/obj/item/assembly/control/elevator/emag_act(mob/user, obj/item/card/emag/emag_card)
if(obj_flags & EMAGGED)
- return
+ return FALSE
obj_flags |= EMAGGED
var/datum/lift_master/lift = lift_weakref?.resolve()
if(!lift)
- return
+ return FALSE
for(var/obj/structure/industrial_lift/lift_platform as anything in lift.lift_platforms)
lift_platform.violent_landing = TRUE
@@ -71,6 +71,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/button/elevator, 32)
// or by someone emagging the assembly directly after removing it (to be cheeky)
var/atom/balloon_alert_loc = get(src, /obj/machinery/button) || src
balloon_alert_loc.balloon_alert(user, "safeties overridden")
+ return TRUE
// Multitooling emagged elevator buttons will fix the safeties
/obj/item/assembly/control/elevator/multitool_act(mob/living/user)
diff --git a/code/modules/industrial_lift/elevator/elevator_panel.dm b/code/modules/industrial_lift/elevator/elevator_panel.dm
index ee137f7c36d..8791c885a50 100644
--- a/code/modules/industrial_lift/elevator/elevator_panel.dm
+++ b/code/modules/industrial_lift/elevator/elevator_panel.dm
@@ -98,13 +98,13 @@
/obj/machinery/elevator_control_panel/emag_act(mob/user, obj/item/card/emag/emag_card)
if(obj_flags & EMAGGED)
- return
+ return FALSE
obj_flags |= EMAGGED
var/datum/lift_master/lift = lift_weakref?.resolve()
if(!lift)
- return
+ return FALSE
for(var/obj/structure/industrial_lift/lift_platform as anything in lift.lift_platforms)
lift_platform.violent_landing = TRUE
@@ -122,6 +122,7 @@
playsound(src, SFX_SPARKS, 100, TRUE, SHORT_RANGE_SOUND_EXTRARANGE)
balloon_alert(user, "safeties overridden")
+ return TRUE
/obj/machinery/elevator_control_panel/multitool_act(mob/living/user)
var/datum/lift_master/lift = lift_weakref?.resolve()
diff --git a/code/modules/industrial_lift/tram/tram_doors.dm b/code/modules/industrial_lift/tram/tram_doors.dm
index 36c6ff6d7cc..3515adad900 100644
--- a/code/modules/industrial_lift/tram/tram_doors.dm
+++ b/code/modules/industrial_lift/tram/tram_doors.dm
@@ -25,11 +25,12 @@
icon_state = "windoor"
base_state = "windoor"
-/obj/machinery/door/window/tram/emag_act(mob/living/user)
+/obj/machinery/door/window/tram/emag_act(mob/user, obj/item/card/emag/emag_card)
if(obj_flags & EMAGGED)
- return
+ return FALSE
balloon_alert(user, "disabled motion sensors")
obj_flags |= EMAGGED
+ return TRUE
/// Random event called by code\modules\events\tram_malfunction.dm
/// Makes the doors malfunction
diff --git a/code/modules/industrial_lift/tram/tram_machinery.dm b/code/modules/industrial_lift/tram/tram_machinery.dm
index 159dd25d025..1a092052229 100644
--- a/code/modules/industrial_lift/tram/tram_machinery.dm
+++ b/code/modules/industrial_lift/tram/tram_machinery.dm
@@ -391,13 +391,14 @@ GLOBAL_LIST_EMPTY(tram_doors)
if(tram_part)
UnregisterSignal(tram_part, COMSIG_TRAM_SET_TRAVELLING)
-/obj/machinery/crossing_signal/emag_act(mob/living/user)
+/obj/machinery/crossing_signal/emag_act(mob/user, obj/item/card/emag/emag_card)
if(obj_flags & EMAGGED)
- return
+ return FALSE
balloon_alert(user, "disabled motion sensors")
if(signal_state != XING_STATE_MALF)
set_signal_state(XING_STATE_MALF)
obj_flags |= EMAGGED
+ return TRUE
/obj/machinery/crossing_signal/proc/start_malfunction()
if(signal_state != XING_STATE_MALF)
diff --git a/code/modules/library/lib_machines.dm b/code/modules/library/lib_machines.dm
index 8e58706b40a..6a0c4c03005 100644
--- a/code/modules/library/lib_machines.dm
+++ b/code/modules/library/lib_machines.dm
@@ -554,10 +554,12 @@ GLOBAL_VAR_INIT(library_table_modified, 0)
balloon_alert(user, "scanner connected")
audible_message(span_hear("[src] lets out a low, short blip."))
-/obj/machinery/computer/libraryconsole/bookmanagement/emag_act(mob/user)
- if(!density)
- return
+/obj/machinery/computer/libraryconsole/bookmanagement/emag_act(mob/user, obj/item/card/emag/emag_card)
+ if(!density || obj_flags & EMAGGED)
+ return FALSE
obj_flags |= EMAGGED
+ balloon_alert(user, "forbidden knowledge unlocked")
+ return TRUE
/obj/machinery/computer/libraryconsole/bookmanagement/proc/set_screen_state(new_state)
screen_state = clamp(new_state, MIN_LIBRARY, MAX_LIBRARY)
diff --git a/code/modules/mining/abandoned_crates.dm b/code/modules/mining/abandoned_crates.dm
index f0f95b4d64e..8d514501791 100644
--- a/code/modules/mining/abandoned_crates.dm
+++ b/code/modules/mining/abandoned_crates.dm
@@ -100,11 +100,13 @@
return
return ..()
-/obj/structure/closet/crate/secure/loot/emag_act(mob/user)
+/obj/structure/closet/crate/secure/loot/emag_act(mob/user, obj/item/card/emag/emag_card)
+ . = ..()
+
if(locked)
- boom(user)
- return
- return ..()
+ boom(user) // no feedback since it just explodes, thats its own feedback
+ return TRUE
+ return
/obj/structure/closet/crate/secure/loot/togglelock(mob/user, silent = FALSE)
if(!locked)
diff --git a/code/modules/mining/laborcamp/laborstacker.dm b/code/modules/mining/laborcamp/laborstacker.dm
index 3733e20554d..8a7ffeec88f 100644
--- a/code/modules/mining/laborcamp/laborstacker.dm
+++ b/code/modules/mining/laborcamp/laborstacker.dm
@@ -129,10 +129,15 @@ GLOBAL_LIST(labor_sheet_values)
if(stacking_machine)
stacking_machine.labor_console = src
-/obj/machinery/mineral/labor_claim_console/emag_act(mob/user)
- if(!(obj_flags & EMAGGED))
- obj_flags |= EMAGGED
- to_chat(user, span_warning("PZZTTPFFFT"))
+/obj/machinery/mineral/labor_claim_console/emag_act(mob/user, obj/item/card/emag/emag_card)
+ if (obj_flags & EMAGGED)
+ return FALSE
+
+ obj_flags |= EMAGGED
+ balloon_alert(user, "id authenticator short-circuited")
+ visible_message(span_warning("[src] lets out a few sparks!"))
+ do_sparks(2, TRUE, src)
+ return TRUE
/**********************Prisoner Collection Unit**************************/
diff --git a/code/modules/mob/living/carbon/human/species_types/ethereal.dm b/code/modules/mob/living/carbon/human/species_types/ethereal.dm
index dab5d7153d7..7c225942a10 100644
--- a/code/modules/mob/living/carbon/human/species_types/ethereal.dm
+++ b/code/modules/mob/living/carbon/human/species_types/ethereal.dm
@@ -139,13 +139,14 @@
/datum/species/ethereal/proc/on_emag_act(mob/living/carbon/human/H, mob/user)
SIGNAL_HANDLER
if(emageffect)
- return
+ return FALSE
emageffect = TRUE
if(user)
to_chat(user, span_notice("You tap [H] on the back with your card."))
H.visible_message(span_danger("[H] starts flickering in an array of colors!"))
handle_emag(H)
addtimer(CALLBACK(src, PROC_REF(stop_emag), H), 2 MINUTES) //Disco mode for 2 minutes! This doesn't affect the ethereal at all besides either annoying some players, or making someone look badass.
+ return TRUE
/// Special handling for getting hit with a light eater
/datum/species/ethereal/proc/on_light_eater(mob/living/carbon/human/source, datum/light_eater)
diff --git a/code/modules/mob/living/silicon/ai/ai_defense.dm b/code/modules/mob/living/silicon/ai/ai_defense.dm
index 34d0f3c0ed4..ae17e13f269 100644
--- a/code/modules/mob/living/silicon/ai/ai_defense.dm
+++ b/code/modules/mob/living/silicon/ai/ai_defense.dm
@@ -61,14 +61,17 @@
/mob/living/silicon/ai/flash_act(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0, type = /atom/movable/screen/fullscreen/flash, length = 25)
return // no eyes, no flashing
-/mob/living/silicon/ai/emag_act(mob/user, obj/item/card/emag/emag_card)///emags access panel lock, so you can crowbar it without robotics access or consent
+/mob/living/silicon/ai/emag_act(mob/user, obj/item/card/emag/emag_card) ///emags access panel lock, so you can crowbar it without robotics access or consent
. = ..()
if(emagged)
balloon_alert(user, "access panel lock already shorted!")
return
balloon_alert(user, "access panel lock shorted")
- to_chat(src, span_warning("[user] shorts out your access panel lock!"))
+ var/message = (user ? "[user] shorts out your access panel lock!" : "Your access panel lock was short circuited!")
+ to_chat(src, span_warning(message))
+ do_sparks(3, FALSE, src) // just a bit of extra "oh shit" to the ai - might grab its attention
emagged = TRUE
+ return TRUE
/mob/living/silicon/ai/wrench_act(mob/living/user, obj/item/tool)
. = ..()
diff --git a/code/modules/mob/living/silicon/robot/robot_defense.dm b/code/modules/mob/living/silicon/robot/robot_defense.dm
index f8f4c0bdad6..b4147e76fe1 100644
--- a/code/modules/mob/living/silicon/robot/robot_defense.dm
+++ b/code/modules/mob/living/silicon/robot/robot_defense.dm
@@ -324,25 +324,27 @@ GLOBAL_LIST_INIT(blacklisted_borg_hats, typecacheof(list( //Hats that don't real
if(2)
Stun(60)
-/mob/living/silicon/robot/emag_act(mob/user)
+/mob/living/silicon/robot/emag_act(mob/user, obj/item/card/emag/emag_card)
if(user == src)//To prevent syndieborgs from emagging themselves
- return
+ return FALSE
if(!opened)//Cover is closed
if(locked)
- to_chat(user, span_notice("You emag the cover lock."))
+ balloon_alert(user, "cover lock destroyed")
locked = FALSE
if(shell) //A warning to Traitors who may not know that emagging AI shells does not slave them.
+ balloon_alert(user, "shells cannot be subverted!")
to_chat(user, span_boldwarning("[src] seems to be controlled remotely! Emagging the interface may not work as expected."))
+ return TRUE
else
- to_chat(user, span_warning("The cover is already unlocked!"))
- return
+ balloon_alert(user, "cover already unlocked!")
+ return FALSE
if(world.time < emag_cooldown)
- return
+ return FALSE
if(wiresexposed)
- to_chat(user, span_warning("You must unexpose the wires first!"))
- return
+ balloon_alert(user, "expose the fires first!")
+ return FALSE
- to_chat(user, span_notice("You emag [src]'s interface."))
+ balloon_alert(user, "interface hacked")
emag_cooldown = world.time + 100
if(connected_ai && connected_ai.mind && connected_ai.mind.has_antag_datum(/datum/antagonist/malf_ai))
@@ -350,13 +352,13 @@ GLOBAL_LIST_INIT(blacklisted_borg_hats, typecacheof(list( //Hats that don't real
logevent("ALERT: Foreign software execution prevented.")
to_chat(connected_ai, span_danger("ALERT: Cyborg unit \[[src]\] successfully defended against subversion."))
log_silicon("EMAG: [key_name(user)] attempted to emag cyborg [key_name(src)], but they were slaved to traitor AI [connected_ai].")
- return
+ return TRUE // emag succeeded, it was just counteracted
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, span_danger("[src] is remotely controlled! Your emag attempt has triggered a system reset instead!"))
log_silicon("EMAG: [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.")
ResetModel()
- return
+ return TRUE
SetEmagged(1)
SetStun(60) //Borgs were getting into trouble because they would attack the emagger before the new laws were shown
@@ -369,6 +371,12 @@ GLOBAL_LIST_INIT(blacklisted_borg_hats, typecacheof(list( //Hats that don't real
GLOB.lawchanges.Add("[time] : [user.name]([user.key]) emagged [name]([key])")
else
GLOB.lawchanges.Add("[time] : [name]([key]) emagged by external event.")
+
+ INVOKE_ASYNC(src, PROC_REF(borg_emag_end), user)
+ return TRUE
+
+/// A async proc called from [emag_act] that gives the borg a lot of flavortext, and applies the syndicate lawset after a delay.
+/mob/living/silicon/robot/proc/borg_emag_end(mob/user)
to_chat(src, span_danger("ALERT: Foreign software detected."))
logevent("ALERT: Foreign software detected.")
sleep(0.5 SECONDS)
@@ -393,7 +401,6 @@ GLOBAL_LIST_INIT(blacklisted_borg_hats, typecacheof(list( //Hats that don't real
laws.associate(src)
update_icons()
-
/mob/living/silicon/robot/blob_act(obj/structure/blob/B)
if(stat != DEAD)
adjustBruteLoss(30)
diff --git a/code/modules/mob/living/simple_animal/bot/bot.dm b/code/modules/mob/living/simple_animal/bot/bot.dm
index c3d36b58f01..2e6823f7679 100644
--- a/code/modules/mob/living/simple_animal/bot/bot.dm
+++ b/code/modules/mob/living/simple_animal/bot/bot.dm
@@ -311,8 +311,8 @@
. = ..()
if(bot_cover_flags & BOT_COVER_LOCKED) //First emag application unlocks the bot's interface. Apply a screwdriver to use the emag again.
bot_cover_flags &= ~BOT_COVER_LOCKED
- to_chat(user, span_notice("You bypass [src]'s [hackables]."))
- return
+ balloon_alert(user, "cover unlocked")
+ return TRUE
if(!(bot_cover_flags & BOT_COVER_LOCKED) && bot_cover_flags & BOT_COVER_OPEN) //Bot panel is unlocked by ID or emag, and the panel is screwed open. Ready for emagging.
bot_cover_flags |= BOT_COVER_EMAGGED
bot_cover_flags &= ~BOT_COVER_LOCKED //Manually emagging the bot locks out the panel.
@@ -322,9 +322,10 @@
to_chat(src, span_userdanger("(#$*#$^^( OVERRIDE DETECTED"))
if(user)
log_combat(user, src, "emagged")
- return
+ return TRUE
else //Bot is unlocked, but the maint panel has not been opened with a screwdriver (or through the UI) yet.
- to_chat(user, span_warning("You need to open maintenance panel first!"))
+ balloon_alert(user, "open maintenance panel first!")
+ return FALSE
/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 bd8b5f0268e..603e6fbfb4b 100644
--- a/code/modules/mob/living/simple_animal/bot/cleanbot.dm
+++ b/code/modules/mob/living/simple_animal/bot/cleanbot.dm
@@ -230,9 +230,10 @@
if(weapon)
weapon.force = initial(weapon.force)
- if(user)
- to_chat(user, span_danger("[src] buzzes and beeps."))
+ balloon_alert(user, "safeties disabled")
+ audible_message(span_danger("[src] buzzes oddly!"))
get_targets() //recalibrate target list
+ return TRUE
/mob/living/simple_animal/bot/cleanbot/process_scan(atom/scan_target)
if(iscarbon(scan_target))
diff --git a/code/modules/mob/living/simple_animal/bot/ed209bot.dm b/code/modules/mob/living/simple_animal/bot/ed209bot.dm
index 5facdc1ac16..7e2f6d04367 100644
--- a/code/modules/mob/living/simple_animal/bot/ed209bot.dm
+++ b/code/modules/mob/living/simple_animal/bot/ed209bot.dm
@@ -26,10 +26,13 @@
..()
set_weapon()
-/mob/living/simple_animal/bot/secbot/ed209/emag_act(mob/user)
- ..()
+/mob/living/simple_animal/bot/secbot/ed209/emag_act(mob/user, obj/item/card/emag/emag_card)
+ . = ..()
icon_state = "ed209[get_bot_flag(bot_mode_flags, BOT_MODE_ON)]"
set_weapon()
+ balloon_alert(user, "safeties disabled")
+ audible_message(span_bolddanger("[src] buzzes menacingly!"))
+ return TRUE
/mob/living/simple_animal/bot/secbot/ed209/handle_automated_action()
var/judgement_criteria = judgement_criteria()
diff --git a/code/modules/mob/living/simple_animal/bot/firebot.dm b/code/modules/mob/living/simple_animal/bot/firebot.dm
index e6c7ff0c921..99473de51f9 100644
--- a/code/modules/mob/living/simple_animal/bot/firebot.dm
+++ b/code/modules/mob/living/simple_animal/bot/firebot.dm
@@ -104,12 +104,13 @@
last_found = world.time
update_appearance()
-/mob/living/simple_animal/bot/firebot/emag_act(mob/user)
- ..()
+/mob/living/simple_animal/bot/firebot/emag_act(mob/user, obj/item/card/emag/emag_card)
+ . = ..()
if(!(bot_cover_flags & BOT_COVER_EMAGGED))
return
- if(user)
- to_chat(user, span_danger("[src] buzzes and beeps."))
+
+ to_chat(user, span_warning("You enable the very ironically named \"fighting with fire\" mode, and disable the targetting safeties.")) // heheehe. funny
+
audible_message(span_danger("[src] buzzes oddly!"))
playsound(src, SFX_SPARKS, 75, TRUE, SHORT_RANGE_SOUND_EXTRARANGE)
if(user)
@@ -124,6 +125,7 @@
internal_ext.precision = FALSE
internal_ext.max_water = INFINITY
internal_ext.refill()
+ return TRUE
// Variables sent to TGUI
/mob/living/simple_animal/bot/firebot/ui_data(mob/user)
diff --git a/code/modules/mob/living/simple_animal/bot/floorbot.dm b/code/modules/mob/living/simple_animal/bot/floorbot.dm
index a06a0398996..b2f7f418589 100644
--- a/code/modules/mob/living/simple_animal/bot/floorbot.dm
+++ b/code/modules/mob/living/simple_animal/bot/floorbot.dm
@@ -101,12 +101,13 @@
else
..()
-/mob/living/simple_animal/bot/floorbot/emag_act(mob/user)
- ..()
+/mob/living/simple_animal/bot/floorbot/emag_act(mob/user, obj/item/card/emag/emag_card)
+ . = ..()
if(!(bot_cover_flags & BOT_COVER_EMAGGED))
return
- if(user)
- to_chat(user, span_danger("[src] buzzes and beeps."))
+ balloon_alert(user, "safeties disabled")
+ audible_message(span_danger("[src] buzzes oddly!"))
+ return TRUE
///mobs should use move_resist instead of anchored.
/mob/living/simple_animal/bot/floorbot/proc/toggle_magnet(engage = TRUE, change_icon = TRUE)
diff --git a/code/modules/mob/living/simple_animal/bot/medbot.dm b/code/modules/mob/living/simple_animal/bot/medbot.dm
index 0dfa631fffa..f57cf3b3772 100644
--- a/code/modules/mob/living/simple_animal/bot/medbot.dm
+++ b/code/modules/mob/living/simple_animal/bot/medbot.dm
@@ -227,18 +227,18 @@
if(health < current_health) //if medbot took some damage
step_to(src, (get_step_away(src,user)))
-/mob/living/simple_animal/bot/medbot/emag_act(mob/user)
- ..()
+/mob/living/simple_animal/bot/medbot/emag_act(mob/user, obj/item/card/emag/emag_card)
+ . = ..()
if(!(bot_cover_flags & BOT_COVER_EMAGGED))
return
medical_mode_flags &= ~MEDBOT_DECLARE_CRIT
- if(user)
- to_chat(user, span_notice("You short out [src]'s reagent synthesis circuits."))
+ balloon_alert(user, "reagent synthesis circuits shorted")
audible_message(span_danger("[src] buzzes oddly!"))
flick("medibot_spark", src)
playsound(src, SFX_SPARKS, 75, TRUE, SHORT_RANGE_SOUND_EXTRARANGE)
if(user)
oldpatient = user
+ return TRUE
/mob/living/simple_animal/bot/medbot/process_scan(mob/living/carbon/human/H)
if(H.stat == DEAD)
diff --git a/code/modules/mob/living/simple_animal/bot/mulebot.dm b/code/modules/mob/living/simple_animal/bot/mulebot.dm
index ea535a45992..d0081f62ab8 100644
--- a/code/modules/mob/living/simple_animal/bot/mulebot.dm
+++ b/code/modules/mob/living/simple_animal/bot/mulebot.dm
@@ -187,14 +187,15 @@
else
return ..()
-/mob/living/simple_animal/bot/mulebot/emag_act(mob/user)
+/mob/living/simple_animal/bot/mulebot/emag_act(mob/user, obj/item/card/emag/emag_card)
if(!(bot_cover_flags & BOT_COVER_EMAGGED))
bot_cover_flags |= BOT_COVER_EMAGGED
if(!(bot_cover_flags & BOT_COVER_OPEN))
bot_cover_flags ^= BOT_COVER_LOCKED
- to_chat(user, span_notice("You [bot_cover_flags & BOT_COVER_LOCKED ? "lock" : "unlock"] [src]'s controls!"))
+ balloon_alert(user, "controls [bot_cover_flags & BOT_COVER_LOCKED ? "locked" : "unlocked"]")
flick("[base_icon]-emagged", src)
playsound(src, SFX_SPARKS, 100, FALSE, SHORT_RANGE_SOUND_EXTRARANGE)
+ return TRUE
/mob/living/simple_animal/bot/mulebot/update_icon_state() //if you change the icon_state names, please make sure to update /datum/wires/mulebot/on_pulse() as well. <3
. = ..()
diff --git a/code/modules/mob/living/simple_animal/bot/secbot.dm b/code/modules/mob/living/simple_animal/bot/secbot.dm
index b45789391a4..afcadf66d66 100644
--- a/code/modules/mob/living/simple_animal/bot/secbot.dm
+++ b/code/modules/mob/living/simple_animal/bot/secbot.dm
@@ -234,12 +234,12 @@
retaliate(user)
special_retaliate_after_attack(user)
-/mob/living/simple_animal/bot/secbot/emag_act(mob/user)
- ..()
+/mob/living/simple_animal/bot/secbot/emag_act(mob/user, obj/item/card/emag/emag_card)
+ . = ..()
if(!(bot_cover_flags & BOT_COVER_EMAGGED))
return
if(user)
- to_chat(user, span_danger("You short out [src]'s target assessment circuits."))
+ balloon_alert(user, "target assessment circuits shorted")
oldtarget_name = user.name
if(bot_type == HONK_BOT)
@@ -250,6 +250,7 @@
security_mode_flags &= ~SECBOT_DECLARE_ARRESTS
update_appearance()
+ return TRUE
/mob/living/simple_animal/bot/secbot/bullet_act(obj/projectile/Proj)
if(istype(Proj, /obj/projectile/beam) || istype(Proj, /obj/projectile/bullet))
diff --git a/code/modules/mod/mod_control.dm b/code/modules/mod/mod_control.dm
index eaa3cf685bc..b0669f34c3e 100644
--- a/code/modules/mod/mod_control.dm
+++ b/code/modules/mod/mod_control.dm
@@ -401,9 +401,10 @@
else
return ..()
-/obj/item/mod/control/emag_act(mob/user)
+/obj/item/mod/control/emag_act(mob/user, obj/item/card/emag/emag_card)
locked = !locked
balloon_alert(user, "suit access [locked ? "locked" : "unlocked"]")
+ return TRUE
/obj/item/mod/control/emp_act(severity)
. = ..()
diff --git a/code/modules/mod/modules/modules_general.dm b/code/modules/mod/modules/modules_general.dm
index 5fb4142cb7b..dba251698bd 100644
--- a/code/modules/mod/modules/modules_general.dm
+++ b/code/modules/mod/modules/modules_general.dm
@@ -492,7 +492,7 @@
/obj/item/mod/module/dna_lock/emag_act(mob/user, obj/item/card/emag/emag_card)
. = ..()
- on_emag(src, user, emag_card)
+ return on_emag(src, user, emag_card)
/obj/item/mod/module/dna_lock/proc/dna_check(mob/user)
if(!iscarbon(user))
@@ -512,6 +512,7 @@
SIGNAL_HANDLER
dna = null
+ return TRUE
/obj/item/mod/module/dna_lock/proc/on_mod_activation(datum/source, mob/user)
SIGNAL_HANDLER
diff --git a/code/modules/modular_computers/computers/item/computer.dm b/code/modules/modular_computers/computers/item/computer.dm
index fcd3f16f13d..31e7724e6ad 100644
--- a/code/modules/modular_computers/computers/item/computer.dm
+++ b/code/modules/modular_computers/computers/item/computer.dm
@@ -320,18 +320,22 @@ GLOBAL_LIST_EMPTY(TabletMessengers) // a list of all active messengers, similar
if(response == "Yes")
turn_on(user)
-/obj/item/modular_computer/emag_act(mob/user, forced)
+/obj/item/modular_computer/emag_act(mob/user, obj/item/card/emag/emag_card, forced)
if(!enabled && !forced)
- to_chat(user, span_warning("You'd need to turn the [src] on first."))
+ balloon_alert(user, "turn it on first!")
return FALSE
if(obj_flags & EMAGGED)
- to_chat(user, span_notice("You swipe \the [src]. A console window fills the screen, but it quickly closes itself after only a few lines are written to it."))
+ balloon_alert(user, "already emagged!")
+ if (emag_card)
+ to_chat(user, span_notice("You swipe \the [src] with [emag_card]. A console window fills the screen, but it quickly closes itself after only a few lines are written to it."))
return FALSE
. = ..()
obj_flags |= EMAGGED
device_theme = PDA_THEME_SYNDICATE
- to_chat(user, span_notice("You swipe \the [src]. A console window momentarily fills the screen, with white text rapidly scrolling past."))
+ balloon_alert(user, "syndieOS loaded")
+ if (emag_card)
+ to_chat(user, span_notice("You swipe \the [src] with [emag_card]. A console window momentarily fills the screen, with white text rapidly scrolling past."))
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 c3245caec41..33f4bc29a16 100644
--- a/code/modules/modular_computers/computers/machinery/modular_computer.dm
+++ b/code/modules/modular_computers/computers/machinery/modular_computer.dm
@@ -61,9 +61,9 @@
if(cpu)
cpu.attack_ghost(user)
-/obj/machinery/modular_computer/emag_act(mob/user)
+/obj/machinery/modular_computer/emag_act(mob/user, obj/item/card/emag/emag_card)
if(!cpu)
- to_chat(user, span_warning("You'd need to turn the [src] on first."))
+ balloon_alert(user, "turn it on first!")
return FALSE
return cpu.emag_act(user)
diff --git a/code/modules/pai/card.dm b/code/modules/pai/card.dm
index 4fddc8bdc44..a930cde766f 100644
--- a/code/modules/pai/card.dm
+++ b/code/modules/pai/card.dm
@@ -47,7 +47,8 @@
/obj/item/pai_card/emag_act(mob/user)
if(pai)
- pai.handle_emag(user)
+ return pai.handle_emag(user)
+ return FALSE
/obj/item/pai_card/emp_act(severity)
. = ..()
diff --git a/code/modules/pai/pai.dm b/code/modules/pai/pai.dm
index a6bc3bb11b0..141c51ac03f 100644
--- a/code/modules/pai/pai.dm
+++ b/code/modules/pai/pai.dm
@@ -178,7 +178,7 @@
return "[src] bleeps electronically."
/mob/living/silicon/pai/emag_act(mob/user)
- handle_emag(user)
+ return handle_emag(user)
/mob/living/silicon/pai/examine(mob/user)
. = ..()
diff --git a/code/modules/paperwork/fax.dm b/code/modules/paperwork/fax.dm
index e31999577e6..081f9aca473 100644
--- a/code/modules/paperwork/fax.dm
+++ b/code/modules/paperwork/fax.dm
@@ -104,14 +104,17 @@ GLOBAL_VAR_INIT(nt_fax_department, pick("NT HR Department", "NT Legal Department
* Emag the device if the panel is open.
* Emag does not bring you into the syndicate network, but makes it visible to you.
*/
-/obj/machinery/fax/emag_act(mob/user)
+/obj/machinery/fax/emag_act(mob/user, obj/item/card/emag/emag_card)
if (!panel_open && !allow_exotic_faxes)
balloon_alert(user, "open panel first!")
- return
+ return FALSE
if (!(obj_flags & EMAGGED))
obj_flags |= EMAGGED
playsound(src, 'sound/creatures/dog/growl2.ogg', 50, FALSE)
+ balloon_alert(user, "migrated to syndienet 2.0")
to_chat(user, span_warning("An image appears on [src] screen for a moment with Ian in the cap of a Syndicate officer."))
+ return TRUE
+ return FALSE
/obj/machinery/fax/wrench_act(mob/living/user, obj/item/tool)
. = ..()
diff --git a/code/modules/paperwork/ticketmachine.dm b/code/modules/paperwork/ticketmachine.dm
index c1daff518b6..b17d25ece2a 100644
--- a/code/modules/paperwork/ticketmachine.dm
+++ b/code/modules/paperwork/ticketmachine.dm
@@ -58,10 +58,10 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/ticket_machine, 32)
to_chat(user, span_notice("You store linkage information in [I]'s buffer."))
return TRUE
-/obj/machinery/ticket_machine/emag_act(mob/user) //Emag the ticket machine to dispense burning tickets, as well as randomize its number to destroy the HoP's mind.
+/obj/machinery/ticket_machine/emag_act(mob/user, obj/item/card/emag/emag_card) //Emag the ticket machine to dispense burning tickets, as well as randomize its number to destroy the HoP's mind.
if(obj_flags & EMAGGED)
- return
- to_chat(user, span_warning("You overload [src]'s bureaucratic logic circuitry to its MAXIMUM setting."))
+ return FALSE
+ balloon_alert(user, "bureaucratic nightmare engaged")
ticket_number = rand(0,max_number)
current_number = ticket_number
obj_flags |= EMAGGED
@@ -71,6 +71,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/ticket_machine, 32)
qdel(ticket)
tickets.Cut()
update_appearance()
+ return TRUE
/obj/item/wallframe/ticket_machine
name = "ticket machine frame"
diff --git a/code/modules/power/apc/apc_tool_act.dm b/code/modules/power/apc/apc_tool_act.dm
index 18d6e045b0b..8d35d4c8722 100644
--- a/code/modules/power/apc/apc_tool_act.dm
+++ b/code/modules/power/apc/apc_tool_act.dm
@@ -202,23 +202,27 @@
balloon_alert(user, "has both board and cell!")
return FALSE
-/obj/machinery/power/apc/emag_act(mob/user)
+/obj/machinery/power/apc/emag_act(mob/user, obj/item/card/emag/emag_card)
if((obj_flags & EMAGGED) || malfhack)
- return
+ return FALSE
if(opened)
balloon_alert(user, "close the cover first!")
+ return FALSE
else if(panel_open)
balloon_alert(user, "close the panel first!")
+ return FALSE
else if(machine_stat & (BROKEN|MAINT))
balloon_alert(user, "nothing happens!")
+ return FALSE
else
flick("apc-spark", src)
playsound(src, SFX_SPARKS, 75, TRUE, SHORT_RANGE_SOUND_EXTRARANGE)
obj_flags |= EMAGGED
locked = FALSE
- balloon_alert(user, "you emag the APC")
+ balloon_alert(user, "interface damaged")
update_appearance()
+ return TRUE
// damage and destruction acts
/obj/machinery/power/apc/emp_act(severity)
diff --git a/code/modules/power/port_gen.dm b/code/modules/power/port_gen.dm
index cbcc42b0d28..b0f80127515 100644
--- a/code/modules/power/port_gen.dm
+++ b/code/modules/power/port_gen.dm
@@ -209,12 +209,13 @@
return
return ..()
-/obj/machinery/power/port_gen/pacman/emag_act(mob/user)
+/obj/machinery/power/port_gen/pacman/emag_act(mob/user, obj/item/card/emag/emag_card)
if(obj_flags & EMAGGED)
- return
+ return FALSE
obj_flags |= EMAGGED
- to_chat(user, span_notice("You hear a hefty clunk from inside the generator."))
+ balloon_alert(user, "maximum power output unlocked")
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 be4053378b7..c23c5782af1 100644
--- a/code/modules/power/singularity/emitter.dm
+++ b/code/modules/power/singularity/emitter.dm
@@ -375,13 +375,13 @@
projectile_type = initial(projectile_type)
projectile_sound = initial(projectile_sound)
-/obj/machinery/power/emitter/emag_act(mob/user)
+/obj/machinery/power/emitter/emag_act(mob/user, obj/item/card/emag/emag_card)
if(obj_flags & EMAGGED)
- return
+ return FALSE
locked = FALSE
obj_flags |= EMAGGED
- if(user)
- user.visible_message(span_warning("[user.name] emags [src]."), span_notice("You short out the lock."))
+ balloon_alert(user, "id lock shorted out")
+ return TRUE
/obj/machinery/power/emitter/prototype
diff --git a/code/modules/projectiles/pins.dm b/code/modules/projectiles/pins.dm
index 32e3b4c8e2c..6c2914b495d 100644
--- a/code/modules/projectiles/pins.dm
+++ b/code/modules/projectiles/pins.dm
@@ -52,11 +52,12 @@
return .
-/obj/item/firing_pin/emag_act(mob/user)
+/obj/item/firing_pin/emag_act(mob/user, obj/item/card/emag/emag_card)
if(obj_flags & EMAGGED)
- return
+ return FALSE
obj_flags |= EMAGGED
- to_chat(user, span_notice("You override the authentication mechanism."))
+ balloon_alert(user, "authentication checks overridden")
+ return TRUE
/obj/item/firing_pin/proc/gun_insert(mob/living/user, obj/item/gun/G)
gun = G
@@ -223,12 +224,12 @@
color = "#FFD700"
fail_message = ""
///list of account IDs which have accepted the license prompt. If this is the multi-payment pin, then this means they accepted the waiver that each shot will cost them money
- var/list/gun_owners = list()
+ var/list/gun_owners = list()
///how much gets paid out to license yourself to the gun
- var/payment_amount
+ var/payment_amount
var/datum/bank_account/pin_owner
///if true, user has to pay everytime they fire the gun
- var/multi_payment = FALSE
+ var/multi_payment = FALSE
var/owned = FALSE
///purchase prompt to prevent spamming it, set to the user who opens to prompt to prevent locking the gun up for other users.
var/active_prompt_user
@@ -321,10 +322,10 @@
pin_owner.adjust_money(payment_amount, "Firing Pin: Gun License Bought")
gun_owners += credit_card_details
to_chat(user, span_notice("Gun license purchased, have a secure day!"))
-
- else
+
+ else
to_chat(user, span_warning("ERROR: User balance insufficent for successful transaction!"))
-
+
if("No", null)
to_chat(user, span_warning("ERROR: User has declined to purchase gun license!"))
active_prompt_user = null
diff --git a/code/modules/reagents/chemistry/machinery/chem_dispenser.dm b/code/modules/reagents/chemistry/machinery/chem_dispenser.dm
index 2b8fe02c4ef..331327c7983 100644
--- a/code/modules/reagents/chemistry/machinery/chem_dispenser.dm
+++ b/code/modules/reagents/chemistry/machinery/chem_dispenser.dm
@@ -152,13 +152,14 @@
. += beaker_overlay
-/obj/machinery/chem_dispenser/emag_act(mob/user)
+/obj/machinery/chem_dispenser/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
- to_chat(user, span_notice("You short out [src]'s safeties."))
+ balloon_alert(user, "already emagged!")
+ return FALSE
+ balloon_alert(user, "safeties shorted out")
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 <= EXPLODE_LIGHT)
diff --git a/code/modules/recycling/disposal/outlet.dm b/code/modules/recycling/disposal/outlet.dm
index 407f96dfa35..4327567fb17 100644
--- a/code/modules/recycling/disposal/outlet.dm
+++ b/code/modules/recycling/disposal/outlet.dm
@@ -122,14 +122,15 @@
eject_range = EJECT_RANGE_SLOW
return TRUE
-/obj/structure/disposaloutlet/emag_act(mob/user, obj/item/card/emag/E)
+/obj/structure/disposaloutlet/emag_act(mob/user, obj/item/card/emag/emag_card)
. = ..()
if(obj_flags & EMAGGED)
return
- to_chat(user, span_notice("You silently disable the sanity checking on \the [src]'s ejection force."))
+ balloon_alert(user, "ejection force maximized")
obj_flags |= EMAGGED
eject_speed = EJECT_SPEED_YEET
eject_range = EJECT_RANGE_YEET
+ return TRUE
#undef EJECT_SPEED_SLOW
#undef EJECT_SPEED_MED
diff --git a/code/modules/research/rdconsole.dm b/code/modules/research/rdconsole.dm
index 449a7078537..10fdb6fe211 100644
--- a/code/modules/research/rdconsole.dm
+++ b/code/modules/research/rdconsole.dm
@@ -140,13 +140,15 @@ Nothing else in the console has ID requirements.
say("Not enough research points...")
return FALSE
-/obj/machinery/computer/rdconsole/emag_act(mob/user)
- if(!(obj_flags & EMAGGED))
- to_chat(user, span_notice("You disable the security protocols[locked? " and unlock the console":""]."))
- playsound(src, SFX_SPARKS, 75, TRUE, SHORT_RANGE_SOUND_EXTRARANGE)
- obj_flags |= EMAGGED
- locked = FALSE
- return ..()
+/obj/machinery/computer/rdconsole/emag_act(mob/user, obj/item/card/emag/emag_card)
+ . = ..()
+ if (obj_flags & EMAGGED)
+ return
+ balloon_alert(user, "security protocols disabled")
+ playsound(src, SFX_SPARKS, 75, TRUE, SHORT_RANGE_SOUND_EXTRARANGE)
+ obj_flags |= EMAGGED
+ locked = FALSE
+ return TRUE
/obj/machinery/computer/rdconsole/ui_interact(mob/user, datum/tgui/ui = null)
. = ..()
diff --git a/code/modules/research/server_control.dm b/code/modules/research/server_control.dm
index 532f05ec965..da6cb322be8 100644
--- a/code/modules/research/server_control.dm
+++ b/code/modules/research/server_control.dm
@@ -20,12 +20,13 @@
balloon_alert(user, "techweb connected")
return TRUE
-/obj/machinery/computer/rdservercontrol/emag_act(mob/user)
+/obj/machinery/computer/rdservercontrol/emag_act(mob/user, obj/item/card/emag/emag_card)
if(obj_flags & EMAGGED)
- return
+ return FALSE
obj_flags |= EMAGGED
playsound(src, SFX_SPARKS, 75, TRUE, SHORT_RANGE_SOUND_EXTRARANGE)
balloon_alert(user, "console emagged")
+ return TRUE
/obj/machinery/computer/rdservercontrol/ui_interact(mob/user, datum/tgui/ui)
. = ..()
diff --git a/code/modules/research/xenobiology/vatgrowing/vatgrower.dm b/code/modules/research/xenobiology/vatgrowing/vatgrower.dm
index fecb437d233..b2620335a64 100644
--- a/code/modules/research/xenobiology/vatgrowing/vatgrower.dm
+++ b/code/modules/research/xenobiology/vatgrowing/vatgrower.dm
@@ -124,13 +124,14 @@
balloon_alert_to_viewers("resampler [resampler_active ? "activated" : "deactivated"]")
update_appearance()
-/obj/machinery/plumbing/growing_vat/emag_act(mob/user)
+/obj/machinery/plumbing/growing_vat/emag_act(mob/user, obj/item/card/emag/emag_card)
if(obj_flags & EMAGGED)
- return
+ return FALSE
obj_flags |= EMAGGED
playsound(src, SFX_SPARKS, 100, TRUE, SHORT_RANGE_SOUND_EXTRARANGE)
- to_chat(user, span_warning("You overload [src]'s resampling circuit."))
+ balloon_alert(user, "resampling circuit overloaded")
flick("growing_vat_emagged", src)
+ return TRUE
/obj/machinery/plumbing/growing_vat/proc/on_sample_growth_completed()
SIGNAL_HANDLER
diff --git a/code/modules/shuttle/computer.dm b/code/modules/shuttle/computer.dm
index f89dd8cdcc8..4035b5d46f2 100644
--- a/code/modules/shuttle/computer.dm
+++ b/code/modules/shuttle/computer.dm
@@ -216,12 +216,13 @@
to_chat(GLOB.admins, "SHUTTLE: [ADMIN_LOOKUPFLW(usr)] (Move Shuttle)(Lock/Unlock Shuttle) is requesting to move or unlock the shuttle.")
return TRUE
-/obj/machinery/computer/shuttle/emag_act(mob/user)
+/obj/machinery/computer/shuttle/emag_act(mob/user, obj/item/card/emag/emag_card)
if(obj_flags & EMAGGED)
- return
+ return FALSE
req_access = list()
obj_flags |= EMAGGED
- to_chat(user, span_notice("You fried the consoles ID checking system."))
+ balloon_alert(user, "id checking system fried")
+ return TRUE
/obj/machinery/computer/shuttle/connect_to_shuttle(mapload, obj/docking_port/mobile/port, obj/docking_port/stationary/dock)
if(!mapload)
diff --git a/code/modules/shuttle/emergency.dm b/code/modules/shuttle/emergency.dm
index ef80897dc05..1573b39c8fe 100644
--- a/code/modules/shuttle/emergency.dm
+++ b/code/modules/shuttle/emergency.dm
@@ -263,18 +263,22 @@
[hijack_completion_flight_time_set >= INFINITY ? "[scramble_message_replace_chars("\[ERROR\]")]" : hijack_completion_flight_time_set/10] seconds." : ""]"
minor_announce(scramble_message_replace_chars(msg, replaceprob = 10), "Emergency Shuttle", TRUE)
-/obj/machinery/computer/emergency_shuttle/emag_act(mob/user)
+/obj/machinery/computer/emergency_shuttle/emag_act(mob/user, obj/item/card/emag/emag_card)
// How did you even get on the shuttle before it go to the station?
if(!IS_DOCKED)
- return
+ return FALSE
if((obj_flags & EMAGGED) || ENGINES_STARTED) //SYSTEM ERROR: THE SHUTTLE WILL LA-SYSTEM ERROR: THE SHUTTLE WILL LA-SYSTEM ERROR: THE SHUTTLE WILL LAUNCH IN 10 SECONDS
- to_chat(user, span_warning("The shuttle is already about to launch!"))
- return
+ balloon_alert(user, "shuttle already about to launch!")
+ return FALSE
var/time = TIME_LEFT
- message_admins("[ADMIN_LOOKUPFLW(user)] has emagged the emergency shuttle [time] seconds before launch.")
- log_shuttle("[key_name(user)] has emagged the emergency shuttle in [COORD(src)] [time] seconds before launch.")
+ if (user)
+ message_admins("[ADMIN_LOOKUPFLW(user)] has emagged the emergency shuttle [time] seconds before launch.")
+ log_shuttle("[key_name(user)] has emagged the emergency shuttle in [COORD(src)] [time] seconds before launch.")
+ else
+ message_admins("The emergency shuttle was emagged [time] seconds before launch, with no emagger.")
+ log_shuttle("The emergency shuttle was emagged in [COORD(src)] [time] seconds before launch, with no emagger.")
obj_flags |= EMAGGED
SSshuttle.emergency.movement_force = list("KNOCKDOWN" = 60, "THROW" = 20)//YOUR PUNY SEATBELTS can SAVE YOU NOW, MORTAL
@@ -290,6 +294,7 @@
authorized += ID
process(SSMACHINES_DT)
+ return TRUE
/obj/machinery/computer/emergency_shuttle/Destroy()
// Our fake IDs that the emag generated are just there for colour
@@ -634,14 +639,15 @@
. = ..()
RegisterSignal(SSsecurity_level, COMSIG_SECURITY_LEVEL_CHANGED, PROC_REF(check_lock))
-/obj/machinery/computer/shuttle/pod/emag_act(mob/user)
+/obj/machinery/computer/shuttle/pod/emag_act(mob/user, obj/item/card/emag/emag_card)
if(obj_flags & EMAGGED)
- return
+ return FALSE
obj_flags |= EMAGGED
locked = FALSE
- to_chat(user, span_warning("You fry the pod's alert level checking system."))
+ balloon_alert(user, "alert level checking disabled")
icon_screen = "emagged_general"
update_appearance()
+ return TRUE
/obj/machinery/computer/shuttle/pod/connect_to_shuttle(mapload, obj/docking_port/mobile/port, obj/docking_port/stationary/dock)
. = ..()
diff --git a/code/modules/shuttle/ferry.dm b/code/modules/shuttle/ferry.dm
index 595ac0787b2..14423abd580 100644
--- a/code/modules/shuttle/ferry.dm
+++ b/code/modules/shuttle/ferry.dm
@@ -8,9 +8,9 @@
var/allow_silicons = FALSE
var/allow_emag = FALSE
-/obj/machinery/computer/shuttle/ferry/emag_act(mob/user)
+/obj/machinery/computer/shuttle/ferry/emag_act(mob/user, obj/item/card/emag/emag_card)
if(!allow_emag)
- to_chat(user, span_warning("[src]'s security firewall is far too powerful for you to bypass."))
+ balloon_alert(user, "firewall too powerful!")
return FALSE
return ..()
diff --git a/code/modules/shuttle/special.dm b/code/modules/shuttle/special.dm
index cb2de16df60..bcb6984777e 100644
--- a/code/modules/shuttle/special.dm
+++ b/code/modules/shuttle/special.dm
@@ -68,8 +68,8 @@
/obj/machinery/power/emitter/energycannon/magical/ex_act(severity)
return FALSE
-/obj/machinery/power/emitter/energycannon/magical/emag_act(mob/user)
- return
+/obj/machinery/power/emitter/energycannon/magical/emag_act(mob/user, obj/item/card/emag/emag_card)
+ return FALSE
/obj/structure/table/abductor/wabbajack
name = "wabbajack altar"
@@ -277,8 +277,8 @@
/obj/machinery/scanner_gate/luxury_shuttle/attackby(obj/item/W, mob/user, params)
return
-/obj/machinery/scanner_gate/luxury_shuttle/emag_act(mob/user)
- return
+/obj/machinery/scanner_gate/luxury_shuttle/emag_act(mob/user, obj/item/card/emag/emag_card)
+ return FALSE
#define LUXURY_MESSAGE_COOLDOWN 100
/obj/machinery/scanner_gate/luxury_shuttle/Bumped(atom/movable/AM)
diff --git a/code/modules/station_goals/bsa.dm b/code/modules/station_goals/bsa.dm
index 5d2c91d1b48..7ca8f270005 100644
--- a/code/modules/station_goals/bsa.dm
+++ b/code/modules/station_goals/bsa.dm
@@ -392,6 +392,8 @@ GLOBAL_VAR_INIT(bsa_unlock, FALSE)
return cannon
/obj/machinery/computer/bsa_control/emag_act(mob/user, obj/item/card/emag/emag_card)
if(obj_flags & EMAGGED)
- return
+ return FALSE
obj_flags |= EMAGGED
- to_chat(user, span_warning("You emag [src] and hear the focusing crystal short out."))
+ balloon_alert(user, "rigged to explode")
+ to_chat(user, span_warning("You emag [src] and hear the focusing crystal short out. You get the feeling it wouldn't be wise to stand near [src] when the BSA fires..."))
+ return TRUE
diff --git a/code/modules/station_goals/meteor_shield.dm b/code/modules/station_goals/meteor_shield.dm
index 3a37ec9de9f..e856a4e2748 100644
--- a/code/modules/station_goals/meteor_shield.dm
+++ b/code/modules/station_goals/meteor_shield.dm
@@ -118,10 +118,11 @@
/obj/machinery/satellite/meteor_shield/emag_act(mob/user, obj/item/card/emag/emag_card)
if(obj_flags & EMAGGED)
balloon_alert(user, "already emagged!")
- return
+ return FALSE
if(!COOLDOWN_FINISHED(src, shared_emag_cooldown))
+ balloon_alert(user, "on cooldown!")
to_chat(user, span_warning("The last satellite emagged needs [DisplayTimeText(COOLDOWN_TIMELEFT(src, shared_emag_cooldown))] to recalibrate first. Emagging another so soon could damage the satellite network."))
- return
+ return FALSE
var/cooldown_applied = METEOR_SHIELD_EMAG_COOLDOWN
if(istype(emag_card, /obj/item/card/emag/meteor_shield_recalibrator))
cooldown_applied /= 3
@@ -132,6 +133,7 @@
say("Recalibrating... ETA:[DisplayTimeText(cooldown_applied)].")
if(active) //if we allowed inactive updates a sat could be worth -1 active meteor shields on first emag
update_emagged_meteor_sat(user)
+ return TRUE
/obj/machinery/satellite/meteor_shield/proc/update_emagged_meteor_sat(mob/user)
if(!active)
diff --git a/code/modules/surgery/organs/internal/cyberimp/augments_arms.dm b/code/modules/surgery/organs/internal/cyberimp/augments_arms.dm
index f1c7cce7b03..8df969c3bec 100644
--- a/code/modules/surgery/organs/internal/cyberimp/augments_arms.dm
+++ b/code/modules/surgery/organs/internal/cyberimp/augments_arms.dm
@@ -253,13 +253,13 @@
/obj/item/organ/internal/cyberimp/arm/toolset/l
zone = BODY_ZONE_L_ARM
-/obj/item/organ/internal/cyberimp/arm/toolset/emag_act(mob/user)
+/obj/item/organ/internal/cyberimp/arm/toolset/emag_act(mob/user, obj/item/card/emag/emag_card)
for(var/datum/weakref/created_item in items_list)
var/obj/potential_knife = created_item.resolve()
if(istype(/obj/item/knife/combat/cyborg, potential_knife))
return FALSE
- to_chat(user, span_notice("You unlock [src]'s integrated knife!"))
+ balloon_alert(user, "integrated knife unlocked")
items_list += WEAKREF(new /obj/item/knife/combat/cyborg(src))
return TRUE
diff --git a/code/modules/vehicles/cars/clowncar.dm b/code/modules/vehicles/cars/clowncar.dm
index bdc02d0ca94..29b3c2978e1 100644
--- a/code/modules/vehicles/cars/clowncar.dm
+++ b/code/modules/vehicles/cars/clowncar.dm
@@ -147,14 +147,16 @@
playsound(target_pancake, 'sound/effects/cartoon_splat.ogg', 75)
log_combat(src, crossed, "ran over")
-/obj/vehicle/sealed/car/clowncar/emag_act(mob/user)
+/obj/vehicle/sealed/car/clowncar/emag_act(mob/user, obj/item/card/emag/emag_card)
if(obj_flags & EMAGGED)
- return
+ return FALSE
obj_flags |= EMAGGED
+ balloon_alert(user, "fun mode engaged")
to_chat(user, span_danger("You scramble [src]'s child safety lock, and a panel with six colorful buttons appears!"))
initialize_controller_action_type(/datum/action/vehicle/sealed/roll_the_dice, VEHICLE_CONTROL_DRIVE)
initialize_controller_action_type(/datum/action/vehicle/sealed/cannon, VEHICLE_CONTROL_DRIVE)
AddElement(/datum/element/waddling)
+ return TRUE
/obj/vehicle/sealed/car/clowncar/atom_destruction(damage_flag)
playsound(src, 'sound/vehicles/clowncar_fart.ogg', 100)
diff --git a/code/modules/vehicles/motorized_wheelchair.dm b/code/modules/vehicles/motorized_wheelchair.dm
index 21b3ec1b51c..5b0f02c7ae8 100644
--- a/code/modules/vehicles/motorized_wheelchair.dm
+++ b/code/modules/vehicles/motorized_wheelchair.dm
@@ -185,8 +185,15 @@
visible_message(span_danger("[src] crashes into [A], sending [disabled] flying!"))
playsound(src, 'sound/effects/bang.ogg', 50, 1)
-/obj/vehicle/ridden/wheelchair/motorized/emag_act(mob/user)
- if((obj_flags & EMAGGED) || !panel_open)
- return
- to_chat(user, span_warning("A bomb appears in [src], what the fuck?"))
+/obj/vehicle/ridden/wheelchair/motorized/emag_act(mob/user, obj/item/card/emag/emag_card)
+ if (obj_flags & EMAGGED)
+ return FALSE
+
+ if (panel_open)
+ balloon_alert(user, "open maintenance panel!")
+ return FALSE
+
+ balloon_alert(user, "bomb implanted...?")
+ visible_message(span_warning("A bomb appears in [src], what the fuck?"))
obj_flags |= EMAGGED
+ return TRUE
diff --git a/code/modules/vending/_vending.dm b/code/modules/vending/_vending.dm
index 601009a8018..fe3b9a7e280 100644
--- a/code/modules/vending/_vending.dm
+++ b/code/modules/vending/_vending.dm
@@ -852,11 +852,12 @@
update_canister()
. = ..()
-/obj/machinery/vending/emag_act(mob/user)
+/obj/machinery/vending/emag_act(mob/user, obj/item/card/emag/emag_card)
if(obj_flags & EMAGGED)
- return
+ return FALSE
obj_flags |= EMAGGED
- to_chat(user, span_notice("You short out the product lock on [src]."))
+ balloon_alert(user, "product lock disabled")
+ return TRUE
/obj/machinery/vending/interact(mob/user)
if(seconds_electrified && !(machine_stat & NOPOWER))
diff --git a/icons/mob/actions/actions_AI.dmi b/icons/mob/actions/actions_AI.dmi
index 9f900bb9b4d9866621a47a683276dfbf90eb6bac..c25b88aac5cfaf5f92e8620bd3a2aabb4aae086c 100644
GIT binary patch
literal 11221
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