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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